@waveform-playlist/browser 5.0.0-alpha.14 → 5.0.0-alpha.15

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sources":["../../playout/dist/index.mjs","../../../node_modules/.pnpm/@dnd-kit+utilities@3.2.2_react@18.3.1/node_modules/@dnd-kit/utilities/dist/utilities.esm.js","../../../node_modules/.pnpm/@dnd-kit+core@6.3.1_react-dom@18.3.1_react@18.3.1/node_modules/@dnd-kit/core/dist/core.esm.js","../../../node_modules/.pnpm/@phosphor-icons+react@2.1.10_react-dom@18.3.1_react@18.3.1/node_modules/@phosphor-icons/react/dist/defs/SpeakerHigh.es.js","../../../node_modules/.pnpm/@phosphor-icons+react@2.1.10_react-dom@18.3.1_react@18.3.1/node_modules/@phosphor-icons/react/dist/defs/SpeakerLow.es.js","../../../node_modules/.pnpm/@phosphor-icons+react@2.1.10_react-dom@18.3.1_react@18.3.1/node_modules/@phosphor-icons/react/dist/lib/context.es.js","../../../node_modules/.pnpm/@phosphor-icons+react@2.1.10_react-dom@18.3.1_react@18.3.1/node_modules/@phosphor-icons/react/dist/lib/IconBase.es.js","../../../node_modules/.pnpm/@phosphor-icons+react@2.1.10_react-dom@18.3.1_react@18.3.1/node_modules/@phosphor-icons/react/dist/csr/SpeakerHigh.es.js","../../../node_modules/.pnpm/@phosphor-icons+react@2.1.10_react-dom@18.3.1_react@18.3.1/node_modules/@phosphor-icons/react/dist/csr/SpeakerLow.es.js","../../ui-components/dist/index.mjs","../../webaudio-peaks/dist/index.mjs","../src/peaksUtil.ts","../../../node_modules/.pnpm/waveform-data@4.5.2/node_modules/waveform-data/dist/waveform-data.esm.js","../src/waveformDataLoader.ts","../../../node_modules/.pnpm/@dnd-kit+core@6.3.1_react-dom@19.2.0_react@18.3.1/node_modules/@dnd-kit/core/dist/core.esm.js","../../annotations/dist/index.mjs","../src/hooks/useTimeFormat.ts","../src/hooks/useZoomControls.ts","../src/hooks/useMasterVolume.ts","../src/hooks/useAudioEffects.ts","../../core/dist/index.mjs","../src/hooks/useAudioTracks.ts","../src/hooks/useClipDragHandlers.ts","../src/hooks/useAnnotationDragHandlers.ts","../../../node_modules/.pnpm/@dnd-kit+utilities@3.2.2_react@19.2.0/node_modules/@dnd-kit/utilities/dist/utilities.esm.js","../../../node_modules/.pnpm/@dnd-kit+core@6.3.1_react-dom@19.2.0_react@19.2.0/node_modules/@dnd-kit/core/dist/core.esm.js","../src/hooks/useDragSensors.ts","../src/hooks/useClipSplitting.ts","../src/hooks/useKeyboardShortcuts.ts","../src/hooks/usePlaybackShortcuts.ts","../src/hooks/useAnnotationKeyboardControls.ts","../../recording/dist/index.mjs","../src/hooks/useIntegratedRecording.ts","../src/effects/effectDefinitions.ts","../src/effects/effectFactory.ts","../src/hooks/useDynamicEffects.ts","../src/hooks/useTrackDynamicEffects.ts","../src/utils/wavEncoder.ts","../src/hooks/useExportWav.ts","../src/WaveformPlaylistContext.tsx","../../media-element-playout/dist/index.mjs","../src/MediaElementPlaylistContext.tsx","../src/components/PlaybackControls.tsx","../src/components/ZoomControls.tsx","../src/components/ContextualControls.tsx","../src/components/AnnotationControls.tsx","../src/components/ExportControls.tsx","../src/components/AnimatedPlayhead.tsx","../src/components/ChannelWithProgress.tsx","../src/components/Waveform.tsx","../src/components/AnimatedMediaElementPlayhead.tsx","../src/components/ChannelWithMediaElementProgress.tsx","../src/components/MediaElementWaveform.tsx"],"sourcesContent":["// src/TonePlayout.ts\nimport {\n Volume as Volume2,\n getDestination as getDestination2,\n start,\n now as now2,\n getTransport,\n getContext\n} from \"tone\";\n\n// src/ToneTrack.ts\nimport {\n Player,\n Volume,\n Gain,\n Panner,\n getDestination,\n now\n} from \"tone\";\n\n// src/fades.ts\nfunction linearCurve(length, fadeIn) {\n const curve = new Float32Array(length);\n const scale = length - 1;\n for (let i = 0; i < length; i++) {\n const x = i / scale;\n curve[i] = fadeIn ? x : 1 - x;\n }\n return curve;\n}\nfunction exponentialCurve(length, fadeIn) {\n const curve = new Float32Array(length);\n const scale = length - 1;\n for (let i = 0; i < length; i++) {\n const x = i / scale;\n const index = fadeIn ? i : length - 1 - i;\n curve[index] = Math.exp(2 * x - 1) / Math.E;\n }\n return curve;\n}\nfunction sCurveCurve(length, fadeIn) {\n const curve = new Float32Array(length);\n const phase = fadeIn ? Math.PI / 2 : -Math.PI / 2;\n for (let i = 0; i < length; i++) {\n curve[i] = Math.sin(Math.PI * i / length - phase) / 2 + 0.5;\n }\n return curve;\n}\nfunction logarithmicCurve(length, fadeIn, base = 10) {\n const curve = new Float32Array(length);\n for (let i = 0; i < length; i++) {\n const index = fadeIn ? i : length - 1 - i;\n const x = i / length;\n curve[index] = Math.log(1 + base * x) / Math.log(1 + base);\n }\n return curve;\n}\nfunction generateCurve(type, length, fadeIn) {\n switch (type) {\n case \"linear\":\n return linearCurve(length, fadeIn);\n case \"exponential\":\n return exponentialCurve(length, fadeIn);\n case \"sCurve\":\n return sCurveCurve(length, fadeIn);\n case \"logarithmic\":\n return logarithmicCurve(length, fadeIn);\n default:\n return linearCurve(length, fadeIn);\n }\n}\nfunction applyFadeIn(param, startTime, duration, type = \"linear\", startValue = 0, endValue = 1) {\n if (duration <= 0) return;\n if (type === \"linear\") {\n param.setValueAtTime(startValue, startTime);\n param.linearRampToValueAtTime(endValue, startTime + duration);\n } else if (type === \"exponential\") {\n param.setValueAtTime(Math.max(startValue, 1e-3), startTime);\n param.exponentialRampToValueAtTime(Math.max(endValue, 1e-3), startTime + duration);\n } else {\n const curve = generateCurve(type, 1e4, true);\n const scaledCurve = new Float32Array(curve.length);\n const range = endValue - startValue;\n for (let i = 0; i < curve.length; i++) {\n scaledCurve[i] = startValue + curve[i] * range;\n }\n param.setValueCurveAtTime(scaledCurve, startTime, duration);\n }\n}\nfunction applyFadeOut(param, startTime, duration, type = \"linear\", startValue = 1, endValue = 0) {\n if (duration <= 0) return;\n if (type === \"linear\") {\n param.setValueAtTime(startValue, startTime);\n param.linearRampToValueAtTime(endValue, startTime + duration);\n } else if (type === \"exponential\") {\n param.setValueAtTime(Math.max(startValue, 1e-3), startTime);\n param.exponentialRampToValueAtTime(Math.max(endValue, 1e-3), startTime + duration);\n } else {\n const curve = generateCurve(type, 1e4, false);\n const scaledCurve = new Float32Array(curve.length);\n const range = startValue - endValue;\n for (let i = 0; i < curve.length; i++) {\n scaledCurve[i] = endValue + curve[i] * range;\n }\n param.setValueCurveAtTime(scaledCurve, startTime, duration);\n }\n}\n\n// src/ToneTrack.ts\nvar ToneTrack = class {\n // Count of currently playing clips\n constructor(options) {\n this.activePlayers = 0;\n this.track = options.track;\n this.volumeNode = new Volume(this.gainToDb(options.track.gain));\n this.panNode = new Panner(options.track.stereoPan);\n this.muteGain = new Gain(options.track.muted ? 0 : 1);\n const destination = options.destination || getDestination();\n if (options.effects) {\n const cleanup = options.effects(this.muteGain, destination, false);\n if (cleanup) {\n this.effectsCleanup = cleanup;\n }\n } else {\n this.muteGain.connect(destination);\n }\n const clipInfos = options.clips || (options.buffer ? [{\n buffer: options.buffer,\n startTime: 0,\n // Legacy: single buffer starts at timeline position 0\n duration: options.buffer.duration,\n // Legacy: play full buffer duration\n offset: 0,\n fadeIn: options.track.fadeIn,\n fadeOut: options.track.fadeOut,\n gain: 1\n }] : []);\n this.clips = clipInfos.map((clipInfo) => {\n const player = new Player({\n url: clipInfo.buffer,\n loop: false,\n onstop: () => {\n this.activePlayers--;\n if (this.activePlayers === 0 && this.onStopCallback) {\n this.onStopCallback();\n }\n }\n });\n const fadeGain = new Gain(clipInfo.gain);\n player.connect(fadeGain);\n fadeGain.chain(this.volumeNode, this.panNode, this.muteGain);\n return {\n player,\n clipInfo,\n fadeGain,\n pausedPosition: 0,\n playStartTime: 0\n };\n });\n }\n /**\n * Schedule fade envelopes for a clip at the given start time\n */\n scheduleFades(clipPlayer, clipStartTime, clipOffset = 0) {\n const { clipInfo, fadeGain } = clipPlayer;\n const audioParam = fadeGain.gain._param;\n audioParam.cancelScheduledValues(0);\n const skipTime = clipOffset - clipInfo.offset;\n if (clipInfo.fadeIn && skipTime < clipInfo.fadeIn.duration) {\n const fadeInDuration = clipInfo.fadeIn.duration;\n if (skipTime <= 0) {\n applyFadeIn(\n audioParam,\n clipStartTime,\n fadeInDuration,\n clipInfo.fadeIn.type || \"linear\",\n 0,\n clipInfo.gain\n );\n } else {\n const remainingFadeDuration = fadeInDuration - skipTime;\n const fadeProgress = skipTime / fadeInDuration;\n const startValue = clipInfo.gain * fadeProgress;\n applyFadeIn(\n audioParam,\n clipStartTime,\n remainingFadeDuration,\n clipInfo.fadeIn.type || \"linear\",\n startValue,\n clipInfo.gain\n );\n }\n } else {\n audioParam.setValueAtTime(clipInfo.gain, clipStartTime);\n }\n if (clipInfo.fadeOut) {\n const fadeOutStart = clipInfo.duration - clipInfo.fadeOut.duration;\n const fadeOutStartInClip = fadeOutStart - skipTime;\n if (fadeOutStartInClip > 0) {\n const absoluteFadeOutStart = clipStartTime + fadeOutStartInClip;\n applyFadeOut(\n audioParam,\n absoluteFadeOutStart,\n clipInfo.fadeOut.duration,\n clipInfo.fadeOut.type || \"linear\",\n clipInfo.gain,\n 0\n );\n } else if (fadeOutStartInClip > -clipInfo.fadeOut.duration) {\n const elapsedFadeOut = -fadeOutStartInClip;\n const remainingFadeDuration = clipInfo.fadeOut.duration - elapsedFadeOut;\n const fadeProgress = elapsedFadeOut / clipInfo.fadeOut.duration;\n const startValue = clipInfo.gain * (1 - fadeProgress);\n applyFadeOut(\n audioParam,\n clipStartTime,\n remainingFadeDuration,\n clipInfo.fadeOut.type || \"linear\",\n startValue,\n 0\n );\n }\n }\n }\n gainToDb(gain) {\n return 20 * Math.log10(gain);\n }\n setVolume(gain) {\n this.track.gain = gain;\n this.volumeNode.volume.value = this.gainToDb(gain);\n }\n setPan(pan) {\n this.track.stereoPan = pan;\n this.panNode.pan.value = pan;\n }\n setMute(muted) {\n this.track.muted = muted;\n this.muteGain.gain.value = muted ? 0 : 1;\n }\n setSolo(soloed) {\n this.track.soloed = soloed;\n }\n play(when, offset = 0, duration) {\n this.clips.forEach((clipPlayer) => {\n clipPlayer.player.stop();\n clipPlayer.player.disconnect();\n clipPlayer.player.dispose();\n const newPlayer = new Player({\n url: clipPlayer.clipInfo.buffer,\n loop: false,\n onstop: () => {\n this.activePlayers--;\n if (this.activePlayers === 0 && this.onStopCallback) {\n this.onStopCallback();\n }\n }\n });\n newPlayer.connect(clipPlayer.fadeGain);\n clipPlayer.player = newPlayer;\n clipPlayer.pausedPosition = 0;\n });\n this.activePlayers = 0;\n this.clips.forEach((clipPlayer) => {\n const { player, clipInfo } = clipPlayer;\n const playbackPosition = offset;\n const clipStart = clipInfo.startTime;\n const clipEnd = clipInfo.startTime + clipInfo.duration;\n if (playbackPosition < clipEnd) {\n this.activePlayers++;\n const currentTime = when ?? now();\n clipPlayer.playStartTime = currentTime;\n if (playbackPosition >= clipStart) {\n const clipOffset = playbackPosition - clipStart + clipInfo.offset;\n const remainingDuration = clipInfo.duration - (playbackPosition - clipStart);\n const clipDuration = duration ? Math.min(duration, remainingDuration) : remainingDuration;\n clipPlayer.pausedPosition = clipOffset;\n this.scheduleFades(clipPlayer, currentTime, clipOffset);\n player.start(currentTime, clipOffset, clipDuration);\n } else {\n const delay = clipStart - playbackPosition;\n const clipDuration = duration ? Math.min(duration - delay, clipInfo.duration) : clipInfo.duration;\n if (delay < (duration ?? Infinity)) {\n clipPlayer.pausedPosition = clipInfo.offset;\n this.scheduleFades(clipPlayer, currentTime + delay, clipInfo.offset);\n player.start(currentTime + delay, clipInfo.offset, clipDuration);\n } else {\n this.activePlayers--;\n }\n }\n }\n });\n }\n pause() {\n this.clips.forEach((clipPlayer) => {\n if (clipPlayer.player.state === \"started\") {\n const elapsed = (now() - clipPlayer.playStartTime) * clipPlayer.player.playbackRate;\n clipPlayer.pausedPosition = clipPlayer.pausedPosition + elapsed;\n }\n clipPlayer.player.stop();\n });\n this.activePlayers = 0;\n }\n stop(when) {\n const stopWhen = when ?? now();\n this.clips.forEach((clipPlayer) => {\n clipPlayer.player.stop(stopWhen);\n clipPlayer.pausedPosition = 0;\n });\n this.activePlayers = 0;\n }\n dispose() {\n if (this.effectsCleanup) {\n this.effectsCleanup();\n }\n this.clips.forEach((clipPlayer) => {\n clipPlayer.player.dispose();\n clipPlayer.fadeGain.dispose();\n });\n this.volumeNode.dispose();\n this.panNode.dispose();\n this.muteGain.dispose();\n }\n get id() {\n return this.track.id;\n }\n get duration() {\n if (this.clips.length === 0) return 0;\n const lastClip = this.clips[this.clips.length - 1];\n return lastClip.clipInfo.startTime + lastClip.clipInfo.duration;\n }\n get buffer() {\n return this.clips[0]?.clipInfo.buffer;\n }\n get isPlaying() {\n return this.clips.some((clipPlayer) => clipPlayer.player.state === \"started\");\n }\n get muted() {\n return this.track.muted;\n }\n get startTime() {\n return this.track.startTime;\n }\n setOnStopCallback(callback) {\n this.onStopCallback = callback;\n }\n};\n\n// src/TonePlayout.ts\nvar TonePlayout = class {\n constructor(options = {}) {\n this.tracks = /* @__PURE__ */ new Map();\n this.isInitialized = false;\n this.soloedTracks = /* @__PURE__ */ new Set();\n this.manualMuteState = /* @__PURE__ */ new Map();\n this.activeTracks = /* @__PURE__ */ new Map();\n // Map track ID to session ID\n this.playbackSessionId = 0;\n this.masterVolume = new Volume2(this.gainToDb(options.masterGain ?? 1));\n if (options.effects) {\n const cleanup = options.effects(this.masterVolume, getDestination2(), false);\n if (cleanup) {\n this.effectsCleanup = cleanup;\n }\n } else {\n this.masterVolume.toDestination();\n }\n if (options.tracks) {\n options.tracks.forEach((track) => {\n this.tracks.set(track.id, track);\n this.manualMuteState.set(track.id, track.muted);\n });\n }\n }\n gainToDb(gain) {\n return 20 * Math.log10(gain);\n }\n async init() {\n if (this.isInitialized) return;\n await start();\n this.isInitialized = true;\n }\n addTrack(trackOptions) {\n const optionsWithDestination = {\n ...trackOptions,\n destination: this.masterVolume\n };\n const toneTrack = new ToneTrack(optionsWithDestination);\n this.tracks.set(toneTrack.id, toneTrack);\n this.manualMuteState.set(toneTrack.id, trackOptions.track.muted ?? false);\n if (trackOptions.track.soloed) {\n this.soloedTracks.add(toneTrack.id);\n }\n return toneTrack;\n }\n /**\n * Apply solo muting after all tracks have been added.\n * Call this after adding all tracks to ensure solo logic is applied correctly.\n */\n applyInitialSoloState() {\n this.updateSoloMuting();\n }\n removeTrack(trackId) {\n const track = this.tracks.get(trackId);\n if (track) {\n track.dispose();\n this.tracks.delete(trackId);\n this.manualMuteState.delete(trackId);\n this.soloedTracks.delete(trackId);\n }\n }\n getTrack(trackId) {\n return this.tracks.get(trackId);\n }\n play(when, offset, duration) {\n if (!this.isInitialized) {\n console.warn(\"TonePlayout not initialized. Call init() first.\");\n return;\n }\n const startTime = when ?? now2();\n const playbackPosition = offset ?? 0;\n this.playbackSessionId++;\n const currentSessionId = this.playbackSessionId;\n this.activeTracks.clear();\n this.tracks.forEach((toneTrack) => {\n const trackStartTime = toneTrack.startTime;\n if (playbackPosition >= trackStartTime) {\n const bufferOffset = playbackPosition - trackStartTime;\n if (duration !== void 0) {\n this.activeTracks.set(toneTrack.id, currentSessionId);\n toneTrack.setOnStopCallback(() => {\n if (this.activeTracks.get(toneTrack.id) === currentSessionId) {\n this.activeTracks.delete(toneTrack.id);\n if (this.activeTracks.size === 0 && this.onPlaybackCompleteCallback) {\n this.onPlaybackCompleteCallback();\n }\n }\n });\n }\n toneTrack.play(startTime, bufferOffset, duration);\n } else {\n const delay = trackStartTime - playbackPosition;\n if (duration !== void 0) {\n this.activeTracks.set(toneTrack.id, currentSessionId);\n toneTrack.setOnStopCallback(() => {\n if (this.activeTracks.get(toneTrack.id) === currentSessionId) {\n this.activeTracks.delete(toneTrack.id);\n if (this.activeTracks.size === 0 && this.onPlaybackCompleteCallback) {\n this.onPlaybackCompleteCallback();\n }\n }\n });\n }\n toneTrack.play(startTime + delay, 0, duration);\n }\n });\n if (offset !== void 0) {\n getTransport().start(startTime, offset);\n } else {\n getTransport().start(startTime);\n }\n }\n pause() {\n getTransport().pause();\n this.tracks.forEach((track) => {\n track.pause();\n });\n }\n stop() {\n getTransport().stop();\n this.tracks.forEach((track) => {\n track.stop();\n });\n }\n setMasterGain(gain) {\n this.masterVolume.volume.value = this.gainToDb(gain);\n }\n setSolo(trackId, soloed) {\n const track = this.tracks.get(trackId);\n if (track) {\n track.setSolo(soloed);\n if (soloed) {\n this.soloedTracks.add(trackId);\n } else {\n this.soloedTracks.delete(trackId);\n }\n this.updateSoloMuting();\n }\n }\n updateSoloMuting() {\n const hasSoloedTracks = this.soloedTracks.size > 0;\n this.tracks.forEach((track, id) => {\n if (hasSoloedTracks) {\n if (!this.soloedTracks.has(id)) {\n track.setMute(true);\n } else {\n const manuallyMuted = this.manualMuteState.get(id) ?? false;\n track.setMute(manuallyMuted);\n }\n } else {\n const manuallyMuted = this.manualMuteState.get(id) ?? false;\n track.setMute(manuallyMuted);\n }\n });\n }\n setMute(trackId, muted) {\n const track = this.tracks.get(trackId);\n if (track) {\n this.manualMuteState.set(trackId, muted);\n track.setMute(muted);\n }\n }\n getCurrentTime() {\n return getTransport().seconds;\n }\n seekTo(time) {\n getTransport().seconds = time;\n }\n dispose() {\n this.tracks.forEach((track) => {\n track.dispose();\n });\n this.tracks.clear();\n if (this.effectsCleanup) {\n this.effectsCleanup();\n }\n this.masterVolume.dispose();\n }\n get context() {\n return getContext();\n }\n get sampleRate() {\n return getContext().sampleRate;\n }\n setOnPlaybackComplete(callback) {\n this.onPlaybackCompleteCallback = callback;\n }\n};\n\n// src/audioContext.ts\nimport { Context, setContext } from \"tone\";\nvar globalToneContext = null;\nfunction getGlobalContext() {\n if (!globalToneContext) {\n globalToneContext = new Context();\n setContext(globalToneContext);\n }\n return globalToneContext;\n}\nfunction getGlobalAudioContext() {\n return getGlobalContext().rawContext;\n}\nfunction getGlobalToneContext() {\n return getGlobalContext();\n}\nasync function resumeGlobalAudioContext() {\n const context = getGlobalContext();\n if (context.state !== \"running\") {\n await context.resume();\n }\n}\nfunction getGlobalAudioContextState() {\n return globalToneContext?.rawContext.state || \"suspended\";\n}\nasync function closeGlobalAudioContext() {\n if (globalToneContext && globalToneContext.rawContext.state !== \"closed\") {\n await globalToneContext.close();\n globalToneContext = null;\n }\n}\n\n// src/mediaStreamSourceManager.ts\nimport { getContext as getContext2 } from \"tone\";\nvar streamSources = /* @__PURE__ */ new Map();\nvar streamCleanupHandlers = /* @__PURE__ */ new Map();\nfunction getMediaStreamSource(stream) {\n if (streamSources.has(stream)) {\n return streamSources.get(stream);\n }\n const context = getContext2();\n const source = context.createMediaStreamSource(stream);\n streamSources.set(stream, source);\n const cleanup = () => {\n source.disconnect();\n streamSources.delete(stream);\n streamCleanupHandlers.delete(stream);\n stream.removeEventListener(\"ended\", cleanup);\n stream.removeEventListener(\"inactive\", cleanup);\n };\n streamCleanupHandlers.set(stream, cleanup);\n stream.addEventListener(\"ended\", cleanup);\n stream.addEventListener(\"inactive\", cleanup);\n return source;\n}\nfunction releaseMediaStreamSource(stream) {\n const cleanup = streamCleanupHandlers.get(stream);\n if (cleanup) {\n cleanup();\n }\n}\nfunction hasMediaStreamSource(stream) {\n return streamSources.has(stream);\n}\nexport {\n TonePlayout,\n ToneTrack,\n applyFadeIn,\n applyFadeOut,\n closeGlobalAudioContext,\n getGlobalAudioContext,\n getGlobalAudioContextState,\n getGlobalContext,\n getGlobalToneContext,\n getMediaStreamSource,\n hasMediaStreamSource,\n releaseMediaStreamSource,\n resumeGlobalAudioContext\n};\n//# sourceMappingURL=index.mjs.map","import { useMemo, useLayoutEffect, useEffect, useRef, useCallback } from 'react';\n\nfunction useCombinedRefs() {\n for (var _len = arguments.length, refs = new Array(_len), _key = 0; _key < _len; _key++) {\n refs[_key] = arguments[_key];\n }\n\n return useMemo(() => node => {\n refs.forEach(ref => ref(node));\n }, // eslint-disable-next-line react-hooks/exhaustive-deps\n refs);\n}\n\n// https://github.com/facebook/react/blob/master/packages/shared/ExecutionEnvironment.js\nconst canUseDOM = typeof window !== 'undefined' && typeof window.document !== 'undefined' && typeof window.document.createElement !== 'undefined';\n\nfunction isWindow(element) {\n const elementString = Object.prototype.toString.call(element);\n return elementString === '[object Window]' || // In Electron context the Window object serializes to [object global]\n elementString === '[object global]';\n}\n\nfunction isNode(node) {\n return 'nodeType' in node;\n}\n\nfunction getWindow(target) {\n var _target$ownerDocument, _target$ownerDocument2;\n\n if (!target) {\n return window;\n }\n\n if (isWindow(target)) {\n return target;\n }\n\n if (!isNode(target)) {\n return window;\n }\n\n return (_target$ownerDocument = (_target$ownerDocument2 = target.ownerDocument) == null ? void 0 : _target$ownerDocument2.defaultView) != null ? _target$ownerDocument : window;\n}\n\nfunction isDocument(node) {\n const {\n Document\n } = getWindow(node);\n return node instanceof Document;\n}\n\nfunction isHTMLElement(node) {\n if (isWindow(node)) {\n return false;\n }\n\n return node instanceof getWindow(node).HTMLElement;\n}\n\nfunction isSVGElement(node) {\n return node instanceof getWindow(node).SVGElement;\n}\n\nfunction getOwnerDocument(target) {\n if (!target) {\n return document;\n }\n\n if (isWindow(target)) {\n return target.document;\n }\n\n if (!isNode(target)) {\n return document;\n }\n\n if (isDocument(target)) {\n return target;\n }\n\n if (isHTMLElement(target) || isSVGElement(target)) {\n return target.ownerDocument;\n }\n\n return document;\n}\n\n/**\r\n * A hook that resolves to useEffect on the server and useLayoutEffect on the client\r\n * @param callback {function} Callback function that is invoked when the dependencies of the hook change\r\n */\n\nconst useIsomorphicLayoutEffect = canUseDOM ? useLayoutEffect : useEffect;\n\nfunction useEvent(handler) {\n const handlerRef = useRef(handler);\n useIsomorphicLayoutEffect(() => {\n handlerRef.current = handler;\n });\n return useCallback(function () {\n for (var _len = arguments.length, args = new Array(_len), _key = 0; _key < _len; _key++) {\n args[_key] = arguments[_key];\n }\n\n return handlerRef.current == null ? void 0 : handlerRef.current(...args);\n }, []);\n}\n\nfunction useInterval() {\n const intervalRef = useRef(null);\n const set = useCallback((listener, duration) => {\n intervalRef.current = setInterval(listener, duration);\n }, []);\n const clear = useCallback(() => {\n if (intervalRef.current !== null) {\n clearInterval(intervalRef.current);\n intervalRef.current = null;\n }\n }, []);\n return [set, clear];\n}\n\nfunction useLatestValue(value, dependencies) {\n if (dependencies === void 0) {\n dependencies = [value];\n }\n\n const valueRef = useRef(value);\n useIsomorphicLayoutEffect(() => {\n if (valueRef.current !== value) {\n valueRef.current = value;\n }\n }, dependencies);\n return valueRef;\n}\n\nfunction useLazyMemo(callback, dependencies) {\n const valueRef = useRef();\n return useMemo(() => {\n const newValue = callback(valueRef.current);\n valueRef.current = newValue;\n return newValue;\n }, // eslint-disable-next-line react-hooks/exhaustive-deps\n [...dependencies]);\n}\n\nfunction useNodeRef(onChange) {\n const onChangeHandler = useEvent(onChange);\n const node = useRef(null);\n const setNodeRef = useCallback(element => {\n if (element !== node.current) {\n onChangeHandler == null ? void 0 : onChangeHandler(element, node.current);\n }\n\n node.current = element;\n }, //eslint-disable-next-line\n []);\n return [node, setNodeRef];\n}\n\nfunction usePrevious(value) {\n const ref = useRef();\n useEffect(() => {\n ref.current = value;\n }, [value]);\n return ref.current;\n}\n\nlet ids = {};\nfunction useUniqueId(prefix, value) {\n return useMemo(() => {\n if (value) {\n return value;\n }\n\n const id = ids[prefix] == null ? 0 : ids[prefix] + 1;\n ids[prefix] = id;\n return prefix + \"-\" + id;\n }, [prefix, value]);\n}\n\nfunction createAdjustmentFn(modifier) {\n return function (object) {\n for (var _len = arguments.length, adjustments = new Array(_len > 1 ? _len - 1 : 0), _key = 1; _key < _len; _key++) {\n adjustments[_key - 1] = arguments[_key];\n }\n\n return adjustments.reduce((accumulator, adjustment) => {\n const entries = Object.entries(adjustment);\n\n for (const [key, valueAdjustment] of entries) {\n const value = accumulator[key];\n\n if (value != null) {\n accumulator[key] = value + modifier * valueAdjustment;\n }\n }\n\n return accumulator;\n }, { ...object\n });\n };\n}\n\nconst add = /*#__PURE__*/createAdjustmentFn(1);\nconst subtract = /*#__PURE__*/createAdjustmentFn(-1);\n\nfunction hasViewportRelativeCoordinates(event) {\n return 'clientX' in event && 'clientY' in event;\n}\n\nfunction isKeyboardEvent(event) {\n if (!event) {\n return false;\n }\n\n const {\n KeyboardEvent\n } = getWindow(event.target);\n return KeyboardEvent && event instanceof KeyboardEvent;\n}\n\nfunction isTouchEvent(event) {\n if (!event) {\n return false;\n }\n\n const {\n TouchEvent\n } = getWindow(event.target);\n return TouchEvent && event instanceof TouchEvent;\n}\n\n/**\r\n * Returns the normalized x and y coordinates for mouse and touch events.\r\n */\n\nfunction getEventCoordinates(event) {\n if (isTouchEvent(event)) {\n if (event.touches && event.touches.length) {\n const {\n clientX: x,\n clientY: y\n } = event.touches[0];\n return {\n x,\n y\n };\n } else if (event.changedTouches && event.changedTouches.length) {\n const {\n clientX: x,\n clientY: y\n } = event.changedTouches[0];\n return {\n x,\n y\n };\n }\n }\n\n if (hasViewportRelativeCoordinates(event)) {\n return {\n x: event.clientX,\n y: event.clientY\n };\n }\n\n return null;\n}\n\nconst CSS = /*#__PURE__*/Object.freeze({\n Translate: {\n toString(transform) {\n if (!transform) {\n return;\n }\n\n const {\n x,\n y\n } = transform;\n return \"translate3d(\" + (x ? Math.round(x) : 0) + \"px, \" + (y ? Math.round(y) : 0) + \"px, 0)\";\n }\n\n },\n Scale: {\n toString(transform) {\n if (!transform) {\n return;\n }\n\n const {\n scaleX,\n scaleY\n } = transform;\n return \"scaleX(\" + scaleX + \") scaleY(\" + scaleY + \")\";\n }\n\n },\n Transform: {\n toString(transform) {\n if (!transform) {\n return;\n }\n\n return [CSS.Translate.toString(transform), CSS.Scale.toString(transform)].join(' ');\n }\n\n },\n Transition: {\n toString(_ref) {\n let {\n property,\n duration,\n easing\n } = _ref;\n return property + \" \" + duration + \"ms \" + easing;\n }\n\n }\n});\n\nconst SELECTOR = 'a,frame,iframe,input:not([type=hidden]):not(:disabled),select:not(:disabled),textarea:not(:disabled),button:not(:disabled),*[tabindex]';\nfunction findFirstFocusableNode(element) {\n if (element.matches(SELECTOR)) {\n return element;\n }\n\n return element.querySelector(SELECTOR);\n}\n\nexport { CSS, add, canUseDOM, findFirstFocusableNode, getEventCoordinates, getOwnerDocument, getWindow, hasViewportRelativeCoordinates, isDocument, isHTMLElement, isKeyboardEvent, isNode, isSVGElement, isTouchEvent, isWindow, subtract, useCombinedRefs, useEvent, useInterval, useIsomorphicLayoutEffect, useLatestValue, useLazyMemo, useNodeRef, usePrevious, useUniqueId };\n//# sourceMappingURL=utilities.esm.js.map\n","import React, { createContext, useContext, useEffect, useState, useCallback, useMemo, useRef, memo, useReducer, cloneElement, forwardRef } from 'react';\nimport { createPortal, unstable_batchedUpdates } from 'react-dom';\nimport { useUniqueId, getEventCoordinates, getWindow, isDocument, isHTMLElement, isSVGElement, canUseDOM, isWindow, isNode, getOwnerDocument, add, isKeyboardEvent, subtract, useLazyMemo, useInterval, usePrevious, useLatestValue, useEvent, useIsomorphicLayoutEffect, useNodeRef, findFirstFocusableNode, CSS } from '@dnd-kit/utilities';\nimport { useAnnouncement, HiddenText, LiveRegion } from '@dnd-kit/accessibility';\n\nconst DndMonitorContext = /*#__PURE__*/createContext(null);\n\nfunction useDndMonitor(listener) {\n const registerListener = useContext(DndMonitorContext);\n useEffect(() => {\n if (!registerListener) {\n throw new Error('useDndMonitor must be used within a children of <DndContext>');\n }\n\n const unsubscribe = registerListener(listener);\n return unsubscribe;\n }, [listener, registerListener]);\n}\n\nfunction useDndMonitorProvider() {\n const [listeners] = useState(() => new Set());\n const registerListener = useCallback(listener => {\n listeners.add(listener);\n return () => listeners.delete(listener);\n }, [listeners]);\n const dispatch = useCallback(_ref => {\n let {\n type,\n event\n } = _ref;\n listeners.forEach(listener => {\n var _listener$type;\n\n return (_listener$type = listener[type]) == null ? void 0 : _listener$type.call(listener, event);\n });\n }, [listeners]);\n return [dispatch, registerListener];\n}\n\nconst defaultScreenReaderInstructions = {\n draggable: \"\\n To pick up a draggable item, press the space bar.\\n While dragging, use the arrow keys to move the item.\\n Press space again to drop the item in its new position, or press escape to cancel.\\n \"\n};\nconst defaultAnnouncements = {\n onDragStart(_ref) {\n let {\n active\n } = _ref;\n return \"Picked up draggable item \" + active.id + \".\";\n },\n\n onDragOver(_ref2) {\n let {\n active,\n over\n } = _ref2;\n\n if (over) {\n return \"Draggable item \" + active.id + \" was moved over droppable area \" + over.id + \".\";\n }\n\n return \"Draggable item \" + active.id + \" is no longer over a droppable area.\";\n },\n\n onDragEnd(_ref3) {\n let {\n active,\n over\n } = _ref3;\n\n if (over) {\n return \"Draggable item \" + active.id + \" was dropped over droppable area \" + over.id;\n }\n\n return \"Draggable item \" + active.id + \" was dropped.\";\n },\n\n onDragCancel(_ref4) {\n let {\n active\n } = _ref4;\n return \"Dragging was cancelled. Draggable item \" + active.id + \" was dropped.\";\n }\n\n};\n\nfunction Accessibility(_ref) {\n let {\n announcements = defaultAnnouncements,\n container,\n hiddenTextDescribedById,\n screenReaderInstructions = defaultScreenReaderInstructions\n } = _ref;\n const {\n announce,\n announcement\n } = useAnnouncement();\n const liveRegionId = useUniqueId(\"DndLiveRegion\");\n const [mounted, setMounted] = useState(false);\n useEffect(() => {\n setMounted(true);\n }, []);\n useDndMonitor(useMemo(() => ({\n onDragStart(_ref2) {\n let {\n active\n } = _ref2;\n announce(announcements.onDragStart({\n active\n }));\n },\n\n onDragMove(_ref3) {\n let {\n active,\n over\n } = _ref3;\n\n if (announcements.onDragMove) {\n announce(announcements.onDragMove({\n active,\n over\n }));\n }\n },\n\n onDragOver(_ref4) {\n let {\n active,\n over\n } = _ref4;\n announce(announcements.onDragOver({\n active,\n over\n }));\n },\n\n onDragEnd(_ref5) {\n let {\n active,\n over\n } = _ref5;\n announce(announcements.onDragEnd({\n active,\n over\n }));\n },\n\n onDragCancel(_ref6) {\n let {\n active,\n over\n } = _ref6;\n announce(announcements.onDragCancel({\n active,\n over\n }));\n }\n\n }), [announce, announcements]));\n\n if (!mounted) {\n return null;\n }\n\n const markup = React.createElement(React.Fragment, null, React.createElement(HiddenText, {\n id: hiddenTextDescribedById,\n value: screenReaderInstructions.draggable\n }), React.createElement(LiveRegion, {\n id: liveRegionId,\n announcement: announcement\n }));\n return container ? createPortal(markup, container) : markup;\n}\n\nvar Action;\n\n(function (Action) {\n Action[\"DragStart\"] = \"dragStart\";\n Action[\"DragMove\"] = \"dragMove\";\n Action[\"DragEnd\"] = \"dragEnd\";\n Action[\"DragCancel\"] = \"dragCancel\";\n Action[\"DragOver\"] = \"dragOver\";\n Action[\"RegisterDroppable\"] = \"registerDroppable\";\n Action[\"SetDroppableDisabled\"] = \"setDroppableDisabled\";\n Action[\"UnregisterDroppable\"] = \"unregisterDroppable\";\n})(Action || (Action = {}));\n\nfunction noop() {}\n\nfunction useSensor(sensor, options) {\n return useMemo(() => ({\n sensor,\n options: options != null ? options : {}\n }), // eslint-disable-next-line react-hooks/exhaustive-deps\n [sensor, options]);\n}\n\nfunction useSensors() {\n for (var _len = arguments.length, sensors = new Array(_len), _key = 0; _key < _len; _key++) {\n sensors[_key] = arguments[_key];\n }\n\n return useMemo(() => [...sensors].filter(sensor => sensor != null), // eslint-disable-next-line react-hooks/exhaustive-deps\n [...sensors]);\n}\n\nconst defaultCoordinates = /*#__PURE__*/Object.freeze({\n x: 0,\n y: 0\n});\n\n/**\r\n * Returns the distance between two points\r\n */\nfunction distanceBetween(p1, p2) {\n return Math.sqrt(Math.pow(p1.x - p2.x, 2) + Math.pow(p1.y - p2.y, 2));\n}\n\nfunction getRelativeTransformOrigin(event, rect) {\n const eventCoordinates = getEventCoordinates(event);\n\n if (!eventCoordinates) {\n return '0 0';\n }\n\n const transformOrigin = {\n x: (eventCoordinates.x - rect.left) / rect.width * 100,\n y: (eventCoordinates.y - rect.top) / rect.height * 100\n };\n return transformOrigin.x + \"% \" + transformOrigin.y + \"%\";\n}\n\n/**\r\n * Sort collisions from smallest to greatest value\r\n */\nfunction sortCollisionsAsc(_ref, _ref2) {\n let {\n data: {\n value: a\n }\n } = _ref;\n let {\n data: {\n value: b\n }\n } = _ref2;\n return a - b;\n}\n/**\r\n * Sort collisions from greatest to smallest value\r\n */\n\nfunction sortCollisionsDesc(_ref3, _ref4) {\n let {\n data: {\n value: a\n }\n } = _ref3;\n let {\n data: {\n value: b\n }\n } = _ref4;\n return b - a;\n}\n/**\r\n * Returns the coordinates of the corners of a given rectangle:\r\n * [TopLeft {x, y}, TopRight {x, y}, BottomLeft {x, y}, BottomRight {x, y}]\r\n */\n\nfunction cornersOfRectangle(_ref5) {\n let {\n left,\n top,\n height,\n width\n } = _ref5;\n return [{\n x: left,\n y: top\n }, {\n x: left + width,\n y: top\n }, {\n x: left,\n y: top + height\n }, {\n x: left + width,\n y: top + height\n }];\n}\nfunction getFirstCollision(collisions, property) {\n if (!collisions || collisions.length === 0) {\n return null;\n }\n\n const [firstCollision] = collisions;\n return property ? firstCollision[property] : firstCollision;\n}\n\n/**\r\n * Returns the coordinates of the center of a given ClientRect\r\n */\n\nfunction centerOfRectangle(rect, left, top) {\n if (left === void 0) {\n left = rect.left;\n }\n\n if (top === void 0) {\n top = rect.top;\n }\n\n return {\n x: left + rect.width * 0.5,\n y: top + rect.height * 0.5\n };\n}\n/**\r\n * Returns the closest rectangles from an array of rectangles to the center of a given\r\n * rectangle.\r\n */\n\n\nconst closestCenter = _ref => {\n let {\n collisionRect,\n droppableRects,\n droppableContainers\n } = _ref;\n const centerRect = centerOfRectangle(collisionRect, collisionRect.left, collisionRect.top);\n const collisions = [];\n\n for (const droppableContainer of droppableContainers) {\n const {\n id\n } = droppableContainer;\n const rect = droppableRects.get(id);\n\n if (rect) {\n const distBetween = distanceBetween(centerOfRectangle(rect), centerRect);\n collisions.push({\n id,\n data: {\n droppableContainer,\n value: distBetween\n }\n });\n }\n }\n\n return collisions.sort(sortCollisionsAsc);\n};\n\n/**\r\n * Returns the closest rectangles from an array of rectangles to the corners of\r\n * another rectangle.\r\n */\n\nconst closestCorners = _ref => {\n let {\n collisionRect,\n droppableRects,\n droppableContainers\n } = _ref;\n const corners = cornersOfRectangle(collisionRect);\n const collisions = [];\n\n for (const droppableContainer of droppableContainers) {\n const {\n id\n } = droppableContainer;\n const rect = droppableRects.get(id);\n\n if (rect) {\n const rectCorners = cornersOfRectangle(rect);\n const distances = corners.reduce((accumulator, corner, index) => {\n return accumulator + distanceBetween(rectCorners[index], corner);\n }, 0);\n const effectiveDistance = Number((distances / 4).toFixed(4));\n collisions.push({\n id,\n data: {\n droppableContainer,\n value: effectiveDistance\n }\n });\n }\n }\n\n return collisions.sort(sortCollisionsAsc);\n};\n\n/**\r\n * Returns the intersecting rectangle area between two rectangles\r\n */\n\nfunction getIntersectionRatio(entry, target) {\n const top = Math.max(target.top, entry.top);\n const left = Math.max(target.left, entry.left);\n const right = Math.min(target.left + target.width, entry.left + entry.width);\n const bottom = Math.min(target.top + target.height, entry.top + entry.height);\n const width = right - left;\n const height = bottom - top;\n\n if (left < right && top < bottom) {\n const targetArea = target.width * target.height;\n const entryArea = entry.width * entry.height;\n const intersectionArea = width * height;\n const intersectionRatio = intersectionArea / (targetArea + entryArea - intersectionArea);\n return Number(intersectionRatio.toFixed(4));\n } // Rectangles do not overlap, or overlap has an area of zero (edge/corner overlap)\n\n\n return 0;\n}\n/**\r\n * Returns the rectangles that has the greatest intersection area with a given\r\n * rectangle in an array of rectangles.\r\n */\n\nconst rectIntersection = _ref => {\n let {\n collisionRect,\n droppableRects,\n droppableContainers\n } = _ref;\n const collisions = [];\n\n for (const droppableContainer of droppableContainers) {\n const {\n id\n } = droppableContainer;\n const rect = droppableRects.get(id);\n\n if (rect) {\n const intersectionRatio = getIntersectionRatio(rect, collisionRect);\n\n if (intersectionRatio > 0) {\n collisions.push({\n id,\n data: {\n droppableContainer,\n value: intersectionRatio\n }\n });\n }\n }\n }\n\n return collisions.sort(sortCollisionsDesc);\n};\n\n/**\r\n * Check if a given point is contained within a bounding rectangle\r\n */\n\nfunction isPointWithinRect(point, rect) {\n const {\n top,\n left,\n bottom,\n right\n } = rect;\n return top <= point.y && point.y <= bottom && left <= point.x && point.x <= right;\n}\n/**\r\n * Returns the rectangles that the pointer is hovering over\r\n */\n\n\nconst pointerWithin = _ref => {\n let {\n droppableContainers,\n droppableRects,\n pointerCoordinates\n } = _ref;\n\n if (!pointerCoordinates) {\n return [];\n }\n\n const collisions = [];\n\n for (const droppableContainer of droppableContainers) {\n const {\n id\n } = droppableContainer;\n const rect = droppableRects.get(id);\n\n if (rect && isPointWithinRect(pointerCoordinates, rect)) {\n /* There may be more than a single rectangle intersecting\r\n * with the pointer coordinates. In order to sort the\r\n * colliding rectangles, we measure the distance between\r\n * the pointer and the corners of the intersecting rectangle\r\n */\n const corners = cornersOfRectangle(rect);\n const distances = corners.reduce((accumulator, corner) => {\n return accumulator + distanceBetween(pointerCoordinates, corner);\n }, 0);\n const effectiveDistance = Number((distances / 4).toFixed(4));\n collisions.push({\n id,\n data: {\n droppableContainer,\n value: effectiveDistance\n }\n });\n }\n }\n\n return collisions.sort(sortCollisionsAsc);\n};\n\nfunction adjustScale(transform, rect1, rect2) {\n return { ...transform,\n scaleX: rect1 && rect2 ? rect1.width / rect2.width : 1,\n scaleY: rect1 && rect2 ? rect1.height / rect2.height : 1\n };\n}\n\nfunction getRectDelta(rect1, rect2) {\n return rect1 && rect2 ? {\n x: rect1.left - rect2.left,\n y: rect1.top - rect2.top\n } : defaultCoordinates;\n}\n\nfunction createRectAdjustmentFn(modifier) {\n return function adjustClientRect(rect) {\n for (var _len = arguments.length, adjustments = new Array(_len > 1 ? _len - 1 : 0), _key = 1; _key < _len; _key++) {\n adjustments[_key - 1] = arguments[_key];\n }\n\n return adjustments.reduce((acc, adjustment) => ({ ...acc,\n top: acc.top + modifier * adjustment.y,\n bottom: acc.bottom + modifier * adjustment.y,\n left: acc.left + modifier * adjustment.x,\n right: acc.right + modifier * adjustment.x\n }), { ...rect\n });\n };\n}\nconst getAdjustedRect = /*#__PURE__*/createRectAdjustmentFn(1);\n\nfunction parseTransform(transform) {\n if (transform.startsWith('matrix3d(')) {\n const transformArray = transform.slice(9, -1).split(/, /);\n return {\n x: +transformArray[12],\n y: +transformArray[13],\n scaleX: +transformArray[0],\n scaleY: +transformArray[5]\n };\n } else if (transform.startsWith('matrix(')) {\n const transformArray = transform.slice(7, -1).split(/, /);\n return {\n x: +transformArray[4],\n y: +transformArray[5],\n scaleX: +transformArray[0],\n scaleY: +transformArray[3]\n };\n }\n\n return null;\n}\n\nfunction inverseTransform(rect, transform, transformOrigin) {\n const parsedTransform = parseTransform(transform);\n\n if (!parsedTransform) {\n return rect;\n }\n\n const {\n scaleX,\n scaleY,\n x: translateX,\n y: translateY\n } = parsedTransform;\n const x = rect.left - translateX - (1 - scaleX) * parseFloat(transformOrigin);\n const y = rect.top - translateY - (1 - scaleY) * parseFloat(transformOrigin.slice(transformOrigin.indexOf(' ') + 1));\n const w = scaleX ? rect.width / scaleX : rect.width;\n const h = scaleY ? rect.height / scaleY : rect.height;\n return {\n width: w,\n height: h,\n top: y,\n right: x + w,\n bottom: y + h,\n left: x\n };\n}\n\nconst defaultOptions = {\n ignoreTransform: false\n};\n/**\r\n * Returns the bounding client rect of an element relative to the viewport.\r\n */\n\nfunction getClientRect(element, options) {\n if (options === void 0) {\n options = defaultOptions;\n }\n\n let rect = element.getBoundingClientRect();\n\n if (options.ignoreTransform) {\n const {\n transform,\n transformOrigin\n } = getWindow(element).getComputedStyle(element);\n\n if (transform) {\n rect = inverseTransform(rect, transform, transformOrigin);\n }\n }\n\n const {\n top,\n left,\n width,\n height,\n bottom,\n right\n } = rect;\n return {\n top,\n left,\n width,\n height,\n bottom,\n right\n };\n}\n/**\r\n * Returns the bounding client rect of an element relative to the viewport.\r\n *\r\n * @remarks\r\n * The ClientRect returned by this method does not take into account transforms\r\n * applied to the element it measures.\r\n *\r\n */\n\nfunction getTransformAgnosticClientRect(element) {\n return getClientRect(element, {\n ignoreTransform: true\n });\n}\n\nfunction getWindowClientRect(element) {\n const width = element.innerWidth;\n const height = element.innerHeight;\n return {\n top: 0,\n left: 0,\n right: width,\n bottom: height,\n width,\n height\n };\n}\n\nfunction isFixed(node, computedStyle) {\n if (computedStyle === void 0) {\n computedStyle = getWindow(node).getComputedStyle(node);\n }\n\n return computedStyle.position === 'fixed';\n}\n\nfunction isScrollable(element, computedStyle) {\n if (computedStyle === void 0) {\n computedStyle = getWindow(element).getComputedStyle(element);\n }\n\n const overflowRegex = /(auto|scroll|overlay)/;\n const properties = ['overflow', 'overflowX', 'overflowY'];\n return properties.some(property => {\n const value = computedStyle[property];\n return typeof value === 'string' ? overflowRegex.test(value) : false;\n });\n}\n\nfunction getScrollableAncestors(element, limit) {\n const scrollParents = [];\n\n function findScrollableAncestors(node) {\n if (limit != null && scrollParents.length >= limit) {\n return scrollParents;\n }\n\n if (!node) {\n return scrollParents;\n }\n\n if (isDocument(node) && node.scrollingElement != null && !scrollParents.includes(node.scrollingElement)) {\n scrollParents.push(node.scrollingElement);\n return scrollParents;\n }\n\n if (!isHTMLElement(node) || isSVGElement(node)) {\n return scrollParents;\n }\n\n if (scrollParents.includes(node)) {\n return scrollParents;\n }\n\n const computedStyle = getWindow(element).getComputedStyle(node);\n\n if (node !== element) {\n if (isScrollable(node, computedStyle)) {\n scrollParents.push(node);\n }\n }\n\n if (isFixed(node, computedStyle)) {\n return scrollParents;\n }\n\n return findScrollableAncestors(node.parentNode);\n }\n\n if (!element) {\n return scrollParents;\n }\n\n return findScrollableAncestors(element);\n}\nfunction getFirstScrollableAncestor(node) {\n const [firstScrollableAncestor] = getScrollableAncestors(node, 1);\n return firstScrollableAncestor != null ? firstScrollableAncestor : null;\n}\n\nfunction getScrollableElement(element) {\n if (!canUseDOM || !element) {\n return null;\n }\n\n if (isWindow(element)) {\n return element;\n }\n\n if (!isNode(element)) {\n return null;\n }\n\n if (isDocument(element) || element === getOwnerDocument(element).scrollingElement) {\n return window;\n }\n\n if (isHTMLElement(element)) {\n return element;\n }\n\n return null;\n}\n\nfunction getScrollXCoordinate(element) {\n if (isWindow(element)) {\n return element.scrollX;\n }\n\n return element.scrollLeft;\n}\nfunction getScrollYCoordinate(element) {\n if (isWindow(element)) {\n return element.scrollY;\n }\n\n return element.scrollTop;\n}\nfunction getScrollCoordinates(element) {\n return {\n x: getScrollXCoordinate(element),\n y: getScrollYCoordinate(element)\n };\n}\n\nvar Direction;\n\n(function (Direction) {\n Direction[Direction[\"Forward\"] = 1] = \"Forward\";\n Direction[Direction[\"Backward\"] = -1] = \"Backward\";\n})(Direction || (Direction = {}));\n\nfunction isDocumentScrollingElement(element) {\n if (!canUseDOM || !element) {\n return false;\n }\n\n return element === document.scrollingElement;\n}\n\nfunction getScrollPosition(scrollingContainer) {\n const minScroll = {\n x: 0,\n y: 0\n };\n const dimensions = isDocumentScrollingElement(scrollingContainer) ? {\n height: window.innerHeight,\n width: window.innerWidth\n } : {\n height: scrollingContainer.clientHeight,\n width: scrollingContainer.clientWidth\n };\n const maxScroll = {\n x: scrollingContainer.scrollWidth - dimensions.width,\n y: scrollingContainer.scrollHeight - dimensions.height\n };\n const isTop = scrollingContainer.scrollTop <= minScroll.y;\n const isLeft = scrollingContainer.scrollLeft <= minScroll.x;\n const isBottom = scrollingContainer.scrollTop >= maxScroll.y;\n const isRight = scrollingContainer.scrollLeft >= maxScroll.x;\n return {\n isTop,\n isLeft,\n isBottom,\n isRight,\n maxScroll,\n minScroll\n };\n}\n\nconst defaultThreshold = {\n x: 0.2,\n y: 0.2\n};\nfunction getScrollDirectionAndSpeed(scrollContainer, scrollContainerRect, _ref, acceleration, thresholdPercentage) {\n let {\n top,\n left,\n right,\n bottom\n } = _ref;\n\n if (acceleration === void 0) {\n acceleration = 10;\n }\n\n if (thresholdPercentage === void 0) {\n thresholdPercentage = defaultThreshold;\n }\n\n const {\n isTop,\n isBottom,\n isLeft,\n isRight\n } = getScrollPosition(scrollContainer);\n const direction = {\n x: 0,\n y: 0\n };\n const speed = {\n x: 0,\n y: 0\n };\n const threshold = {\n height: scrollContainerRect.height * thresholdPercentage.y,\n width: scrollContainerRect.width * thresholdPercentage.x\n };\n\n if (!isTop && top <= scrollContainerRect.top + threshold.height) {\n // Scroll Up\n direction.y = Direction.Backward;\n speed.y = acceleration * Math.abs((scrollContainerRect.top + threshold.height - top) / threshold.height);\n } else if (!isBottom && bottom >= scrollContainerRect.bottom - threshold.height) {\n // Scroll Down\n direction.y = Direction.Forward;\n speed.y = acceleration * Math.abs((scrollContainerRect.bottom - threshold.height - bottom) / threshold.height);\n }\n\n if (!isRight && right >= scrollContainerRect.right - threshold.width) {\n // Scroll Right\n direction.x = Direction.Forward;\n speed.x = acceleration * Math.abs((scrollContainerRect.right - threshold.width - right) / threshold.width);\n } else if (!isLeft && left <= scrollContainerRect.left + threshold.width) {\n // Scroll Left\n direction.x = Direction.Backward;\n speed.x = acceleration * Math.abs((scrollContainerRect.left + threshold.width - left) / threshold.width);\n }\n\n return {\n direction,\n speed\n };\n}\n\nfunction getScrollElementRect(element) {\n if (element === document.scrollingElement) {\n const {\n innerWidth,\n innerHeight\n } = window;\n return {\n top: 0,\n left: 0,\n right: innerWidth,\n bottom: innerHeight,\n width: innerWidth,\n height: innerHeight\n };\n }\n\n const {\n top,\n left,\n right,\n bottom\n } = element.getBoundingClientRect();\n return {\n top,\n left,\n right,\n bottom,\n width: element.clientWidth,\n height: element.clientHeight\n };\n}\n\nfunction getScrollOffsets(scrollableAncestors) {\n return scrollableAncestors.reduce((acc, node) => {\n return add(acc, getScrollCoordinates(node));\n }, defaultCoordinates);\n}\nfunction getScrollXOffset(scrollableAncestors) {\n return scrollableAncestors.reduce((acc, node) => {\n return acc + getScrollXCoordinate(node);\n }, 0);\n}\nfunction getScrollYOffset(scrollableAncestors) {\n return scrollableAncestors.reduce((acc, node) => {\n return acc + getScrollYCoordinate(node);\n }, 0);\n}\n\nfunction scrollIntoViewIfNeeded(element, measure) {\n if (measure === void 0) {\n measure = getClientRect;\n }\n\n if (!element) {\n return;\n }\n\n const {\n top,\n left,\n bottom,\n right\n } = measure(element);\n const firstScrollableAncestor = getFirstScrollableAncestor(element);\n\n if (!firstScrollableAncestor) {\n return;\n }\n\n if (bottom <= 0 || right <= 0 || top >= window.innerHeight || left >= window.innerWidth) {\n element.scrollIntoView({\n block: 'center',\n inline: 'center'\n });\n }\n}\n\nconst properties = [['x', ['left', 'right'], getScrollXOffset], ['y', ['top', 'bottom'], getScrollYOffset]];\nclass Rect {\n constructor(rect, element) {\n this.rect = void 0;\n this.width = void 0;\n this.height = void 0;\n this.top = void 0;\n this.bottom = void 0;\n this.right = void 0;\n this.left = void 0;\n const scrollableAncestors = getScrollableAncestors(element);\n const scrollOffsets = getScrollOffsets(scrollableAncestors);\n this.rect = { ...rect\n };\n this.width = rect.width;\n this.height = rect.height;\n\n for (const [axis, keys, getScrollOffset] of properties) {\n for (const key of keys) {\n Object.defineProperty(this, key, {\n get: () => {\n const currentOffsets = getScrollOffset(scrollableAncestors);\n const scrollOffsetsDeltla = scrollOffsets[axis] - currentOffsets;\n return this.rect[key] + scrollOffsetsDeltla;\n },\n enumerable: true\n });\n }\n }\n\n Object.defineProperty(this, 'rect', {\n enumerable: false\n });\n }\n\n}\n\nclass Listeners {\n constructor(target) {\n this.target = void 0;\n this.listeners = [];\n\n this.removeAll = () => {\n this.listeners.forEach(listener => {\n var _this$target;\n\n return (_this$target = this.target) == null ? void 0 : _this$target.removeEventListener(...listener);\n });\n };\n\n this.target = target;\n }\n\n add(eventName, handler, options) {\n var _this$target2;\n\n (_this$target2 = this.target) == null ? void 0 : _this$target2.addEventListener(eventName, handler, options);\n this.listeners.push([eventName, handler, options]);\n }\n\n}\n\nfunction getEventListenerTarget(target) {\n // If the `event.target` element is removed from the document events will still be targeted\n // at it, and hence won't always bubble up to the window or document anymore.\n // If there is any risk of an element being removed while it is being dragged,\n // the best practice is to attach the event listeners directly to the target.\n // https://developer.mozilla.org/en-US/docs/Web/API/EventTarget\n const {\n EventTarget\n } = getWindow(target);\n return target instanceof EventTarget ? target : getOwnerDocument(target);\n}\n\nfunction hasExceededDistance(delta, measurement) {\n const dx = Math.abs(delta.x);\n const dy = Math.abs(delta.y);\n\n if (typeof measurement === 'number') {\n return Math.sqrt(dx ** 2 + dy ** 2) > measurement;\n }\n\n if ('x' in measurement && 'y' in measurement) {\n return dx > measurement.x && dy > measurement.y;\n }\n\n if ('x' in measurement) {\n return dx > measurement.x;\n }\n\n if ('y' in measurement) {\n return dy > measurement.y;\n }\n\n return false;\n}\n\nvar EventName;\n\n(function (EventName) {\n EventName[\"Click\"] = \"click\";\n EventName[\"DragStart\"] = \"dragstart\";\n EventName[\"Keydown\"] = \"keydown\";\n EventName[\"ContextMenu\"] = \"contextmenu\";\n EventName[\"Resize\"] = \"resize\";\n EventName[\"SelectionChange\"] = \"selectionchange\";\n EventName[\"VisibilityChange\"] = \"visibilitychange\";\n})(EventName || (EventName = {}));\n\nfunction preventDefault(event) {\n event.preventDefault();\n}\nfunction stopPropagation(event) {\n event.stopPropagation();\n}\n\nvar KeyboardCode;\n\n(function (KeyboardCode) {\n KeyboardCode[\"Space\"] = \"Space\";\n KeyboardCode[\"Down\"] = \"ArrowDown\";\n KeyboardCode[\"Right\"] = \"ArrowRight\";\n KeyboardCode[\"Left\"] = \"ArrowLeft\";\n KeyboardCode[\"Up\"] = \"ArrowUp\";\n KeyboardCode[\"Esc\"] = \"Escape\";\n KeyboardCode[\"Enter\"] = \"Enter\";\n KeyboardCode[\"Tab\"] = \"Tab\";\n})(KeyboardCode || (KeyboardCode = {}));\n\nconst defaultKeyboardCodes = {\n start: [KeyboardCode.Space, KeyboardCode.Enter],\n cancel: [KeyboardCode.Esc],\n end: [KeyboardCode.Space, KeyboardCode.Enter, KeyboardCode.Tab]\n};\nconst defaultKeyboardCoordinateGetter = (event, _ref) => {\n let {\n currentCoordinates\n } = _ref;\n\n switch (event.code) {\n case KeyboardCode.Right:\n return { ...currentCoordinates,\n x: currentCoordinates.x + 25\n };\n\n case KeyboardCode.Left:\n return { ...currentCoordinates,\n x: currentCoordinates.x - 25\n };\n\n case KeyboardCode.Down:\n return { ...currentCoordinates,\n y: currentCoordinates.y + 25\n };\n\n case KeyboardCode.Up:\n return { ...currentCoordinates,\n y: currentCoordinates.y - 25\n };\n }\n\n return undefined;\n};\n\nclass KeyboardSensor {\n constructor(props) {\n this.props = void 0;\n this.autoScrollEnabled = false;\n this.referenceCoordinates = void 0;\n this.listeners = void 0;\n this.windowListeners = void 0;\n this.props = props;\n const {\n event: {\n target\n }\n } = props;\n this.props = props;\n this.listeners = new Listeners(getOwnerDocument(target));\n this.windowListeners = new Listeners(getWindow(target));\n this.handleKeyDown = this.handleKeyDown.bind(this);\n this.handleCancel = this.handleCancel.bind(this);\n this.attach();\n }\n\n attach() {\n this.handleStart();\n this.windowListeners.add(EventName.Resize, this.handleCancel);\n this.windowListeners.add(EventName.VisibilityChange, this.handleCancel);\n setTimeout(() => this.listeners.add(EventName.Keydown, this.handleKeyDown));\n }\n\n handleStart() {\n const {\n activeNode,\n onStart\n } = this.props;\n const node = activeNode.node.current;\n\n if (node) {\n scrollIntoViewIfNeeded(node);\n }\n\n onStart(defaultCoordinates);\n }\n\n handleKeyDown(event) {\n if (isKeyboardEvent(event)) {\n const {\n active,\n context,\n options\n } = this.props;\n const {\n keyboardCodes = defaultKeyboardCodes,\n coordinateGetter = defaultKeyboardCoordinateGetter,\n scrollBehavior = 'smooth'\n } = options;\n const {\n code\n } = event;\n\n if (keyboardCodes.end.includes(code)) {\n this.handleEnd(event);\n return;\n }\n\n if (keyboardCodes.cancel.includes(code)) {\n this.handleCancel(event);\n return;\n }\n\n const {\n collisionRect\n } = context.current;\n const currentCoordinates = collisionRect ? {\n x: collisionRect.left,\n y: collisionRect.top\n } : defaultCoordinates;\n\n if (!this.referenceCoordinates) {\n this.referenceCoordinates = currentCoordinates;\n }\n\n const newCoordinates = coordinateGetter(event, {\n active,\n context: context.current,\n currentCoordinates\n });\n\n if (newCoordinates) {\n const coordinatesDelta = subtract(newCoordinates, currentCoordinates);\n const scrollDelta = {\n x: 0,\n y: 0\n };\n const {\n scrollableAncestors\n } = context.current;\n\n for (const scrollContainer of scrollableAncestors) {\n const direction = event.code;\n const {\n isTop,\n isRight,\n isLeft,\n isBottom,\n maxScroll,\n minScroll\n } = getScrollPosition(scrollContainer);\n const scrollElementRect = getScrollElementRect(scrollContainer);\n const clampedCoordinates = {\n x: Math.min(direction === KeyboardCode.Right ? scrollElementRect.right - scrollElementRect.width / 2 : scrollElementRect.right, Math.max(direction === KeyboardCode.Right ? scrollElementRect.left : scrollElementRect.left + scrollElementRect.width / 2, newCoordinates.x)),\n y: Math.min(direction === KeyboardCode.Down ? scrollElementRect.bottom - scrollElementRect.height / 2 : scrollElementRect.bottom, Math.max(direction === KeyboardCode.Down ? scrollElementRect.top : scrollElementRect.top + scrollElementRect.height / 2, newCoordinates.y))\n };\n const canScrollX = direction === KeyboardCode.Right && !isRight || direction === KeyboardCode.Left && !isLeft;\n const canScrollY = direction === KeyboardCode.Down && !isBottom || direction === KeyboardCode.Up && !isTop;\n\n if (canScrollX && clampedCoordinates.x !== newCoordinates.x) {\n const newScrollCoordinates = scrollContainer.scrollLeft + coordinatesDelta.x;\n const canScrollToNewCoordinates = direction === KeyboardCode.Right && newScrollCoordinates <= maxScroll.x || direction === KeyboardCode.Left && newScrollCoordinates >= minScroll.x;\n\n if (canScrollToNewCoordinates && !coordinatesDelta.y) {\n // We don't need to update coordinates, the scroll adjustment alone will trigger\n // logic to auto-detect the new container we are over\n scrollContainer.scrollTo({\n left: newScrollCoordinates,\n behavior: scrollBehavior\n });\n return;\n }\n\n if (canScrollToNewCoordinates) {\n scrollDelta.x = scrollContainer.scrollLeft - newScrollCoordinates;\n } else {\n scrollDelta.x = direction === KeyboardCode.Right ? scrollContainer.scrollLeft - maxScroll.x : scrollContainer.scrollLeft - minScroll.x;\n }\n\n if (scrollDelta.x) {\n scrollContainer.scrollBy({\n left: -scrollDelta.x,\n behavior: scrollBehavior\n });\n }\n\n break;\n } else if (canScrollY && clampedCoordinates.y !== newCoordinates.y) {\n const newScrollCoordinates = scrollContainer.scrollTop + coordinatesDelta.y;\n const canScrollToNewCoordinates = direction === KeyboardCode.Down && newScrollCoordinates <= maxScroll.y || direction === KeyboardCode.Up && newScrollCoordinates >= minScroll.y;\n\n if (canScrollToNewCoordinates && !coordinatesDelta.x) {\n // We don't need to update coordinates, the scroll adjustment alone will trigger\n // logic to auto-detect the new container we are over\n scrollContainer.scrollTo({\n top: newScrollCoordinates,\n behavior: scrollBehavior\n });\n return;\n }\n\n if (canScrollToNewCoordinates) {\n scrollDelta.y = scrollContainer.scrollTop - newScrollCoordinates;\n } else {\n scrollDelta.y = direction === KeyboardCode.Down ? scrollContainer.scrollTop - maxScroll.y : scrollContainer.scrollTop - minScroll.y;\n }\n\n if (scrollDelta.y) {\n scrollContainer.scrollBy({\n top: -scrollDelta.y,\n behavior: scrollBehavior\n });\n }\n\n break;\n }\n }\n\n this.handleMove(event, add(subtract(newCoordinates, this.referenceCoordinates), scrollDelta));\n }\n }\n }\n\n handleMove(event, coordinates) {\n const {\n onMove\n } = this.props;\n event.preventDefault();\n onMove(coordinates);\n }\n\n handleEnd(event) {\n const {\n onEnd\n } = this.props;\n event.preventDefault();\n this.detach();\n onEnd();\n }\n\n handleCancel(event) {\n const {\n onCancel\n } = this.props;\n event.preventDefault();\n this.detach();\n onCancel();\n }\n\n detach() {\n this.listeners.removeAll();\n this.windowListeners.removeAll();\n }\n\n}\nKeyboardSensor.activators = [{\n eventName: 'onKeyDown',\n handler: (event, _ref, _ref2) => {\n let {\n keyboardCodes = defaultKeyboardCodes,\n onActivation\n } = _ref;\n let {\n active\n } = _ref2;\n const {\n code\n } = event.nativeEvent;\n\n if (keyboardCodes.start.includes(code)) {\n const activator = active.activatorNode.current;\n\n if (activator && event.target !== activator) {\n return false;\n }\n\n event.preventDefault();\n onActivation == null ? void 0 : onActivation({\n event: event.nativeEvent\n });\n return true;\n }\n\n return false;\n }\n}];\n\nfunction isDistanceConstraint(constraint) {\n return Boolean(constraint && 'distance' in constraint);\n}\n\nfunction isDelayConstraint(constraint) {\n return Boolean(constraint && 'delay' in constraint);\n}\n\nclass AbstractPointerSensor {\n constructor(props, events, listenerTarget) {\n var _getEventCoordinates;\n\n if (listenerTarget === void 0) {\n listenerTarget = getEventListenerTarget(props.event.target);\n }\n\n this.props = void 0;\n this.events = void 0;\n this.autoScrollEnabled = true;\n this.document = void 0;\n this.activated = false;\n this.initialCoordinates = void 0;\n this.timeoutId = null;\n this.listeners = void 0;\n this.documentListeners = void 0;\n this.windowListeners = void 0;\n this.props = props;\n this.events = events;\n const {\n event\n } = props;\n const {\n target\n } = event;\n this.props = props;\n this.events = events;\n this.document = getOwnerDocument(target);\n this.documentListeners = new Listeners(this.document);\n this.listeners = new Listeners(listenerTarget);\n this.windowListeners = new Listeners(getWindow(target));\n this.initialCoordinates = (_getEventCoordinates = getEventCoordinates(event)) != null ? _getEventCoordinates : defaultCoordinates;\n this.handleStart = this.handleStart.bind(this);\n this.handleMove = this.handleMove.bind(this);\n this.handleEnd = this.handleEnd.bind(this);\n this.handleCancel = this.handleCancel.bind(this);\n this.handleKeydown = this.handleKeydown.bind(this);\n this.removeTextSelection = this.removeTextSelection.bind(this);\n this.attach();\n }\n\n attach() {\n const {\n events,\n props: {\n options: {\n activationConstraint,\n bypassActivationConstraint\n }\n }\n } = this;\n this.listeners.add(events.move.name, this.handleMove, {\n passive: false\n });\n this.listeners.add(events.end.name, this.handleEnd);\n\n if (events.cancel) {\n this.listeners.add(events.cancel.name, this.handleCancel);\n }\n\n this.windowListeners.add(EventName.Resize, this.handleCancel);\n this.windowListeners.add(EventName.DragStart, preventDefault);\n this.windowListeners.add(EventName.VisibilityChange, this.handleCancel);\n this.windowListeners.add(EventName.ContextMenu, preventDefault);\n this.documentListeners.add(EventName.Keydown, this.handleKeydown);\n\n if (activationConstraint) {\n if (bypassActivationConstraint != null && bypassActivationConstraint({\n event: this.props.event,\n activeNode: this.props.activeNode,\n options: this.props.options\n })) {\n return this.handleStart();\n }\n\n if (isDelayConstraint(activationConstraint)) {\n this.timeoutId = setTimeout(this.handleStart, activationConstraint.delay);\n this.handlePending(activationConstraint);\n return;\n }\n\n if (isDistanceConstraint(activationConstraint)) {\n this.handlePending(activationConstraint);\n return;\n }\n }\n\n this.handleStart();\n }\n\n detach() {\n this.listeners.removeAll();\n this.windowListeners.removeAll(); // Wait until the next event loop before removing document listeners\n // This is necessary because we listen for `click` and `selection` events on the document\n\n setTimeout(this.documentListeners.removeAll, 50);\n\n if (this.timeoutId !== null) {\n clearTimeout(this.timeoutId);\n this.timeoutId = null;\n }\n }\n\n handlePending(constraint, offset) {\n const {\n active,\n onPending\n } = this.props;\n onPending(active, constraint, this.initialCoordinates, offset);\n }\n\n handleStart() {\n const {\n initialCoordinates\n } = this;\n const {\n onStart\n } = this.props;\n\n if (initialCoordinates) {\n this.activated = true; // Stop propagation of click events once activation constraints are met\n\n this.documentListeners.add(EventName.Click, stopPropagation, {\n capture: true\n }); // Remove any text selection from the document\n\n this.removeTextSelection(); // Prevent further text selection while dragging\n\n this.documentListeners.add(EventName.SelectionChange, this.removeTextSelection);\n onStart(initialCoordinates);\n }\n }\n\n handleMove(event) {\n var _getEventCoordinates2;\n\n const {\n activated,\n initialCoordinates,\n props\n } = this;\n const {\n onMove,\n options: {\n activationConstraint\n }\n } = props;\n\n if (!initialCoordinates) {\n return;\n }\n\n const coordinates = (_getEventCoordinates2 = getEventCoordinates(event)) != null ? _getEventCoordinates2 : defaultCoordinates;\n const delta = subtract(initialCoordinates, coordinates); // Constraint validation\n\n if (!activated && activationConstraint) {\n if (isDistanceConstraint(activationConstraint)) {\n if (activationConstraint.tolerance != null && hasExceededDistance(delta, activationConstraint.tolerance)) {\n return this.handleCancel();\n }\n\n if (hasExceededDistance(delta, activationConstraint.distance)) {\n return this.handleStart();\n }\n }\n\n if (isDelayConstraint(activationConstraint)) {\n if (hasExceededDistance(delta, activationConstraint.tolerance)) {\n return this.handleCancel();\n }\n }\n\n this.handlePending(activationConstraint, delta);\n return;\n }\n\n if (event.cancelable) {\n event.preventDefault();\n }\n\n onMove(coordinates);\n }\n\n handleEnd() {\n const {\n onAbort,\n onEnd\n } = this.props;\n this.detach();\n\n if (!this.activated) {\n onAbort(this.props.active);\n }\n\n onEnd();\n }\n\n handleCancel() {\n const {\n onAbort,\n onCancel\n } = this.props;\n this.detach();\n\n if (!this.activated) {\n onAbort(this.props.active);\n }\n\n onCancel();\n }\n\n handleKeydown(event) {\n if (event.code === KeyboardCode.Esc) {\n this.handleCancel();\n }\n }\n\n removeTextSelection() {\n var _this$document$getSel;\n\n (_this$document$getSel = this.document.getSelection()) == null ? void 0 : _this$document$getSel.removeAllRanges();\n }\n\n}\n\nconst events = {\n cancel: {\n name: 'pointercancel'\n },\n move: {\n name: 'pointermove'\n },\n end: {\n name: 'pointerup'\n }\n};\nclass PointerSensor extends AbstractPointerSensor {\n constructor(props) {\n const {\n event\n } = props; // Pointer events stop firing if the target is unmounted while dragging\n // Therefore we attach listeners to the owner document instead\n\n const listenerTarget = getOwnerDocument(event.target);\n super(props, events, listenerTarget);\n }\n\n}\nPointerSensor.activators = [{\n eventName: 'onPointerDown',\n handler: (_ref, _ref2) => {\n let {\n nativeEvent: event\n } = _ref;\n let {\n onActivation\n } = _ref2;\n\n if (!event.isPrimary || event.button !== 0) {\n return false;\n }\n\n onActivation == null ? void 0 : onActivation({\n event\n });\n return true;\n }\n}];\n\nconst events$1 = {\n move: {\n name: 'mousemove'\n },\n end: {\n name: 'mouseup'\n }\n};\nvar MouseButton;\n\n(function (MouseButton) {\n MouseButton[MouseButton[\"RightClick\"] = 2] = \"RightClick\";\n})(MouseButton || (MouseButton = {}));\n\nclass MouseSensor extends AbstractPointerSensor {\n constructor(props) {\n super(props, events$1, getOwnerDocument(props.event.target));\n }\n\n}\nMouseSensor.activators = [{\n eventName: 'onMouseDown',\n handler: (_ref, _ref2) => {\n let {\n nativeEvent: event\n } = _ref;\n let {\n onActivation\n } = _ref2;\n\n if (event.button === MouseButton.RightClick) {\n return false;\n }\n\n onActivation == null ? void 0 : onActivation({\n event\n });\n return true;\n }\n}];\n\nconst events$2 = {\n cancel: {\n name: 'touchcancel'\n },\n move: {\n name: 'touchmove'\n },\n end: {\n name: 'touchend'\n }\n};\nclass TouchSensor extends AbstractPointerSensor {\n constructor(props) {\n super(props, events$2);\n }\n\n static setup() {\n // Adding a non-capture and non-passive `touchmove` listener in order\n // to force `event.preventDefault()` calls to work in dynamically added\n // touchmove event handlers. This is required for iOS Safari.\n window.addEventListener(events$2.move.name, noop, {\n capture: false,\n passive: false\n });\n return function teardown() {\n window.removeEventListener(events$2.move.name, noop);\n }; // We create a new handler because the teardown function of another sensor\n // could remove our event listener if we use a referentially equal listener.\n\n function noop() {}\n }\n\n}\nTouchSensor.activators = [{\n eventName: 'onTouchStart',\n handler: (_ref, _ref2) => {\n let {\n nativeEvent: event\n } = _ref;\n let {\n onActivation\n } = _ref2;\n const {\n touches\n } = event;\n\n if (touches.length > 1) {\n return false;\n }\n\n onActivation == null ? void 0 : onActivation({\n event\n });\n return true;\n }\n}];\n\nvar AutoScrollActivator;\n\n(function (AutoScrollActivator) {\n AutoScrollActivator[AutoScrollActivator[\"Pointer\"] = 0] = \"Pointer\";\n AutoScrollActivator[AutoScrollActivator[\"DraggableRect\"] = 1] = \"DraggableRect\";\n})(AutoScrollActivator || (AutoScrollActivator = {}));\n\nvar TraversalOrder;\n\n(function (TraversalOrder) {\n TraversalOrder[TraversalOrder[\"TreeOrder\"] = 0] = \"TreeOrder\";\n TraversalOrder[TraversalOrder[\"ReversedTreeOrder\"] = 1] = \"ReversedTreeOrder\";\n})(TraversalOrder || (TraversalOrder = {}));\n\nfunction useAutoScroller(_ref) {\n let {\n acceleration,\n activator = AutoScrollActivator.Pointer,\n canScroll,\n draggingRect,\n enabled,\n interval = 5,\n order = TraversalOrder.TreeOrder,\n pointerCoordinates,\n scrollableAncestors,\n scrollableAncestorRects,\n delta,\n threshold\n } = _ref;\n const scrollIntent = useScrollIntent({\n delta,\n disabled: !enabled\n });\n const [setAutoScrollInterval, clearAutoScrollInterval] = useInterval();\n const scrollSpeed = useRef({\n x: 0,\n y: 0\n });\n const scrollDirection = useRef({\n x: 0,\n y: 0\n });\n const rect = useMemo(() => {\n switch (activator) {\n case AutoScrollActivator.Pointer:\n return pointerCoordinates ? {\n top: pointerCoordinates.y,\n bottom: pointerCoordinates.y,\n left: pointerCoordinates.x,\n right: pointerCoordinates.x\n } : null;\n\n case AutoScrollActivator.DraggableRect:\n return draggingRect;\n }\n }, [activator, draggingRect, pointerCoordinates]);\n const scrollContainerRef = useRef(null);\n const autoScroll = useCallback(() => {\n const scrollContainer = scrollContainerRef.current;\n\n if (!scrollContainer) {\n return;\n }\n\n const scrollLeft = scrollSpeed.current.x * scrollDirection.current.x;\n const scrollTop = scrollSpeed.current.y * scrollDirection.current.y;\n scrollContainer.scrollBy(scrollLeft, scrollTop);\n }, []);\n const sortedScrollableAncestors = useMemo(() => order === TraversalOrder.TreeOrder ? [...scrollableAncestors].reverse() : scrollableAncestors, [order, scrollableAncestors]);\n useEffect(() => {\n if (!enabled || !scrollableAncestors.length || !rect) {\n clearAutoScrollInterval();\n return;\n }\n\n for (const scrollContainer of sortedScrollableAncestors) {\n if ((canScroll == null ? void 0 : canScroll(scrollContainer)) === false) {\n continue;\n }\n\n const index = scrollableAncestors.indexOf(scrollContainer);\n const scrollContainerRect = scrollableAncestorRects[index];\n\n if (!scrollContainerRect) {\n continue;\n }\n\n const {\n direction,\n speed\n } = getScrollDirectionAndSpeed(scrollContainer, scrollContainerRect, rect, acceleration, threshold);\n\n for (const axis of ['x', 'y']) {\n if (!scrollIntent[axis][direction[axis]]) {\n speed[axis] = 0;\n direction[axis] = 0;\n }\n }\n\n if (speed.x > 0 || speed.y > 0) {\n clearAutoScrollInterval();\n scrollContainerRef.current = scrollContainer;\n setAutoScrollInterval(autoScroll, interval);\n scrollSpeed.current = speed;\n scrollDirection.current = direction;\n return;\n }\n }\n\n scrollSpeed.current = {\n x: 0,\n y: 0\n };\n scrollDirection.current = {\n x: 0,\n y: 0\n };\n clearAutoScrollInterval();\n }, // eslint-disable-next-line react-hooks/exhaustive-deps\n [acceleration, autoScroll, canScroll, clearAutoScrollInterval, enabled, interval, // eslint-disable-next-line react-hooks/exhaustive-deps\n JSON.stringify(rect), // eslint-disable-next-line react-hooks/exhaustive-deps\n JSON.stringify(scrollIntent), setAutoScrollInterval, scrollableAncestors, sortedScrollableAncestors, scrollableAncestorRects, // eslint-disable-next-line react-hooks/exhaustive-deps\n JSON.stringify(threshold)]);\n}\nconst defaultScrollIntent = {\n x: {\n [Direction.Backward]: false,\n [Direction.Forward]: false\n },\n y: {\n [Direction.Backward]: false,\n [Direction.Forward]: false\n }\n};\n\nfunction useScrollIntent(_ref2) {\n let {\n delta,\n disabled\n } = _ref2;\n const previousDelta = usePrevious(delta);\n return useLazyMemo(previousIntent => {\n if (disabled || !previousDelta || !previousIntent) {\n // Reset scroll intent tracking when auto-scrolling is disabled\n return defaultScrollIntent;\n }\n\n const direction = {\n x: Math.sign(delta.x - previousDelta.x),\n y: Math.sign(delta.y - previousDelta.y)\n }; // Keep track of the user intent to scroll in each direction for both axis\n\n return {\n x: {\n [Direction.Backward]: previousIntent.x[Direction.Backward] || direction.x === -1,\n [Direction.Forward]: previousIntent.x[Direction.Forward] || direction.x === 1\n },\n y: {\n [Direction.Backward]: previousIntent.y[Direction.Backward] || direction.y === -1,\n [Direction.Forward]: previousIntent.y[Direction.Forward] || direction.y === 1\n }\n };\n }, [disabled, delta, previousDelta]);\n}\n\nfunction useCachedNode(draggableNodes, id) {\n const draggableNode = id != null ? draggableNodes.get(id) : undefined;\n const node = draggableNode ? draggableNode.node.current : null;\n return useLazyMemo(cachedNode => {\n var _ref;\n\n if (id == null) {\n return null;\n } // In some cases, the draggable node can unmount while dragging\n // This is the case for virtualized lists. In those situations,\n // we fall back to the last known value for that node.\n\n\n return (_ref = node != null ? node : cachedNode) != null ? _ref : null;\n }, [node, id]);\n}\n\nfunction useCombineActivators(sensors, getSyntheticHandler) {\n return useMemo(() => sensors.reduce((accumulator, sensor) => {\n const {\n sensor: Sensor\n } = sensor;\n const sensorActivators = Sensor.activators.map(activator => ({\n eventName: activator.eventName,\n handler: getSyntheticHandler(activator.handler, sensor)\n }));\n return [...accumulator, ...sensorActivators];\n }, []), [sensors, getSyntheticHandler]);\n}\n\nvar MeasuringStrategy;\n\n(function (MeasuringStrategy) {\n MeasuringStrategy[MeasuringStrategy[\"Always\"] = 0] = \"Always\";\n MeasuringStrategy[MeasuringStrategy[\"BeforeDragging\"] = 1] = \"BeforeDragging\";\n MeasuringStrategy[MeasuringStrategy[\"WhileDragging\"] = 2] = \"WhileDragging\";\n})(MeasuringStrategy || (MeasuringStrategy = {}));\n\nvar MeasuringFrequency;\n\n(function (MeasuringFrequency) {\n MeasuringFrequency[\"Optimized\"] = \"optimized\";\n})(MeasuringFrequency || (MeasuringFrequency = {}));\n\nconst defaultValue = /*#__PURE__*/new Map();\nfunction useDroppableMeasuring(containers, _ref) {\n let {\n dragging,\n dependencies,\n config\n } = _ref;\n const [queue, setQueue] = useState(null);\n const {\n frequency,\n measure,\n strategy\n } = config;\n const containersRef = useRef(containers);\n const disabled = isDisabled();\n const disabledRef = useLatestValue(disabled);\n const measureDroppableContainers = useCallback(function (ids) {\n if (ids === void 0) {\n ids = [];\n }\n\n if (disabledRef.current) {\n return;\n }\n\n setQueue(value => {\n if (value === null) {\n return ids;\n }\n\n return value.concat(ids.filter(id => !value.includes(id)));\n });\n }, [disabledRef]);\n const timeoutId = useRef(null);\n const droppableRects = useLazyMemo(previousValue => {\n if (disabled && !dragging) {\n return defaultValue;\n }\n\n if (!previousValue || previousValue === defaultValue || containersRef.current !== containers || queue != null) {\n const map = new Map();\n\n for (let container of containers) {\n if (!container) {\n continue;\n }\n\n if (queue && queue.length > 0 && !queue.includes(container.id) && container.rect.current) {\n // This container does not need to be re-measured\n map.set(container.id, container.rect.current);\n continue;\n }\n\n const node = container.node.current;\n const rect = node ? new Rect(measure(node), node) : null;\n container.rect.current = rect;\n\n if (rect) {\n map.set(container.id, rect);\n }\n }\n\n return map;\n }\n\n return previousValue;\n }, [containers, queue, dragging, disabled, measure]);\n useEffect(() => {\n containersRef.current = containers;\n }, [containers]);\n useEffect(() => {\n if (disabled) {\n return;\n }\n\n measureDroppableContainers();\n }, // eslint-disable-next-line react-hooks/exhaustive-deps\n [dragging, disabled]);\n useEffect(() => {\n if (queue && queue.length > 0) {\n setQueue(null);\n }\n }, //eslint-disable-next-line react-hooks/exhaustive-deps\n [JSON.stringify(queue)]);\n useEffect(() => {\n if (disabled || typeof frequency !== 'number' || timeoutId.current !== null) {\n return;\n }\n\n timeoutId.current = setTimeout(() => {\n measureDroppableContainers();\n timeoutId.current = null;\n }, frequency);\n }, // eslint-disable-next-line react-hooks/exhaustive-deps\n [frequency, disabled, measureDroppableContainers, ...dependencies]);\n return {\n droppableRects,\n measureDroppableContainers,\n measuringScheduled: queue != null\n };\n\n function isDisabled() {\n switch (strategy) {\n case MeasuringStrategy.Always:\n return false;\n\n case MeasuringStrategy.BeforeDragging:\n return dragging;\n\n default:\n return !dragging;\n }\n }\n}\n\nfunction useInitialValue(value, computeFn) {\n return useLazyMemo(previousValue => {\n if (!value) {\n return null;\n }\n\n if (previousValue) {\n return previousValue;\n }\n\n return typeof computeFn === 'function' ? computeFn(value) : value;\n }, [computeFn, value]);\n}\n\nfunction useInitialRect(node, measure) {\n return useInitialValue(node, measure);\n}\n\n/**\r\n * Returns a new MutationObserver instance.\r\n * If `MutationObserver` is undefined in the execution environment, returns `undefined`.\r\n */\n\nfunction useMutationObserver(_ref) {\n let {\n callback,\n disabled\n } = _ref;\n const handleMutations = useEvent(callback);\n const mutationObserver = useMemo(() => {\n if (disabled || typeof window === 'undefined' || typeof window.MutationObserver === 'undefined') {\n return undefined;\n }\n\n const {\n MutationObserver\n } = window;\n return new MutationObserver(handleMutations);\n }, [handleMutations, disabled]);\n useEffect(() => {\n return () => mutationObserver == null ? void 0 : mutationObserver.disconnect();\n }, [mutationObserver]);\n return mutationObserver;\n}\n\n/**\r\n * Returns a new ResizeObserver instance bound to the `onResize` callback.\r\n * If `ResizeObserver` is undefined in the execution environment, returns `undefined`.\r\n */\n\nfunction useResizeObserver(_ref) {\n let {\n callback,\n disabled\n } = _ref;\n const handleResize = useEvent(callback);\n const resizeObserver = useMemo(() => {\n if (disabled || typeof window === 'undefined' || typeof window.ResizeObserver === 'undefined') {\n return undefined;\n }\n\n const {\n ResizeObserver\n } = window;\n return new ResizeObserver(handleResize);\n }, // eslint-disable-next-line react-hooks/exhaustive-deps\n [disabled]);\n useEffect(() => {\n return () => resizeObserver == null ? void 0 : resizeObserver.disconnect();\n }, [resizeObserver]);\n return resizeObserver;\n}\n\nfunction defaultMeasure(element) {\n return new Rect(getClientRect(element), element);\n}\n\nfunction useRect(element, measure, fallbackRect) {\n if (measure === void 0) {\n measure = defaultMeasure;\n }\n\n const [rect, setRect] = useState(null);\n\n function measureRect() {\n setRect(currentRect => {\n if (!element) {\n return null;\n }\n\n if (element.isConnected === false) {\n var _ref;\n\n // Fall back to last rect we measured if the element is\n // no longer connected to the DOM.\n return (_ref = currentRect != null ? currentRect : fallbackRect) != null ? _ref : null;\n }\n\n const newRect = measure(element);\n\n if (JSON.stringify(currentRect) === JSON.stringify(newRect)) {\n return currentRect;\n }\n\n return newRect;\n });\n }\n\n const mutationObserver = useMutationObserver({\n callback(records) {\n if (!element) {\n return;\n }\n\n for (const record of records) {\n const {\n type,\n target\n } = record;\n\n if (type === 'childList' && target instanceof HTMLElement && target.contains(element)) {\n measureRect();\n break;\n }\n }\n }\n\n });\n const resizeObserver = useResizeObserver({\n callback: measureRect\n });\n useIsomorphicLayoutEffect(() => {\n measureRect();\n\n if (element) {\n resizeObserver == null ? void 0 : resizeObserver.observe(element);\n mutationObserver == null ? void 0 : mutationObserver.observe(document.body, {\n childList: true,\n subtree: true\n });\n } else {\n resizeObserver == null ? void 0 : resizeObserver.disconnect();\n mutationObserver == null ? void 0 : mutationObserver.disconnect();\n }\n }, [element]);\n return rect;\n}\n\nfunction useRectDelta(rect) {\n const initialRect = useInitialValue(rect);\n return getRectDelta(rect, initialRect);\n}\n\nconst defaultValue$1 = [];\nfunction useScrollableAncestors(node) {\n const previousNode = useRef(node);\n const ancestors = useLazyMemo(previousValue => {\n if (!node) {\n return defaultValue$1;\n }\n\n if (previousValue && previousValue !== defaultValue$1 && node && previousNode.current && node.parentNode === previousNode.current.parentNode) {\n return previousValue;\n }\n\n return getScrollableAncestors(node);\n }, [node]);\n useEffect(() => {\n previousNode.current = node;\n }, [node]);\n return ancestors;\n}\n\nfunction useScrollOffsets(elements) {\n const [scrollCoordinates, setScrollCoordinates] = useState(null);\n const prevElements = useRef(elements); // To-do: Throttle the handleScroll callback\n\n const handleScroll = useCallback(event => {\n const scrollingElement = getScrollableElement(event.target);\n\n if (!scrollingElement) {\n return;\n }\n\n setScrollCoordinates(scrollCoordinates => {\n if (!scrollCoordinates) {\n return null;\n }\n\n scrollCoordinates.set(scrollingElement, getScrollCoordinates(scrollingElement));\n return new Map(scrollCoordinates);\n });\n }, []);\n useEffect(() => {\n const previousElements = prevElements.current;\n\n if (elements !== previousElements) {\n cleanup(previousElements);\n const entries = elements.map(element => {\n const scrollableElement = getScrollableElement(element);\n\n if (scrollableElement) {\n scrollableElement.addEventListener('scroll', handleScroll, {\n passive: true\n });\n return [scrollableElement, getScrollCoordinates(scrollableElement)];\n }\n\n return null;\n }).filter(entry => entry != null);\n setScrollCoordinates(entries.length ? new Map(entries) : null);\n prevElements.current = elements;\n }\n\n return () => {\n cleanup(elements);\n cleanup(previousElements);\n };\n\n function cleanup(elements) {\n elements.forEach(element => {\n const scrollableElement = getScrollableElement(element);\n scrollableElement == null ? void 0 : scrollableElement.removeEventListener('scroll', handleScroll);\n });\n }\n }, [handleScroll, elements]);\n return useMemo(() => {\n if (elements.length) {\n return scrollCoordinates ? Array.from(scrollCoordinates.values()).reduce((acc, coordinates) => add(acc, coordinates), defaultCoordinates) : getScrollOffsets(elements);\n }\n\n return defaultCoordinates;\n }, [elements, scrollCoordinates]);\n}\n\nfunction useScrollOffsetsDelta(scrollOffsets, dependencies) {\n if (dependencies === void 0) {\n dependencies = [];\n }\n\n const initialScrollOffsets = useRef(null);\n useEffect(() => {\n initialScrollOffsets.current = null;\n }, // eslint-disable-next-line react-hooks/exhaustive-deps\n dependencies);\n useEffect(() => {\n const hasScrollOffsets = scrollOffsets !== defaultCoordinates;\n\n if (hasScrollOffsets && !initialScrollOffsets.current) {\n initialScrollOffsets.current = scrollOffsets;\n }\n\n if (!hasScrollOffsets && initialScrollOffsets.current) {\n initialScrollOffsets.current = null;\n }\n }, [scrollOffsets]);\n return initialScrollOffsets.current ? subtract(scrollOffsets, initialScrollOffsets.current) : defaultCoordinates;\n}\n\nfunction useSensorSetup(sensors) {\n useEffect(() => {\n if (!canUseDOM) {\n return;\n }\n\n const teardownFns = sensors.map(_ref => {\n let {\n sensor\n } = _ref;\n return sensor.setup == null ? void 0 : sensor.setup();\n });\n return () => {\n for (const teardown of teardownFns) {\n teardown == null ? void 0 : teardown();\n }\n };\n }, // TO-DO: Sensors length could theoretically change which would not be a valid dependency\n // eslint-disable-next-line react-hooks/exhaustive-deps\n sensors.map(_ref2 => {\n let {\n sensor\n } = _ref2;\n return sensor;\n }));\n}\n\nfunction useSyntheticListeners(listeners, id) {\n return useMemo(() => {\n return listeners.reduce((acc, _ref) => {\n let {\n eventName,\n handler\n } = _ref;\n\n acc[eventName] = event => {\n handler(event, id);\n };\n\n return acc;\n }, {});\n }, [listeners, id]);\n}\n\nfunction useWindowRect(element) {\n return useMemo(() => element ? getWindowClientRect(element) : null, [element]);\n}\n\nconst defaultValue$2 = [];\nfunction useRects(elements, measure) {\n if (measure === void 0) {\n measure = getClientRect;\n }\n\n const [firstElement] = elements;\n const windowRect = useWindowRect(firstElement ? getWindow(firstElement) : null);\n const [rects, setRects] = useState(defaultValue$2);\n\n function measureRects() {\n setRects(() => {\n if (!elements.length) {\n return defaultValue$2;\n }\n\n return elements.map(element => isDocumentScrollingElement(element) ? windowRect : new Rect(measure(element), element));\n });\n }\n\n const resizeObserver = useResizeObserver({\n callback: measureRects\n });\n useIsomorphicLayoutEffect(() => {\n resizeObserver == null ? void 0 : resizeObserver.disconnect();\n measureRects();\n elements.forEach(element => resizeObserver == null ? void 0 : resizeObserver.observe(element));\n }, [elements]);\n return rects;\n}\n\nfunction getMeasurableNode(node) {\n if (!node) {\n return null;\n }\n\n if (node.children.length > 1) {\n return node;\n }\n\n const firstChild = node.children[0];\n return isHTMLElement(firstChild) ? firstChild : node;\n}\n\nfunction useDragOverlayMeasuring(_ref) {\n let {\n measure\n } = _ref;\n const [rect, setRect] = useState(null);\n const handleResize = useCallback(entries => {\n for (const {\n target\n } of entries) {\n if (isHTMLElement(target)) {\n setRect(rect => {\n const newRect = measure(target);\n return rect ? { ...rect,\n width: newRect.width,\n height: newRect.height\n } : newRect;\n });\n break;\n }\n }\n }, [measure]);\n const resizeObserver = useResizeObserver({\n callback: handleResize\n });\n const handleNodeChange = useCallback(element => {\n const node = getMeasurableNode(element);\n resizeObserver == null ? void 0 : resizeObserver.disconnect();\n\n if (node) {\n resizeObserver == null ? void 0 : resizeObserver.observe(node);\n }\n\n setRect(node ? measure(node) : null);\n }, [measure, resizeObserver]);\n const [nodeRef, setRef] = useNodeRef(handleNodeChange);\n return useMemo(() => ({\n nodeRef,\n rect,\n setRef\n }), [rect, nodeRef, setRef]);\n}\n\nconst defaultSensors = [{\n sensor: PointerSensor,\n options: {}\n}, {\n sensor: KeyboardSensor,\n options: {}\n}];\nconst defaultData = {\n current: {}\n};\nconst defaultMeasuringConfiguration = {\n draggable: {\n measure: getTransformAgnosticClientRect\n },\n droppable: {\n measure: getTransformAgnosticClientRect,\n strategy: MeasuringStrategy.WhileDragging,\n frequency: MeasuringFrequency.Optimized\n },\n dragOverlay: {\n measure: getClientRect\n }\n};\n\nclass DroppableContainersMap extends Map {\n get(id) {\n var _super$get;\n\n return id != null ? (_super$get = super.get(id)) != null ? _super$get : undefined : undefined;\n }\n\n toArray() {\n return Array.from(this.values());\n }\n\n getEnabled() {\n return this.toArray().filter(_ref => {\n let {\n disabled\n } = _ref;\n return !disabled;\n });\n }\n\n getNodeFor(id) {\n var _this$get$node$curren, _this$get;\n\n return (_this$get$node$curren = (_this$get = this.get(id)) == null ? void 0 : _this$get.node.current) != null ? _this$get$node$curren : undefined;\n }\n\n}\n\nconst defaultPublicContext = {\n activatorEvent: null,\n active: null,\n activeNode: null,\n activeNodeRect: null,\n collisions: null,\n containerNodeRect: null,\n draggableNodes: /*#__PURE__*/new Map(),\n droppableRects: /*#__PURE__*/new Map(),\n droppableContainers: /*#__PURE__*/new DroppableContainersMap(),\n over: null,\n dragOverlay: {\n nodeRef: {\n current: null\n },\n rect: null,\n setRef: noop\n },\n scrollableAncestors: [],\n scrollableAncestorRects: [],\n measuringConfiguration: defaultMeasuringConfiguration,\n measureDroppableContainers: noop,\n windowRect: null,\n measuringScheduled: false\n};\nconst defaultInternalContext = {\n activatorEvent: null,\n activators: [],\n active: null,\n activeNodeRect: null,\n ariaDescribedById: {\n draggable: ''\n },\n dispatch: noop,\n draggableNodes: /*#__PURE__*/new Map(),\n over: null,\n measureDroppableContainers: noop\n};\nconst InternalContext = /*#__PURE__*/createContext(defaultInternalContext);\nconst PublicContext = /*#__PURE__*/createContext(defaultPublicContext);\n\nfunction getInitialState() {\n return {\n draggable: {\n active: null,\n initialCoordinates: {\n x: 0,\n y: 0\n },\n nodes: new Map(),\n translate: {\n x: 0,\n y: 0\n }\n },\n droppable: {\n containers: new DroppableContainersMap()\n }\n };\n}\nfunction reducer(state, action) {\n switch (action.type) {\n case Action.DragStart:\n return { ...state,\n draggable: { ...state.draggable,\n initialCoordinates: action.initialCoordinates,\n active: action.active\n }\n };\n\n case Action.DragMove:\n if (state.draggable.active == null) {\n return state;\n }\n\n return { ...state,\n draggable: { ...state.draggable,\n translate: {\n x: action.coordinates.x - state.draggable.initialCoordinates.x,\n y: action.coordinates.y - state.draggable.initialCoordinates.y\n }\n }\n };\n\n case Action.DragEnd:\n case Action.DragCancel:\n return { ...state,\n draggable: { ...state.draggable,\n active: null,\n initialCoordinates: {\n x: 0,\n y: 0\n },\n translate: {\n x: 0,\n y: 0\n }\n }\n };\n\n case Action.RegisterDroppable:\n {\n const {\n element\n } = action;\n const {\n id\n } = element;\n const containers = new DroppableContainersMap(state.droppable.containers);\n containers.set(id, element);\n return { ...state,\n droppable: { ...state.droppable,\n containers\n }\n };\n }\n\n case Action.SetDroppableDisabled:\n {\n const {\n id,\n key,\n disabled\n } = action;\n const element = state.droppable.containers.get(id);\n\n if (!element || key !== element.key) {\n return state;\n }\n\n const containers = new DroppableContainersMap(state.droppable.containers);\n containers.set(id, { ...element,\n disabled\n });\n return { ...state,\n droppable: { ...state.droppable,\n containers\n }\n };\n }\n\n case Action.UnregisterDroppable:\n {\n const {\n id,\n key\n } = action;\n const element = state.droppable.containers.get(id);\n\n if (!element || key !== element.key) {\n return state;\n }\n\n const containers = new DroppableContainersMap(state.droppable.containers);\n containers.delete(id);\n return { ...state,\n droppable: { ...state.droppable,\n containers\n }\n };\n }\n\n default:\n {\n return state;\n }\n }\n}\n\nfunction RestoreFocus(_ref) {\n let {\n disabled\n } = _ref;\n const {\n active,\n activatorEvent,\n draggableNodes\n } = useContext(InternalContext);\n const previousActivatorEvent = usePrevious(activatorEvent);\n const previousActiveId = usePrevious(active == null ? void 0 : active.id); // Restore keyboard focus on the activator node\n\n useEffect(() => {\n if (disabled) {\n return;\n }\n\n if (!activatorEvent && previousActivatorEvent && previousActiveId != null) {\n if (!isKeyboardEvent(previousActivatorEvent)) {\n return;\n }\n\n if (document.activeElement === previousActivatorEvent.target) {\n // No need to restore focus\n return;\n }\n\n const draggableNode = draggableNodes.get(previousActiveId);\n\n if (!draggableNode) {\n return;\n }\n\n const {\n activatorNode,\n node\n } = draggableNode;\n\n if (!activatorNode.current && !node.current) {\n return;\n }\n\n requestAnimationFrame(() => {\n for (const element of [activatorNode.current, node.current]) {\n if (!element) {\n continue;\n }\n\n const focusableNode = findFirstFocusableNode(element);\n\n if (focusableNode) {\n focusableNode.focus();\n break;\n }\n }\n });\n }\n }, [activatorEvent, disabled, draggableNodes, previousActiveId, previousActivatorEvent]);\n return null;\n}\n\nfunction applyModifiers(modifiers, _ref) {\n let {\n transform,\n ...args\n } = _ref;\n return modifiers != null && modifiers.length ? modifiers.reduce((accumulator, modifier) => {\n return modifier({\n transform: accumulator,\n ...args\n });\n }, transform) : transform;\n}\n\nfunction useMeasuringConfiguration(config) {\n return useMemo(() => ({\n draggable: { ...defaultMeasuringConfiguration.draggable,\n ...(config == null ? void 0 : config.draggable)\n },\n droppable: { ...defaultMeasuringConfiguration.droppable,\n ...(config == null ? void 0 : config.droppable)\n },\n dragOverlay: { ...defaultMeasuringConfiguration.dragOverlay,\n ...(config == null ? void 0 : config.dragOverlay)\n }\n }), // eslint-disable-next-line react-hooks/exhaustive-deps\n [config == null ? void 0 : config.draggable, config == null ? void 0 : config.droppable, config == null ? void 0 : config.dragOverlay]);\n}\n\nfunction useLayoutShiftScrollCompensation(_ref) {\n let {\n activeNode,\n measure,\n initialRect,\n config = true\n } = _ref;\n const initialized = useRef(false);\n const {\n x,\n y\n } = typeof config === 'boolean' ? {\n x: config,\n y: config\n } : config;\n useIsomorphicLayoutEffect(() => {\n const disabled = !x && !y;\n\n if (disabled || !activeNode) {\n initialized.current = false;\n return;\n }\n\n if (initialized.current || !initialRect) {\n // Return early if layout shift scroll compensation was already attempted\n // or if there is no initialRect to compare to.\n return;\n } // Get the most up to date node ref for the active draggable\n\n\n const node = activeNode == null ? void 0 : activeNode.node.current;\n\n if (!node || node.isConnected === false) {\n // Return early if there is no attached node ref or if the node is\n // disconnected from the document.\n return;\n }\n\n const rect = measure(node);\n const rectDelta = getRectDelta(rect, initialRect);\n\n if (!x) {\n rectDelta.x = 0;\n }\n\n if (!y) {\n rectDelta.y = 0;\n } // Only perform layout shift scroll compensation once\n\n\n initialized.current = true;\n\n if (Math.abs(rectDelta.x) > 0 || Math.abs(rectDelta.y) > 0) {\n const firstScrollableAncestor = getFirstScrollableAncestor(node);\n\n if (firstScrollableAncestor) {\n firstScrollableAncestor.scrollBy({\n top: rectDelta.y,\n left: rectDelta.x\n });\n }\n }\n }, [activeNode, x, y, initialRect, measure]);\n}\n\nconst ActiveDraggableContext = /*#__PURE__*/createContext({ ...defaultCoordinates,\n scaleX: 1,\n scaleY: 1\n});\nvar Status;\n\n(function (Status) {\n Status[Status[\"Uninitialized\"] = 0] = \"Uninitialized\";\n Status[Status[\"Initializing\"] = 1] = \"Initializing\";\n Status[Status[\"Initialized\"] = 2] = \"Initialized\";\n})(Status || (Status = {}));\n\nconst DndContext = /*#__PURE__*/memo(function DndContext(_ref) {\n var _sensorContext$curren, _dragOverlay$nodeRef$, _dragOverlay$rect, _over$rect;\n\n let {\n id,\n accessibility,\n autoScroll = true,\n children,\n sensors = defaultSensors,\n collisionDetection = rectIntersection,\n measuring,\n modifiers,\n ...props\n } = _ref;\n const store = useReducer(reducer, undefined, getInitialState);\n const [state, dispatch] = store;\n const [dispatchMonitorEvent, registerMonitorListener] = useDndMonitorProvider();\n const [status, setStatus] = useState(Status.Uninitialized);\n const isInitialized = status === Status.Initialized;\n const {\n draggable: {\n active: activeId,\n nodes: draggableNodes,\n translate\n },\n droppable: {\n containers: droppableContainers\n }\n } = state;\n const node = activeId != null ? draggableNodes.get(activeId) : null;\n const activeRects = useRef({\n initial: null,\n translated: null\n });\n const active = useMemo(() => {\n var _node$data;\n\n return activeId != null ? {\n id: activeId,\n // It's possible for the active node to unmount while dragging\n data: (_node$data = node == null ? void 0 : node.data) != null ? _node$data : defaultData,\n rect: activeRects\n } : null;\n }, [activeId, node]);\n const activeRef = useRef(null);\n const [activeSensor, setActiveSensor] = useState(null);\n const [activatorEvent, setActivatorEvent] = useState(null);\n const latestProps = useLatestValue(props, Object.values(props));\n const draggableDescribedById = useUniqueId(\"DndDescribedBy\", id);\n const enabledDroppableContainers = useMemo(() => droppableContainers.getEnabled(), [droppableContainers]);\n const measuringConfiguration = useMeasuringConfiguration(measuring);\n const {\n droppableRects,\n measureDroppableContainers,\n measuringScheduled\n } = useDroppableMeasuring(enabledDroppableContainers, {\n dragging: isInitialized,\n dependencies: [translate.x, translate.y],\n config: measuringConfiguration.droppable\n });\n const activeNode = useCachedNode(draggableNodes, activeId);\n const activationCoordinates = useMemo(() => activatorEvent ? getEventCoordinates(activatorEvent) : null, [activatorEvent]);\n const autoScrollOptions = getAutoScrollerOptions();\n const initialActiveNodeRect = useInitialRect(activeNode, measuringConfiguration.draggable.measure);\n useLayoutShiftScrollCompensation({\n activeNode: activeId != null ? draggableNodes.get(activeId) : null,\n config: autoScrollOptions.layoutShiftCompensation,\n initialRect: initialActiveNodeRect,\n measure: measuringConfiguration.draggable.measure\n });\n const activeNodeRect = useRect(activeNode, measuringConfiguration.draggable.measure, initialActiveNodeRect);\n const containerNodeRect = useRect(activeNode ? activeNode.parentElement : null);\n const sensorContext = useRef({\n activatorEvent: null,\n active: null,\n activeNode,\n collisionRect: null,\n collisions: null,\n droppableRects,\n draggableNodes,\n draggingNode: null,\n draggingNodeRect: null,\n droppableContainers,\n over: null,\n scrollableAncestors: [],\n scrollAdjustedTranslate: null\n });\n const overNode = droppableContainers.getNodeFor((_sensorContext$curren = sensorContext.current.over) == null ? void 0 : _sensorContext$curren.id);\n const dragOverlay = useDragOverlayMeasuring({\n measure: measuringConfiguration.dragOverlay.measure\n }); // Use the rect of the drag overlay if it is mounted\n\n const draggingNode = (_dragOverlay$nodeRef$ = dragOverlay.nodeRef.current) != null ? _dragOverlay$nodeRef$ : activeNode;\n const draggingNodeRect = isInitialized ? (_dragOverlay$rect = dragOverlay.rect) != null ? _dragOverlay$rect : activeNodeRect : null;\n const usesDragOverlay = Boolean(dragOverlay.nodeRef.current && dragOverlay.rect); // The delta between the previous and new position of the draggable node\n // is only relevant when there is no drag overlay\n\n const nodeRectDelta = useRectDelta(usesDragOverlay ? null : activeNodeRect); // Get the window rect of the dragging node\n\n const windowRect = useWindowRect(draggingNode ? getWindow(draggingNode) : null); // Get scrollable ancestors of the dragging node\n\n const scrollableAncestors = useScrollableAncestors(isInitialized ? overNode != null ? overNode : activeNode : null);\n const scrollableAncestorRects = useRects(scrollableAncestors); // Apply modifiers\n\n const modifiedTranslate = applyModifiers(modifiers, {\n transform: {\n x: translate.x - nodeRectDelta.x,\n y: translate.y - nodeRectDelta.y,\n scaleX: 1,\n scaleY: 1\n },\n activatorEvent,\n active,\n activeNodeRect,\n containerNodeRect,\n draggingNodeRect,\n over: sensorContext.current.over,\n overlayNodeRect: dragOverlay.rect,\n scrollableAncestors,\n scrollableAncestorRects,\n windowRect\n });\n const pointerCoordinates = activationCoordinates ? add(activationCoordinates, translate) : null;\n const scrollOffsets = useScrollOffsets(scrollableAncestors); // Represents the scroll delta since dragging was initiated\n\n const scrollAdjustment = useScrollOffsetsDelta(scrollOffsets); // Represents the scroll delta since the last time the active node rect was measured\n\n const activeNodeScrollDelta = useScrollOffsetsDelta(scrollOffsets, [activeNodeRect]);\n const scrollAdjustedTranslate = add(modifiedTranslate, scrollAdjustment);\n const collisionRect = draggingNodeRect ? getAdjustedRect(draggingNodeRect, modifiedTranslate) : null;\n const collisions = active && collisionRect ? collisionDetection({\n active,\n collisionRect,\n droppableRects,\n droppableContainers: enabledDroppableContainers,\n pointerCoordinates\n }) : null;\n const overId = getFirstCollision(collisions, 'id');\n const [over, setOver] = useState(null); // When there is no drag overlay used, we need to account for the\n // window scroll delta\n\n const appliedTranslate = usesDragOverlay ? modifiedTranslate : add(modifiedTranslate, activeNodeScrollDelta);\n const transform = adjustScale(appliedTranslate, (_over$rect = over == null ? void 0 : over.rect) != null ? _over$rect : null, activeNodeRect);\n const activeSensorRef = useRef(null);\n const instantiateSensor = useCallback((event, _ref2) => {\n let {\n sensor: Sensor,\n options\n } = _ref2;\n\n if (activeRef.current == null) {\n return;\n }\n\n const activeNode = draggableNodes.get(activeRef.current);\n\n if (!activeNode) {\n return;\n }\n\n const activatorEvent = event.nativeEvent;\n const sensorInstance = new Sensor({\n active: activeRef.current,\n activeNode,\n event: activatorEvent,\n options,\n // Sensors need to be instantiated with refs for arguments that change over time\n // otherwise they are frozen in time with the stale arguments\n context: sensorContext,\n\n onAbort(id) {\n const draggableNode = draggableNodes.get(id);\n\n if (!draggableNode) {\n return;\n }\n\n const {\n onDragAbort\n } = latestProps.current;\n const event = {\n id\n };\n onDragAbort == null ? void 0 : onDragAbort(event);\n dispatchMonitorEvent({\n type: 'onDragAbort',\n event\n });\n },\n\n onPending(id, constraint, initialCoordinates, offset) {\n const draggableNode = draggableNodes.get(id);\n\n if (!draggableNode) {\n return;\n }\n\n const {\n onDragPending\n } = latestProps.current;\n const event = {\n id,\n constraint,\n initialCoordinates,\n offset\n };\n onDragPending == null ? void 0 : onDragPending(event);\n dispatchMonitorEvent({\n type: 'onDragPending',\n event\n });\n },\n\n onStart(initialCoordinates) {\n const id = activeRef.current;\n\n if (id == null) {\n return;\n }\n\n const draggableNode = draggableNodes.get(id);\n\n if (!draggableNode) {\n return;\n }\n\n const {\n onDragStart\n } = latestProps.current;\n const event = {\n activatorEvent,\n active: {\n id,\n data: draggableNode.data,\n rect: activeRects\n }\n };\n unstable_batchedUpdates(() => {\n onDragStart == null ? void 0 : onDragStart(event);\n setStatus(Status.Initializing);\n dispatch({\n type: Action.DragStart,\n initialCoordinates,\n active: id\n });\n dispatchMonitorEvent({\n type: 'onDragStart',\n event\n });\n setActiveSensor(activeSensorRef.current);\n setActivatorEvent(activatorEvent);\n });\n },\n\n onMove(coordinates) {\n dispatch({\n type: Action.DragMove,\n coordinates\n });\n },\n\n onEnd: createHandler(Action.DragEnd),\n onCancel: createHandler(Action.DragCancel)\n });\n activeSensorRef.current = sensorInstance;\n\n function createHandler(type) {\n return async function handler() {\n const {\n active,\n collisions,\n over,\n scrollAdjustedTranslate\n } = sensorContext.current;\n let event = null;\n\n if (active && scrollAdjustedTranslate) {\n const {\n cancelDrop\n } = latestProps.current;\n event = {\n activatorEvent,\n active: active,\n collisions,\n delta: scrollAdjustedTranslate,\n over\n };\n\n if (type === Action.DragEnd && typeof cancelDrop === 'function') {\n const shouldCancel = await Promise.resolve(cancelDrop(event));\n\n if (shouldCancel) {\n type = Action.DragCancel;\n }\n }\n }\n\n activeRef.current = null;\n unstable_batchedUpdates(() => {\n dispatch({\n type\n });\n setStatus(Status.Uninitialized);\n setOver(null);\n setActiveSensor(null);\n setActivatorEvent(null);\n activeSensorRef.current = null;\n const eventName = type === Action.DragEnd ? 'onDragEnd' : 'onDragCancel';\n\n if (event) {\n const handler = latestProps.current[eventName];\n handler == null ? void 0 : handler(event);\n dispatchMonitorEvent({\n type: eventName,\n event\n });\n }\n });\n };\n }\n }, // eslint-disable-next-line react-hooks/exhaustive-deps\n [draggableNodes]);\n const bindActivatorToSensorInstantiator = useCallback((handler, sensor) => {\n return (event, active) => {\n const nativeEvent = event.nativeEvent;\n const activeDraggableNode = draggableNodes.get(active);\n\n if ( // Another sensor is already instantiating\n activeRef.current !== null || // No active draggable\n !activeDraggableNode || // Event has already been captured\n nativeEvent.dndKit || nativeEvent.defaultPrevented) {\n return;\n }\n\n const activationContext = {\n active: activeDraggableNode\n };\n const shouldActivate = handler(event, sensor.options, activationContext);\n\n if (shouldActivate === true) {\n nativeEvent.dndKit = {\n capturedBy: sensor.sensor\n };\n activeRef.current = active;\n instantiateSensor(event, sensor);\n }\n };\n }, [draggableNodes, instantiateSensor]);\n const activators = useCombineActivators(sensors, bindActivatorToSensorInstantiator);\n useSensorSetup(sensors);\n useIsomorphicLayoutEffect(() => {\n if (activeNodeRect && status === Status.Initializing) {\n setStatus(Status.Initialized);\n }\n }, [activeNodeRect, status]);\n useEffect(() => {\n const {\n onDragMove\n } = latestProps.current;\n const {\n active,\n activatorEvent,\n collisions,\n over\n } = sensorContext.current;\n\n if (!active || !activatorEvent) {\n return;\n }\n\n const event = {\n active,\n activatorEvent,\n collisions,\n delta: {\n x: scrollAdjustedTranslate.x,\n y: scrollAdjustedTranslate.y\n },\n over\n };\n unstable_batchedUpdates(() => {\n onDragMove == null ? void 0 : onDragMove(event);\n dispatchMonitorEvent({\n type: 'onDragMove',\n event\n });\n });\n }, // eslint-disable-next-line react-hooks/exhaustive-deps\n [scrollAdjustedTranslate.x, scrollAdjustedTranslate.y]);\n useEffect(() => {\n const {\n active,\n activatorEvent,\n collisions,\n droppableContainers,\n scrollAdjustedTranslate\n } = sensorContext.current;\n\n if (!active || activeRef.current == null || !activatorEvent || !scrollAdjustedTranslate) {\n return;\n }\n\n const {\n onDragOver\n } = latestProps.current;\n const overContainer = droppableContainers.get(overId);\n const over = overContainer && overContainer.rect.current ? {\n id: overContainer.id,\n rect: overContainer.rect.current,\n data: overContainer.data,\n disabled: overContainer.disabled\n } : null;\n const event = {\n active,\n activatorEvent,\n collisions,\n delta: {\n x: scrollAdjustedTranslate.x,\n y: scrollAdjustedTranslate.y\n },\n over\n };\n unstable_batchedUpdates(() => {\n setOver(over);\n onDragOver == null ? void 0 : onDragOver(event);\n dispatchMonitorEvent({\n type: 'onDragOver',\n event\n });\n });\n }, // eslint-disable-next-line react-hooks/exhaustive-deps\n [overId]);\n useIsomorphicLayoutEffect(() => {\n sensorContext.current = {\n activatorEvent,\n active,\n activeNode,\n collisionRect,\n collisions,\n droppableRects,\n draggableNodes,\n draggingNode,\n draggingNodeRect,\n droppableContainers,\n over,\n scrollableAncestors,\n scrollAdjustedTranslate\n };\n activeRects.current = {\n initial: draggingNodeRect,\n translated: collisionRect\n };\n }, [active, activeNode, collisions, collisionRect, draggableNodes, draggingNode, draggingNodeRect, droppableRects, droppableContainers, over, scrollableAncestors, scrollAdjustedTranslate]);\n useAutoScroller({ ...autoScrollOptions,\n delta: translate,\n draggingRect: collisionRect,\n pointerCoordinates,\n scrollableAncestors,\n scrollableAncestorRects\n });\n const publicContext = useMemo(() => {\n const context = {\n active,\n activeNode,\n activeNodeRect,\n activatorEvent,\n collisions,\n containerNodeRect,\n dragOverlay,\n draggableNodes,\n droppableContainers,\n droppableRects,\n over,\n measureDroppableContainers,\n scrollableAncestors,\n scrollableAncestorRects,\n measuringConfiguration,\n measuringScheduled,\n windowRect\n };\n return context;\n }, [active, activeNode, activeNodeRect, activatorEvent, collisions, containerNodeRect, dragOverlay, draggableNodes, droppableContainers, droppableRects, over, measureDroppableContainers, scrollableAncestors, scrollableAncestorRects, measuringConfiguration, measuringScheduled, windowRect]);\n const internalContext = useMemo(() => {\n const context = {\n activatorEvent,\n activators,\n active,\n activeNodeRect,\n ariaDescribedById: {\n draggable: draggableDescribedById\n },\n dispatch,\n draggableNodes,\n over,\n measureDroppableContainers\n };\n return context;\n }, [activatorEvent, activators, active, activeNodeRect, dispatch, draggableDescribedById, draggableNodes, over, measureDroppableContainers]);\n return React.createElement(DndMonitorContext.Provider, {\n value: registerMonitorListener\n }, React.createElement(InternalContext.Provider, {\n value: internalContext\n }, React.createElement(PublicContext.Provider, {\n value: publicContext\n }, React.createElement(ActiveDraggableContext.Provider, {\n value: transform\n }, children)), React.createElement(RestoreFocus, {\n disabled: (accessibility == null ? void 0 : accessibility.restoreFocus) === false\n })), React.createElement(Accessibility, { ...accessibility,\n hiddenTextDescribedById: draggableDescribedById\n }));\n\n function getAutoScrollerOptions() {\n const activeSensorDisablesAutoscroll = (activeSensor == null ? void 0 : activeSensor.autoScrollEnabled) === false;\n const autoScrollGloballyDisabled = typeof autoScroll === 'object' ? autoScroll.enabled === false : autoScroll === false;\n const enabled = isInitialized && !activeSensorDisablesAutoscroll && !autoScrollGloballyDisabled;\n\n if (typeof autoScroll === 'object') {\n return { ...autoScroll,\n enabled\n };\n }\n\n return {\n enabled\n };\n }\n});\n\nconst NullContext = /*#__PURE__*/createContext(null);\nconst defaultRole = 'button';\nconst ID_PREFIX = 'Draggable';\nfunction useDraggable(_ref) {\n let {\n id,\n data,\n disabled = false,\n attributes\n } = _ref;\n const key = useUniqueId(ID_PREFIX);\n const {\n activators,\n activatorEvent,\n active,\n activeNodeRect,\n ariaDescribedById,\n draggableNodes,\n over\n } = useContext(InternalContext);\n const {\n role = defaultRole,\n roleDescription = 'draggable',\n tabIndex = 0\n } = attributes != null ? attributes : {};\n const isDragging = (active == null ? void 0 : active.id) === id;\n const transform = useContext(isDragging ? ActiveDraggableContext : NullContext);\n const [node, setNodeRef] = useNodeRef();\n const [activatorNode, setActivatorNodeRef] = useNodeRef();\n const listeners = useSyntheticListeners(activators, id);\n const dataRef = useLatestValue(data);\n useIsomorphicLayoutEffect(() => {\n draggableNodes.set(id, {\n id,\n key,\n node,\n activatorNode,\n data: dataRef\n });\n return () => {\n const node = draggableNodes.get(id);\n\n if (node && node.key === key) {\n draggableNodes.delete(id);\n }\n };\n }, // eslint-disable-next-line react-hooks/exhaustive-deps\n [draggableNodes, id]);\n const memoizedAttributes = useMemo(() => ({\n role,\n tabIndex,\n 'aria-disabled': disabled,\n 'aria-pressed': isDragging && role === defaultRole ? true : undefined,\n 'aria-roledescription': roleDescription,\n 'aria-describedby': ariaDescribedById.draggable\n }), [disabled, role, tabIndex, isDragging, roleDescription, ariaDescribedById.draggable]);\n return {\n active,\n activatorEvent,\n activeNodeRect,\n attributes: memoizedAttributes,\n isDragging,\n listeners: disabled ? undefined : listeners,\n node,\n over,\n setNodeRef,\n setActivatorNodeRef,\n transform\n };\n}\n\nfunction useDndContext() {\n return useContext(PublicContext);\n}\n\nconst ID_PREFIX$1 = 'Droppable';\nconst defaultResizeObserverConfig = {\n timeout: 25\n};\nfunction useDroppable(_ref) {\n let {\n data,\n disabled = false,\n id,\n resizeObserverConfig\n } = _ref;\n const key = useUniqueId(ID_PREFIX$1);\n const {\n active,\n dispatch,\n over,\n measureDroppableContainers\n } = useContext(InternalContext);\n const previous = useRef({\n disabled\n });\n const resizeObserverConnected = useRef(false);\n const rect = useRef(null);\n const callbackId = useRef(null);\n const {\n disabled: resizeObserverDisabled,\n updateMeasurementsFor,\n timeout: resizeObserverTimeout\n } = { ...defaultResizeObserverConfig,\n ...resizeObserverConfig\n };\n const ids = useLatestValue(updateMeasurementsFor != null ? updateMeasurementsFor : id);\n const handleResize = useCallback(() => {\n if (!resizeObserverConnected.current) {\n // ResizeObserver invokes the `handleResize` callback as soon as `observe` is called,\n // assuming the element is rendered and displayed.\n resizeObserverConnected.current = true;\n return;\n }\n\n if (callbackId.current != null) {\n clearTimeout(callbackId.current);\n }\n\n callbackId.current = setTimeout(() => {\n measureDroppableContainers(Array.isArray(ids.current) ? ids.current : [ids.current]);\n callbackId.current = null;\n }, resizeObserverTimeout);\n }, //eslint-disable-next-line react-hooks/exhaustive-deps\n [resizeObserverTimeout]);\n const resizeObserver = useResizeObserver({\n callback: handleResize,\n disabled: resizeObserverDisabled || !active\n });\n const handleNodeChange = useCallback((newElement, previousElement) => {\n if (!resizeObserver) {\n return;\n }\n\n if (previousElement) {\n resizeObserver.unobserve(previousElement);\n resizeObserverConnected.current = false;\n }\n\n if (newElement) {\n resizeObserver.observe(newElement);\n }\n }, [resizeObserver]);\n const [nodeRef, setNodeRef] = useNodeRef(handleNodeChange);\n const dataRef = useLatestValue(data);\n useEffect(() => {\n if (!resizeObserver || !nodeRef.current) {\n return;\n }\n\n resizeObserver.disconnect();\n resizeObserverConnected.current = false;\n resizeObserver.observe(nodeRef.current);\n }, [nodeRef, resizeObserver]);\n useEffect(() => {\n dispatch({\n type: Action.RegisterDroppable,\n element: {\n id,\n key,\n disabled,\n node: nodeRef,\n rect,\n data: dataRef\n }\n });\n return () => dispatch({\n type: Action.UnregisterDroppable,\n key,\n id\n });\n }, // eslint-disable-next-line react-hooks/exhaustive-deps\n [id]);\n useEffect(() => {\n if (disabled !== previous.current.disabled) {\n dispatch({\n type: Action.SetDroppableDisabled,\n id,\n key,\n disabled\n });\n previous.current.disabled = disabled;\n }\n }, [id, key, disabled, dispatch]);\n return {\n active,\n rect,\n isOver: (over == null ? void 0 : over.id) === id,\n node: nodeRef,\n over,\n setNodeRef\n };\n}\n\nfunction AnimationManager(_ref) {\n let {\n animation,\n children\n } = _ref;\n const [clonedChildren, setClonedChildren] = useState(null);\n const [element, setElement] = useState(null);\n const previousChildren = usePrevious(children);\n\n if (!children && !clonedChildren && previousChildren) {\n setClonedChildren(previousChildren);\n }\n\n useIsomorphicLayoutEffect(() => {\n if (!element) {\n return;\n }\n\n const key = clonedChildren == null ? void 0 : clonedChildren.key;\n const id = clonedChildren == null ? void 0 : clonedChildren.props.id;\n\n if (key == null || id == null) {\n setClonedChildren(null);\n return;\n }\n\n Promise.resolve(animation(id, element)).then(() => {\n setClonedChildren(null);\n });\n }, [animation, clonedChildren, element]);\n return React.createElement(React.Fragment, null, children, clonedChildren ? cloneElement(clonedChildren, {\n ref: setElement\n }) : null);\n}\n\nconst defaultTransform = {\n x: 0,\n y: 0,\n scaleX: 1,\n scaleY: 1\n};\nfunction NullifiedContextProvider(_ref) {\n let {\n children\n } = _ref;\n return React.createElement(InternalContext.Provider, {\n value: defaultInternalContext\n }, React.createElement(ActiveDraggableContext.Provider, {\n value: defaultTransform\n }, children));\n}\n\nconst baseStyles = {\n position: 'fixed',\n touchAction: 'none'\n};\n\nconst defaultTransition = activatorEvent => {\n const isKeyboardActivator = isKeyboardEvent(activatorEvent);\n return isKeyboardActivator ? 'transform 250ms ease' : undefined;\n};\n\nconst PositionedOverlay = /*#__PURE__*/forwardRef((_ref, ref) => {\n let {\n as,\n activatorEvent,\n adjustScale,\n children,\n className,\n rect,\n style,\n transform,\n transition = defaultTransition\n } = _ref;\n\n if (!rect) {\n return null;\n }\n\n const scaleAdjustedTransform = adjustScale ? transform : { ...transform,\n scaleX: 1,\n scaleY: 1\n };\n const styles = { ...baseStyles,\n width: rect.width,\n height: rect.height,\n top: rect.top,\n left: rect.left,\n transform: CSS.Transform.toString(scaleAdjustedTransform),\n transformOrigin: adjustScale && activatorEvent ? getRelativeTransformOrigin(activatorEvent, rect) : undefined,\n transition: typeof transition === 'function' ? transition(activatorEvent) : transition,\n ...style\n };\n return React.createElement(as, {\n className,\n style: styles,\n ref\n }, children);\n});\n\nconst defaultDropAnimationSideEffects = options => _ref => {\n let {\n active,\n dragOverlay\n } = _ref;\n const originalStyles = {};\n const {\n styles,\n className\n } = options;\n\n if (styles != null && styles.active) {\n for (const [key, value] of Object.entries(styles.active)) {\n if (value === undefined) {\n continue;\n }\n\n originalStyles[key] = active.node.style.getPropertyValue(key);\n active.node.style.setProperty(key, value);\n }\n }\n\n if (styles != null && styles.dragOverlay) {\n for (const [key, value] of Object.entries(styles.dragOverlay)) {\n if (value === undefined) {\n continue;\n }\n\n dragOverlay.node.style.setProperty(key, value);\n }\n }\n\n if (className != null && className.active) {\n active.node.classList.add(className.active);\n }\n\n if (className != null && className.dragOverlay) {\n dragOverlay.node.classList.add(className.dragOverlay);\n }\n\n return function cleanup() {\n for (const [key, value] of Object.entries(originalStyles)) {\n active.node.style.setProperty(key, value);\n }\n\n if (className != null && className.active) {\n active.node.classList.remove(className.active);\n }\n };\n};\n\nconst defaultKeyframeResolver = _ref2 => {\n let {\n transform: {\n initial,\n final\n }\n } = _ref2;\n return [{\n transform: CSS.Transform.toString(initial)\n }, {\n transform: CSS.Transform.toString(final)\n }];\n};\n\nconst defaultDropAnimationConfiguration = {\n duration: 250,\n easing: 'ease',\n keyframes: defaultKeyframeResolver,\n sideEffects: /*#__PURE__*/defaultDropAnimationSideEffects({\n styles: {\n active: {\n opacity: '0'\n }\n }\n })\n};\nfunction useDropAnimation(_ref3) {\n let {\n config,\n draggableNodes,\n droppableContainers,\n measuringConfiguration\n } = _ref3;\n return useEvent((id, node) => {\n if (config === null) {\n return;\n }\n\n const activeDraggable = draggableNodes.get(id);\n\n if (!activeDraggable) {\n return;\n }\n\n const activeNode = activeDraggable.node.current;\n\n if (!activeNode) {\n return;\n }\n\n const measurableNode = getMeasurableNode(node);\n\n if (!measurableNode) {\n return;\n }\n\n const {\n transform\n } = getWindow(node).getComputedStyle(node);\n const parsedTransform = parseTransform(transform);\n\n if (!parsedTransform) {\n return;\n }\n\n const animation = typeof config === 'function' ? config : createDefaultDropAnimation(config);\n scrollIntoViewIfNeeded(activeNode, measuringConfiguration.draggable.measure);\n return animation({\n active: {\n id,\n data: activeDraggable.data,\n node: activeNode,\n rect: measuringConfiguration.draggable.measure(activeNode)\n },\n draggableNodes,\n dragOverlay: {\n node,\n rect: measuringConfiguration.dragOverlay.measure(measurableNode)\n },\n droppableContainers,\n measuringConfiguration,\n transform: parsedTransform\n });\n });\n}\n\nfunction createDefaultDropAnimation(options) {\n const {\n duration,\n easing,\n sideEffects,\n keyframes\n } = { ...defaultDropAnimationConfiguration,\n ...options\n };\n return _ref4 => {\n let {\n active,\n dragOverlay,\n transform,\n ...rest\n } = _ref4;\n\n if (!duration) {\n // Do not animate if animation duration is zero.\n return;\n }\n\n const delta = {\n x: dragOverlay.rect.left - active.rect.left,\n y: dragOverlay.rect.top - active.rect.top\n };\n const scale = {\n scaleX: transform.scaleX !== 1 ? active.rect.width * transform.scaleX / dragOverlay.rect.width : 1,\n scaleY: transform.scaleY !== 1 ? active.rect.height * transform.scaleY / dragOverlay.rect.height : 1\n };\n const finalTransform = {\n x: transform.x - delta.x,\n y: transform.y - delta.y,\n ...scale\n };\n const animationKeyframes = keyframes({ ...rest,\n active,\n dragOverlay,\n transform: {\n initial: transform,\n final: finalTransform\n }\n });\n const [firstKeyframe] = animationKeyframes;\n const lastKeyframe = animationKeyframes[animationKeyframes.length - 1];\n\n if (JSON.stringify(firstKeyframe) === JSON.stringify(lastKeyframe)) {\n // The start and end keyframes are the same, infer that there is no animation needed.\n return;\n }\n\n const cleanup = sideEffects == null ? void 0 : sideEffects({\n active,\n dragOverlay,\n ...rest\n });\n const animation = dragOverlay.node.animate(animationKeyframes, {\n duration,\n easing,\n fill: 'forwards'\n });\n return new Promise(resolve => {\n animation.onfinish = () => {\n cleanup == null ? void 0 : cleanup();\n resolve();\n };\n });\n };\n}\n\nlet key = 0;\nfunction useKey(id) {\n return useMemo(() => {\n if (id == null) {\n return;\n }\n\n key++;\n return key;\n }, [id]);\n}\n\nconst DragOverlay = /*#__PURE__*/React.memo(_ref => {\n let {\n adjustScale = false,\n children,\n dropAnimation: dropAnimationConfig,\n style,\n transition,\n modifiers,\n wrapperElement = 'div',\n className,\n zIndex = 999\n } = _ref;\n const {\n activatorEvent,\n active,\n activeNodeRect,\n containerNodeRect,\n draggableNodes,\n droppableContainers,\n dragOverlay,\n over,\n measuringConfiguration,\n scrollableAncestors,\n scrollableAncestorRects,\n windowRect\n } = useDndContext();\n const transform = useContext(ActiveDraggableContext);\n const key = useKey(active == null ? void 0 : active.id);\n const modifiedTransform = applyModifiers(modifiers, {\n activatorEvent,\n active,\n activeNodeRect,\n containerNodeRect,\n draggingNodeRect: dragOverlay.rect,\n over,\n overlayNodeRect: dragOverlay.rect,\n scrollableAncestors,\n scrollableAncestorRects,\n transform,\n windowRect\n });\n const initialRect = useInitialValue(activeNodeRect);\n const dropAnimation = useDropAnimation({\n config: dropAnimationConfig,\n draggableNodes,\n droppableContainers,\n measuringConfiguration\n }); // We need to wait for the active node to be measured before connecting the drag overlay ref\n // otherwise collisions can be computed against a mispositioned drag overlay\n\n const ref = initialRect ? dragOverlay.setRef : undefined;\n return React.createElement(NullifiedContextProvider, null, React.createElement(AnimationManager, {\n animation: dropAnimation\n }, active && key ? React.createElement(PositionedOverlay, {\n key: key,\n id: active.id,\n ref: ref,\n as: wrapperElement,\n activatorEvent: activatorEvent,\n adjustScale: adjustScale,\n className: className,\n transition: transition,\n rect: initialRect,\n style: {\n zIndex,\n ...style\n },\n transform: modifiedTransform\n }, children) : null));\n});\n\nexport { AutoScrollActivator, DndContext, DragOverlay, KeyboardCode, KeyboardSensor, MeasuringFrequency, MeasuringStrategy, MouseSensor, PointerSensor, TouchSensor, TraversalOrder, applyModifiers, closestCenter, closestCorners, defaultAnnouncements, defaultCoordinates, defaultDropAnimationConfiguration as defaultDropAnimation, defaultDropAnimationSideEffects, defaultKeyboardCoordinateGetter, defaultScreenReaderInstructions, getClientRect, getFirstCollision, getScrollableAncestors, pointerWithin, rectIntersection, useDndContext, useDndMonitor, useDraggable, useDroppable, useSensor, useSensors };\n//# sourceMappingURL=core.esm.js.map\n","import * as a from \"react\";\nconst e = /* @__PURE__ */ new Map([\n [\n \"bold\",\n /* @__PURE__ */ a.createElement(a.Fragment, null, /* @__PURE__ */ a.createElement(\"path\", { d: \"M157.27,21.22a12,12,0,0,0-12.64,1.31L75.88,76H32A20,20,0,0,0,12,96v64a20,20,0,0,0,20,20H75.88l68.75,53.47A12,12,0,0,0,164,224V32A12,12,0,0,0,157.27,21.22ZM36,100H68v56H36Zm104,99.46L92,162.13V93.87l48-37.33ZM212,128a44,44,0,0,1-11,29.11,12,12,0,1,1-18-15.88,20,20,0,0,0,0-26.43,12,12,0,0,1,18-15.86A43.94,43.94,0,0,1,212,128Zm40,0a83.87,83.87,0,0,1-21.39,56,12,12,0,0,1-17.89-16,60,60,0,0,0,0-80,12,12,0,1,1,17.88-16A83.87,83.87,0,0,1,252,128Z\" }))\n ],\n [\n \"duotone\",\n /* @__PURE__ */ a.createElement(a.Fragment, null, /* @__PURE__ */ a.createElement(\"path\", { d: \"M80,88v80H32a8,8,0,0,1-8-8V96a8,8,0,0,1,8-8Z\", opacity: \"0.2\" }), /* @__PURE__ */ a.createElement(\"path\", { d: \"M155.51,24.81a8,8,0,0,0-8.42.88L77.25,80H32A16,16,0,0,0,16,96v64a16,16,0,0,0,16,16H77.25l69.84,54.31A8,8,0,0,0,160,224V32A8,8,0,0,0,155.51,24.81ZM32,96H72v64H32ZM144,207.64,88,164.09V91.91l56-43.55Zm54-106.08a40,40,0,0,1,0,52.88,8,8,0,0,1-12-10.58,24,24,0,0,0,0-31.72,8,8,0,0,1,12-10.58ZM248,128a79.9,79.9,0,0,1-20.37,53.34,8,8,0,0,1-11.92-10.67,64,64,0,0,0,0-85.33,8,8,0,1,1,11.92-10.67A79.83,79.83,0,0,1,248,128Z\" }))\n ],\n [\n \"fill\",\n /* @__PURE__ */ a.createElement(a.Fragment, null, /* @__PURE__ */ a.createElement(\"path\", { d: \"M160,32.25V223.69a8.29,8.29,0,0,1-3.91,7.18,8,8,0,0,1-9-.56l-65.57-51A4,4,0,0,1,80,176.16V79.84a4,4,0,0,1,1.55-3.15l65.57-51a8,8,0,0,1,10,.16A8.27,8.27,0,0,1,160,32.25ZM60,80H32A16,16,0,0,0,16,96v64a16,16,0,0,0,16,16H60a4,4,0,0,0,4-4V84A4,4,0,0,0,60,80Zm126.77,20.84a8,8,0,0,0-.72,11.3,24,24,0,0,1,0,31.72,8,8,0,1,0,12,10.58,40,40,0,0,0,0-52.88A8,8,0,0,0,186.74,100.84Zm40.89-26.17a8,8,0,1,0-11.92,10.66,64,64,0,0,1,0,85.34,8,8,0,1,0,11.92,10.66,80,80,0,0,0,0-106.66Z\" }))\n ],\n [\n \"light\",\n /* @__PURE__ */ a.createElement(a.Fragment, null, /* @__PURE__ */ a.createElement(\"path\", { d: \"M154.64,26.61a6,6,0,0,0-6.32.65L77.94,82H32A14,14,0,0,0,18,96v64a14,14,0,0,0,14,14H77.94l70.38,54.74A6,6,0,0,0,158,224V32A6,6,0,0,0,154.64,26.61ZM30,160V96a2,2,0,0,1,2-2H74v68H32A2,2,0,0,1,30,160Zm116,51.73L86,165.07V90.93l60-46.66Zm50.53-108.85a38,38,0,0,1,0,50.24,6,6,0,1,1-9-7.94,26,26,0,0,0,0-34.37,6,6,0,0,1,9-7.93ZM246,128a77.86,77.86,0,0,1-19.86,52,6,6,0,1,1-8.94-8,66,66,0,0,0,0-88,6,6,0,1,1,8.94-8A77.86,77.86,0,0,1,246,128Z\" }))\n ],\n [\n \"regular\",\n /* @__PURE__ */ a.createElement(a.Fragment, null, /* @__PURE__ */ a.createElement(\"path\", { d: \"M155.51,24.81a8,8,0,0,0-8.42.88L77.25,80H32A16,16,0,0,0,16,96v64a16,16,0,0,0,16,16H77.25l69.84,54.31A8,8,0,0,0,160,224V32A8,8,0,0,0,155.51,24.81ZM32,96H72v64H32ZM144,207.64,88,164.09V91.91l56-43.55Zm54-106.08a40,40,0,0,1,0,52.88,8,8,0,0,1-12-10.58,24,24,0,0,0,0-31.72,8,8,0,0,1,12-10.58ZM248,128a79.9,79.9,0,0,1-20.37,53.34,8,8,0,0,1-11.92-10.67,64,64,0,0,0,0-85.33,8,8,0,1,1,11.92-10.67A79.83,79.83,0,0,1,248,128Z\" }))\n ],\n [\n \"thin\",\n /* @__PURE__ */ a.createElement(a.Fragment, null, /* @__PURE__ */ a.createElement(\"path\", { d: \"M153.76,28.41a4,4,0,0,0-4.22.43L78.63,84H32A12,12,0,0,0,20,96v64a12,12,0,0,0,12,12H78.63l70.91,55.16A4.07,4.07,0,0,0,152,228a3.92,3.92,0,0,0,1.76-.41A4,4,0,0,0,156,224V32A4,4,0,0,0,153.76,28.41ZM28,160V96a4,4,0,0,1,4-4H76v72H32A4,4,0,0,1,28,160Zm120,55.82L84,166V90l64-49.78Zm47-111.61a36,36,0,0,1,0,47.59,4,4,0,1,1-6-5.3,28,28,0,0,0,0-37,4,4,0,0,1,6-5.28ZM244,128a75.88,75.88,0,0,1-19.35,50.67,4,4,0,0,1-6-5.34,68,68,0,0,0,0-90.66,4,4,0,0,1,6-5.34A75.88,75.88,0,0,1,244,128Z\" }))\n ]\n]);\nexport {\n e as default\n};\n","import * as e from \"react\";\nconst a = /* @__PURE__ */ new Map([\n [\n \"bold\",\n /* @__PURE__ */ e.createElement(e.Fragment, null, /* @__PURE__ */ e.createElement(\"path\", { d: \"M157.27,21.22a12,12,0,0,0-12.64,1.31L75.88,76H32A20,20,0,0,0,12,96v64a20,20,0,0,0,20,20H75.88l68.75,53.47A12,12,0,0,0,164,224V32A12,12,0,0,0,157.27,21.22ZM36,100H68v56H36Zm104,99.46L92,162.13V93.87l48-37.33ZM212,128a44,44,0,0,1-11,29.11,12,12,0,0,1-18-15.88,20,20,0,0,0,0-26.44,12,12,0,0,1,18-15.85A43.94,43.94,0,0,1,212,128Z\" }))\n ],\n [\n \"duotone\",\n /* @__PURE__ */ e.createElement(e.Fragment, null, /* @__PURE__ */ e.createElement(\"path\", { d: \"M80,88v80H32a8,8,0,0,1-8-8V96a8,8,0,0,1,8-8Z\", opacity: \"0.2\" }), /* @__PURE__ */ e.createElement(\"path\", { d: \"M155.51,24.81a8,8,0,0,0-8.42.88L77.25,80H32A16,16,0,0,0,16,96v64a16,16,0,0,0,16,16H77.25l69.84,54.31A8,8,0,0,0,160,224V32A8,8,0,0,0,155.51,24.81ZM32,96H72v64H32ZM144,207.64,88,164.09V91.91l56-43.55ZM208,128a39.93,39.93,0,0,1-10,26.46,8,8,0,0,1-12-10.58,24,24,0,0,0,0-31.72,8,8,0,1,1,12-10.58A40,40,0,0,1,208,128Z\" }))\n ],\n [\n \"fill\",\n /* @__PURE__ */ e.createElement(e.Fragment, null, /* @__PURE__ */ e.createElement(\"path\", { d: \"M160,32.25V223.69a8.29,8.29,0,0,1-3.91,7.18,8,8,0,0,1-9-.56l-65.57-51A4,4,0,0,1,80,176.16V79.84a4,4,0,0,1,1.55-3.15l65.57-51a8,8,0,0,1,10,.16A8.27,8.27,0,0,1,160,32.25ZM60,80H32A16,16,0,0,0,16,96v64a16,16,0,0,0,16,16H60a4,4,0,0,0,4-4V84A4,4,0,0,0,60,80ZM198,101.56a8,8,0,1,0-12,10.58,24,24,0,0,1,0,31.72,8,8,0,1,0,12,10.58,40,40,0,0,0,0-52.88Z\" }))\n ],\n [\n \"light\",\n /* @__PURE__ */ e.createElement(e.Fragment, null, /* @__PURE__ */ e.createElement(\"path\", { d: \"M154.64,26.61a6,6,0,0,0-6.32.65L77.94,82H32A14,14,0,0,0,18,96v64a14,14,0,0,0,14,14H77.94l70.38,54.74A6,6,0,0,0,158,224V32A6,6,0,0,0,154.64,26.61ZM30,160V96a2,2,0,0,1,2-2H74v68H32A2,2,0,0,1,30,160Zm116,51.73L86,165.07V90.93l60-46.66ZM206,128a37.94,37.94,0,0,1-9.5,25.14,6,6,0,1,1-9-7.94,26,26,0,0,0,0-34.37,6,6,0,0,1,9-7.93A38,38,0,0,1,206,128Z\" }))\n ],\n [\n \"regular\",\n /* @__PURE__ */ e.createElement(e.Fragment, null, /* @__PURE__ */ e.createElement(\"path\", { d: \"M155.51,24.81a8,8,0,0,0-8.42.88L77.25,80H32A16,16,0,0,0,16,96v64a16,16,0,0,0,16,16H77.25l69.84,54.31A8,8,0,0,0,160,224V32A8,8,0,0,0,155.51,24.81ZM32,96H72v64H32ZM144,207.64,88,164.09V91.91l56-43.55ZM208,128a39.93,39.93,0,0,1-10,26.46,8,8,0,0,1-12-10.58,24,24,0,0,0,0-31.72,8,8,0,1,1,12-10.58A40,40,0,0,1,208,128Z\" }))\n ],\n [\n \"thin\",\n /* @__PURE__ */ e.createElement(e.Fragment, null, /* @__PURE__ */ e.createElement(\"path\", { d: \"M153.76,28.41a4,4,0,0,0-4.22.43L78.63,84H32A12,12,0,0,0,20,96v64a12,12,0,0,0,12,12H78.63l70.91,55.16A4.07,4.07,0,0,0,152,228a3.92,3.92,0,0,0,1.76-.41A4,4,0,0,0,156,224V32A4,4,0,0,0,153.76,28.41ZM28,160V96a4,4,0,0,1,4-4H76v72H32A4,4,0,0,1,28,160Zm120,55.82L84,166V90l64-49.78ZM204,128a36,36,0,0,1-9,23.82,4,4,0,1,1-6-5.3,28,28,0,0,0,0-37,4,4,0,0,1,6-5.28A36,36,0,0,1,204,128Z\" }))\n ]\n]);\nexport {\n a as default\n};\n","import { createContext as r } from \"react\";\nconst o = r({\n color: \"currentColor\",\n size: \"1em\",\n weight: \"regular\",\n mirrored: !1\n});\nexport {\n o as IconContext\n};\n","import * as e from \"react\";\nimport { IconContext as h } from \"./context.es.js\";\nconst p = e.forwardRef(\n (s, a) => {\n const {\n alt: n,\n color: r,\n size: t,\n weight: o,\n mirrored: c,\n children: i,\n weights: m,\n ...x\n } = s, {\n color: d = \"currentColor\",\n size: l,\n weight: f = \"regular\",\n mirrored: g = !1,\n ...w\n } = e.useContext(h);\n return /* @__PURE__ */ e.createElement(\n \"svg\",\n {\n ref: a,\n xmlns: \"http://www.w3.org/2000/svg\",\n width: t != null ? t : l,\n height: t != null ? t : l,\n fill: r != null ? r : d,\n viewBox: \"0 0 256 256\",\n transform: c || g ? \"scale(-1, 1)\" : void 0,\n ...w,\n ...x\n },\n !!n && /* @__PURE__ */ e.createElement(\"title\", null, n),\n i,\n m.get(o != null ? o : f)\n );\n }\n);\np.displayName = \"IconBase\";\nexport {\n p as default\n};\n","import * as e from \"react\";\nimport t from \"../lib/IconBase.es.js\";\nimport i from \"../defs/SpeakerHigh.es.js\";\nconst o = e.forwardRef((r, a) => /* @__PURE__ */ e.createElement(t, { ref: a, ...r, weights: i }));\no.displayName = \"SpeakerHighIcon\";\nconst c = o;\nexport {\n c as SpeakerHigh,\n o as SpeakerHighIcon\n};\n","import * as e from \"react\";\nimport t from \"../lib/IconBase.es.js\";\nimport m from \"../defs/SpeakerLow.es.js\";\nconst o = e.forwardRef((r, a) => /* @__PURE__ */ e.createElement(t, { ref: a, ...r, weights: m }));\no.displayName = \"SpeakerLowIcon\";\nconst s = o;\nexport {\n s as SpeakerLow,\n o as SpeakerLowIcon\n};\n","// src/components/AudioPosition.tsx\nimport styled from \"styled-components\";\nimport { jsx } from \"react/jsx-runtime\";\nvar PositionDisplay = styled.span`\n font-family: 'Courier New', Monaco, monospace;\n font-size: 1rem;\n font-weight: 600;\n color: ${(props) => props.theme?.textColor || \"#333\"};\n user-select: none;\n`;\nvar AudioPosition = ({\n formattedTime,\n className\n}) => {\n return /* @__PURE__ */ jsx(PositionDisplay, { className, \"aria-label\": \"Audio position\", children: formattedTime });\n};\n\n// src/styled/BaseButton.tsx\nimport styled2 from \"styled-components\";\nvar BaseButton = styled2.button`\n display: inline-flex;\n align-items: center;\n justify-content: center;\n padding: 0.5rem 1rem;\n font-family: ${(props) => props.theme.fontFamily};\n font-size: ${(props) => props.theme.fontSize};\n font-weight: 500;\n color: ${(props) => props.theme.buttonText};\n background-color: ${(props) => props.theme.buttonBackground};\n border: 1px solid ${(props) => props.theme.buttonBorder};\n border-radius: ${(props) => props.theme.borderRadius};\n cursor: pointer;\n outline: none;\n transition: background-color 0.15s ease-in-out, border-color 0.15s ease-in-out,\n box-shadow 0.15s ease-in-out;\n\n &:hover:not(:disabled) {\n background-color: ${(props) => props.theme.buttonHoverBackground};\n }\n\n &:focus {\n box-shadow: 0 0 0 2px ${(props) => props.theme.inputFocusBorder}33;\n }\n\n &:disabled {\n opacity: 0.6;\n cursor: not-allowed;\n }\n`;\nvar BaseButtonSmall = styled2(BaseButton)`\n padding: 0.25rem 0.5rem;\n font-size: ${(props) => props.theme.fontSizeSmall};\n`;\nvar IconButton = styled2(BaseButton)`\n padding: 0.5rem;\n min-width: 2.25rem;\n min-height: 2.25rem;\n`;\nvar IconButtonSmall = styled2(BaseButton)`\n padding: 0.25rem;\n min-width: 1.75rem;\n min-height: 1.75rem;\n font-size: ${(props) => props.theme.fontSizeSmall};\n`;\n\n// src/styled/BaseCheckbox.tsx\nimport styled3 from \"styled-components\";\nvar BaseCheckboxWrapper = styled3.div`\n display: inline-flex;\n align-items: center;\n gap: 0.5rem;\n`;\nvar BaseCheckbox = styled3.input`\n cursor: pointer;\n accent-color: ${(props) => props.theme.inputFocusBorder};\n\n &:disabled {\n cursor: not-allowed;\n }\n`;\nvar BaseCheckboxLabel = styled3.label`\n margin: 0;\n cursor: pointer;\n user-select: none;\n font-family: ${(props) => props.theme.fontFamily};\n font-size: ${(props) => props.theme.fontSize};\n color: ${(props) => props.theme.textColor};\n`;\n\n// src/styled/BaseControlButton.tsx\nimport styled4 from \"styled-components\";\nvar BaseControlButton = styled4.button`\n padding: 0.5rem 1rem;\n background: ${(props) => props.theme.buttonBackground || \"#007bff\"};\n color: ${(props) => props.theme.buttonText || \"white\"};\n border: none;\n border-radius: ${(props) => props.theme.borderRadius};\n cursor: pointer;\n font-family: ${(props) => props.theme.fontFamily};\n font-size: ${(props) => props.theme.fontSize};\n font-weight: 500;\n transition: background-color 0.15s ease-in-out;\n\n &:hover:not(:disabled) {\n background: ${(props) => props.theme.buttonHoverBackground || \"#0056b3\"};\n }\n\n &:focus {\n outline: none;\n box-shadow: 0 0 0 2px ${(props) => props.theme.buttonBackground || \"#007bff\"}66;\n }\n\n &:disabled {\n background: #6c757d;\n cursor: not-allowed;\n opacity: 0.6;\n }\n`;\n\n// src/styled/BaseInput.tsx\nimport styled5 from \"styled-components\";\nvar BaseInput = styled5.input`\n padding: 0.5rem 0.75rem;\n font-family: ${(props) => props.theme.fontFamily};\n font-size: ${(props) => props.theme.fontSize};\n color: ${(props) => props.theme.inputText};\n background-color: ${(props) => props.theme.inputBackground};\n border: 1px solid ${(props) => props.theme.inputBorder};\n border-radius: ${(props) => props.theme.borderRadius};\n outline: none;\n transition: border-color 0.15s ease-in-out, box-shadow 0.15s ease-in-out;\n\n &::placeholder {\n color: ${(props) => props.theme.inputPlaceholder};\n }\n\n &:focus {\n border-color: ${(props) => props.theme.inputFocusBorder};\n box-shadow: 0 0 0 2px ${(props) => props.theme.inputFocusBorder}33;\n }\n\n &:disabled {\n opacity: 0.6;\n cursor: not-allowed;\n }\n`;\nvar BaseInputSmall = styled5(BaseInput)`\n padding: 0.25rem 0.5rem;\n font-size: ${(props) => props.theme.fontSizeSmall};\n`;\n\n// src/styled/BaseLabel.tsx\nimport styled6 from \"styled-components\";\nvar BaseLabel = styled6.label`\n font-family: ${(props) => props.theme.fontFamily};\n font-size: ${(props) => props.theme.fontSizeSmall};\n font-weight: 500;\n color: ${(props) => props.theme.textColorMuted};\n margin-bottom: 0.25rem;\n display: block;\n`;\nvar InlineLabel = styled6.label`\n font-family: ${(props) => props.theme.fontFamily};\n font-size: ${(props) => props.theme.fontSize};\n color: ${(props) => props.theme.textColor};\n display: inline-flex;\n align-items: center;\n gap: 0.5rem;\n cursor: pointer;\n`;\nvar ScreenReaderOnly = styled6.span`\n position: absolute;\n width: 1px;\n height: 1px;\n padding: 0;\n margin: -1px;\n overflow: hidden;\n clip: rect(0, 0, 0, 0);\n white-space: nowrap;\n border: 0;\n`;\n\n// src/styled/BaseSelect.tsx\nimport styled7 from \"styled-components\";\nvar BaseSelect = styled7.select`\n padding: 0.5rem 2rem 0.5rem 0.75rem;\n font-family: ${(props) => props.theme.fontFamily};\n font-size: ${(props) => props.theme.fontSize};\n color: ${(props) => props.theme.inputText};\n background-color: ${(props) => props.theme.inputBackground};\n border: 1px solid ${(props) => props.theme.inputBorder};\n border-radius: ${(props) => props.theme.borderRadius};\n outline: none;\n cursor: pointer;\n appearance: none;\n background-image: url(\"data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='12' height='12' viewBox='0 0 12 12'%3E%3Cpath fill='%23666' d='M6 8L1 3h10z'/%3E%3C/svg%3E\");\n background-repeat: no-repeat;\n background-position: right 0.75rem center;\n transition: border-color 0.15s ease-in-out, box-shadow 0.15s ease-in-out;\n\n &:focus {\n border-color: ${(props) => props.theme.inputFocusBorder};\n box-shadow: 0 0 0 2px ${(props) => props.theme.inputFocusBorder}33;\n }\n\n &:disabled {\n opacity: 0.6;\n cursor: not-allowed;\n }\n\n /* Style native option elements for dark mode support */\n option {\n color: ${(props) => props.theme.inputText};\n background-color: ${(props) => props.theme.inputBackground};\n }\n`;\nvar BaseSelectSmall = styled7(BaseSelect)`\n padding: 0.25rem 1.75rem 0.25rem 0.5rem;\n font-size: ${(props) => props.theme.fontSizeSmall};\n`;\n\n// src/styled/BaseSlider.tsx\nimport styled8 from \"styled-components\";\nvar BaseSlider = styled8.input.attrs({ type: \"range\" })`\n -webkit-appearance: none;\n appearance: none;\n width: 100%;\n height: 6px;\n background: ${(props) => props.theme.sliderTrackColor};\n border-radius: 3px;\n cursor: pointer;\n outline: none;\n\n /* WebKit (Chrome, Safari) */\n &::-webkit-slider-thumb {\n -webkit-appearance: none;\n appearance: none;\n width: 16px;\n height: 16px;\n background: ${(props) => props.theme.sliderThumbColor};\n border: 2px solid ${(props) => props.theme.inputBackground};\n border-radius: 50%;\n cursor: pointer;\n box-shadow: 0 1px 3px rgba(0, 0, 0, 0.2);\n transition: transform 0.15s ease, box-shadow 0.15s ease;\n }\n\n &::-webkit-slider-thumb:hover {\n transform: scale(1.1);\n box-shadow: 0 2px 4px rgba(0, 0, 0, 0.3);\n }\n\n /* Firefox */\n &::-moz-range-thumb {\n width: 16px;\n height: 16px;\n background: ${(props) => props.theme.sliderThumbColor};\n border: 2px solid ${(props) => props.theme.inputBackground};\n border-radius: 50%;\n cursor: pointer;\n box-shadow: 0 1px 3px rgba(0, 0, 0, 0.2);\n transition: transform 0.15s ease, box-shadow 0.15s ease;\n }\n\n &::-moz-range-thumb:hover {\n transform: scale(1.1);\n box-shadow: 0 2px 4px rgba(0, 0, 0, 0.3);\n }\n\n &::-moz-range-track {\n background: ${(props) => props.theme.sliderTrackColor};\n border-radius: 3px;\n height: 6px;\n }\n\n &:focus {\n outline: none;\n }\n\n &:focus::-webkit-slider-thumb {\n box-shadow: 0 0 0 3px ${(props) => props.theme.inputFocusBorder}33;\n }\n\n &:focus::-moz-range-thumb {\n box-shadow: 0 0 0 3px ${(props) => props.theme.inputFocusBorder}33;\n }\n\n &:disabled {\n cursor: not-allowed;\n opacity: 0.5;\n }\n\n &:disabled::-webkit-slider-thumb {\n cursor: not-allowed;\n }\n\n &:disabled::-moz-range-thumb {\n cursor: not-allowed;\n }\n`;\n\n// src/components/AutomaticScrollCheckbox.tsx\nimport { jsx as jsx2, jsxs } from \"react/jsx-runtime\";\nvar AutomaticScrollCheckbox = ({\n checked,\n onChange,\n disabled = false,\n className\n}) => {\n const handleChange = (e) => {\n onChange(e.target.checked);\n };\n return /* @__PURE__ */ jsxs(BaseCheckboxWrapper, { className, children: [\n /* @__PURE__ */ jsx2(\n BaseCheckbox,\n {\n type: \"checkbox\",\n id: \"automatic-scroll\",\n className: \"automatic-scroll\",\n checked,\n onChange: handleChange,\n disabled\n }\n ),\n /* @__PURE__ */ jsx2(BaseCheckboxLabel, { htmlFor: \"automatic-scroll\", children: \"Automatic Scroll\" })\n ] });\n};\n\n// src/components/Channel.tsx\nimport { useLayoutEffect, useCallback, useRef } from \"react\";\nimport styled9 from \"styled-components\";\n\n// src/wfpl-theme.ts\nfunction isWaveformGradient(color) {\n return typeof color === \"object\" && color !== null && \"type\" in color;\n}\nfunction waveformColorToCss(color) {\n if (!isWaveformGradient(color)) {\n return color;\n }\n const direction = color.direction === \"vertical\" ? \"to bottom\" : \"to right\";\n const stops = color.stops.map((stop) => `${stop.color} ${stop.offset * 100}%`).join(\", \");\n return `linear-gradient(${direction}, ${stops})`;\n}\nvar defaultTheme = {\n waveformDrawMode: \"inverted\",\n waveOutlineColor: \"#ffffff\",\n waveFillColor: \"#1a7f8e\",\n // White background for crisp look\n waveProgressColor: \"rgba(0, 0, 0, 0.10)\",\n // Subtle dark overlay for light mode\n selectedWaveOutlineColor: \"#ffffff\",\n selectedWaveFillColor: \"#00b4d8\",\n // Selected: brighter cyan\n selectedTrackControlsBackground: \"#d9e9ff\",\n // Light blue background for selected track controls\n timeColor: \"#000\",\n timescaleBackgroundColor: \"#fff\",\n playheadColor: \"#f00\",\n selectionColor: \"rgba(255, 105, 180, 0.7)\",\n // hot pink - high contrast on light backgrounds\n loopRegionColor: \"rgba(59, 130, 246, 0.3)\",\n // Blue - distinct from pink selection\n loopMarkerColor: \"#3b82f6\",\n // Blue marker triangles\n clipHeaderBackgroundColor: \"rgba(0, 0, 0, 0.1)\",\n clipHeaderBorderColor: \"rgba(0, 0, 0, 0.2)\",\n clipHeaderTextColor: \"#333\",\n clipHeaderFontFamily: \"inherit\",\n selectedClipHeaderBackgroundColor: \"#b3d9ff\",\n // Brighter blue for selected track clip headers\n // Fade overlay colors\n fadeOverlayColor: \"rgba(0, 0, 0, 0.4)\",\n // Semi-transparent overlay for fade regions\n // UI component colors\n backgroundColor: \"#ffffff\",\n surfaceColor: \"#f5f5f5\",\n borderColor: \"#ddd\",\n textColor: \"#333\",\n textColorMuted: \"#666\",\n // Interactive element colors\n inputBackground: \"#ffffff\",\n inputBorder: \"#ccc\",\n inputText: \"#333\",\n inputPlaceholder: \"#999\",\n inputFocusBorder: \"#0066cc\",\n // Button colors - blue to match common UI patterns\n buttonBackground: \"#0091ff\",\n buttonText: \"#ffffff\",\n buttonBorder: \"#0081e6\",\n buttonHoverBackground: \"#0081e6\",\n // Slider colors\n sliderTrackColor: \"#ddd\",\n sliderThumbColor: \"#daa520\",\n // goldenrod\n // Annotation colors\n annotationBoxBackground: \"rgba(255, 255, 255, 0.85)\",\n annotationBoxActiveBackground: \"rgba(255, 255, 255, 0.95)\",\n annotationBoxHoverBackground: \"rgba(255, 255, 255, 0.98)\",\n annotationBoxBorder: \"#ff9800\",\n annotationBoxActiveBorder: \"#d67600\",\n annotationLabelColor: \"#2a2a2a\",\n annotationResizeHandleColor: \"rgba(0, 0, 0, 0.4)\",\n annotationResizeHandleActiveColor: \"rgba(0, 0, 0, 0.8)\",\n annotationTextItemHoverBackground: \"rgba(0, 0, 0, 0.03)\",\n // Spacing and sizing\n borderRadius: \"4px\",\n fontFamily: '-apple-system, BlinkMacSystemFont, \"Segoe UI\", Roboto, Oxygen, Ubuntu, sans-serif',\n fontSize: \"14px\",\n fontSizeSmall: \"12px\"\n};\nvar darkTheme = {\n // Normal mode: waveOutlineColor = bars, waveFillColor = background\n waveformDrawMode: \"inverted\",\n // Dark bars on warm amber background\n waveOutlineColor: \"#c49a6c\",\n // Solid warm amber for background\n waveFillColor: \"#1a1612\",\n // Very dark warm brown for bars\n waveProgressColor: \"rgba(100, 70, 40, 0.6)\",\n // Warm brown progress overlay\n // Selected: slightly lighter bars on brighter amber background\n selectedWaveFillColor: \"#241c14\",\n // Slightly lighter warm brown bars when selected\n selectedWaveOutlineColor: \"#e8c090\",\n // Brighter amber background when selected\n selectedTrackControlsBackground: \"#2a2218\",\n // Dark warm brown for selected track controls\n timeColor: \"#d8c0a8\",\n // Warm amber for timescale text\n timescaleBackgroundColor: \"#1a1612\",\n // Dark warm brown background\n playheadColor: \"#3a8838\",\n // Darker Ampelmännchen green playhead\n selectionColor: \"rgba(60, 140, 58, 0.6)\",\n // Darker Ampelmännchen green selection - visible on dark backgrounds\n loopRegionColor: \"rgba(96, 165, 250, 0.35)\",\n // Light blue - distinct from green selection\n loopMarkerColor: \"#60a5fa\",\n // Light blue marker triangles\n clipHeaderBackgroundColor: \"rgba(20, 16, 12, 0.85)\",\n // Dark background for clip headers\n clipHeaderBorderColor: \"rgba(200, 160, 120, 0.25)\",\n clipHeaderTextColor: \"#d8c0a8\",\n // Warm amber text\n clipHeaderFontFamily: \"inherit\",\n selectedClipHeaderBackgroundColor: \"#3a2c20\",\n // Darker warm brown for selected clip headers\n // Fade overlay colors\n fadeOverlayColor: \"rgba(200, 100, 80, 0.5)\",\n // Warm red-orange overlay visible on dark backgrounds\n // UI component colors\n backgroundColor: \"#1e1e1e\",\n surfaceColor: \"#2d2d2d\",\n borderColor: \"#444\",\n textColor: \"#e0e0e0\",\n textColorMuted: \"#999\",\n // Interactive element colors\n inputBackground: \"#2d2d2d\",\n inputBorder: \"#555\",\n inputText: \"#e0e0e0\",\n inputPlaceholder: \"#777\",\n inputFocusBorder: \"#4A9EFF\",\n // Button colors - Ampelmännchen green (#63C75F) with black text\n buttonBackground: \"#63C75F\",\n buttonText: \"#0a0a0f\",\n buttonBorder: \"#52b84e\",\n buttonHoverBackground: \"#78d074\",\n // Slider colors\n sliderTrackColor: \"#555\",\n sliderThumbColor: \"#f0c040\",\n // brighter goldenrod for dark mode\n // Annotation colors (dark mode - warm amber theme)\n annotationBoxBackground: \"rgba(40, 32, 24, 0.9)\",\n annotationBoxActiveBackground: \"rgba(50, 40, 30, 0.95)\",\n annotationBoxHoverBackground: \"rgba(60, 48, 36, 0.98)\",\n annotationBoxBorder: \"#c49a6c\",\n annotationBoxActiveBorder: \"#d4a87c\",\n annotationLabelColor: \"#d8c0a8\",\n annotationResizeHandleColor: \"rgba(200, 160, 120, 0.5)\",\n annotationResizeHandleActiveColor: \"rgba(220, 180, 140, 0.8)\",\n annotationTextItemHoverBackground: \"rgba(200, 160, 120, 0.08)\",\n // Spacing and sizing\n borderRadius: \"4px\",\n fontFamily: '-apple-system, BlinkMacSystemFont, \"Segoe UI\", Roboto, Oxygen, Ubuntu, sans-serif',\n fontSize: \"14px\",\n fontSizeSmall: \"12px\"\n};\n\n// src/components/Channel.tsx\nimport { jsx as jsx3 } from \"react/jsx-runtime\";\nvar MAX_CANVAS_WIDTH = 1e3;\nfunction createCanvasFillStyle(ctx, color, width, height) {\n if (!isWaveformGradient(color)) {\n return color;\n }\n let gradient;\n if (color.direction === \"vertical\") {\n gradient = ctx.createLinearGradient(0, 0, 0, height);\n } else {\n gradient = ctx.createLinearGradient(0, 0, width, 0);\n }\n for (const stop of color.stops) {\n gradient.addColorStop(stop.offset, stop.color);\n }\n return gradient;\n}\nvar Waveform = styled9.canvas.attrs((props) => ({\n style: {\n width: `${props.$cssWidth}px`,\n height: `${props.$waveHeight}px`\n }\n}))`\n float: left;\n position: relative;\n /* Promote to own compositing layer for smoother scrolling */\n will-change: transform;\n /* Disable image rendering interpolation */\n image-rendering: pixelated;\n image-rendering: crisp-edges;\n`;\nvar Wrapper = styled9.div.attrs((props) => ({\n style: {\n top: `${props.$waveHeight * props.$index}px`,\n width: `${props.$cssWidth}px`,\n height: `${props.$waveHeight}px`\n }\n}))`\n position: absolute;\n background: ${(props) => props.$waveFillColor};\n /* Force GPU compositing layer to reduce scroll flickering */\n transform: translateZ(0);\n backface-visibility: hidden;\n`;\nvar Channel = (props) => {\n const {\n data,\n bits,\n length,\n index,\n className,\n devicePixelRatio = 1,\n waveHeight = 80,\n waveOutlineColor = \"#E0EFF1\",\n waveFillColor = \"grey\",\n barWidth = 1,\n barGap = 0,\n transparentBackground = false,\n drawMode = \"inverted\"\n } = props;\n const canvasesRef = useRef([]);\n const canvasRef = useCallback(\n (canvas) => {\n if (canvas !== null) {\n const index2 = parseInt(canvas.dataset.index, 10);\n canvasesRef.current[index2] = canvas;\n }\n },\n []\n );\n useLayoutEffect(() => {\n const canvases = canvasesRef.current;\n const step = barWidth + barGap;\n let globalPixelOffset = 0;\n for (let i = 0; i < canvases.length; i++) {\n const canvas = canvases[i];\n const ctx = canvas.getContext(\"2d\");\n const h2 = Math.floor(waveHeight / 2);\n const maxValue = 2 ** (bits - 1);\n if (ctx) {\n ctx.resetTransform();\n ctx.clearRect(0, 0, canvas.width, canvas.height);\n ctx.imageSmoothingEnabled = false;\n ctx.scale(devicePixelRatio, devicePixelRatio);\n const canvasWidth = canvas.width / devicePixelRatio;\n let fillColor;\n if (drawMode === \"normal\") {\n fillColor = waveFillColor;\n } else {\n fillColor = waveOutlineColor;\n }\n ctx.fillStyle = createCanvasFillStyle(\n ctx,\n fillColor,\n canvasWidth,\n waveHeight\n );\n const canvasStartGlobal = globalPixelOffset;\n const canvasEndGlobal = globalPixelOffset + canvasWidth;\n const firstBarGlobal = Math.floor((canvasStartGlobal - barWidth + step) / step) * step;\n for (let barGlobal = Math.max(0, firstBarGlobal); barGlobal < canvasEndGlobal; barGlobal += step) {\n const x = barGlobal - canvasStartGlobal;\n if (x + barWidth <= 0) continue;\n const peakIndex = barGlobal;\n if (peakIndex * 2 + 1 < data.length) {\n const minPeak = data[peakIndex * 2] / maxValue;\n const maxPeak = data[peakIndex * 2 + 1] / maxValue;\n const min = Math.abs(minPeak * h2);\n const max = Math.abs(maxPeak * h2);\n if (drawMode === \"normal\") {\n ctx.fillRect(x, h2 - max, barWidth, max + min);\n } else {\n ctx.fillRect(x, 0, barWidth, h2 - max);\n ctx.fillRect(x, h2 + min, barWidth, h2 - min);\n }\n }\n }\n }\n globalPixelOffset += canvas.width / devicePixelRatio;\n }\n }, [\n data,\n bits,\n waveHeight,\n waveOutlineColor,\n waveFillColor,\n devicePixelRatio,\n length,\n barWidth,\n barGap,\n drawMode\n ]);\n let totalWidth = length;\n let waveformCount = 0;\n const waveforms = [];\n while (totalWidth > 0) {\n const currentWidth = Math.min(totalWidth, MAX_CANVAS_WIDTH);\n const waveform = /* @__PURE__ */ jsx3(\n Waveform,\n {\n $cssWidth: currentWidth,\n width: currentWidth * devicePixelRatio,\n height: waveHeight * devicePixelRatio,\n $waveHeight: waveHeight,\n \"data-index\": waveformCount,\n ref: canvasRef\n },\n `${length}-${waveformCount}`\n );\n waveforms.push(waveform);\n totalWidth -= currentWidth;\n waveformCount += 1;\n }\n const bgColor = waveFillColor;\n const backgroundCss = transparentBackground ? \"transparent\" : waveformColorToCss(bgColor);\n return /* @__PURE__ */ jsx3(\n Wrapper,\n {\n $index: index,\n $cssWidth: length,\n className,\n $waveHeight: waveHeight,\n $waveFillColor: backgroundCss,\n children: waveforms\n }\n );\n};\n\n// src/components/Clip.tsx\nimport styled13 from \"styled-components\";\nimport { useDraggable } from \"@dnd-kit/core\";\nimport { CSS } from \"@dnd-kit/utilities\";\n\n// src/components/ClipHeader.tsx\nimport styled10 from \"styled-components\";\nimport { jsx as jsx4 } from \"react/jsx-runtime\";\nvar CLIP_HEADER_HEIGHT = 22;\nvar HeaderContainer = styled10.div`\n position: relative;\n height: ${CLIP_HEADER_HEIGHT}px;\n background: ${(props) => props.$isSelected ? props.theme.selectedClipHeaderBackgroundColor : props.theme.clipHeaderBackgroundColor};\n border-bottom: 1px solid ${(props) => props.theme.clipHeaderBorderColor};\n display: flex;\n align-items: center;\n padding: 0 8px;\n cursor: ${(props) => props.$interactive ? props.$isDragging ? \"grabbing\" : \"grab\" : \"default\"};\n user-select: none;\n z-index: 110;\n flex-shrink: 0;\n pointer-events: auto; /* Re-enable pointer events (parent ClipContainer has pointer-events: none) */\n touch-action: ${(props) => props.$interactive ? \"none\" : \"auto\"}; /* Prevent browser scroll during drag on touch devices */\n\n ${(props) => props.$interactive && `\n &:hover {\n background: ${props.theme.clipHeaderBackgroundColor}dd;\n }\n\n &:active {\n cursor: grabbing;\n }\n `}\n`;\nvar TrackName = styled10.span`\n font-size: 11px;\n font-weight: 600;\n font-family: ${(props) => props.theme.clipHeaderFontFamily};\n color: ${(props) => props.theme.clipHeaderTextColor};\n white-space: nowrap;\n overflow: hidden;\n text-overflow: ellipsis;\n`;\nvar ClipHeaderPresentational = ({\n trackName,\n isSelected = false\n}) => {\n return /* @__PURE__ */ jsx4(\n HeaderContainer,\n {\n $isDragging: false,\n $interactive: false,\n $isSelected: isSelected,\n children: /* @__PURE__ */ jsx4(TrackName, { children: trackName })\n }\n );\n};\nvar ClipHeader = ({\n clipId,\n trackIndex,\n clipIndex,\n trackName,\n isSelected = false,\n disableDrag = false,\n dragHandleProps\n}) => {\n if (disableDrag || !dragHandleProps) {\n return /* @__PURE__ */ jsx4(\n ClipHeaderPresentational,\n {\n trackName,\n isSelected\n }\n );\n }\n const { attributes, listeners, setActivatorNodeRef } = dragHandleProps;\n return /* @__PURE__ */ jsx4(\n HeaderContainer,\n {\n ref: setActivatorNodeRef,\n \"data-clip-id\": clipId,\n $interactive: true,\n $isSelected: isSelected,\n ...listeners,\n ...attributes,\n children: /* @__PURE__ */ jsx4(TrackName, { children: trackName })\n }\n );\n};\n\n// src/components/ClipBoundary.tsx\nimport React2 from \"react\";\nimport styled11 from \"styled-components\";\nimport { jsx as jsx5 } from \"react/jsx-runtime\";\nvar CLIP_BOUNDARY_WIDTH = 8;\nvar CLIP_BOUNDARY_WIDTH_TOUCH = 24;\nvar BoundaryContainer = styled11.div`\n position: absolute;\n ${(props) => props.$edge === \"left\" ? \"left: 0;\" : \"right: 0;\"}\n top: 0;\n bottom: 0;\n width: ${(props) => props.$touchOptimized ? CLIP_BOUNDARY_WIDTH_TOUCH : CLIP_BOUNDARY_WIDTH}px;\n cursor: col-resize;\n user-select: none;\n z-index: 105; /* Above waveform, below header */\n pointer-events: auto; /* Re-enable pointer events (parent ClipContainer has pointer-events: none) */\n touch-action: none; /* Prevent browser scroll during drag on touch devices */\n\n /* Invisible by default, visible on hover */\n background: ${(props) => props.$isDragging ? \"rgba(255, 255, 255, 0.4)\" : props.$isHovered ? \"rgba(255, 255, 255, 0.2)\" : \"transparent\"};\n\n ${(props) => props.$edge === \"left\" ? `border-left: 2px solid ${props.$isDragging ? \"rgba(255, 255, 255, 0.8)\" : props.$isHovered ? \"rgba(255, 255, 255, 0.5)\" : \"transparent\"};` : `border-right: 2px solid ${props.$isDragging ? \"rgba(255, 255, 255, 0.8)\" : props.$isHovered ? \"rgba(255, 255, 255, 0.5)\" : \"transparent\"};`}\n\n transition: background 0.15s ease, border-color 0.15s ease;\n\n &:hover {\n background: rgba(255, 255, 255, 0.2);\n ${(props) => props.$edge === \"left\" ? \"border-left: 2px solid rgba(255, 255, 255, 0.5);\" : \"border-right: 2px solid rgba(255, 255, 255, 0.5);\"}\n }\n\n &:active {\n background: rgba(255, 255, 255, 0.4);\n ${(props) => props.$edge === \"left\" ? \"border-left: 2px solid rgba(255, 255, 255, 0.8);\" : \"border-right: 2px solid rgba(255, 255, 255, 0.8);\"}\n }\n`;\nvar ClipBoundary = ({\n clipId,\n trackIndex,\n clipIndex,\n edge,\n dragHandleProps,\n touchOptimized = false\n}) => {\n const [isHovered, setIsHovered] = React2.useState(false);\n if (!dragHandleProps) {\n return null;\n }\n const { attributes, listeners, setActivatorNodeRef, isDragging } = dragHandleProps;\n return /* @__PURE__ */ jsx5(\n BoundaryContainer,\n {\n ref: setActivatorNodeRef,\n \"data-clip-id\": clipId,\n \"data-boundary-edge\": edge,\n $edge: edge,\n $isDragging: isDragging,\n $isHovered: isHovered,\n $touchOptimized: touchOptimized,\n onMouseEnter: () => setIsHovered(true),\n onMouseLeave: () => setIsHovered(false),\n ...listeners,\n ...attributes\n }\n );\n};\n\n// src/components/FadeOverlay.tsx\nimport styled12, { useTheme } from \"styled-components\";\nimport { jsx as jsx6 } from \"react/jsx-runtime\";\nvar FadeContainer = styled12.div.attrs((props) => ({\n style: {\n left: `${props.$left}px`,\n width: `${props.$width}px`\n }\n}))`\n position: absolute;\n top: 0;\n bottom: 0;\n pointer-events: none;\n z-index: 50;\n`;\nvar FadeSvg = styled12.svg`\n width: 100%;\n height: 100%;\n display: block;\n /* Flip horizontally for fadeOut - makes it mirror of fadeIn */\n transform: ${(props) => props.$type === \"fadeOut\" ? \"scaleX(-1)\" : \"none\"};\n`;\nfunction generateFadePath(width, height, curveType = \"logarithmic\") {\n const points = [];\n const numPoints = Math.max(20, Math.min(width, 100));\n for (let i = 0; i <= numPoints; i++) {\n const x = i / numPoints * width;\n const progress = i / numPoints;\n let curvedProgress;\n switch (curveType) {\n case \"linear\":\n curvedProgress = progress;\n break;\n case \"exponential\":\n curvedProgress = progress * progress;\n break;\n case \"sCurve\":\n curvedProgress = (1 - Math.cos(progress * Math.PI)) / 2;\n break;\n case \"logarithmic\":\n default:\n curvedProgress = Math.log10(1 + progress * 9) / Math.log10(10);\n break;\n }\n const y = (1 - curvedProgress) * height;\n points.push(`${x},${y}`);\n }\n return `M 0,${height} L ${points.join(\" L \")} L ${width},0 L 0,0 Z`;\n}\nvar FadeOverlay = ({\n left,\n width,\n type,\n curveType = \"logarithmic\",\n color\n}) => {\n const theme = useTheme();\n if (width < 1) return null;\n const fillColor = color || theme?.fadeOverlayColor || \"rgba(0, 0, 0, 0.4)\";\n return /* @__PURE__ */ jsx6(FadeContainer, { $left: left, $width: width, $type: type, children: /* @__PURE__ */ jsx6(FadeSvg, { $type: type, viewBox: `0 0 ${width} 100`, preserveAspectRatio: \"none\", children: /* @__PURE__ */ jsx6(\n \"path\",\n {\n d: generateFadePath(width, 100, curveType),\n fill: fillColor\n }\n ) }) });\n};\n\n// src/components/Clip.tsx\nimport { Fragment, jsx as jsx7, jsxs as jsxs2 } from \"react/jsx-runtime\";\nvar ClipContainer = styled13.div.attrs((props) => ({\n style: props.$isOverlay ? {} : {\n left: `${props.$left}px`,\n width: `${props.$width}px`\n }\n}))`\n position: ${(props) => props.$isOverlay ? \"relative\" : \"absolute\"};\n top: 0;\n height: ${(props) => props.$isOverlay ? \"auto\" : \"100%\"};\n width: ${(props) => props.$isOverlay ? `${props.$width}px` : \"auto\"};\n display: flex;\n flex-direction: column;\n background: rgba(255, 255, 255, 0.05);\n z-index: 10; /* Above progress overlay (z-index: 2) but below controls/playhead */\n pointer-events: none; /* Let clicks pass through to ClickOverlay for playhead positioning */\n\n &:hover {\n background: rgba(255, 255, 255, 0.08);\n }\n`;\nvar ChannelsWrapper = styled13.div`\n flex: 1;\n position: relative;\n overflow: ${(props) => props.$isOverlay ? \"visible\" : \"hidden\"};\n`;\nvar Clip = ({\n children,\n className,\n clipId,\n trackIndex,\n clipIndex,\n trackName,\n startSample,\n durationSamples,\n samplesPerPixel,\n showHeader = false,\n disableHeaderDrag = false,\n isOverlay = false,\n isSelected = false,\n onMouseDown,\n trackId,\n fadeIn,\n fadeOut,\n sampleRate = 44100,\n showFades = false,\n touchOptimized = false\n}) => {\n const left = Math.floor(startSample / samplesPerPixel);\n const endPixel = Math.floor((startSample + durationSamples) / samplesPerPixel);\n const width = endPixel - left;\n const enableDrag = showHeader && !disableHeaderDrag && !isOverlay;\n const draggableId = `clip-${trackIndex}-${clipIndex}`;\n const { attributes, listeners, setNodeRef, setActivatorNodeRef, transform, isDragging } = useDraggable({\n id: draggableId,\n data: { clipId, trackIndex, clipIndex },\n disabled: !enableDrag\n });\n const leftBoundaryId = `clip-boundary-left-${trackIndex}-${clipIndex}`;\n const {\n attributes: leftBoundaryAttributes,\n listeners: leftBoundaryListeners,\n setActivatorNodeRef: setLeftBoundaryActivatorRef,\n isDragging: isLeftBoundaryDragging\n } = useDraggable({\n id: leftBoundaryId,\n data: { clipId, trackIndex, clipIndex, boundary: \"left\" },\n disabled: !enableDrag\n });\n const rightBoundaryId = `clip-boundary-right-${trackIndex}-${clipIndex}`;\n const {\n attributes: rightBoundaryAttributes,\n listeners: rightBoundaryListeners,\n setActivatorNodeRef: setRightBoundaryActivatorRef,\n isDragging: isRightBoundaryDragging\n } = useDraggable({\n id: rightBoundaryId,\n data: { clipId, trackIndex, clipIndex, boundary: \"right\" },\n disabled: !enableDrag\n });\n const style = transform ? {\n transform: CSS.Translate.toString(transform),\n zIndex: isDragging ? 100 : void 0\n // Below controls (z-index: 999) but above other clips\n } : void 0;\n return /* @__PURE__ */ jsxs2(\n ClipContainer,\n {\n ref: setNodeRef,\n style,\n className,\n $left: left,\n $width: width,\n $isOverlay: isOverlay,\n \"data-clip-container\": \"true\",\n \"data-track-id\": trackId,\n onMouseDown,\n children: [\n showHeader && /* @__PURE__ */ jsx7(\n ClipHeader,\n {\n clipId,\n trackIndex,\n clipIndex,\n trackName,\n isSelected,\n disableDrag: disableHeaderDrag,\n dragHandleProps: enableDrag ? { attributes, listeners, setActivatorNodeRef } : void 0\n }\n ),\n /* @__PURE__ */ jsxs2(ChannelsWrapper, { $isOverlay: isOverlay, children: [\n children,\n showFades && fadeIn && fadeIn.duration > 0 && /* @__PURE__ */ jsx7(\n FadeOverlay,\n {\n left: 0,\n width: Math.floor(fadeIn.duration * sampleRate / samplesPerPixel),\n type: \"fadeIn\",\n curveType: fadeIn.type\n }\n ),\n showFades && fadeOut && fadeOut.duration > 0 && /* @__PURE__ */ jsx7(\n FadeOverlay,\n {\n left: width - Math.floor(fadeOut.duration * sampleRate / samplesPerPixel),\n width: Math.floor(fadeOut.duration * sampleRate / samplesPerPixel),\n type: \"fadeOut\",\n curveType: fadeOut.type\n }\n )\n ] }),\n showHeader && !disableHeaderDrag && !isOverlay && /* @__PURE__ */ jsxs2(Fragment, { children: [\n /* @__PURE__ */ jsx7(\n ClipBoundary,\n {\n clipId,\n trackIndex,\n clipIndex,\n edge: \"left\",\n touchOptimized,\n dragHandleProps: {\n attributes: leftBoundaryAttributes,\n listeners: leftBoundaryListeners,\n setActivatorNodeRef: setLeftBoundaryActivatorRef,\n isDragging: isLeftBoundaryDragging\n }\n }\n ),\n /* @__PURE__ */ jsx7(\n ClipBoundary,\n {\n clipId,\n trackIndex,\n clipIndex,\n edge: \"right\",\n touchOptimized,\n dragHandleProps: {\n attributes: rightBoundaryAttributes,\n listeners: rightBoundaryListeners,\n setActivatorNodeRef: setRightBoundaryActivatorRef,\n isDragging: isRightBoundaryDragging\n }\n }\n )\n ] })\n ]\n }\n );\n};\n\n// src/components/MasterVolumeControl.tsx\nimport styled14 from \"styled-components\";\nimport { jsx as jsx8, jsxs as jsxs3 } from \"react/jsx-runtime\";\nvar VolumeContainer = styled14.div`\n display: inline-flex;\n align-items: center;\n gap: 0.5rem;\n`;\nvar VolumeLabel = styled14(BaseLabel)`\n margin: 0;\n white-space: nowrap;\n`;\nvar VolumeSlider = styled14(BaseSlider)`\n width: 120px;\n`;\nvar MasterVolumeControl = ({\n volume,\n onChange,\n disabled = false,\n className\n}) => {\n const handleChange = (e) => {\n onChange(parseFloat(e.target.value) / 100);\n };\n return /* @__PURE__ */ jsxs3(VolumeContainer, { className, children: [\n /* @__PURE__ */ jsx8(VolumeLabel, { htmlFor: \"master-gain\", children: \"Master Volume\" }),\n /* @__PURE__ */ jsx8(\n VolumeSlider,\n {\n min: \"0\",\n max: \"100\",\n value: volume * 100,\n onChange: handleChange,\n disabled,\n id: \"master-gain\"\n }\n )\n ] });\n};\n\n// src/components/Playhead.tsx\nimport { useRef as useRef2, useEffect } from \"react\";\nimport styled15 from \"styled-components\";\nimport { jsx as jsx9, jsxs as jsxs4 } from \"react/jsx-runtime\";\nvar PlayheadLine = styled15.div.attrs((props) => ({\n style: {\n transform: `translate3d(${props.$position}px, 0, 0)`\n }\n}))`\n position: absolute;\n top: 0;\n left: 0;\n width: 2px;\n background: ${(props) => props.$color};\n height: 100%;\n z-index: 100; /* Below sticky controls (z-index: 101) so playhead is hidden when scrolled behind controls */\n pointer-events: none;\n will-change: transform;\n`;\nvar Playhead = ({ position, color = \"#ff0000\" }) => {\n return /* @__PURE__ */ jsx9(PlayheadLine, { $position: position, $color: color });\n};\nvar PlayheadWithMarkerContainer = styled15.div`\n position: absolute;\n top: 0;\n left: 0;\n height: 100%;\n z-index: 100; /* Below sticky controls (z-index: 101) so playhead is hidden when scrolled behind controls */\n pointer-events: none;\n will-change: transform;\n`;\nvar MarkerTriangle = styled15.div`\n position: absolute;\n top: -10px;\n left: -6px;\n width: 0;\n height: 0;\n border-left: 7px solid transparent;\n border-right: 7px solid transparent;\n border-top: 10px solid ${(props) => props.$color};\n`;\nvar MarkerLine = styled15.div`\n position: absolute;\n top: 0;\n left: 0;\n width: 2px;\n height: 100%;\n background: ${(props) => props.$color};\n`;\nvar PlayheadWithMarker = ({\n color = \"#ff0000\",\n isPlaying,\n currentTimeRef,\n playbackStartTimeRef,\n audioStartPositionRef,\n samplesPerPixel,\n sampleRate,\n controlsOffset,\n getAudioContextTime\n}) => {\n const containerRef = useRef2(null);\n const animationFrameRef = useRef2(null);\n useEffect(() => {\n const updatePosition = () => {\n if (containerRef.current) {\n let time;\n if (isPlaying && getAudioContextTime) {\n const elapsed = getAudioContextTime() - (playbackStartTimeRef.current ?? 0);\n time = (audioStartPositionRef.current ?? 0) + elapsed;\n } else {\n time = currentTimeRef.current ?? 0;\n }\n const pos = time * sampleRate / samplesPerPixel + controlsOffset;\n containerRef.current.style.transform = `translate3d(${pos}px, 0, 0)`;\n }\n if (isPlaying) {\n animationFrameRef.current = requestAnimationFrame(updatePosition);\n }\n };\n if (isPlaying) {\n animationFrameRef.current = requestAnimationFrame(updatePosition);\n } else {\n updatePosition();\n }\n return () => {\n if (animationFrameRef.current) {\n cancelAnimationFrame(animationFrameRef.current);\n animationFrameRef.current = null;\n }\n };\n }, [isPlaying, sampleRate, samplesPerPixel, controlsOffset, currentTimeRef, playbackStartTimeRef, audioStartPositionRef, getAudioContextTime]);\n useEffect(() => {\n if (!isPlaying && containerRef.current) {\n const time = currentTimeRef.current ?? 0;\n const pos = time * sampleRate / samplesPerPixel + controlsOffset;\n containerRef.current.style.transform = `translate3d(${pos}px, 0, 0)`;\n }\n });\n return /* @__PURE__ */ jsxs4(PlayheadWithMarkerContainer, { ref: containerRef, $color: color, children: [\n /* @__PURE__ */ jsx9(MarkerTriangle, { $color: color }),\n /* @__PURE__ */ jsx9(MarkerLine, { $color: color })\n ] });\n};\n\n// src/components/Playlist.tsx\nimport styled16, { withTheme } from \"styled-components\";\nimport { jsx as jsx10, jsxs as jsxs5 } from \"react/jsx-runtime\";\nvar Wrapper2 = styled16.div`\n overflow-y: hidden;\n overflow-x: auto;\n position: relative;\n`;\nvar ScrollContainer = styled16.div.attrs((props) => ({\n style: props.$width !== void 0 ? { width: `${props.$width}px` } : {}\n}))`\n position: relative;\n background: ${(props) => props.$backgroundColor || \"transparent\"};\n`;\nvar TimescaleWrapper = styled16.div.attrs((props) => ({\n style: props.$width ? { minWidth: `${props.$width}px` } : {}\n}))`\n background: ${(props) => props.$backgroundColor || \"white\"};\n width: 100%;\n position: relative;\n overflow: hidden; /* Constrain loop region to timescale area */\n`;\nvar TracksContainer = styled16.div.attrs((props) => ({\n style: props.$width !== void 0 ? { minWidth: `${props.$width}px` } : {}\n}))`\n position: relative;\n background: ${(props) => props.$backgroundColor || \"transparent\"};\n width: 100%;\n`;\nvar ClickOverlay = styled16.div`\n position: absolute;\n top: 0;\n left: 0;\n right: 0;\n bottom: 0;\n cursor: crosshair;\n /* When selecting, raise z-index above clip boundaries (z-index: 105) to prevent interference */\n z-index: ${(props) => props.$isSelecting ? 110 : 1};\n`;\nvar Playlist = ({\n children,\n backgroundColor,\n timescaleBackgroundColor,\n timescale,\n timescaleWidth,\n tracksWidth,\n scrollContainerWidth,\n controlsWidth,\n onTracksClick,\n onTracksMouseDown,\n onTracksMouseMove,\n onTracksMouseUp,\n scrollContainerRef,\n isSelecting\n}) => {\n return /* @__PURE__ */ jsx10(Wrapper2, { \"data-scroll-container\": \"true\", ref: scrollContainerRef, children: /* @__PURE__ */ jsxs5(\n ScrollContainer,\n {\n $backgroundColor: backgroundColor,\n $width: scrollContainerWidth,\n children: [\n timescale && /* @__PURE__ */ jsx10(TimescaleWrapper, { $width: timescaleWidth, $backgroundColor: timescaleBackgroundColor, children: timescale }),\n /* @__PURE__ */ jsxs5(TracksContainer, { $width: tracksWidth, $backgroundColor: backgroundColor, children: [\n children,\n (onTracksClick || onTracksMouseDown) && /* @__PURE__ */ jsx10(\n ClickOverlay,\n {\n $controlsWidth: controlsWidth,\n $isSelecting: isSelecting,\n onClick: onTracksClick,\n onMouseDown: onTracksMouseDown,\n onMouseMove: onTracksMouseMove,\n onMouseUp: onTracksMouseUp\n }\n )\n ] })\n ]\n }\n ) });\n};\nvar StyledPlaylist = withTheme(Playlist);\n\n// src/components/Selection.tsx\nimport styled17 from \"styled-components\";\nimport { jsx as jsx11 } from \"react/jsx-runtime\";\nvar SelectionOverlay = styled17.div.attrs((props) => ({\n style: {\n left: `${props.$left}px`,\n width: `${props.$width}px`\n }\n}))`\n position: absolute;\n top: 0;\n background: ${(props) => props.$color};\n height: 100%;\n z-index: 60; /* Above clips (z-index: 10) and fades (z-index: 50), below playhead (z-index: 100) */\n pointer-events: none;\n opacity: 0.3;\n`;\nvar Selection = ({\n startPosition,\n endPosition,\n color = \"#00ff00\"\n}) => {\n const width = Math.max(0, endPosition - startPosition);\n if (width <= 0) {\n return null;\n }\n return /* @__PURE__ */ jsx11(SelectionOverlay, { $left: startPosition, $width: width, $color: color, \"data-selection\": true });\n};\n\n// src/components/LoopRegion.tsx\nimport { useCallback as useCallback2, useRef as useRef3, useState } from \"react\";\nimport styled18 from \"styled-components\";\nimport { Fragment as Fragment2, jsx as jsx12, jsxs as jsxs6 } from \"react/jsx-runtime\";\nvar LoopRegionOverlayDiv = styled18.div.attrs((props) => ({\n style: {\n left: `${props.$left}px`,\n width: `${props.$width}px`\n }\n}))`\n position: absolute;\n top: 0;\n background: ${(props) => props.$color};\n height: 100%;\n z-index: 55; /* Between clips (z-index: 50) and selection (z-index: 60) */\n pointer-events: none;\n`;\nvar LoopMarker = styled18.div.attrs((props) => ({\n style: {\n left: `${props.$left}px`\n }\n}))`\n position: absolute;\n top: 0;\n width: 2px;\n height: 100%;\n background: ${(props) => props.$color};\n z-index: 90; /* Below playhead (z-index: 100) */\n pointer-events: none;\n\n /* Triangle marker at top */\n &::before {\n content: '';\n position: absolute;\n top: 0;\n ${(props) => props.$isStart ? \"left: 0\" : \"right: 0\"};\n width: 0;\n height: 0;\n border-top: 8px solid ${(props) => props.$color};\n ${(props) => props.$isStart ? \"border-right: 8px solid transparent;\" : \"border-left: 8px solid transparent;\"}\n }\n`;\nvar LoopRegion = ({\n startPosition,\n endPosition,\n regionColor = \"rgba(59, 130, 246, 0.3)\",\n markerColor = \"#3b82f6\"\n}) => {\n const width = Math.max(0, endPosition - startPosition);\n if (width <= 0) {\n return null;\n }\n return /* @__PURE__ */ jsxs6(Fragment2, { children: [\n /* @__PURE__ */ jsx12(\n LoopRegionOverlayDiv,\n {\n $left: startPosition,\n $width: width,\n $color: regionColor,\n \"data-loop-region\": true\n }\n ),\n /* @__PURE__ */ jsx12(\n LoopMarker,\n {\n $left: startPosition,\n $color: markerColor,\n $isStart: true,\n \"data-loop-marker\": \"start\"\n }\n ),\n /* @__PURE__ */ jsx12(\n LoopMarker,\n {\n $left: endPosition - 2,\n $color: markerColor,\n $isStart: false,\n \"data-loop-marker\": \"end\"\n }\n )\n ] });\n};\nvar DraggableMarkerHandle = styled18.div.attrs((props) => ({\n style: {\n left: `${props.$left}px`\n }\n}))`\n position: absolute;\n top: 0;\n width: 12px;\n height: 100%;\n cursor: ew-resize;\n z-index: 100;\n /* Center the handle on the marker position */\n transform: translateX(-5px);\n\n /* Visual marker line */\n &::before {\n content: '';\n position: absolute;\n top: 0;\n left: 5px;\n width: 2px;\n height: 100%;\n background: ${(props) => props.$color};\n opacity: ${(props) => props.$isDragging ? 1 : 0.8};\n }\n\n /* Triangle marker at top */\n &::after {\n content: '';\n position: absolute;\n top: 0;\n ${(props) => props.$isStart ? \"left: 5px\" : \"left: -1px\"};\n width: 0;\n height: 0;\n border-top: 10px solid ${(props) => props.$color};\n ${(props) => props.$isStart ? \"border-right: 10px solid transparent;\" : \"border-left: 10px solid transparent;\"}\n }\n\n &:hover::before {\n opacity: 1;\n }\n`;\nvar TimescaleLoopShade = styled18.div.attrs((props) => ({\n style: {\n left: `${props.$left}px`,\n width: `${props.$width}px`\n }\n}))`\n position: absolute;\n top: 0;\n height: 100%;\n background: ${(props) => props.$color};\n z-index: 50;\n cursor: grab;\n\n &:active {\n cursor: grabbing;\n }\n`;\nvar LoopRegionMarkers = ({\n startPosition,\n endPosition,\n markerColor = \"#3b82f6\",\n regionColor = \"rgba(59, 130, 246, 0.3)\",\n onLoopStartChange,\n onLoopEndChange,\n onLoopRegionMove,\n minPosition = 0,\n maxPosition = Infinity\n}) => {\n const [draggingMarker, setDraggingMarker] = useState(null);\n const dragStartX = useRef3(0);\n const dragStartPosition = useRef3(0);\n const dragStartEnd = useRef3(0);\n const width = Math.max(0, endPosition - startPosition);\n const handleMarkerMouseDown = useCallback2((e, marker) => {\n e.preventDefault();\n e.stopPropagation();\n setDraggingMarker(marker);\n dragStartX.current = e.clientX;\n dragStartPosition.current = marker === \"start\" ? startPosition : endPosition;\n const handleMouseMove = (moveEvent) => {\n const delta = moveEvent.clientX - dragStartX.current;\n const newPosition = dragStartPosition.current + delta;\n if (marker === \"start\") {\n const clampedPosition = Math.max(minPosition, Math.min(endPosition - 10, newPosition));\n onLoopStartChange?.(clampedPosition);\n } else {\n const clampedPosition = Math.max(startPosition + 10, Math.min(maxPosition, newPosition));\n onLoopEndChange?.(clampedPosition);\n }\n };\n const handleMouseUp = () => {\n setDraggingMarker(null);\n document.removeEventListener(\"mousemove\", handleMouseMove);\n document.removeEventListener(\"mouseup\", handleMouseUp);\n };\n document.addEventListener(\"mousemove\", handleMouseMove);\n document.addEventListener(\"mouseup\", handleMouseUp);\n }, [startPosition, endPosition, minPosition, maxPosition, onLoopStartChange, onLoopEndChange]);\n const handleRegionMouseDown = useCallback2((e) => {\n e.preventDefault();\n e.stopPropagation();\n setDraggingMarker(\"region\");\n dragStartX.current = e.clientX;\n dragStartPosition.current = startPosition;\n dragStartEnd.current = endPosition;\n const regionWidth = endPosition - startPosition;\n const handleMouseMove = (moveEvent) => {\n const delta = moveEvent.clientX - dragStartX.current;\n let newStart = dragStartPosition.current + delta;\n let newEnd = dragStartEnd.current + delta;\n if (newStart < minPosition) {\n newStart = minPosition;\n newEnd = minPosition + regionWidth;\n }\n if (newEnd > maxPosition) {\n newEnd = maxPosition;\n newStart = maxPosition - regionWidth;\n }\n onLoopRegionMove?.(newStart, newEnd);\n };\n const handleMouseUp = () => {\n setDraggingMarker(null);\n document.removeEventListener(\"mousemove\", handleMouseMove);\n document.removeEventListener(\"mouseup\", handleMouseUp);\n };\n document.addEventListener(\"mousemove\", handleMouseMove);\n document.addEventListener(\"mouseup\", handleMouseUp);\n }, [startPosition, endPosition, minPosition, maxPosition, onLoopRegionMove]);\n if (width <= 0) {\n return null;\n }\n return /* @__PURE__ */ jsxs6(Fragment2, { children: [\n /* @__PURE__ */ jsx12(\n TimescaleLoopShade,\n {\n $left: startPosition,\n $width: width,\n $color: regionColor,\n $isDragging: draggingMarker === \"region\",\n onMouseDown: handleRegionMouseDown,\n \"data-loop-region-timescale\": true\n }\n ),\n /* @__PURE__ */ jsx12(\n DraggableMarkerHandle,\n {\n $left: startPosition,\n $color: markerColor,\n $isStart: true,\n $isDragging: draggingMarker === \"start\",\n onMouseDown: (e) => handleMarkerMouseDown(e, \"start\"),\n \"data-loop-marker-handle\": \"start\"\n }\n ),\n /* @__PURE__ */ jsx12(\n DraggableMarkerHandle,\n {\n $left: endPosition,\n $color: markerColor,\n $isStart: false,\n $isDragging: draggingMarker === \"end\",\n onMouseDown: (e) => handleMarkerMouseDown(e, \"end\"),\n \"data-loop-marker-handle\": \"end\"\n }\n )\n ] });\n};\nvar TimescaleLoopCreator = styled18.div.attrs((props) => ({\n style: {\n left: `${props.$leftOffset || 0}px`\n }\n}))`\n position: absolute;\n top: 0;\n right: 0;\n height: 100%; /* Stay within timescale bounds, don't extend into tracks */\n cursor: crosshair;\n z-index: 40; /* Below markers and shading */\n`;\nvar TimescaleLoopRegion = ({\n startPosition,\n endPosition,\n markerColor = \"#3b82f6\",\n regionColor = \"rgba(59, 130, 246, 0.3)\",\n onLoopRegionChange,\n minPosition = 0,\n maxPosition = Infinity,\n controlsOffset = 0\n}) => {\n const [isCreating, setIsCreating] = useState(false);\n const createStartX = useRef3(0);\n const containerRef = useRef3(null);\n const hasLoopRegion = endPosition > startPosition;\n const handleBackgroundMouseDown = useCallback2((e) => {\n const target = e.target;\n if (target.closest(\"[data-loop-marker-handle]\") || target.closest(\"[data-loop-region-timescale]\")) {\n return;\n }\n e.preventDefault();\n setIsCreating(true);\n const rect = containerRef.current?.getBoundingClientRect();\n if (!rect) return;\n const clickX = e.clientX - rect.left;\n const clampedX = Math.max(minPosition, Math.min(maxPosition, clickX));\n createStartX.current = clampedX;\n onLoopRegionChange?.(clampedX, clampedX);\n const handleMouseMove = (moveEvent) => {\n const currentX = moveEvent.clientX - rect.left;\n const clampedCurrentX = Math.max(minPosition, Math.min(maxPosition, currentX));\n const newStart = Math.min(createStartX.current, clampedCurrentX);\n const newEnd = Math.max(createStartX.current, clampedCurrentX);\n onLoopRegionChange?.(newStart, newEnd);\n };\n const handleMouseUp = () => {\n setIsCreating(false);\n document.removeEventListener(\"mousemove\", handleMouseMove);\n document.removeEventListener(\"mouseup\", handleMouseUp);\n };\n document.addEventListener(\"mousemove\", handleMouseMove);\n document.addEventListener(\"mouseup\", handleMouseUp);\n }, [minPosition, maxPosition, onLoopRegionChange]);\n return /* @__PURE__ */ jsx12(\n TimescaleLoopCreator,\n {\n ref: containerRef,\n $leftOffset: controlsOffset,\n onMouseDown: handleBackgroundMouseDown,\n \"data-timescale-loop-creator\": true,\n children: hasLoopRegion && /* @__PURE__ */ jsx12(\n LoopRegionMarkers,\n {\n startPosition,\n endPosition,\n markerColor,\n regionColor,\n minPosition,\n maxPosition,\n onLoopStartChange: (newStart) => onLoopRegionChange?.(newStart, endPosition),\n onLoopEndChange: (newEnd) => onLoopRegionChange?.(startPosition, newEnd),\n onLoopRegionMove: (newStart, newEnd) => onLoopRegionChange?.(newStart, newEnd)\n }\n )\n }\n );\n};\n\n// src/components/SelectionTimeInputs.tsx\nimport { useEffect as useEffect3, useState as useState3 } from \"react\";\n\n// src/components/TimeInput.tsx\nimport { useEffect as useEffect2, useState as useState2 } from \"react\";\n\n// src/utils/timeFormat.ts\nfunction clockFormat(seconds, decimals) {\n const hours = Math.floor(seconds / 3600) % 24;\n const minutes = Math.floor(seconds / 60) % 60;\n const secs = (seconds % 60).toFixed(decimals);\n return String(hours).padStart(2, \"0\") + \":\" + String(minutes).padStart(2, \"0\") + \":\" + secs.padStart(decimals + 3, \"0\");\n}\nfunction formatTime(seconds, format) {\n switch (format) {\n case \"seconds\":\n return seconds.toFixed(0);\n case \"thousandths\":\n return seconds.toFixed(3);\n case \"hh:mm:ss\":\n return clockFormat(seconds, 0);\n case \"hh:mm:ss.u\":\n return clockFormat(seconds, 1);\n case \"hh:mm:ss.uu\":\n return clockFormat(seconds, 2);\n case \"hh:mm:ss.uuu\":\n return clockFormat(seconds, 3);\n default:\n return clockFormat(seconds, 3);\n }\n}\nfunction parseTime(timeStr, format) {\n if (!timeStr) return 0;\n switch (format) {\n case \"seconds\":\n case \"thousandths\":\n return parseFloat(timeStr) || 0;\n case \"hh:mm:ss\":\n case \"hh:mm:ss.u\":\n case \"hh:mm:ss.uu\":\n case \"hh:mm:ss.uuu\": {\n const parts = timeStr.split(\":\");\n if (parts.length !== 3) return 0;\n const hours = parseInt(parts[0], 10) || 0;\n const minutes = parseInt(parts[1], 10) || 0;\n const seconds = parseFloat(parts[2]) || 0;\n return hours * 3600 + minutes * 60 + seconds;\n }\n default:\n return 0;\n }\n}\n\n// src/components/TimeInput.tsx\nimport { Fragment as Fragment3, jsx as jsx13, jsxs as jsxs7 } from \"react/jsx-runtime\";\nvar TimeInput = ({\n id,\n label,\n value,\n format,\n className,\n onChange,\n readOnly = false\n}) => {\n const [displayValue, setDisplayValue] = useState2(\"\");\n useEffect2(() => {\n const formatted = formatTime(value, format);\n setDisplayValue(formatted);\n }, [value, format, id]);\n const handleChange = (e) => {\n const newDisplayValue = e.target.value;\n setDisplayValue(newDisplayValue);\n };\n const handleBlur = () => {\n if (onChange) {\n const parsedValue = parseTime(displayValue, format);\n onChange(parsedValue);\n }\n setDisplayValue(formatTime(value, format));\n };\n const handleKeyDown = (e) => {\n if (e.key === \"Enter\") {\n e.currentTarget.blur();\n }\n };\n return /* @__PURE__ */ jsxs7(Fragment3, { children: [\n /* @__PURE__ */ jsx13(ScreenReaderOnly, { as: \"label\", htmlFor: id, children: label }),\n /* @__PURE__ */ jsx13(\n BaseInput,\n {\n type: \"text\",\n className,\n id,\n value: displayValue,\n onChange: handleChange,\n onBlur: handleBlur,\n onKeyDown: handleKeyDown,\n readOnly\n }\n )\n ] });\n};\n\n// src/components/SelectionTimeInputs.tsx\nimport { Fragment as Fragment4, jsx as jsx14, jsxs as jsxs8 } from \"react/jsx-runtime\";\nvar SelectionTimeInputs = ({\n selectionStart,\n selectionEnd,\n onSelectionChange,\n className\n}) => {\n const [timeFormat, setTimeFormat] = useState3(\"hh:mm:ss.uuu\");\n useEffect3(() => {\n const timeFormatSelect = document.querySelector(\".time-format\");\n const handleFormatChange = () => {\n if (timeFormatSelect) {\n setTimeFormat(timeFormatSelect.value);\n }\n };\n if (timeFormatSelect) {\n setTimeFormat(timeFormatSelect.value);\n timeFormatSelect.addEventListener(\"change\", handleFormatChange);\n }\n return () => {\n timeFormatSelect?.removeEventListener(\"change\", handleFormatChange);\n };\n }, []);\n const handleStartChange = (value) => {\n if (onSelectionChange) {\n onSelectionChange(value, selectionEnd);\n }\n };\n const handleEndChange = (value) => {\n if (onSelectionChange) {\n onSelectionChange(selectionStart, value);\n }\n };\n return /* @__PURE__ */ jsxs8(Fragment4, { children: [\n /* @__PURE__ */ jsx14(\n TimeInput,\n {\n id: \"audio_start\",\n label: \"Start of audio selection\",\n value: selectionStart,\n format: timeFormat,\n className: \"audio-start form-control mr-sm-2\",\n onChange: handleStartChange\n }\n ),\n /* @__PURE__ */ jsx14(\n TimeInput,\n {\n id: \"audio_end\",\n label: \"End of audio selection\",\n value: selectionEnd,\n format: timeFormat,\n className: \"audio-end form-control mr-sm-2\",\n onChange: handleEndChange\n }\n )\n ] });\n};\n\n// src/contexts/DevicePixelRatio.tsx\nimport { useState as useState4, createContext, useContext } from \"react\";\nimport { jsx as jsx15 } from \"react/jsx-runtime\";\nfunction getScale() {\n return window.devicePixelRatio;\n}\nvar DevicePixelRatioContext = createContext(getScale());\nvar DevicePixelRatioProvider = ({ children }) => {\n const [scale, setScale] = useState4(getScale());\n matchMedia(`(resolution: ${getScale()}dppx)`).addEventListener(\n \"change\",\n () => {\n setScale(getScale());\n },\n { once: true }\n );\n return /* @__PURE__ */ jsx15(DevicePixelRatioContext.Provider, { value: Math.ceil(scale), children });\n};\nvar useDevicePixelRatio = () => useContext(DevicePixelRatioContext);\n\n// src/contexts/PlaylistInfo.tsx\nimport { createContext as createContext2, useContext as useContext2 } from \"react\";\nvar PlaylistInfoContext = createContext2({\n sampleRate: 48e3,\n samplesPerPixel: 1e3,\n zoomLevels: [1e3, 1500, 2e3, 2500],\n waveHeight: 80,\n timeScaleHeight: 15,\n controls: {\n show: false,\n width: 150\n },\n duration: 3e4,\n barWidth: 1,\n barGap: 0\n});\nvar usePlaylistInfo = () => useContext2(PlaylistInfoContext);\n\n// src/contexts/Theme.tsx\nimport { useContext as useContext3 } from \"react\";\nimport { ThemeContext } from \"styled-components\";\nvar useTheme2 = () => useContext3(ThemeContext);\n\n// src/contexts/TrackControls.tsx\nimport { createContext as createContext3, useContext as useContext4, Fragment as Fragment5 } from \"react\";\nimport { jsx as jsx16 } from \"react/jsx-runtime\";\nvar TrackControlsContext = createContext3(/* @__PURE__ */ jsx16(Fragment5, {}));\nvar useTrackControls = () => useContext4(TrackControlsContext);\n\n// src/contexts/Playout.tsx\nimport {\n useState as useState5,\n createContext as createContext4,\n useContext as useContext5\n} from \"react\";\nimport { jsx as jsx17 } from \"react/jsx-runtime\";\nvar defaultProgress = 0;\nvar defaultIsPlaying = false;\nvar defaultSelectionStart = 0;\nvar defaultSelectionEnd = 0;\nvar defaultPlayout = {\n progress: defaultProgress,\n isPlaying: defaultIsPlaying,\n selectionStart: defaultSelectionStart,\n selectionEnd: defaultSelectionEnd\n};\nvar PlayoutStatusContext = createContext4(defaultPlayout);\nvar PlayoutStatusUpdateContext = createContext4({\n setIsPlaying: () => {\n },\n setProgress: () => {\n },\n setSelection: () => {\n }\n});\nvar PlayoutProvider = ({ children }) => {\n const [isPlaying, setIsPlaying] = useState5(defaultIsPlaying);\n const [progress, setProgress] = useState5(defaultProgress);\n const [selectionStart, setSelectionStart] = useState5(defaultSelectionStart);\n const [selectionEnd, setSelectionEnd] = useState5(defaultSelectionEnd);\n const setSelection = (start, end) => {\n setSelectionStart(start);\n setSelectionEnd(end);\n };\n return /* @__PURE__ */ jsx17(PlayoutStatusUpdateContext.Provider, { value: { setIsPlaying, setProgress, setSelection }, children: /* @__PURE__ */ jsx17(PlayoutStatusContext.Provider, { value: { isPlaying, progress, selectionStart, selectionEnd }, children }) });\n};\nvar usePlayoutStatus = () => useContext5(PlayoutStatusContext);\nvar usePlayoutStatusUpdate = () => useContext5(PlayoutStatusUpdateContext);\n\n// src/components/SmartChannel.tsx\nimport { jsx as jsx18 } from \"react/jsx-runtime\";\nvar SmartChannel = ({ isSelected, transparentBackground, ...props }) => {\n const theme = useTheme2();\n const { waveHeight, barWidth, barGap } = usePlaylistInfo();\n const devicePixelRatio = useDevicePixelRatio();\n const waveOutlineColor = isSelected && theme ? theme.selectedWaveOutlineColor : theme?.waveOutlineColor;\n const waveFillColor = isSelected && theme ? theme.selectedWaveFillColor : theme?.waveFillColor;\n const drawMode = theme?.waveformDrawMode || \"inverted\";\n return /* @__PURE__ */ jsx18(\n Channel,\n {\n ...props,\n ...theme,\n waveOutlineColor,\n waveFillColor,\n waveHeight,\n devicePixelRatio,\n barWidth,\n barGap,\n transparentBackground,\n drawMode\n }\n );\n};\n\n// src/components/SmartScale.tsx\nimport { useContext as useContext7 } from \"react\";\n\n// src/components/TimeScale.tsx\nimport React10, { useRef as useRef4, useEffect as useEffect4, useContext as useContext6 } from \"react\";\nimport styled19, { withTheme as withTheme2 } from \"styled-components\";\n\n// src/utils/conversions.ts\nfunction samplesToSeconds(samples, sampleRate) {\n return samples / sampleRate;\n}\nfunction secondsToSamples(seconds, sampleRate) {\n return Math.ceil(seconds * sampleRate);\n}\nfunction samplesToPixels(samples, samplesPerPixel) {\n return Math.floor(samples / samplesPerPixel);\n}\nfunction pixelsToSamples(pixels, samplesPerPixel) {\n return Math.floor(pixels * samplesPerPixel);\n}\nfunction pixelsToSeconds(pixels, samplesPerPixel, sampleRate) {\n return pixels * samplesPerPixel / sampleRate;\n}\nfunction secondsToPixels(seconds, samplesPerPixel, sampleRate) {\n return Math.ceil(seconds * sampleRate / samplesPerPixel);\n}\n\n// src/components/TimeScale.tsx\nimport { jsx as jsx19, jsxs as jsxs9 } from \"react/jsx-runtime\";\nfunction formatTime2(milliseconds) {\n const seconds = Math.floor(milliseconds / 1e3);\n const s = seconds % 60;\n const m = (seconds - s) / 60;\n return `${m}:${String(s).padStart(2, \"0\")}`;\n}\nvar PlaylistTimeScaleScroll = styled19.div.attrs((props) => ({\n style: {\n width: `${props.$cssWidth}px`,\n marginLeft: `${props.$controlWidth}px`,\n height: `${props.$timeScaleHeight}px`\n }\n}))`\n position: relative;\n overflow: visible; /* Allow time labels to render above the container */\n border-bottom: 1px solid ${(props) => props.theme.timeColor};\n box-sizing: border-box;\n`;\nvar TimeTicks = styled19.canvas.attrs((props) => ({\n style: {\n width: `${props.$cssWidth}px`,\n height: `${props.$timeScaleHeight}px`\n }\n}))`\n position: absolute;\n left: 0;\n right: 0;\n bottom: 0;\n`;\nvar TimeStamp = styled19.div.attrs((props) => ({\n style: {\n left: `${props.$left + 4}px`\n // Offset 4px to the right of the tick\n }\n}))`\n position: absolute;\n font-size: 0.75rem; /* Smaller font to prevent overflow */\n white-space: nowrap; /* Prevent text wrapping */\n color: ${(props) => props.theme.timeColor}; /* Use theme color instead of inheriting */\n`;\nvar TimeScale = (props) => {\n const {\n theme: { timeColor },\n duration,\n marker,\n bigStep,\n secondStep,\n renderTimestamp\n } = props;\n const canvasInfo = /* @__PURE__ */ new Map();\n const timeMarkers = [];\n const canvasRef = useRef4(null);\n const {\n sampleRate,\n samplesPerPixel,\n timeScaleHeight,\n controls: { show: showControls, width: controlWidth }\n } = useContext6(PlaylistInfoContext);\n const devicePixelRatio = useDevicePixelRatio();\n useEffect4(() => {\n if (canvasRef.current !== null) {\n const canvas = canvasRef.current;\n const ctx = canvas.getContext(\"2d\");\n if (ctx) {\n ctx.resetTransform();\n ctx.clearRect(0, 0, canvas.width, canvas.height);\n ctx.imageSmoothingEnabled = false;\n ctx.fillStyle = timeColor;\n ctx.scale(devicePixelRatio, devicePixelRatio);\n for (const [pixLeft, scaleHeight] of canvasInfo.entries()) {\n const scaleY = timeScaleHeight - scaleHeight;\n ctx.fillRect(pixLeft, scaleY, 1, scaleHeight);\n }\n }\n }\n }, [\n duration,\n devicePixelRatio,\n timeColor,\n timeScaleHeight,\n bigStep,\n secondStep,\n marker,\n canvasInfo\n ]);\n const widthX = secondsToPixels(duration / 1e3, samplesPerPixel, sampleRate);\n const pixPerSec = sampleRate / samplesPerPixel;\n let counter = 0;\n for (let i = 0; i < widthX; i += pixPerSec * secondStep / 1e3) {\n const pix = Math.floor(i);\n if (counter % marker === 0) {\n const timeMs = counter;\n const timestamp = formatTime2(timeMs);\n const timestampContent = renderTimestamp ? /* @__PURE__ */ jsx19(React10.Fragment, { children: renderTimestamp(timeMs, pix) }, `timestamp-${counter}`) : /* @__PURE__ */ jsx19(TimeStamp, { $left: pix, children: timestamp }, timestamp);\n timeMarkers.push(timestampContent);\n canvasInfo.set(pix, timeScaleHeight);\n } else if (counter % bigStep === 0) {\n canvasInfo.set(pix, Math.floor(timeScaleHeight / 2));\n } else if (counter % secondStep === 0) {\n canvasInfo.set(pix, Math.floor(timeScaleHeight / 5));\n }\n counter += secondStep;\n }\n return /* @__PURE__ */ jsxs9(\n PlaylistTimeScaleScroll,\n {\n $cssWidth: widthX,\n $controlWidth: showControls ? controlWidth : 0,\n $timeScaleHeight: timeScaleHeight,\n children: [\n timeMarkers,\n /* @__PURE__ */ jsx19(\n TimeTicks,\n {\n $cssWidth: widthX,\n $timeScaleHeight: timeScaleHeight,\n width: widthX * devicePixelRatio,\n height: timeScaleHeight * devicePixelRatio,\n ref: canvasRef\n }\n )\n ]\n }\n );\n};\nvar StyledTimeScale = withTheme2(TimeScale);\n\n// src/components/SmartScale.tsx\nimport { jsx as jsx20 } from \"react/jsx-runtime\";\nvar timeinfo = /* @__PURE__ */ new Map([\n [\n 700,\n {\n marker: 1e3,\n bigStep: 500,\n smallStep: 100\n }\n ],\n [\n 1500,\n {\n marker: 2e3,\n bigStep: 1e3,\n smallStep: 200\n }\n ],\n [\n 2500,\n {\n marker: 2e3,\n bigStep: 1e3,\n smallStep: 500\n }\n ],\n [\n 5e3,\n {\n marker: 5e3,\n bigStep: 1e3,\n smallStep: 500\n }\n ],\n [\n 1e4,\n {\n marker: 1e4,\n bigStep: 5e3,\n smallStep: 1e3\n }\n ],\n [\n 12e3,\n {\n marker: 15e3,\n bigStep: 5e3,\n smallStep: 1e3\n }\n ],\n [\n Infinity,\n {\n marker: 3e4,\n bigStep: 1e4,\n smallStep: 5e3\n }\n ]\n]);\nfunction getScaleInfo(samplesPerPixel) {\n const keys = timeinfo.keys();\n let config;\n for (const resolution of keys) {\n if (samplesPerPixel < resolution) {\n config = timeinfo.get(resolution);\n break;\n }\n }\n if (config === void 0) {\n config = { marker: 3e4, bigStep: 1e4, smallStep: 5e3 };\n }\n return config;\n}\nvar SmartScale = () => {\n const { samplesPerPixel, duration } = useContext7(PlaylistInfoContext);\n let config = getScaleInfo(samplesPerPixel);\n return /* @__PURE__ */ jsx20(\n StyledTimeScale,\n {\n marker: config.marker,\n bigStep: config.bigStep,\n secondStep: config.smallStep,\n duration\n }\n );\n};\n\n// src/components/TimeFormatSelect.tsx\nimport styled20 from \"styled-components\";\nimport { jsx as jsx21 } from \"react/jsx-runtime\";\nvar SelectWrapper = styled20.div`\n display: inline-flex;\n align-items: center;\n gap: 0.5rem;\n`;\nvar TIME_FORMAT_OPTIONS = [\n { value: \"seconds\", label: \"seconds\" },\n { value: \"thousandths\", label: \"thousandths\" },\n { value: \"hh:mm:ss\", label: \"hh:mm:ss\" },\n { value: \"hh:mm:ss.u\", label: \"hh:mm:ss + tenths\" },\n { value: \"hh:mm:ss.uu\", label: \"hh:mm:ss + hundredths\" },\n { value: \"hh:mm:ss.uuu\", label: \"hh:mm:ss + milliseconds\" }\n];\nvar TimeFormatSelect = ({\n value,\n onChange,\n disabled = false,\n className\n}) => {\n const handleChange = (e) => {\n onChange(e.target.value);\n };\n return /* @__PURE__ */ jsx21(SelectWrapper, { className, children: /* @__PURE__ */ jsx21(\n BaseSelect,\n {\n className: \"time-format\",\n value,\n onChange: handleChange,\n disabled,\n \"aria-label\": \"Time format selection\",\n children: TIME_FORMAT_OPTIONS.map((option) => /* @__PURE__ */ jsx21(\"option\", { value: option.value, children: option.label }, option.value))\n }\n ) });\n};\n\n// src/components/Track.tsx\nimport styled21 from \"styled-components\";\nimport { jsx as jsx22, jsxs as jsxs10 } from \"react/jsx-runtime\";\nvar Container = styled21.div.attrs((props) => ({\n style: {\n height: `${props.$waveHeight * props.$numChannels + (props.$hasClipHeaders ? CLIP_HEADER_HEIGHT : 0)}px`\n }\n}))`\n position: relative;\n display: flex;\n ${(props) => props.$width !== void 0 && `width: ${props.$width}px;`}\n`;\nvar ChannelContainer = styled21.div.attrs((props) => ({\n style: {\n paddingLeft: `${props.$offset || 0}px`\n }\n}))`\n position: relative;\n background: ${(props) => props.$backgroundColor || \"transparent\"};\n flex: 1;\n`;\nvar ControlsWrapper = styled21.div.attrs((props) => ({\n style: {\n width: `${props.$controlWidth}px`\n }\n}))`\n position: sticky;\n z-index: 101; /* Above waveform content, below Docusaurus navbar (z-index: 200) */\n left: 0;\n height: 100%;\n flex-shrink: 0;\n pointer-events: auto;\n background: ${(props) => props.theme.surfaceColor};\n transition: background 0.15s ease-in-out;\n\n /* Selected track: highlighted background */\n ${(props) => props.$isSelected && `\n background: ${props.theme.selectedTrackControlsBackground};\n `}\n`;\nvar Track = ({\n numChannels,\n children,\n className,\n backgroundColor,\n offset = 0,\n width,\n hasClipHeaders = false,\n onClick,\n trackId,\n isSelected = false\n}) => {\n const {\n waveHeight,\n controls: { show, width: controlWidth }\n } = usePlaylistInfo();\n const controls = useTrackControls();\n return /* @__PURE__ */ jsxs10(\n Container,\n {\n $numChannels: numChannels,\n className,\n $waveHeight: waveHeight,\n $controlWidth: show ? controlWidth : 0,\n $width: width,\n $hasClipHeaders: hasClipHeaders,\n $isSelected: isSelected,\n children: [\n /* @__PURE__ */ jsx22(\n ControlsWrapper,\n {\n $controlWidth: show ? controlWidth : 0,\n $isSelected: isSelected,\n children: controls\n }\n ),\n /* @__PURE__ */ jsx22(\n ChannelContainer,\n {\n $controlWidth: show ? controlWidth : 0,\n $backgroundColor: backgroundColor,\n $offset: offset,\n onClick,\n \"data-track-id\": trackId,\n children\n }\n )\n ]\n }\n );\n};\n\n// src/components/TrackControls/Button.tsx\nimport styled22 from \"styled-components\";\nvar Button = styled22.button.attrs({\n type: \"button\"\n})`\n display: inline-block;\n font-family: ${(props) => props.theme.fontFamily};\n font-weight: 500;\n text-align: center;\n vertical-align: middle;\n user-select: none;\n padding: 0.25rem 0.4rem;\n font-size: ${(props) => props.theme.fontSizeSmall};\n line-height: 1;\n border-radius: ${(props) => props.theme.borderRadius};\n transition: color 0.15s ease-in-out, background-color 0.15s ease-in-out,\n border-color 0.15s ease-in-out, box-shadow 0.15s ease-in-out;\n cursor: pointer;\n\n ${(props) => {\n if (props.$variant === \"danger\") {\n return `\n color: #fff;\n background-color: #dc3545;\n border: 1px solid #dc3545;\n\n &:hover {\n background-color: #c82333;\n border-color: #bd2130;\n }\n\n &:focus {\n outline: none;\n box-shadow: 0 0 0 0.2rem rgba(225, 83, 97, 0.5);\n }\n `;\n } else if (props.$variant === \"info\") {\n return `\n color: #fff;\n background-color: #17a2b8;\n border: 1px solid #17a2b8;\n\n &:hover {\n background-color: #138496;\n border-color: #117a8b;\n }\n\n &:focus {\n outline: none;\n box-shadow: 0 0 0 0.2rem rgba(58, 176, 195, 0.5);\n }\n `;\n } else {\n return `\n color: ${props.theme.textColor};\n background-color: transparent;\n border: 1px solid ${props.theme.borderColor};\n\n &:hover {\n color: #fff;\n background-color: ${props.theme.textColor};\n border-color: ${props.theme.textColor};\n }\n\n &:focus {\n outline: none;\n box-shadow: 0 0 0 0.2rem ${props.theme.inputFocusBorder}33;\n }\n `;\n }\n}}\n`;\n\n// src/components/TrackControls/ButtonGroup.tsx\nimport styled23 from \"styled-components\";\nvar ButtonGroup = styled23.div`\n margin-bottom: 0.3rem;\n\n button:not(:first-child) {\n border-top-left-radius: 0;\n border-bottom-left-radius: 0;\n }\n\n button:not(:last-child) {\n border-top-right-radius: 0;\n border-bottom-right-radius: 0;\n }\n`;\n\n// src/components/TrackControls/Controls.tsx\nimport styled24 from \"styled-components\";\nvar Controls = styled24.div`\n background: transparent;\n width: 100%;\n height: 100%;\n display: flex;\n flex-direction: column;\n align-items: center;\n justify-content: flex-start;\n overflow: hidden;\n box-sizing: border-box;\n text-align: center;\n border: 1px solid ${(props) => props.theme.borderColor};\n border-radius: ${(props) => props.theme.borderRadius};\n`;\n\n// src/components/TrackControls/Header.tsx\nimport styled25 from \"styled-components\";\nvar Header = styled25.header`\n overflow: hidden;\n height: 26px;\n width: 100%;\n display: flex;\n align-items: center;\n justify-content: space-between;\n padding: 0 0.2rem;\n font-size: ${(props) => props.theme.fontSizeSmall};\n color: ${(props) => props.theme.textColor};\n background-color: transparent;\n`;\n\n// src/components/TrackControls/VolumeDownIcon.tsx\nimport { SpeakerLowIcon } from \"@phosphor-icons/react\";\nimport { jsx as jsx23 } from \"react/jsx-runtime\";\nvar VolumeDownIcon = (props) => /* @__PURE__ */ jsx23(SpeakerLowIcon, { weight: \"light\", ...props });\n\n// src/components/TrackControls/VolumeUpIcon.tsx\nimport { SpeakerHighIcon } from \"@phosphor-icons/react\";\nimport { jsx as jsx24 } from \"react/jsx-runtime\";\nvar VolumeUpIcon = (props) => /* @__PURE__ */ jsx24(SpeakerHighIcon, { weight: \"light\", ...props });\n\n// src/components/TrackControls/TrashIcon.tsx\nimport { TrashIcon as PhosphorTrashIcon } from \"@phosphor-icons/react\";\nimport { jsx as jsx25 } from \"react/jsx-runtime\";\nvar TrashIcon = (props) => /* @__PURE__ */ jsx25(PhosphorTrashIcon, { weight: \"light\", ...props });\n\n// src/components/TrackControls/Slider.tsx\nimport styled26 from \"styled-components\";\nvar Slider = styled26(BaseSlider)`\n width: 75%;\n height: 5px;\n background: ${(props) => props.theme.sliderTrackColor};\n\n &::-webkit-slider-thumb {\n width: 12px;\n height: 12px;\n background: ${(props) => props.theme.sliderThumbColor};\n border: none;\n margin-top: -4px;\n cursor: ew-resize;\n }\n\n &::-moz-range-thumb {\n width: 12px;\n height: 12px;\n background: ${(props) => props.theme.sliderThumbColor};\n border: none;\n cursor: ew-resize;\n }\n\n &::-webkit-slider-runnable-track {\n height: 5px;\n background: ${(props) => props.theme.sliderTrackColor};\n border-radius: 3px;\n }\n\n &::-moz-range-track {\n height: 5px;\n background: ${(props) => props.theme.sliderTrackColor};\n border-radius: 3px;\n }\n\n &:focus::-webkit-slider-runnable-track {\n background: ${(props) => props.theme.inputBorder};\n }\n\n &:focus::-moz-range-track {\n background: ${(props) => props.theme.inputBorder};\n }\n\n &:focus::-webkit-slider-thumb {\n border: 2px solid ${(props) => props.theme.textColor};\n }\n\n &:focus::-moz-range-thumb {\n border: 2px solid ${(props) => props.theme.textColor};\n }\n`;\n\n// src/components/TrackControls/SliderWrapper.tsx\nimport styled27 from \"styled-components\";\nvar SliderWrapper = styled27.label`\n width: 100%;\n display: flex;\n justify-content: space-between;\n align-items: center;\n padding: 0 1rem;\n margin-bottom: 0.2rem;\n font-size: 14px;\n`;\n\n// src/components/TrackControlsWithDelete.tsx\nimport styled28 from \"styled-components\";\nimport { jsx as jsx26, jsxs as jsxs11 } from \"react/jsx-runtime\";\nvar HeaderContainer2 = styled28.div`\n display: flex;\n align-items: center;\n gap: 0.25rem;\n padding: 0.5rem 0.5rem 0.25rem 0.5rem;\n`;\nvar TrackNameSpan = styled28.span`\n flex: 1;\n font-weight: 600;\n font-size: 0.875rem;\n overflow: hidden;\n text-overflow: ellipsis;\n white-space: nowrap;\n margin: 0 0.25rem;\n`;\nvar DeleteIconButton = styled28.button`\n display: flex;\n align-items: center;\n justify-content: center;\n width: 20px;\n height: 20px;\n padding: 0;\n border: none;\n background: transparent;\n color: #999;\n cursor: pointer;\n font-size: 16px;\n line-height: 1;\n border-radius: 3px;\n transition: all 0.2s ease-in-out;\n flex-shrink: 0;\n\n &:hover {\n background: #dc3545;\n color: white;\n }\n\n &:active {\n transform: scale(0.9);\n }\n`;\nvar TrackControlsWithDelete = ({\n trackName,\n muted,\n soloed,\n volume,\n pan,\n onMuteChange,\n onSoloChange,\n onVolumeChange,\n onPanChange,\n onDelete\n}) => {\n return /* @__PURE__ */ jsxs11(Controls, { children: [\n /* @__PURE__ */ jsxs11(HeaderContainer2, { children: [\n /* @__PURE__ */ jsx26(DeleteIconButton, { onClick: onDelete, title: \"Delete track\", children: /* @__PURE__ */ jsx26(TrashIcon, {}) }),\n /* @__PURE__ */ jsx26(TrackNameSpan, { children: trackName })\n ] }),\n /* @__PURE__ */ jsxs11(ButtonGroup, { children: [\n /* @__PURE__ */ jsx26(\n Button,\n {\n $variant: muted ? \"danger\" : \"outline\",\n onClick: () => onMuteChange(!muted),\n children: \"Mute\"\n }\n ),\n /* @__PURE__ */ jsx26(\n Button,\n {\n $variant: soloed ? \"info\" : \"outline\",\n onClick: () => onSoloChange(!soloed),\n children: \"Solo\"\n }\n )\n ] }),\n /* @__PURE__ */ jsxs11(SliderWrapper, { children: [\n /* @__PURE__ */ jsx26(VolumeDownIcon, {}),\n /* @__PURE__ */ jsx26(\n Slider,\n {\n min: \"0\",\n max: \"1\",\n step: \"0.01\",\n value: volume,\n onChange: (e) => onVolumeChange(parseFloat(e.target.value))\n }\n ),\n /* @__PURE__ */ jsx26(VolumeUpIcon, {})\n ] }),\n /* @__PURE__ */ jsxs11(SliderWrapper, { children: [\n /* @__PURE__ */ jsx26(\"span\", { children: \"L\" }),\n /* @__PURE__ */ jsx26(\n Slider,\n {\n min: \"-1\",\n max: \"1\",\n step: \"0.01\",\n value: pan,\n onChange: (e) => onPanChange(parseFloat(e.target.value))\n }\n ),\n /* @__PURE__ */ jsx26(\"span\", { children: \"R\" })\n ] })\n ] });\n};\nexport {\n AudioPosition,\n AutomaticScrollCheckbox,\n BaseButton,\n BaseCheckbox,\n BaseCheckboxLabel,\n BaseCheckboxWrapper,\n BaseControlButton,\n BaseInput,\n BaseLabel,\n BaseSelect,\n BaseSlider,\n Button,\n ButtonGroup,\n CLIP_BOUNDARY_WIDTH,\n CLIP_BOUNDARY_WIDTH_TOUCH,\n CLIP_HEADER_HEIGHT,\n Channel,\n Clip,\n ClipBoundary,\n ClipHeader,\n ClipHeaderPresentational,\n Controls,\n DevicePixelRatioProvider,\n FadeOverlay,\n Header,\n InlineLabel,\n LoopRegion,\n LoopRegionMarkers,\n MasterVolumeControl,\n Playhead,\n PlayheadWithMarker,\n Playlist,\n PlaylistInfoContext,\n PlayoutProvider,\n ScreenReaderOnly,\n Selection,\n SelectionTimeInputs,\n Slider,\n SliderWrapper,\n SmartChannel,\n SmartScale,\n StyledPlaylist,\n StyledTimeScale,\n TimeFormatSelect,\n TimeInput,\n TimeScale,\n TimescaleLoopRegion,\n Track,\n TrackControlsContext,\n TrackControlsWithDelete,\n TrashIcon,\n VolumeDownIcon,\n VolumeUpIcon,\n darkTheme,\n defaultTheme,\n formatTime,\n isWaveformGradient,\n parseTime,\n pixelsToSamples,\n pixelsToSeconds,\n samplesToPixels,\n samplesToSeconds,\n secondsToPixels,\n secondsToSamples,\n useDevicePixelRatio,\n usePlaylistInfo,\n usePlayoutStatus,\n usePlayoutStatusUpdate,\n useTheme2 as useTheme,\n useTrackControls,\n waveformColorToCss\n};\n//# sourceMappingURL=index.mjs.map","// src/index.ts\nfunction findMinMax(array) {\n let min = Infinity;\n let max = -Infinity;\n for (let i = 0; i < array.length; i++) {\n const curr = array[i];\n if (min > curr) {\n min = curr;\n }\n if (max < curr) {\n max = curr;\n }\n }\n return { min, max };\n}\nfunction convert(n, bits) {\n const maxValue = Math.pow(2, bits - 1);\n const v = n < 0 ? n * maxValue : n * (maxValue - 1);\n return Math.max(-maxValue, Math.min(maxValue - 1, v));\n}\nfunction makeTypedArray(bits, length) {\n switch (bits) {\n case 8:\n return new Int8Array(length);\n case 16:\n return new Int16Array(length);\n }\n}\nfunction extractPeaks(channel, samplesPerPixel, bits) {\n const chanLength = channel.length;\n const numPeaks = Math.ceil(chanLength / samplesPerPixel);\n const peaks = makeTypedArray(bits, numPeaks * 2);\n for (let i = 0; i < numPeaks; i++) {\n const start = i * samplesPerPixel;\n const end = Math.min((i + 1) * samplesPerPixel, chanLength);\n const segment = channel.subarray(start, end);\n const extrema = findMinMax(segment);\n const min = convert(extrema.min, bits);\n const max = convert(extrema.max, bits);\n peaks[i * 2] = min;\n peaks[i * 2 + 1] = max;\n }\n return peaks;\n}\nfunction makeMono(channelPeaks, bits) {\n const numChan = channelPeaks.length;\n const weight = 1 / numChan;\n const numPeaks = channelPeaks[0].length / 2;\n const peaks = makeTypedArray(bits, numPeaks * 2);\n for (let i = 0; i < numPeaks; i++) {\n let min = 0;\n let max = 0;\n for (let c = 0; c < numChan; c++) {\n min += weight * channelPeaks[c][i * 2];\n max += weight * channelPeaks[c][i * 2 + 1];\n }\n peaks[i * 2] = min;\n peaks[i * 2 + 1] = max;\n }\n return [peaks];\n}\nfunction extractPeaksFromBuffer(source, samplesPerPixel = 1e3, isMono = true, cueIn = 0, cueOut, bits = 16) {\n if (bits !== 8 && bits !== 16) {\n throw new Error(\"Invalid number of bits specified for peaks. Must be 8 or 16.\");\n }\n let peaks = [];\n if (\"getChannelData\" in source) {\n const numChan = source.numberOfChannels;\n const actualCueOut = cueOut ?? source.length;\n for (let c = 0; c < numChan; c++) {\n const channel = source.getChannelData(c);\n const slice = channel.subarray(cueIn, actualCueOut);\n peaks.push(extractPeaks(slice, samplesPerPixel, bits));\n }\n } else {\n const actualCueOut = cueOut ?? source.length;\n const slice = source.subarray(cueIn, actualCueOut);\n peaks.push(extractPeaks(slice, samplesPerPixel, bits));\n }\n if (isMono && peaks.length > 1) {\n peaks = makeMono(peaks, bits);\n }\n const numPeaks = peaks[0].length / 2;\n return {\n length: numPeaks,\n data: peaks,\n bits\n };\n}\nexport {\n extractPeaksFromBuffer as default\n};\n//# sourceMappingURL=index.mjs.map","import extractPeaks, { type PeakData } from '@waveform-playlist/webaudio-peaks';\n\n/**\n * Generate peaks from an AudioBuffer for waveform visualization\n * This is a thin wrapper around the webaudio-peaks package\n *\n * @param audioBuffer - The audio buffer to extract peaks from\n * @param samplesPerPixel - Number of samples per pixel\n * @param isMono - Whether to merge channels to mono\n * @param bits - Bit depth for peak data (8 or 16)\n * @param offsetSamples - Start offset in samples (for trimming)\n * @param durationSamples - Duration in samples (for trimming)\n */\nexport function generatePeaks(\n audioBuffer: AudioBuffer,\n samplesPerPixel: number = 1000,\n isMono: boolean = true,\n bits: 8 | 16 = 8,\n offsetSamples: number = 0,\n durationSamples?: number\n): PeakData {\n // Calculate cueOut from offset + duration (both in samples)\n const cueOut = durationSamples !== undefined\n ? offsetSamples + durationSamples\n : undefined;\n\n return extractPeaks(audioBuffer, samplesPerPixel, isMono, offsetSamples, cueOut, bits);\n}\n","/**\n * Provides access to the waveform data for a single audio channel.\n */\n\nfunction WaveformDataChannel(waveformData, channelIndex) {\n this._waveformData = waveformData;\n this._channelIndex = channelIndex;\n}\n\n/**\n * Returns the waveform minimum at the given index position.\n */\n\nWaveformDataChannel.prototype.min_sample = function (index) {\n var offset = (index * this._waveformData.channels + this._channelIndex) * 2;\n return this._waveformData._at(offset);\n};\n\n/**\n * Returns the waveform maximum at the given index position.\n */\n\nWaveformDataChannel.prototype.max_sample = function (index) {\n var offset = (index * this._waveformData.channels + this._channelIndex) * 2 + 1;\n return this._waveformData._at(offset);\n};\n\n/**\n * Sets the waveform minimum at the given index position.\n */\n\nWaveformDataChannel.prototype.set_min_sample = function (index, sample) {\n var offset = (index * this._waveformData.channels + this._channelIndex) * 2;\n return this._waveformData._set_at(offset, sample);\n};\n\n/**\n * Sets the waveform maximum at the given index position.\n */\n\nWaveformDataChannel.prototype.set_max_sample = function (index, sample) {\n var offset = (index * this._waveformData.channels + this._channelIndex) * 2 + 1;\n return this._waveformData._set_at(offset, sample);\n};\n\n/**\n * Returns all the waveform minimum values as an array.\n */\n\nWaveformDataChannel.prototype.min_array = function () {\n var length = this._waveformData.length;\n var values = [];\n for (var i = 0; i < length; i++) {\n values.push(this.min_sample(i));\n }\n return values;\n};\n\n/**\n * Returns all the waveform maximum values as an array.\n */\n\nWaveformDataChannel.prototype.max_array = function () {\n var length = this._waveformData.length;\n var values = [];\n for (var i = 0; i < length; i++) {\n values.push(this.max_sample(i));\n }\n return values;\n};\n\n/**\n * AudioBuffer-based WaveformData generator\n *\n * Adapted from BlockFile::CalcSummary in Audacity, with permission.\n * See https://github.com/audacity/audacity/blob/\n * 1108c1376c09166162335fab4743008cba57c4ee/src/BlockFile.cpp#L198\n */\n\nvar INT8_MAX = 127;\nvar INT8_MIN = -128;\nvar INT16_MAX = 32767;\nvar INT16_MIN = -32768;\nfunction calculateWaveformDataLength(audio_sample_count, scale) {\n var data_length = Math.floor(audio_sample_count / scale);\n var samples_remaining = audio_sample_count - data_length * scale;\n if (samples_remaining > 0) {\n data_length++;\n }\n return data_length;\n}\nfunction generateWaveformData(options) {\n var scale = options.scale;\n var amplitude_scale = options.amplitude_scale;\n var split_channels = options.split_channels;\n var length = options.length;\n var sample_rate = options.sample_rate;\n var channels = options.channels.map(function (channel) {\n return new Float32Array(channel);\n });\n var output_channels = split_channels ? channels.length : 1;\n var header_size = 24;\n var data_length = calculateWaveformDataLength(length, scale);\n var bytes_per_sample = options.bits === 8 ? 1 : 2;\n var total_size = header_size + data_length * 2 * bytes_per_sample * output_channels;\n var buffer = new ArrayBuffer(total_size);\n var data_view = new DataView(buffer);\n var scale_counter = 0;\n var offset = header_size;\n var min_value = new Array(output_channels);\n var max_value = new Array(output_channels);\n for (var channel = 0; channel < output_channels; channel++) {\n min_value[channel] = Infinity;\n max_value[channel] = -Infinity;\n }\n var range_min = options.bits === 8 ? INT8_MIN : INT16_MIN;\n var range_max = options.bits === 8 ? INT8_MAX : INT16_MAX;\n data_view.setInt32(0, 2, true); // Version\n data_view.setUint32(4, options.bits === 8, true); // Is 8 bit?\n data_view.setInt32(8, sample_rate, true); // Sample rate\n data_view.setInt32(12, scale, true); // Scale\n data_view.setInt32(16, data_length, true); // Length\n data_view.setInt32(20, output_channels, true);\n for (var i = 0; i < length; i++) {\n var sample = 0;\n if (output_channels === 1) {\n for (var _channel = 0; _channel < channels.length; ++_channel) {\n sample += channels[_channel][i];\n }\n sample = Math.floor(range_max * sample * amplitude_scale / channels.length);\n if (sample < min_value[0]) {\n min_value[0] = sample;\n if (min_value[0] < range_min) {\n min_value[0] = range_min;\n }\n }\n if (sample > max_value[0]) {\n max_value[0] = sample;\n if (max_value[0] > range_max) {\n max_value[0] = range_max;\n }\n }\n } else {\n for (var _channel2 = 0; _channel2 < output_channels; ++_channel2) {\n sample = Math.floor(range_max * channels[_channel2][i] * amplitude_scale);\n if (sample < min_value[_channel2]) {\n min_value[_channel2] = sample;\n if (min_value[_channel2] < range_min) {\n min_value[_channel2] = range_min;\n }\n }\n if (sample > max_value[_channel2]) {\n max_value[_channel2] = sample;\n if (max_value[_channel2] > range_max) {\n max_value[_channel2] = range_max;\n }\n }\n }\n }\n if (++scale_counter === scale) {\n for (var _channel3 = 0; _channel3 < output_channels; _channel3++) {\n if (options.bits === 8) {\n data_view.setInt8(offset++, min_value[_channel3]);\n data_view.setInt8(offset++, max_value[_channel3]);\n } else {\n data_view.setInt16(offset, min_value[_channel3], true);\n data_view.setInt16(offset + 2, max_value[_channel3], true);\n offset += 4;\n }\n min_value[_channel3] = Infinity;\n max_value[_channel3] = -Infinity;\n }\n scale_counter = 0;\n }\n }\n if (scale_counter > 0) {\n for (var _channel4 = 0; _channel4 < output_channels; _channel4++) {\n if (options.bits === 8) {\n data_view.setInt8(offset++, min_value[_channel4]);\n data_view.setInt8(offset++, max_value[_channel4]);\n } else {\n data_view.setInt16(offset, min_value[_channel4], true);\n data_view.setInt16(offset + 2, max_value[_channel4], true);\n }\n }\n }\n return buffer;\n}\n\nfunction _typeof(o) {\n \"@babel/helpers - typeof\";\n\n return _typeof = \"function\" == typeof Symbol && \"symbol\" == typeof Symbol.iterator ? function (o) {\n return typeof o;\n } : function (o) {\n return o && \"function\" == typeof Symbol && o.constructor === Symbol && o !== Symbol.prototype ? \"symbol\" : typeof o;\n }, _typeof(o);\n}\n\nfunction isJsonWaveformData(data) {\n return data && _typeof(data) === 'object' && 'sample_rate' in data && 'samples_per_pixel' in data && 'bits' in data && 'length' in data && 'data' in data;\n}\nfunction isBinaryWaveformData(data) {\n var isCompatible = data && _typeof(data) === 'object' && 'byteLength' in data;\n if (isCompatible) {\n var view = new DataView(data);\n var version = view.getInt32(0, true);\n if (version !== 1 && version !== 2) {\n throw new TypeError('WaveformData.create(): This waveform data version not supported');\n }\n }\n return isCompatible;\n}\nfunction convertJsonToBinary(data) {\n var waveformData = data.data;\n var channels = data.channels || 1;\n var header_size = 24; // version 2\n var bytes_per_sample = data.bits === 8 ? 1 : 2;\n var expected_length = data.length * 2 * channels;\n if (waveformData.length !== expected_length) {\n throw new Error('WaveformData.create(): Length mismatch in JSON waveform data');\n }\n var total_size = header_size + waveformData.length * bytes_per_sample;\n var array_buffer = new ArrayBuffer(total_size);\n var data_object = new DataView(array_buffer);\n data_object.setInt32(0, 2, true); // Version\n data_object.setUint32(4, data.bits === 8, true);\n data_object.setInt32(8, data.sample_rate, true);\n data_object.setInt32(12, data.samples_per_pixel, true);\n data_object.setInt32(16, data.length, true);\n data_object.setInt32(20, channels, true);\n var index = header_size;\n if (data.bits === 8) {\n for (var i = 0; i < waveformData.length; i++) {\n data_object.setInt8(index++, waveformData[i], true);\n }\n } else {\n for (var _i = 0; _i < waveformData.length; _i++) {\n data_object.setInt16(index, waveformData[_i], true);\n index += 2;\n }\n }\n return array_buffer;\n}\n\nfunction isNullOrUndefined(value) {\n return value === undefined || value === null;\n}\n\nfunction decodeBase64(base64, enableUnicode) {\n var binaryString = atob(base64);\n if (enableUnicode) {\n var binaryView = new Uint8Array(binaryString.length);\n for (var i = 0, n = binaryString.length; i < n; ++i) {\n binaryView[i] = binaryString.charCodeAt(i);\n }\n return String.fromCharCode.apply(null, new Uint16Array(binaryView.buffer));\n }\n return binaryString;\n}\n\nfunction createURL(base64, sourcemapArg, enableUnicodeArg) {\n var sourcemap = sourcemapArg === undefined ? null : sourcemapArg;\n var enableUnicode = enableUnicodeArg === undefined ? false : enableUnicodeArg;\n var source = decodeBase64(base64, enableUnicode);\n var start = source.indexOf('\\n', 10) + 1;\n var body = source.substring(start) + (sourcemap ? '\\/\\/# sourceMappingURL=' + sourcemap : '');\n var blob = new Blob([body], { type: 'application/javascript' });\n return URL.createObjectURL(blob);\n}\n\nfunction createBase64WorkerFactory(base64, sourcemapArg, enableUnicodeArg) {\n var url;\n return function WorkerFactory(options) {\n url = url || createURL(base64, sourcemapArg, enableUnicodeArg);\n return new Worker(url, options);\n };\n}\n\nvar WorkerFactory = /*#__PURE__*/createBase64WorkerFactory('Lyogcm9sbHVwLXBsdWdpbi13ZWItd29ya2VyLWxvYWRlciAqLwooZnVuY3Rpb24gKCkgewogICd1c2Ugc3RyaWN0JzsKCiAgLyoqCiAgICogQXVkaW9CdWZmZXItYmFzZWQgV2F2ZWZvcm1EYXRhIGdlbmVyYXRvcgogICAqCiAgICogQWRhcHRlZCBmcm9tIEJsb2NrRmlsZTo6Q2FsY1N1bW1hcnkgaW4gQXVkYWNpdHksIHdpdGggcGVybWlzc2lvbi4KICAgKiBTZWUgaHR0cHM6Ly9naXRodWIuY29tL2F1ZGFjaXR5L2F1ZGFjaXR5L2Jsb2IvCiAgICogICAxMTA4YzEzNzZjMDkxNjYxNjIzMzVmYWI0NzQzMDA4Y2JhNTdjNGVlL3NyYy9CbG9ja0ZpbGUuY3BwI0wxOTgKICAgKi8KCiAgdmFyIElOVDhfTUFYID0gMTI3OwogIHZhciBJTlQ4X01JTiA9IC0xMjg7CiAgdmFyIElOVDE2X01BWCA9IDMyNzY3OwogIHZhciBJTlQxNl9NSU4gPSAtMzI3Njg7CiAgZnVuY3Rpb24gY2FsY3VsYXRlV2F2ZWZvcm1EYXRhTGVuZ3RoKGF1ZGlvX3NhbXBsZV9jb3VudCwgc2NhbGUpIHsKICAgIHZhciBkYXRhX2xlbmd0aCA9IE1hdGguZmxvb3IoYXVkaW9fc2FtcGxlX2NvdW50IC8gc2NhbGUpOwogICAgdmFyIHNhbXBsZXNfcmVtYWluaW5nID0gYXVkaW9fc2FtcGxlX2NvdW50IC0gZGF0YV9sZW5ndGggKiBzY2FsZTsKICAgIGlmIChzYW1wbGVzX3JlbWFpbmluZyA+IDApIHsKICAgICAgZGF0YV9sZW5ndGgrKzsKICAgIH0KICAgIHJldHVybiBkYXRhX2xlbmd0aDsKICB9CiAgZnVuY3Rpb24gZ2VuZXJhdGVXYXZlZm9ybURhdGEob3B0aW9ucykgewogICAgdmFyIHNjYWxlID0gb3B0aW9ucy5zY2FsZTsKICAgIHZhciBhbXBsaXR1ZGVfc2NhbGUgPSBvcHRpb25zLmFtcGxpdHVkZV9zY2FsZTsKICAgIHZhciBzcGxpdF9jaGFubmVscyA9IG9wdGlvbnMuc3BsaXRfY2hhbm5lbHM7CiAgICB2YXIgbGVuZ3RoID0gb3B0aW9ucy5sZW5ndGg7CiAgICB2YXIgc2FtcGxlX3JhdGUgPSBvcHRpb25zLnNhbXBsZV9yYXRlOwogICAgdmFyIGNoYW5uZWxzID0gb3B0aW9ucy5jaGFubmVscy5tYXAoZnVuY3Rpb24gKGNoYW5uZWwpIHsKICAgICAgcmV0dXJuIG5ldyBGbG9hdDMyQXJyYXkoY2hhbm5lbCk7CiAgICB9KTsKICAgIHZhciBvdXRwdXRfY2hhbm5lbHMgPSBzcGxpdF9jaGFubmVscyA/IGNoYW5uZWxzLmxlbmd0aCA6IDE7CiAgICB2YXIgaGVhZGVyX3NpemUgPSAyNDsKICAgIHZhciBkYXRhX2xlbmd0aCA9IGNhbGN1bGF0ZVdhdmVmb3JtRGF0YUxlbmd0aChsZW5ndGgsIHNjYWxlKTsKICAgIHZhciBieXRlc19wZXJfc2FtcGxlID0gb3B0aW9ucy5iaXRzID09PSA4ID8gMSA6IDI7CiAgICB2YXIgdG90YWxfc2l6ZSA9IGhlYWRlcl9zaXplICsgZGF0YV9sZW5ndGggKiAyICogYnl0ZXNfcGVyX3NhbXBsZSAqIG91dHB1dF9jaGFubmVsczsKICAgIHZhciBidWZmZXIgPSBuZXcgQXJyYXlCdWZmZXIodG90YWxfc2l6ZSk7CiAgICB2YXIgZGF0YV92aWV3ID0gbmV3IERhdGFWaWV3KGJ1ZmZlcik7CiAgICB2YXIgc2NhbGVfY291bnRlciA9IDA7CiAgICB2YXIgb2Zmc2V0ID0gaGVhZGVyX3NpemU7CiAgICB2YXIgbWluX3ZhbHVlID0gbmV3IEFycmF5KG91dHB1dF9jaGFubmVscyk7CiAgICB2YXIgbWF4X3ZhbHVlID0gbmV3IEFycmF5KG91dHB1dF9jaGFubmVscyk7CiAgICBmb3IgKHZhciBjaGFubmVsID0gMDsgY2hhbm5lbCA8IG91dHB1dF9jaGFubmVsczsgY2hhbm5lbCsrKSB7CiAgICAgIG1pbl92YWx1ZVtjaGFubmVsXSA9IEluZmluaXR5OwogICAgICBtYXhfdmFsdWVbY2hhbm5lbF0gPSAtSW5maW5pdHk7CiAgICB9CiAgICB2YXIgcmFuZ2VfbWluID0gb3B0aW9ucy5iaXRzID09PSA4ID8gSU5UOF9NSU4gOiBJTlQxNl9NSU47CiAgICB2YXIgcmFuZ2VfbWF4ID0gb3B0aW9ucy5iaXRzID09PSA4ID8gSU5UOF9NQVggOiBJTlQxNl9NQVg7CiAgICBkYXRhX3ZpZXcuc2V0SW50MzIoMCwgMiwgdHJ1ZSk7IC8vIFZlcnNpb24KICAgIGRhdGFfdmlldy5zZXRVaW50MzIoNCwgb3B0aW9ucy5iaXRzID09PSA4LCB0cnVlKTsgLy8gSXMgOCBiaXQ/CiAgICBkYXRhX3ZpZXcuc2V0SW50MzIoOCwgc2FtcGxlX3JhdGUsIHRydWUpOyAvLyBTYW1wbGUgcmF0ZQogICAgZGF0YV92aWV3LnNldEludDMyKDEyLCBzY2FsZSwgdHJ1ZSk7IC8vIFNjYWxlCiAgICBkYXRhX3ZpZXcuc2V0SW50MzIoMTYsIGRhdGFfbGVuZ3RoLCB0cnVlKTsgLy8gTGVuZ3RoCiAgICBkYXRhX3ZpZXcuc2V0SW50MzIoMjAsIG91dHB1dF9jaGFubmVscywgdHJ1ZSk7CiAgICBmb3IgKHZhciBpID0gMDsgaSA8IGxlbmd0aDsgaSsrKSB7CiAgICAgIHZhciBzYW1wbGUgPSAwOwogICAgICBpZiAob3V0cHV0X2NoYW5uZWxzID09PSAxKSB7CiAgICAgICAgZm9yICh2YXIgX2NoYW5uZWwgPSAwOyBfY2hhbm5lbCA8IGNoYW5uZWxzLmxlbmd0aDsgKytfY2hhbm5lbCkgewogICAgICAgICAgc2FtcGxlICs9IGNoYW5uZWxzW19jaGFubmVsXVtpXTsKICAgICAgICB9CiAgICAgICAgc2FtcGxlID0gTWF0aC5mbG9vcihyYW5nZV9tYXggKiBzYW1wbGUgKiBhbXBsaXR1ZGVfc2NhbGUgLyBjaGFubmVscy5sZW5ndGgpOwogICAgICAgIGlmIChzYW1wbGUgPCBtaW5fdmFsdWVbMF0pIHsKICAgICAgICAgIG1pbl92YWx1ZVswXSA9IHNhbXBsZTsKICAgICAgICAgIGlmIChtaW5fdmFsdWVbMF0gPCByYW5nZV9taW4pIHsKICAgICAgICAgICAgbWluX3ZhbHVlWzBdID0gcmFuZ2VfbWluOwogICAgICAgICAgfQogICAgICAgIH0KICAgICAgICBpZiAoc2FtcGxlID4gbWF4X3ZhbHVlWzBdKSB7CiAgICAgICAgICBtYXhfdmFsdWVbMF0gPSBzYW1wbGU7CiAgICAgICAgICBpZiAobWF4X3ZhbHVlWzBdID4gcmFuZ2VfbWF4KSB7CiAgICAgICAgICAgIG1heF92YWx1ZVswXSA9IHJhbmdlX21heDsKICAgICAgICAgIH0KICAgICAgICB9CiAgICAgIH0gZWxzZSB7CiAgICAgICAgZm9yICh2YXIgX2NoYW5uZWwyID0gMDsgX2NoYW5uZWwyIDwgb3V0cHV0X2NoYW5uZWxzOyArK19jaGFubmVsMikgewogICAgICAgICAgc2FtcGxlID0gTWF0aC5mbG9vcihyYW5nZV9tYXggKiBjaGFubmVsc1tfY2hhbm5lbDJdW2ldICogYW1wbGl0dWRlX3NjYWxlKTsKICAgICAgICAgIGlmIChzYW1wbGUgPCBtaW5fdmFsdWVbX2NoYW5uZWwyXSkgewogICAgICAgICAgICBtaW5fdmFsdWVbX2NoYW5uZWwyXSA9IHNhbXBsZTsKICAgICAgICAgICAgaWYgKG1pbl92YWx1ZVtfY2hhbm5lbDJdIDwgcmFuZ2VfbWluKSB7CiAgICAgICAgICAgICAgbWluX3ZhbHVlW19jaGFubmVsMl0gPSByYW5nZV9taW47CiAgICAgICAgICAgIH0KICAgICAgICAgIH0KICAgICAgICAgIGlmIChzYW1wbGUgPiBtYXhfdmFsdWVbX2NoYW5uZWwyXSkgewogICAgICAgICAgICBtYXhfdmFsdWVbX2NoYW5uZWwyXSA9IHNhbXBsZTsKICAgICAgICAgICAgaWYgKG1heF92YWx1ZVtfY2hhbm5lbDJdID4gcmFuZ2VfbWF4KSB7CiAgICAgICAgICAgICAgbWF4X3ZhbHVlW19jaGFubmVsMl0gPSByYW5nZV9tYXg7CiAgICAgICAgICAgIH0KICAgICAgICAgIH0KICAgICAgICB9CiAgICAgIH0KICAgICAgaWYgKCsrc2NhbGVfY291bnRlciA9PT0gc2NhbGUpIHsKICAgICAgICBmb3IgKHZhciBfY2hhbm5lbDMgPSAwOyBfY2hhbm5lbDMgPCBvdXRwdXRfY2hhbm5lbHM7IF9jaGFubmVsMysrKSB7CiAgICAgICAgICBpZiAob3B0aW9ucy5iaXRzID09PSA4KSB7CiAgICAgICAgICAgIGRhdGFfdmlldy5zZXRJbnQ4KG9mZnNldCsrLCBtaW5fdmFsdWVbX2NoYW5uZWwzXSk7CiAgICAgICAgICAgIGRhdGFfdmlldy5zZXRJbnQ4KG9mZnNldCsrLCBtYXhfdmFsdWVbX2NoYW5uZWwzXSk7CiAgICAgICAgICB9IGVsc2UgewogICAgICAgICAgICBkYXRhX3ZpZXcuc2V0SW50MTYob2Zmc2V0LCBtaW5fdmFsdWVbX2NoYW5uZWwzXSwgdHJ1ZSk7CiAgICAgICAgICAgIGRhdGFfdmlldy5zZXRJbnQxNihvZmZzZXQgKyAyLCBtYXhfdmFsdWVbX2NoYW5uZWwzXSwgdHJ1ZSk7CiAgICAgICAgICAgIG9mZnNldCArPSA0OwogICAgICAgICAgfQogICAgICAgICAgbWluX3ZhbHVlW19jaGFubmVsM10gPSBJbmZpbml0eTsKICAgICAgICAgIG1heF92YWx1ZVtfY2hhbm5lbDNdID0gLUluZmluaXR5OwogICAgICAgIH0KICAgICAgICBzY2FsZV9jb3VudGVyID0gMDsKICAgICAgfQogICAgfQogICAgaWYgKHNjYWxlX2NvdW50ZXIgPiAwKSB7CiAgICAgIGZvciAodmFyIF9jaGFubmVsNCA9IDA7IF9jaGFubmVsNCA8IG91dHB1dF9jaGFubmVsczsgX2NoYW5uZWw0KyspIHsKICAgICAgICBpZiAob3B0aW9ucy5iaXRzID09PSA4KSB7CiAgICAgICAgICBkYXRhX3ZpZXcuc2V0SW50OChvZmZzZXQrKywgbWluX3ZhbHVlW19jaGFubmVsNF0pOwogICAgICAgICAgZGF0YV92aWV3LnNldEludDgob2Zmc2V0KyssIG1heF92YWx1ZVtfY2hhbm5lbDRdKTsKICAgICAgICB9IGVsc2UgewogICAgICAgICAgZGF0YV92aWV3LnNldEludDE2KG9mZnNldCwgbWluX3ZhbHVlW19jaGFubmVsNF0sIHRydWUpOwogICAgICAgICAgZGF0YV92aWV3LnNldEludDE2KG9mZnNldCArIDIsIG1heF92YWx1ZVtfY2hhbm5lbDRdLCB0cnVlKTsKICAgICAgICB9CiAgICAgIH0KICAgIH0KICAgIHJldHVybiBidWZmZXI7CiAgfQoKICBvbm1lc3NhZ2UgPSBmdW5jdGlvbiBvbm1lc3NhZ2UoZXZ0KSB7CiAgICB2YXIgYnVmZmVyID0gZ2VuZXJhdGVXYXZlZm9ybURhdGEoZXZ0LmRhdGEpOwoKICAgIC8vIFRyYW5zZmVyIGJ1ZmZlciB0byB0aGUgY2FsbGluZyB0aHJlYWQKICAgIHRoaXMucG9zdE1lc3NhZ2UoYnVmZmVyLCBbYnVmZmVyXSk7CiAgICB0aGlzLmNsb3NlKCk7CiAgfTsKCn0pKCk7Ci8vIyBzb3VyY2VNYXBwaW5nVVJMPXdhdmVmb3JtLWRhdGEtd29ya2VyLmpzLm1hcAoK', null, false);\n/* eslint-enable */\n\n/**\n * Provides access to waveform data.\n */\n\nfunction WaveformData(data) {\n if (isJsonWaveformData(data)) {\n data = convertJsonToBinary(data);\n }\n if (isBinaryWaveformData(data)) {\n this._data = new DataView(data);\n this._offset = this._version() === 2 ? 24 : 20;\n this._channels = [];\n for (var channel = 0; channel < this.channels; channel++) {\n this._channels[channel] = new WaveformDataChannel(this, channel);\n }\n } else {\n throw new TypeError('WaveformData.create(): Unknown data format');\n }\n}\nvar defaultOptions = {\n scale: 512,\n bits: 8,\n amplitude_scale: 1.0,\n split_channels: false,\n disable_worker: false\n};\nfunction getOptions(options) {\n var opts = {\n scale: options.scale || defaultOptions.scale,\n bits: options.bits || defaultOptions.bits,\n amplitude_scale: options.amplitude_scale || defaultOptions.amplitude_scale,\n split_channels: options.split_channels || defaultOptions.split_channels,\n disable_worker: options.disable_worker || defaultOptions.disable_worker\n };\n return opts;\n}\nfunction getChannelData(audio_buffer) {\n var channels = [];\n for (var i = 0; i < audio_buffer.numberOfChannels; ++i) {\n channels.push(audio_buffer.getChannelData(i).buffer);\n }\n return channels;\n}\nfunction createFromAudioBuffer(audio_buffer, options, callback) {\n var channels = getChannelData(audio_buffer);\n if (options.disable_worker) {\n var buffer = generateWaveformData({\n scale: options.scale,\n bits: options.bits,\n amplitude_scale: options.amplitude_scale,\n split_channels: options.split_channels,\n length: audio_buffer.length,\n sample_rate: audio_buffer.sampleRate,\n channels: channels\n });\n callback(undefined, new WaveformData(buffer), audio_buffer);\n } else {\n var worker = new WorkerFactory();\n worker.onmessage = function (evt) {\n callback(undefined, new WaveformData(evt.data), audio_buffer);\n };\n worker.postMessage({\n scale: options.scale,\n bits: options.bits,\n amplitude_scale: options.amplitude_scale,\n split_channels: options.split_channels,\n length: audio_buffer.length,\n sample_rate: audio_buffer.sampleRate,\n channels: channels\n }, channels);\n }\n}\nfunction createFromArrayBuffer(audioContext, audioData, options, callback) {\n // The following function is a workaround for a Webkit bug where decodeAudioData\n // invokes the errorCallback with null instead of a DOMException.\n // See https://webaudio.github.io/web-audio-api/#dom-baseaudiocontext-decodeaudiodata\n // and http://stackoverflow.com/q/10365335/103396\n\n function errorCallback(error) {\n if (!error) {\n error = new DOMException('EncodingError');\n }\n callback(error);\n // prevent double-calling the callback on errors:\n callback = function callback() {};\n }\n var promise = audioContext.decodeAudioData(audioData, function (audio_buffer) {\n createFromAudioBuffer(audio_buffer, options, callback);\n }, errorCallback);\n if (promise) {\n promise.catch(errorCallback);\n }\n}\n\n/**\n * Creates and returns a WaveformData instance from the given waveform data.\n */\n\nWaveformData.create = function create(data) {\n return new WaveformData(data);\n};\n\n/**\n * Creates a WaveformData instance from audio.\n */\n\nWaveformData.createFromAudio = function (options, callback) {\n var opts = getOptions(options);\n if (options.audio_context && options.array_buffer) {\n return createFromArrayBuffer(options.audio_context, options.array_buffer, opts, callback);\n } else if (options.audio_buffer) {\n return createFromAudioBuffer(options.audio_buffer, opts, callback);\n } else {\n throw new TypeError(\n // eslint-disable-next-line\n 'WaveformData.createFromAudio(): Pass either an AudioContext and ArrayBuffer, or an AudioBuffer object');\n }\n};\nfunction WaveformResampler(options) {\n this._inputData = options.waveformData;\n\n // Scale we want to reach\n this._output_samples_per_pixel = options.scale;\n this._scale = this._inputData.scale; // scale we are coming from\n\n // The amount of data we want to resample i.e. final zoom want to resample\n // all data but for intermediate zoom we want to resample subset\n this._input_buffer_size = this._inputData.length;\n var input_buffer_length_samples = this._input_buffer_size * this._inputData.scale;\n var output_buffer_length_samples = Math.ceil(input_buffer_length_samples / this._output_samples_per_pixel);\n var output_header_size = 24; // version 2\n var bytes_per_sample = this._inputData.bits === 8 ? 1 : 2;\n var total_size = output_header_size + output_buffer_length_samples * 2 * this._inputData.channels * bytes_per_sample;\n this._output_data = new ArrayBuffer(total_size);\n this.output_dataview = new DataView(this._output_data);\n this.output_dataview.setInt32(0, 2, true); // Version\n this.output_dataview.setUint32(4, this._inputData.bits === 8, true); // Is 8 bit?\n this.output_dataview.setInt32(8, this._inputData.sample_rate, true);\n this.output_dataview.setInt32(12, this._output_samples_per_pixel, true);\n this.output_dataview.setInt32(16, output_buffer_length_samples, true);\n this.output_dataview.setInt32(20, this._inputData.channels, true);\n this._outputWaveformData = new WaveformData(this._output_data);\n this._input_index = 0;\n this._output_index = 0;\n var channels = this._inputData.channels;\n this._min = new Array(channels);\n this._max = new Array(channels);\n for (var channel = 0; channel < channels; ++channel) {\n if (this._input_buffer_size > 0) {\n this._min[channel] = this._inputData.channel(channel).min_sample(this._input_index);\n this._max[channel] = this._inputData.channel(channel).max_sample(this._input_index);\n } else {\n this._min[channel] = 0;\n this._max[channel] = 0;\n }\n }\n this._min_value = this._inputData.bits === 8 ? -128 : -32768;\n this._max_value = this._inputData.bits === 8 ? 127 : 32767;\n this._where = 0;\n this._prev_where = 0;\n this._stop = 0;\n this._last_input_index = 0;\n}\nWaveformResampler.prototype.sample_at_pixel = function (x) {\n return Math.floor(x * this._output_samples_per_pixel);\n};\nWaveformResampler.prototype.next = function () {\n var count = 0;\n var total = 1000;\n var channels = this._inputData.channels;\n var channel;\n while (this._input_index < this._input_buffer_size && count < total) {\n while (Math.floor(this.sample_at_pixel(this._output_index) / this._scale) === this._input_index) {\n if (this._output_index > 0) {\n for (var i = 0; i < channels; ++i) {\n channel = this._outputWaveformData.channel(i);\n channel.set_min_sample(this._output_index - 1, this._min[i]);\n channel.set_max_sample(this._output_index - 1, this._max[i]);\n }\n }\n this._last_input_index = this._input_index;\n this._output_index++;\n this._where = this.sample_at_pixel(this._output_index);\n this._prev_where = this.sample_at_pixel(this._output_index - 1);\n if (this._where !== this._prev_where) {\n for (var _i = 0; _i < channels; ++_i) {\n this._min[_i] = this._max_value;\n this._max[_i] = this._min_value;\n }\n }\n }\n this._where = this.sample_at_pixel(this._output_index);\n this._stop = Math.floor(this._where / this._scale);\n if (this._stop > this._input_buffer_size) {\n this._stop = this._input_buffer_size;\n }\n while (this._input_index < this._stop) {\n for (var _i2 = 0; _i2 < channels; ++_i2) {\n channel = this._inputData.channel(_i2);\n var value = channel.min_sample(this._input_index);\n if (value < this._min[_i2]) {\n this._min[_i2] = value;\n }\n value = channel.max_sample(this._input_index);\n if (value > this._max[_i2]) {\n this._max[_i2] = value;\n }\n }\n this._input_index++;\n }\n count++;\n }\n if (this._input_index < this._input_buffer_size) {\n // More to do\n return false;\n } else {\n // Done\n if (this._input_index !== this._last_input_index) {\n for (var _i3 = 0; _i3 < channels; ++_i3) {\n channel = this._outputWaveformData.channel(_i3);\n channel.set_min_sample(this._output_index - 1, this._min[_i3]);\n channel.set_max_sample(this._output_index - 1, this._max[_i3]);\n }\n }\n return true;\n }\n};\nWaveformResampler.prototype.getOutputData = function () {\n return this._output_data;\n};\nWaveformData.prototype = {\n _getResampleOptions: function _getResampleOptions(options) {\n var opts = {};\n opts.scale = options.scale;\n opts.width = options.width;\n if (!isNullOrUndefined(opts.width) && (typeof opts.width !== 'number' || opts.width <= 0)) {\n throw new RangeError('WaveformData.resample(): width should be a positive integer value');\n }\n if (!isNullOrUndefined(opts.scale) && (typeof opts.scale !== 'number' || opts.scale <= 0)) {\n throw new RangeError('WaveformData.resample(): scale should be a positive integer value');\n }\n if (!opts.scale && !opts.width) {\n throw new Error('WaveformData.resample(): Missing scale or width option');\n }\n if (opts.width) {\n // Calculate the target scale for the resampled waveform\n opts.scale = Math.floor(this.duration * this.sample_rate / opts.width);\n }\n if (opts.scale < this.scale) {\n throw new Error('WaveformData.resample(): Zoom level ' + opts.scale + ' too low, minimum: ' + this.scale);\n }\n opts.abortSignal = options.abortSignal;\n return opts;\n },\n resample: function resample(options) {\n options = this._getResampleOptions(options);\n options.waveformData = this;\n var resampler = new WaveformResampler(options);\n while (!resampler.next()) {\n // nothing\n }\n return new WaveformData(resampler.getOutputData());\n },\n /**\n * Concatenates with one or more other waveforms, returning a new WaveformData object.\n */\n\n concat: function concat() {\n var self = this;\n var otherWaveforms = Array.prototype.slice.call(arguments);\n\n // Check that all the supplied waveforms are compatible\n otherWaveforms.forEach(function (otherWaveform) {\n if (self.channels !== otherWaveform.channels || self.sample_rate !== otherWaveform.sample_rate || self.bits !== otherWaveform.bits || self.scale !== otherWaveform.scale) {\n throw new Error('WaveformData.concat(): Waveforms are incompatible');\n }\n });\n var combinedBuffer = this._concatBuffers.apply(this, otherWaveforms);\n return WaveformData.create(combinedBuffer);\n },\n /**\n * Returns a new ArrayBuffer with the concatenated waveform.\n * All waveforms must have identical metadata (version, channels, etc)\n */\n\n _concatBuffers: function _concatBuffers() {\n var otherWaveforms = Array.prototype.slice.call(arguments);\n var headerSize = this._offset;\n var totalSize = headerSize;\n var totalDataLength = 0;\n var bufferCollection = [this].concat(otherWaveforms).map(function (w) {\n return w._data.buffer;\n });\n for (var i = 0; i < bufferCollection.length; i++) {\n var buffer = bufferCollection[i];\n var dataSize = new DataView(buffer).getInt32(16, true);\n totalSize += buffer.byteLength - headerSize;\n totalDataLength += dataSize;\n }\n var totalBuffer = new ArrayBuffer(totalSize);\n var sourceHeader = new DataView(bufferCollection[0]);\n var totalBufferView = new DataView(totalBuffer);\n\n // Copy the header from the first chunk\n for (var _i4 = 0; _i4 < headerSize; _i4++) {\n totalBufferView.setUint8(_i4, sourceHeader.getUint8(_i4));\n }\n\n // Rewrite the data-length header item to reflect all of the samples concatenated together\n totalBufferView.setInt32(16, totalDataLength, true);\n var offset = 0;\n var dataOfTotalBuffer = new Uint8Array(totalBuffer, headerSize);\n for (var _i5 = 0; _i5 < bufferCollection.length; _i5++) {\n var _buffer = bufferCollection[_i5];\n dataOfTotalBuffer.set(new Uint8Array(_buffer, headerSize), offset);\n offset += _buffer.byteLength - headerSize;\n }\n return totalBuffer;\n },\n slice: function slice(options) {\n var startIndex = 0;\n var endIndex = 0;\n if (!isNullOrUndefined(options.startIndex) && !isNullOrUndefined(options.endIndex)) {\n startIndex = options.startIndex;\n endIndex = options.endIndex;\n } else if (!isNullOrUndefined(options.startTime) && !isNullOrUndefined(options.endTime)) {\n startIndex = this.at_time(options.startTime);\n endIndex = this.at_time(options.endTime);\n }\n if (startIndex < 0) {\n throw new RangeError('startIndex or startTime must not be negative');\n }\n if (endIndex < 0) {\n throw new RangeError('endIndex or endTime must not be negative');\n }\n if (startIndex > this.length) {\n startIndex = this.length;\n }\n if (endIndex > this.length) {\n endIndex = this.length;\n }\n if (startIndex > endIndex) {\n startIndex = endIndex;\n }\n var length = endIndex - startIndex;\n var header_size = 24; // Version 2\n var bytes_per_sample = this.bits === 8 ? 1 : 2;\n var total_size = header_size + length * 2 * this.channels * bytes_per_sample;\n var output_data = new ArrayBuffer(total_size);\n var output_dataview = new DataView(output_data);\n output_dataview.setInt32(0, 2, true); // Version\n output_dataview.setUint32(4, this.bits === 8, true); // Is 8 bit?\n output_dataview.setInt32(8, this.sample_rate, true);\n output_dataview.setInt32(12, this.scale, true);\n output_dataview.setInt32(16, length, true);\n output_dataview.setInt32(20, this.channels, true);\n for (var i = 0; i < length * this.channels * 2; i++) {\n var sample = this._at(startIndex * this.channels * 2 + i);\n if (this.bits === 8) {\n output_dataview.setInt8(header_size + i, sample);\n } else {\n output_dataview.setInt16(header_size + i * 2, sample, true);\n }\n }\n return new WaveformData(output_data);\n },\n /**\n * Returns the data format version number.\n */\n\n _version: function _version() {\n return this._data.getInt32(0, true);\n },\n /**\n * Returns the length of the waveform, in pixels.\n */\n\n get length() {\n return this._data.getUint32(16, true);\n },\n /**\n * Returns the number of bits per sample, either 8 or 16.\n */\n\n get bits() {\n var bits = Boolean(this._data.getUint32(4, true));\n return bits ? 8 : 16;\n },\n /**\n * Returns the (approximate) duration of the audio file, in seconds.\n */\n\n get duration() {\n return this.length * this.scale / this.sample_rate;\n },\n /**\n * Returns the number of pixels per second.\n */\n\n get pixels_per_second() {\n return this.sample_rate / this.scale;\n },\n /**\n * Returns the amount of time represented by a single pixel, in seconds.\n */\n\n get seconds_per_pixel() {\n return this.scale / this.sample_rate;\n },\n /**\n * Returns the number of waveform channels.\n */\n\n get channels() {\n if (this._version() === 2) {\n return this._data.getInt32(20, true);\n } else {\n return 1;\n }\n },\n /**\n * Returns a waveform channel.\n */\n\n channel: function channel(index) {\n if (index >= 0 && index < this._channels.length) {\n return this._channels[index];\n } else {\n throw new RangeError('Invalid channel: ' + index);\n }\n },\n /**\n * Returns the number of audio samples per second.\n */\n\n get sample_rate() {\n return this._data.getInt32(8, true);\n },\n /**\n * Returns the number of audio samples per pixel.\n */\n\n get scale() {\n return this._data.getInt32(12, true);\n },\n /**\n * Returns a waveform data value at a specific offset.\n */\n\n _at: function at_sample(index) {\n if (this.bits === 8) {\n return this._data.getInt8(this._offset + index);\n } else {\n return this._data.getInt16(this._offset + index * 2, true);\n }\n },\n /**\n * Sets a waveform data value at a specific offset.\n */\n\n _set_at: function set_at(index, sample) {\n if (this.bits === 8) {\n return this._data.setInt8(this._offset + index, sample);\n } else {\n return this._data.setInt16(this._offset + index * 2, sample, true);\n }\n },\n /**\n * Returns the waveform data index position for a given time.\n */\n\n at_time: function at_time(time) {\n return Math.floor(time * this.sample_rate / this.scale);\n },\n /**\n * Returns the time in seconds for a given index.\n */\n\n time: function time(index) {\n return index * this.scale / this.sample_rate;\n },\n /**\n * Returns an object containing the waveform data.\n */\n\n toJSON: function toJSON() {\n var waveform = {\n version: 2,\n channels: this.channels,\n sample_rate: this.sample_rate,\n samples_per_pixel: this.scale,\n bits: this.bits,\n length: this.length,\n data: []\n };\n for (var i = 0; i < this.length; i++) {\n for (var channel = 0; channel < this.channels; channel++) {\n waveform.data.push(this.channel(channel).min_sample(i));\n waveform.data.push(this.channel(channel).max_sample(i));\n }\n }\n return waveform;\n },\n /**\n * Returns the waveform data in binary format as an ArrayBuffer.\n */\n\n toArrayBuffer: function toArrayBuffer() {\n return this._data.buffer;\n }\n};\n\nexport { WaveformData as default };\n","/**\n * Waveform Data Loader\n *\n * Utilities for loading pre-computed waveform data in waveform-data.js format.\n * Supports both binary (.dat) and JSON formats from BBC's audiowaveform tool.\n */\n\nimport WaveformData from 'waveform-data';\n\n/**\n * Load waveform data from a .dat or .json file\n *\n * @param src - URL to waveform data file (.dat or .json)\n * @returns WaveformData instance\n */\nexport async function loadWaveformData(src: string): Promise<WaveformData> {\n const response = await fetch(src);\n\n if (!response.ok) {\n throw new Error(`Failed to fetch waveform data: ${response.statusText}`);\n }\n\n // Check file extension to determine format\n const isBinary = src.endsWith('.dat');\n\n if (isBinary) {\n const arrayBuffer = await response.arrayBuffer();\n return WaveformData.create(arrayBuffer);\n } else {\n const json = await response.json();\n return WaveformData.create(json);\n }\n}\n\n/**\n * Convert WaveformData to our internal Peaks format\n *\n * @param waveformData - WaveformData instance from waveform-data.js\n * @param channelIndex - Channel index (0 for mono/left, 1 for right)\n * @returns Peaks data with alternating min/max values, preserving original bit depth\n */\nexport function waveformDataToPeaks(\n waveformData: WaveformData,\n channelIndex: number = 0\n): { data: Int8Array | Int16Array; bits: 8 | 16; length: number; sampleRate: number } {\n const channel = waveformData.channel(channelIndex);\n const bits = waveformData.bits as 8 | 16;\n\n // Get the min/max arrays to determine length\n const minArray = channel.min_array();\n const maxArray = channel.max_array();\n const length = minArray.length;\n\n // Use appropriate typed array based on source file bit depth\n // 8-bit: values range from -128 to 127\n // 16-bit: values range from -32768 to 32767\n const peaks = bits === 8\n ? new Int8Array(length * 2)\n : new Int16Array(length * 2);\n\n // Interleave min/max pairs\n for (let i = 0; i < length; i++) {\n peaks[i * 2] = minArray[i];\n peaks[i * 2 + 1] = maxArray[i];\n }\n\n return {\n data: peaks,\n bits,\n length,\n sampleRate: waveformData.sample_rate,\n };\n}\n\n/**\n * Load waveform data file and convert to Peaks format in one step\n *\n * @param src - URL to waveform data file (.dat or .json)\n * @param channelIndex - Channel index (default: 0)\n * @returns Peaks data ready for rendering\n */\nexport async function loadPeaksFromWaveformData(\n src: string,\n channelIndex: number = 0\n): Promise<{ data: Int8Array | Int16Array; bits: 8 | 16; length: number; sampleRate: number }> {\n const waveformData = await loadWaveformData(src);\n return waveformDataToPeaks(waveformData, channelIndex);\n}\n\n/**\n * Get metadata from waveform data file without converting to peaks\n *\n * @param src - URL to waveform data file\n * @returns Metadata (sample rate, channels, duration, bits, etc.)\n */\nexport async function getWaveformDataMetadata(src: string): Promise<{\n sampleRate: number;\n channels: number;\n duration: number;\n samplesPerPixel: number;\n length: number;\n bits: 8 | 16;\n}> {\n const waveformData = await loadWaveformData(src);\n\n return {\n sampleRate: waveformData.sample_rate,\n channels: waveformData.channels,\n duration: waveformData.duration,\n samplesPerPixel: waveformData.scale,\n length: waveformData.length,\n bits: waveformData.bits as 8 | 16,\n };\n}\n\n/**\n * Extract peaks from a WaveformData object at a specific scale (samplesPerPixel)\n * and optionally slice to a sample range.\n *\n * @param waveformData - WaveformData instance from waveform-data.js\n * @param samplesPerPixel - Target samples per pixel (will resample if different)\n * @param channelIndex - Channel index (default: 0)\n * @param offsetSamples - Optional start offset in samples (for clip trimming)\n * @param durationSamples - Optional duration in samples (for clip trimming)\n * @returns Peaks data ready for rendering\n */\nexport function extractPeaksFromWaveformData(\n waveformData: WaveformData,\n samplesPerPixel: number,\n channelIndex: number = 0,\n offsetSamples?: number,\n durationSamples?: number\n): { data: Int8Array | Int16Array; bits: 8 | 16; length: number } {\n let processedData = waveformData;\n\n // Slice if offset/duration specified (using index-based slicing for sample accuracy)\n if (offsetSamples !== undefined && durationSamples !== undefined) {\n // Convert samples to waveform data indices\n // waveformData.scale is the samples per pixel of the source data\n const sourceScale = waveformData.scale;\n const startIndex = Math.floor(offsetSamples / sourceScale);\n const endIndex = Math.ceil((offsetSamples + durationSamples) / sourceScale);\n processedData = processedData.slice({ startIndex, endIndex });\n }\n\n // Resample to target scale if different\n if (processedData.scale !== samplesPerPixel) {\n processedData = processedData.resample({ scale: samplesPerPixel });\n }\n\n // Convert to our peaks format\n const channel = processedData.channel(channelIndex);\n const bits = processedData.bits as 8 | 16;\n const minArray = channel.min_array();\n const maxArray = channel.max_array();\n const length = minArray.length;\n\n const peaks = bits === 8\n ? new Int8Array(length * 2)\n : new Int16Array(length * 2);\n\n for (let i = 0; i < length; i++) {\n peaks[i * 2] = minArray[i];\n peaks[i * 2 + 1] = maxArray[i];\n }\n\n return { data: peaks, bits, length };\n}\n","import React, { createContext, useContext, useEffect, useState, useCallback, useMemo, useRef, memo, useReducer, cloneElement, forwardRef } from 'react';\nimport { createPortal, unstable_batchedUpdates } from 'react-dom';\nimport { useUniqueId, getEventCoordinates, getWindow, isDocument, isHTMLElement, isSVGElement, canUseDOM, isWindow, isNode, getOwnerDocument, add, isKeyboardEvent, subtract, useLazyMemo, useInterval, usePrevious, useLatestValue, useEvent, useIsomorphicLayoutEffect, useNodeRef, findFirstFocusableNode, CSS } from '@dnd-kit/utilities';\nimport { useAnnouncement, HiddenText, LiveRegion } from '@dnd-kit/accessibility';\n\nconst DndMonitorContext = /*#__PURE__*/createContext(null);\n\nfunction useDndMonitor(listener) {\n const registerListener = useContext(DndMonitorContext);\n useEffect(() => {\n if (!registerListener) {\n throw new Error('useDndMonitor must be used within a children of <DndContext>');\n }\n\n const unsubscribe = registerListener(listener);\n return unsubscribe;\n }, [listener, registerListener]);\n}\n\nfunction useDndMonitorProvider() {\n const [listeners] = useState(() => new Set());\n const registerListener = useCallback(listener => {\n listeners.add(listener);\n return () => listeners.delete(listener);\n }, [listeners]);\n const dispatch = useCallback(_ref => {\n let {\n type,\n event\n } = _ref;\n listeners.forEach(listener => {\n var _listener$type;\n\n return (_listener$type = listener[type]) == null ? void 0 : _listener$type.call(listener, event);\n });\n }, [listeners]);\n return [dispatch, registerListener];\n}\n\nconst defaultScreenReaderInstructions = {\n draggable: \"\\n To pick up a draggable item, press the space bar.\\n While dragging, use the arrow keys to move the item.\\n Press space again to drop the item in its new position, or press escape to cancel.\\n \"\n};\nconst defaultAnnouncements = {\n onDragStart(_ref) {\n let {\n active\n } = _ref;\n return \"Picked up draggable item \" + active.id + \".\";\n },\n\n onDragOver(_ref2) {\n let {\n active,\n over\n } = _ref2;\n\n if (over) {\n return \"Draggable item \" + active.id + \" was moved over droppable area \" + over.id + \".\";\n }\n\n return \"Draggable item \" + active.id + \" is no longer over a droppable area.\";\n },\n\n onDragEnd(_ref3) {\n let {\n active,\n over\n } = _ref3;\n\n if (over) {\n return \"Draggable item \" + active.id + \" was dropped over droppable area \" + over.id;\n }\n\n return \"Draggable item \" + active.id + \" was dropped.\";\n },\n\n onDragCancel(_ref4) {\n let {\n active\n } = _ref4;\n return \"Dragging was cancelled. Draggable item \" + active.id + \" was dropped.\";\n }\n\n};\n\nfunction Accessibility(_ref) {\n let {\n announcements = defaultAnnouncements,\n container,\n hiddenTextDescribedById,\n screenReaderInstructions = defaultScreenReaderInstructions\n } = _ref;\n const {\n announce,\n announcement\n } = useAnnouncement();\n const liveRegionId = useUniqueId(\"DndLiveRegion\");\n const [mounted, setMounted] = useState(false);\n useEffect(() => {\n setMounted(true);\n }, []);\n useDndMonitor(useMemo(() => ({\n onDragStart(_ref2) {\n let {\n active\n } = _ref2;\n announce(announcements.onDragStart({\n active\n }));\n },\n\n onDragMove(_ref3) {\n let {\n active,\n over\n } = _ref3;\n\n if (announcements.onDragMove) {\n announce(announcements.onDragMove({\n active,\n over\n }));\n }\n },\n\n onDragOver(_ref4) {\n let {\n active,\n over\n } = _ref4;\n announce(announcements.onDragOver({\n active,\n over\n }));\n },\n\n onDragEnd(_ref5) {\n let {\n active,\n over\n } = _ref5;\n announce(announcements.onDragEnd({\n active,\n over\n }));\n },\n\n onDragCancel(_ref6) {\n let {\n active,\n over\n } = _ref6;\n announce(announcements.onDragCancel({\n active,\n over\n }));\n }\n\n }), [announce, announcements]));\n\n if (!mounted) {\n return null;\n }\n\n const markup = React.createElement(React.Fragment, null, React.createElement(HiddenText, {\n id: hiddenTextDescribedById,\n value: screenReaderInstructions.draggable\n }), React.createElement(LiveRegion, {\n id: liveRegionId,\n announcement: announcement\n }));\n return container ? createPortal(markup, container) : markup;\n}\n\nvar Action;\n\n(function (Action) {\n Action[\"DragStart\"] = \"dragStart\";\n Action[\"DragMove\"] = \"dragMove\";\n Action[\"DragEnd\"] = \"dragEnd\";\n Action[\"DragCancel\"] = \"dragCancel\";\n Action[\"DragOver\"] = \"dragOver\";\n Action[\"RegisterDroppable\"] = \"registerDroppable\";\n Action[\"SetDroppableDisabled\"] = \"setDroppableDisabled\";\n Action[\"UnregisterDroppable\"] = \"unregisterDroppable\";\n})(Action || (Action = {}));\n\nfunction noop() {}\n\nfunction useSensor(sensor, options) {\n return useMemo(() => ({\n sensor,\n options: options != null ? options : {}\n }), // eslint-disable-next-line react-hooks/exhaustive-deps\n [sensor, options]);\n}\n\nfunction useSensors() {\n for (var _len = arguments.length, sensors = new Array(_len), _key = 0; _key < _len; _key++) {\n sensors[_key] = arguments[_key];\n }\n\n return useMemo(() => [...sensors].filter(sensor => sensor != null), // eslint-disable-next-line react-hooks/exhaustive-deps\n [...sensors]);\n}\n\nconst defaultCoordinates = /*#__PURE__*/Object.freeze({\n x: 0,\n y: 0\n});\n\n/**\r\n * Returns the distance between two points\r\n */\nfunction distanceBetween(p1, p2) {\n return Math.sqrt(Math.pow(p1.x - p2.x, 2) + Math.pow(p1.y - p2.y, 2));\n}\n\nfunction getRelativeTransformOrigin(event, rect) {\n const eventCoordinates = getEventCoordinates(event);\n\n if (!eventCoordinates) {\n return '0 0';\n }\n\n const transformOrigin = {\n x: (eventCoordinates.x - rect.left) / rect.width * 100,\n y: (eventCoordinates.y - rect.top) / rect.height * 100\n };\n return transformOrigin.x + \"% \" + transformOrigin.y + \"%\";\n}\n\n/**\r\n * Sort collisions from smallest to greatest value\r\n */\nfunction sortCollisionsAsc(_ref, _ref2) {\n let {\n data: {\n value: a\n }\n } = _ref;\n let {\n data: {\n value: b\n }\n } = _ref2;\n return a - b;\n}\n/**\r\n * Sort collisions from greatest to smallest value\r\n */\n\nfunction sortCollisionsDesc(_ref3, _ref4) {\n let {\n data: {\n value: a\n }\n } = _ref3;\n let {\n data: {\n value: b\n }\n } = _ref4;\n return b - a;\n}\n/**\r\n * Returns the coordinates of the corners of a given rectangle:\r\n * [TopLeft {x, y}, TopRight {x, y}, BottomLeft {x, y}, BottomRight {x, y}]\r\n */\n\nfunction cornersOfRectangle(_ref5) {\n let {\n left,\n top,\n height,\n width\n } = _ref5;\n return [{\n x: left,\n y: top\n }, {\n x: left + width,\n y: top\n }, {\n x: left,\n y: top + height\n }, {\n x: left + width,\n y: top + height\n }];\n}\nfunction getFirstCollision(collisions, property) {\n if (!collisions || collisions.length === 0) {\n return null;\n }\n\n const [firstCollision] = collisions;\n return property ? firstCollision[property] : firstCollision;\n}\n\n/**\r\n * Returns the coordinates of the center of a given ClientRect\r\n */\n\nfunction centerOfRectangle(rect, left, top) {\n if (left === void 0) {\n left = rect.left;\n }\n\n if (top === void 0) {\n top = rect.top;\n }\n\n return {\n x: left + rect.width * 0.5,\n y: top + rect.height * 0.5\n };\n}\n/**\r\n * Returns the closest rectangles from an array of rectangles to the center of a given\r\n * rectangle.\r\n */\n\n\nconst closestCenter = _ref => {\n let {\n collisionRect,\n droppableRects,\n droppableContainers\n } = _ref;\n const centerRect = centerOfRectangle(collisionRect, collisionRect.left, collisionRect.top);\n const collisions = [];\n\n for (const droppableContainer of droppableContainers) {\n const {\n id\n } = droppableContainer;\n const rect = droppableRects.get(id);\n\n if (rect) {\n const distBetween = distanceBetween(centerOfRectangle(rect), centerRect);\n collisions.push({\n id,\n data: {\n droppableContainer,\n value: distBetween\n }\n });\n }\n }\n\n return collisions.sort(sortCollisionsAsc);\n};\n\n/**\r\n * Returns the closest rectangles from an array of rectangles to the corners of\r\n * another rectangle.\r\n */\n\nconst closestCorners = _ref => {\n let {\n collisionRect,\n droppableRects,\n droppableContainers\n } = _ref;\n const corners = cornersOfRectangle(collisionRect);\n const collisions = [];\n\n for (const droppableContainer of droppableContainers) {\n const {\n id\n } = droppableContainer;\n const rect = droppableRects.get(id);\n\n if (rect) {\n const rectCorners = cornersOfRectangle(rect);\n const distances = corners.reduce((accumulator, corner, index) => {\n return accumulator + distanceBetween(rectCorners[index], corner);\n }, 0);\n const effectiveDistance = Number((distances / 4).toFixed(4));\n collisions.push({\n id,\n data: {\n droppableContainer,\n value: effectiveDistance\n }\n });\n }\n }\n\n return collisions.sort(sortCollisionsAsc);\n};\n\n/**\r\n * Returns the intersecting rectangle area between two rectangles\r\n */\n\nfunction getIntersectionRatio(entry, target) {\n const top = Math.max(target.top, entry.top);\n const left = Math.max(target.left, entry.left);\n const right = Math.min(target.left + target.width, entry.left + entry.width);\n const bottom = Math.min(target.top + target.height, entry.top + entry.height);\n const width = right - left;\n const height = bottom - top;\n\n if (left < right && top < bottom) {\n const targetArea = target.width * target.height;\n const entryArea = entry.width * entry.height;\n const intersectionArea = width * height;\n const intersectionRatio = intersectionArea / (targetArea + entryArea - intersectionArea);\n return Number(intersectionRatio.toFixed(4));\n } // Rectangles do not overlap, or overlap has an area of zero (edge/corner overlap)\n\n\n return 0;\n}\n/**\r\n * Returns the rectangles that has the greatest intersection area with a given\r\n * rectangle in an array of rectangles.\r\n */\n\nconst rectIntersection = _ref => {\n let {\n collisionRect,\n droppableRects,\n droppableContainers\n } = _ref;\n const collisions = [];\n\n for (const droppableContainer of droppableContainers) {\n const {\n id\n } = droppableContainer;\n const rect = droppableRects.get(id);\n\n if (rect) {\n const intersectionRatio = getIntersectionRatio(rect, collisionRect);\n\n if (intersectionRatio > 0) {\n collisions.push({\n id,\n data: {\n droppableContainer,\n value: intersectionRatio\n }\n });\n }\n }\n }\n\n return collisions.sort(sortCollisionsDesc);\n};\n\n/**\r\n * Check if a given point is contained within a bounding rectangle\r\n */\n\nfunction isPointWithinRect(point, rect) {\n const {\n top,\n left,\n bottom,\n right\n } = rect;\n return top <= point.y && point.y <= bottom && left <= point.x && point.x <= right;\n}\n/**\r\n * Returns the rectangles that the pointer is hovering over\r\n */\n\n\nconst pointerWithin = _ref => {\n let {\n droppableContainers,\n droppableRects,\n pointerCoordinates\n } = _ref;\n\n if (!pointerCoordinates) {\n return [];\n }\n\n const collisions = [];\n\n for (const droppableContainer of droppableContainers) {\n const {\n id\n } = droppableContainer;\n const rect = droppableRects.get(id);\n\n if (rect && isPointWithinRect(pointerCoordinates, rect)) {\n /* There may be more than a single rectangle intersecting\r\n * with the pointer coordinates. In order to sort the\r\n * colliding rectangles, we measure the distance between\r\n * the pointer and the corners of the intersecting rectangle\r\n */\n const corners = cornersOfRectangle(rect);\n const distances = corners.reduce((accumulator, corner) => {\n return accumulator + distanceBetween(pointerCoordinates, corner);\n }, 0);\n const effectiveDistance = Number((distances / 4).toFixed(4));\n collisions.push({\n id,\n data: {\n droppableContainer,\n value: effectiveDistance\n }\n });\n }\n }\n\n return collisions.sort(sortCollisionsAsc);\n};\n\nfunction adjustScale(transform, rect1, rect2) {\n return { ...transform,\n scaleX: rect1 && rect2 ? rect1.width / rect2.width : 1,\n scaleY: rect1 && rect2 ? rect1.height / rect2.height : 1\n };\n}\n\nfunction getRectDelta(rect1, rect2) {\n return rect1 && rect2 ? {\n x: rect1.left - rect2.left,\n y: rect1.top - rect2.top\n } : defaultCoordinates;\n}\n\nfunction createRectAdjustmentFn(modifier) {\n return function adjustClientRect(rect) {\n for (var _len = arguments.length, adjustments = new Array(_len > 1 ? _len - 1 : 0), _key = 1; _key < _len; _key++) {\n adjustments[_key - 1] = arguments[_key];\n }\n\n return adjustments.reduce((acc, adjustment) => ({ ...acc,\n top: acc.top + modifier * adjustment.y,\n bottom: acc.bottom + modifier * adjustment.y,\n left: acc.left + modifier * adjustment.x,\n right: acc.right + modifier * adjustment.x\n }), { ...rect\n });\n };\n}\nconst getAdjustedRect = /*#__PURE__*/createRectAdjustmentFn(1);\n\nfunction parseTransform(transform) {\n if (transform.startsWith('matrix3d(')) {\n const transformArray = transform.slice(9, -1).split(/, /);\n return {\n x: +transformArray[12],\n y: +transformArray[13],\n scaleX: +transformArray[0],\n scaleY: +transformArray[5]\n };\n } else if (transform.startsWith('matrix(')) {\n const transformArray = transform.slice(7, -1).split(/, /);\n return {\n x: +transformArray[4],\n y: +transformArray[5],\n scaleX: +transformArray[0],\n scaleY: +transformArray[3]\n };\n }\n\n return null;\n}\n\nfunction inverseTransform(rect, transform, transformOrigin) {\n const parsedTransform = parseTransform(transform);\n\n if (!parsedTransform) {\n return rect;\n }\n\n const {\n scaleX,\n scaleY,\n x: translateX,\n y: translateY\n } = parsedTransform;\n const x = rect.left - translateX - (1 - scaleX) * parseFloat(transformOrigin);\n const y = rect.top - translateY - (1 - scaleY) * parseFloat(transformOrigin.slice(transformOrigin.indexOf(' ') + 1));\n const w = scaleX ? rect.width / scaleX : rect.width;\n const h = scaleY ? rect.height / scaleY : rect.height;\n return {\n width: w,\n height: h,\n top: y,\n right: x + w,\n bottom: y + h,\n left: x\n };\n}\n\nconst defaultOptions = {\n ignoreTransform: false\n};\n/**\r\n * Returns the bounding client rect of an element relative to the viewport.\r\n */\n\nfunction getClientRect(element, options) {\n if (options === void 0) {\n options = defaultOptions;\n }\n\n let rect = element.getBoundingClientRect();\n\n if (options.ignoreTransform) {\n const {\n transform,\n transformOrigin\n } = getWindow(element).getComputedStyle(element);\n\n if (transform) {\n rect = inverseTransform(rect, transform, transformOrigin);\n }\n }\n\n const {\n top,\n left,\n width,\n height,\n bottom,\n right\n } = rect;\n return {\n top,\n left,\n width,\n height,\n bottom,\n right\n };\n}\n/**\r\n * Returns the bounding client rect of an element relative to the viewport.\r\n *\r\n * @remarks\r\n * The ClientRect returned by this method does not take into account transforms\r\n * applied to the element it measures.\r\n *\r\n */\n\nfunction getTransformAgnosticClientRect(element) {\n return getClientRect(element, {\n ignoreTransform: true\n });\n}\n\nfunction getWindowClientRect(element) {\n const width = element.innerWidth;\n const height = element.innerHeight;\n return {\n top: 0,\n left: 0,\n right: width,\n bottom: height,\n width,\n height\n };\n}\n\nfunction isFixed(node, computedStyle) {\n if (computedStyle === void 0) {\n computedStyle = getWindow(node).getComputedStyle(node);\n }\n\n return computedStyle.position === 'fixed';\n}\n\nfunction isScrollable(element, computedStyle) {\n if (computedStyle === void 0) {\n computedStyle = getWindow(element).getComputedStyle(element);\n }\n\n const overflowRegex = /(auto|scroll|overlay)/;\n const properties = ['overflow', 'overflowX', 'overflowY'];\n return properties.some(property => {\n const value = computedStyle[property];\n return typeof value === 'string' ? overflowRegex.test(value) : false;\n });\n}\n\nfunction getScrollableAncestors(element, limit) {\n const scrollParents = [];\n\n function findScrollableAncestors(node) {\n if (limit != null && scrollParents.length >= limit) {\n return scrollParents;\n }\n\n if (!node) {\n return scrollParents;\n }\n\n if (isDocument(node) && node.scrollingElement != null && !scrollParents.includes(node.scrollingElement)) {\n scrollParents.push(node.scrollingElement);\n return scrollParents;\n }\n\n if (!isHTMLElement(node) || isSVGElement(node)) {\n return scrollParents;\n }\n\n if (scrollParents.includes(node)) {\n return scrollParents;\n }\n\n const computedStyle = getWindow(element).getComputedStyle(node);\n\n if (node !== element) {\n if (isScrollable(node, computedStyle)) {\n scrollParents.push(node);\n }\n }\n\n if (isFixed(node, computedStyle)) {\n return scrollParents;\n }\n\n return findScrollableAncestors(node.parentNode);\n }\n\n if (!element) {\n return scrollParents;\n }\n\n return findScrollableAncestors(element);\n}\nfunction getFirstScrollableAncestor(node) {\n const [firstScrollableAncestor] = getScrollableAncestors(node, 1);\n return firstScrollableAncestor != null ? firstScrollableAncestor : null;\n}\n\nfunction getScrollableElement(element) {\n if (!canUseDOM || !element) {\n return null;\n }\n\n if (isWindow(element)) {\n return element;\n }\n\n if (!isNode(element)) {\n return null;\n }\n\n if (isDocument(element) || element === getOwnerDocument(element).scrollingElement) {\n return window;\n }\n\n if (isHTMLElement(element)) {\n return element;\n }\n\n return null;\n}\n\nfunction getScrollXCoordinate(element) {\n if (isWindow(element)) {\n return element.scrollX;\n }\n\n return element.scrollLeft;\n}\nfunction getScrollYCoordinate(element) {\n if (isWindow(element)) {\n return element.scrollY;\n }\n\n return element.scrollTop;\n}\nfunction getScrollCoordinates(element) {\n return {\n x: getScrollXCoordinate(element),\n y: getScrollYCoordinate(element)\n };\n}\n\nvar Direction;\n\n(function (Direction) {\n Direction[Direction[\"Forward\"] = 1] = \"Forward\";\n Direction[Direction[\"Backward\"] = -1] = \"Backward\";\n})(Direction || (Direction = {}));\n\nfunction isDocumentScrollingElement(element) {\n if (!canUseDOM || !element) {\n return false;\n }\n\n return element === document.scrollingElement;\n}\n\nfunction getScrollPosition(scrollingContainer) {\n const minScroll = {\n x: 0,\n y: 0\n };\n const dimensions = isDocumentScrollingElement(scrollingContainer) ? {\n height: window.innerHeight,\n width: window.innerWidth\n } : {\n height: scrollingContainer.clientHeight,\n width: scrollingContainer.clientWidth\n };\n const maxScroll = {\n x: scrollingContainer.scrollWidth - dimensions.width,\n y: scrollingContainer.scrollHeight - dimensions.height\n };\n const isTop = scrollingContainer.scrollTop <= minScroll.y;\n const isLeft = scrollingContainer.scrollLeft <= minScroll.x;\n const isBottom = scrollingContainer.scrollTop >= maxScroll.y;\n const isRight = scrollingContainer.scrollLeft >= maxScroll.x;\n return {\n isTop,\n isLeft,\n isBottom,\n isRight,\n maxScroll,\n minScroll\n };\n}\n\nconst defaultThreshold = {\n x: 0.2,\n y: 0.2\n};\nfunction getScrollDirectionAndSpeed(scrollContainer, scrollContainerRect, _ref, acceleration, thresholdPercentage) {\n let {\n top,\n left,\n right,\n bottom\n } = _ref;\n\n if (acceleration === void 0) {\n acceleration = 10;\n }\n\n if (thresholdPercentage === void 0) {\n thresholdPercentage = defaultThreshold;\n }\n\n const {\n isTop,\n isBottom,\n isLeft,\n isRight\n } = getScrollPosition(scrollContainer);\n const direction = {\n x: 0,\n y: 0\n };\n const speed = {\n x: 0,\n y: 0\n };\n const threshold = {\n height: scrollContainerRect.height * thresholdPercentage.y,\n width: scrollContainerRect.width * thresholdPercentage.x\n };\n\n if (!isTop && top <= scrollContainerRect.top + threshold.height) {\n // Scroll Up\n direction.y = Direction.Backward;\n speed.y = acceleration * Math.abs((scrollContainerRect.top + threshold.height - top) / threshold.height);\n } else if (!isBottom && bottom >= scrollContainerRect.bottom - threshold.height) {\n // Scroll Down\n direction.y = Direction.Forward;\n speed.y = acceleration * Math.abs((scrollContainerRect.bottom - threshold.height - bottom) / threshold.height);\n }\n\n if (!isRight && right >= scrollContainerRect.right - threshold.width) {\n // Scroll Right\n direction.x = Direction.Forward;\n speed.x = acceleration * Math.abs((scrollContainerRect.right - threshold.width - right) / threshold.width);\n } else if (!isLeft && left <= scrollContainerRect.left + threshold.width) {\n // Scroll Left\n direction.x = Direction.Backward;\n speed.x = acceleration * Math.abs((scrollContainerRect.left + threshold.width - left) / threshold.width);\n }\n\n return {\n direction,\n speed\n };\n}\n\nfunction getScrollElementRect(element) {\n if (element === document.scrollingElement) {\n const {\n innerWidth,\n innerHeight\n } = window;\n return {\n top: 0,\n left: 0,\n right: innerWidth,\n bottom: innerHeight,\n width: innerWidth,\n height: innerHeight\n };\n }\n\n const {\n top,\n left,\n right,\n bottom\n } = element.getBoundingClientRect();\n return {\n top,\n left,\n right,\n bottom,\n width: element.clientWidth,\n height: element.clientHeight\n };\n}\n\nfunction getScrollOffsets(scrollableAncestors) {\n return scrollableAncestors.reduce((acc, node) => {\n return add(acc, getScrollCoordinates(node));\n }, defaultCoordinates);\n}\nfunction getScrollXOffset(scrollableAncestors) {\n return scrollableAncestors.reduce((acc, node) => {\n return acc + getScrollXCoordinate(node);\n }, 0);\n}\nfunction getScrollYOffset(scrollableAncestors) {\n return scrollableAncestors.reduce((acc, node) => {\n return acc + getScrollYCoordinate(node);\n }, 0);\n}\n\nfunction scrollIntoViewIfNeeded(element, measure) {\n if (measure === void 0) {\n measure = getClientRect;\n }\n\n if (!element) {\n return;\n }\n\n const {\n top,\n left,\n bottom,\n right\n } = measure(element);\n const firstScrollableAncestor = getFirstScrollableAncestor(element);\n\n if (!firstScrollableAncestor) {\n return;\n }\n\n if (bottom <= 0 || right <= 0 || top >= window.innerHeight || left >= window.innerWidth) {\n element.scrollIntoView({\n block: 'center',\n inline: 'center'\n });\n }\n}\n\nconst properties = [['x', ['left', 'right'], getScrollXOffset], ['y', ['top', 'bottom'], getScrollYOffset]];\nclass Rect {\n constructor(rect, element) {\n this.rect = void 0;\n this.width = void 0;\n this.height = void 0;\n this.top = void 0;\n this.bottom = void 0;\n this.right = void 0;\n this.left = void 0;\n const scrollableAncestors = getScrollableAncestors(element);\n const scrollOffsets = getScrollOffsets(scrollableAncestors);\n this.rect = { ...rect\n };\n this.width = rect.width;\n this.height = rect.height;\n\n for (const [axis, keys, getScrollOffset] of properties) {\n for (const key of keys) {\n Object.defineProperty(this, key, {\n get: () => {\n const currentOffsets = getScrollOffset(scrollableAncestors);\n const scrollOffsetsDeltla = scrollOffsets[axis] - currentOffsets;\n return this.rect[key] + scrollOffsetsDeltla;\n },\n enumerable: true\n });\n }\n }\n\n Object.defineProperty(this, 'rect', {\n enumerable: false\n });\n }\n\n}\n\nclass Listeners {\n constructor(target) {\n this.target = void 0;\n this.listeners = [];\n\n this.removeAll = () => {\n this.listeners.forEach(listener => {\n var _this$target;\n\n return (_this$target = this.target) == null ? void 0 : _this$target.removeEventListener(...listener);\n });\n };\n\n this.target = target;\n }\n\n add(eventName, handler, options) {\n var _this$target2;\n\n (_this$target2 = this.target) == null ? void 0 : _this$target2.addEventListener(eventName, handler, options);\n this.listeners.push([eventName, handler, options]);\n }\n\n}\n\nfunction getEventListenerTarget(target) {\n // If the `event.target` element is removed from the document events will still be targeted\n // at it, and hence won't always bubble up to the window or document anymore.\n // If there is any risk of an element being removed while it is being dragged,\n // the best practice is to attach the event listeners directly to the target.\n // https://developer.mozilla.org/en-US/docs/Web/API/EventTarget\n const {\n EventTarget\n } = getWindow(target);\n return target instanceof EventTarget ? target : getOwnerDocument(target);\n}\n\nfunction hasExceededDistance(delta, measurement) {\n const dx = Math.abs(delta.x);\n const dy = Math.abs(delta.y);\n\n if (typeof measurement === 'number') {\n return Math.sqrt(dx ** 2 + dy ** 2) > measurement;\n }\n\n if ('x' in measurement && 'y' in measurement) {\n return dx > measurement.x && dy > measurement.y;\n }\n\n if ('x' in measurement) {\n return dx > measurement.x;\n }\n\n if ('y' in measurement) {\n return dy > measurement.y;\n }\n\n return false;\n}\n\nvar EventName;\n\n(function (EventName) {\n EventName[\"Click\"] = \"click\";\n EventName[\"DragStart\"] = \"dragstart\";\n EventName[\"Keydown\"] = \"keydown\";\n EventName[\"ContextMenu\"] = \"contextmenu\";\n EventName[\"Resize\"] = \"resize\";\n EventName[\"SelectionChange\"] = \"selectionchange\";\n EventName[\"VisibilityChange\"] = \"visibilitychange\";\n})(EventName || (EventName = {}));\n\nfunction preventDefault(event) {\n event.preventDefault();\n}\nfunction stopPropagation(event) {\n event.stopPropagation();\n}\n\nvar KeyboardCode;\n\n(function (KeyboardCode) {\n KeyboardCode[\"Space\"] = \"Space\";\n KeyboardCode[\"Down\"] = \"ArrowDown\";\n KeyboardCode[\"Right\"] = \"ArrowRight\";\n KeyboardCode[\"Left\"] = \"ArrowLeft\";\n KeyboardCode[\"Up\"] = \"ArrowUp\";\n KeyboardCode[\"Esc\"] = \"Escape\";\n KeyboardCode[\"Enter\"] = \"Enter\";\n KeyboardCode[\"Tab\"] = \"Tab\";\n})(KeyboardCode || (KeyboardCode = {}));\n\nconst defaultKeyboardCodes = {\n start: [KeyboardCode.Space, KeyboardCode.Enter],\n cancel: [KeyboardCode.Esc],\n end: [KeyboardCode.Space, KeyboardCode.Enter, KeyboardCode.Tab]\n};\nconst defaultKeyboardCoordinateGetter = (event, _ref) => {\n let {\n currentCoordinates\n } = _ref;\n\n switch (event.code) {\n case KeyboardCode.Right:\n return { ...currentCoordinates,\n x: currentCoordinates.x + 25\n };\n\n case KeyboardCode.Left:\n return { ...currentCoordinates,\n x: currentCoordinates.x - 25\n };\n\n case KeyboardCode.Down:\n return { ...currentCoordinates,\n y: currentCoordinates.y + 25\n };\n\n case KeyboardCode.Up:\n return { ...currentCoordinates,\n y: currentCoordinates.y - 25\n };\n }\n\n return undefined;\n};\n\nclass KeyboardSensor {\n constructor(props) {\n this.props = void 0;\n this.autoScrollEnabled = false;\n this.referenceCoordinates = void 0;\n this.listeners = void 0;\n this.windowListeners = void 0;\n this.props = props;\n const {\n event: {\n target\n }\n } = props;\n this.props = props;\n this.listeners = new Listeners(getOwnerDocument(target));\n this.windowListeners = new Listeners(getWindow(target));\n this.handleKeyDown = this.handleKeyDown.bind(this);\n this.handleCancel = this.handleCancel.bind(this);\n this.attach();\n }\n\n attach() {\n this.handleStart();\n this.windowListeners.add(EventName.Resize, this.handleCancel);\n this.windowListeners.add(EventName.VisibilityChange, this.handleCancel);\n setTimeout(() => this.listeners.add(EventName.Keydown, this.handleKeyDown));\n }\n\n handleStart() {\n const {\n activeNode,\n onStart\n } = this.props;\n const node = activeNode.node.current;\n\n if (node) {\n scrollIntoViewIfNeeded(node);\n }\n\n onStart(defaultCoordinates);\n }\n\n handleKeyDown(event) {\n if (isKeyboardEvent(event)) {\n const {\n active,\n context,\n options\n } = this.props;\n const {\n keyboardCodes = defaultKeyboardCodes,\n coordinateGetter = defaultKeyboardCoordinateGetter,\n scrollBehavior = 'smooth'\n } = options;\n const {\n code\n } = event;\n\n if (keyboardCodes.end.includes(code)) {\n this.handleEnd(event);\n return;\n }\n\n if (keyboardCodes.cancel.includes(code)) {\n this.handleCancel(event);\n return;\n }\n\n const {\n collisionRect\n } = context.current;\n const currentCoordinates = collisionRect ? {\n x: collisionRect.left,\n y: collisionRect.top\n } : defaultCoordinates;\n\n if (!this.referenceCoordinates) {\n this.referenceCoordinates = currentCoordinates;\n }\n\n const newCoordinates = coordinateGetter(event, {\n active,\n context: context.current,\n currentCoordinates\n });\n\n if (newCoordinates) {\n const coordinatesDelta = subtract(newCoordinates, currentCoordinates);\n const scrollDelta = {\n x: 0,\n y: 0\n };\n const {\n scrollableAncestors\n } = context.current;\n\n for (const scrollContainer of scrollableAncestors) {\n const direction = event.code;\n const {\n isTop,\n isRight,\n isLeft,\n isBottom,\n maxScroll,\n minScroll\n } = getScrollPosition(scrollContainer);\n const scrollElementRect = getScrollElementRect(scrollContainer);\n const clampedCoordinates = {\n x: Math.min(direction === KeyboardCode.Right ? scrollElementRect.right - scrollElementRect.width / 2 : scrollElementRect.right, Math.max(direction === KeyboardCode.Right ? scrollElementRect.left : scrollElementRect.left + scrollElementRect.width / 2, newCoordinates.x)),\n y: Math.min(direction === KeyboardCode.Down ? scrollElementRect.bottom - scrollElementRect.height / 2 : scrollElementRect.bottom, Math.max(direction === KeyboardCode.Down ? scrollElementRect.top : scrollElementRect.top + scrollElementRect.height / 2, newCoordinates.y))\n };\n const canScrollX = direction === KeyboardCode.Right && !isRight || direction === KeyboardCode.Left && !isLeft;\n const canScrollY = direction === KeyboardCode.Down && !isBottom || direction === KeyboardCode.Up && !isTop;\n\n if (canScrollX && clampedCoordinates.x !== newCoordinates.x) {\n const newScrollCoordinates = scrollContainer.scrollLeft + coordinatesDelta.x;\n const canScrollToNewCoordinates = direction === KeyboardCode.Right && newScrollCoordinates <= maxScroll.x || direction === KeyboardCode.Left && newScrollCoordinates >= minScroll.x;\n\n if (canScrollToNewCoordinates && !coordinatesDelta.y) {\n // We don't need to update coordinates, the scroll adjustment alone will trigger\n // logic to auto-detect the new container we are over\n scrollContainer.scrollTo({\n left: newScrollCoordinates,\n behavior: scrollBehavior\n });\n return;\n }\n\n if (canScrollToNewCoordinates) {\n scrollDelta.x = scrollContainer.scrollLeft - newScrollCoordinates;\n } else {\n scrollDelta.x = direction === KeyboardCode.Right ? scrollContainer.scrollLeft - maxScroll.x : scrollContainer.scrollLeft - minScroll.x;\n }\n\n if (scrollDelta.x) {\n scrollContainer.scrollBy({\n left: -scrollDelta.x,\n behavior: scrollBehavior\n });\n }\n\n break;\n } else if (canScrollY && clampedCoordinates.y !== newCoordinates.y) {\n const newScrollCoordinates = scrollContainer.scrollTop + coordinatesDelta.y;\n const canScrollToNewCoordinates = direction === KeyboardCode.Down && newScrollCoordinates <= maxScroll.y || direction === KeyboardCode.Up && newScrollCoordinates >= minScroll.y;\n\n if (canScrollToNewCoordinates && !coordinatesDelta.x) {\n // We don't need to update coordinates, the scroll adjustment alone will trigger\n // logic to auto-detect the new container we are over\n scrollContainer.scrollTo({\n top: newScrollCoordinates,\n behavior: scrollBehavior\n });\n return;\n }\n\n if (canScrollToNewCoordinates) {\n scrollDelta.y = scrollContainer.scrollTop - newScrollCoordinates;\n } else {\n scrollDelta.y = direction === KeyboardCode.Down ? scrollContainer.scrollTop - maxScroll.y : scrollContainer.scrollTop - minScroll.y;\n }\n\n if (scrollDelta.y) {\n scrollContainer.scrollBy({\n top: -scrollDelta.y,\n behavior: scrollBehavior\n });\n }\n\n break;\n }\n }\n\n this.handleMove(event, add(subtract(newCoordinates, this.referenceCoordinates), scrollDelta));\n }\n }\n }\n\n handleMove(event, coordinates) {\n const {\n onMove\n } = this.props;\n event.preventDefault();\n onMove(coordinates);\n }\n\n handleEnd(event) {\n const {\n onEnd\n } = this.props;\n event.preventDefault();\n this.detach();\n onEnd();\n }\n\n handleCancel(event) {\n const {\n onCancel\n } = this.props;\n event.preventDefault();\n this.detach();\n onCancel();\n }\n\n detach() {\n this.listeners.removeAll();\n this.windowListeners.removeAll();\n }\n\n}\nKeyboardSensor.activators = [{\n eventName: 'onKeyDown',\n handler: (event, _ref, _ref2) => {\n let {\n keyboardCodes = defaultKeyboardCodes,\n onActivation\n } = _ref;\n let {\n active\n } = _ref2;\n const {\n code\n } = event.nativeEvent;\n\n if (keyboardCodes.start.includes(code)) {\n const activator = active.activatorNode.current;\n\n if (activator && event.target !== activator) {\n return false;\n }\n\n event.preventDefault();\n onActivation == null ? void 0 : onActivation({\n event: event.nativeEvent\n });\n return true;\n }\n\n return false;\n }\n}];\n\nfunction isDistanceConstraint(constraint) {\n return Boolean(constraint && 'distance' in constraint);\n}\n\nfunction isDelayConstraint(constraint) {\n return Boolean(constraint && 'delay' in constraint);\n}\n\nclass AbstractPointerSensor {\n constructor(props, events, listenerTarget) {\n var _getEventCoordinates;\n\n if (listenerTarget === void 0) {\n listenerTarget = getEventListenerTarget(props.event.target);\n }\n\n this.props = void 0;\n this.events = void 0;\n this.autoScrollEnabled = true;\n this.document = void 0;\n this.activated = false;\n this.initialCoordinates = void 0;\n this.timeoutId = null;\n this.listeners = void 0;\n this.documentListeners = void 0;\n this.windowListeners = void 0;\n this.props = props;\n this.events = events;\n const {\n event\n } = props;\n const {\n target\n } = event;\n this.props = props;\n this.events = events;\n this.document = getOwnerDocument(target);\n this.documentListeners = new Listeners(this.document);\n this.listeners = new Listeners(listenerTarget);\n this.windowListeners = new Listeners(getWindow(target));\n this.initialCoordinates = (_getEventCoordinates = getEventCoordinates(event)) != null ? _getEventCoordinates : defaultCoordinates;\n this.handleStart = this.handleStart.bind(this);\n this.handleMove = this.handleMove.bind(this);\n this.handleEnd = this.handleEnd.bind(this);\n this.handleCancel = this.handleCancel.bind(this);\n this.handleKeydown = this.handleKeydown.bind(this);\n this.removeTextSelection = this.removeTextSelection.bind(this);\n this.attach();\n }\n\n attach() {\n const {\n events,\n props: {\n options: {\n activationConstraint,\n bypassActivationConstraint\n }\n }\n } = this;\n this.listeners.add(events.move.name, this.handleMove, {\n passive: false\n });\n this.listeners.add(events.end.name, this.handleEnd);\n\n if (events.cancel) {\n this.listeners.add(events.cancel.name, this.handleCancel);\n }\n\n this.windowListeners.add(EventName.Resize, this.handleCancel);\n this.windowListeners.add(EventName.DragStart, preventDefault);\n this.windowListeners.add(EventName.VisibilityChange, this.handleCancel);\n this.windowListeners.add(EventName.ContextMenu, preventDefault);\n this.documentListeners.add(EventName.Keydown, this.handleKeydown);\n\n if (activationConstraint) {\n if (bypassActivationConstraint != null && bypassActivationConstraint({\n event: this.props.event,\n activeNode: this.props.activeNode,\n options: this.props.options\n })) {\n return this.handleStart();\n }\n\n if (isDelayConstraint(activationConstraint)) {\n this.timeoutId = setTimeout(this.handleStart, activationConstraint.delay);\n this.handlePending(activationConstraint);\n return;\n }\n\n if (isDistanceConstraint(activationConstraint)) {\n this.handlePending(activationConstraint);\n return;\n }\n }\n\n this.handleStart();\n }\n\n detach() {\n this.listeners.removeAll();\n this.windowListeners.removeAll(); // Wait until the next event loop before removing document listeners\n // This is necessary because we listen for `click` and `selection` events on the document\n\n setTimeout(this.documentListeners.removeAll, 50);\n\n if (this.timeoutId !== null) {\n clearTimeout(this.timeoutId);\n this.timeoutId = null;\n }\n }\n\n handlePending(constraint, offset) {\n const {\n active,\n onPending\n } = this.props;\n onPending(active, constraint, this.initialCoordinates, offset);\n }\n\n handleStart() {\n const {\n initialCoordinates\n } = this;\n const {\n onStart\n } = this.props;\n\n if (initialCoordinates) {\n this.activated = true; // Stop propagation of click events once activation constraints are met\n\n this.documentListeners.add(EventName.Click, stopPropagation, {\n capture: true\n }); // Remove any text selection from the document\n\n this.removeTextSelection(); // Prevent further text selection while dragging\n\n this.documentListeners.add(EventName.SelectionChange, this.removeTextSelection);\n onStart(initialCoordinates);\n }\n }\n\n handleMove(event) {\n var _getEventCoordinates2;\n\n const {\n activated,\n initialCoordinates,\n props\n } = this;\n const {\n onMove,\n options: {\n activationConstraint\n }\n } = props;\n\n if (!initialCoordinates) {\n return;\n }\n\n const coordinates = (_getEventCoordinates2 = getEventCoordinates(event)) != null ? _getEventCoordinates2 : defaultCoordinates;\n const delta = subtract(initialCoordinates, coordinates); // Constraint validation\n\n if (!activated && activationConstraint) {\n if (isDistanceConstraint(activationConstraint)) {\n if (activationConstraint.tolerance != null && hasExceededDistance(delta, activationConstraint.tolerance)) {\n return this.handleCancel();\n }\n\n if (hasExceededDistance(delta, activationConstraint.distance)) {\n return this.handleStart();\n }\n }\n\n if (isDelayConstraint(activationConstraint)) {\n if (hasExceededDistance(delta, activationConstraint.tolerance)) {\n return this.handleCancel();\n }\n }\n\n this.handlePending(activationConstraint, delta);\n return;\n }\n\n if (event.cancelable) {\n event.preventDefault();\n }\n\n onMove(coordinates);\n }\n\n handleEnd() {\n const {\n onAbort,\n onEnd\n } = this.props;\n this.detach();\n\n if (!this.activated) {\n onAbort(this.props.active);\n }\n\n onEnd();\n }\n\n handleCancel() {\n const {\n onAbort,\n onCancel\n } = this.props;\n this.detach();\n\n if (!this.activated) {\n onAbort(this.props.active);\n }\n\n onCancel();\n }\n\n handleKeydown(event) {\n if (event.code === KeyboardCode.Esc) {\n this.handleCancel();\n }\n }\n\n removeTextSelection() {\n var _this$document$getSel;\n\n (_this$document$getSel = this.document.getSelection()) == null ? void 0 : _this$document$getSel.removeAllRanges();\n }\n\n}\n\nconst events = {\n cancel: {\n name: 'pointercancel'\n },\n move: {\n name: 'pointermove'\n },\n end: {\n name: 'pointerup'\n }\n};\nclass PointerSensor extends AbstractPointerSensor {\n constructor(props) {\n const {\n event\n } = props; // Pointer events stop firing if the target is unmounted while dragging\n // Therefore we attach listeners to the owner document instead\n\n const listenerTarget = getOwnerDocument(event.target);\n super(props, events, listenerTarget);\n }\n\n}\nPointerSensor.activators = [{\n eventName: 'onPointerDown',\n handler: (_ref, _ref2) => {\n let {\n nativeEvent: event\n } = _ref;\n let {\n onActivation\n } = _ref2;\n\n if (!event.isPrimary || event.button !== 0) {\n return false;\n }\n\n onActivation == null ? void 0 : onActivation({\n event\n });\n return true;\n }\n}];\n\nconst events$1 = {\n move: {\n name: 'mousemove'\n },\n end: {\n name: 'mouseup'\n }\n};\nvar MouseButton;\n\n(function (MouseButton) {\n MouseButton[MouseButton[\"RightClick\"] = 2] = \"RightClick\";\n})(MouseButton || (MouseButton = {}));\n\nclass MouseSensor extends AbstractPointerSensor {\n constructor(props) {\n super(props, events$1, getOwnerDocument(props.event.target));\n }\n\n}\nMouseSensor.activators = [{\n eventName: 'onMouseDown',\n handler: (_ref, _ref2) => {\n let {\n nativeEvent: event\n } = _ref;\n let {\n onActivation\n } = _ref2;\n\n if (event.button === MouseButton.RightClick) {\n return false;\n }\n\n onActivation == null ? void 0 : onActivation({\n event\n });\n return true;\n }\n}];\n\nconst events$2 = {\n cancel: {\n name: 'touchcancel'\n },\n move: {\n name: 'touchmove'\n },\n end: {\n name: 'touchend'\n }\n};\nclass TouchSensor extends AbstractPointerSensor {\n constructor(props) {\n super(props, events$2);\n }\n\n static setup() {\n // Adding a non-capture and non-passive `touchmove` listener in order\n // to force `event.preventDefault()` calls to work in dynamically added\n // touchmove event handlers. This is required for iOS Safari.\n window.addEventListener(events$2.move.name, noop, {\n capture: false,\n passive: false\n });\n return function teardown() {\n window.removeEventListener(events$2.move.name, noop);\n }; // We create a new handler because the teardown function of another sensor\n // could remove our event listener if we use a referentially equal listener.\n\n function noop() {}\n }\n\n}\nTouchSensor.activators = [{\n eventName: 'onTouchStart',\n handler: (_ref, _ref2) => {\n let {\n nativeEvent: event\n } = _ref;\n let {\n onActivation\n } = _ref2;\n const {\n touches\n } = event;\n\n if (touches.length > 1) {\n return false;\n }\n\n onActivation == null ? void 0 : onActivation({\n event\n });\n return true;\n }\n}];\n\nvar AutoScrollActivator;\n\n(function (AutoScrollActivator) {\n AutoScrollActivator[AutoScrollActivator[\"Pointer\"] = 0] = \"Pointer\";\n AutoScrollActivator[AutoScrollActivator[\"DraggableRect\"] = 1] = \"DraggableRect\";\n})(AutoScrollActivator || (AutoScrollActivator = {}));\n\nvar TraversalOrder;\n\n(function (TraversalOrder) {\n TraversalOrder[TraversalOrder[\"TreeOrder\"] = 0] = \"TreeOrder\";\n TraversalOrder[TraversalOrder[\"ReversedTreeOrder\"] = 1] = \"ReversedTreeOrder\";\n})(TraversalOrder || (TraversalOrder = {}));\n\nfunction useAutoScroller(_ref) {\n let {\n acceleration,\n activator = AutoScrollActivator.Pointer,\n canScroll,\n draggingRect,\n enabled,\n interval = 5,\n order = TraversalOrder.TreeOrder,\n pointerCoordinates,\n scrollableAncestors,\n scrollableAncestorRects,\n delta,\n threshold\n } = _ref;\n const scrollIntent = useScrollIntent({\n delta,\n disabled: !enabled\n });\n const [setAutoScrollInterval, clearAutoScrollInterval] = useInterval();\n const scrollSpeed = useRef({\n x: 0,\n y: 0\n });\n const scrollDirection = useRef({\n x: 0,\n y: 0\n });\n const rect = useMemo(() => {\n switch (activator) {\n case AutoScrollActivator.Pointer:\n return pointerCoordinates ? {\n top: pointerCoordinates.y,\n bottom: pointerCoordinates.y,\n left: pointerCoordinates.x,\n right: pointerCoordinates.x\n } : null;\n\n case AutoScrollActivator.DraggableRect:\n return draggingRect;\n }\n }, [activator, draggingRect, pointerCoordinates]);\n const scrollContainerRef = useRef(null);\n const autoScroll = useCallback(() => {\n const scrollContainer = scrollContainerRef.current;\n\n if (!scrollContainer) {\n return;\n }\n\n const scrollLeft = scrollSpeed.current.x * scrollDirection.current.x;\n const scrollTop = scrollSpeed.current.y * scrollDirection.current.y;\n scrollContainer.scrollBy(scrollLeft, scrollTop);\n }, []);\n const sortedScrollableAncestors = useMemo(() => order === TraversalOrder.TreeOrder ? [...scrollableAncestors].reverse() : scrollableAncestors, [order, scrollableAncestors]);\n useEffect(() => {\n if (!enabled || !scrollableAncestors.length || !rect) {\n clearAutoScrollInterval();\n return;\n }\n\n for (const scrollContainer of sortedScrollableAncestors) {\n if ((canScroll == null ? void 0 : canScroll(scrollContainer)) === false) {\n continue;\n }\n\n const index = scrollableAncestors.indexOf(scrollContainer);\n const scrollContainerRect = scrollableAncestorRects[index];\n\n if (!scrollContainerRect) {\n continue;\n }\n\n const {\n direction,\n speed\n } = getScrollDirectionAndSpeed(scrollContainer, scrollContainerRect, rect, acceleration, threshold);\n\n for (const axis of ['x', 'y']) {\n if (!scrollIntent[axis][direction[axis]]) {\n speed[axis] = 0;\n direction[axis] = 0;\n }\n }\n\n if (speed.x > 0 || speed.y > 0) {\n clearAutoScrollInterval();\n scrollContainerRef.current = scrollContainer;\n setAutoScrollInterval(autoScroll, interval);\n scrollSpeed.current = speed;\n scrollDirection.current = direction;\n return;\n }\n }\n\n scrollSpeed.current = {\n x: 0,\n y: 0\n };\n scrollDirection.current = {\n x: 0,\n y: 0\n };\n clearAutoScrollInterval();\n }, // eslint-disable-next-line react-hooks/exhaustive-deps\n [acceleration, autoScroll, canScroll, clearAutoScrollInterval, enabled, interval, // eslint-disable-next-line react-hooks/exhaustive-deps\n JSON.stringify(rect), // eslint-disable-next-line react-hooks/exhaustive-deps\n JSON.stringify(scrollIntent), setAutoScrollInterval, scrollableAncestors, sortedScrollableAncestors, scrollableAncestorRects, // eslint-disable-next-line react-hooks/exhaustive-deps\n JSON.stringify(threshold)]);\n}\nconst defaultScrollIntent = {\n x: {\n [Direction.Backward]: false,\n [Direction.Forward]: false\n },\n y: {\n [Direction.Backward]: false,\n [Direction.Forward]: false\n }\n};\n\nfunction useScrollIntent(_ref2) {\n let {\n delta,\n disabled\n } = _ref2;\n const previousDelta = usePrevious(delta);\n return useLazyMemo(previousIntent => {\n if (disabled || !previousDelta || !previousIntent) {\n // Reset scroll intent tracking when auto-scrolling is disabled\n return defaultScrollIntent;\n }\n\n const direction = {\n x: Math.sign(delta.x - previousDelta.x),\n y: Math.sign(delta.y - previousDelta.y)\n }; // Keep track of the user intent to scroll in each direction for both axis\n\n return {\n x: {\n [Direction.Backward]: previousIntent.x[Direction.Backward] || direction.x === -1,\n [Direction.Forward]: previousIntent.x[Direction.Forward] || direction.x === 1\n },\n y: {\n [Direction.Backward]: previousIntent.y[Direction.Backward] || direction.y === -1,\n [Direction.Forward]: previousIntent.y[Direction.Forward] || direction.y === 1\n }\n };\n }, [disabled, delta, previousDelta]);\n}\n\nfunction useCachedNode(draggableNodes, id) {\n const draggableNode = id != null ? draggableNodes.get(id) : undefined;\n const node = draggableNode ? draggableNode.node.current : null;\n return useLazyMemo(cachedNode => {\n var _ref;\n\n if (id == null) {\n return null;\n } // In some cases, the draggable node can unmount while dragging\n // This is the case for virtualized lists. In those situations,\n // we fall back to the last known value for that node.\n\n\n return (_ref = node != null ? node : cachedNode) != null ? _ref : null;\n }, [node, id]);\n}\n\nfunction useCombineActivators(sensors, getSyntheticHandler) {\n return useMemo(() => sensors.reduce((accumulator, sensor) => {\n const {\n sensor: Sensor\n } = sensor;\n const sensorActivators = Sensor.activators.map(activator => ({\n eventName: activator.eventName,\n handler: getSyntheticHandler(activator.handler, sensor)\n }));\n return [...accumulator, ...sensorActivators];\n }, []), [sensors, getSyntheticHandler]);\n}\n\nvar MeasuringStrategy;\n\n(function (MeasuringStrategy) {\n MeasuringStrategy[MeasuringStrategy[\"Always\"] = 0] = \"Always\";\n MeasuringStrategy[MeasuringStrategy[\"BeforeDragging\"] = 1] = \"BeforeDragging\";\n MeasuringStrategy[MeasuringStrategy[\"WhileDragging\"] = 2] = \"WhileDragging\";\n})(MeasuringStrategy || (MeasuringStrategy = {}));\n\nvar MeasuringFrequency;\n\n(function (MeasuringFrequency) {\n MeasuringFrequency[\"Optimized\"] = \"optimized\";\n})(MeasuringFrequency || (MeasuringFrequency = {}));\n\nconst defaultValue = /*#__PURE__*/new Map();\nfunction useDroppableMeasuring(containers, _ref) {\n let {\n dragging,\n dependencies,\n config\n } = _ref;\n const [queue, setQueue] = useState(null);\n const {\n frequency,\n measure,\n strategy\n } = config;\n const containersRef = useRef(containers);\n const disabled = isDisabled();\n const disabledRef = useLatestValue(disabled);\n const measureDroppableContainers = useCallback(function (ids) {\n if (ids === void 0) {\n ids = [];\n }\n\n if (disabledRef.current) {\n return;\n }\n\n setQueue(value => {\n if (value === null) {\n return ids;\n }\n\n return value.concat(ids.filter(id => !value.includes(id)));\n });\n }, [disabledRef]);\n const timeoutId = useRef(null);\n const droppableRects = useLazyMemo(previousValue => {\n if (disabled && !dragging) {\n return defaultValue;\n }\n\n if (!previousValue || previousValue === defaultValue || containersRef.current !== containers || queue != null) {\n const map = new Map();\n\n for (let container of containers) {\n if (!container) {\n continue;\n }\n\n if (queue && queue.length > 0 && !queue.includes(container.id) && container.rect.current) {\n // This container does not need to be re-measured\n map.set(container.id, container.rect.current);\n continue;\n }\n\n const node = container.node.current;\n const rect = node ? new Rect(measure(node), node) : null;\n container.rect.current = rect;\n\n if (rect) {\n map.set(container.id, rect);\n }\n }\n\n return map;\n }\n\n return previousValue;\n }, [containers, queue, dragging, disabled, measure]);\n useEffect(() => {\n containersRef.current = containers;\n }, [containers]);\n useEffect(() => {\n if (disabled) {\n return;\n }\n\n measureDroppableContainers();\n }, // eslint-disable-next-line react-hooks/exhaustive-deps\n [dragging, disabled]);\n useEffect(() => {\n if (queue && queue.length > 0) {\n setQueue(null);\n }\n }, //eslint-disable-next-line react-hooks/exhaustive-deps\n [JSON.stringify(queue)]);\n useEffect(() => {\n if (disabled || typeof frequency !== 'number' || timeoutId.current !== null) {\n return;\n }\n\n timeoutId.current = setTimeout(() => {\n measureDroppableContainers();\n timeoutId.current = null;\n }, frequency);\n }, // eslint-disable-next-line react-hooks/exhaustive-deps\n [frequency, disabled, measureDroppableContainers, ...dependencies]);\n return {\n droppableRects,\n measureDroppableContainers,\n measuringScheduled: queue != null\n };\n\n function isDisabled() {\n switch (strategy) {\n case MeasuringStrategy.Always:\n return false;\n\n case MeasuringStrategy.BeforeDragging:\n return dragging;\n\n default:\n return !dragging;\n }\n }\n}\n\nfunction useInitialValue(value, computeFn) {\n return useLazyMemo(previousValue => {\n if (!value) {\n return null;\n }\n\n if (previousValue) {\n return previousValue;\n }\n\n return typeof computeFn === 'function' ? computeFn(value) : value;\n }, [computeFn, value]);\n}\n\nfunction useInitialRect(node, measure) {\n return useInitialValue(node, measure);\n}\n\n/**\r\n * Returns a new MutationObserver instance.\r\n * If `MutationObserver` is undefined in the execution environment, returns `undefined`.\r\n */\n\nfunction useMutationObserver(_ref) {\n let {\n callback,\n disabled\n } = _ref;\n const handleMutations = useEvent(callback);\n const mutationObserver = useMemo(() => {\n if (disabled || typeof window === 'undefined' || typeof window.MutationObserver === 'undefined') {\n return undefined;\n }\n\n const {\n MutationObserver\n } = window;\n return new MutationObserver(handleMutations);\n }, [handleMutations, disabled]);\n useEffect(() => {\n return () => mutationObserver == null ? void 0 : mutationObserver.disconnect();\n }, [mutationObserver]);\n return mutationObserver;\n}\n\n/**\r\n * Returns a new ResizeObserver instance bound to the `onResize` callback.\r\n * If `ResizeObserver` is undefined in the execution environment, returns `undefined`.\r\n */\n\nfunction useResizeObserver(_ref) {\n let {\n callback,\n disabled\n } = _ref;\n const handleResize = useEvent(callback);\n const resizeObserver = useMemo(() => {\n if (disabled || typeof window === 'undefined' || typeof window.ResizeObserver === 'undefined') {\n return undefined;\n }\n\n const {\n ResizeObserver\n } = window;\n return new ResizeObserver(handleResize);\n }, // eslint-disable-next-line react-hooks/exhaustive-deps\n [disabled]);\n useEffect(() => {\n return () => resizeObserver == null ? void 0 : resizeObserver.disconnect();\n }, [resizeObserver]);\n return resizeObserver;\n}\n\nfunction defaultMeasure(element) {\n return new Rect(getClientRect(element), element);\n}\n\nfunction useRect(element, measure, fallbackRect) {\n if (measure === void 0) {\n measure = defaultMeasure;\n }\n\n const [rect, setRect] = useState(null);\n\n function measureRect() {\n setRect(currentRect => {\n if (!element) {\n return null;\n }\n\n if (element.isConnected === false) {\n var _ref;\n\n // Fall back to last rect we measured if the element is\n // no longer connected to the DOM.\n return (_ref = currentRect != null ? currentRect : fallbackRect) != null ? _ref : null;\n }\n\n const newRect = measure(element);\n\n if (JSON.stringify(currentRect) === JSON.stringify(newRect)) {\n return currentRect;\n }\n\n return newRect;\n });\n }\n\n const mutationObserver = useMutationObserver({\n callback(records) {\n if (!element) {\n return;\n }\n\n for (const record of records) {\n const {\n type,\n target\n } = record;\n\n if (type === 'childList' && target instanceof HTMLElement && target.contains(element)) {\n measureRect();\n break;\n }\n }\n }\n\n });\n const resizeObserver = useResizeObserver({\n callback: measureRect\n });\n useIsomorphicLayoutEffect(() => {\n measureRect();\n\n if (element) {\n resizeObserver == null ? void 0 : resizeObserver.observe(element);\n mutationObserver == null ? void 0 : mutationObserver.observe(document.body, {\n childList: true,\n subtree: true\n });\n } else {\n resizeObserver == null ? void 0 : resizeObserver.disconnect();\n mutationObserver == null ? void 0 : mutationObserver.disconnect();\n }\n }, [element]);\n return rect;\n}\n\nfunction useRectDelta(rect) {\n const initialRect = useInitialValue(rect);\n return getRectDelta(rect, initialRect);\n}\n\nconst defaultValue$1 = [];\nfunction useScrollableAncestors(node) {\n const previousNode = useRef(node);\n const ancestors = useLazyMemo(previousValue => {\n if (!node) {\n return defaultValue$1;\n }\n\n if (previousValue && previousValue !== defaultValue$1 && node && previousNode.current && node.parentNode === previousNode.current.parentNode) {\n return previousValue;\n }\n\n return getScrollableAncestors(node);\n }, [node]);\n useEffect(() => {\n previousNode.current = node;\n }, [node]);\n return ancestors;\n}\n\nfunction useScrollOffsets(elements) {\n const [scrollCoordinates, setScrollCoordinates] = useState(null);\n const prevElements = useRef(elements); // To-do: Throttle the handleScroll callback\n\n const handleScroll = useCallback(event => {\n const scrollingElement = getScrollableElement(event.target);\n\n if (!scrollingElement) {\n return;\n }\n\n setScrollCoordinates(scrollCoordinates => {\n if (!scrollCoordinates) {\n return null;\n }\n\n scrollCoordinates.set(scrollingElement, getScrollCoordinates(scrollingElement));\n return new Map(scrollCoordinates);\n });\n }, []);\n useEffect(() => {\n const previousElements = prevElements.current;\n\n if (elements !== previousElements) {\n cleanup(previousElements);\n const entries = elements.map(element => {\n const scrollableElement = getScrollableElement(element);\n\n if (scrollableElement) {\n scrollableElement.addEventListener('scroll', handleScroll, {\n passive: true\n });\n return [scrollableElement, getScrollCoordinates(scrollableElement)];\n }\n\n return null;\n }).filter(entry => entry != null);\n setScrollCoordinates(entries.length ? new Map(entries) : null);\n prevElements.current = elements;\n }\n\n return () => {\n cleanup(elements);\n cleanup(previousElements);\n };\n\n function cleanup(elements) {\n elements.forEach(element => {\n const scrollableElement = getScrollableElement(element);\n scrollableElement == null ? void 0 : scrollableElement.removeEventListener('scroll', handleScroll);\n });\n }\n }, [handleScroll, elements]);\n return useMemo(() => {\n if (elements.length) {\n return scrollCoordinates ? Array.from(scrollCoordinates.values()).reduce((acc, coordinates) => add(acc, coordinates), defaultCoordinates) : getScrollOffsets(elements);\n }\n\n return defaultCoordinates;\n }, [elements, scrollCoordinates]);\n}\n\nfunction useScrollOffsetsDelta(scrollOffsets, dependencies) {\n if (dependencies === void 0) {\n dependencies = [];\n }\n\n const initialScrollOffsets = useRef(null);\n useEffect(() => {\n initialScrollOffsets.current = null;\n }, // eslint-disable-next-line react-hooks/exhaustive-deps\n dependencies);\n useEffect(() => {\n const hasScrollOffsets = scrollOffsets !== defaultCoordinates;\n\n if (hasScrollOffsets && !initialScrollOffsets.current) {\n initialScrollOffsets.current = scrollOffsets;\n }\n\n if (!hasScrollOffsets && initialScrollOffsets.current) {\n initialScrollOffsets.current = null;\n }\n }, [scrollOffsets]);\n return initialScrollOffsets.current ? subtract(scrollOffsets, initialScrollOffsets.current) : defaultCoordinates;\n}\n\nfunction useSensorSetup(sensors) {\n useEffect(() => {\n if (!canUseDOM) {\n return;\n }\n\n const teardownFns = sensors.map(_ref => {\n let {\n sensor\n } = _ref;\n return sensor.setup == null ? void 0 : sensor.setup();\n });\n return () => {\n for (const teardown of teardownFns) {\n teardown == null ? void 0 : teardown();\n }\n };\n }, // TO-DO: Sensors length could theoretically change which would not be a valid dependency\n // eslint-disable-next-line react-hooks/exhaustive-deps\n sensors.map(_ref2 => {\n let {\n sensor\n } = _ref2;\n return sensor;\n }));\n}\n\nfunction useSyntheticListeners(listeners, id) {\n return useMemo(() => {\n return listeners.reduce((acc, _ref) => {\n let {\n eventName,\n handler\n } = _ref;\n\n acc[eventName] = event => {\n handler(event, id);\n };\n\n return acc;\n }, {});\n }, [listeners, id]);\n}\n\nfunction useWindowRect(element) {\n return useMemo(() => element ? getWindowClientRect(element) : null, [element]);\n}\n\nconst defaultValue$2 = [];\nfunction useRects(elements, measure) {\n if (measure === void 0) {\n measure = getClientRect;\n }\n\n const [firstElement] = elements;\n const windowRect = useWindowRect(firstElement ? getWindow(firstElement) : null);\n const [rects, setRects] = useState(defaultValue$2);\n\n function measureRects() {\n setRects(() => {\n if (!elements.length) {\n return defaultValue$2;\n }\n\n return elements.map(element => isDocumentScrollingElement(element) ? windowRect : new Rect(measure(element), element));\n });\n }\n\n const resizeObserver = useResizeObserver({\n callback: measureRects\n });\n useIsomorphicLayoutEffect(() => {\n resizeObserver == null ? void 0 : resizeObserver.disconnect();\n measureRects();\n elements.forEach(element => resizeObserver == null ? void 0 : resizeObserver.observe(element));\n }, [elements]);\n return rects;\n}\n\nfunction getMeasurableNode(node) {\n if (!node) {\n return null;\n }\n\n if (node.children.length > 1) {\n return node;\n }\n\n const firstChild = node.children[0];\n return isHTMLElement(firstChild) ? firstChild : node;\n}\n\nfunction useDragOverlayMeasuring(_ref) {\n let {\n measure\n } = _ref;\n const [rect, setRect] = useState(null);\n const handleResize = useCallback(entries => {\n for (const {\n target\n } of entries) {\n if (isHTMLElement(target)) {\n setRect(rect => {\n const newRect = measure(target);\n return rect ? { ...rect,\n width: newRect.width,\n height: newRect.height\n } : newRect;\n });\n break;\n }\n }\n }, [measure]);\n const resizeObserver = useResizeObserver({\n callback: handleResize\n });\n const handleNodeChange = useCallback(element => {\n const node = getMeasurableNode(element);\n resizeObserver == null ? void 0 : resizeObserver.disconnect();\n\n if (node) {\n resizeObserver == null ? void 0 : resizeObserver.observe(node);\n }\n\n setRect(node ? measure(node) : null);\n }, [measure, resizeObserver]);\n const [nodeRef, setRef] = useNodeRef(handleNodeChange);\n return useMemo(() => ({\n nodeRef,\n rect,\n setRef\n }), [rect, nodeRef, setRef]);\n}\n\nconst defaultSensors = [{\n sensor: PointerSensor,\n options: {}\n}, {\n sensor: KeyboardSensor,\n options: {}\n}];\nconst defaultData = {\n current: {}\n};\nconst defaultMeasuringConfiguration = {\n draggable: {\n measure: getTransformAgnosticClientRect\n },\n droppable: {\n measure: getTransformAgnosticClientRect,\n strategy: MeasuringStrategy.WhileDragging,\n frequency: MeasuringFrequency.Optimized\n },\n dragOverlay: {\n measure: getClientRect\n }\n};\n\nclass DroppableContainersMap extends Map {\n get(id) {\n var _super$get;\n\n return id != null ? (_super$get = super.get(id)) != null ? _super$get : undefined : undefined;\n }\n\n toArray() {\n return Array.from(this.values());\n }\n\n getEnabled() {\n return this.toArray().filter(_ref => {\n let {\n disabled\n } = _ref;\n return !disabled;\n });\n }\n\n getNodeFor(id) {\n var _this$get$node$curren, _this$get;\n\n return (_this$get$node$curren = (_this$get = this.get(id)) == null ? void 0 : _this$get.node.current) != null ? _this$get$node$curren : undefined;\n }\n\n}\n\nconst defaultPublicContext = {\n activatorEvent: null,\n active: null,\n activeNode: null,\n activeNodeRect: null,\n collisions: null,\n containerNodeRect: null,\n draggableNodes: /*#__PURE__*/new Map(),\n droppableRects: /*#__PURE__*/new Map(),\n droppableContainers: /*#__PURE__*/new DroppableContainersMap(),\n over: null,\n dragOverlay: {\n nodeRef: {\n current: null\n },\n rect: null,\n setRef: noop\n },\n scrollableAncestors: [],\n scrollableAncestorRects: [],\n measuringConfiguration: defaultMeasuringConfiguration,\n measureDroppableContainers: noop,\n windowRect: null,\n measuringScheduled: false\n};\nconst defaultInternalContext = {\n activatorEvent: null,\n activators: [],\n active: null,\n activeNodeRect: null,\n ariaDescribedById: {\n draggable: ''\n },\n dispatch: noop,\n draggableNodes: /*#__PURE__*/new Map(),\n over: null,\n measureDroppableContainers: noop\n};\nconst InternalContext = /*#__PURE__*/createContext(defaultInternalContext);\nconst PublicContext = /*#__PURE__*/createContext(defaultPublicContext);\n\nfunction getInitialState() {\n return {\n draggable: {\n active: null,\n initialCoordinates: {\n x: 0,\n y: 0\n },\n nodes: new Map(),\n translate: {\n x: 0,\n y: 0\n }\n },\n droppable: {\n containers: new DroppableContainersMap()\n }\n };\n}\nfunction reducer(state, action) {\n switch (action.type) {\n case Action.DragStart:\n return { ...state,\n draggable: { ...state.draggable,\n initialCoordinates: action.initialCoordinates,\n active: action.active\n }\n };\n\n case Action.DragMove:\n if (state.draggable.active == null) {\n return state;\n }\n\n return { ...state,\n draggable: { ...state.draggable,\n translate: {\n x: action.coordinates.x - state.draggable.initialCoordinates.x,\n y: action.coordinates.y - state.draggable.initialCoordinates.y\n }\n }\n };\n\n case Action.DragEnd:\n case Action.DragCancel:\n return { ...state,\n draggable: { ...state.draggable,\n active: null,\n initialCoordinates: {\n x: 0,\n y: 0\n },\n translate: {\n x: 0,\n y: 0\n }\n }\n };\n\n case Action.RegisterDroppable:\n {\n const {\n element\n } = action;\n const {\n id\n } = element;\n const containers = new DroppableContainersMap(state.droppable.containers);\n containers.set(id, element);\n return { ...state,\n droppable: { ...state.droppable,\n containers\n }\n };\n }\n\n case Action.SetDroppableDisabled:\n {\n const {\n id,\n key,\n disabled\n } = action;\n const element = state.droppable.containers.get(id);\n\n if (!element || key !== element.key) {\n return state;\n }\n\n const containers = new DroppableContainersMap(state.droppable.containers);\n containers.set(id, { ...element,\n disabled\n });\n return { ...state,\n droppable: { ...state.droppable,\n containers\n }\n };\n }\n\n case Action.UnregisterDroppable:\n {\n const {\n id,\n key\n } = action;\n const element = state.droppable.containers.get(id);\n\n if (!element || key !== element.key) {\n return state;\n }\n\n const containers = new DroppableContainersMap(state.droppable.containers);\n containers.delete(id);\n return { ...state,\n droppable: { ...state.droppable,\n containers\n }\n };\n }\n\n default:\n {\n return state;\n }\n }\n}\n\nfunction RestoreFocus(_ref) {\n let {\n disabled\n } = _ref;\n const {\n active,\n activatorEvent,\n draggableNodes\n } = useContext(InternalContext);\n const previousActivatorEvent = usePrevious(activatorEvent);\n const previousActiveId = usePrevious(active == null ? void 0 : active.id); // Restore keyboard focus on the activator node\n\n useEffect(() => {\n if (disabled) {\n return;\n }\n\n if (!activatorEvent && previousActivatorEvent && previousActiveId != null) {\n if (!isKeyboardEvent(previousActivatorEvent)) {\n return;\n }\n\n if (document.activeElement === previousActivatorEvent.target) {\n // No need to restore focus\n return;\n }\n\n const draggableNode = draggableNodes.get(previousActiveId);\n\n if (!draggableNode) {\n return;\n }\n\n const {\n activatorNode,\n node\n } = draggableNode;\n\n if (!activatorNode.current && !node.current) {\n return;\n }\n\n requestAnimationFrame(() => {\n for (const element of [activatorNode.current, node.current]) {\n if (!element) {\n continue;\n }\n\n const focusableNode = findFirstFocusableNode(element);\n\n if (focusableNode) {\n focusableNode.focus();\n break;\n }\n }\n });\n }\n }, [activatorEvent, disabled, draggableNodes, previousActiveId, previousActivatorEvent]);\n return null;\n}\n\nfunction applyModifiers(modifiers, _ref) {\n let {\n transform,\n ...args\n } = _ref;\n return modifiers != null && modifiers.length ? modifiers.reduce((accumulator, modifier) => {\n return modifier({\n transform: accumulator,\n ...args\n });\n }, transform) : transform;\n}\n\nfunction useMeasuringConfiguration(config) {\n return useMemo(() => ({\n draggable: { ...defaultMeasuringConfiguration.draggable,\n ...(config == null ? void 0 : config.draggable)\n },\n droppable: { ...defaultMeasuringConfiguration.droppable,\n ...(config == null ? void 0 : config.droppable)\n },\n dragOverlay: { ...defaultMeasuringConfiguration.dragOverlay,\n ...(config == null ? void 0 : config.dragOverlay)\n }\n }), // eslint-disable-next-line react-hooks/exhaustive-deps\n [config == null ? void 0 : config.draggable, config == null ? void 0 : config.droppable, config == null ? void 0 : config.dragOverlay]);\n}\n\nfunction useLayoutShiftScrollCompensation(_ref) {\n let {\n activeNode,\n measure,\n initialRect,\n config = true\n } = _ref;\n const initialized = useRef(false);\n const {\n x,\n y\n } = typeof config === 'boolean' ? {\n x: config,\n y: config\n } : config;\n useIsomorphicLayoutEffect(() => {\n const disabled = !x && !y;\n\n if (disabled || !activeNode) {\n initialized.current = false;\n return;\n }\n\n if (initialized.current || !initialRect) {\n // Return early if layout shift scroll compensation was already attempted\n // or if there is no initialRect to compare to.\n return;\n } // Get the most up to date node ref for the active draggable\n\n\n const node = activeNode == null ? void 0 : activeNode.node.current;\n\n if (!node || node.isConnected === false) {\n // Return early if there is no attached node ref or if the node is\n // disconnected from the document.\n return;\n }\n\n const rect = measure(node);\n const rectDelta = getRectDelta(rect, initialRect);\n\n if (!x) {\n rectDelta.x = 0;\n }\n\n if (!y) {\n rectDelta.y = 0;\n } // Only perform layout shift scroll compensation once\n\n\n initialized.current = true;\n\n if (Math.abs(rectDelta.x) > 0 || Math.abs(rectDelta.y) > 0) {\n const firstScrollableAncestor = getFirstScrollableAncestor(node);\n\n if (firstScrollableAncestor) {\n firstScrollableAncestor.scrollBy({\n top: rectDelta.y,\n left: rectDelta.x\n });\n }\n }\n }, [activeNode, x, y, initialRect, measure]);\n}\n\nconst ActiveDraggableContext = /*#__PURE__*/createContext({ ...defaultCoordinates,\n scaleX: 1,\n scaleY: 1\n});\nvar Status;\n\n(function (Status) {\n Status[Status[\"Uninitialized\"] = 0] = \"Uninitialized\";\n Status[Status[\"Initializing\"] = 1] = \"Initializing\";\n Status[Status[\"Initialized\"] = 2] = \"Initialized\";\n})(Status || (Status = {}));\n\nconst DndContext = /*#__PURE__*/memo(function DndContext(_ref) {\n var _sensorContext$curren, _dragOverlay$nodeRef$, _dragOverlay$rect, _over$rect;\n\n let {\n id,\n accessibility,\n autoScroll = true,\n children,\n sensors = defaultSensors,\n collisionDetection = rectIntersection,\n measuring,\n modifiers,\n ...props\n } = _ref;\n const store = useReducer(reducer, undefined, getInitialState);\n const [state, dispatch] = store;\n const [dispatchMonitorEvent, registerMonitorListener] = useDndMonitorProvider();\n const [status, setStatus] = useState(Status.Uninitialized);\n const isInitialized = status === Status.Initialized;\n const {\n draggable: {\n active: activeId,\n nodes: draggableNodes,\n translate\n },\n droppable: {\n containers: droppableContainers\n }\n } = state;\n const node = activeId != null ? draggableNodes.get(activeId) : null;\n const activeRects = useRef({\n initial: null,\n translated: null\n });\n const active = useMemo(() => {\n var _node$data;\n\n return activeId != null ? {\n id: activeId,\n // It's possible for the active node to unmount while dragging\n data: (_node$data = node == null ? void 0 : node.data) != null ? _node$data : defaultData,\n rect: activeRects\n } : null;\n }, [activeId, node]);\n const activeRef = useRef(null);\n const [activeSensor, setActiveSensor] = useState(null);\n const [activatorEvent, setActivatorEvent] = useState(null);\n const latestProps = useLatestValue(props, Object.values(props));\n const draggableDescribedById = useUniqueId(\"DndDescribedBy\", id);\n const enabledDroppableContainers = useMemo(() => droppableContainers.getEnabled(), [droppableContainers]);\n const measuringConfiguration = useMeasuringConfiguration(measuring);\n const {\n droppableRects,\n measureDroppableContainers,\n measuringScheduled\n } = useDroppableMeasuring(enabledDroppableContainers, {\n dragging: isInitialized,\n dependencies: [translate.x, translate.y],\n config: measuringConfiguration.droppable\n });\n const activeNode = useCachedNode(draggableNodes, activeId);\n const activationCoordinates = useMemo(() => activatorEvent ? getEventCoordinates(activatorEvent) : null, [activatorEvent]);\n const autoScrollOptions = getAutoScrollerOptions();\n const initialActiveNodeRect = useInitialRect(activeNode, measuringConfiguration.draggable.measure);\n useLayoutShiftScrollCompensation({\n activeNode: activeId != null ? draggableNodes.get(activeId) : null,\n config: autoScrollOptions.layoutShiftCompensation,\n initialRect: initialActiveNodeRect,\n measure: measuringConfiguration.draggable.measure\n });\n const activeNodeRect = useRect(activeNode, measuringConfiguration.draggable.measure, initialActiveNodeRect);\n const containerNodeRect = useRect(activeNode ? activeNode.parentElement : null);\n const sensorContext = useRef({\n activatorEvent: null,\n active: null,\n activeNode,\n collisionRect: null,\n collisions: null,\n droppableRects,\n draggableNodes,\n draggingNode: null,\n draggingNodeRect: null,\n droppableContainers,\n over: null,\n scrollableAncestors: [],\n scrollAdjustedTranslate: null\n });\n const overNode = droppableContainers.getNodeFor((_sensorContext$curren = sensorContext.current.over) == null ? void 0 : _sensorContext$curren.id);\n const dragOverlay = useDragOverlayMeasuring({\n measure: measuringConfiguration.dragOverlay.measure\n }); // Use the rect of the drag overlay if it is mounted\n\n const draggingNode = (_dragOverlay$nodeRef$ = dragOverlay.nodeRef.current) != null ? _dragOverlay$nodeRef$ : activeNode;\n const draggingNodeRect = isInitialized ? (_dragOverlay$rect = dragOverlay.rect) != null ? _dragOverlay$rect : activeNodeRect : null;\n const usesDragOverlay = Boolean(dragOverlay.nodeRef.current && dragOverlay.rect); // The delta between the previous and new position of the draggable node\n // is only relevant when there is no drag overlay\n\n const nodeRectDelta = useRectDelta(usesDragOverlay ? null : activeNodeRect); // Get the window rect of the dragging node\n\n const windowRect = useWindowRect(draggingNode ? getWindow(draggingNode) : null); // Get scrollable ancestors of the dragging node\n\n const scrollableAncestors = useScrollableAncestors(isInitialized ? overNode != null ? overNode : activeNode : null);\n const scrollableAncestorRects = useRects(scrollableAncestors); // Apply modifiers\n\n const modifiedTranslate = applyModifiers(modifiers, {\n transform: {\n x: translate.x - nodeRectDelta.x,\n y: translate.y - nodeRectDelta.y,\n scaleX: 1,\n scaleY: 1\n },\n activatorEvent,\n active,\n activeNodeRect,\n containerNodeRect,\n draggingNodeRect,\n over: sensorContext.current.over,\n overlayNodeRect: dragOverlay.rect,\n scrollableAncestors,\n scrollableAncestorRects,\n windowRect\n });\n const pointerCoordinates = activationCoordinates ? add(activationCoordinates, translate) : null;\n const scrollOffsets = useScrollOffsets(scrollableAncestors); // Represents the scroll delta since dragging was initiated\n\n const scrollAdjustment = useScrollOffsetsDelta(scrollOffsets); // Represents the scroll delta since the last time the active node rect was measured\n\n const activeNodeScrollDelta = useScrollOffsetsDelta(scrollOffsets, [activeNodeRect]);\n const scrollAdjustedTranslate = add(modifiedTranslate, scrollAdjustment);\n const collisionRect = draggingNodeRect ? getAdjustedRect(draggingNodeRect, modifiedTranslate) : null;\n const collisions = active && collisionRect ? collisionDetection({\n active,\n collisionRect,\n droppableRects,\n droppableContainers: enabledDroppableContainers,\n pointerCoordinates\n }) : null;\n const overId = getFirstCollision(collisions, 'id');\n const [over, setOver] = useState(null); // When there is no drag overlay used, we need to account for the\n // window scroll delta\n\n const appliedTranslate = usesDragOverlay ? modifiedTranslate : add(modifiedTranslate, activeNodeScrollDelta);\n const transform = adjustScale(appliedTranslate, (_over$rect = over == null ? void 0 : over.rect) != null ? _over$rect : null, activeNodeRect);\n const activeSensorRef = useRef(null);\n const instantiateSensor = useCallback((event, _ref2) => {\n let {\n sensor: Sensor,\n options\n } = _ref2;\n\n if (activeRef.current == null) {\n return;\n }\n\n const activeNode = draggableNodes.get(activeRef.current);\n\n if (!activeNode) {\n return;\n }\n\n const activatorEvent = event.nativeEvent;\n const sensorInstance = new Sensor({\n active: activeRef.current,\n activeNode,\n event: activatorEvent,\n options,\n // Sensors need to be instantiated with refs for arguments that change over time\n // otherwise they are frozen in time with the stale arguments\n context: sensorContext,\n\n onAbort(id) {\n const draggableNode = draggableNodes.get(id);\n\n if (!draggableNode) {\n return;\n }\n\n const {\n onDragAbort\n } = latestProps.current;\n const event = {\n id\n };\n onDragAbort == null ? void 0 : onDragAbort(event);\n dispatchMonitorEvent({\n type: 'onDragAbort',\n event\n });\n },\n\n onPending(id, constraint, initialCoordinates, offset) {\n const draggableNode = draggableNodes.get(id);\n\n if (!draggableNode) {\n return;\n }\n\n const {\n onDragPending\n } = latestProps.current;\n const event = {\n id,\n constraint,\n initialCoordinates,\n offset\n };\n onDragPending == null ? void 0 : onDragPending(event);\n dispatchMonitorEvent({\n type: 'onDragPending',\n event\n });\n },\n\n onStart(initialCoordinates) {\n const id = activeRef.current;\n\n if (id == null) {\n return;\n }\n\n const draggableNode = draggableNodes.get(id);\n\n if (!draggableNode) {\n return;\n }\n\n const {\n onDragStart\n } = latestProps.current;\n const event = {\n activatorEvent,\n active: {\n id,\n data: draggableNode.data,\n rect: activeRects\n }\n };\n unstable_batchedUpdates(() => {\n onDragStart == null ? void 0 : onDragStart(event);\n setStatus(Status.Initializing);\n dispatch({\n type: Action.DragStart,\n initialCoordinates,\n active: id\n });\n dispatchMonitorEvent({\n type: 'onDragStart',\n event\n });\n setActiveSensor(activeSensorRef.current);\n setActivatorEvent(activatorEvent);\n });\n },\n\n onMove(coordinates) {\n dispatch({\n type: Action.DragMove,\n coordinates\n });\n },\n\n onEnd: createHandler(Action.DragEnd),\n onCancel: createHandler(Action.DragCancel)\n });\n activeSensorRef.current = sensorInstance;\n\n function createHandler(type) {\n return async function handler() {\n const {\n active,\n collisions,\n over,\n scrollAdjustedTranslate\n } = sensorContext.current;\n let event = null;\n\n if (active && scrollAdjustedTranslate) {\n const {\n cancelDrop\n } = latestProps.current;\n event = {\n activatorEvent,\n active: active,\n collisions,\n delta: scrollAdjustedTranslate,\n over\n };\n\n if (type === Action.DragEnd && typeof cancelDrop === 'function') {\n const shouldCancel = await Promise.resolve(cancelDrop(event));\n\n if (shouldCancel) {\n type = Action.DragCancel;\n }\n }\n }\n\n activeRef.current = null;\n unstable_batchedUpdates(() => {\n dispatch({\n type\n });\n setStatus(Status.Uninitialized);\n setOver(null);\n setActiveSensor(null);\n setActivatorEvent(null);\n activeSensorRef.current = null;\n const eventName = type === Action.DragEnd ? 'onDragEnd' : 'onDragCancel';\n\n if (event) {\n const handler = latestProps.current[eventName];\n handler == null ? void 0 : handler(event);\n dispatchMonitorEvent({\n type: eventName,\n event\n });\n }\n });\n };\n }\n }, // eslint-disable-next-line react-hooks/exhaustive-deps\n [draggableNodes]);\n const bindActivatorToSensorInstantiator = useCallback((handler, sensor) => {\n return (event, active) => {\n const nativeEvent = event.nativeEvent;\n const activeDraggableNode = draggableNodes.get(active);\n\n if ( // Another sensor is already instantiating\n activeRef.current !== null || // No active draggable\n !activeDraggableNode || // Event has already been captured\n nativeEvent.dndKit || nativeEvent.defaultPrevented) {\n return;\n }\n\n const activationContext = {\n active: activeDraggableNode\n };\n const shouldActivate = handler(event, sensor.options, activationContext);\n\n if (shouldActivate === true) {\n nativeEvent.dndKit = {\n capturedBy: sensor.sensor\n };\n activeRef.current = active;\n instantiateSensor(event, sensor);\n }\n };\n }, [draggableNodes, instantiateSensor]);\n const activators = useCombineActivators(sensors, bindActivatorToSensorInstantiator);\n useSensorSetup(sensors);\n useIsomorphicLayoutEffect(() => {\n if (activeNodeRect && status === Status.Initializing) {\n setStatus(Status.Initialized);\n }\n }, [activeNodeRect, status]);\n useEffect(() => {\n const {\n onDragMove\n } = latestProps.current;\n const {\n active,\n activatorEvent,\n collisions,\n over\n } = sensorContext.current;\n\n if (!active || !activatorEvent) {\n return;\n }\n\n const event = {\n active,\n activatorEvent,\n collisions,\n delta: {\n x: scrollAdjustedTranslate.x,\n y: scrollAdjustedTranslate.y\n },\n over\n };\n unstable_batchedUpdates(() => {\n onDragMove == null ? void 0 : onDragMove(event);\n dispatchMonitorEvent({\n type: 'onDragMove',\n event\n });\n });\n }, // eslint-disable-next-line react-hooks/exhaustive-deps\n [scrollAdjustedTranslate.x, scrollAdjustedTranslate.y]);\n useEffect(() => {\n const {\n active,\n activatorEvent,\n collisions,\n droppableContainers,\n scrollAdjustedTranslate\n } = sensorContext.current;\n\n if (!active || activeRef.current == null || !activatorEvent || !scrollAdjustedTranslate) {\n return;\n }\n\n const {\n onDragOver\n } = latestProps.current;\n const overContainer = droppableContainers.get(overId);\n const over = overContainer && overContainer.rect.current ? {\n id: overContainer.id,\n rect: overContainer.rect.current,\n data: overContainer.data,\n disabled: overContainer.disabled\n } : null;\n const event = {\n active,\n activatorEvent,\n collisions,\n delta: {\n x: scrollAdjustedTranslate.x,\n y: scrollAdjustedTranslate.y\n },\n over\n };\n unstable_batchedUpdates(() => {\n setOver(over);\n onDragOver == null ? void 0 : onDragOver(event);\n dispatchMonitorEvent({\n type: 'onDragOver',\n event\n });\n });\n }, // eslint-disable-next-line react-hooks/exhaustive-deps\n [overId]);\n useIsomorphicLayoutEffect(() => {\n sensorContext.current = {\n activatorEvent,\n active,\n activeNode,\n collisionRect,\n collisions,\n droppableRects,\n draggableNodes,\n draggingNode,\n draggingNodeRect,\n droppableContainers,\n over,\n scrollableAncestors,\n scrollAdjustedTranslate\n };\n activeRects.current = {\n initial: draggingNodeRect,\n translated: collisionRect\n };\n }, [active, activeNode, collisions, collisionRect, draggableNodes, draggingNode, draggingNodeRect, droppableRects, droppableContainers, over, scrollableAncestors, scrollAdjustedTranslate]);\n useAutoScroller({ ...autoScrollOptions,\n delta: translate,\n draggingRect: collisionRect,\n pointerCoordinates,\n scrollableAncestors,\n scrollableAncestorRects\n });\n const publicContext = useMemo(() => {\n const context = {\n active,\n activeNode,\n activeNodeRect,\n activatorEvent,\n collisions,\n containerNodeRect,\n dragOverlay,\n draggableNodes,\n droppableContainers,\n droppableRects,\n over,\n measureDroppableContainers,\n scrollableAncestors,\n scrollableAncestorRects,\n measuringConfiguration,\n measuringScheduled,\n windowRect\n };\n return context;\n }, [active, activeNode, activeNodeRect, activatorEvent, collisions, containerNodeRect, dragOverlay, draggableNodes, droppableContainers, droppableRects, over, measureDroppableContainers, scrollableAncestors, scrollableAncestorRects, measuringConfiguration, measuringScheduled, windowRect]);\n const internalContext = useMemo(() => {\n const context = {\n activatorEvent,\n activators,\n active,\n activeNodeRect,\n ariaDescribedById: {\n draggable: draggableDescribedById\n },\n dispatch,\n draggableNodes,\n over,\n measureDroppableContainers\n };\n return context;\n }, [activatorEvent, activators, active, activeNodeRect, dispatch, draggableDescribedById, draggableNodes, over, measureDroppableContainers]);\n return React.createElement(DndMonitorContext.Provider, {\n value: registerMonitorListener\n }, React.createElement(InternalContext.Provider, {\n value: internalContext\n }, React.createElement(PublicContext.Provider, {\n value: publicContext\n }, React.createElement(ActiveDraggableContext.Provider, {\n value: transform\n }, children)), React.createElement(RestoreFocus, {\n disabled: (accessibility == null ? void 0 : accessibility.restoreFocus) === false\n })), React.createElement(Accessibility, { ...accessibility,\n hiddenTextDescribedById: draggableDescribedById\n }));\n\n function getAutoScrollerOptions() {\n const activeSensorDisablesAutoscroll = (activeSensor == null ? void 0 : activeSensor.autoScrollEnabled) === false;\n const autoScrollGloballyDisabled = typeof autoScroll === 'object' ? autoScroll.enabled === false : autoScroll === false;\n const enabled = isInitialized && !activeSensorDisablesAutoscroll && !autoScrollGloballyDisabled;\n\n if (typeof autoScroll === 'object') {\n return { ...autoScroll,\n enabled\n };\n }\n\n return {\n enabled\n };\n }\n});\n\nconst NullContext = /*#__PURE__*/createContext(null);\nconst defaultRole = 'button';\nconst ID_PREFIX = 'Draggable';\nfunction useDraggable(_ref) {\n let {\n id,\n data,\n disabled = false,\n attributes\n } = _ref;\n const key = useUniqueId(ID_PREFIX);\n const {\n activators,\n activatorEvent,\n active,\n activeNodeRect,\n ariaDescribedById,\n draggableNodes,\n over\n } = useContext(InternalContext);\n const {\n role = defaultRole,\n roleDescription = 'draggable',\n tabIndex = 0\n } = attributes != null ? attributes : {};\n const isDragging = (active == null ? void 0 : active.id) === id;\n const transform = useContext(isDragging ? ActiveDraggableContext : NullContext);\n const [node, setNodeRef] = useNodeRef();\n const [activatorNode, setActivatorNodeRef] = useNodeRef();\n const listeners = useSyntheticListeners(activators, id);\n const dataRef = useLatestValue(data);\n useIsomorphicLayoutEffect(() => {\n draggableNodes.set(id, {\n id,\n key,\n node,\n activatorNode,\n data: dataRef\n });\n return () => {\n const node = draggableNodes.get(id);\n\n if (node && node.key === key) {\n draggableNodes.delete(id);\n }\n };\n }, // eslint-disable-next-line react-hooks/exhaustive-deps\n [draggableNodes, id]);\n const memoizedAttributes = useMemo(() => ({\n role,\n tabIndex,\n 'aria-disabled': disabled,\n 'aria-pressed': isDragging && role === defaultRole ? true : undefined,\n 'aria-roledescription': roleDescription,\n 'aria-describedby': ariaDescribedById.draggable\n }), [disabled, role, tabIndex, isDragging, roleDescription, ariaDescribedById.draggable]);\n return {\n active,\n activatorEvent,\n activeNodeRect,\n attributes: memoizedAttributes,\n isDragging,\n listeners: disabled ? undefined : listeners,\n node,\n over,\n setNodeRef,\n setActivatorNodeRef,\n transform\n };\n}\n\nfunction useDndContext() {\n return useContext(PublicContext);\n}\n\nconst ID_PREFIX$1 = 'Droppable';\nconst defaultResizeObserverConfig = {\n timeout: 25\n};\nfunction useDroppable(_ref) {\n let {\n data,\n disabled = false,\n id,\n resizeObserverConfig\n } = _ref;\n const key = useUniqueId(ID_PREFIX$1);\n const {\n active,\n dispatch,\n over,\n measureDroppableContainers\n } = useContext(InternalContext);\n const previous = useRef({\n disabled\n });\n const resizeObserverConnected = useRef(false);\n const rect = useRef(null);\n const callbackId = useRef(null);\n const {\n disabled: resizeObserverDisabled,\n updateMeasurementsFor,\n timeout: resizeObserverTimeout\n } = { ...defaultResizeObserverConfig,\n ...resizeObserverConfig\n };\n const ids = useLatestValue(updateMeasurementsFor != null ? updateMeasurementsFor : id);\n const handleResize = useCallback(() => {\n if (!resizeObserverConnected.current) {\n // ResizeObserver invokes the `handleResize` callback as soon as `observe` is called,\n // assuming the element is rendered and displayed.\n resizeObserverConnected.current = true;\n return;\n }\n\n if (callbackId.current != null) {\n clearTimeout(callbackId.current);\n }\n\n callbackId.current = setTimeout(() => {\n measureDroppableContainers(Array.isArray(ids.current) ? ids.current : [ids.current]);\n callbackId.current = null;\n }, resizeObserverTimeout);\n }, //eslint-disable-next-line react-hooks/exhaustive-deps\n [resizeObserverTimeout]);\n const resizeObserver = useResizeObserver({\n callback: handleResize,\n disabled: resizeObserverDisabled || !active\n });\n const handleNodeChange = useCallback((newElement, previousElement) => {\n if (!resizeObserver) {\n return;\n }\n\n if (previousElement) {\n resizeObserver.unobserve(previousElement);\n resizeObserverConnected.current = false;\n }\n\n if (newElement) {\n resizeObserver.observe(newElement);\n }\n }, [resizeObserver]);\n const [nodeRef, setNodeRef] = useNodeRef(handleNodeChange);\n const dataRef = useLatestValue(data);\n useEffect(() => {\n if (!resizeObserver || !nodeRef.current) {\n return;\n }\n\n resizeObserver.disconnect();\n resizeObserverConnected.current = false;\n resizeObserver.observe(nodeRef.current);\n }, [nodeRef, resizeObserver]);\n useEffect(() => {\n dispatch({\n type: Action.RegisterDroppable,\n element: {\n id,\n key,\n disabled,\n node: nodeRef,\n rect,\n data: dataRef\n }\n });\n return () => dispatch({\n type: Action.UnregisterDroppable,\n key,\n id\n });\n }, // eslint-disable-next-line react-hooks/exhaustive-deps\n [id]);\n useEffect(() => {\n if (disabled !== previous.current.disabled) {\n dispatch({\n type: Action.SetDroppableDisabled,\n id,\n key,\n disabled\n });\n previous.current.disabled = disabled;\n }\n }, [id, key, disabled, dispatch]);\n return {\n active,\n rect,\n isOver: (over == null ? void 0 : over.id) === id,\n node: nodeRef,\n over,\n setNodeRef\n };\n}\n\nfunction AnimationManager(_ref) {\n let {\n animation,\n children\n } = _ref;\n const [clonedChildren, setClonedChildren] = useState(null);\n const [element, setElement] = useState(null);\n const previousChildren = usePrevious(children);\n\n if (!children && !clonedChildren && previousChildren) {\n setClonedChildren(previousChildren);\n }\n\n useIsomorphicLayoutEffect(() => {\n if (!element) {\n return;\n }\n\n const key = clonedChildren == null ? void 0 : clonedChildren.key;\n const id = clonedChildren == null ? void 0 : clonedChildren.props.id;\n\n if (key == null || id == null) {\n setClonedChildren(null);\n return;\n }\n\n Promise.resolve(animation(id, element)).then(() => {\n setClonedChildren(null);\n });\n }, [animation, clonedChildren, element]);\n return React.createElement(React.Fragment, null, children, clonedChildren ? cloneElement(clonedChildren, {\n ref: setElement\n }) : null);\n}\n\nconst defaultTransform = {\n x: 0,\n y: 0,\n scaleX: 1,\n scaleY: 1\n};\nfunction NullifiedContextProvider(_ref) {\n let {\n children\n } = _ref;\n return React.createElement(InternalContext.Provider, {\n value: defaultInternalContext\n }, React.createElement(ActiveDraggableContext.Provider, {\n value: defaultTransform\n }, children));\n}\n\nconst baseStyles = {\n position: 'fixed',\n touchAction: 'none'\n};\n\nconst defaultTransition = activatorEvent => {\n const isKeyboardActivator = isKeyboardEvent(activatorEvent);\n return isKeyboardActivator ? 'transform 250ms ease' : undefined;\n};\n\nconst PositionedOverlay = /*#__PURE__*/forwardRef((_ref, ref) => {\n let {\n as,\n activatorEvent,\n adjustScale,\n children,\n className,\n rect,\n style,\n transform,\n transition = defaultTransition\n } = _ref;\n\n if (!rect) {\n return null;\n }\n\n const scaleAdjustedTransform = adjustScale ? transform : { ...transform,\n scaleX: 1,\n scaleY: 1\n };\n const styles = { ...baseStyles,\n width: rect.width,\n height: rect.height,\n top: rect.top,\n left: rect.left,\n transform: CSS.Transform.toString(scaleAdjustedTransform),\n transformOrigin: adjustScale && activatorEvent ? getRelativeTransformOrigin(activatorEvent, rect) : undefined,\n transition: typeof transition === 'function' ? transition(activatorEvent) : transition,\n ...style\n };\n return React.createElement(as, {\n className,\n style: styles,\n ref\n }, children);\n});\n\nconst defaultDropAnimationSideEffects = options => _ref => {\n let {\n active,\n dragOverlay\n } = _ref;\n const originalStyles = {};\n const {\n styles,\n className\n } = options;\n\n if (styles != null && styles.active) {\n for (const [key, value] of Object.entries(styles.active)) {\n if (value === undefined) {\n continue;\n }\n\n originalStyles[key] = active.node.style.getPropertyValue(key);\n active.node.style.setProperty(key, value);\n }\n }\n\n if (styles != null && styles.dragOverlay) {\n for (const [key, value] of Object.entries(styles.dragOverlay)) {\n if (value === undefined) {\n continue;\n }\n\n dragOverlay.node.style.setProperty(key, value);\n }\n }\n\n if (className != null && className.active) {\n active.node.classList.add(className.active);\n }\n\n if (className != null && className.dragOverlay) {\n dragOverlay.node.classList.add(className.dragOverlay);\n }\n\n return function cleanup() {\n for (const [key, value] of Object.entries(originalStyles)) {\n active.node.style.setProperty(key, value);\n }\n\n if (className != null && className.active) {\n active.node.classList.remove(className.active);\n }\n };\n};\n\nconst defaultKeyframeResolver = _ref2 => {\n let {\n transform: {\n initial,\n final\n }\n } = _ref2;\n return [{\n transform: CSS.Transform.toString(initial)\n }, {\n transform: CSS.Transform.toString(final)\n }];\n};\n\nconst defaultDropAnimationConfiguration = {\n duration: 250,\n easing: 'ease',\n keyframes: defaultKeyframeResolver,\n sideEffects: /*#__PURE__*/defaultDropAnimationSideEffects({\n styles: {\n active: {\n opacity: '0'\n }\n }\n })\n};\nfunction useDropAnimation(_ref3) {\n let {\n config,\n draggableNodes,\n droppableContainers,\n measuringConfiguration\n } = _ref3;\n return useEvent((id, node) => {\n if (config === null) {\n return;\n }\n\n const activeDraggable = draggableNodes.get(id);\n\n if (!activeDraggable) {\n return;\n }\n\n const activeNode = activeDraggable.node.current;\n\n if (!activeNode) {\n return;\n }\n\n const measurableNode = getMeasurableNode(node);\n\n if (!measurableNode) {\n return;\n }\n\n const {\n transform\n } = getWindow(node).getComputedStyle(node);\n const parsedTransform = parseTransform(transform);\n\n if (!parsedTransform) {\n return;\n }\n\n const animation = typeof config === 'function' ? config : createDefaultDropAnimation(config);\n scrollIntoViewIfNeeded(activeNode, measuringConfiguration.draggable.measure);\n return animation({\n active: {\n id,\n data: activeDraggable.data,\n node: activeNode,\n rect: measuringConfiguration.draggable.measure(activeNode)\n },\n draggableNodes,\n dragOverlay: {\n node,\n rect: measuringConfiguration.dragOverlay.measure(measurableNode)\n },\n droppableContainers,\n measuringConfiguration,\n transform: parsedTransform\n });\n });\n}\n\nfunction createDefaultDropAnimation(options) {\n const {\n duration,\n easing,\n sideEffects,\n keyframes\n } = { ...defaultDropAnimationConfiguration,\n ...options\n };\n return _ref4 => {\n let {\n active,\n dragOverlay,\n transform,\n ...rest\n } = _ref4;\n\n if (!duration) {\n // Do not animate if animation duration is zero.\n return;\n }\n\n const delta = {\n x: dragOverlay.rect.left - active.rect.left,\n y: dragOverlay.rect.top - active.rect.top\n };\n const scale = {\n scaleX: transform.scaleX !== 1 ? active.rect.width * transform.scaleX / dragOverlay.rect.width : 1,\n scaleY: transform.scaleY !== 1 ? active.rect.height * transform.scaleY / dragOverlay.rect.height : 1\n };\n const finalTransform = {\n x: transform.x - delta.x,\n y: transform.y - delta.y,\n ...scale\n };\n const animationKeyframes = keyframes({ ...rest,\n active,\n dragOverlay,\n transform: {\n initial: transform,\n final: finalTransform\n }\n });\n const [firstKeyframe] = animationKeyframes;\n const lastKeyframe = animationKeyframes[animationKeyframes.length - 1];\n\n if (JSON.stringify(firstKeyframe) === JSON.stringify(lastKeyframe)) {\n // The start and end keyframes are the same, infer that there is no animation needed.\n return;\n }\n\n const cleanup = sideEffects == null ? void 0 : sideEffects({\n active,\n dragOverlay,\n ...rest\n });\n const animation = dragOverlay.node.animate(animationKeyframes, {\n duration,\n easing,\n fill: 'forwards'\n });\n return new Promise(resolve => {\n animation.onfinish = () => {\n cleanup == null ? void 0 : cleanup();\n resolve();\n };\n });\n };\n}\n\nlet key = 0;\nfunction useKey(id) {\n return useMemo(() => {\n if (id == null) {\n return;\n }\n\n key++;\n return key;\n }, [id]);\n}\n\nconst DragOverlay = /*#__PURE__*/React.memo(_ref => {\n let {\n adjustScale = false,\n children,\n dropAnimation: dropAnimationConfig,\n style,\n transition,\n modifiers,\n wrapperElement = 'div',\n className,\n zIndex = 999\n } = _ref;\n const {\n activatorEvent,\n active,\n activeNodeRect,\n containerNodeRect,\n draggableNodes,\n droppableContainers,\n dragOverlay,\n over,\n measuringConfiguration,\n scrollableAncestors,\n scrollableAncestorRects,\n windowRect\n } = useDndContext();\n const transform = useContext(ActiveDraggableContext);\n const key = useKey(active == null ? void 0 : active.id);\n const modifiedTransform = applyModifiers(modifiers, {\n activatorEvent,\n active,\n activeNodeRect,\n containerNodeRect,\n draggingNodeRect: dragOverlay.rect,\n over,\n overlayNodeRect: dragOverlay.rect,\n scrollableAncestors,\n scrollableAncestorRects,\n transform,\n windowRect\n });\n const initialRect = useInitialValue(activeNodeRect);\n const dropAnimation = useDropAnimation({\n config: dropAnimationConfig,\n draggableNodes,\n droppableContainers,\n measuringConfiguration\n }); // We need to wait for the active node to be measured before connecting the drag overlay ref\n // otherwise collisions can be computed against a mispositioned drag overlay\n\n const ref = initialRect ? dragOverlay.setRef : undefined;\n return React.createElement(NullifiedContextProvider, null, React.createElement(AnimationManager, {\n animation: dropAnimation\n }, active && key ? React.createElement(PositionedOverlay, {\n key: key,\n id: active.id,\n ref: ref,\n as: wrapperElement,\n activatorEvent: activatorEvent,\n adjustScale: adjustScale,\n className: className,\n transition: transition,\n rect: initialRect,\n style: {\n zIndex,\n ...style\n },\n transform: modifiedTransform\n }, children) : null));\n});\n\nexport { AutoScrollActivator, DndContext, DragOverlay, KeyboardCode, KeyboardSensor, MeasuringFrequency, MeasuringStrategy, MouseSensor, PointerSensor, TouchSensor, TraversalOrder, applyModifiers, closestCenter, closestCorners, defaultAnnouncements, defaultCoordinates, defaultDropAnimationConfiguration as defaultDropAnimation, defaultDropAnimationSideEffects, defaultKeyboardCoordinateGetter, defaultScreenReaderInstructions, getClientRect, getFirstCollision, getScrollableAncestors, pointerWithin, rectIntersection, useDndContext, useDndMonitor, useDraggable, useDroppable, useSensor, useSensors };\n//# sourceMappingURL=core.esm.js.map\n","// src/parsers/aeneas.ts\nfunction parseAeneas(data) {\n return {\n id: data.id,\n start: parseFloat(data.begin),\n end: parseFloat(data.end),\n lines: data.lines,\n lang: data.language\n };\n}\nfunction serializeAeneas(annotation) {\n return {\n id: annotation.id,\n begin: annotation.start.toFixed(3),\n end: annotation.end.toFixed(3),\n lines: annotation.lines,\n language: annotation.lang || \"en\"\n };\n}\n\n// src/components/Annotation.tsx\nimport { useState } from \"react\";\nimport styled from \"styled-components\";\nimport { jsx, jsxs } from \"react/jsx-runtime\";\nvar AnnotationOverlay = styled.div.attrs((props) => ({\n style: {\n left: `${props.$left}px`,\n width: `${props.$width}px`\n }\n}))`\n position: absolute;\n top: 0;\n background: ${(props) => props.$color};\n height: 100%;\n z-index: 10;\n pointer-events: auto;\n opacity: 0.3;\n border: 2px solid ${(props) => props.$color};\n border-radius: 4px;\n cursor: pointer;\n\n &:hover {\n opacity: 0.5;\n border-color: ${(props) => props.$color};\n }\n`;\nvar AnnotationText = styled.div`\n position: absolute;\n bottom: 0;\n left: 0;\n right: 0;\n background: rgba(0, 0, 0, 0.7);\n color: white;\n padding: 4px 8px;\n font-size: 12px;\n line-height: 1.3;\n max-height: 60%;\n overflow: hidden;\n text-overflow: ellipsis;\n pointer-events: none;\n white-space: pre-wrap;\n word-break: break-word;\n`;\nvar EditableText = styled.textarea`\n position: absolute;\n bottom: 0;\n left: 0;\n right: 0;\n background: rgba(0, 0, 0, 0.9);\n color: white;\n padding: 4px 8px;\n font-size: 12px;\n line-height: 1.3;\n max-height: 60%;\n overflow: auto;\n border: 1px solid #fff;\n resize: none;\n font-family: inherit;\n\n &:focus {\n outline: none;\n border-color: #4CAF50;\n }\n`;\nvar ControlsBar = styled.div`\n position: absolute;\n top: 0;\n left: 0;\n right: 0;\n background: rgba(0, 0, 0, 0.8);\n display: flex;\n gap: 4px;\n padding: 4px;\n justify-content: flex-start;\n align-items: center;\n`;\nvar ControlButton = styled.button`\n background: transparent;\n border: 1px solid rgba(255, 255, 255, 0.5);\n color: white;\n padding: 4px 8px;\n font-size: 10px;\n cursor: pointer;\n border-radius: 3px;\n display: flex;\n align-items: center;\n justify-content: center;\n min-width: 24px;\n height: 24px;\n\n &:hover {\n background: rgba(255, 255, 255, 0.2);\n border-color: white;\n }\n\n &:active {\n background: rgba(255, 255, 255, 0.3);\n }\n`;\nvar Annotation = ({\n annotation,\n index,\n allAnnotations,\n startPosition,\n endPosition,\n color = \"#ff9800\",\n editable = false,\n controls = [],\n onAnnotationUpdate,\n annotationListConfig,\n onClick\n}) => {\n const [isEditing, setIsEditing] = useState(false);\n const [editedText, setEditedText] = useState(annotation.lines.join(\"\\n\"));\n const width = Math.max(0, endPosition - startPosition);\n if (width <= 0) {\n return null;\n }\n const handleClick = () => {\n if (onClick) {\n onClick(annotation);\n }\n };\n const handleDoubleClick = () => {\n if (editable) {\n setIsEditing(true);\n }\n };\n const handleTextChange = (e) => {\n setEditedText(e.target.value);\n };\n const handleTextBlur = () => {\n setIsEditing(false);\n const newLines = editedText.split(\"\\n\");\n if (newLines.join(\"\\n\") !== annotation.lines.join(\"\\n\")) {\n const updatedAnnotations = [...allAnnotations];\n updatedAnnotations[index] = { ...annotation, lines: newLines };\n if (onAnnotationUpdate) {\n onAnnotationUpdate(updatedAnnotations);\n }\n }\n };\n const handleControlClick = (control) => {\n const annotationsCopy = [...allAnnotations];\n control.action(annotationsCopy[index], index, annotationsCopy, annotationListConfig || {});\n if (onAnnotationUpdate) {\n onAnnotationUpdate(annotationsCopy);\n }\n };\n const getIconClass = (classString) => {\n return classString.replace(/\\./g, \" \");\n };\n return /* @__PURE__ */ jsxs(\n AnnotationOverlay,\n {\n $left: startPosition,\n $width: width,\n $color: color,\n onClick: handleClick,\n onDoubleClick: handleDoubleClick,\n children: [\n controls.length > 0 && /* @__PURE__ */ jsx(ControlsBar, { children: controls.map((control, idx) => /* @__PURE__ */ jsx(\n ControlButton,\n {\n title: control.title,\n onClick: (e) => {\n e.stopPropagation();\n handleControlClick(control);\n },\n children: control.text ? control.text : /* @__PURE__ */ jsx(\"i\", { className: getIconClass(control.class || \"\") })\n },\n idx\n )) }),\n isEditing ? /* @__PURE__ */ jsx(\n EditableText,\n {\n value: editedText,\n onChange: handleTextChange,\n onBlur: handleTextBlur,\n autoFocus: true,\n onClick: (e) => e.stopPropagation(),\n onDoubleClick: (e) => e.stopPropagation()\n }\n ) : /* @__PURE__ */ jsx(AnnotationText, { children: annotation.lines.join(\"\\n\") })\n ]\n }\n );\n};\n\n// src/components/AnnotationBox.tsx\nimport styled2 from \"styled-components\";\nimport { useDraggable } from \"@dnd-kit/core\";\nimport { jsx as jsx2, jsxs as jsxs2 } from \"react/jsx-runtime\";\nvar Wrapper = styled2.div.attrs((props) => ({\n style: {\n left: `${props.$left}px`,\n width: `${props.$width}px`\n }\n}))`\n position: absolute;\n top: 0;\n height: 100%;\n pointer-events: none; /* Let events pass through to children */\n`;\nvar Box = styled2.div`\n position: absolute;\n top: 0;\n left: 0;\n right: 0;\n height: 100%;\n background: ${(props) => props.$isActive ? props.theme?.annotationBoxActiveBackground || \"rgba(255, 200, 100, 0.95)\" : props.theme?.annotationBoxBackground || \"rgba(255, 255, 255, 0.85)\"};\n border: ${(props) => props.$isActive ? \"3px\" : \"2px\"} solid ${(props) => props.$isActive ? props.theme?.annotationBoxActiveBorder || \"#ff9800\" : props.$color};\n border-radius: 4px;\n cursor: pointer;\n pointer-events: auto;\n display: flex;\n align-items: center;\n justify-content: center;\n overflow: hidden;\n transition: all 0.2s ease;\n box-shadow: ${(props) => props.$isActive ? \"0 2px 8px rgba(255, 152, 0, 0.4), inset 0 0 0 1px rgba(255, 152, 0, 0.2)\" : \"0 1px 3px rgba(0, 0, 0, 0.1)\"};\n\n &:hover {\n background: ${(props) => props.theme?.annotationBoxHoverBackground || \"rgba(255, 255, 255, 0.98)\"};\n border-color: ${(props) => props.theme?.annotationBoxActiveBorder || \"#ff9800\"};\n border-width: 3px;\n box-shadow: 0 2px 6px rgba(0, 0, 0, 0.15);\n }\n`;\nvar Label = styled2.span`\n font-size: 12px;\n font-weight: 600;\n color: ${(props) => props.theme?.annotationLabelColor || \"#2a2a2a\"};\n white-space: nowrap;\n overflow: hidden;\n text-overflow: ellipsis;\n padding: 0 6px;\n letter-spacing: 0.3px;\n user-select: none;\n`;\nvar ResizeHandle = styled2.div`\n position: absolute;\n top: 0;\n ${(props) => props.$position === \"left\" ? \"left: -8px\" : \"right: -8px\"};\n width: 16px;\n height: 100%;\n cursor: ew-resize;\n z-index: 120; /* Above ClickOverlay (z-index: 100) and AnnotationBoxesWrapper (z-index: 110) */\n background: ${(props) => props.$isDragging ? props.theme?.annotationResizeHandleColor || \"rgba(0, 0, 0, 0.2)\" : \"transparent\"};\n border-radius: 4px;\n touch-action: none; /* Important for @dnd-kit on touch devices */\n pointer-events: auto;\n\n &::before {\n content: '';\n position: absolute;\n top: 50%;\n left: 50%;\n transform: translate(-50%, -50%);\n width: 4px;\n height: 60%;\n background: ${(props) => props.$isDragging ? props.theme?.annotationResizeHandleActiveColor || \"rgba(0, 0, 0, 0.8)\" : props.theme?.annotationResizeHandleColor || \"rgba(0, 0, 0, 0.4)\"};\n border-radius: 2px;\n opacity: ${(props) => props.$isDragging ? 1 : 0.6};\n transition: opacity 0.2s, background 0.2s;\n }\n\n &:hover {\n background: ${(props) => props.theme?.annotationResizeHandleColor || \"rgba(0, 0, 0, 0.1)\"};\n }\n\n &:hover::before {\n opacity: 1;\n background: ${(props) => props.theme?.annotationResizeHandleActiveColor || \"rgba(0, 0, 0, 0.7)\"};\n }\n`;\nvar AnnotationBox = ({\n annotationId,\n annotationIndex,\n startPosition,\n endPosition,\n label,\n color = \"#ff9800\",\n isActive = false,\n onClick,\n editable = true\n}) => {\n const width = Math.max(0, endPosition - startPosition);\n const leftBoundaryId = `annotation-boundary-start-${annotationIndex}`;\n const {\n attributes: leftAttributes,\n listeners: leftListeners,\n setActivatorNodeRef: setLeftActivatorRef,\n isDragging: isLeftDragging\n } = useDraggable({\n id: leftBoundaryId,\n data: { annotationId, annotationIndex, edge: \"start\" },\n disabled: !editable\n });\n const rightBoundaryId = `annotation-boundary-end-${annotationIndex}`;\n const {\n attributes: rightAttributes,\n listeners: rightListeners,\n setActivatorNodeRef: setRightActivatorRef,\n isDragging: isRightDragging\n } = useDraggable({\n id: rightBoundaryId,\n data: { annotationId, annotationIndex, edge: \"end\" },\n disabled: !editable\n });\n if (width <= 0) {\n return null;\n }\n const createPointerDownHandler = (dndKitHandler) => {\n return (e) => {\n e.stopPropagation();\n dndKitHandler?.(e);\n };\n };\n const handleHandleClick = (e) => {\n e.stopPropagation();\n };\n return /* @__PURE__ */ jsxs2(Wrapper, { $left: startPosition, $width: width, children: [\n /* @__PURE__ */ jsx2(\n Box,\n {\n $color: color,\n $isActive: isActive,\n onClick,\n children: label && /* @__PURE__ */ jsx2(Label, { children: label })\n }\n ),\n editable && /* @__PURE__ */ jsx2(\n ResizeHandle,\n {\n ref: setLeftActivatorRef,\n $position: \"left\",\n $isDragging: isLeftDragging,\n onClick: handleHandleClick,\n ...leftListeners,\n onPointerDown: createPointerDownHandler(leftListeners?.onPointerDown),\n ...leftAttributes\n }\n ),\n editable && /* @__PURE__ */ jsx2(\n ResizeHandle,\n {\n ref: setRightActivatorRef,\n $position: \"right\",\n $isDragging: isRightDragging,\n onClick: handleHandleClick,\n ...rightListeners,\n onPointerDown: createPointerDownHandler(rightListeners?.onPointerDown),\n ...rightAttributes\n }\n )\n ] });\n};\n\n// src/components/AnnotationBoxesWrapper.tsx\nimport styled3 from \"styled-components\";\nimport { usePlaylistInfo } from \"@waveform-playlist/ui-components\";\nimport { jsx as jsx3, jsxs as jsxs3 } from \"react/jsx-runtime\";\nvar Container = styled3.div.attrs((props) => ({\n style: {\n height: `${props.$height}px`\n }\n}))`\n position: relative;\n display: flex;\n ${(props) => props.$width !== void 0 && `width: ${props.$width}px;`}\n background: transparent;\n z-index: 110;\n`;\nvar ControlsPlaceholder = styled3.div`\n position: sticky;\n z-index: 200;\n left: 0;\n height: 100%;\n width: ${(props) => props.$controlWidth}px;\n flex-shrink: 0;\n background: transparent;\n`;\nvar BoxesContainer = styled3.div`\n position: relative;\n flex: 1;\n padding-left: ${(props) => props.$offset || 0}px;\n`;\nvar AnnotationBoxesWrapper = ({\n children,\n className,\n height = 30,\n offset = 0,\n width\n}) => {\n const {\n controls: { show, width: controlWidth }\n } = usePlaylistInfo();\n return /* @__PURE__ */ jsxs3(\n Container,\n {\n className,\n $height: height,\n $controlWidth: show ? controlWidth : 0,\n $width: width,\n children: [\n /* @__PURE__ */ jsx3(ControlsPlaceholder, { $controlWidth: show ? controlWidth : 0 }),\n /* @__PURE__ */ jsx3(BoxesContainer, { $offset: offset, children })\n ]\n }\n );\n};\n\n// src/components/AnnotationsTrack.tsx\nimport styled4 from \"styled-components\";\nimport { usePlaylistInfo as usePlaylistInfo2 } from \"@waveform-playlist/ui-components\";\nimport { jsx as jsx4, jsxs as jsxs4 } from \"react/jsx-runtime\";\nvar Container2 = styled4.div.attrs((props) => ({\n style: {\n height: `${props.$height}px`\n }\n}))`\n position: relative;\n display: flex;\n ${(props) => props.$width !== void 0 && `width: ${props.$width}px;`}\n background: transparent;\n`;\nvar ControlsPlaceholder2 = styled4.div`\n position: sticky;\n z-index: 200;\n left: 0;\n height: 100%;\n width: ${(props) => props.$controlWidth}px;\n flex-shrink: 0;\n background: transparent;\n display: flex;\n align-items: center;\n justify-content: center;\n font-size: 12px;\n color: ${(props) => props.theme?.textColorMuted || \"#666\"};\n font-weight: bold;\n`;\nvar AnnotationsContainer = styled4.div`\n position: relative;\n flex: 1;\n padding-left: ${(props) => props.$offset || 0}px;\n`;\nvar AnnotationsTrack = ({\n children,\n className,\n height = 100,\n offset = 0,\n width\n}) => {\n const {\n controls: { show, width: controlWidth }\n } = usePlaylistInfo2();\n return /* @__PURE__ */ jsxs4(\n Container2,\n {\n className,\n $height: height,\n $controlWidth: show ? controlWidth : 0,\n $width: width,\n children: [\n /* @__PURE__ */ jsx4(ControlsPlaceholder2, { $controlWidth: show ? controlWidth : 0, children: \"Annotations\" }),\n /* @__PURE__ */ jsx4(AnnotationsContainer, { $offset: offset, children })\n ]\n }\n );\n};\n\n// src/components/AnnotationText.tsx\nimport React2, { useRef, useEffect } from \"react\";\nimport styled5 from \"styled-components\";\nimport { jsx as jsx5, jsxs as jsxs5 } from \"react/jsx-runtime\";\nvar Container3 = styled5.div`\n background: ${(props) => props.theme?.backgroundColor || \"#fff\"};\n ${(props) => props.$height ? `height: ${props.$height}px;` : \"max-height: 200px;\"}\n overflow-y: auto;\n padding: 8px;\n`;\nvar AnnotationItem = styled5.div`\n padding: 12px;\n margin-bottom: 6px;\n border-left: 4px solid ${(props) => props.$isActive ? \"#ff9800\" : \"transparent\"};\n background: ${(props) => props.$isActive ? \"rgba(255, 152, 0, 0.15)\" : \"transparent\"};\n border-radius: 4px;\n transition: all 0.2s;\n cursor: pointer;\n box-shadow: ${(props) => props.$isActive ? \"0 2px 8px rgba(255, 152, 0, 0.25), inset 0 0 0 1px rgba(255, 152, 0, 0.3)\" : \"none\"};\n\n &:hover {\n background: ${(props) => props.$isActive ? \"rgba(255, 152, 0, 0.2)\" : props.theme?.annotationTextItemHoverBackground || \"rgba(0, 0, 0, 0.05)\"};\n border-left-color: ${(props) => props.$isActive ? \"#ff9800\" : props.theme?.borderColor || \"#ddd\"};\n }\n\n &:focus-visible {\n outline: 2px solid #ff9800;\n outline-offset: 2px;\n }\n`;\nvar AnnotationHeader = styled5.div`\n display: flex;\n justify-content: space-between;\n align-items: center;\n margin-bottom: 6px;\n`;\nvar AnnotationInfo = styled5.div`\n display: flex;\n align-items: center;\n gap: 8px;\n`;\nvar AnnotationIdLabel = styled5.span`\n font-size: 11px;\n font-weight: 600;\n color: ${(props) => props.theme?.textColorMuted || \"#666\"};\n background: transparent;\n padding: 2px 6px;\n border-radius: 3px;\n min-width: 20px;\n outline: ${(props) => props.$isEditable ? `1px dashed ${props.theme?.borderColor || \"#ddd\"}` : \"none\"};\n\n &[contenteditable='true']:focus {\n outline: 2px solid #ff9800;\n background: rgba(255, 152, 0, 0.1);\n }\n`;\nvar TimeRange = styled5.span`\n font-size: 12px;\n font-weight: 500;\n color: ${(props) => props.theme?.textColorMuted || \"#555\"};\n font-family: 'Monaco', 'Menlo', 'Ubuntu Mono', monospace;\n letter-spacing: 0.5px;\n`;\nvar AnnotationControls = styled5.div`\n display: flex;\n gap: 6px;\n`;\nvar ControlButton2 = styled5.button`\n background: ${(props) => props.theme?.surfaceColor || \"#f5f5f5\"};\n border: 1px solid ${(props) => props.theme?.borderColor || \"#ccc\"};\n color: ${(props) => props.theme?.textColor || \"#333\"};\n padding: 4px 8px;\n font-size: 14px;\n cursor: pointer;\n border-radius: 4px;\n transition: all 0.15s ease;\n\n &:hover {\n background: ${(props) => props.theme?.inputBackground || \"#3d3d3d\"};\n border-color: ${(props) => props.theme?.textColorMuted || \"#999\"};\n transform: scale(1.05);\n }\n\n &:active {\n transform: scale(0.95);\n }\n`;\nvar AnnotationTextContent = styled5.div`\n font-size: 14px;\n line-height: 1.6;\n color: ${(props) => props.theme?.textColor || \"#2a2a2a\"};\n white-space: pre-wrap;\n word-break: break-word;\n outline: ${(props) => props.$isEditable ? `1px dashed ${props.theme?.borderColor || \"#ddd\"}` : \"none\"};\n padding: ${(props) => props.$isEditable ? \"6px\" : \"0\"};\n border-radius: 3px;\n min-height: 20px;\n\n &[contenteditable='true']:focus {\n outline: 2px solid #ff9800;\n background: rgba(255, 152, 0, 0.1);\n }\n`;\nvar AnnotationTextComponent = ({\n annotations,\n activeAnnotationId,\n shouldScrollToActive = false,\n editable = false,\n controls = [],\n annotationListConfig,\n height,\n onAnnotationClick,\n onAnnotationUpdate,\n renderAnnotationItem\n}) => {\n const activeAnnotationRef = useRef(null);\n const containerRef = useRef(null);\n const prevActiveIdRef = useRef(void 0);\n useEffect(() => {\n });\n useEffect(() => {\n const container = containerRef.current;\n if (!container) return;\n const handleScroll = () => {\n };\n container.addEventListener(\"scroll\", handleScroll);\n return () => container.removeEventListener(\"scroll\", handleScroll);\n }, []);\n useEffect(() => {\n if (activeAnnotationId && activeAnnotationRef.current && shouldScrollToActive) {\n activeAnnotationRef.current.scrollIntoView({\n behavior: \"smooth\",\n block: \"nearest\"\n });\n }\n prevActiveIdRef.current = activeAnnotationId;\n }, [activeAnnotationId, shouldScrollToActive]);\n const formatTime = (seconds) => {\n if (isNaN(seconds) || !isFinite(seconds)) {\n return \"0:00.000\";\n }\n const mins = Math.floor(seconds / 60);\n const secs = (seconds % 60).toFixed(3);\n return `${mins}:${secs.padStart(6, \"0\")}`;\n };\n const handleTextEdit = (index, newText) => {\n if (!editable || !onAnnotationUpdate) return;\n const updatedAnnotations = [...annotations];\n updatedAnnotations[index] = {\n ...updatedAnnotations[index],\n lines: newText.split(\"\\n\")\n };\n onAnnotationUpdate(updatedAnnotations);\n };\n const handleIdEdit = (index, newId) => {\n if (!editable || !onAnnotationUpdate) return;\n const trimmedId = newId.trim();\n if (!trimmedId) return;\n const updatedAnnotations = [...annotations];\n updatedAnnotations[index] = {\n ...updatedAnnotations[index],\n id: trimmedId\n };\n onAnnotationUpdate(updatedAnnotations);\n };\n const handleControlClick = (control, annotation, index) => {\n if (!onAnnotationUpdate) return;\n const annotationsCopy = [...annotations];\n control.action(annotationsCopy[index], index, annotationsCopy, annotationListConfig || {});\n onAnnotationUpdate(annotationsCopy);\n };\n const getIconClass = (classString) => {\n return classString.replace(/\\./g, \" \");\n };\n return /* @__PURE__ */ jsx5(Container3, { ref: containerRef, $height: height, children: annotations.map((annotation, index) => {\n const isActive = annotation.id === activeAnnotationId;\n const handleClick = () => onAnnotationClick?.(annotation);\n if (renderAnnotationItem) {\n return /* @__PURE__ */ jsx5(\n \"div\",\n {\n ref: isActive ? activeAnnotationRef : null,\n children: renderAnnotationItem({\n annotation,\n index,\n isActive,\n onClick: handleClick,\n formatTime\n })\n },\n annotation.id\n );\n }\n return /* @__PURE__ */ jsxs5(\n AnnotationItem,\n {\n ref: isActive ? activeAnnotationRef : null,\n $isActive: isActive,\n onClick: handleClick,\n children: [\n /* @__PURE__ */ jsxs5(AnnotationHeader, { children: [\n /* @__PURE__ */ jsxs5(AnnotationInfo, { children: [\n /* @__PURE__ */ jsx5(\n AnnotationIdLabel,\n {\n $isEditable: editable,\n contentEditable: editable,\n suppressContentEditableWarning: true,\n onBlur: (e) => handleIdEdit(index, e.currentTarget.textContent || \"\"),\n children: annotation.id\n }\n ),\n /* @__PURE__ */ jsxs5(TimeRange, { children: [\n formatTime(annotation.start),\n \" - \",\n formatTime(annotation.end)\n ] })\n ] }),\n controls.length > 0 && /* @__PURE__ */ jsx5(AnnotationControls, { onClick: (e) => e.stopPropagation(), children: controls.map((control, idx) => /* @__PURE__ */ jsx5(\n ControlButton2,\n {\n title: control.title,\n onClick: () => handleControlClick(control, annotation, index),\n children: control.text ? control.text : /* @__PURE__ */ jsx5(\"i\", { className: getIconClass(control.class || \"\") })\n },\n idx\n )) })\n ] }),\n /* @__PURE__ */ jsx5(\n AnnotationTextContent,\n {\n $isEditable: editable,\n contentEditable: editable,\n suppressContentEditableWarning: true,\n onBlur: (e) => handleTextEdit(index, e.currentTarget.textContent || \"\"),\n children: annotation.lines.join(\"\\n\")\n }\n )\n ]\n },\n annotation.id\n );\n }) });\n};\nvar AnnotationText2 = React2.memo(AnnotationTextComponent);\n\n// src/components/ContinuousPlayCheckbox.tsx\nimport { BaseCheckboxWrapper, BaseCheckbox, BaseCheckboxLabel } from \"@waveform-playlist/ui-components\";\nimport { jsx as jsx6, jsxs as jsxs6 } from \"react/jsx-runtime\";\nvar ContinuousPlayCheckbox = ({\n checked,\n onChange,\n disabled = false,\n className\n}) => {\n const handleChange = (e) => {\n onChange(e.target.checked);\n };\n return /* @__PURE__ */ jsxs6(BaseCheckboxWrapper, { className, children: [\n /* @__PURE__ */ jsx6(\n BaseCheckbox,\n {\n type: \"checkbox\",\n id: \"continuous-play\",\n className: \"continuous-play\",\n checked,\n onChange: handleChange,\n disabled\n }\n ),\n /* @__PURE__ */ jsx6(BaseCheckboxLabel, { htmlFor: \"continuous-play\", children: \"Continuous Play\" })\n ] });\n};\n\n// src/components/LinkEndpointsCheckbox.tsx\nimport { BaseCheckboxWrapper as BaseCheckboxWrapper2, BaseCheckbox as BaseCheckbox2, BaseCheckboxLabel as BaseCheckboxLabel2 } from \"@waveform-playlist/ui-components\";\nimport { jsx as jsx7, jsxs as jsxs7 } from \"react/jsx-runtime\";\nvar LinkEndpointsCheckbox = ({\n checked,\n onChange,\n disabled = false,\n className\n}) => {\n const handleChange = (e) => {\n onChange(e.target.checked);\n };\n return /* @__PURE__ */ jsxs7(BaseCheckboxWrapper2, { className, children: [\n /* @__PURE__ */ jsx7(\n BaseCheckbox2,\n {\n type: \"checkbox\",\n id: \"link-endpoints\",\n className: \"link-endpoints\",\n checked,\n onChange: handleChange,\n disabled\n }\n ),\n /* @__PURE__ */ jsx7(BaseCheckboxLabel2, { htmlFor: \"link-endpoints\", children: \"Link Endpoints\" })\n ] });\n};\n\n// src/components/EditableCheckbox.tsx\nimport { BaseCheckboxWrapper as BaseCheckboxWrapper3, BaseCheckbox as BaseCheckbox3, BaseCheckboxLabel as BaseCheckboxLabel3 } from \"@waveform-playlist/ui-components\";\nimport { jsx as jsx8, jsxs as jsxs8 } from \"react/jsx-runtime\";\nvar EditableCheckbox = ({\n checked,\n onChange,\n className\n}) => {\n return /* @__PURE__ */ jsxs8(BaseCheckboxWrapper3, { className, children: [\n /* @__PURE__ */ jsx8(\n BaseCheckbox3,\n {\n type: \"checkbox\",\n id: \"editable-annotations\",\n checked,\n onChange: (e) => onChange(e.target.checked)\n }\n ),\n /* @__PURE__ */ jsx8(BaseCheckboxLabel3, { htmlFor: \"editable-annotations\", children: \"Editable Annotations\" })\n ] });\n};\n\n// src/components/DownloadAnnotationsButton.tsx\nimport styled6 from \"styled-components\";\nimport { jsx as jsx9 } from \"react/jsx-runtime\";\nvar StyledButton = styled6.button`\n padding: 0.5rem 1rem;\n background: ${(props) => props.theme?.surfaceColor || \"#f5f5f5\"};\n color: ${(props) => props.theme?.textColor || \"#333\"};\n border: 1px solid ${(props) => props.theme?.borderColor || \"#ccc\"};\n border-radius: ${(props) => props.theme?.borderRadius || \"4px\"};\n cursor: pointer;\n font-family: ${(props) => props.theme?.fontFamily || \"inherit\"};\n font-size: ${(props) => props.theme?.fontSize || \"14px\"};\n font-weight: 500;\n transition: all 0.15s ease;\n\n &:hover:not(:disabled) {\n background: ${(props) => props.theme?.inputBackground || \"#3d3d3d\"};\n border-color: ${(props) => props.theme?.textColorMuted || \"#999\"};\n }\n\n &:focus {\n outline: none;\n box-shadow: 0 0 0 2px ${(props) => props.theme?.inputFocusBorder || \"#007bff\"}44;\n }\n\n &:disabled {\n opacity: 0.6;\n cursor: not-allowed;\n }\n`;\nvar DownloadAnnotationsButton = ({\n annotations,\n filename = \"annotations.json\",\n disabled = false,\n className,\n children = \"Download JSON\"\n}) => {\n const handleDownload = () => {\n if (annotations.length === 0) {\n return;\n }\n const jsonData = annotations.map((annotation) => serializeAeneas(annotation));\n const jsonString = JSON.stringify(jsonData, null, 2);\n const blob = new Blob([jsonString], { type: \"application/json\" });\n const url = URL.createObjectURL(blob);\n const link = document.createElement(\"a\");\n link.href = url;\n link.download = filename;\n document.body.appendChild(link);\n link.click();\n document.body.removeChild(link);\n URL.revokeObjectURL(url);\n };\n return /* @__PURE__ */ jsx9(\n StyledButton,\n {\n onClick: handleDownload,\n disabled: disabled || annotations.length === 0,\n className,\n title: annotations.length === 0 ? \"No annotations to download\" : \"Download the annotations as JSON\",\n children\n }\n );\n};\n\n// src/hooks/useAnnotationControls.ts\nimport { useState as useState2, useCallback } from \"react\";\nvar LINK_THRESHOLD = 0.01;\nvar useAnnotationControls = (options = {}) => {\n const {\n initialContinuousPlay = false,\n initialLinkEndpoints = true\n } = options;\n const [continuousPlay, setContinuousPlay] = useState2(initialContinuousPlay);\n const [linkEndpoints, setLinkEndpoints] = useState2(initialLinkEndpoints);\n const updateAnnotationBoundaries = useCallback(\n ({\n annotationIndex,\n newTime,\n isDraggingStart,\n annotations,\n duration,\n linkEndpoints: shouldLinkEndpoints\n }) => {\n const updatedAnnotations = [...annotations];\n const annotation = annotations[annotationIndex];\n if (isDraggingStart) {\n const constrainedStart = Math.min(annotation.end - 0.1, Math.max(0, newTime));\n const delta = constrainedStart - annotation.start;\n updatedAnnotations[annotationIndex] = {\n ...annotation,\n start: constrainedStart\n };\n if (shouldLinkEndpoints && annotationIndex > 0) {\n const prevAnnotation = updatedAnnotations[annotationIndex - 1];\n if (Math.abs(prevAnnotation.end - annotation.start) < LINK_THRESHOLD) {\n updatedAnnotations[annotationIndex - 1] = {\n ...prevAnnotation,\n end: Math.max(prevAnnotation.start + 0.1, prevAnnotation.end + delta)\n };\n } else if (constrainedStart <= prevAnnotation.end) {\n updatedAnnotations[annotationIndex] = {\n ...updatedAnnotations[annotationIndex],\n start: prevAnnotation.end\n };\n }\n } else if (!shouldLinkEndpoints && annotationIndex > 0 && constrainedStart < updatedAnnotations[annotationIndex - 1].end) {\n updatedAnnotations[annotationIndex - 1] = {\n ...updatedAnnotations[annotationIndex - 1],\n end: constrainedStart\n };\n }\n } else {\n const constrainedEnd = Math.max(annotation.start + 0.1, Math.min(newTime, duration));\n const delta = constrainedEnd - annotation.end;\n updatedAnnotations[annotationIndex] = {\n ...annotation,\n end: constrainedEnd\n };\n if (shouldLinkEndpoints && annotationIndex < updatedAnnotations.length - 1) {\n const nextAnnotation = updatedAnnotations[annotationIndex + 1];\n if (Math.abs(nextAnnotation.start - annotation.end) < LINK_THRESHOLD) {\n const newStart = nextAnnotation.start + delta;\n updatedAnnotations[annotationIndex + 1] = {\n ...nextAnnotation,\n start: Math.min(nextAnnotation.end - 0.1, newStart)\n };\n let currentIndex = annotationIndex + 1;\n while (currentIndex < updatedAnnotations.length - 1) {\n const current = updatedAnnotations[currentIndex];\n const next = updatedAnnotations[currentIndex + 1];\n if (Math.abs(next.start - current.end) < LINK_THRESHOLD) {\n const nextDelta = current.end - annotations[currentIndex].end;\n updatedAnnotations[currentIndex + 1] = {\n ...next,\n start: Math.min(next.end - 0.1, next.start + nextDelta)\n };\n currentIndex++;\n } else {\n break;\n }\n }\n } else if (constrainedEnd >= nextAnnotation.start) {\n updatedAnnotations[annotationIndex] = {\n ...updatedAnnotations[annotationIndex],\n end: nextAnnotation.start\n };\n }\n } else if (!shouldLinkEndpoints && annotationIndex < updatedAnnotations.length - 1 && constrainedEnd > updatedAnnotations[annotationIndex + 1].start) {\n const nextAnnotation = updatedAnnotations[annotationIndex + 1];\n updatedAnnotations[annotationIndex + 1] = {\n ...nextAnnotation,\n start: constrainedEnd\n };\n let currentIndex = annotationIndex + 1;\n while (currentIndex < updatedAnnotations.length - 1) {\n const current = updatedAnnotations[currentIndex];\n const next = updatedAnnotations[currentIndex + 1];\n if (current.end > next.start) {\n updatedAnnotations[currentIndex + 1] = {\n ...next,\n start: current.end\n };\n currentIndex++;\n } else {\n break;\n }\n }\n }\n }\n return updatedAnnotations;\n },\n []\n );\n return {\n continuousPlay,\n linkEndpoints,\n setContinuousPlay,\n setLinkEndpoints,\n updateAnnotationBoundaries\n };\n};\nexport {\n Annotation,\n AnnotationBox,\n AnnotationBoxesWrapper,\n AnnotationText2 as AnnotationText,\n AnnotationsTrack,\n ContinuousPlayCheckbox,\n DownloadAnnotationsButton,\n EditableCheckbox,\n LinkEndpointsCheckbox,\n parseAeneas,\n serializeAeneas,\n useAnnotationControls\n};\n//# sourceMappingURL=index.mjs.map","import { useState } from 'react';\nimport { formatTime as formatTimeUtil, parseTime as parseTimeUtil, type TimeFormat } from '@waveform-playlist/ui-components';\n\nexport interface TimeFormatControls {\n timeFormat: TimeFormat;\n setTimeFormat: (format: TimeFormat) => void;\n formatTime: (seconds: number) => string;\n parseTime: (timeString: string) => number;\n}\n\n/**\n * Hook to manage time format state\n *\n * @example\n * ```tsx\n * const { timeFormat, setTimeFormat, formatTime, parseTime } = useTimeFormat();\n *\n * <TimeFormatSelect\n * value={timeFormat}\n * onChange={setTimeFormat}\n * />\n * <span>{formatTime(currentTime)}</span>\n * <input onChange={(e) => seekTo(parseTime(e.target.value))} />\n * ```\n */\nexport function useTimeFormat(): TimeFormatControls {\n const [timeFormat, setTimeFormat] = useState<TimeFormat>('hh:mm:ss.uuu');\n\n const formatTime = (seconds: number) => {\n return formatTimeUtil(seconds, timeFormat);\n };\n\n const parseTime = (timeString: string) => {\n return parseTimeUtil(timeString, timeFormat);\n };\n\n return {\n timeFormat,\n setTimeFormat,\n formatTime,\n parseTime,\n };\n}\n","import { useState, useCallback } from 'react';\n\nexport interface ZoomControls {\n samplesPerPixel: number;\n zoomIn: () => void;\n zoomOut: () => void;\n canZoomIn: boolean;\n canZoomOut: boolean;\n}\n\nexport interface UseZoomControlsProps {\n initialSamplesPerPixel: number;\n zoomLevels?: number[]; // Array of samples per pixel values (lower = more zoomed in)\n}\n\nconst DEFAULT_ZOOM_LEVELS = [256, 512, 1024, 2048, 4096, 8192];\n\nexport function useZoomControls({\n initialSamplesPerPixel,\n zoomLevels = DEFAULT_ZOOM_LEVELS,\n}: UseZoomControlsProps): ZoomControls {\n const [zoomIndex, setZoomIndex] = useState(() => {\n const index = zoomLevels.indexOf(initialSamplesPerPixel);\n return index !== -1 ? index : Math.floor(zoomLevels.length / 2);\n });\n\n const samplesPerPixel = zoomLevels[zoomIndex];\n const canZoomIn = zoomIndex > 0;\n const canZoomOut = zoomIndex < zoomLevels.length - 1;\n\n const zoomIn = useCallback(() => {\n setZoomIndex((prev) => Math.max(0, prev - 1));\n }, []);\n\n const zoomOut = useCallback(() => {\n setZoomIndex((prev) => Math.min(zoomLevels.length - 1, prev + 1));\n }, [zoomLevels.length]);\n\n return {\n samplesPerPixel,\n zoomIn,\n zoomOut,\n canZoomIn,\n canZoomOut,\n };\n}\n","import { useState, useCallback, RefObject } from 'react';\nimport { TonePlayout } from '@waveform-playlist/playout';\n\nexport interface UseMasterVolumeProps {\n playoutRef: RefObject<TonePlayout | null>;\n initialVolume?: number; // 0-1.0 (linear gain, consistent with Web Audio API)\n onVolumeChange?: (volume: number) => void;\n}\n\nexport interface MasterVolumeControls {\n masterVolume: number;\n setMasterVolume: (volume: number) => void;\n}\n\n/**\n * Hook for managing master volume control\n *\n * @example\n * ```tsx\n * const { masterVolume, setMasterVolume } = useMasterVolume({\n * playoutRef,\n * initialVolume: 1.0,\n * });\n *\n * <MasterVolumeControl\n * volume={masterVolume}\n * onChange={setMasterVolume}\n * />\n * ```\n */\nexport function useMasterVolume({\n playoutRef,\n initialVolume = 1.0,\n onVolumeChange,\n}: UseMasterVolumeProps): MasterVolumeControls {\n const [masterVolume, setMasterVolumeState] = useState(initialVolume);\n\n const setMasterVolume = useCallback((volume: number) => {\n setMasterVolumeState(volume);\n\n // Update the playout with linear gain (0-1.0 range)\n if (playoutRef.current) {\n playoutRef.current.setMasterGain(volume);\n }\n\n // Call optional callback\n onVolumeChange?.(volume);\n }, [playoutRef, onVolumeChange]);\n\n return {\n masterVolume,\n setMasterVolume,\n };\n}\n","import { useRef, useCallback } from 'react';\nimport type { EffectsFunction } from '@waveform-playlist/playout';\n// Import Tone.js classes directly for tree-shaking\nimport { Analyser } from 'tone';\n\n/**\n * Hook for master effects with frequency analyzer\n * Returns the analyser ref and the effects function to pass to WaveformPlaylistProvider\n *\n * For more advanced effects (reverb, delay, filters, etc.), use useDynamicEffects instead.\n */\nexport const useMasterAnalyser = (fftSize: number = 256) => {\n const analyserRef = useRef<any>(null);\n\n const masterEffects: EffectsFunction = useCallback((masterGainNode, destination, _isOffline) => {\n // Create analyser and connect it in parallel to monitor the output\n const analyserNode = new Analyser('fft', fftSize);\n masterGainNode.connect(analyserNode);\n\n // Connect master to destination as normal\n masterGainNode.connect(destination);\n\n // Store analyser for visualization\n analyserRef.current = analyserNode;\n\n return function cleanup() {\n // Cleanup when playlist is destroyed\n analyserNode.dispose();\n analyserRef.current = null;\n };\n }, [fftSize]);\n\n return { analyserRef, masterEffects };\n};\n","// src/types/clip.ts\nfunction createClip(options) {\n const {\n audioBuffer,\n startSample,\n offsetSamples = 0,\n gain = 1,\n name,\n color,\n fadeIn,\n fadeOut,\n waveformData\n } = options;\n const sampleRate = audioBuffer?.sampleRate ?? options.sampleRate ?? waveformData?.sample_rate;\n const sourceDurationSamples = audioBuffer?.length ?? options.sourceDurationSamples ?? (waveformData && sampleRate ? Math.ceil(waveformData.duration * sampleRate) : void 0);\n if (sampleRate === void 0) {\n throw new Error(\"createClip: sampleRate is required when audioBuffer is not provided (can use waveformData.sample_rate)\");\n }\n if (sourceDurationSamples === void 0) {\n throw new Error(\"createClip: sourceDurationSamples is required when audioBuffer is not provided (can use waveformData.duration)\");\n }\n if (audioBuffer && waveformData && audioBuffer.sampleRate !== waveformData.sample_rate) {\n console.warn(\n `Sample rate mismatch: audioBuffer (${audioBuffer.sampleRate}) vs waveformData (${waveformData.sample_rate}). Using audioBuffer sample rate. Waveform visualization may be slightly off.`\n );\n }\n const durationSamples = options.durationSamples ?? sourceDurationSamples;\n return {\n id: generateId(),\n audioBuffer,\n startSample,\n durationSamples,\n offsetSamples,\n sampleRate,\n sourceDurationSamples,\n gain,\n name,\n color,\n fadeIn,\n fadeOut,\n waveformData\n };\n}\nfunction createClipFromSeconds(options) {\n const {\n audioBuffer,\n startTime,\n offset = 0,\n gain = 1,\n name,\n color,\n fadeIn,\n fadeOut,\n waveformData\n } = options;\n const sampleRate = audioBuffer?.sampleRate ?? options.sampleRate ?? waveformData?.sample_rate;\n if (sampleRate === void 0) {\n throw new Error(\"createClipFromSeconds: sampleRate is required when audioBuffer is not provided (can use waveformData.sample_rate)\");\n }\n const sourceDuration = audioBuffer?.duration ?? options.sourceDuration ?? waveformData?.duration;\n if (sourceDuration === void 0) {\n throw new Error(\"createClipFromSeconds: sourceDuration is required when audioBuffer is not provided (can use waveformData.duration)\");\n }\n if (audioBuffer && waveformData && audioBuffer.sampleRate !== waveformData.sample_rate) {\n console.warn(\n `Sample rate mismatch: audioBuffer (${audioBuffer.sampleRate}) vs waveformData (${waveformData.sample_rate}). Using audioBuffer sample rate. Waveform visualization may be slightly off.`\n );\n }\n const duration = options.duration ?? sourceDuration;\n return createClip({\n audioBuffer,\n startSample: Math.round(startTime * sampleRate),\n durationSamples: Math.round(duration * sampleRate),\n offsetSamples: Math.round(offset * sampleRate),\n sampleRate,\n sourceDurationSamples: Math.ceil(sourceDuration * sampleRate),\n gain,\n name,\n color,\n fadeIn,\n fadeOut,\n waveformData\n });\n}\nfunction createTrack(options) {\n const {\n name,\n clips = [],\n muted = false,\n soloed = false,\n volume = 1,\n pan = 0,\n color,\n height\n } = options;\n return {\n id: generateId(),\n name,\n clips,\n muted,\n soloed,\n volume,\n pan,\n color,\n height\n };\n}\nfunction createTimeline(tracks, sampleRate = 44100, options) {\n const durationSamples = tracks.reduce((maxSamples, track) => {\n const trackSamples = track.clips.reduce((max, clip) => {\n return Math.max(max, clip.startSample + clip.durationSamples);\n }, 0);\n return Math.max(maxSamples, trackSamples);\n }, 0);\n const duration = durationSamples / sampleRate;\n return {\n tracks,\n duration,\n sampleRate,\n name: options?.name,\n tempo: options?.tempo,\n timeSignature: options?.timeSignature\n };\n}\nfunction generateId() {\n return `${Date.now()}-${Math.random().toString(36).substr(2, 9)}`;\n}\nfunction getClipsInRange(track, startSample, endSample) {\n return track.clips.filter((clip) => {\n const clipEnd = clip.startSample + clip.durationSamples;\n return clip.startSample < endSample && clipEnd > startSample;\n });\n}\nfunction getClipsAtSample(track, sample) {\n return track.clips.filter((clip) => {\n const clipEnd = clip.startSample + clip.durationSamples;\n return sample >= clip.startSample && sample < clipEnd;\n });\n}\nfunction clipsOverlap(clip1, clip2) {\n const clip1End = clip1.startSample + clip1.durationSamples;\n const clip2End = clip2.startSample + clip2.durationSamples;\n return clip1.startSample < clip2End && clip1End > clip2.startSample;\n}\nfunction sortClipsByTime(clips) {\n return [...clips].sort((a, b) => a.startSample - b.startSample);\n}\nfunction findGaps(track) {\n if (track.clips.length === 0) return [];\n const sorted = sortClipsByTime(track.clips);\n const gaps = [];\n for (let i = 0; i < sorted.length - 1; i++) {\n const currentClipEnd = sorted[i].startSample + sorted[i].durationSamples;\n const nextClipStart = sorted[i + 1].startSample;\n if (nextClipStart > currentClipEnd) {\n gaps.push({\n startSample: currentClipEnd,\n endSample: nextClipStart,\n durationSamples: nextClipStart - currentClipEnd\n });\n }\n }\n return gaps;\n}\n\n// src/types/index.ts\nvar InteractionState = /* @__PURE__ */ ((InteractionState2) => {\n InteractionState2[\"Cursor\"] = \"cursor\";\n InteractionState2[\"Select\"] = \"select\";\n InteractionState2[\"Shift\"] = \"shift\";\n InteractionState2[\"FadeIn\"] = \"fadein\";\n InteractionState2[\"FadeOut\"] = \"fadeout\";\n return InteractionState2;\n})(InteractionState || {});\n\n// src/utils/conversions.ts\nfunction samplesToSeconds(samples, sampleRate) {\n return samples / sampleRate;\n}\nfunction secondsToSamples(seconds, sampleRate) {\n return Math.ceil(seconds * sampleRate);\n}\nfunction samplesToPixels(samples, samplesPerPixel) {\n return Math.floor(samples / samplesPerPixel);\n}\nfunction pixelsToSamples(pixels, samplesPerPixel) {\n return Math.floor(pixels * samplesPerPixel);\n}\nfunction pixelsToSeconds(pixels, samplesPerPixel, sampleRate) {\n return pixels * samplesPerPixel / sampleRate;\n}\nfunction secondsToPixels(seconds, samplesPerPixel, sampleRate) {\n return Math.ceil(seconds * sampleRate / samplesPerPixel);\n}\nexport {\n InteractionState,\n clipsOverlap,\n createClip,\n createClipFromSeconds,\n createTimeline,\n createTrack,\n findGaps,\n getClipsAtSample,\n getClipsInRange,\n pixelsToSamples,\n pixelsToSeconds,\n samplesToPixels,\n samplesToSeconds,\n secondsToPixels,\n secondsToSamples,\n sortClipsByTime\n};\n//# sourceMappingURL=index.mjs.map","import { useState, useEffect, useRef, useCallback } from 'react';\nimport { ClipTrack, createTrack, createClipFromSeconds, type Fade, type TrackEffectsFunction, type WaveformDataObject } from '@waveform-playlist/core';\nimport * as Tone from 'tone';\n\n/**\n * Configuration for a single audio track to load\n *\n * Audio can be provided in three ways:\n * 1. `src` - URL to fetch and decode (standard loading)\n * 2. `audioBuffer` - Pre-loaded AudioBuffer (skip fetch/decode)\n * 3. `waveformData` only - Peaks-first rendering (audio loads later)\n *\n * For peaks-first rendering, just provide `waveformData` - the sample rate\n * and duration are derived from the waveform data automatically.\n */\nexport interface AudioTrackConfig {\n /** URL to audio file - used if audioBuffer not provided */\n src?: string;\n /** Pre-loaded AudioBuffer - skips fetch/decode if provided */\n audioBuffer?: AudioBuffer;\n name?: string;\n muted?: boolean;\n soloed?: boolean;\n volume?: number;\n pan?: number;\n color?: string;\n effects?: TrackEffectsFunction;\n // Multi-clip support\n startTime?: number; // When the clip starts on the timeline (default: 0)\n duration?: number; // Duration of the clip (default: full audio duration)\n offset?: number; // Offset into the source audio file (default: 0)\n // Fade support\n fadeIn?: Fade; // Fade in configuration\n fadeOut?: Fade; // Fade out configuration\n // Pre-computed waveform data (BBC audiowaveform format)\n // For peaks-first rendering, provide this without audioBuffer/src\n // Sample rate and duration are derived from waveformData.sample_rate and waveformData.duration\n waveformData?: WaveformDataObject;\n}\n\n/**\n * Options for useAudioTracks hook\n */\nexport interface UseAudioTracksOptions {\n /**\n * When true, tracks are added to the playlist progressively as they load,\n * rather than waiting for all tracks to finish loading.\n * Default: false (wait for all tracks)\n */\n progressive?: boolean;\n}\n\n/**\n * Hook to load audio from URLs and convert to ClipTrack format\n *\n * This hook fetches audio files, decodes them, and creates ClipTrack objects\n * with a single clip per track. Supports custom positioning for multi-clip arrangements.\n *\n * @param configs - Array of audio track configurations\n * @param options - Optional configuration for loading behavior\n * @returns Object with tracks array, loading state, and progress info\n *\n * @example\n * ```typescript\n * // Basic usage (clips positioned at start)\n * const { tracks, loading, error } = useAudioTracks([\n * { src: 'audio/vocals.mp3', name: 'Vocals' },\n * { src: 'audio/drums.mp3', name: 'Drums' },\n * ]);\n *\n * // Progressive loading (tracks appear as they load)\n * const { tracks, loading, loadedCount, totalCount } = useAudioTracks(\n * [{ src: 'audio/vocals.mp3' }, { src: 'audio/drums.mp3' }],\n * { progressive: true }\n * );\n *\n * // Pre-loaded AudioBuffer (skip fetch/decode)\n * const { tracks } = useAudioTracks([\n * { audioBuffer: myPreloadedBuffer, name: 'Pre-loaded' },\n * ]);\n *\n * // Peaks-first rendering (instant visual, audio loads later)\n * const { tracks } = useAudioTracks([\n * { waveformData: preloadedPeaks, name: 'Peaks Only' }, // Renders immediately\n * ]);\n *\n * if (loading) return <div>Loading {loadedCount}/{totalCount}...</div>;\n * if (error) return <div>Error: {error}</div>;\n *\n * return <WaveformPlaylistProvider tracks={tracks}>...</WaveformPlaylistProvider>;\n * ```\n */\nexport function useAudioTracks(\n configs: AudioTrackConfig[],\n options: UseAudioTracksOptions = {}\n) {\n const { progressive = false } = options;\n const [tracks, setTracks] = useState<ClipTrack[]>([]);\n const [loading, setLoading] = useState(true);\n const [error, setError] = useState<string | null>(null);\n const [loadedCount, setLoadedCount] = useState(0);\n\n // Track which configs need audio loading vs already have data\n const totalCount = configs.length;\n\n useEffect(() => {\n if (configs.length === 0) {\n setTracks([]);\n setLoading(false);\n setLoadedCount(0);\n return;\n }\n\n let cancelled = false;\n // Track loaded tracks by their config index for progressive mode\n const loadedTracksMap = new Map<number, ClipTrack>();\n\n const createTrackFromConfig = (\n config: AudioTrackConfig,\n index: number,\n audioBuffer?: AudioBuffer\n ): ClipTrack => {\n // Use provided audioBuffer, config's audioBuffer, or undefined for peaks-only\n const buffer = audioBuffer ?? config.audioBuffer;\n\n // For peaks-first rendering, we need waveformData if no buffer\n if (!buffer && !config.waveformData) {\n throw new Error(\n `Track ${index + 1}: Must provide src, audioBuffer, or waveformData`\n );\n }\n\n // Determine source duration for clip creation\n const sourceDuration = buffer?.duration ?? config.waveformData?.duration;\n\n // Create clip - createClipFromSeconds handles deriving sampleRate from waveformData\n const clip = createClipFromSeconds({\n audioBuffer: buffer,\n startTime: config.startTime ?? 0,\n duration: config.duration ?? sourceDuration,\n offset: config.offset ?? 0,\n name: config.name || `Track ${index + 1}`,\n fadeIn: config.fadeIn,\n fadeOut: config.fadeOut,\n waveformData: config.waveformData,\n });\n\n // Validate clip values\n if (isNaN(clip.startSample) || isNaN(clip.durationSamples) || isNaN(clip.offsetSamples)) {\n console.error('Invalid clip values:', clip);\n throw new Error(`Invalid clip values for track ${index + 1}`);\n }\n\n // Create the track with the single clip\n const track: ClipTrack = {\n ...createTrack({\n name: config.name || `Track ${index + 1}`,\n clips: [clip],\n muted: config.muted ?? false,\n soloed: config.soloed ?? false,\n volume: config.volume ?? 1.0,\n pan: config.pan ?? 0,\n color: config.color,\n }),\n effects: config.effects,\n };\n\n return track;\n };\n\n const loadTracks = async () => {\n try {\n setLoading(true);\n setError(null);\n setLoadedCount(0);\n\n const audioContext = Tone.getContext().rawContext as AudioContext;\n\n // Process each config\n const loadPromises = configs.map(async (config, index) => {\n // Case 1: Already have audioBuffer - no loading needed\n if (config.audioBuffer) {\n const track = createTrackFromConfig(config, index, config.audioBuffer);\n\n if (progressive && !cancelled) {\n loadedTracksMap.set(index, track);\n setLoadedCount(prev => prev + 1);\n // Update tracks maintaining order\n setTracks(\n Array.from({ length: configs.length }, (_, i) => loadedTracksMap.get(i))\n .filter((t): t is ClipTrack => t !== undefined)\n );\n }\n\n return track;\n }\n\n // Case 2: Have waveformData but no src - peaks-only (no audio to load)\n if (!config.src && config.waveformData) {\n const track = createTrackFromConfig(config, index);\n\n if (progressive && !cancelled) {\n loadedTracksMap.set(index, track);\n setLoadedCount(prev => prev + 1);\n setTracks(\n Array.from({ length: configs.length }, (_, i) => loadedTracksMap.get(i))\n .filter((t): t is ClipTrack => t !== undefined)\n );\n }\n\n return track;\n }\n\n // Case 3: Need to fetch and decode audio from src\n if (!config.src) {\n throw new Error(`Track ${index + 1}: Must provide src, audioBuffer, or waveformData`);\n }\n\n const response = await fetch(config.src);\n if (!response.ok) {\n throw new Error(`Failed to fetch ${config.src}: ${response.statusText}`);\n }\n\n const arrayBuffer = await response.arrayBuffer();\n const audioBuffer = await audioContext.decodeAudioData(arrayBuffer);\n\n // Validate audioBuffer\n if (!audioBuffer || !audioBuffer.sampleRate || !audioBuffer.duration) {\n throw new Error(`Invalid audio buffer for ${config.src}`);\n }\n\n const track = createTrackFromConfig(config, index, audioBuffer);\n\n if (progressive && !cancelled) {\n loadedTracksMap.set(index, track);\n setLoadedCount(prev => prev + 1);\n // Update tracks maintaining original config order\n setTracks(\n Array.from({ length: configs.length }, (_, i) => loadedTracksMap.get(i))\n .filter((t): t is ClipTrack => t !== undefined)\n );\n }\n\n return track;\n });\n\n const loadedTracks = await Promise.all(loadPromises);\n\n if (!cancelled) {\n // For non-progressive mode, set all tracks at once\n if (!progressive) {\n setTracks(loadedTracks);\n setLoadedCount(loadedTracks.length);\n }\n setLoading(false);\n }\n } catch (err) {\n if (!cancelled) {\n const errorMessage = err instanceof Error ? err.message : 'Unknown error loading audio';\n setError(errorMessage);\n setLoading(false);\n console.error('Error loading audio tracks:', err);\n }\n }\n };\n\n loadTracks();\n\n // Cleanup function to prevent state updates if component unmounts\n return () => {\n cancelled = true;\n };\n }, [configs, progressive]);\n\n return { tracks, loading, error, loadedCount, totalCount };\n}\n","import React from 'react';\nimport type { DragEndEvent } from '@dnd-kit/core';\nimport type { ClipTrack } from '@waveform-playlist/core';\n\ninterface UseClipDragHandlersOptions {\n tracks: ClipTrack[];\n onTracksChange: (tracks: ClipTrack[]) => void;\n samplesPerPixel: number;\n sampleRate: number;\n}\n\n/**\n * Custom hook for handling clip drag operations (movement and trimming)\n *\n * Provides drag handlers and collision modifier for use with @dnd-kit/core DndContext.\n * Handles both clip movement (dragging entire clips) and boundary trimming (adjusting clip edges).\n *\n * @example\n * ```tsx\n * const { onDragStart, onDragMove, onDragEnd, collisionModifier } = useClipDragHandlers({\n * tracks,\n * onTracksChange: setTracks,\n * samplesPerPixel,\n * sampleRate,\n * });\n *\n * return (\n * <DndContext\n * onDragStart={onDragStart}\n * onDragMove={onDragMove}\n * onDragEnd={onDragEnd}\n * modifiers={[restrictToHorizontalAxis, collisionModifier]}\n * >\n * <Waveform showClipHeaders={true} />\n * </DndContext>\n * );\n * ```\n */\nexport function useClipDragHandlers({\n tracks,\n onTracksChange,\n samplesPerPixel,\n sampleRate,\n}: UseClipDragHandlersOptions) {\n // Store original clip state when drag starts (for cumulative delta application)\n const originalClipStateRef = React.useRef<{\n offsetSamples: number;\n durationSamples: number;\n startSample: number;\n } | null>(null);\n\n // Custom modifier for real-time collision detection during clip movement\n const collisionModifier = React.useCallback(\n (args: { transform: { x: number; y: number }; active: any }) => {\n const { transform, active } = args;\n\n if (!active?.data?.current) return { ...transform, scaleX: 1, scaleY: 1 };\n\n const { trackIndex, clipIndex, boundary } = active.data.current as {\n clipId: string;\n trackIndex: number;\n clipIndex: number;\n boundary?: 'left' | 'right';\n };\n\n // For boundary trimming, skip modifier - onDragMove handles constraints\n if (boundary) {\n return { ...transform, scaleX: 1, scaleY: 1 };\n }\n\n const track = tracks[trackIndex];\n if (!track) return { ...transform, scaleX: 1, scaleY: 1 };\n\n const clip = track.clips[clipIndex];\n if (!clip) return { ...transform, scaleX: 1, scaleY: 1 };\n\n // Convert sample-based properties to time for calculations\n const clipStartTime = clip.startSample / sampleRate;\n const clipDuration = clip.durationSamples / sampleRate;\n\n // Convert pixel delta to time delta\n const timeDelta = (transform.x * samplesPerPixel) / sampleRate;\n\n // Handle clip movement (not trimming)\n let newStartTime = clipStartTime + timeDelta;\n\n // Get sorted clips for collision detection\n const sortedClips = [...track.clips].sort((a, b) => (a.startSample - b.startSample));\n const sortedIndex = sortedClips.findIndex((c) => c === clip);\n\n // Constraint 1: Cannot go before time 0\n newStartTime = Math.max(0, newStartTime);\n\n // Constraint 2: Cannot overlap with previous clip\n const previousClip = sortedIndex > 0 ? sortedClips[sortedIndex - 1] : null;\n if (previousClip) {\n const previousEndTime = (previousClip.startSample + previousClip.durationSamples) / sampleRate;\n newStartTime = Math.max(newStartTime, previousEndTime);\n }\n\n // Constraint 3: Cannot overlap with next clip\n const nextClip = sortedIndex < sortedClips.length - 1 ? sortedClips[sortedIndex + 1] : null;\n if (nextClip) {\n const newEndTime = newStartTime + clipDuration;\n const nextClipStartTime = nextClip.startSample / sampleRate;\n if (newEndTime > nextClipStartTime) {\n newStartTime = nextClipStartTime - clipDuration;\n }\n }\n\n // Convert constrained time back to pixel delta\n const constrainedTimeDelta = newStartTime - clipStartTime;\n const constrainedX = (constrainedTimeDelta * sampleRate) / samplesPerPixel;\n\n return {\n ...transform,\n x: constrainedX,\n scaleX: 1,\n scaleY: 1,\n };\n },\n [tracks, samplesPerPixel, sampleRate]\n );\n\n const onDragStart = React.useCallback(\n (event: { active: any }) => {\n const { active } = event;\n const { boundary } = active.data.current as { boundary?: 'left' | 'right' };\n\n // Only store state for boundary trimming operations\n if (!boundary) {\n originalClipStateRef.current = null;\n return;\n }\n\n const { trackIndex, clipIndex } = active.data.current as {\n clipId: string;\n trackIndex: number;\n clipIndex: number;\n boundary: 'left' | 'right';\n };\n\n const track = tracks[trackIndex];\n const clip = track?.clips[clipIndex];\n\n if (clip) {\n // Store original clip state for cumulative delta application\n originalClipStateRef.current = {\n offsetSamples: clip.offsetSamples,\n durationSamples: clip.durationSamples,\n startSample: clip.startSample,\n };\n }\n },\n [tracks]\n );\n\n const onDragMove = React.useCallback(\n (event: { active: any; delta: { x: number; y: number } }) => {\n const { active, delta } = event;\n\n // Only update for boundary trimming operations (not clip movement)\n const { boundary } = active.data.current as { boundary?: 'left' | 'right' };\n if (!boundary) return;\n\n // Need original clip state to apply cumulative delta\n if (!originalClipStateRef.current) return;\n\n // Extract clip metadata\n const { trackIndex, clipIndex } = active.data.current as {\n clipId: string;\n trackIndex: number;\n clipIndex: number;\n boundary: 'left' | 'right';\n };\n\n const sampleDelta = delta.x * samplesPerPixel;\n const MIN_DURATION_SAMPLES = Math.floor(0.1 * sampleRate); // 0.1 seconds minimum\n\n // Get original clip state (stored on drag start)\n const originalClip = originalClipStateRef.current;\n\n // Update tracks in real-time during drag\n const newTracks = tracks.map((track, tIdx) => {\n if (tIdx !== trackIndex) return track;\n\n const sortedClips = [...track.clips].sort((a, b) => a.startSample - b.startSample);\n const sortedIndex = sortedClips.findIndex((clip) => clip === track.clips[clipIndex]);\n\n const newClips = track.clips.map((clip, cIdx) => {\n if (cIdx !== clipIndex) return clip;\n\n // Use sourceDurationSamples (works for both audio and peaks-only clips)\n const audioBufferDurationSamples = clip.sourceDurationSamples;\n\n if (boundary === 'left') {\n // Left boundary drag: moving left (negative delta) expands clip, moving right shrinks it\n // The RIGHT edge stays fixed. We're moving the LEFT edge.\n //\n // When dragging left (sampleDelta < 0):\n // - startSample decreases (moves left)\n // - durationSamples increases (clip gets longer)\n // - offsetSamples decreases (reveal earlier audio from buffer)\n //\n // When dragging right (sampleDelta > 0):\n // - startSample increases (moves right)\n // - durationSamples decreases (clip gets shorter)\n // - offsetSamples increases (hide earlier audio)\n\n // Calculate the constrained delta first, then apply it uniformly\n let constrainedDelta = Math.floor(sampleDelta);\n\n // Constraint 1: startSample cannot go below 0 (dragging left limit)\n // newStartSample = originalClip.startSample + delta >= 0\n // delta >= -originalClip.startSample\n const minDeltaForStart = -originalClip.startSample;\n if (constrainedDelta < minDeltaForStart) {\n constrainedDelta = minDeltaForStart;\n }\n\n // Constraint 2: offsetSamples cannot go below 0 (can't reveal audio before buffer start)\n // newOffsetSamples = originalClip.offsetSamples + delta >= 0\n // delta >= -originalClip.offsetSamples\n const minDeltaForOffset = -originalClip.offsetSamples;\n if (constrainedDelta < minDeltaForOffset) {\n constrainedDelta = minDeltaForOffset;\n }\n\n // Constraint 3: Cannot overlap with previous clip (dragging left limit)\n const previousClip = sortedIndex > 0 ? sortedClips[sortedIndex - 1] : null;\n if (previousClip) {\n const previousEndSample = previousClip.startSample + previousClip.durationSamples;\n // newStartSample = originalClip.startSample + delta >= previousEndSample\n // delta >= previousEndSample - originalClip.startSample\n const minDeltaForPrevious = previousEndSample - originalClip.startSample;\n if (constrainedDelta < minDeltaForPrevious) {\n constrainedDelta = minDeltaForPrevious;\n }\n }\n\n // Constraint 4: Minimum duration (dragging right limit)\n // newDurationSamples = originalClip.durationSamples - delta >= MIN_DURATION_SAMPLES\n // -delta >= MIN_DURATION_SAMPLES - originalClip.durationSamples\n // delta <= originalClip.durationSamples - MIN_DURATION_SAMPLES\n const maxDeltaForMinDuration = originalClip.durationSamples - MIN_DURATION_SAMPLES;\n if (constrainedDelta > maxDeltaForMinDuration) {\n constrainedDelta = maxDeltaForMinDuration;\n }\n\n // Constraint 5: Cannot exceed audio buffer length\n // newOffsetSamples + newDurationSamples <= audioBufferDurationSamples\n // (originalClip.offsetSamples + delta) + (originalClip.durationSamples - delta) <= audioBufferDurationSamples\n // This simplifies to: originalClip.offsetSamples + originalClip.durationSamples <= audioBufferDurationSamples\n // This is always true if the clip was valid to begin with, so no constraint needed here\n\n // Now apply the constrained delta\n const newOffsetSamples = originalClip.offsetSamples + constrainedDelta;\n const newDurationSamples = originalClip.durationSamples - constrainedDelta;\n const newStartSample = originalClip.startSample + constrainedDelta;\n\n return {\n ...clip,\n offsetSamples: newOffsetSamples,\n durationSamples: newDurationSamples,\n startSample: newStartSample\n };\n } else {\n // Right boundary - only update duration\n // Apply cumulative delta to ORIGINAL state (not current state)\n let newDurationSamples = Math.floor(originalClip.durationSamples + sampleDelta);\n newDurationSamples = Math.max(MIN_DURATION_SAMPLES, newDurationSamples);\n\n if (originalClip.offsetSamples + newDurationSamples > audioBufferDurationSamples) {\n newDurationSamples = audioBufferDurationSamples - originalClip.offsetSamples;\n }\n\n const nextClip = sortedIndex < sortedClips.length - 1 ? sortedClips[sortedIndex + 1] : null;\n if (nextClip) {\n const newEndSample = originalClip.startSample + newDurationSamples;\n if (newEndSample > nextClip.startSample) {\n newDurationSamples = nextClip.startSample - originalClip.startSample;\n newDurationSamples = Math.max(MIN_DURATION_SAMPLES, newDurationSamples);\n }\n }\n\n return { ...clip, durationSamples: newDurationSamples };\n }\n });\n\n return { ...track, clips: newClips };\n });\n\n onTracksChange(newTracks);\n },\n [tracks, onTracksChange, samplesPerPixel, sampleRate]\n );\n\n const onDragEnd = React.useCallback(\n (event: DragEndEvent) => {\n const { active, delta } = event;\n\n // Extract clip metadata from drag data\n const { trackIndex, clipIndex, boundary } = active.data.current as {\n clipId: string;\n trackIndex: number;\n clipIndex: number;\n boundary?: 'left' | 'right';\n };\n\n // Convert pixel delta to samples\n const sampleDelta = delta.x * samplesPerPixel;\n\n // Check if this is a boundary trim operation\n if (boundary) {\n // For boundary trimming, onDragMove already updated the tracks\n // onDragEnd doesn't need to do anything (state is already correct)\n // Just clear the original clip state ref\n originalClipStateRef.current = null;\n return;\n }\n\n // Handle clip movement (not trimming)\n const newTracks = tracks.map((track, tIdx) => {\n if (tIdx !== trackIndex) return track;\n\n // Get sorted clips for collision detection\n const sortedClips = [...track.clips].sort((a, b) => a.startSample - b.startSample);\n const sortedIndex = sortedClips.findIndex((clip) => clip === track.clips[clipIndex]);\n\n // Update the specific clip in this track\n const newClips = track.clips.map((clip, cIdx) => {\n if (cIdx !== clipIndex) return clip;\n\n // Calculate desired new start sample\n let newStartSample = Math.floor(clip.startSample + sampleDelta);\n\n // Collision detection constraints:\n // 1. Cannot go before sample 0\n newStartSample = Math.max(0, newStartSample);\n\n // 2. Cannot overlap with previous clip\n const previousClip = sortedIndex > 0 ? sortedClips[sortedIndex - 1] : null;\n if (previousClip) {\n const previousEndSample = previousClip.startSample + previousClip.durationSamples;\n newStartSample = Math.max(newStartSample, previousEndSample);\n }\n\n // 3. Cannot overlap with next clip\n const nextClip = sortedIndex < sortedClips.length - 1 ? sortedClips[sortedIndex + 1] : null;\n if (nextClip) {\n const newEndSample = newStartSample + clip.durationSamples;\n if (newEndSample > nextClip.startSample) {\n // Push back to be adjacent to next clip\n newStartSample = nextClip.startSample - clip.durationSamples;\n }\n }\n\n return {\n ...clip,\n startSample: newStartSample,\n };\n });\n\n return {\n ...track,\n clips: newClips,\n };\n });\n\n onTracksChange(newTracks);\n },\n [tracks, onTracksChange, samplesPerPixel, sampleRate]\n );\n\n return {\n onDragStart,\n onDragMove,\n onDragEnd,\n collisionModifier,\n };\n}\n","import React from 'react';\nimport type { AnnotationType } from '@waveform-playlist/annotations';\n\nconst LINK_THRESHOLD = 0.01; // Consider edges \"linked\" if within 10ms\n\ninterface UseAnnotationDragHandlersOptions {\n annotations: AnnotationType[];\n onAnnotationsChange: (annotations: AnnotationType[]) => void;\n samplesPerPixel: number;\n sampleRate: number;\n duration: number;\n linkEndpoints: boolean;\n}\n\n/**\n * Custom hook for handling annotation drag operations (boundary trimming)\n *\n * Provides drag handlers for use with @dnd-kit/core DndContext.\n * Handles annotation boundary resizing with linked endpoints support.\n *\n * @example\n * ```tsx\n * const { onDragStart, onDragMove, onDragEnd } = useAnnotationDragHandlers({\n * annotations,\n * onAnnotationsChange: setAnnotations,\n * samplesPerPixel,\n * sampleRate,\n * duration,\n * linkEndpoints,\n * });\n *\n * return (\n * <DndContext\n * onDragStart={onDragStart}\n * onDragMove={onDragMove}\n * onDragEnd={onDragEnd}\n * modifiers={[restrictToHorizontalAxis]}\n * >\n * {renderAnnotations()}\n * </DndContext>\n * );\n * ```\n */\nexport function useAnnotationDragHandlers({\n annotations,\n onAnnotationsChange,\n samplesPerPixel,\n sampleRate,\n duration,\n linkEndpoints,\n}: UseAnnotationDragHandlersOptions) {\n // Store original annotation state when drag starts (for cumulative delta application)\n const originalAnnotationStateRef = React.useRef<{\n start: number;\n end: number;\n annotationIndex: number;\n } | null>(null);\n\n const onDragStart = React.useCallback(\n (event: { active: any }) => {\n const { active } = event;\n const data = active.data.current as {\n annotationId: string;\n annotationIndex: number;\n edge: 'start' | 'end';\n };\n\n if (!data || data.annotationIndex === undefined) {\n originalAnnotationStateRef.current = null;\n return;\n }\n\n const annotation = annotations[data.annotationIndex];\n if (annotation) {\n originalAnnotationStateRef.current = {\n start: annotation.start,\n end: annotation.end,\n annotationIndex: data.annotationIndex,\n };\n }\n },\n [annotations]\n );\n\n const onDragMove = React.useCallback(\n (event: { active: any; delta: { x: number; y: number } }) => {\n const { active, delta } = event;\n\n if (!originalAnnotationStateRef.current) {\n return;\n }\n\n const data = active.data.current as {\n annotationId: string;\n annotationIndex: number;\n edge: 'start' | 'end';\n };\n\n if (!data) return;\n\n const { edge, annotationIndex } = data;\n const originalState = originalAnnotationStateRef.current;\n\n // Convert pixel delta to time delta\n const timeDelta = (delta.x * samplesPerPixel) / sampleRate;\n\n // Apply delta to original state\n const newTime = edge === 'start'\n ? originalState.start + timeDelta\n : originalState.end + timeDelta;\n\n // Update annotations using the boundary logic\n const updatedAnnotations = updateAnnotationBoundaries({\n annotationIndex,\n newTime,\n isDraggingStart: edge === 'start',\n annotations,\n duration,\n linkEndpoints,\n });\n\n onAnnotationsChange(updatedAnnotations);\n },\n [annotations, onAnnotationsChange, samplesPerPixel, sampleRate, duration, linkEndpoints]\n );\n\n const onDragEnd = React.useCallback(() => {\n originalAnnotationStateRef.current = null;\n }, []);\n\n return {\n onDragStart,\n onDragMove,\n onDragEnd,\n };\n}\n\n/**\n * Updates annotation boundaries based on drag operations.\n * Handles linked endpoints and collision detection.\n */\nfunction updateAnnotationBoundaries({\n annotationIndex,\n newTime,\n isDraggingStart,\n annotations,\n duration,\n linkEndpoints: shouldLinkEndpoints,\n}: {\n annotationIndex: number;\n newTime: number;\n isDraggingStart: boolean;\n annotations: AnnotationType[];\n duration: number;\n linkEndpoints: boolean;\n}): AnnotationType[] {\n const updatedAnnotations = [...annotations];\n const annotation = annotations[annotationIndex];\n\n if (isDraggingStart) {\n // Dragging start edge\n const constrainedStart = Math.min(annotation.end - 0.1, Math.max(0, newTime));\n const delta = constrainedStart - annotation.start;\n\n updatedAnnotations[annotationIndex] = {\n ...annotation,\n start: constrainedStart,\n };\n\n if (shouldLinkEndpoints && annotationIndex > 0) {\n // Link Endpoints mode: handle both already-linked and collision scenarios\n const prevAnnotation = updatedAnnotations[annotationIndex - 1];\n\n if (Math.abs(prevAnnotation.end - annotation.start) < LINK_THRESHOLD) {\n // Already linked: move previous annotation's end together with this start\n updatedAnnotations[annotationIndex - 1] = {\n ...prevAnnotation,\n end: Math.max(prevAnnotation.start + 0.1, prevAnnotation.end + delta),\n };\n } else if (constrainedStart <= prevAnnotation.end) {\n // Dragged past previous annotation: snap to link them together\n updatedAnnotations[annotationIndex] = {\n ...updatedAnnotations[annotationIndex],\n start: prevAnnotation.end,\n };\n }\n } else if (!shouldLinkEndpoints && annotationIndex > 0 && constrainedStart < updatedAnnotations[annotationIndex - 1].end) {\n // Collision detection: push previous annotation's end back\n updatedAnnotations[annotationIndex - 1] = {\n ...updatedAnnotations[annotationIndex - 1],\n end: constrainedStart,\n };\n }\n } else {\n // Dragging end edge\n const constrainedEnd = Math.max(annotation.start + 0.1, Math.min(newTime, duration));\n const delta = constrainedEnd - annotation.end;\n\n updatedAnnotations[annotationIndex] = {\n ...annotation,\n end: constrainedEnd,\n };\n\n if (shouldLinkEndpoints && annotationIndex < updatedAnnotations.length - 1) {\n // Link Endpoints mode: handle both already-linked and collision scenarios\n const nextAnnotation = updatedAnnotations[annotationIndex + 1];\n\n if (Math.abs(nextAnnotation.start - annotation.end) < LINK_THRESHOLD) {\n // Already linked: move next annotation's start together with this end\n const newStart = nextAnnotation.start + delta;\n updatedAnnotations[annotationIndex + 1] = {\n ...nextAnnotation,\n start: Math.min(nextAnnotation.end - 0.1, newStart),\n };\n\n // Cascade linked endpoints\n let currentIndex = annotationIndex + 1;\n while (currentIndex < updatedAnnotations.length - 1) {\n const current = updatedAnnotations[currentIndex];\n const next = updatedAnnotations[currentIndex + 1];\n\n if (Math.abs(next.start - current.end) < LINK_THRESHOLD) {\n const nextDelta = current.end - annotations[currentIndex].end;\n updatedAnnotations[currentIndex + 1] = {\n ...next,\n start: Math.min(next.end - 0.1, next.start + nextDelta),\n };\n currentIndex++;\n } else {\n break; // No more linked endpoints\n }\n }\n } else if (constrainedEnd >= nextAnnotation.start) {\n // Dragged past next annotation: snap to link them together\n updatedAnnotations[annotationIndex] = {\n ...updatedAnnotations[annotationIndex],\n end: nextAnnotation.start,\n };\n }\n } else if (!shouldLinkEndpoints && annotationIndex < updatedAnnotations.length - 1 && constrainedEnd > updatedAnnotations[annotationIndex + 1].start) {\n // Collision detection: push next annotation's start forward\n const nextAnnotation = updatedAnnotations[annotationIndex + 1];\n\n updatedAnnotations[annotationIndex + 1] = {\n ...nextAnnotation,\n start: constrainedEnd,\n };\n\n // Cascade collisions\n let currentIndex = annotationIndex + 1;\n while (currentIndex < updatedAnnotations.length - 1) {\n const current = updatedAnnotations[currentIndex];\n const next = updatedAnnotations[currentIndex + 1];\n\n if (current.end > next.start) {\n updatedAnnotations[currentIndex + 1] = {\n ...next,\n start: current.end,\n };\n currentIndex++;\n } else {\n break; // No more collisions\n }\n }\n }\n }\n\n return updatedAnnotations;\n}\n","import { useMemo, useLayoutEffect, useEffect, useRef, useCallback } from 'react';\n\nfunction useCombinedRefs() {\n for (var _len = arguments.length, refs = new Array(_len), _key = 0; _key < _len; _key++) {\n refs[_key] = arguments[_key];\n }\n\n return useMemo(() => node => {\n refs.forEach(ref => ref(node));\n }, // eslint-disable-next-line react-hooks/exhaustive-deps\n refs);\n}\n\n// https://github.com/facebook/react/blob/master/packages/shared/ExecutionEnvironment.js\nconst canUseDOM = typeof window !== 'undefined' && typeof window.document !== 'undefined' && typeof window.document.createElement !== 'undefined';\n\nfunction isWindow(element) {\n const elementString = Object.prototype.toString.call(element);\n return elementString === '[object Window]' || // In Electron context the Window object serializes to [object global]\n elementString === '[object global]';\n}\n\nfunction isNode(node) {\n return 'nodeType' in node;\n}\n\nfunction getWindow(target) {\n var _target$ownerDocument, _target$ownerDocument2;\n\n if (!target) {\n return window;\n }\n\n if (isWindow(target)) {\n return target;\n }\n\n if (!isNode(target)) {\n return window;\n }\n\n return (_target$ownerDocument = (_target$ownerDocument2 = target.ownerDocument) == null ? void 0 : _target$ownerDocument2.defaultView) != null ? _target$ownerDocument : window;\n}\n\nfunction isDocument(node) {\n const {\n Document\n } = getWindow(node);\n return node instanceof Document;\n}\n\nfunction isHTMLElement(node) {\n if (isWindow(node)) {\n return false;\n }\n\n return node instanceof getWindow(node).HTMLElement;\n}\n\nfunction isSVGElement(node) {\n return node instanceof getWindow(node).SVGElement;\n}\n\nfunction getOwnerDocument(target) {\n if (!target) {\n return document;\n }\n\n if (isWindow(target)) {\n return target.document;\n }\n\n if (!isNode(target)) {\n return document;\n }\n\n if (isDocument(target)) {\n return target;\n }\n\n if (isHTMLElement(target) || isSVGElement(target)) {\n return target.ownerDocument;\n }\n\n return document;\n}\n\n/**\r\n * A hook that resolves to useEffect on the server and useLayoutEffect on the client\r\n * @param callback {function} Callback function that is invoked when the dependencies of the hook change\r\n */\n\nconst useIsomorphicLayoutEffect = canUseDOM ? useLayoutEffect : useEffect;\n\nfunction useEvent(handler) {\n const handlerRef = useRef(handler);\n useIsomorphicLayoutEffect(() => {\n handlerRef.current = handler;\n });\n return useCallback(function () {\n for (var _len = arguments.length, args = new Array(_len), _key = 0; _key < _len; _key++) {\n args[_key] = arguments[_key];\n }\n\n return handlerRef.current == null ? void 0 : handlerRef.current(...args);\n }, []);\n}\n\nfunction useInterval() {\n const intervalRef = useRef(null);\n const set = useCallback((listener, duration) => {\n intervalRef.current = setInterval(listener, duration);\n }, []);\n const clear = useCallback(() => {\n if (intervalRef.current !== null) {\n clearInterval(intervalRef.current);\n intervalRef.current = null;\n }\n }, []);\n return [set, clear];\n}\n\nfunction useLatestValue(value, dependencies) {\n if (dependencies === void 0) {\n dependencies = [value];\n }\n\n const valueRef = useRef(value);\n useIsomorphicLayoutEffect(() => {\n if (valueRef.current !== value) {\n valueRef.current = value;\n }\n }, dependencies);\n return valueRef;\n}\n\nfunction useLazyMemo(callback, dependencies) {\n const valueRef = useRef();\n return useMemo(() => {\n const newValue = callback(valueRef.current);\n valueRef.current = newValue;\n return newValue;\n }, // eslint-disable-next-line react-hooks/exhaustive-deps\n [...dependencies]);\n}\n\nfunction useNodeRef(onChange) {\n const onChangeHandler = useEvent(onChange);\n const node = useRef(null);\n const setNodeRef = useCallback(element => {\n if (element !== node.current) {\n onChangeHandler == null ? void 0 : onChangeHandler(element, node.current);\n }\n\n node.current = element;\n }, //eslint-disable-next-line\n []);\n return [node, setNodeRef];\n}\n\nfunction usePrevious(value) {\n const ref = useRef();\n useEffect(() => {\n ref.current = value;\n }, [value]);\n return ref.current;\n}\n\nlet ids = {};\nfunction useUniqueId(prefix, value) {\n return useMemo(() => {\n if (value) {\n return value;\n }\n\n const id = ids[prefix] == null ? 0 : ids[prefix] + 1;\n ids[prefix] = id;\n return prefix + \"-\" + id;\n }, [prefix, value]);\n}\n\nfunction createAdjustmentFn(modifier) {\n return function (object) {\n for (var _len = arguments.length, adjustments = new Array(_len > 1 ? _len - 1 : 0), _key = 1; _key < _len; _key++) {\n adjustments[_key - 1] = arguments[_key];\n }\n\n return adjustments.reduce((accumulator, adjustment) => {\n const entries = Object.entries(adjustment);\n\n for (const [key, valueAdjustment] of entries) {\n const value = accumulator[key];\n\n if (value != null) {\n accumulator[key] = value + modifier * valueAdjustment;\n }\n }\n\n return accumulator;\n }, { ...object\n });\n };\n}\n\nconst add = /*#__PURE__*/createAdjustmentFn(1);\nconst subtract = /*#__PURE__*/createAdjustmentFn(-1);\n\nfunction hasViewportRelativeCoordinates(event) {\n return 'clientX' in event && 'clientY' in event;\n}\n\nfunction isKeyboardEvent(event) {\n if (!event) {\n return false;\n }\n\n const {\n KeyboardEvent\n } = getWindow(event.target);\n return KeyboardEvent && event instanceof KeyboardEvent;\n}\n\nfunction isTouchEvent(event) {\n if (!event) {\n return false;\n }\n\n const {\n TouchEvent\n } = getWindow(event.target);\n return TouchEvent && event instanceof TouchEvent;\n}\n\n/**\r\n * Returns the normalized x and y coordinates for mouse and touch events.\r\n */\n\nfunction getEventCoordinates(event) {\n if (isTouchEvent(event)) {\n if (event.touches && event.touches.length) {\n const {\n clientX: x,\n clientY: y\n } = event.touches[0];\n return {\n x,\n y\n };\n } else if (event.changedTouches && event.changedTouches.length) {\n const {\n clientX: x,\n clientY: y\n } = event.changedTouches[0];\n return {\n x,\n y\n };\n }\n }\n\n if (hasViewportRelativeCoordinates(event)) {\n return {\n x: event.clientX,\n y: event.clientY\n };\n }\n\n return null;\n}\n\nconst CSS = /*#__PURE__*/Object.freeze({\n Translate: {\n toString(transform) {\n if (!transform) {\n return;\n }\n\n const {\n x,\n y\n } = transform;\n return \"translate3d(\" + (x ? Math.round(x) : 0) + \"px, \" + (y ? Math.round(y) : 0) + \"px, 0)\";\n }\n\n },\n Scale: {\n toString(transform) {\n if (!transform) {\n return;\n }\n\n const {\n scaleX,\n scaleY\n } = transform;\n return \"scaleX(\" + scaleX + \") scaleY(\" + scaleY + \")\";\n }\n\n },\n Transform: {\n toString(transform) {\n if (!transform) {\n return;\n }\n\n return [CSS.Translate.toString(transform), CSS.Scale.toString(transform)].join(' ');\n }\n\n },\n Transition: {\n toString(_ref) {\n let {\n property,\n duration,\n easing\n } = _ref;\n return property + \" \" + duration + \"ms \" + easing;\n }\n\n }\n});\n\nconst SELECTOR = 'a,frame,iframe,input:not([type=hidden]):not(:disabled),select:not(:disabled),textarea:not(:disabled),button:not(:disabled),*[tabindex]';\nfunction findFirstFocusableNode(element) {\n if (element.matches(SELECTOR)) {\n return element;\n }\n\n return element.querySelector(SELECTOR);\n}\n\nexport { CSS, add, canUseDOM, findFirstFocusableNode, getEventCoordinates, getOwnerDocument, getWindow, hasViewportRelativeCoordinates, isDocument, isHTMLElement, isKeyboardEvent, isNode, isSVGElement, isTouchEvent, isWindow, subtract, useCombinedRefs, useEvent, useInterval, useIsomorphicLayoutEffect, useLatestValue, useLazyMemo, useNodeRef, usePrevious, useUniqueId };\n//# sourceMappingURL=utilities.esm.js.map\n","import React, { createContext, useContext, useEffect, useState, useCallback, useMemo, useRef, memo, useReducer, cloneElement, forwardRef } from 'react';\nimport { createPortal, unstable_batchedUpdates } from 'react-dom';\nimport { useUniqueId, getEventCoordinates, getWindow, isDocument, isHTMLElement, isSVGElement, canUseDOM, isWindow, isNode, getOwnerDocument, add, isKeyboardEvent, subtract, useLazyMemo, useInterval, usePrevious, useLatestValue, useEvent, useIsomorphicLayoutEffect, useNodeRef, findFirstFocusableNode, CSS } from '@dnd-kit/utilities';\nimport { useAnnouncement, HiddenText, LiveRegion } from '@dnd-kit/accessibility';\n\nconst DndMonitorContext = /*#__PURE__*/createContext(null);\n\nfunction useDndMonitor(listener) {\n const registerListener = useContext(DndMonitorContext);\n useEffect(() => {\n if (!registerListener) {\n throw new Error('useDndMonitor must be used within a children of <DndContext>');\n }\n\n const unsubscribe = registerListener(listener);\n return unsubscribe;\n }, [listener, registerListener]);\n}\n\nfunction useDndMonitorProvider() {\n const [listeners] = useState(() => new Set());\n const registerListener = useCallback(listener => {\n listeners.add(listener);\n return () => listeners.delete(listener);\n }, [listeners]);\n const dispatch = useCallback(_ref => {\n let {\n type,\n event\n } = _ref;\n listeners.forEach(listener => {\n var _listener$type;\n\n return (_listener$type = listener[type]) == null ? void 0 : _listener$type.call(listener, event);\n });\n }, [listeners]);\n return [dispatch, registerListener];\n}\n\nconst defaultScreenReaderInstructions = {\n draggable: \"\\n To pick up a draggable item, press the space bar.\\n While dragging, use the arrow keys to move the item.\\n Press space again to drop the item in its new position, or press escape to cancel.\\n \"\n};\nconst defaultAnnouncements = {\n onDragStart(_ref) {\n let {\n active\n } = _ref;\n return \"Picked up draggable item \" + active.id + \".\";\n },\n\n onDragOver(_ref2) {\n let {\n active,\n over\n } = _ref2;\n\n if (over) {\n return \"Draggable item \" + active.id + \" was moved over droppable area \" + over.id + \".\";\n }\n\n return \"Draggable item \" + active.id + \" is no longer over a droppable area.\";\n },\n\n onDragEnd(_ref3) {\n let {\n active,\n over\n } = _ref3;\n\n if (over) {\n return \"Draggable item \" + active.id + \" was dropped over droppable area \" + over.id;\n }\n\n return \"Draggable item \" + active.id + \" was dropped.\";\n },\n\n onDragCancel(_ref4) {\n let {\n active\n } = _ref4;\n return \"Dragging was cancelled. Draggable item \" + active.id + \" was dropped.\";\n }\n\n};\n\nfunction Accessibility(_ref) {\n let {\n announcements = defaultAnnouncements,\n container,\n hiddenTextDescribedById,\n screenReaderInstructions = defaultScreenReaderInstructions\n } = _ref;\n const {\n announce,\n announcement\n } = useAnnouncement();\n const liveRegionId = useUniqueId(\"DndLiveRegion\");\n const [mounted, setMounted] = useState(false);\n useEffect(() => {\n setMounted(true);\n }, []);\n useDndMonitor(useMemo(() => ({\n onDragStart(_ref2) {\n let {\n active\n } = _ref2;\n announce(announcements.onDragStart({\n active\n }));\n },\n\n onDragMove(_ref3) {\n let {\n active,\n over\n } = _ref3;\n\n if (announcements.onDragMove) {\n announce(announcements.onDragMove({\n active,\n over\n }));\n }\n },\n\n onDragOver(_ref4) {\n let {\n active,\n over\n } = _ref4;\n announce(announcements.onDragOver({\n active,\n over\n }));\n },\n\n onDragEnd(_ref5) {\n let {\n active,\n over\n } = _ref5;\n announce(announcements.onDragEnd({\n active,\n over\n }));\n },\n\n onDragCancel(_ref6) {\n let {\n active,\n over\n } = _ref6;\n announce(announcements.onDragCancel({\n active,\n over\n }));\n }\n\n }), [announce, announcements]));\n\n if (!mounted) {\n return null;\n }\n\n const markup = React.createElement(React.Fragment, null, React.createElement(HiddenText, {\n id: hiddenTextDescribedById,\n value: screenReaderInstructions.draggable\n }), React.createElement(LiveRegion, {\n id: liveRegionId,\n announcement: announcement\n }));\n return container ? createPortal(markup, container) : markup;\n}\n\nvar Action;\n\n(function (Action) {\n Action[\"DragStart\"] = \"dragStart\";\n Action[\"DragMove\"] = \"dragMove\";\n Action[\"DragEnd\"] = \"dragEnd\";\n Action[\"DragCancel\"] = \"dragCancel\";\n Action[\"DragOver\"] = \"dragOver\";\n Action[\"RegisterDroppable\"] = \"registerDroppable\";\n Action[\"SetDroppableDisabled\"] = \"setDroppableDisabled\";\n Action[\"UnregisterDroppable\"] = \"unregisterDroppable\";\n})(Action || (Action = {}));\n\nfunction noop() {}\n\nfunction useSensor(sensor, options) {\n return useMemo(() => ({\n sensor,\n options: options != null ? options : {}\n }), // eslint-disable-next-line react-hooks/exhaustive-deps\n [sensor, options]);\n}\n\nfunction useSensors() {\n for (var _len = arguments.length, sensors = new Array(_len), _key = 0; _key < _len; _key++) {\n sensors[_key] = arguments[_key];\n }\n\n return useMemo(() => [...sensors].filter(sensor => sensor != null), // eslint-disable-next-line react-hooks/exhaustive-deps\n [...sensors]);\n}\n\nconst defaultCoordinates = /*#__PURE__*/Object.freeze({\n x: 0,\n y: 0\n});\n\n/**\r\n * Returns the distance between two points\r\n */\nfunction distanceBetween(p1, p2) {\n return Math.sqrt(Math.pow(p1.x - p2.x, 2) + Math.pow(p1.y - p2.y, 2));\n}\n\nfunction getRelativeTransformOrigin(event, rect) {\n const eventCoordinates = getEventCoordinates(event);\n\n if (!eventCoordinates) {\n return '0 0';\n }\n\n const transformOrigin = {\n x: (eventCoordinates.x - rect.left) / rect.width * 100,\n y: (eventCoordinates.y - rect.top) / rect.height * 100\n };\n return transformOrigin.x + \"% \" + transformOrigin.y + \"%\";\n}\n\n/**\r\n * Sort collisions from smallest to greatest value\r\n */\nfunction sortCollisionsAsc(_ref, _ref2) {\n let {\n data: {\n value: a\n }\n } = _ref;\n let {\n data: {\n value: b\n }\n } = _ref2;\n return a - b;\n}\n/**\r\n * Sort collisions from greatest to smallest value\r\n */\n\nfunction sortCollisionsDesc(_ref3, _ref4) {\n let {\n data: {\n value: a\n }\n } = _ref3;\n let {\n data: {\n value: b\n }\n } = _ref4;\n return b - a;\n}\n/**\r\n * Returns the coordinates of the corners of a given rectangle:\r\n * [TopLeft {x, y}, TopRight {x, y}, BottomLeft {x, y}, BottomRight {x, y}]\r\n */\n\nfunction cornersOfRectangle(_ref5) {\n let {\n left,\n top,\n height,\n width\n } = _ref5;\n return [{\n x: left,\n y: top\n }, {\n x: left + width,\n y: top\n }, {\n x: left,\n y: top + height\n }, {\n x: left + width,\n y: top + height\n }];\n}\nfunction getFirstCollision(collisions, property) {\n if (!collisions || collisions.length === 0) {\n return null;\n }\n\n const [firstCollision] = collisions;\n return property ? firstCollision[property] : firstCollision;\n}\n\n/**\r\n * Returns the coordinates of the center of a given ClientRect\r\n */\n\nfunction centerOfRectangle(rect, left, top) {\n if (left === void 0) {\n left = rect.left;\n }\n\n if (top === void 0) {\n top = rect.top;\n }\n\n return {\n x: left + rect.width * 0.5,\n y: top + rect.height * 0.5\n };\n}\n/**\r\n * Returns the closest rectangles from an array of rectangles to the center of a given\r\n * rectangle.\r\n */\n\n\nconst closestCenter = _ref => {\n let {\n collisionRect,\n droppableRects,\n droppableContainers\n } = _ref;\n const centerRect = centerOfRectangle(collisionRect, collisionRect.left, collisionRect.top);\n const collisions = [];\n\n for (const droppableContainer of droppableContainers) {\n const {\n id\n } = droppableContainer;\n const rect = droppableRects.get(id);\n\n if (rect) {\n const distBetween = distanceBetween(centerOfRectangle(rect), centerRect);\n collisions.push({\n id,\n data: {\n droppableContainer,\n value: distBetween\n }\n });\n }\n }\n\n return collisions.sort(sortCollisionsAsc);\n};\n\n/**\r\n * Returns the closest rectangles from an array of rectangles to the corners of\r\n * another rectangle.\r\n */\n\nconst closestCorners = _ref => {\n let {\n collisionRect,\n droppableRects,\n droppableContainers\n } = _ref;\n const corners = cornersOfRectangle(collisionRect);\n const collisions = [];\n\n for (const droppableContainer of droppableContainers) {\n const {\n id\n } = droppableContainer;\n const rect = droppableRects.get(id);\n\n if (rect) {\n const rectCorners = cornersOfRectangle(rect);\n const distances = corners.reduce((accumulator, corner, index) => {\n return accumulator + distanceBetween(rectCorners[index], corner);\n }, 0);\n const effectiveDistance = Number((distances / 4).toFixed(4));\n collisions.push({\n id,\n data: {\n droppableContainer,\n value: effectiveDistance\n }\n });\n }\n }\n\n return collisions.sort(sortCollisionsAsc);\n};\n\n/**\r\n * Returns the intersecting rectangle area between two rectangles\r\n */\n\nfunction getIntersectionRatio(entry, target) {\n const top = Math.max(target.top, entry.top);\n const left = Math.max(target.left, entry.left);\n const right = Math.min(target.left + target.width, entry.left + entry.width);\n const bottom = Math.min(target.top + target.height, entry.top + entry.height);\n const width = right - left;\n const height = bottom - top;\n\n if (left < right && top < bottom) {\n const targetArea = target.width * target.height;\n const entryArea = entry.width * entry.height;\n const intersectionArea = width * height;\n const intersectionRatio = intersectionArea / (targetArea + entryArea - intersectionArea);\n return Number(intersectionRatio.toFixed(4));\n } // Rectangles do not overlap, or overlap has an area of zero (edge/corner overlap)\n\n\n return 0;\n}\n/**\r\n * Returns the rectangles that has the greatest intersection area with a given\r\n * rectangle in an array of rectangles.\r\n */\n\nconst rectIntersection = _ref => {\n let {\n collisionRect,\n droppableRects,\n droppableContainers\n } = _ref;\n const collisions = [];\n\n for (const droppableContainer of droppableContainers) {\n const {\n id\n } = droppableContainer;\n const rect = droppableRects.get(id);\n\n if (rect) {\n const intersectionRatio = getIntersectionRatio(rect, collisionRect);\n\n if (intersectionRatio > 0) {\n collisions.push({\n id,\n data: {\n droppableContainer,\n value: intersectionRatio\n }\n });\n }\n }\n }\n\n return collisions.sort(sortCollisionsDesc);\n};\n\n/**\r\n * Check if a given point is contained within a bounding rectangle\r\n */\n\nfunction isPointWithinRect(point, rect) {\n const {\n top,\n left,\n bottom,\n right\n } = rect;\n return top <= point.y && point.y <= bottom && left <= point.x && point.x <= right;\n}\n/**\r\n * Returns the rectangles that the pointer is hovering over\r\n */\n\n\nconst pointerWithin = _ref => {\n let {\n droppableContainers,\n droppableRects,\n pointerCoordinates\n } = _ref;\n\n if (!pointerCoordinates) {\n return [];\n }\n\n const collisions = [];\n\n for (const droppableContainer of droppableContainers) {\n const {\n id\n } = droppableContainer;\n const rect = droppableRects.get(id);\n\n if (rect && isPointWithinRect(pointerCoordinates, rect)) {\n /* There may be more than a single rectangle intersecting\r\n * with the pointer coordinates. In order to sort the\r\n * colliding rectangles, we measure the distance between\r\n * the pointer and the corners of the intersecting rectangle\r\n */\n const corners = cornersOfRectangle(rect);\n const distances = corners.reduce((accumulator, corner) => {\n return accumulator + distanceBetween(pointerCoordinates, corner);\n }, 0);\n const effectiveDistance = Number((distances / 4).toFixed(4));\n collisions.push({\n id,\n data: {\n droppableContainer,\n value: effectiveDistance\n }\n });\n }\n }\n\n return collisions.sort(sortCollisionsAsc);\n};\n\nfunction adjustScale(transform, rect1, rect2) {\n return { ...transform,\n scaleX: rect1 && rect2 ? rect1.width / rect2.width : 1,\n scaleY: rect1 && rect2 ? rect1.height / rect2.height : 1\n };\n}\n\nfunction getRectDelta(rect1, rect2) {\n return rect1 && rect2 ? {\n x: rect1.left - rect2.left,\n y: rect1.top - rect2.top\n } : defaultCoordinates;\n}\n\nfunction createRectAdjustmentFn(modifier) {\n return function adjustClientRect(rect) {\n for (var _len = arguments.length, adjustments = new Array(_len > 1 ? _len - 1 : 0), _key = 1; _key < _len; _key++) {\n adjustments[_key - 1] = arguments[_key];\n }\n\n return adjustments.reduce((acc, adjustment) => ({ ...acc,\n top: acc.top + modifier * adjustment.y,\n bottom: acc.bottom + modifier * adjustment.y,\n left: acc.left + modifier * adjustment.x,\n right: acc.right + modifier * adjustment.x\n }), { ...rect\n });\n };\n}\nconst getAdjustedRect = /*#__PURE__*/createRectAdjustmentFn(1);\n\nfunction parseTransform(transform) {\n if (transform.startsWith('matrix3d(')) {\n const transformArray = transform.slice(9, -1).split(/, /);\n return {\n x: +transformArray[12],\n y: +transformArray[13],\n scaleX: +transformArray[0],\n scaleY: +transformArray[5]\n };\n } else if (transform.startsWith('matrix(')) {\n const transformArray = transform.slice(7, -1).split(/, /);\n return {\n x: +transformArray[4],\n y: +transformArray[5],\n scaleX: +transformArray[0],\n scaleY: +transformArray[3]\n };\n }\n\n return null;\n}\n\nfunction inverseTransform(rect, transform, transformOrigin) {\n const parsedTransform = parseTransform(transform);\n\n if (!parsedTransform) {\n return rect;\n }\n\n const {\n scaleX,\n scaleY,\n x: translateX,\n y: translateY\n } = parsedTransform;\n const x = rect.left - translateX - (1 - scaleX) * parseFloat(transformOrigin);\n const y = rect.top - translateY - (1 - scaleY) * parseFloat(transformOrigin.slice(transformOrigin.indexOf(' ') + 1));\n const w = scaleX ? rect.width / scaleX : rect.width;\n const h = scaleY ? rect.height / scaleY : rect.height;\n return {\n width: w,\n height: h,\n top: y,\n right: x + w,\n bottom: y + h,\n left: x\n };\n}\n\nconst defaultOptions = {\n ignoreTransform: false\n};\n/**\r\n * Returns the bounding client rect of an element relative to the viewport.\r\n */\n\nfunction getClientRect(element, options) {\n if (options === void 0) {\n options = defaultOptions;\n }\n\n let rect = element.getBoundingClientRect();\n\n if (options.ignoreTransform) {\n const {\n transform,\n transformOrigin\n } = getWindow(element).getComputedStyle(element);\n\n if (transform) {\n rect = inverseTransform(rect, transform, transformOrigin);\n }\n }\n\n const {\n top,\n left,\n width,\n height,\n bottom,\n right\n } = rect;\n return {\n top,\n left,\n width,\n height,\n bottom,\n right\n };\n}\n/**\r\n * Returns the bounding client rect of an element relative to the viewport.\r\n *\r\n * @remarks\r\n * The ClientRect returned by this method does not take into account transforms\r\n * applied to the element it measures.\r\n *\r\n */\n\nfunction getTransformAgnosticClientRect(element) {\n return getClientRect(element, {\n ignoreTransform: true\n });\n}\n\nfunction getWindowClientRect(element) {\n const width = element.innerWidth;\n const height = element.innerHeight;\n return {\n top: 0,\n left: 0,\n right: width,\n bottom: height,\n width,\n height\n };\n}\n\nfunction isFixed(node, computedStyle) {\n if (computedStyle === void 0) {\n computedStyle = getWindow(node).getComputedStyle(node);\n }\n\n return computedStyle.position === 'fixed';\n}\n\nfunction isScrollable(element, computedStyle) {\n if (computedStyle === void 0) {\n computedStyle = getWindow(element).getComputedStyle(element);\n }\n\n const overflowRegex = /(auto|scroll|overlay)/;\n const properties = ['overflow', 'overflowX', 'overflowY'];\n return properties.some(property => {\n const value = computedStyle[property];\n return typeof value === 'string' ? overflowRegex.test(value) : false;\n });\n}\n\nfunction getScrollableAncestors(element, limit) {\n const scrollParents = [];\n\n function findScrollableAncestors(node) {\n if (limit != null && scrollParents.length >= limit) {\n return scrollParents;\n }\n\n if (!node) {\n return scrollParents;\n }\n\n if (isDocument(node) && node.scrollingElement != null && !scrollParents.includes(node.scrollingElement)) {\n scrollParents.push(node.scrollingElement);\n return scrollParents;\n }\n\n if (!isHTMLElement(node) || isSVGElement(node)) {\n return scrollParents;\n }\n\n if (scrollParents.includes(node)) {\n return scrollParents;\n }\n\n const computedStyle = getWindow(element).getComputedStyle(node);\n\n if (node !== element) {\n if (isScrollable(node, computedStyle)) {\n scrollParents.push(node);\n }\n }\n\n if (isFixed(node, computedStyle)) {\n return scrollParents;\n }\n\n return findScrollableAncestors(node.parentNode);\n }\n\n if (!element) {\n return scrollParents;\n }\n\n return findScrollableAncestors(element);\n}\nfunction getFirstScrollableAncestor(node) {\n const [firstScrollableAncestor] = getScrollableAncestors(node, 1);\n return firstScrollableAncestor != null ? firstScrollableAncestor : null;\n}\n\nfunction getScrollableElement(element) {\n if (!canUseDOM || !element) {\n return null;\n }\n\n if (isWindow(element)) {\n return element;\n }\n\n if (!isNode(element)) {\n return null;\n }\n\n if (isDocument(element) || element === getOwnerDocument(element).scrollingElement) {\n return window;\n }\n\n if (isHTMLElement(element)) {\n return element;\n }\n\n return null;\n}\n\nfunction getScrollXCoordinate(element) {\n if (isWindow(element)) {\n return element.scrollX;\n }\n\n return element.scrollLeft;\n}\nfunction getScrollYCoordinate(element) {\n if (isWindow(element)) {\n return element.scrollY;\n }\n\n return element.scrollTop;\n}\nfunction getScrollCoordinates(element) {\n return {\n x: getScrollXCoordinate(element),\n y: getScrollYCoordinate(element)\n };\n}\n\nvar Direction;\n\n(function (Direction) {\n Direction[Direction[\"Forward\"] = 1] = \"Forward\";\n Direction[Direction[\"Backward\"] = -1] = \"Backward\";\n})(Direction || (Direction = {}));\n\nfunction isDocumentScrollingElement(element) {\n if (!canUseDOM || !element) {\n return false;\n }\n\n return element === document.scrollingElement;\n}\n\nfunction getScrollPosition(scrollingContainer) {\n const minScroll = {\n x: 0,\n y: 0\n };\n const dimensions = isDocumentScrollingElement(scrollingContainer) ? {\n height: window.innerHeight,\n width: window.innerWidth\n } : {\n height: scrollingContainer.clientHeight,\n width: scrollingContainer.clientWidth\n };\n const maxScroll = {\n x: scrollingContainer.scrollWidth - dimensions.width,\n y: scrollingContainer.scrollHeight - dimensions.height\n };\n const isTop = scrollingContainer.scrollTop <= minScroll.y;\n const isLeft = scrollingContainer.scrollLeft <= minScroll.x;\n const isBottom = scrollingContainer.scrollTop >= maxScroll.y;\n const isRight = scrollingContainer.scrollLeft >= maxScroll.x;\n return {\n isTop,\n isLeft,\n isBottom,\n isRight,\n maxScroll,\n minScroll\n };\n}\n\nconst defaultThreshold = {\n x: 0.2,\n y: 0.2\n};\nfunction getScrollDirectionAndSpeed(scrollContainer, scrollContainerRect, _ref, acceleration, thresholdPercentage) {\n let {\n top,\n left,\n right,\n bottom\n } = _ref;\n\n if (acceleration === void 0) {\n acceleration = 10;\n }\n\n if (thresholdPercentage === void 0) {\n thresholdPercentage = defaultThreshold;\n }\n\n const {\n isTop,\n isBottom,\n isLeft,\n isRight\n } = getScrollPosition(scrollContainer);\n const direction = {\n x: 0,\n y: 0\n };\n const speed = {\n x: 0,\n y: 0\n };\n const threshold = {\n height: scrollContainerRect.height * thresholdPercentage.y,\n width: scrollContainerRect.width * thresholdPercentage.x\n };\n\n if (!isTop && top <= scrollContainerRect.top + threshold.height) {\n // Scroll Up\n direction.y = Direction.Backward;\n speed.y = acceleration * Math.abs((scrollContainerRect.top + threshold.height - top) / threshold.height);\n } else if (!isBottom && bottom >= scrollContainerRect.bottom - threshold.height) {\n // Scroll Down\n direction.y = Direction.Forward;\n speed.y = acceleration * Math.abs((scrollContainerRect.bottom - threshold.height - bottom) / threshold.height);\n }\n\n if (!isRight && right >= scrollContainerRect.right - threshold.width) {\n // Scroll Right\n direction.x = Direction.Forward;\n speed.x = acceleration * Math.abs((scrollContainerRect.right - threshold.width - right) / threshold.width);\n } else if (!isLeft && left <= scrollContainerRect.left + threshold.width) {\n // Scroll Left\n direction.x = Direction.Backward;\n speed.x = acceleration * Math.abs((scrollContainerRect.left + threshold.width - left) / threshold.width);\n }\n\n return {\n direction,\n speed\n };\n}\n\nfunction getScrollElementRect(element) {\n if (element === document.scrollingElement) {\n const {\n innerWidth,\n innerHeight\n } = window;\n return {\n top: 0,\n left: 0,\n right: innerWidth,\n bottom: innerHeight,\n width: innerWidth,\n height: innerHeight\n };\n }\n\n const {\n top,\n left,\n right,\n bottom\n } = element.getBoundingClientRect();\n return {\n top,\n left,\n right,\n bottom,\n width: element.clientWidth,\n height: element.clientHeight\n };\n}\n\nfunction getScrollOffsets(scrollableAncestors) {\n return scrollableAncestors.reduce((acc, node) => {\n return add(acc, getScrollCoordinates(node));\n }, defaultCoordinates);\n}\nfunction getScrollXOffset(scrollableAncestors) {\n return scrollableAncestors.reduce((acc, node) => {\n return acc + getScrollXCoordinate(node);\n }, 0);\n}\nfunction getScrollYOffset(scrollableAncestors) {\n return scrollableAncestors.reduce((acc, node) => {\n return acc + getScrollYCoordinate(node);\n }, 0);\n}\n\nfunction scrollIntoViewIfNeeded(element, measure) {\n if (measure === void 0) {\n measure = getClientRect;\n }\n\n if (!element) {\n return;\n }\n\n const {\n top,\n left,\n bottom,\n right\n } = measure(element);\n const firstScrollableAncestor = getFirstScrollableAncestor(element);\n\n if (!firstScrollableAncestor) {\n return;\n }\n\n if (bottom <= 0 || right <= 0 || top >= window.innerHeight || left >= window.innerWidth) {\n element.scrollIntoView({\n block: 'center',\n inline: 'center'\n });\n }\n}\n\nconst properties = [['x', ['left', 'right'], getScrollXOffset], ['y', ['top', 'bottom'], getScrollYOffset]];\nclass Rect {\n constructor(rect, element) {\n this.rect = void 0;\n this.width = void 0;\n this.height = void 0;\n this.top = void 0;\n this.bottom = void 0;\n this.right = void 0;\n this.left = void 0;\n const scrollableAncestors = getScrollableAncestors(element);\n const scrollOffsets = getScrollOffsets(scrollableAncestors);\n this.rect = { ...rect\n };\n this.width = rect.width;\n this.height = rect.height;\n\n for (const [axis, keys, getScrollOffset] of properties) {\n for (const key of keys) {\n Object.defineProperty(this, key, {\n get: () => {\n const currentOffsets = getScrollOffset(scrollableAncestors);\n const scrollOffsetsDeltla = scrollOffsets[axis] - currentOffsets;\n return this.rect[key] + scrollOffsetsDeltla;\n },\n enumerable: true\n });\n }\n }\n\n Object.defineProperty(this, 'rect', {\n enumerable: false\n });\n }\n\n}\n\nclass Listeners {\n constructor(target) {\n this.target = void 0;\n this.listeners = [];\n\n this.removeAll = () => {\n this.listeners.forEach(listener => {\n var _this$target;\n\n return (_this$target = this.target) == null ? void 0 : _this$target.removeEventListener(...listener);\n });\n };\n\n this.target = target;\n }\n\n add(eventName, handler, options) {\n var _this$target2;\n\n (_this$target2 = this.target) == null ? void 0 : _this$target2.addEventListener(eventName, handler, options);\n this.listeners.push([eventName, handler, options]);\n }\n\n}\n\nfunction getEventListenerTarget(target) {\n // If the `event.target` element is removed from the document events will still be targeted\n // at it, and hence won't always bubble up to the window or document anymore.\n // If there is any risk of an element being removed while it is being dragged,\n // the best practice is to attach the event listeners directly to the target.\n // https://developer.mozilla.org/en-US/docs/Web/API/EventTarget\n const {\n EventTarget\n } = getWindow(target);\n return target instanceof EventTarget ? target : getOwnerDocument(target);\n}\n\nfunction hasExceededDistance(delta, measurement) {\n const dx = Math.abs(delta.x);\n const dy = Math.abs(delta.y);\n\n if (typeof measurement === 'number') {\n return Math.sqrt(dx ** 2 + dy ** 2) > measurement;\n }\n\n if ('x' in measurement && 'y' in measurement) {\n return dx > measurement.x && dy > measurement.y;\n }\n\n if ('x' in measurement) {\n return dx > measurement.x;\n }\n\n if ('y' in measurement) {\n return dy > measurement.y;\n }\n\n return false;\n}\n\nvar EventName;\n\n(function (EventName) {\n EventName[\"Click\"] = \"click\";\n EventName[\"DragStart\"] = \"dragstart\";\n EventName[\"Keydown\"] = \"keydown\";\n EventName[\"ContextMenu\"] = \"contextmenu\";\n EventName[\"Resize\"] = \"resize\";\n EventName[\"SelectionChange\"] = \"selectionchange\";\n EventName[\"VisibilityChange\"] = \"visibilitychange\";\n})(EventName || (EventName = {}));\n\nfunction preventDefault(event) {\n event.preventDefault();\n}\nfunction stopPropagation(event) {\n event.stopPropagation();\n}\n\nvar KeyboardCode;\n\n(function (KeyboardCode) {\n KeyboardCode[\"Space\"] = \"Space\";\n KeyboardCode[\"Down\"] = \"ArrowDown\";\n KeyboardCode[\"Right\"] = \"ArrowRight\";\n KeyboardCode[\"Left\"] = \"ArrowLeft\";\n KeyboardCode[\"Up\"] = \"ArrowUp\";\n KeyboardCode[\"Esc\"] = \"Escape\";\n KeyboardCode[\"Enter\"] = \"Enter\";\n KeyboardCode[\"Tab\"] = \"Tab\";\n})(KeyboardCode || (KeyboardCode = {}));\n\nconst defaultKeyboardCodes = {\n start: [KeyboardCode.Space, KeyboardCode.Enter],\n cancel: [KeyboardCode.Esc],\n end: [KeyboardCode.Space, KeyboardCode.Enter, KeyboardCode.Tab]\n};\nconst defaultKeyboardCoordinateGetter = (event, _ref) => {\n let {\n currentCoordinates\n } = _ref;\n\n switch (event.code) {\n case KeyboardCode.Right:\n return { ...currentCoordinates,\n x: currentCoordinates.x + 25\n };\n\n case KeyboardCode.Left:\n return { ...currentCoordinates,\n x: currentCoordinates.x - 25\n };\n\n case KeyboardCode.Down:\n return { ...currentCoordinates,\n y: currentCoordinates.y + 25\n };\n\n case KeyboardCode.Up:\n return { ...currentCoordinates,\n y: currentCoordinates.y - 25\n };\n }\n\n return undefined;\n};\n\nclass KeyboardSensor {\n constructor(props) {\n this.props = void 0;\n this.autoScrollEnabled = false;\n this.referenceCoordinates = void 0;\n this.listeners = void 0;\n this.windowListeners = void 0;\n this.props = props;\n const {\n event: {\n target\n }\n } = props;\n this.props = props;\n this.listeners = new Listeners(getOwnerDocument(target));\n this.windowListeners = new Listeners(getWindow(target));\n this.handleKeyDown = this.handleKeyDown.bind(this);\n this.handleCancel = this.handleCancel.bind(this);\n this.attach();\n }\n\n attach() {\n this.handleStart();\n this.windowListeners.add(EventName.Resize, this.handleCancel);\n this.windowListeners.add(EventName.VisibilityChange, this.handleCancel);\n setTimeout(() => this.listeners.add(EventName.Keydown, this.handleKeyDown));\n }\n\n handleStart() {\n const {\n activeNode,\n onStart\n } = this.props;\n const node = activeNode.node.current;\n\n if (node) {\n scrollIntoViewIfNeeded(node);\n }\n\n onStart(defaultCoordinates);\n }\n\n handleKeyDown(event) {\n if (isKeyboardEvent(event)) {\n const {\n active,\n context,\n options\n } = this.props;\n const {\n keyboardCodes = defaultKeyboardCodes,\n coordinateGetter = defaultKeyboardCoordinateGetter,\n scrollBehavior = 'smooth'\n } = options;\n const {\n code\n } = event;\n\n if (keyboardCodes.end.includes(code)) {\n this.handleEnd(event);\n return;\n }\n\n if (keyboardCodes.cancel.includes(code)) {\n this.handleCancel(event);\n return;\n }\n\n const {\n collisionRect\n } = context.current;\n const currentCoordinates = collisionRect ? {\n x: collisionRect.left,\n y: collisionRect.top\n } : defaultCoordinates;\n\n if (!this.referenceCoordinates) {\n this.referenceCoordinates = currentCoordinates;\n }\n\n const newCoordinates = coordinateGetter(event, {\n active,\n context: context.current,\n currentCoordinates\n });\n\n if (newCoordinates) {\n const coordinatesDelta = subtract(newCoordinates, currentCoordinates);\n const scrollDelta = {\n x: 0,\n y: 0\n };\n const {\n scrollableAncestors\n } = context.current;\n\n for (const scrollContainer of scrollableAncestors) {\n const direction = event.code;\n const {\n isTop,\n isRight,\n isLeft,\n isBottom,\n maxScroll,\n minScroll\n } = getScrollPosition(scrollContainer);\n const scrollElementRect = getScrollElementRect(scrollContainer);\n const clampedCoordinates = {\n x: Math.min(direction === KeyboardCode.Right ? scrollElementRect.right - scrollElementRect.width / 2 : scrollElementRect.right, Math.max(direction === KeyboardCode.Right ? scrollElementRect.left : scrollElementRect.left + scrollElementRect.width / 2, newCoordinates.x)),\n y: Math.min(direction === KeyboardCode.Down ? scrollElementRect.bottom - scrollElementRect.height / 2 : scrollElementRect.bottom, Math.max(direction === KeyboardCode.Down ? scrollElementRect.top : scrollElementRect.top + scrollElementRect.height / 2, newCoordinates.y))\n };\n const canScrollX = direction === KeyboardCode.Right && !isRight || direction === KeyboardCode.Left && !isLeft;\n const canScrollY = direction === KeyboardCode.Down && !isBottom || direction === KeyboardCode.Up && !isTop;\n\n if (canScrollX && clampedCoordinates.x !== newCoordinates.x) {\n const newScrollCoordinates = scrollContainer.scrollLeft + coordinatesDelta.x;\n const canScrollToNewCoordinates = direction === KeyboardCode.Right && newScrollCoordinates <= maxScroll.x || direction === KeyboardCode.Left && newScrollCoordinates >= minScroll.x;\n\n if (canScrollToNewCoordinates && !coordinatesDelta.y) {\n // We don't need to update coordinates, the scroll adjustment alone will trigger\n // logic to auto-detect the new container we are over\n scrollContainer.scrollTo({\n left: newScrollCoordinates,\n behavior: scrollBehavior\n });\n return;\n }\n\n if (canScrollToNewCoordinates) {\n scrollDelta.x = scrollContainer.scrollLeft - newScrollCoordinates;\n } else {\n scrollDelta.x = direction === KeyboardCode.Right ? scrollContainer.scrollLeft - maxScroll.x : scrollContainer.scrollLeft - minScroll.x;\n }\n\n if (scrollDelta.x) {\n scrollContainer.scrollBy({\n left: -scrollDelta.x,\n behavior: scrollBehavior\n });\n }\n\n break;\n } else if (canScrollY && clampedCoordinates.y !== newCoordinates.y) {\n const newScrollCoordinates = scrollContainer.scrollTop + coordinatesDelta.y;\n const canScrollToNewCoordinates = direction === KeyboardCode.Down && newScrollCoordinates <= maxScroll.y || direction === KeyboardCode.Up && newScrollCoordinates >= minScroll.y;\n\n if (canScrollToNewCoordinates && !coordinatesDelta.x) {\n // We don't need to update coordinates, the scroll adjustment alone will trigger\n // logic to auto-detect the new container we are over\n scrollContainer.scrollTo({\n top: newScrollCoordinates,\n behavior: scrollBehavior\n });\n return;\n }\n\n if (canScrollToNewCoordinates) {\n scrollDelta.y = scrollContainer.scrollTop - newScrollCoordinates;\n } else {\n scrollDelta.y = direction === KeyboardCode.Down ? scrollContainer.scrollTop - maxScroll.y : scrollContainer.scrollTop - minScroll.y;\n }\n\n if (scrollDelta.y) {\n scrollContainer.scrollBy({\n top: -scrollDelta.y,\n behavior: scrollBehavior\n });\n }\n\n break;\n }\n }\n\n this.handleMove(event, add(subtract(newCoordinates, this.referenceCoordinates), scrollDelta));\n }\n }\n }\n\n handleMove(event, coordinates) {\n const {\n onMove\n } = this.props;\n event.preventDefault();\n onMove(coordinates);\n }\n\n handleEnd(event) {\n const {\n onEnd\n } = this.props;\n event.preventDefault();\n this.detach();\n onEnd();\n }\n\n handleCancel(event) {\n const {\n onCancel\n } = this.props;\n event.preventDefault();\n this.detach();\n onCancel();\n }\n\n detach() {\n this.listeners.removeAll();\n this.windowListeners.removeAll();\n }\n\n}\nKeyboardSensor.activators = [{\n eventName: 'onKeyDown',\n handler: (event, _ref, _ref2) => {\n let {\n keyboardCodes = defaultKeyboardCodes,\n onActivation\n } = _ref;\n let {\n active\n } = _ref2;\n const {\n code\n } = event.nativeEvent;\n\n if (keyboardCodes.start.includes(code)) {\n const activator = active.activatorNode.current;\n\n if (activator && event.target !== activator) {\n return false;\n }\n\n event.preventDefault();\n onActivation == null ? void 0 : onActivation({\n event: event.nativeEvent\n });\n return true;\n }\n\n return false;\n }\n}];\n\nfunction isDistanceConstraint(constraint) {\n return Boolean(constraint && 'distance' in constraint);\n}\n\nfunction isDelayConstraint(constraint) {\n return Boolean(constraint && 'delay' in constraint);\n}\n\nclass AbstractPointerSensor {\n constructor(props, events, listenerTarget) {\n var _getEventCoordinates;\n\n if (listenerTarget === void 0) {\n listenerTarget = getEventListenerTarget(props.event.target);\n }\n\n this.props = void 0;\n this.events = void 0;\n this.autoScrollEnabled = true;\n this.document = void 0;\n this.activated = false;\n this.initialCoordinates = void 0;\n this.timeoutId = null;\n this.listeners = void 0;\n this.documentListeners = void 0;\n this.windowListeners = void 0;\n this.props = props;\n this.events = events;\n const {\n event\n } = props;\n const {\n target\n } = event;\n this.props = props;\n this.events = events;\n this.document = getOwnerDocument(target);\n this.documentListeners = new Listeners(this.document);\n this.listeners = new Listeners(listenerTarget);\n this.windowListeners = new Listeners(getWindow(target));\n this.initialCoordinates = (_getEventCoordinates = getEventCoordinates(event)) != null ? _getEventCoordinates : defaultCoordinates;\n this.handleStart = this.handleStart.bind(this);\n this.handleMove = this.handleMove.bind(this);\n this.handleEnd = this.handleEnd.bind(this);\n this.handleCancel = this.handleCancel.bind(this);\n this.handleKeydown = this.handleKeydown.bind(this);\n this.removeTextSelection = this.removeTextSelection.bind(this);\n this.attach();\n }\n\n attach() {\n const {\n events,\n props: {\n options: {\n activationConstraint,\n bypassActivationConstraint\n }\n }\n } = this;\n this.listeners.add(events.move.name, this.handleMove, {\n passive: false\n });\n this.listeners.add(events.end.name, this.handleEnd);\n\n if (events.cancel) {\n this.listeners.add(events.cancel.name, this.handleCancel);\n }\n\n this.windowListeners.add(EventName.Resize, this.handleCancel);\n this.windowListeners.add(EventName.DragStart, preventDefault);\n this.windowListeners.add(EventName.VisibilityChange, this.handleCancel);\n this.windowListeners.add(EventName.ContextMenu, preventDefault);\n this.documentListeners.add(EventName.Keydown, this.handleKeydown);\n\n if (activationConstraint) {\n if (bypassActivationConstraint != null && bypassActivationConstraint({\n event: this.props.event,\n activeNode: this.props.activeNode,\n options: this.props.options\n })) {\n return this.handleStart();\n }\n\n if (isDelayConstraint(activationConstraint)) {\n this.timeoutId = setTimeout(this.handleStart, activationConstraint.delay);\n this.handlePending(activationConstraint);\n return;\n }\n\n if (isDistanceConstraint(activationConstraint)) {\n this.handlePending(activationConstraint);\n return;\n }\n }\n\n this.handleStart();\n }\n\n detach() {\n this.listeners.removeAll();\n this.windowListeners.removeAll(); // Wait until the next event loop before removing document listeners\n // This is necessary because we listen for `click` and `selection` events on the document\n\n setTimeout(this.documentListeners.removeAll, 50);\n\n if (this.timeoutId !== null) {\n clearTimeout(this.timeoutId);\n this.timeoutId = null;\n }\n }\n\n handlePending(constraint, offset) {\n const {\n active,\n onPending\n } = this.props;\n onPending(active, constraint, this.initialCoordinates, offset);\n }\n\n handleStart() {\n const {\n initialCoordinates\n } = this;\n const {\n onStart\n } = this.props;\n\n if (initialCoordinates) {\n this.activated = true; // Stop propagation of click events once activation constraints are met\n\n this.documentListeners.add(EventName.Click, stopPropagation, {\n capture: true\n }); // Remove any text selection from the document\n\n this.removeTextSelection(); // Prevent further text selection while dragging\n\n this.documentListeners.add(EventName.SelectionChange, this.removeTextSelection);\n onStart(initialCoordinates);\n }\n }\n\n handleMove(event) {\n var _getEventCoordinates2;\n\n const {\n activated,\n initialCoordinates,\n props\n } = this;\n const {\n onMove,\n options: {\n activationConstraint\n }\n } = props;\n\n if (!initialCoordinates) {\n return;\n }\n\n const coordinates = (_getEventCoordinates2 = getEventCoordinates(event)) != null ? _getEventCoordinates2 : defaultCoordinates;\n const delta = subtract(initialCoordinates, coordinates); // Constraint validation\n\n if (!activated && activationConstraint) {\n if (isDistanceConstraint(activationConstraint)) {\n if (activationConstraint.tolerance != null && hasExceededDistance(delta, activationConstraint.tolerance)) {\n return this.handleCancel();\n }\n\n if (hasExceededDistance(delta, activationConstraint.distance)) {\n return this.handleStart();\n }\n }\n\n if (isDelayConstraint(activationConstraint)) {\n if (hasExceededDistance(delta, activationConstraint.tolerance)) {\n return this.handleCancel();\n }\n }\n\n this.handlePending(activationConstraint, delta);\n return;\n }\n\n if (event.cancelable) {\n event.preventDefault();\n }\n\n onMove(coordinates);\n }\n\n handleEnd() {\n const {\n onAbort,\n onEnd\n } = this.props;\n this.detach();\n\n if (!this.activated) {\n onAbort(this.props.active);\n }\n\n onEnd();\n }\n\n handleCancel() {\n const {\n onAbort,\n onCancel\n } = this.props;\n this.detach();\n\n if (!this.activated) {\n onAbort(this.props.active);\n }\n\n onCancel();\n }\n\n handleKeydown(event) {\n if (event.code === KeyboardCode.Esc) {\n this.handleCancel();\n }\n }\n\n removeTextSelection() {\n var _this$document$getSel;\n\n (_this$document$getSel = this.document.getSelection()) == null ? void 0 : _this$document$getSel.removeAllRanges();\n }\n\n}\n\nconst events = {\n cancel: {\n name: 'pointercancel'\n },\n move: {\n name: 'pointermove'\n },\n end: {\n name: 'pointerup'\n }\n};\nclass PointerSensor extends AbstractPointerSensor {\n constructor(props) {\n const {\n event\n } = props; // Pointer events stop firing if the target is unmounted while dragging\n // Therefore we attach listeners to the owner document instead\n\n const listenerTarget = getOwnerDocument(event.target);\n super(props, events, listenerTarget);\n }\n\n}\nPointerSensor.activators = [{\n eventName: 'onPointerDown',\n handler: (_ref, _ref2) => {\n let {\n nativeEvent: event\n } = _ref;\n let {\n onActivation\n } = _ref2;\n\n if (!event.isPrimary || event.button !== 0) {\n return false;\n }\n\n onActivation == null ? void 0 : onActivation({\n event\n });\n return true;\n }\n}];\n\nconst events$1 = {\n move: {\n name: 'mousemove'\n },\n end: {\n name: 'mouseup'\n }\n};\nvar MouseButton;\n\n(function (MouseButton) {\n MouseButton[MouseButton[\"RightClick\"] = 2] = \"RightClick\";\n})(MouseButton || (MouseButton = {}));\n\nclass MouseSensor extends AbstractPointerSensor {\n constructor(props) {\n super(props, events$1, getOwnerDocument(props.event.target));\n }\n\n}\nMouseSensor.activators = [{\n eventName: 'onMouseDown',\n handler: (_ref, _ref2) => {\n let {\n nativeEvent: event\n } = _ref;\n let {\n onActivation\n } = _ref2;\n\n if (event.button === MouseButton.RightClick) {\n return false;\n }\n\n onActivation == null ? void 0 : onActivation({\n event\n });\n return true;\n }\n}];\n\nconst events$2 = {\n cancel: {\n name: 'touchcancel'\n },\n move: {\n name: 'touchmove'\n },\n end: {\n name: 'touchend'\n }\n};\nclass TouchSensor extends AbstractPointerSensor {\n constructor(props) {\n super(props, events$2);\n }\n\n static setup() {\n // Adding a non-capture and non-passive `touchmove` listener in order\n // to force `event.preventDefault()` calls to work in dynamically added\n // touchmove event handlers. This is required for iOS Safari.\n window.addEventListener(events$2.move.name, noop, {\n capture: false,\n passive: false\n });\n return function teardown() {\n window.removeEventListener(events$2.move.name, noop);\n }; // We create a new handler because the teardown function of another sensor\n // could remove our event listener if we use a referentially equal listener.\n\n function noop() {}\n }\n\n}\nTouchSensor.activators = [{\n eventName: 'onTouchStart',\n handler: (_ref, _ref2) => {\n let {\n nativeEvent: event\n } = _ref;\n let {\n onActivation\n } = _ref2;\n const {\n touches\n } = event;\n\n if (touches.length > 1) {\n return false;\n }\n\n onActivation == null ? void 0 : onActivation({\n event\n });\n return true;\n }\n}];\n\nvar AutoScrollActivator;\n\n(function (AutoScrollActivator) {\n AutoScrollActivator[AutoScrollActivator[\"Pointer\"] = 0] = \"Pointer\";\n AutoScrollActivator[AutoScrollActivator[\"DraggableRect\"] = 1] = \"DraggableRect\";\n})(AutoScrollActivator || (AutoScrollActivator = {}));\n\nvar TraversalOrder;\n\n(function (TraversalOrder) {\n TraversalOrder[TraversalOrder[\"TreeOrder\"] = 0] = \"TreeOrder\";\n TraversalOrder[TraversalOrder[\"ReversedTreeOrder\"] = 1] = \"ReversedTreeOrder\";\n})(TraversalOrder || (TraversalOrder = {}));\n\nfunction useAutoScroller(_ref) {\n let {\n acceleration,\n activator = AutoScrollActivator.Pointer,\n canScroll,\n draggingRect,\n enabled,\n interval = 5,\n order = TraversalOrder.TreeOrder,\n pointerCoordinates,\n scrollableAncestors,\n scrollableAncestorRects,\n delta,\n threshold\n } = _ref;\n const scrollIntent = useScrollIntent({\n delta,\n disabled: !enabled\n });\n const [setAutoScrollInterval, clearAutoScrollInterval] = useInterval();\n const scrollSpeed = useRef({\n x: 0,\n y: 0\n });\n const scrollDirection = useRef({\n x: 0,\n y: 0\n });\n const rect = useMemo(() => {\n switch (activator) {\n case AutoScrollActivator.Pointer:\n return pointerCoordinates ? {\n top: pointerCoordinates.y,\n bottom: pointerCoordinates.y,\n left: pointerCoordinates.x,\n right: pointerCoordinates.x\n } : null;\n\n case AutoScrollActivator.DraggableRect:\n return draggingRect;\n }\n }, [activator, draggingRect, pointerCoordinates]);\n const scrollContainerRef = useRef(null);\n const autoScroll = useCallback(() => {\n const scrollContainer = scrollContainerRef.current;\n\n if (!scrollContainer) {\n return;\n }\n\n const scrollLeft = scrollSpeed.current.x * scrollDirection.current.x;\n const scrollTop = scrollSpeed.current.y * scrollDirection.current.y;\n scrollContainer.scrollBy(scrollLeft, scrollTop);\n }, []);\n const sortedScrollableAncestors = useMemo(() => order === TraversalOrder.TreeOrder ? [...scrollableAncestors].reverse() : scrollableAncestors, [order, scrollableAncestors]);\n useEffect(() => {\n if (!enabled || !scrollableAncestors.length || !rect) {\n clearAutoScrollInterval();\n return;\n }\n\n for (const scrollContainer of sortedScrollableAncestors) {\n if ((canScroll == null ? void 0 : canScroll(scrollContainer)) === false) {\n continue;\n }\n\n const index = scrollableAncestors.indexOf(scrollContainer);\n const scrollContainerRect = scrollableAncestorRects[index];\n\n if (!scrollContainerRect) {\n continue;\n }\n\n const {\n direction,\n speed\n } = getScrollDirectionAndSpeed(scrollContainer, scrollContainerRect, rect, acceleration, threshold);\n\n for (const axis of ['x', 'y']) {\n if (!scrollIntent[axis][direction[axis]]) {\n speed[axis] = 0;\n direction[axis] = 0;\n }\n }\n\n if (speed.x > 0 || speed.y > 0) {\n clearAutoScrollInterval();\n scrollContainerRef.current = scrollContainer;\n setAutoScrollInterval(autoScroll, interval);\n scrollSpeed.current = speed;\n scrollDirection.current = direction;\n return;\n }\n }\n\n scrollSpeed.current = {\n x: 0,\n y: 0\n };\n scrollDirection.current = {\n x: 0,\n y: 0\n };\n clearAutoScrollInterval();\n }, // eslint-disable-next-line react-hooks/exhaustive-deps\n [acceleration, autoScroll, canScroll, clearAutoScrollInterval, enabled, interval, // eslint-disable-next-line react-hooks/exhaustive-deps\n JSON.stringify(rect), // eslint-disable-next-line react-hooks/exhaustive-deps\n JSON.stringify(scrollIntent), setAutoScrollInterval, scrollableAncestors, sortedScrollableAncestors, scrollableAncestorRects, // eslint-disable-next-line react-hooks/exhaustive-deps\n JSON.stringify(threshold)]);\n}\nconst defaultScrollIntent = {\n x: {\n [Direction.Backward]: false,\n [Direction.Forward]: false\n },\n y: {\n [Direction.Backward]: false,\n [Direction.Forward]: false\n }\n};\n\nfunction useScrollIntent(_ref2) {\n let {\n delta,\n disabled\n } = _ref2;\n const previousDelta = usePrevious(delta);\n return useLazyMemo(previousIntent => {\n if (disabled || !previousDelta || !previousIntent) {\n // Reset scroll intent tracking when auto-scrolling is disabled\n return defaultScrollIntent;\n }\n\n const direction = {\n x: Math.sign(delta.x - previousDelta.x),\n y: Math.sign(delta.y - previousDelta.y)\n }; // Keep track of the user intent to scroll in each direction for both axis\n\n return {\n x: {\n [Direction.Backward]: previousIntent.x[Direction.Backward] || direction.x === -1,\n [Direction.Forward]: previousIntent.x[Direction.Forward] || direction.x === 1\n },\n y: {\n [Direction.Backward]: previousIntent.y[Direction.Backward] || direction.y === -1,\n [Direction.Forward]: previousIntent.y[Direction.Forward] || direction.y === 1\n }\n };\n }, [disabled, delta, previousDelta]);\n}\n\nfunction useCachedNode(draggableNodes, id) {\n const draggableNode = id != null ? draggableNodes.get(id) : undefined;\n const node = draggableNode ? draggableNode.node.current : null;\n return useLazyMemo(cachedNode => {\n var _ref;\n\n if (id == null) {\n return null;\n } // In some cases, the draggable node can unmount while dragging\n // This is the case for virtualized lists. In those situations,\n // we fall back to the last known value for that node.\n\n\n return (_ref = node != null ? node : cachedNode) != null ? _ref : null;\n }, [node, id]);\n}\n\nfunction useCombineActivators(sensors, getSyntheticHandler) {\n return useMemo(() => sensors.reduce((accumulator, sensor) => {\n const {\n sensor: Sensor\n } = sensor;\n const sensorActivators = Sensor.activators.map(activator => ({\n eventName: activator.eventName,\n handler: getSyntheticHandler(activator.handler, sensor)\n }));\n return [...accumulator, ...sensorActivators];\n }, []), [sensors, getSyntheticHandler]);\n}\n\nvar MeasuringStrategy;\n\n(function (MeasuringStrategy) {\n MeasuringStrategy[MeasuringStrategy[\"Always\"] = 0] = \"Always\";\n MeasuringStrategy[MeasuringStrategy[\"BeforeDragging\"] = 1] = \"BeforeDragging\";\n MeasuringStrategy[MeasuringStrategy[\"WhileDragging\"] = 2] = \"WhileDragging\";\n})(MeasuringStrategy || (MeasuringStrategy = {}));\n\nvar MeasuringFrequency;\n\n(function (MeasuringFrequency) {\n MeasuringFrequency[\"Optimized\"] = \"optimized\";\n})(MeasuringFrequency || (MeasuringFrequency = {}));\n\nconst defaultValue = /*#__PURE__*/new Map();\nfunction useDroppableMeasuring(containers, _ref) {\n let {\n dragging,\n dependencies,\n config\n } = _ref;\n const [queue, setQueue] = useState(null);\n const {\n frequency,\n measure,\n strategy\n } = config;\n const containersRef = useRef(containers);\n const disabled = isDisabled();\n const disabledRef = useLatestValue(disabled);\n const measureDroppableContainers = useCallback(function (ids) {\n if (ids === void 0) {\n ids = [];\n }\n\n if (disabledRef.current) {\n return;\n }\n\n setQueue(value => {\n if (value === null) {\n return ids;\n }\n\n return value.concat(ids.filter(id => !value.includes(id)));\n });\n }, [disabledRef]);\n const timeoutId = useRef(null);\n const droppableRects = useLazyMemo(previousValue => {\n if (disabled && !dragging) {\n return defaultValue;\n }\n\n if (!previousValue || previousValue === defaultValue || containersRef.current !== containers || queue != null) {\n const map = new Map();\n\n for (let container of containers) {\n if (!container) {\n continue;\n }\n\n if (queue && queue.length > 0 && !queue.includes(container.id) && container.rect.current) {\n // This container does not need to be re-measured\n map.set(container.id, container.rect.current);\n continue;\n }\n\n const node = container.node.current;\n const rect = node ? new Rect(measure(node), node) : null;\n container.rect.current = rect;\n\n if (rect) {\n map.set(container.id, rect);\n }\n }\n\n return map;\n }\n\n return previousValue;\n }, [containers, queue, dragging, disabled, measure]);\n useEffect(() => {\n containersRef.current = containers;\n }, [containers]);\n useEffect(() => {\n if (disabled) {\n return;\n }\n\n measureDroppableContainers();\n }, // eslint-disable-next-line react-hooks/exhaustive-deps\n [dragging, disabled]);\n useEffect(() => {\n if (queue && queue.length > 0) {\n setQueue(null);\n }\n }, //eslint-disable-next-line react-hooks/exhaustive-deps\n [JSON.stringify(queue)]);\n useEffect(() => {\n if (disabled || typeof frequency !== 'number' || timeoutId.current !== null) {\n return;\n }\n\n timeoutId.current = setTimeout(() => {\n measureDroppableContainers();\n timeoutId.current = null;\n }, frequency);\n }, // eslint-disable-next-line react-hooks/exhaustive-deps\n [frequency, disabled, measureDroppableContainers, ...dependencies]);\n return {\n droppableRects,\n measureDroppableContainers,\n measuringScheduled: queue != null\n };\n\n function isDisabled() {\n switch (strategy) {\n case MeasuringStrategy.Always:\n return false;\n\n case MeasuringStrategy.BeforeDragging:\n return dragging;\n\n default:\n return !dragging;\n }\n }\n}\n\nfunction useInitialValue(value, computeFn) {\n return useLazyMemo(previousValue => {\n if (!value) {\n return null;\n }\n\n if (previousValue) {\n return previousValue;\n }\n\n return typeof computeFn === 'function' ? computeFn(value) : value;\n }, [computeFn, value]);\n}\n\nfunction useInitialRect(node, measure) {\n return useInitialValue(node, measure);\n}\n\n/**\r\n * Returns a new MutationObserver instance.\r\n * If `MutationObserver` is undefined in the execution environment, returns `undefined`.\r\n */\n\nfunction useMutationObserver(_ref) {\n let {\n callback,\n disabled\n } = _ref;\n const handleMutations = useEvent(callback);\n const mutationObserver = useMemo(() => {\n if (disabled || typeof window === 'undefined' || typeof window.MutationObserver === 'undefined') {\n return undefined;\n }\n\n const {\n MutationObserver\n } = window;\n return new MutationObserver(handleMutations);\n }, [handleMutations, disabled]);\n useEffect(() => {\n return () => mutationObserver == null ? void 0 : mutationObserver.disconnect();\n }, [mutationObserver]);\n return mutationObserver;\n}\n\n/**\r\n * Returns a new ResizeObserver instance bound to the `onResize` callback.\r\n * If `ResizeObserver` is undefined in the execution environment, returns `undefined`.\r\n */\n\nfunction useResizeObserver(_ref) {\n let {\n callback,\n disabled\n } = _ref;\n const handleResize = useEvent(callback);\n const resizeObserver = useMemo(() => {\n if (disabled || typeof window === 'undefined' || typeof window.ResizeObserver === 'undefined') {\n return undefined;\n }\n\n const {\n ResizeObserver\n } = window;\n return new ResizeObserver(handleResize);\n }, // eslint-disable-next-line react-hooks/exhaustive-deps\n [disabled]);\n useEffect(() => {\n return () => resizeObserver == null ? void 0 : resizeObserver.disconnect();\n }, [resizeObserver]);\n return resizeObserver;\n}\n\nfunction defaultMeasure(element) {\n return new Rect(getClientRect(element), element);\n}\n\nfunction useRect(element, measure, fallbackRect) {\n if (measure === void 0) {\n measure = defaultMeasure;\n }\n\n const [rect, setRect] = useState(null);\n\n function measureRect() {\n setRect(currentRect => {\n if (!element) {\n return null;\n }\n\n if (element.isConnected === false) {\n var _ref;\n\n // Fall back to last rect we measured if the element is\n // no longer connected to the DOM.\n return (_ref = currentRect != null ? currentRect : fallbackRect) != null ? _ref : null;\n }\n\n const newRect = measure(element);\n\n if (JSON.stringify(currentRect) === JSON.stringify(newRect)) {\n return currentRect;\n }\n\n return newRect;\n });\n }\n\n const mutationObserver = useMutationObserver({\n callback(records) {\n if (!element) {\n return;\n }\n\n for (const record of records) {\n const {\n type,\n target\n } = record;\n\n if (type === 'childList' && target instanceof HTMLElement && target.contains(element)) {\n measureRect();\n break;\n }\n }\n }\n\n });\n const resizeObserver = useResizeObserver({\n callback: measureRect\n });\n useIsomorphicLayoutEffect(() => {\n measureRect();\n\n if (element) {\n resizeObserver == null ? void 0 : resizeObserver.observe(element);\n mutationObserver == null ? void 0 : mutationObserver.observe(document.body, {\n childList: true,\n subtree: true\n });\n } else {\n resizeObserver == null ? void 0 : resizeObserver.disconnect();\n mutationObserver == null ? void 0 : mutationObserver.disconnect();\n }\n }, [element]);\n return rect;\n}\n\nfunction useRectDelta(rect) {\n const initialRect = useInitialValue(rect);\n return getRectDelta(rect, initialRect);\n}\n\nconst defaultValue$1 = [];\nfunction useScrollableAncestors(node) {\n const previousNode = useRef(node);\n const ancestors = useLazyMemo(previousValue => {\n if (!node) {\n return defaultValue$1;\n }\n\n if (previousValue && previousValue !== defaultValue$1 && node && previousNode.current && node.parentNode === previousNode.current.parentNode) {\n return previousValue;\n }\n\n return getScrollableAncestors(node);\n }, [node]);\n useEffect(() => {\n previousNode.current = node;\n }, [node]);\n return ancestors;\n}\n\nfunction useScrollOffsets(elements) {\n const [scrollCoordinates, setScrollCoordinates] = useState(null);\n const prevElements = useRef(elements); // To-do: Throttle the handleScroll callback\n\n const handleScroll = useCallback(event => {\n const scrollingElement = getScrollableElement(event.target);\n\n if (!scrollingElement) {\n return;\n }\n\n setScrollCoordinates(scrollCoordinates => {\n if (!scrollCoordinates) {\n return null;\n }\n\n scrollCoordinates.set(scrollingElement, getScrollCoordinates(scrollingElement));\n return new Map(scrollCoordinates);\n });\n }, []);\n useEffect(() => {\n const previousElements = prevElements.current;\n\n if (elements !== previousElements) {\n cleanup(previousElements);\n const entries = elements.map(element => {\n const scrollableElement = getScrollableElement(element);\n\n if (scrollableElement) {\n scrollableElement.addEventListener('scroll', handleScroll, {\n passive: true\n });\n return [scrollableElement, getScrollCoordinates(scrollableElement)];\n }\n\n return null;\n }).filter(entry => entry != null);\n setScrollCoordinates(entries.length ? new Map(entries) : null);\n prevElements.current = elements;\n }\n\n return () => {\n cleanup(elements);\n cleanup(previousElements);\n };\n\n function cleanup(elements) {\n elements.forEach(element => {\n const scrollableElement = getScrollableElement(element);\n scrollableElement == null ? void 0 : scrollableElement.removeEventListener('scroll', handleScroll);\n });\n }\n }, [handleScroll, elements]);\n return useMemo(() => {\n if (elements.length) {\n return scrollCoordinates ? Array.from(scrollCoordinates.values()).reduce((acc, coordinates) => add(acc, coordinates), defaultCoordinates) : getScrollOffsets(elements);\n }\n\n return defaultCoordinates;\n }, [elements, scrollCoordinates]);\n}\n\nfunction useScrollOffsetsDelta(scrollOffsets, dependencies) {\n if (dependencies === void 0) {\n dependencies = [];\n }\n\n const initialScrollOffsets = useRef(null);\n useEffect(() => {\n initialScrollOffsets.current = null;\n }, // eslint-disable-next-line react-hooks/exhaustive-deps\n dependencies);\n useEffect(() => {\n const hasScrollOffsets = scrollOffsets !== defaultCoordinates;\n\n if (hasScrollOffsets && !initialScrollOffsets.current) {\n initialScrollOffsets.current = scrollOffsets;\n }\n\n if (!hasScrollOffsets && initialScrollOffsets.current) {\n initialScrollOffsets.current = null;\n }\n }, [scrollOffsets]);\n return initialScrollOffsets.current ? subtract(scrollOffsets, initialScrollOffsets.current) : defaultCoordinates;\n}\n\nfunction useSensorSetup(sensors) {\n useEffect(() => {\n if (!canUseDOM) {\n return;\n }\n\n const teardownFns = sensors.map(_ref => {\n let {\n sensor\n } = _ref;\n return sensor.setup == null ? void 0 : sensor.setup();\n });\n return () => {\n for (const teardown of teardownFns) {\n teardown == null ? void 0 : teardown();\n }\n };\n }, // TO-DO: Sensors length could theoretically change which would not be a valid dependency\n // eslint-disable-next-line react-hooks/exhaustive-deps\n sensors.map(_ref2 => {\n let {\n sensor\n } = _ref2;\n return sensor;\n }));\n}\n\nfunction useSyntheticListeners(listeners, id) {\n return useMemo(() => {\n return listeners.reduce((acc, _ref) => {\n let {\n eventName,\n handler\n } = _ref;\n\n acc[eventName] = event => {\n handler(event, id);\n };\n\n return acc;\n }, {});\n }, [listeners, id]);\n}\n\nfunction useWindowRect(element) {\n return useMemo(() => element ? getWindowClientRect(element) : null, [element]);\n}\n\nconst defaultValue$2 = [];\nfunction useRects(elements, measure) {\n if (measure === void 0) {\n measure = getClientRect;\n }\n\n const [firstElement] = elements;\n const windowRect = useWindowRect(firstElement ? getWindow(firstElement) : null);\n const [rects, setRects] = useState(defaultValue$2);\n\n function measureRects() {\n setRects(() => {\n if (!elements.length) {\n return defaultValue$2;\n }\n\n return elements.map(element => isDocumentScrollingElement(element) ? windowRect : new Rect(measure(element), element));\n });\n }\n\n const resizeObserver = useResizeObserver({\n callback: measureRects\n });\n useIsomorphicLayoutEffect(() => {\n resizeObserver == null ? void 0 : resizeObserver.disconnect();\n measureRects();\n elements.forEach(element => resizeObserver == null ? void 0 : resizeObserver.observe(element));\n }, [elements]);\n return rects;\n}\n\nfunction getMeasurableNode(node) {\n if (!node) {\n return null;\n }\n\n if (node.children.length > 1) {\n return node;\n }\n\n const firstChild = node.children[0];\n return isHTMLElement(firstChild) ? firstChild : node;\n}\n\nfunction useDragOverlayMeasuring(_ref) {\n let {\n measure\n } = _ref;\n const [rect, setRect] = useState(null);\n const handleResize = useCallback(entries => {\n for (const {\n target\n } of entries) {\n if (isHTMLElement(target)) {\n setRect(rect => {\n const newRect = measure(target);\n return rect ? { ...rect,\n width: newRect.width,\n height: newRect.height\n } : newRect;\n });\n break;\n }\n }\n }, [measure]);\n const resizeObserver = useResizeObserver({\n callback: handleResize\n });\n const handleNodeChange = useCallback(element => {\n const node = getMeasurableNode(element);\n resizeObserver == null ? void 0 : resizeObserver.disconnect();\n\n if (node) {\n resizeObserver == null ? void 0 : resizeObserver.observe(node);\n }\n\n setRect(node ? measure(node) : null);\n }, [measure, resizeObserver]);\n const [nodeRef, setRef] = useNodeRef(handleNodeChange);\n return useMemo(() => ({\n nodeRef,\n rect,\n setRef\n }), [rect, nodeRef, setRef]);\n}\n\nconst defaultSensors = [{\n sensor: PointerSensor,\n options: {}\n}, {\n sensor: KeyboardSensor,\n options: {}\n}];\nconst defaultData = {\n current: {}\n};\nconst defaultMeasuringConfiguration = {\n draggable: {\n measure: getTransformAgnosticClientRect\n },\n droppable: {\n measure: getTransformAgnosticClientRect,\n strategy: MeasuringStrategy.WhileDragging,\n frequency: MeasuringFrequency.Optimized\n },\n dragOverlay: {\n measure: getClientRect\n }\n};\n\nclass DroppableContainersMap extends Map {\n get(id) {\n var _super$get;\n\n return id != null ? (_super$get = super.get(id)) != null ? _super$get : undefined : undefined;\n }\n\n toArray() {\n return Array.from(this.values());\n }\n\n getEnabled() {\n return this.toArray().filter(_ref => {\n let {\n disabled\n } = _ref;\n return !disabled;\n });\n }\n\n getNodeFor(id) {\n var _this$get$node$curren, _this$get;\n\n return (_this$get$node$curren = (_this$get = this.get(id)) == null ? void 0 : _this$get.node.current) != null ? _this$get$node$curren : undefined;\n }\n\n}\n\nconst defaultPublicContext = {\n activatorEvent: null,\n active: null,\n activeNode: null,\n activeNodeRect: null,\n collisions: null,\n containerNodeRect: null,\n draggableNodes: /*#__PURE__*/new Map(),\n droppableRects: /*#__PURE__*/new Map(),\n droppableContainers: /*#__PURE__*/new DroppableContainersMap(),\n over: null,\n dragOverlay: {\n nodeRef: {\n current: null\n },\n rect: null,\n setRef: noop\n },\n scrollableAncestors: [],\n scrollableAncestorRects: [],\n measuringConfiguration: defaultMeasuringConfiguration,\n measureDroppableContainers: noop,\n windowRect: null,\n measuringScheduled: false\n};\nconst defaultInternalContext = {\n activatorEvent: null,\n activators: [],\n active: null,\n activeNodeRect: null,\n ariaDescribedById: {\n draggable: ''\n },\n dispatch: noop,\n draggableNodes: /*#__PURE__*/new Map(),\n over: null,\n measureDroppableContainers: noop\n};\nconst InternalContext = /*#__PURE__*/createContext(defaultInternalContext);\nconst PublicContext = /*#__PURE__*/createContext(defaultPublicContext);\n\nfunction getInitialState() {\n return {\n draggable: {\n active: null,\n initialCoordinates: {\n x: 0,\n y: 0\n },\n nodes: new Map(),\n translate: {\n x: 0,\n y: 0\n }\n },\n droppable: {\n containers: new DroppableContainersMap()\n }\n };\n}\nfunction reducer(state, action) {\n switch (action.type) {\n case Action.DragStart:\n return { ...state,\n draggable: { ...state.draggable,\n initialCoordinates: action.initialCoordinates,\n active: action.active\n }\n };\n\n case Action.DragMove:\n if (state.draggable.active == null) {\n return state;\n }\n\n return { ...state,\n draggable: { ...state.draggable,\n translate: {\n x: action.coordinates.x - state.draggable.initialCoordinates.x,\n y: action.coordinates.y - state.draggable.initialCoordinates.y\n }\n }\n };\n\n case Action.DragEnd:\n case Action.DragCancel:\n return { ...state,\n draggable: { ...state.draggable,\n active: null,\n initialCoordinates: {\n x: 0,\n y: 0\n },\n translate: {\n x: 0,\n y: 0\n }\n }\n };\n\n case Action.RegisterDroppable:\n {\n const {\n element\n } = action;\n const {\n id\n } = element;\n const containers = new DroppableContainersMap(state.droppable.containers);\n containers.set(id, element);\n return { ...state,\n droppable: { ...state.droppable,\n containers\n }\n };\n }\n\n case Action.SetDroppableDisabled:\n {\n const {\n id,\n key,\n disabled\n } = action;\n const element = state.droppable.containers.get(id);\n\n if (!element || key !== element.key) {\n return state;\n }\n\n const containers = new DroppableContainersMap(state.droppable.containers);\n containers.set(id, { ...element,\n disabled\n });\n return { ...state,\n droppable: { ...state.droppable,\n containers\n }\n };\n }\n\n case Action.UnregisterDroppable:\n {\n const {\n id,\n key\n } = action;\n const element = state.droppable.containers.get(id);\n\n if (!element || key !== element.key) {\n return state;\n }\n\n const containers = new DroppableContainersMap(state.droppable.containers);\n containers.delete(id);\n return { ...state,\n droppable: { ...state.droppable,\n containers\n }\n };\n }\n\n default:\n {\n return state;\n }\n }\n}\n\nfunction RestoreFocus(_ref) {\n let {\n disabled\n } = _ref;\n const {\n active,\n activatorEvent,\n draggableNodes\n } = useContext(InternalContext);\n const previousActivatorEvent = usePrevious(activatorEvent);\n const previousActiveId = usePrevious(active == null ? void 0 : active.id); // Restore keyboard focus on the activator node\n\n useEffect(() => {\n if (disabled) {\n return;\n }\n\n if (!activatorEvent && previousActivatorEvent && previousActiveId != null) {\n if (!isKeyboardEvent(previousActivatorEvent)) {\n return;\n }\n\n if (document.activeElement === previousActivatorEvent.target) {\n // No need to restore focus\n return;\n }\n\n const draggableNode = draggableNodes.get(previousActiveId);\n\n if (!draggableNode) {\n return;\n }\n\n const {\n activatorNode,\n node\n } = draggableNode;\n\n if (!activatorNode.current && !node.current) {\n return;\n }\n\n requestAnimationFrame(() => {\n for (const element of [activatorNode.current, node.current]) {\n if (!element) {\n continue;\n }\n\n const focusableNode = findFirstFocusableNode(element);\n\n if (focusableNode) {\n focusableNode.focus();\n break;\n }\n }\n });\n }\n }, [activatorEvent, disabled, draggableNodes, previousActiveId, previousActivatorEvent]);\n return null;\n}\n\nfunction applyModifiers(modifiers, _ref) {\n let {\n transform,\n ...args\n } = _ref;\n return modifiers != null && modifiers.length ? modifiers.reduce((accumulator, modifier) => {\n return modifier({\n transform: accumulator,\n ...args\n });\n }, transform) : transform;\n}\n\nfunction useMeasuringConfiguration(config) {\n return useMemo(() => ({\n draggable: { ...defaultMeasuringConfiguration.draggable,\n ...(config == null ? void 0 : config.draggable)\n },\n droppable: { ...defaultMeasuringConfiguration.droppable,\n ...(config == null ? void 0 : config.droppable)\n },\n dragOverlay: { ...defaultMeasuringConfiguration.dragOverlay,\n ...(config == null ? void 0 : config.dragOverlay)\n }\n }), // eslint-disable-next-line react-hooks/exhaustive-deps\n [config == null ? void 0 : config.draggable, config == null ? void 0 : config.droppable, config == null ? void 0 : config.dragOverlay]);\n}\n\nfunction useLayoutShiftScrollCompensation(_ref) {\n let {\n activeNode,\n measure,\n initialRect,\n config = true\n } = _ref;\n const initialized = useRef(false);\n const {\n x,\n y\n } = typeof config === 'boolean' ? {\n x: config,\n y: config\n } : config;\n useIsomorphicLayoutEffect(() => {\n const disabled = !x && !y;\n\n if (disabled || !activeNode) {\n initialized.current = false;\n return;\n }\n\n if (initialized.current || !initialRect) {\n // Return early if layout shift scroll compensation was already attempted\n // or if there is no initialRect to compare to.\n return;\n } // Get the most up to date node ref for the active draggable\n\n\n const node = activeNode == null ? void 0 : activeNode.node.current;\n\n if (!node || node.isConnected === false) {\n // Return early if there is no attached node ref or if the node is\n // disconnected from the document.\n return;\n }\n\n const rect = measure(node);\n const rectDelta = getRectDelta(rect, initialRect);\n\n if (!x) {\n rectDelta.x = 0;\n }\n\n if (!y) {\n rectDelta.y = 0;\n } // Only perform layout shift scroll compensation once\n\n\n initialized.current = true;\n\n if (Math.abs(rectDelta.x) > 0 || Math.abs(rectDelta.y) > 0) {\n const firstScrollableAncestor = getFirstScrollableAncestor(node);\n\n if (firstScrollableAncestor) {\n firstScrollableAncestor.scrollBy({\n top: rectDelta.y,\n left: rectDelta.x\n });\n }\n }\n }, [activeNode, x, y, initialRect, measure]);\n}\n\nconst ActiveDraggableContext = /*#__PURE__*/createContext({ ...defaultCoordinates,\n scaleX: 1,\n scaleY: 1\n});\nvar Status;\n\n(function (Status) {\n Status[Status[\"Uninitialized\"] = 0] = \"Uninitialized\";\n Status[Status[\"Initializing\"] = 1] = \"Initializing\";\n Status[Status[\"Initialized\"] = 2] = \"Initialized\";\n})(Status || (Status = {}));\n\nconst DndContext = /*#__PURE__*/memo(function DndContext(_ref) {\n var _sensorContext$curren, _dragOverlay$nodeRef$, _dragOverlay$rect, _over$rect;\n\n let {\n id,\n accessibility,\n autoScroll = true,\n children,\n sensors = defaultSensors,\n collisionDetection = rectIntersection,\n measuring,\n modifiers,\n ...props\n } = _ref;\n const store = useReducer(reducer, undefined, getInitialState);\n const [state, dispatch] = store;\n const [dispatchMonitorEvent, registerMonitorListener] = useDndMonitorProvider();\n const [status, setStatus] = useState(Status.Uninitialized);\n const isInitialized = status === Status.Initialized;\n const {\n draggable: {\n active: activeId,\n nodes: draggableNodes,\n translate\n },\n droppable: {\n containers: droppableContainers\n }\n } = state;\n const node = activeId != null ? draggableNodes.get(activeId) : null;\n const activeRects = useRef({\n initial: null,\n translated: null\n });\n const active = useMemo(() => {\n var _node$data;\n\n return activeId != null ? {\n id: activeId,\n // It's possible for the active node to unmount while dragging\n data: (_node$data = node == null ? void 0 : node.data) != null ? _node$data : defaultData,\n rect: activeRects\n } : null;\n }, [activeId, node]);\n const activeRef = useRef(null);\n const [activeSensor, setActiveSensor] = useState(null);\n const [activatorEvent, setActivatorEvent] = useState(null);\n const latestProps = useLatestValue(props, Object.values(props));\n const draggableDescribedById = useUniqueId(\"DndDescribedBy\", id);\n const enabledDroppableContainers = useMemo(() => droppableContainers.getEnabled(), [droppableContainers]);\n const measuringConfiguration = useMeasuringConfiguration(measuring);\n const {\n droppableRects,\n measureDroppableContainers,\n measuringScheduled\n } = useDroppableMeasuring(enabledDroppableContainers, {\n dragging: isInitialized,\n dependencies: [translate.x, translate.y],\n config: measuringConfiguration.droppable\n });\n const activeNode = useCachedNode(draggableNodes, activeId);\n const activationCoordinates = useMemo(() => activatorEvent ? getEventCoordinates(activatorEvent) : null, [activatorEvent]);\n const autoScrollOptions = getAutoScrollerOptions();\n const initialActiveNodeRect = useInitialRect(activeNode, measuringConfiguration.draggable.measure);\n useLayoutShiftScrollCompensation({\n activeNode: activeId != null ? draggableNodes.get(activeId) : null,\n config: autoScrollOptions.layoutShiftCompensation,\n initialRect: initialActiveNodeRect,\n measure: measuringConfiguration.draggable.measure\n });\n const activeNodeRect = useRect(activeNode, measuringConfiguration.draggable.measure, initialActiveNodeRect);\n const containerNodeRect = useRect(activeNode ? activeNode.parentElement : null);\n const sensorContext = useRef({\n activatorEvent: null,\n active: null,\n activeNode,\n collisionRect: null,\n collisions: null,\n droppableRects,\n draggableNodes,\n draggingNode: null,\n draggingNodeRect: null,\n droppableContainers,\n over: null,\n scrollableAncestors: [],\n scrollAdjustedTranslate: null\n });\n const overNode = droppableContainers.getNodeFor((_sensorContext$curren = sensorContext.current.over) == null ? void 0 : _sensorContext$curren.id);\n const dragOverlay = useDragOverlayMeasuring({\n measure: measuringConfiguration.dragOverlay.measure\n }); // Use the rect of the drag overlay if it is mounted\n\n const draggingNode = (_dragOverlay$nodeRef$ = dragOverlay.nodeRef.current) != null ? _dragOverlay$nodeRef$ : activeNode;\n const draggingNodeRect = isInitialized ? (_dragOverlay$rect = dragOverlay.rect) != null ? _dragOverlay$rect : activeNodeRect : null;\n const usesDragOverlay = Boolean(dragOverlay.nodeRef.current && dragOverlay.rect); // The delta between the previous and new position of the draggable node\n // is only relevant when there is no drag overlay\n\n const nodeRectDelta = useRectDelta(usesDragOverlay ? null : activeNodeRect); // Get the window rect of the dragging node\n\n const windowRect = useWindowRect(draggingNode ? getWindow(draggingNode) : null); // Get scrollable ancestors of the dragging node\n\n const scrollableAncestors = useScrollableAncestors(isInitialized ? overNode != null ? overNode : activeNode : null);\n const scrollableAncestorRects = useRects(scrollableAncestors); // Apply modifiers\n\n const modifiedTranslate = applyModifiers(modifiers, {\n transform: {\n x: translate.x - nodeRectDelta.x,\n y: translate.y - nodeRectDelta.y,\n scaleX: 1,\n scaleY: 1\n },\n activatorEvent,\n active,\n activeNodeRect,\n containerNodeRect,\n draggingNodeRect,\n over: sensorContext.current.over,\n overlayNodeRect: dragOverlay.rect,\n scrollableAncestors,\n scrollableAncestorRects,\n windowRect\n });\n const pointerCoordinates = activationCoordinates ? add(activationCoordinates, translate) : null;\n const scrollOffsets = useScrollOffsets(scrollableAncestors); // Represents the scroll delta since dragging was initiated\n\n const scrollAdjustment = useScrollOffsetsDelta(scrollOffsets); // Represents the scroll delta since the last time the active node rect was measured\n\n const activeNodeScrollDelta = useScrollOffsetsDelta(scrollOffsets, [activeNodeRect]);\n const scrollAdjustedTranslate = add(modifiedTranslate, scrollAdjustment);\n const collisionRect = draggingNodeRect ? getAdjustedRect(draggingNodeRect, modifiedTranslate) : null;\n const collisions = active && collisionRect ? collisionDetection({\n active,\n collisionRect,\n droppableRects,\n droppableContainers: enabledDroppableContainers,\n pointerCoordinates\n }) : null;\n const overId = getFirstCollision(collisions, 'id');\n const [over, setOver] = useState(null); // When there is no drag overlay used, we need to account for the\n // window scroll delta\n\n const appliedTranslate = usesDragOverlay ? modifiedTranslate : add(modifiedTranslate, activeNodeScrollDelta);\n const transform = adjustScale(appliedTranslate, (_over$rect = over == null ? void 0 : over.rect) != null ? _over$rect : null, activeNodeRect);\n const activeSensorRef = useRef(null);\n const instantiateSensor = useCallback((event, _ref2) => {\n let {\n sensor: Sensor,\n options\n } = _ref2;\n\n if (activeRef.current == null) {\n return;\n }\n\n const activeNode = draggableNodes.get(activeRef.current);\n\n if (!activeNode) {\n return;\n }\n\n const activatorEvent = event.nativeEvent;\n const sensorInstance = new Sensor({\n active: activeRef.current,\n activeNode,\n event: activatorEvent,\n options,\n // Sensors need to be instantiated with refs for arguments that change over time\n // otherwise they are frozen in time with the stale arguments\n context: sensorContext,\n\n onAbort(id) {\n const draggableNode = draggableNodes.get(id);\n\n if (!draggableNode) {\n return;\n }\n\n const {\n onDragAbort\n } = latestProps.current;\n const event = {\n id\n };\n onDragAbort == null ? void 0 : onDragAbort(event);\n dispatchMonitorEvent({\n type: 'onDragAbort',\n event\n });\n },\n\n onPending(id, constraint, initialCoordinates, offset) {\n const draggableNode = draggableNodes.get(id);\n\n if (!draggableNode) {\n return;\n }\n\n const {\n onDragPending\n } = latestProps.current;\n const event = {\n id,\n constraint,\n initialCoordinates,\n offset\n };\n onDragPending == null ? void 0 : onDragPending(event);\n dispatchMonitorEvent({\n type: 'onDragPending',\n event\n });\n },\n\n onStart(initialCoordinates) {\n const id = activeRef.current;\n\n if (id == null) {\n return;\n }\n\n const draggableNode = draggableNodes.get(id);\n\n if (!draggableNode) {\n return;\n }\n\n const {\n onDragStart\n } = latestProps.current;\n const event = {\n activatorEvent,\n active: {\n id,\n data: draggableNode.data,\n rect: activeRects\n }\n };\n unstable_batchedUpdates(() => {\n onDragStart == null ? void 0 : onDragStart(event);\n setStatus(Status.Initializing);\n dispatch({\n type: Action.DragStart,\n initialCoordinates,\n active: id\n });\n dispatchMonitorEvent({\n type: 'onDragStart',\n event\n });\n setActiveSensor(activeSensorRef.current);\n setActivatorEvent(activatorEvent);\n });\n },\n\n onMove(coordinates) {\n dispatch({\n type: Action.DragMove,\n coordinates\n });\n },\n\n onEnd: createHandler(Action.DragEnd),\n onCancel: createHandler(Action.DragCancel)\n });\n activeSensorRef.current = sensorInstance;\n\n function createHandler(type) {\n return async function handler() {\n const {\n active,\n collisions,\n over,\n scrollAdjustedTranslate\n } = sensorContext.current;\n let event = null;\n\n if (active && scrollAdjustedTranslate) {\n const {\n cancelDrop\n } = latestProps.current;\n event = {\n activatorEvent,\n active: active,\n collisions,\n delta: scrollAdjustedTranslate,\n over\n };\n\n if (type === Action.DragEnd && typeof cancelDrop === 'function') {\n const shouldCancel = await Promise.resolve(cancelDrop(event));\n\n if (shouldCancel) {\n type = Action.DragCancel;\n }\n }\n }\n\n activeRef.current = null;\n unstable_batchedUpdates(() => {\n dispatch({\n type\n });\n setStatus(Status.Uninitialized);\n setOver(null);\n setActiveSensor(null);\n setActivatorEvent(null);\n activeSensorRef.current = null;\n const eventName = type === Action.DragEnd ? 'onDragEnd' : 'onDragCancel';\n\n if (event) {\n const handler = latestProps.current[eventName];\n handler == null ? void 0 : handler(event);\n dispatchMonitorEvent({\n type: eventName,\n event\n });\n }\n });\n };\n }\n }, // eslint-disable-next-line react-hooks/exhaustive-deps\n [draggableNodes]);\n const bindActivatorToSensorInstantiator = useCallback((handler, sensor) => {\n return (event, active) => {\n const nativeEvent = event.nativeEvent;\n const activeDraggableNode = draggableNodes.get(active);\n\n if ( // Another sensor is already instantiating\n activeRef.current !== null || // No active draggable\n !activeDraggableNode || // Event has already been captured\n nativeEvent.dndKit || nativeEvent.defaultPrevented) {\n return;\n }\n\n const activationContext = {\n active: activeDraggableNode\n };\n const shouldActivate = handler(event, sensor.options, activationContext);\n\n if (shouldActivate === true) {\n nativeEvent.dndKit = {\n capturedBy: sensor.sensor\n };\n activeRef.current = active;\n instantiateSensor(event, sensor);\n }\n };\n }, [draggableNodes, instantiateSensor]);\n const activators = useCombineActivators(sensors, bindActivatorToSensorInstantiator);\n useSensorSetup(sensors);\n useIsomorphicLayoutEffect(() => {\n if (activeNodeRect && status === Status.Initializing) {\n setStatus(Status.Initialized);\n }\n }, [activeNodeRect, status]);\n useEffect(() => {\n const {\n onDragMove\n } = latestProps.current;\n const {\n active,\n activatorEvent,\n collisions,\n over\n } = sensorContext.current;\n\n if (!active || !activatorEvent) {\n return;\n }\n\n const event = {\n active,\n activatorEvent,\n collisions,\n delta: {\n x: scrollAdjustedTranslate.x,\n y: scrollAdjustedTranslate.y\n },\n over\n };\n unstable_batchedUpdates(() => {\n onDragMove == null ? void 0 : onDragMove(event);\n dispatchMonitorEvent({\n type: 'onDragMove',\n event\n });\n });\n }, // eslint-disable-next-line react-hooks/exhaustive-deps\n [scrollAdjustedTranslate.x, scrollAdjustedTranslate.y]);\n useEffect(() => {\n const {\n active,\n activatorEvent,\n collisions,\n droppableContainers,\n scrollAdjustedTranslate\n } = sensorContext.current;\n\n if (!active || activeRef.current == null || !activatorEvent || !scrollAdjustedTranslate) {\n return;\n }\n\n const {\n onDragOver\n } = latestProps.current;\n const overContainer = droppableContainers.get(overId);\n const over = overContainer && overContainer.rect.current ? {\n id: overContainer.id,\n rect: overContainer.rect.current,\n data: overContainer.data,\n disabled: overContainer.disabled\n } : null;\n const event = {\n active,\n activatorEvent,\n collisions,\n delta: {\n x: scrollAdjustedTranslate.x,\n y: scrollAdjustedTranslate.y\n },\n over\n };\n unstable_batchedUpdates(() => {\n setOver(over);\n onDragOver == null ? void 0 : onDragOver(event);\n dispatchMonitorEvent({\n type: 'onDragOver',\n event\n });\n });\n }, // eslint-disable-next-line react-hooks/exhaustive-deps\n [overId]);\n useIsomorphicLayoutEffect(() => {\n sensorContext.current = {\n activatorEvent,\n active,\n activeNode,\n collisionRect,\n collisions,\n droppableRects,\n draggableNodes,\n draggingNode,\n draggingNodeRect,\n droppableContainers,\n over,\n scrollableAncestors,\n scrollAdjustedTranslate\n };\n activeRects.current = {\n initial: draggingNodeRect,\n translated: collisionRect\n };\n }, [active, activeNode, collisions, collisionRect, draggableNodes, draggingNode, draggingNodeRect, droppableRects, droppableContainers, over, scrollableAncestors, scrollAdjustedTranslate]);\n useAutoScroller({ ...autoScrollOptions,\n delta: translate,\n draggingRect: collisionRect,\n pointerCoordinates,\n scrollableAncestors,\n scrollableAncestorRects\n });\n const publicContext = useMemo(() => {\n const context = {\n active,\n activeNode,\n activeNodeRect,\n activatorEvent,\n collisions,\n containerNodeRect,\n dragOverlay,\n draggableNodes,\n droppableContainers,\n droppableRects,\n over,\n measureDroppableContainers,\n scrollableAncestors,\n scrollableAncestorRects,\n measuringConfiguration,\n measuringScheduled,\n windowRect\n };\n return context;\n }, [active, activeNode, activeNodeRect, activatorEvent, collisions, containerNodeRect, dragOverlay, draggableNodes, droppableContainers, droppableRects, over, measureDroppableContainers, scrollableAncestors, scrollableAncestorRects, measuringConfiguration, measuringScheduled, windowRect]);\n const internalContext = useMemo(() => {\n const context = {\n activatorEvent,\n activators,\n active,\n activeNodeRect,\n ariaDescribedById: {\n draggable: draggableDescribedById\n },\n dispatch,\n draggableNodes,\n over,\n measureDroppableContainers\n };\n return context;\n }, [activatorEvent, activators, active, activeNodeRect, dispatch, draggableDescribedById, draggableNodes, over, measureDroppableContainers]);\n return React.createElement(DndMonitorContext.Provider, {\n value: registerMonitorListener\n }, React.createElement(InternalContext.Provider, {\n value: internalContext\n }, React.createElement(PublicContext.Provider, {\n value: publicContext\n }, React.createElement(ActiveDraggableContext.Provider, {\n value: transform\n }, children)), React.createElement(RestoreFocus, {\n disabled: (accessibility == null ? void 0 : accessibility.restoreFocus) === false\n })), React.createElement(Accessibility, { ...accessibility,\n hiddenTextDescribedById: draggableDescribedById\n }));\n\n function getAutoScrollerOptions() {\n const activeSensorDisablesAutoscroll = (activeSensor == null ? void 0 : activeSensor.autoScrollEnabled) === false;\n const autoScrollGloballyDisabled = typeof autoScroll === 'object' ? autoScroll.enabled === false : autoScroll === false;\n const enabled = isInitialized && !activeSensorDisablesAutoscroll && !autoScrollGloballyDisabled;\n\n if (typeof autoScroll === 'object') {\n return { ...autoScroll,\n enabled\n };\n }\n\n return {\n enabled\n };\n }\n});\n\nconst NullContext = /*#__PURE__*/createContext(null);\nconst defaultRole = 'button';\nconst ID_PREFIX = 'Draggable';\nfunction useDraggable(_ref) {\n let {\n id,\n data,\n disabled = false,\n attributes\n } = _ref;\n const key = useUniqueId(ID_PREFIX);\n const {\n activators,\n activatorEvent,\n active,\n activeNodeRect,\n ariaDescribedById,\n draggableNodes,\n over\n } = useContext(InternalContext);\n const {\n role = defaultRole,\n roleDescription = 'draggable',\n tabIndex = 0\n } = attributes != null ? attributes : {};\n const isDragging = (active == null ? void 0 : active.id) === id;\n const transform = useContext(isDragging ? ActiveDraggableContext : NullContext);\n const [node, setNodeRef] = useNodeRef();\n const [activatorNode, setActivatorNodeRef] = useNodeRef();\n const listeners = useSyntheticListeners(activators, id);\n const dataRef = useLatestValue(data);\n useIsomorphicLayoutEffect(() => {\n draggableNodes.set(id, {\n id,\n key,\n node,\n activatorNode,\n data: dataRef\n });\n return () => {\n const node = draggableNodes.get(id);\n\n if (node && node.key === key) {\n draggableNodes.delete(id);\n }\n };\n }, // eslint-disable-next-line react-hooks/exhaustive-deps\n [draggableNodes, id]);\n const memoizedAttributes = useMemo(() => ({\n role,\n tabIndex,\n 'aria-disabled': disabled,\n 'aria-pressed': isDragging && role === defaultRole ? true : undefined,\n 'aria-roledescription': roleDescription,\n 'aria-describedby': ariaDescribedById.draggable\n }), [disabled, role, tabIndex, isDragging, roleDescription, ariaDescribedById.draggable]);\n return {\n active,\n activatorEvent,\n activeNodeRect,\n attributes: memoizedAttributes,\n isDragging,\n listeners: disabled ? undefined : listeners,\n node,\n over,\n setNodeRef,\n setActivatorNodeRef,\n transform\n };\n}\n\nfunction useDndContext() {\n return useContext(PublicContext);\n}\n\nconst ID_PREFIX$1 = 'Droppable';\nconst defaultResizeObserverConfig = {\n timeout: 25\n};\nfunction useDroppable(_ref) {\n let {\n data,\n disabled = false,\n id,\n resizeObserverConfig\n } = _ref;\n const key = useUniqueId(ID_PREFIX$1);\n const {\n active,\n dispatch,\n over,\n measureDroppableContainers\n } = useContext(InternalContext);\n const previous = useRef({\n disabled\n });\n const resizeObserverConnected = useRef(false);\n const rect = useRef(null);\n const callbackId = useRef(null);\n const {\n disabled: resizeObserverDisabled,\n updateMeasurementsFor,\n timeout: resizeObserverTimeout\n } = { ...defaultResizeObserverConfig,\n ...resizeObserverConfig\n };\n const ids = useLatestValue(updateMeasurementsFor != null ? updateMeasurementsFor : id);\n const handleResize = useCallback(() => {\n if (!resizeObserverConnected.current) {\n // ResizeObserver invokes the `handleResize` callback as soon as `observe` is called,\n // assuming the element is rendered and displayed.\n resizeObserverConnected.current = true;\n return;\n }\n\n if (callbackId.current != null) {\n clearTimeout(callbackId.current);\n }\n\n callbackId.current = setTimeout(() => {\n measureDroppableContainers(Array.isArray(ids.current) ? ids.current : [ids.current]);\n callbackId.current = null;\n }, resizeObserverTimeout);\n }, //eslint-disable-next-line react-hooks/exhaustive-deps\n [resizeObserverTimeout]);\n const resizeObserver = useResizeObserver({\n callback: handleResize,\n disabled: resizeObserverDisabled || !active\n });\n const handleNodeChange = useCallback((newElement, previousElement) => {\n if (!resizeObserver) {\n return;\n }\n\n if (previousElement) {\n resizeObserver.unobserve(previousElement);\n resizeObserverConnected.current = false;\n }\n\n if (newElement) {\n resizeObserver.observe(newElement);\n }\n }, [resizeObserver]);\n const [nodeRef, setNodeRef] = useNodeRef(handleNodeChange);\n const dataRef = useLatestValue(data);\n useEffect(() => {\n if (!resizeObserver || !nodeRef.current) {\n return;\n }\n\n resizeObserver.disconnect();\n resizeObserverConnected.current = false;\n resizeObserver.observe(nodeRef.current);\n }, [nodeRef, resizeObserver]);\n useEffect(() => {\n dispatch({\n type: Action.RegisterDroppable,\n element: {\n id,\n key,\n disabled,\n node: nodeRef,\n rect,\n data: dataRef\n }\n });\n return () => dispatch({\n type: Action.UnregisterDroppable,\n key,\n id\n });\n }, // eslint-disable-next-line react-hooks/exhaustive-deps\n [id]);\n useEffect(() => {\n if (disabled !== previous.current.disabled) {\n dispatch({\n type: Action.SetDroppableDisabled,\n id,\n key,\n disabled\n });\n previous.current.disabled = disabled;\n }\n }, [id, key, disabled, dispatch]);\n return {\n active,\n rect,\n isOver: (over == null ? void 0 : over.id) === id,\n node: nodeRef,\n over,\n setNodeRef\n };\n}\n\nfunction AnimationManager(_ref) {\n let {\n animation,\n children\n } = _ref;\n const [clonedChildren, setClonedChildren] = useState(null);\n const [element, setElement] = useState(null);\n const previousChildren = usePrevious(children);\n\n if (!children && !clonedChildren && previousChildren) {\n setClonedChildren(previousChildren);\n }\n\n useIsomorphicLayoutEffect(() => {\n if (!element) {\n return;\n }\n\n const key = clonedChildren == null ? void 0 : clonedChildren.key;\n const id = clonedChildren == null ? void 0 : clonedChildren.props.id;\n\n if (key == null || id == null) {\n setClonedChildren(null);\n return;\n }\n\n Promise.resolve(animation(id, element)).then(() => {\n setClonedChildren(null);\n });\n }, [animation, clonedChildren, element]);\n return React.createElement(React.Fragment, null, children, clonedChildren ? cloneElement(clonedChildren, {\n ref: setElement\n }) : null);\n}\n\nconst defaultTransform = {\n x: 0,\n y: 0,\n scaleX: 1,\n scaleY: 1\n};\nfunction NullifiedContextProvider(_ref) {\n let {\n children\n } = _ref;\n return React.createElement(InternalContext.Provider, {\n value: defaultInternalContext\n }, React.createElement(ActiveDraggableContext.Provider, {\n value: defaultTransform\n }, children));\n}\n\nconst baseStyles = {\n position: 'fixed',\n touchAction: 'none'\n};\n\nconst defaultTransition = activatorEvent => {\n const isKeyboardActivator = isKeyboardEvent(activatorEvent);\n return isKeyboardActivator ? 'transform 250ms ease' : undefined;\n};\n\nconst PositionedOverlay = /*#__PURE__*/forwardRef((_ref, ref) => {\n let {\n as,\n activatorEvent,\n adjustScale,\n children,\n className,\n rect,\n style,\n transform,\n transition = defaultTransition\n } = _ref;\n\n if (!rect) {\n return null;\n }\n\n const scaleAdjustedTransform = adjustScale ? transform : { ...transform,\n scaleX: 1,\n scaleY: 1\n };\n const styles = { ...baseStyles,\n width: rect.width,\n height: rect.height,\n top: rect.top,\n left: rect.left,\n transform: CSS.Transform.toString(scaleAdjustedTransform),\n transformOrigin: adjustScale && activatorEvent ? getRelativeTransformOrigin(activatorEvent, rect) : undefined,\n transition: typeof transition === 'function' ? transition(activatorEvent) : transition,\n ...style\n };\n return React.createElement(as, {\n className,\n style: styles,\n ref\n }, children);\n});\n\nconst defaultDropAnimationSideEffects = options => _ref => {\n let {\n active,\n dragOverlay\n } = _ref;\n const originalStyles = {};\n const {\n styles,\n className\n } = options;\n\n if (styles != null && styles.active) {\n for (const [key, value] of Object.entries(styles.active)) {\n if (value === undefined) {\n continue;\n }\n\n originalStyles[key] = active.node.style.getPropertyValue(key);\n active.node.style.setProperty(key, value);\n }\n }\n\n if (styles != null && styles.dragOverlay) {\n for (const [key, value] of Object.entries(styles.dragOverlay)) {\n if (value === undefined) {\n continue;\n }\n\n dragOverlay.node.style.setProperty(key, value);\n }\n }\n\n if (className != null && className.active) {\n active.node.classList.add(className.active);\n }\n\n if (className != null && className.dragOverlay) {\n dragOverlay.node.classList.add(className.dragOverlay);\n }\n\n return function cleanup() {\n for (const [key, value] of Object.entries(originalStyles)) {\n active.node.style.setProperty(key, value);\n }\n\n if (className != null && className.active) {\n active.node.classList.remove(className.active);\n }\n };\n};\n\nconst defaultKeyframeResolver = _ref2 => {\n let {\n transform: {\n initial,\n final\n }\n } = _ref2;\n return [{\n transform: CSS.Transform.toString(initial)\n }, {\n transform: CSS.Transform.toString(final)\n }];\n};\n\nconst defaultDropAnimationConfiguration = {\n duration: 250,\n easing: 'ease',\n keyframes: defaultKeyframeResolver,\n sideEffects: /*#__PURE__*/defaultDropAnimationSideEffects({\n styles: {\n active: {\n opacity: '0'\n }\n }\n })\n};\nfunction useDropAnimation(_ref3) {\n let {\n config,\n draggableNodes,\n droppableContainers,\n measuringConfiguration\n } = _ref3;\n return useEvent((id, node) => {\n if (config === null) {\n return;\n }\n\n const activeDraggable = draggableNodes.get(id);\n\n if (!activeDraggable) {\n return;\n }\n\n const activeNode = activeDraggable.node.current;\n\n if (!activeNode) {\n return;\n }\n\n const measurableNode = getMeasurableNode(node);\n\n if (!measurableNode) {\n return;\n }\n\n const {\n transform\n } = getWindow(node).getComputedStyle(node);\n const parsedTransform = parseTransform(transform);\n\n if (!parsedTransform) {\n return;\n }\n\n const animation = typeof config === 'function' ? config : createDefaultDropAnimation(config);\n scrollIntoViewIfNeeded(activeNode, measuringConfiguration.draggable.measure);\n return animation({\n active: {\n id,\n data: activeDraggable.data,\n node: activeNode,\n rect: measuringConfiguration.draggable.measure(activeNode)\n },\n draggableNodes,\n dragOverlay: {\n node,\n rect: measuringConfiguration.dragOverlay.measure(measurableNode)\n },\n droppableContainers,\n measuringConfiguration,\n transform: parsedTransform\n });\n });\n}\n\nfunction createDefaultDropAnimation(options) {\n const {\n duration,\n easing,\n sideEffects,\n keyframes\n } = { ...defaultDropAnimationConfiguration,\n ...options\n };\n return _ref4 => {\n let {\n active,\n dragOverlay,\n transform,\n ...rest\n } = _ref4;\n\n if (!duration) {\n // Do not animate if animation duration is zero.\n return;\n }\n\n const delta = {\n x: dragOverlay.rect.left - active.rect.left,\n y: dragOverlay.rect.top - active.rect.top\n };\n const scale = {\n scaleX: transform.scaleX !== 1 ? active.rect.width * transform.scaleX / dragOverlay.rect.width : 1,\n scaleY: transform.scaleY !== 1 ? active.rect.height * transform.scaleY / dragOverlay.rect.height : 1\n };\n const finalTransform = {\n x: transform.x - delta.x,\n y: transform.y - delta.y,\n ...scale\n };\n const animationKeyframes = keyframes({ ...rest,\n active,\n dragOverlay,\n transform: {\n initial: transform,\n final: finalTransform\n }\n });\n const [firstKeyframe] = animationKeyframes;\n const lastKeyframe = animationKeyframes[animationKeyframes.length - 1];\n\n if (JSON.stringify(firstKeyframe) === JSON.stringify(lastKeyframe)) {\n // The start and end keyframes are the same, infer that there is no animation needed.\n return;\n }\n\n const cleanup = sideEffects == null ? void 0 : sideEffects({\n active,\n dragOverlay,\n ...rest\n });\n const animation = dragOverlay.node.animate(animationKeyframes, {\n duration,\n easing,\n fill: 'forwards'\n });\n return new Promise(resolve => {\n animation.onfinish = () => {\n cleanup == null ? void 0 : cleanup();\n resolve();\n };\n });\n };\n}\n\nlet key = 0;\nfunction useKey(id) {\n return useMemo(() => {\n if (id == null) {\n return;\n }\n\n key++;\n return key;\n }, [id]);\n}\n\nconst DragOverlay = /*#__PURE__*/React.memo(_ref => {\n let {\n adjustScale = false,\n children,\n dropAnimation: dropAnimationConfig,\n style,\n transition,\n modifiers,\n wrapperElement = 'div',\n className,\n zIndex = 999\n } = _ref;\n const {\n activatorEvent,\n active,\n activeNodeRect,\n containerNodeRect,\n draggableNodes,\n droppableContainers,\n dragOverlay,\n over,\n measuringConfiguration,\n scrollableAncestors,\n scrollableAncestorRects,\n windowRect\n } = useDndContext();\n const transform = useContext(ActiveDraggableContext);\n const key = useKey(active == null ? void 0 : active.id);\n const modifiedTransform = applyModifiers(modifiers, {\n activatorEvent,\n active,\n activeNodeRect,\n containerNodeRect,\n draggingNodeRect: dragOverlay.rect,\n over,\n overlayNodeRect: dragOverlay.rect,\n scrollableAncestors,\n scrollableAncestorRects,\n transform,\n windowRect\n });\n const initialRect = useInitialValue(activeNodeRect);\n const dropAnimation = useDropAnimation({\n config: dropAnimationConfig,\n draggableNodes,\n droppableContainers,\n measuringConfiguration\n }); // We need to wait for the active node to be measured before connecting the drag overlay ref\n // otherwise collisions can be computed against a mispositioned drag overlay\n\n const ref = initialRect ? dragOverlay.setRef : undefined;\n return React.createElement(NullifiedContextProvider, null, React.createElement(AnimationManager, {\n animation: dropAnimation\n }, active && key ? React.createElement(PositionedOverlay, {\n key: key,\n id: active.id,\n ref: ref,\n as: wrapperElement,\n activatorEvent: activatorEvent,\n adjustScale: adjustScale,\n className: className,\n transition: transition,\n rect: initialRect,\n style: {\n zIndex,\n ...style\n },\n transform: modifiedTransform\n }, children) : null));\n});\n\nexport { AutoScrollActivator, DndContext, DragOverlay, KeyboardCode, KeyboardSensor, MeasuringFrequency, MeasuringStrategy, MouseSensor, PointerSensor, TouchSensor, TraversalOrder, applyModifiers, closestCenter, closestCorners, defaultAnnouncements, defaultCoordinates, defaultDropAnimationConfiguration as defaultDropAnimation, defaultDropAnimationSideEffects, defaultKeyboardCoordinateGetter, defaultScreenReaderInstructions, getClientRect, getFirstCollision, getScrollableAncestors, pointerWithin, rectIntersection, useDndContext, useDndMonitor, useDraggable, useDroppable, useSensor, useSensors };\n//# sourceMappingURL=core.esm.js.map\n","/**\n * Hook for configuring @dnd-kit sensors for clip dragging\n *\n * Provides consistent drag activation behavior across all examples.\n * Supports both desktop (immediate feedback) and mobile (delay-based) interactions.\n */\n\nimport { useSensor, useSensors, PointerSensor, TouchSensor, MouseSensor } from '@dnd-kit/core';\n\nexport interface DragSensorOptions {\n /**\n * Enable mobile-optimized touch handling with delay-based activation.\n * When true, uses TouchSensor with 250ms delay to distinguish drag from scroll.\n * When false (default), uses PointerSensor with 1px activation for immediate feedback.\n */\n touchOptimized?: boolean;\n /**\n * Delay in milliseconds before touch drag activates (only when touchOptimized is true).\n * Default: 250ms - long enough to distinguish from scroll intent\n */\n touchDelay?: number;\n /**\n * Distance tolerance during touch delay (only when touchOptimized is true).\n * If finger moves more than this during delay, drag is cancelled.\n * Default: 5px - allows slight finger movement\n */\n touchTolerance?: number;\n /**\n * Distance in pixels before mouse drag activates.\n * Default: 1px for immediate feedback on desktop\n */\n mouseDistance?: number;\n}\n\n/**\n * Returns configured sensors for @dnd-kit drag operations\n *\n * @param options - Configuration options for drag sensors\n * @returns Configured sensors appropriate for the interaction mode\n *\n * @example\n * // Desktop-optimized (default)\n * const sensors = useDragSensors();\n *\n * @example\n * // Mobile-optimized with touch delay\n * const sensors = useDragSensors({ touchOptimized: true });\n *\n * @example\n * // Custom touch settings\n * const sensors = useDragSensors({\n * touchOptimized: true,\n * touchDelay: 300,\n * touchTolerance: 8\n * });\n */\nexport function useDragSensors(options: DragSensorOptions = {}) {\n const {\n touchOptimized = false,\n touchDelay = 250,\n touchTolerance = 5,\n mouseDistance = 1,\n } = options;\n\n // Touch-optimized: Use separate MouseSensor and TouchSensor\n // This allows different activation constraints for each input type\n const mouseSensor = useSensor(MouseSensor, {\n activationConstraint: {\n distance: mouseDistance,\n },\n });\n\n const touchSensor = useSensor(TouchSensor, {\n activationConstraint: touchOptimized\n ? {\n // Delay-based activation for mobile - wait before starting drag\n // This allows users to scroll without accidentally triggering drag\n delay: touchDelay,\n tolerance: touchTolerance,\n }\n : {\n // Distance-based activation for non-optimized mode\n distance: mouseDistance,\n },\n });\n\n // Non-optimized: Use PointerSensor for unified handling (original behavior)\n const pointerSensor = useSensor(PointerSensor, {\n activationConstraint: {\n distance: mouseDistance,\n },\n });\n\n // When touch-optimized, use separate sensors for better control\n // Otherwise, use unified PointerSensor for backwards compatibility\n return useSensors(\n ...(touchOptimized ? [mouseSensor, touchSensor] : [pointerSensor])\n );\n}\n","import { useCallback } from 'react';\nimport { type ClipTrack, createClip } from '@waveform-playlist/core';\nimport { usePlaybackAnimation, usePlaylistState } from '../WaveformPlaylistContext';\n\nexport interface UseClipSplittingOptions {\n tracks: ClipTrack[];\n onTracksChange: (tracks: ClipTrack[]) => void;\n sampleRate: number;\n samplesPerPixel: number;\n}\n\nexport interface UseClipSplittingResult {\n splitClipAtPlayhead: () => boolean;\n splitClipAt: (trackIndex: number, clipIndex: number, splitTime: number) => boolean;\n}\n\n/**\n * Hook for splitting clips at the playhead or at a specific time\n *\n * @param options - Configuration options\n * @returns Object with split functions\n *\n * @example\n * ```tsx\n * const { splitClipAtPlayhead } = useClipSplitting({\n * tracks,\n * onTracksChange: setTracks,\n * currentTime,\n * });\n *\n * // In keyboard handler\n * const handleKeyPress = (e: KeyboardEvent) => {\n * if (e.key === 's' || e.key === 'S') {\n * splitClipAtPlayhead();\n * }\n * };\n * ```\n */\nexport const useClipSplitting = (options: UseClipSplittingOptions): UseClipSplittingResult => {\n const { tracks, onTracksChange, sampleRate } = options;\n const { currentTimeRef } = usePlaybackAnimation();\n const { selectedTrackId } = usePlaylistState();\n\n /**\n * Split a specific clip at a given time\n *\n * @param trackIndex - Index of the track containing the clip\n * @param clipIndex - Index of the clip within the track\n * @param splitTime - Timeline position where to split (in seconds)\n * @returns true if split was successful, false otherwise\n */\n const splitClipAt = useCallback(\n (trackIndex: number, clipIndex: number, splitTime: number): boolean => {\n // Work with samples and pixels (all integers!) to avoid floating-point precision issues\n // Key insight: A pixel represents a RANGE of samples (samplesPerPixel samples)\n // By working in samples, we eliminate all floating-point errors\n const { sampleRate, samplesPerPixel } = options;\n\n const track = tracks[trackIndex];\n if (!track) return false;\n\n const clip = track.clips[clipIndex];\n if (!clip) return false;\n\n // Convert clip positions from samples to seconds for bounds checking\n const clipStartTime = clip.startSample / sampleRate;\n const clipEndTime = (clip.startSample + clip.durationSamples) / sampleRate;\n\n // Validate that split time is within clip bounds\n if (splitTime <= clipStartTime || splitTime >= clipEndTime) {\n console.warn('Split time is outside clip bounds');\n return false;\n }\n\n // Convert split time from seconds to samples (round to nearest sample)\n const splitSample = Math.round(splitTime * sampleRate);\n\n // Calculate pixel positions from sample positions using integer division\n const splitPixel = Math.floor(splitSample / samplesPerPixel);\n const clipEndSample = clip.startSample + clip.durationSamples;\n\n // Calculate sample positions from exact pixel boundaries\n // Both clips share the same boundary: the start of the split pixel\n const snappedSplitSample = splitPixel * samplesPerPixel;\n\n // First clip: starts at clip's original start, ends at split pixel boundary\n const firstClipStartSample = clip.startSample;\n const firstClipDurationSamples = snappedSplitSample - firstClipStartSample;\n\n // Second clip: starts at split pixel boundary, ends at clip's original end\n const secondClipStartSample = snappedSplitSample;\n const secondClipDurationSamples = clipEndSample - secondClipStartSample;\n\n // Calculate offset increment for second clip (in samples)\n const offsetIncrement = snappedSplitSample - clip.startSample;\n\n // Create first clip (from start to split point)\n const firstClip = createClip({\n audioBuffer: clip.audioBuffer,\n startSample: firstClipStartSample,\n durationSamples: firstClipDurationSamples,\n offsetSamples: clip.offsetSamples,\n sampleRate: clip.sampleRate,\n sourceDurationSamples: clip.sourceDurationSamples,\n gain: clip.gain,\n name: clip.name ? `${clip.name} (1)` : undefined,\n color: clip.color,\n fadeIn: clip.fadeIn,\n waveformData: clip.waveformData, // Share waveformData - slicing happens at render time\n // Note: fadeOut removed for first clip since it's cut\n });\n\n // Create second clip (from split point to end)\n const secondClip = createClip({\n audioBuffer: clip.audioBuffer,\n startSample: secondClipStartSample,\n durationSamples: secondClipDurationSamples,\n offsetSamples: clip.offsetSamples + offsetIncrement,\n sampleRate: clip.sampleRate,\n sourceDurationSamples: clip.sourceDurationSamples,\n gain: clip.gain,\n name: clip.name ? `${clip.name} (2)` : undefined,\n color: clip.color,\n waveformData: clip.waveformData, // Share waveformData - slicing happens at render time\n // Note: fadeIn removed for second clip since it's cut\n fadeOut: clip.fadeOut,\n });\n\n // Create new clips array with the split clips\n const newClips = [...track.clips];\n newClips.splice(clipIndex, 1, firstClip, secondClip);\n\n // Update the track with new clips\n const newTracks = [...tracks];\n newTracks[trackIndex] = {\n ...track,\n clips: newClips,\n };\n\n onTracksChange(newTracks);\n return true;\n },\n [tracks, onTracksChange, options]\n );\n\n /**\n * Split clip at the current playhead position on the selected track\n * If no track is selected, does nothing\n *\n * @returns true if a clip was split, false otherwise\n */\n const splitClipAtPlayhead = useCallback((): boolean => {\n // If no track is selected, cannot split\n if (!selectedTrackId) {\n console.log('No track selected - click a clip to select a track first');\n return false;\n }\n\n // Find the selected track\n const trackIndex = tracks.findIndex(track => track.id === selectedTrackId);\n if (trackIndex === -1) {\n console.warn('Selected track not found');\n return false;\n }\n\n const track = tracks[trackIndex];\n\n // Use ref for real-time position during playback (state updates are throttled)\n const currentTime = currentTimeRef.current ?? 0;\n\n // Find clip at current time on the selected track\n for (let clipIndex = 0; clipIndex < track.clips.length; clipIndex++) {\n const clip = track.clips[clipIndex];\n const clipStartTime = clip.startSample / sampleRate;\n const clipEndTime = (clip.startSample + clip.durationSamples) / sampleRate;\n\n // Check if currentTime is within this clip (not at boundaries)\n if (currentTime > clipStartTime && currentTime < clipEndTime) {\n // Found a clip! Split it\n console.log(`Splitting clip on track \"${track.name}\" at ${currentTime}s`);\n return splitClipAt(trackIndex, clipIndex, currentTime);\n }\n }\n\n console.log(`No clip found at playhead position on track \"${track.name}\"`);\n return false;\n }, [tracks, currentTimeRef, selectedTrackId, splitClipAt, sampleRate]);\n\n return {\n splitClipAtPlayhead,\n splitClipAt,\n };\n};\n","import { useEffect, useCallback } from 'react';\n\nexport interface KeyboardShortcut {\n key: string;\n ctrlKey?: boolean;\n shiftKey?: boolean;\n metaKey?: boolean;\n altKey?: boolean;\n action: () => void;\n description?: string;\n preventDefault?: boolean;\n}\n\nexport interface UseKeyboardShortcutsOptions {\n shortcuts: KeyboardShortcut[];\n enabled?: boolean;\n}\n\n/**\n * Hook for managing keyboard shortcuts\n *\n * @param options - Configuration options\n *\n * @example\n * ```tsx\n * const { splitClipAtPlayhead } = useClipSplitting({ ... });\n *\n * useKeyboardShortcuts({\n * shortcuts: [\n * {\n * key: 's',\n * action: splitClipAtPlayhead,\n * description: 'Split clip at playhead',\n * preventDefault: true,\n * },\n * {\n * key: 'S',\n * shiftKey: true,\n * action: () => splitAtSelection(),\n * description: 'Split at selection boundaries',\n * preventDefault: true,\n * },\n * ],\n * });\n * ```\n */\nexport const useKeyboardShortcuts = (options: UseKeyboardShortcutsOptions): void => {\n const { shortcuts, enabled = true } = options;\n\n const handleKeyDown = useCallback(\n (event: KeyboardEvent) => {\n if (!enabled) return;\n\n // Check if we're in an input/textarea element\n const target = event.target as HTMLElement;\n if (\n target.tagName === 'INPUT' ||\n target.tagName === 'TEXTAREA' ||\n target.isContentEditable\n ) {\n // Don't trigger shortcuts when typing in input fields\n return;\n }\n\n // Find matching shortcut\n const matchingShortcut = shortcuts.find((shortcut) => {\n const keyMatch =\n event.key.toLowerCase() === shortcut.key.toLowerCase() ||\n event.key === shortcut.key;\n\n const ctrlMatch = shortcut.ctrlKey === undefined || event.ctrlKey === shortcut.ctrlKey;\n const shiftMatch =\n shortcut.shiftKey === undefined || event.shiftKey === shortcut.shiftKey;\n const metaMatch = shortcut.metaKey === undefined || event.metaKey === shortcut.metaKey;\n const altMatch = shortcut.altKey === undefined || event.altKey === shortcut.altKey;\n\n return keyMatch && ctrlMatch && shiftMatch && metaMatch && altMatch;\n });\n\n if (matchingShortcut) {\n if (matchingShortcut.preventDefault !== false) {\n event.preventDefault();\n }\n matchingShortcut.action();\n }\n },\n [shortcuts, enabled]\n );\n\n useEffect(() => {\n if (!enabled) return;\n\n window.addEventListener('keydown', handleKeyDown);\n\n return () => {\n window.removeEventListener('keydown', handleKeyDown);\n };\n }, [handleKeyDown, enabled]);\n};\n\n/**\n * Get a human-readable string representation of a keyboard shortcut\n *\n * @param shortcut - The keyboard shortcut\n * @returns Human-readable string (e.g., \"Cmd+Shift+S\")\n */\nexport const getShortcutLabel = (shortcut: KeyboardShortcut): string => {\n const parts: string[] = [];\n\n // Use Cmd on Mac, Ctrl on other platforms\n const isMac = typeof navigator !== 'undefined' && navigator.platform.includes('Mac');\n\n if (shortcut.metaKey) {\n parts.push(isMac ? 'Cmd' : 'Ctrl');\n }\n\n if (shortcut.ctrlKey && !shortcut.metaKey) {\n parts.push('Ctrl');\n }\n\n if (shortcut.altKey) {\n parts.push(isMac ? 'Option' : 'Alt');\n }\n\n if (shortcut.shiftKey) {\n parts.push('Shift');\n }\n\n parts.push(shortcut.key.toUpperCase());\n\n return parts.join('+');\n};\n","import { useCallback } from 'react';\nimport { usePlaybackAnimation, usePlaylistControls, usePlaylistData } from '../WaveformPlaylistContext';\nimport { useKeyboardShortcuts, type KeyboardShortcut } from './useKeyboardShortcuts';\n\nexport interface UsePlaybackShortcutsOptions {\n /**\n * Enable the shortcuts. Defaults to true.\n */\n enabled?: boolean;\n /**\n * Additional shortcuts to include alongside the default playback shortcuts.\n */\n additionalShortcuts?: KeyboardShortcut[];\n /**\n * Override default shortcuts. If provided, only these shortcuts will be used.\n */\n shortcuts?: KeyboardShortcut[];\n}\n\nexport interface UsePlaybackShortcutsReturn {\n /** Rewind to the beginning (time = 0) */\n rewindToStart: () => void;\n /** Toggle play/pause */\n togglePlayPause: () => void;\n /** Stop playback and return to start position */\n stopPlayback: () => void;\n /** The list of active keyboard shortcuts */\n shortcuts: KeyboardShortcut[];\n}\n\n/**\n * Hook that provides common playback keyboard shortcuts for the playlist.\n *\n * Default shortcuts:\n * - `Space` - Toggle play/pause\n * - `Escape` - Stop playback\n * - `0` - Rewind to start (seek to time 0)\n *\n * @example\n * ```tsx\n * // Basic usage - enables default shortcuts\n * usePlaybackShortcuts();\n *\n * // With additional custom shortcuts\n * usePlaybackShortcuts({\n * additionalShortcuts: [\n * { key: 's', action: splitClipAtPlayhead, description: 'Split clip' },\n * ],\n * });\n *\n * // Completely override shortcuts\n * usePlaybackShortcuts({\n * shortcuts: [\n * { key: 'Home', action: rewindToStart, description: 'Go to start' },\n * ],\n * });\n * ```\n */\nexport const usePlaybackShortcuts = (\n options: UsePlaybackShortcutsOptions = {}\n): UsePlaybackShortcutsReturn => {\n const { enabled = true, additionalShortcuts = [], shortcuts: overrideShortcuts } = options;\n\n const { isPlaying } = usePlaybackAnimation();\n const { setCurrentTime, play, pause, stop } = usePlaylistControls();\n const { playoutRef } = usePlaylistData();\n\n /**\n * Toggle between play and pause.\n */\n const togglePlayPause = useCallback(() => {\n if (isPlaying) {\n pause();\n } else {\n play();\n }\n }, [isPlaying, play, pause]);\n\n /**\n * Stop playback and return to start position.\n */\n const stopPlayback = useCallback(() => {\n stop();\n }, [stop]);\n\n /**\n * Rewind to the beginning of the timeline.\n * If playing, stops and restarts playback from the beginning.\n */\n const rewindToStart = useCallback(() => {\n if (isPlaying && playoutRef.current) {\n playoutRef.current.stop();\n setCurrentTime(0);\n play(0);\n } else {\n setCurrentTime(0);\n }\n }, [isPlaying, playoutRef, setCurrentTime, play]);\n\n // Default playback shortcuts\n const defaultShortcuts: KeyboardShortcut[] = [\n {\n key: ' ',\n action: togglePlayPause,\n description: 'Play/Pause',\n preventDefault: true,\n },\n {\n key: 'Escape',\n action: stopPlayback,\n description: 'Stop',\n preventDefault: true,\n },\n {\n key: '0',\n action: rewindToStart,\n description: 'Rewind to start',\n preventDefault: true,\n },\n ];\n\n // Use override shortcuts if provided, otherwise combine defaults with additional\n const activeShortcuts = overrideShortcuts ?? [...defaultShortcuts, ...additionalShortcuts];\n\n // Register the keyboard shortcuts\n useKeyboardShortcuts({\n shortcuts: activeShortcuts,\n enabled,\n });\n\n return {\n rewindToStart,\n togglePlayPause,\n stopPlayback,\n shortcuts: activeShortcuts,\n };\n};\n","import { useCallback, useMemo, useEffect } from 'react';\nimport type { AnnotationType } from '@waveform-playlist/annotations';\nimport { useKeyboardShortcuts } from './useKeyboardShortcuts';\n\nconst LINK_THRESHOLD = 0.01; // Consider edges \"linked\" if within 10ms\nconst TIME_DELTA = 0.01; // 10ms adjustment per keypress\n\ninterface UseAnnotationKeyboardControlsOptions {\n annotations: AnnotationType[];\n activeAnnotationId: string | null;\n onAnnotationsChange: (annotations: AnnotationType[]) => void;\n /** Callback to set the active annotation ID for selection */\n onActiveAnnotationChange?: (id: string | null) => void;\n duration: number;\n linkEndpoints: boolean;\n /** Whether continuous play is enabled (affects playback duration) */\n continuousPlay?: boolean;\n enabled?: boolean;\n /** Optional: scroll container ref for auto-scrolling to annotation */\n scrollContainerRef?: React.RefObject<HTMLDivElement | null>;\n /** Optional: samples per pixel for scroll position calculation */\n samplesPerPixel?: number;\n /** Optional: sample rate for scroll position calculation */\n sampleRate?: number;\n /** Optional: controls width offset for scroll position calculation */\n controlsWidth?: number;\n /** Optional: callback to start playback at a time with optional duration */\n onPlay?: (startTime: number, duration?: number) => void;\n}\n\n/**\n * Hook for keyboard-based annotation navigation and boundary editing\n *\n * Navigation Shortcuts:\n * - ArrowUp / ArrowLeft = Select previous annotation\n * - ArrowDown / ArrowRight = Select next annotation\n * - Home = Select first annotation\n * - End = Select last annotation\n * - Escape = Deselect annotation\n * - Enter = Play selected annotation\n *\n * Boundary Editing Shortcuts (requires active annotation):\n * - [ = Move start boundary earlier (left)\n * - ] = Move start boundary later (right)\n * - Shift+[ = Move end boundary earlier (left)\n * - Shift+] = Move end boundary later (right)\n *\n * Respects linkEndpoints and continuousPlay settings.\n *\n * @example\n * ```tsx\n * useAnnotationKeyboardControls({\n * annotations,\n * activeAnnotationId,\n * onAnnotationsChange: setAnnotations,\n * onActiveAnnotationChange: setActiveAnnotationId,\n * duration,\n * linkEndpoints,\n * });\n * ```\n */\nexport function useAnnotationKeyboardControls({\n annotations,\n activeAnnotationId,\n onAnnotationsChange,\n onActiveAnnotationChange,\n duration,\n linkEndpoints,\n continuousPlay = false,\n enabled = true,\n scrollContainerRef,\n samplesPerPixel,\n sampleRate,\n controlsWidth = 0,\n onPlay,\n}: UseAnnotationKeyboardControlsOptions) {\n const activeIndex = useMemo(() => {\n if (!activeAnnotationId) return -1;\n return annotations.findIndex((a) => a.id === activeAnnotationId);\n }, [annotations, activeAnnotationId]);\n\n // Scroll waveform to show a specific annotation\n const scrollToAnnotation = useCallback(\n (annotationId: string) => {\n if (!scrollContainerRef?.current || !samplesPerPixel || !sampleRate) return;\n\n const annotation = annotations.find((a) => a.id === annotationId);\n if (!annotation) return;\n\n const container = scrollContainerRef.current;\n const containerWidth = container.clientWidth;\n\n // Calculate pixel positions for annotation start and center\n const startPixel = (annotation.start * sampleRate) / samplesPerPixel + controlsWidth;\n const endPixel = (annotation.end * sampleRate) / samplesPerPixel + controlsWidth;\n const annotationCenter = (startPixel + endPixel) / 2;\n\n // Check if annotation is currently visible\n const scrollLeft = container.scrollLeft;\n const visibleStart = scrollLeft;\n const visibleEnd = scrollLeft + containerWidth;\n\n // If annotation is not fully visible, scroll to center it\n if (startPixel < visibleStart || endPixel > visibleEnd) {\n const targetScrollLeft = Math.max(0, annotationCenter - containerWidth / 2);\n container.scrollTo({\n left: targetScrollLeft,\n behavior: 'smooth',\n });\n }\n },\n [annotations, scrollContainerRef, samplesPerPixel, sampleRate, controlsWidth]\n );\n\n // Auto-scroll when active annotation changes via keyboard navigation\n useEffect(() => {\n if (activeAnnotationId && scrollContainerRef?.current && samplesPerPixel && sampleRate) {\n scrollToAnnotation(activeAnnotationId);\n }\n }, [activeAnnotationId, scrollToAnnotation, scrollContainerRef, samplesPerPixel, sampleRate]);\n\n const moveStartBoundary = useCallback(\n (delta: number) => {\n if (activeIndex < 0) return;\n\n const annotation = annotations[activeIndex];\n const newStart = Math.max(0, Math.min(annotation.end - 0.1, annotation.start + delta));\n const actualDelta = newStart - annotation.start;\n\n const updatedAnnotations = [...annotations];\n updatedAnnotations[activeIndex] = {\n ...annotation,\n start: newStart,\n };\n\n // Handle linked endpoints\n if (linkEndpoints && activeIndex > 0) {\n const prevAnnotation = updatedAnnotations[activeIndex - 1];\n if (Math.abs(prevAnnotation.end - annotation.start) < LINK_THRESHOLD) {\n // Already linked: move previous annotation's end together\n updatedAnnotations[activeIndex - 1] = {\n ...prevAnnotation,\n end: Math.max(prevAnnotation.start + 0.1, prevAnnotation.end + actualDelta),\n };\n }\n } else if (!linkEndpoints && activeIndex > 0) {\n // Non-linked mode: don't overlap previous annotation\n const prevAnnotation = updatedAnnotations[activeIndex - 1];\n if (newStart < prevAnnotation.end) {\n // Push back previous annotation's end\n updatedAnnotations[activeIndex - 1] = {\n ...prevAnnotation,\n end: newStart,\n };\n }\n }\n\n onAnnotationsChange(updatedAnnotations);\n },\n [annotations, activeIndex, linkEndpoints, onAnnotationsChange]\n );\n\n const moveEndBoundary = useCallback(\n (delta: number) => {\n if (activeIndex < 0) return;\n\n const annotation = annotations[activeIndex];\n const newEnd = Math.max(annotation.start + 0.1, Math.min(duration, annotation.end + delta));\n const actualDelta = newEnd - annotation.end;\n\n const updatedAnnotations = [...annotations];\n updatedAnnotations[activeIndex] = {\n ...annotation,\n end: newEnd,\n };\n\n // Handle linked endpoints\n if (linkEndpoints && activeIndex < annotations.length - 1) {\n const nextAnnotation = updatedAnnotations[activeIndex + 1];\n if (Math.abs(nextAnnotation.start - annotation.end) < LINK_THRESHOLD) {\n // Already linked: move next annotation's start together\n const newNextStart = Math.min(nextAnnotation.end - 0.1, nextAnnotation.start + actualDelta);\n updatedAnnotations[activeIndex + 1] = {\n ...nextAnnotation,\n start: newNextStart,\n };\n\n // Cascade linked endpoints\n let currentIndex = activeIndex + 1;\n while (currentIndex < updatedAnnotations.length - 1) {\n const current = updatedAnnotations[currentIndex];\n const next = updatedAnnotations[currentIndex + 1];\n\n if (Math.abs(next.start - annotations[currentIndex].end) < LINK_THRESHOLD) {\n const nextDelta = current.end - annotations[currentIndex].end;\n updatedAnnotations[currentIndex + 1] = {\n ...next,\n start: Math.min(next.end - 0.1, next.start + nextDelta),\n };\n currentIndex++;\n } else {\n break;\n }\n }\n }\n } else if (!linkEndpoints && activeIndex < annotations.length - 1) {\n // Non-linked mode: don't overlap next annotation\n const nextAnnotation = updatedAnnotations[activeIndex + 1];\n if (newEnd > nextAnnotation.start) {\n // Push forward next annotation's start\n updatedAnnotations[activeIndex + 1] = {\n ...nextAnnotation,\n start: newEnd,\n };\n\n // Cascade collisions\n let currentIndex = activeIndex + 1;\n while (currentIndex < updatedAnnotations.length - 1) {\n const current = updatedAnnotations[currentIndex];\n const next = updatedAnnotations[currentIndex + 1];\n\n if (current.end > next.start) {\n updatedAnnotations[currentIndex + 1] = {\n ...next,\n start: current.end,\n };\n currentIndex++;\n } else {\n break;\n }\n }\n }\n }\n\n onAnnotationsChange(updatedAnnotations);\n },\n [annotations, activeIndex, duration, linkEndpoints, onAnnotationsChange]\n );\n\n // Navigation functions\n const selectPrevious = useCallback(() => {\n if (!onActiveAnnotationChange || annotations.length === 0) return;\n\n if (activeIndex <= 0) {\n // If no selection or at first, select last annotation\n onActiveAnnotationChange(annotations[annotations.length - 1].id);\n } else {\n onActiveAnnotationChange(annotations[activeIndex - 1].id);\n }\n }, [annotations, activeIndex, onActiveAnnotationChange]);\n\n const selectNext = useCallback(() => {\n if (!onActiveAnnotationChange || annotations.length === 0) return;\n\n if (activeIndex < 0 || activeIndex >= annotations.length - 1) {\n // If no selection or at last, select first annotation\n onActiveAnnotationChange(annotations[0].id);\n } else {\n onActiveAnnotationChange(annotations[activeIndex + 1].id);\n }\n }, [annotations, activeIndex, onActiveAnnotationChange]);\n\n const selectFirst = useCallback(() => {\n if (!onActiveAnnotationChange || annotations.length === 0) return;\n onActiveAnnotationChange(annotations[0].id);\n }, [annotations, onActiveAnnotationChange]);\n\n const selectLast = useCallback(() => {\n if (!onActiveAnnotationChange || annotations.length === 0) return;\n onActiveAnnotationChange(annotations[annotations.length - 1].id);\n }, [annotations, onActiveAnnotationChange]);\n\n const clearSelection = useCallback(() => {\n if (!onActiveAnnotationChange) return;\n onActiveAnnotationChange(null);\n }, [onActiveAnnotationChange]);\n\n // Play the currently selected annotation\n const playActiveAnnotation = useCallback(() => {\n if (activeIndex < 0 || !onPlay) return;\n\n const annotation = annotations[activeIndex];\n // If continuous play is off, play just this annotation's duration\n const playDuration = !continuousPlay ? annotation.end - annotation.start : undefined;\n onPlay(annotation.start, playDuration);\n }, [annotations, activeIndex, continuousPlay, onPlay]);\n\n // Shortcuts that require an active annotation (boundary editing + playback)\n const activeAnnotationShortcuts = useMemo(\n () => [\n {\n key: '[',\n action: () => moveStartBoundary(-TIME_DELTA),\n description: 'Move annotation start earlier',\n preventDefault: true,\n },\n {\n key: ']',\n action: () => moveStartBoundary(TIME_DELTA),\n description: 'Move annotation start later',\n preventDefault: true,\n },\n {\n key: '{',\n shiftKey: true,\n action: () => moveEndBoundary(-TIME_DELTA),\n description: 'Move annotation end earlier',\n preventDefault: true,\n },\n {\n key: '}',\n shiftKey: true,\n action: () => moveEndBoundary(TIME_DELTA),\n description: 'Move annotation end later',\n preventDefault: true,\n },\n {\n key: 'Enter',\n action: playActiveAnnotation,\n description: 'Play selected annotation',\n preventDefault: true,\n },\n ],\n [moveStartBoundary, moveEndBoundary, playActiveAnnotation]\n );\n\n // Navigation shortcuts (always active when enabled and there are annotations)\n const navigationShortcuts = useMemo(\n () => [\n {\n key: 'ArrowUp',\n action: selectPrevious,\n description: 'Select previous annotation',\n preventDefault: true,\n },\n {\n key: 'ArrowLeft',\n action: selectPrevious,\n description: 'Select previous annotation',\n preventDefault: true,\n },\n {\n key: 'ArrowDown',\n action: selectNext,\n description: 'Select next annotation',\n preventDefault: true,\n },\n {\n key: 'ArrowRight',\n action: selectNext,\n description: 'Select next annotation',\n preventDefault: true,\n },\n {\n key: 'Home',\n action: selectFirst,\n description: 'Select first annotation',\n preventDefault: true,\n },\n {\n key: 'End',\n action: selectLast,\n description: 'Select last annotation',\n preventDefault: true,\n },\n {\n key: 'Escape',\n action: clearSelection,\n description: 'Deselect annotation',\n preventDefault: true,\n },\n ],\n [selectPrevious, selectNext, selectFirst, selectLast, clearSelection]\n );\n\n // Active annotation shortcuts only work when an annotation is selected\n useKeyboardShortcuts({\n shortcuts: activeAnnotationShortcuts,\n enabled: enabled && activeIndex >= 0,\n });\n\n // Navigation shortcuts work whenever there are annotations\n useKeyboardShortcuts({\n shortcuts: navigationShortcuts,\n enabled: enabled && annotations.length > 0 && !!onActiveAnnotationChange,\n });\n\n return {\n moveStartBoundary,\n moveEndBoundary,\n selectPrevious,\n selectNext,\n selectFirst,\n selectLast,\n clearSelection,\n scrollToAnnotation,\n playActiveAnnotation,\n };\n}\n","// src/hooks/useRecording.ts\nimport { useState, useRef, useCallback, useEffect } from \"react\";\n\n// src/utils/audioBufferUtils.ts\nfunction concatenateAudioData(chunks) {\n const totalLength = chunks.reduce((sum, chunk) => sum + chunk.length, 0);\n const result = new Float32Array(totalLength);\n let offset = 0;\n for (const chunk of chunks) {\n result.set(chunk, offset);\n offset += chunk.length;\n }\n return result;\n}\nfunction createAudioBuffer(audioContext, samples, sampleRate, channelCount = 1) {\n const buffer = audioContext.createBuffer(\n channelCount,\n samples.length,\n sampleRate\n );\n const typedSamples = new Float32Array(samples);\n buffer.copyToChannel(typedSamples, 0);\n return buffer;\n}\n\n// src/utils/peaksGenerator.ts\nfunction generatePeaks(samples, samplesPerPixel, bits = 16) {\n const numPeaks = Math.ceil(samples.length / samplesPerPixel);\n const peakArray = bits === 8 ? new Int8Array(numPeaks * 2) : new Int16Array(numPeaks * 2);\n const maxValue = 2 ** (bits - 1);\n for (let i = 0; i < numPeaks; i++) {\n const start = i * samplesPerPixel;\n const end = Math.min(start + samplesPerPixel, samples.length);\n let min = 0;\n let max = 0;\n for (let j = start; j < end; j++) {\n const value = samples[j];\n if (value < min) min = value;\n if (value > max) max = value;\n }\n peakArray[i * 2] = Math.floor(min * maxValue);\n peakArray[i * 2 + 1] = Math.floor(max * maxValue);\n }\n return peakArray;\n}\nfunction appendPeaks(existingPeaks, newSamples, samplesPerPixel, totalSamplesProcessed, bits = 16) {\n const maxValue = 2 ** (bits - 1);\n const remainder = totalSamplesProcessed % samplesPerPixel;\n let offset = 0;\n if (remainder > 0 && existingPeaks.length > 0) {\n const samplesToComplete = samplesPerPixel - remainder;\n const endIndex = Math.min(samplesToComplete, newSamples.length);\n let min = existingPeaks[existingPeaks.length - 2] / maxValue;\n let max = existingPeaks[existingPeaks.length - 1] / maxValue;\n for (let i = 0; i < endIndex; i++) {\n const value = newSamples[i];\n if (value < min) min = value;\n if (value > max) max = value;\n }\n const updated = new (bits === 8 ? Int8Array : Int16Array)(existingPeaks.length);\n updated.set(existingPeaks);\n updated[existingPeaks.length - 2] = Math.floor(min * maxValue);\n updated[existingPeaks.length - 1] = Math.floor(max * maxValue);\n offset = endIndex;\n const newPeaks2 = generatePeaks(newSamples.slice(offset), samplesPerPixel, bits);\n const result2 = new (bits === 8 ? Int8Array : Int16Array)(updated.length + newPeaks2.length);\n result2.set(updated);\n result2.set(newPeaks2, updated.length);\n return result2;\n }\n const newPeaks = generatePeaks(newSamples.slice(offset), samplesPerPixel, bits);\n const result = new (bits === 8 ? Int8Array : Int16Array)(existingPeaks.length + newPeaks.length);\n result.set(existingPeaks);\n result.set(newPeaks, existingPeaks.length);\n return result;\n}\n\n// src/hooks/useRecording.ts\nimport { getContext } from \"tone\";\nfunction useRecording(stream, options = {}) {\n const {\n channelCount = 1,\n samplesPerPixel = 1024\n } = options;\n const [isRecording, setIsRecording] = useState(false);\n const [isPaused, setIsPaused] = useState(false);\n const [duration, setDuration] = useState(0);\n const [peaks, setPeaks] = useState(new Int16Array(0));\n const [audioBuffer, setAudioBuffer] = useState(null);\n const [error, setError] = useState(null);\n const [level, setLevel] = useState(0);\n const [peakLevel, setPeakLevel] = useState(0);\n const bits = 16;\n const workletLoadedRef = useRef(false);\n const workletNodeRef = useRef(null);\n const mediaStreamSourceRef = useRef(null);\n const recordedChunksRef = useRef([]);\n const totalSamplesRef = useRef(0);\n const animationFrameRef = useRef(null);\n const startTimeRef = useRef(0);\n const isRecordingRef = useRef(false);\n const isPausedRef = useRef(false);\n const loadWorklet = useCallback(async () => {\n if (workletLoadedRef.current) {\n return;\n }\n try {\n const context = getContext();\n const workletUrl = new URL(\n \"./worklet/recording-processor.worklet.js\",\n import.meta.url\n ).href;\n await context.addAudioWorkletModule(workletUrl);\n workletLoadedRef.current = true;\n } catch (err) {\n console.error(\"Failed to load AudioWorklet module:\", err);\n throw new Error(\"Failed to load recording processor\");\n }\n }, []);\n const startRecording = useCallback(async () => {\n if (!stream) {\n setError(new Error(\"No microphone stream available\"));\n return;\n }\n try {\n setError(null);\n const context = getContext();\n if (context.state === \"suspended\") {\n await context.resume();\n }\n await loadWorklet();\n const source = context.createMediaStreamSource(stream);\n mediaStreamSourceRef.current = source;\n const workletNode = context.createAudioWorkletNode(\"recording-processor\");\n workletNodeRef.current = workletNode;\n source.connect(workletNode);\n workletNode.port.onmessage = (event) => {\n const { samples } = event.data;\n recordedChunksRef.current.push(samples);\n totalSamplesRef.current += samples.length;\n setPeaks(\n (prevPeaks) => appendPeaks(\n prevPeaks,\n samples,\n samplesPerPixel,\n totalSamplesRef.current - samples.length,\n bits\n )\n );\n };\n workletNode.port.postMessage({\n command: \"start\",\n sampleRate: context.sampleRate,\n channelCount\n });\n recordedChunksRef.current = [];\n totalSamplesRef.current = 0;\n setPeaks(new Int16Array(0));\n setAudioBuffer(null);\n setLevel(0);\n setPeakLevel(0);\n isRecordingRef.current = true;\n isPausedRef.current = false;\n setIsRecording(true);\n setIsPaused(false);\n startTimeRef.current = performance.now();\n const updateDuration = () => {\n if (isRecordingRef.current && !isPausedRef.current) {\n const elapsed = (performance.now() - startTimeRef.current) / 1e3;\n setDuration(elapsed);\n animationFrameRef.current = requestAnimationFrame(updateDuration);\n }\n };\n updateDuration();\n } catch (err) {\n console.error(\"Failed to start recording:\", err);\n setError(err instanceof Error ? err : new Error(\"Failed to start recording\"));\n }\n }, [stream, channelCount, samplesPerPixel, loadWorklet, isRecording, isPaused]);\n const stopRecording = useCallback(async () => {\n if (!isRecording) {\n return null;\n }\n try {\n if (workletNodeRef.current) {\n workletNodeRef.current.port.postMessage({ command: \"stop\" });\n if (mediaStreamSourceRef.current) {\n try {\n mediaStreamSourceRef.current.disconnect(workletNodeRef.current);\n } catch (e) {\n }\n }\n workletNodeRef.current.disconnect();\n }\n if (animationFrameRef.current !== null) {\n cancelAnimationFrame(animationFrameRef.current);\n animationFrameRef.current = null;\n }\n const allSamples = concatenateAudioData(recordedChunksRef.current);\n const context = getContext();\n const rawContext = context.rawContext;\n const buffer = createAudioBuffer(\n rawContext,\n allSamples,\n rawContext.sampleRate,\n channelCount\n );\n setAudioBuffer(buffer);\n setDuration(buffer.duration);\n isRecordingRef.current = false;\n isPausedRef.current = false;\n setIsRecording(false);\n setIsPaused(false);\n setLevel(0);\n return buffer;\n } catch (err) {\n console.error(\"Failed to stop recording:\", err);\n setError(err instanceof Error ? err : new Error(\"Failed to stop recording\"));\n return null;\n }\n }, [isRecording, channelCount]);\n const pauseRecording = useCallback(() => {\n if (isRecording && !isPaused) {\n if (animationFrameRef.current !== null) {\n cancelAnimationFrame(animationFrameRef.current);\n animationFrameRef.current = null;\n }\n isPausedRef.current = true;\n setIsPaused(true);\n }\n }, [isRecording, isPaused]);\n const resumeRecording = useCallback(() => {\n if (isRecording && isPaused) {\n isPausedRef.current = false;\n setIsPaused(false);\n startTimeRef.current = performance.now() - duration * 1e3;\n const updateDuration = () => {\n if (isRecordingRef.current && !isPausedRef.current) {\n const elapsed = (performance.now() - startTimeRef.current) / 1e3;\n setDuration(elapsed);\n animationFrameRef.current = requestAnimationFrame(updateDuration);\n }\n };\n updateDuration();\n }\n }, [isRecording, isPaused, duration]);\n useEffect(() => {\n return () => {\n if (workletNodeRef.current) {\n workletNodeRef.current.port.postMessage({ command: \"stop\" });\n if (mediaStreamSourceRef.current) {\n try {\n mediaStreamSourceRef.current.disconnect(workletNodeRef.current);\n } catch (e) {\n }\n }\n workletNodeRef.current.disconnect();\n }\n if (animationFrameRef.current !== null) {\n cancelAnimationFrame(animationFrameRef.current);\n }\n };\n }, []);\n return {\n isRecording,\n isPaused,\n duration,\n peaks,\n audioBuffer,\n level,\n peakLevel,\n startRecording,\n stopRecording,\n pauseRecording,\n resumeRecording,\n error\n };\n}\n\n// src/hooks/useMicrophoneAccess.ts\nimport { useState as useState2, useEffect as useEffect2, useCallback as useCallback2 } from \"react\";\nfunction useMicrophoneAccess() {\n const [stream, setStream] = useState2(null);\n const [devices, setDevices] = useState2([]);\n const [hasPermission, setHasPermission] = useState2(false);\n const [isLoading, setIsLoading] = useState2(false);\n const [error, setError] = useState2(null);\n const enumerateDevices = useCallback2(async () => {\n try {\n const allDevices = await navigator.mediaDevices.enumerateDevices();\n const audioInputs = allDevices.filter((device) => device.kind === \"audioinput\").map((device) => ({\n deviceId: device.deviceId,\n label: device.label || `Microphone ${device.deviceId.slice(0, 8)}`,\n groupId: device.groupId\n }));\n setDevices(audioInputs);\n } catch (err) {\n console.error(\"Failed to enumerate devices:\", err);\n setError(err instanceof Error ? err : new Error(\"Failed to enumerate devices\"));\n }\n }, []);\n const requestAccess = useCallback2(async (deviceId, audioConstraints) => {\n setIsLoading(true);\n setError(null);\n try {\n if (stream) {\n stream.getTracks().forEach((track) => track.stop());\n }\n const audio = {\n // Recording-optimized defaults: prioritize raw audio quality and low latency\n echoCancellation: false,\n noiseSuppression: false,\n autoGainControl: false,\n latency: 0,\n // Low latency mode (not in TS types yet, but supported in modern browsers)\n // User-provided constraints override defaults\n ...audioConstraints,\n // Device ID override (if specified)\n ...deviceId && { deviceId: { exact: deviceId } }\n };\n const constraints = {\n audio,\n video: false\n };\n const newStream = await navigator.mediaDevices.getUserMedia(constraints);\n setStream(newStream);\n setHasPermission(true);\n await enumerateDevices();\n } catch (err) {\n console.error(\"Failed to access microphone:\", err);\n setError(\n err instanceof Error ? err : new Error(\"Failed to access microphone\")\n );\n setHasPermission(false);\n } finally {\n setIsLoading(false);\n }\n }, [stream, enumerateDevices]);\n const stopStream = useCallback2(() => {\n if (stream) {\n stream.getTracks().forEach((track) => track.stop());\n setStream(null);\n setHasPermission(false);\n }\n }, [stream]);\n useEffect2(() => {\n enumerateDevices();\n return () => {\n if (stream) {\n stream.getTracks().forEach((track) => track.stop());\n }\n };\n }, []);\n return {\n stream,\n devices,\n hasPermission,\n isLoading,\n requestAccess,\n stopStream,\n error\n };\n}\n\n// src/hooks/useMicrophoneLevel.ts\nimport { useEffect as useEffect3, useState as useState3, useRef as useRef2 } from \"react\";\nimport { Meter, getContext as getContext2, connect } from \"tone\";\nfunction useMicrophoneLevel(stream, options = {}) {\n const {\n updateRate = 60,\n smoothingTimeConstant = 0.8\n } = options;\n const [level, setLevel] = useState3(0);\n const [peakLevel, setPeakLevel] = useState3(0);\n const meterRef = useRef2(null);\n const sourceRef = useRef2(null);\n const animationFrameRef = useRef2(null);\n const resetPeak = () => setPeakLevel(0);\n useEffect3(() => {\n if (!stream) {\n setLevel(0);\n setPeakLevel(0);\n return;\n }\n let isMounted = true;\n const setupMonitoring = async () => {\n if (!isMounted) return;\n const context = getContext2();\n if (context.state === \"suspended\") {\n await context.resume();\n }\n if (!isMounted) return;\n const meter = new Meter({ smoothing: smoothingTimeConstant, context });\n meterRef.current = meter;\n const source = context.createMediaStreamSource(stream);\n sourceRef.current = source;\n connect(source, meter);\n const updateInterval = 1e3 / updateRate;\n let lastUpdateTime = 0;\n const updateLevel = (timestamp) => {\n if (!isMounted || !meterRef.current) return;\n if (timestamp - lastUpdateTime >= updateInterval) {\n lastUpdateTime = timestamp;\n const db = meterRef.current.getValue();\n const dbValue = typeof db === \"number\" ? db : db[0];\n const normalized = Math.max(0, Math.min(1, (dbValue + 100) / 100));\n setLevel(normalized);\n setPeakLevel((prev) => Math.max(prev, normalized));\n }\n animationFrameRef.current = requestAnimationFrame(updateLevel);\n };\n animationFrameRef.current = requestAnimationFrame(updateLevel);\n };\n setupMonitoring();\n return () => {\n isMounted = false;\n if (animationFrameRef.current) {\n cancelAnimationFrame(animationFrameRef.current);\n animationFrameRef.current = null;\n }\n if (sourceRef.current) {\n try {\n sourceRef.current.disconnect();\n } catch (e) {\n }\n sourceRef.current = null;\n }\n if (meterRef.current) {\n meterRef.current.dispose();\n meterRef.current = null;\n }\n };\n }, [stream, smoothingTimeConstant, updateRate]);\n return {\n level,\n peakLevel,\n resetPeak\n };\n}\n\n// src/components/RecordButton.tsx\nimport styled from \"styled-components\";\nimport { jsx, jsxs } from \"react/jsx-runtime\";\nvar Button = styled.button`\n padding: 0.5rem 1rem;\n font-size: 0.875rem;\n font-weight: 500;\n border: none;\n border-radius: 0.25rem;\n cursor: pointer;\n transition: all 0.2s ease-in-out;\n background: ${(props) => props.$isRecording ? \"#dc3545\" : \"#e74c3c\"};\n color: white;\n\n &:hover:not(:disabled) {\n background: ${(props) => props.$isRecording ? \"#c82333\" : \"#c0392b\"};\n transform: translateY(-1px);\n box-shadow: 0 2px 4px rgba(0, 0, 0, 0.2);\n }\n\n &:active:not(:disabled) {\n transform: translateY(0);\n }\n\n &:disabled {\n opacity: 0.5;\n cursor: not-allowed;\n }\n\n &:focus {\n outline: none;\n box-shadow: 0 0 0 3px rgba(231, 76, 60, 0.3);\n }\n`;\nvar RecordingIndicator = styled.span`\n display: inline-block;\n width: 8px;\n height: 8px;\n border-radius: 50%;\n background: white;\n margin-right: 0.5rem;\n animation: pulse 1.5s ease-in-out infinite;\n\n @keyframes pulse {\n 0%,\n 100% {\n opacity: 1;\n }\n 50% {\n opacity: 0.3;\n }\n }\n`;\nvar RecordButton = ({\n isRecording,\n onClick,\n disabled = false,\n className\n}) => {\n return /* @__PURE__ */ jsxs(\n Button,\n {\n $isRecording: isRecording,\n onClick,\n disabled,\n className,\n \"aria-label\": isRecording ? \"Stop recording\" : \"Start recording\",\n children: [\n isRecording && /* @__PURE__ */ jsx(RecordingIndicator, {}),\n isRecording ? \"Stop Recording\" : \"Record\"\n ]\n }\n );\n};\n\n// src/components/MicrophoneSelector.tsx\nimport styled2 from \"styled-components\";\nimport { BaseSelect, BaseLabel } from \"@waveform-playlist/ui-components\";\nimport { jsx as jsx2, jsxs as jsxs2 } from \"react/jsx-runtime\";\nvar Select = styled2(BaseSelect)`\n min-width: 200px;\n`;\nvar Label = styled2(BaseLabel)`\n display: flex;\n flex-direction: column;\n gap: 0.25rem;\n`;\nvar MicrophoneSelector = ({\n devices,\n selectedDeviceId,\n onDeviceChange,\n disabled = false,\n className\n}) => {\n const handleChange = (event) => {\n onDeviceChange(event.target.value);\n };\n const currentValue = selectedDeviceId || (devices.length > 0 ? devices[0].deviceId : \"\");\n return /* @__PURE__ */ jsxs2(Label, { className, children: [\n \"Microphone\",\n /* @__PURE__ */ jsx2(\n Select,\n {\n value: currentValue,\n onChange: handleChange,\n disabled: disabled || devices.length === 0,\n children: devices.length === 0 ? /* @__PURE__ */ jsx2(\"option\", { value: \"\", children: \"No microphones found\" }) : devices.map((device) => /* @__PURE__ */ jsx2(\"option\", { value: device.deviceId, children: device.label }, device.deviceId))\n }\n )\n ] });\n};\n\n// src/components/RecordingIndicator.tsx\nimport styled3 from \"styled-components\";\nimport { jsx as jsx3, jsxs as jsxs3 } from \"react/jsx-runtime\";\nvar Container = styled3.div`\n display: flex;\n align-items: center;\n gap: 0.75rem;\n padding: 0.5rem 0.75rem;\n background: ${(props) => props.$isRecording ? \"#fff3cd\" : \"transparent\"};\n border-radius: 0.25rem;\n transition: background 0.2s ease-in-out;\n`;\nvar Dot = styled3.div`\n width: 12px;\n height: 12px;\n border-radius: 50%;\n background: ${(props) => props.$isPaused ? \"#ffc107\" : \"#dc3545\"};\n opacity: ${(props) => props.$isRecording ? 1 : 0};\n transition: opacity 0.2s ease-in-out;\n\n ${(props) => props.$isRecording && !props.$isPaused && `\n animation: blink 1.5s ease-in-out infinite;\n\n @keyframes blink {\n 0%, 100% {\n opacity: 1;\n }\n 50% {\n opacity: 0.3;\n }\n }\n `}\n`;\nvar Duration = styled3.span`\n font-family: 'Courier New', Monaco, monospace;\n font-size: 1rem;\n font-weight: 600;\n color: #495057;\n min-width: 70px;\n`;\nvar Status = styled3.span`\n font-size: 0.75rem;\n font-weight: 500;\n color: ${(props) => props.$isPaused ? \"#ffc107\" : \"#dc3545\"};\n text-transform: uppercase;\n`;\nvar defaultFormatTime = (seconds) => {\n const mins = Math.floor(seconds / 60);\n const secs = Math.floor(seconds % 60);\n return `${mins.toString().padStart(2, \"0\")}:${secs.toString().padStart(2, \"0\")}`;\n};\nvar RecordingIndicator2 = ({\n isRecording,\n isPaused = false,\n duration,\n formatTime = defaultFormatTime,\n className\n}) => {\n return /* @__PURE__ */ jsxs3(Container, { $isRecording: isRecording, className, children: [\n /* @__PURE__ */ jsx3(Dot, { $isRecording: isRecording, $isPaused: isPaused }),\n /* @__PURE__ */ jsx3(Duration, { children: formatTime(duration) }),\n isRecording && /* @__PURE__ */ jsx3(Status, { $isPaused: isPaused, children: isPaused ? \"Paused\" : \"Recording\" })\n ] });\n};\n\n// src/components/VUMeter.tsx\nimport React from \"react\";\nimport styled4 from \"styled-components\";\nimport { jsx as jsx4, jsxs as jsxs4 } from \"react/jsx-runtime\";\nvar MeterContainer = styled4.div`\n position: relative;\n width: ${(props) => props.$width}px;\n height: ${(props) => props.$height}px;\n background: #2c3e50;\n border-radius: 4px;\n overflow: hidden;\n box-shadow: inset 0 2px 4px rgba(0, 0, 0, 0.3);\n`;\nvar getLevelGradient = (level) => {\n if (level < 0.6) return \"linear-gradient(90deg, #27ae60, #2ecc71)\";\n if (level < 0.85) return \"linear-gradient(90deg, #f39c12, #f1c40f)\";\n return \"linear-gradient(90deg, #c0392b, #e74c3c)\";\n};\nvar MeterFill = styled4.div.attrs((props) => ({\n style: {\n width: `${props.$level * 100}%`,\n height: `${props.$height}px`,\n background: getLevelGradient(props.$level),\n boxShadow: props.$level > 0.01 ? \"0 0 8px rgba(255, 255, 255, 0.3)\" : \"none\"\n }\n}))`\n position: absolute;\n left: 0;\n top: 0;\n transition: width 0.05s ease-out, background 0.1s ease-out;\n`;\nvar PeakIndicator = styled4.div.attrs((props) => ({\n style: {\n left: `${props.$peakLevel * 100}%`,\n height: `${props.$height}px`\n }\n}))`\n position: absolute;\n top: 0;\n width: 2px;\n background: #ecf0f1;\n box-shadow: 0 0 4px rgba(236, 240, 241, 0.8);\n transition: left 0.1s ease-out;\n`;\nvar ScaleMarkers = styled4.div`\n position: absolute;\n top: 0;\n left: 0;\n width: 100%;\n height: ${(props) => props.$height}px;\n pointer-events: none;\n`;\nvar ScaleMark = styled4.div`\n position: absolute;\n left: ${(props) => props.$position}%;\n top: 0;\n width: 1px;\n height: ${(props) => props.$height}px;\n background: rgba(255, 255, 255, 0.2);\n`;\nvar VUMeterComponent = ({\n level,\n peakLevel,\n width = 200,\n height = 20,\n className\n}) => {\n const clampedLevel = Math.max(0, Math.min(1, level));\n const clampedPeak = peakLevel !== void 0 ? Math.max(0, Math.min(1, peakLevel)) : 0;\n return /* @__PURE__ */ jsxs4(MeterContainer, { $width: width, $height: height, className, children: [\n /* @__PURE__ */ jsx4(MeterFill, { $level: clampedLevel, $height: height }),\n peakLevel !== void 0 && clampedPeak > 0 && /* @__PURE__ */ jsx4(PeakIndicator, { $peakLevel: clampedPeak, $height: height }),\n /* @__PURE__ */ jsxs4(ScaleMarkers, { $height: height, children: [\n /* @__PURE__ */ jsx4(ScaleMark, { $position: 60, $height: height }),\n /* @__PURE__ */ jsx4(ScaleMark, { $position: 85, $height: height })\n ] })\n ] });\n};\nvar VUMeter = React.memo(VUMeterComponent);\nexport {\n MicrophoneSelector,\n RecordButton,\n RecordingIndicator2 as RecordingIndicator,\n VUMeter,\n concatenateAudioData,\n createAudioBuffer,\n generatePeaks,\n useMicrophoneAccess,\n useMicrophoneLevel,\n useRecording\n};\n//# sourceMappingURL=index.mjs.map","/**\n * Hook for integrated multi-track recording\n * Combines recording functionality with track management\n */\n\nimport { useState, useCallback, useEffect } from 'react';\nimport {\n useRecording,\n useMicrophoneAccess,\n useMicrophoneLevel,\n type MicrophoneDevice,\n} from '@waveform-playlist/recording';\nimport { type ClipTrack, type AudioClip } from '@waveform-playlist/core';\nimport { resumeGlobalAudioContext } from '@waveform-playlist/playout';\n\nexport interface IntegratedRecordingOptions {\n /**\n * Current playback/cursor position in seconds\n * Recording will start from max(currentTime, lastClipEndTime)\n */\n currentTime?: number;\n\n /**\n * MediaTrackConstraints for audio recording\n * These will override the recording-optimized defaults (echo cancellation off, low latency)\n */\n audioConstraints?: MediaTrackConstraints;\n\n /**\n * Number of channels to record (1 = mono, 2 = stereo)\n * Default: 1 (mono)\n */\n channelCount?: number;\n\n /**\n * Samples per pixel for peak generation\n * Default: 1024\n */\n samplesPerPixel?: number;\n}\n\nexport interface UseIntegratedRecordingReturn {\n // Recording state\n isRecording: boolean;\n isPaused: boolean;\n duration: number;\n level: number;\n peakLevel: number;\n error: Error | null;\n\n // Microphone state\n stream: MediaStream | null;\n devices: MicrophoneDevice[];\n hasPermission: boolean;\n selectedDevice: string | null;\n\n // Recording controls\n startRecording: () => void;\n stopRecording: () => void;\n pauseRecording: () => void;\n resumeRecording: () => void;\n requestMicAccess: () => Promise<void>;\n changeDevice: (deviceId: string) => Promise<void>;\n\n // Track state (for live waveform during recording)\n recordingPeaks: Int8Array | Int16Array;\n}\n\nexport function useIntegratedRecording(\n tracks: ClipTrack[],\n setTracks: (tracks: ClipTrack[]) => void,\n selectedTrackId: string | null,\n options: IntegratedRecordingOptions = {}\n): UseIntegratedRecordingReturn {\n const { currentTime = 0, audioConstraints, ...recordingOptions } = options;\n\n // Track if we're currently monitoring (for auto-resume audio context)\n const [isMonitoring, setIsMonitoring] = useState(false);\n const [selectedDevice, setSelectedDevice] = useState<string | null>(null);\n\n // Microphone access\n const {\n stream,\n devices,\n hasPermission,\n requestAccess,\n error: micError,\n } = useMicrophoneAccess();\n\n // Microphone level (for VU meter)\n const { level, peakLevel } = useMicrophoneLevel(stream);\n\n // Recording\n const {\n isRecording,\n isPaused,\n duration,\n peaks,\n audioBuffer: _audioBuffer,\n startRecording: startRec,\n stopRecording: stopRec,\n pauseRecording,\n resumeRecording,\n error: recError,\n } = useRecording(stream, recordingOptions);\n\n // Start recording handler\n const startRecording = useCallback(async () => {\n if (!selectedTrackId) {\n // No track selected - UI should handle creating/selecting track before calling this\n return;\n }\n\n // Resume audio context if needed\n if (!isMonitoring) {\n await resumeGlobalAudioContext();\n setIsMonitoring(true);\n }\n\n await startRec();\n }, [selectedTrackId, isMonitoring, startRec]);\n\n // Stop recording and add clip to selected track\n const stopRecording = useCallback(async () => {\n const buffer = await stopRec();\n\n // Add clip to track after recording completes\n if (buffer && selectedTrackId) {\n const selectedTrackIndex = tracks.findIndex(t => t.id === selectedTrackId);\n if (selectedTrackIndex === -1) return;\n\n const selectedTrack = tracks[selectedTrackIndex];\n\n // Calculate start position: max(currentTime, lastClipEndTime)\n const currentTimeSamples = Math.floor(currentTime * buffer.sampleRate);\n\n let lastClipEndSample = 0;\n if (selectedTrack.clips.length > 0) {\n // Find the end time of the last clip (in samples)\n const endSamples = selectedTrack.clips.map(clip =>\n clip.startSample + clip.durationSamples\n );\n lastClipEndSample = Math.max(...endSamples);\n }\n\n // Use whichever is greater: cursor position or last clip end\n const startSample = Math.max(currentTimeSamples, lastClipEndSample);\n\n // Create new clip from recording\n const newClip: AudioClip = {\n id: `clip-${Date.now()}`,\n audioBuffer: buffer,\n startSample,\n durationSamples: buffer.length,\n offsetSamples: 0,\n sampleRate: buffer.sampleRate,\n sourceDurationSamples: buffer.length,\n gain: 1.0,\n name: `Recording ${new Date().toLocaleTimeString()}`,\n };\n\n // Add clip to track\n const newTracks = tracks.map((track, index) => {\n if (index === selectedTrackIndex) {\n return {\n ...track,\n clips: [...track.clips, newClip],\n };\n }\n return track;\n });\n\n setTracks(newTracks);\n }\n }, [selectedTrackId, tracks, setTracks, currentTime, stopRec]);\n\n // Auto-select the first device when devices become available\n useEffect(() => {\n // Only auto-select if we have permission, devices are available, and nothing is selected yet\n if (hasPermission && devices.length > 0 && selectedDevice === null) {\n setSelectedDevice(devices[0].deviceId);\n }\n }, [hasPermission, devices.length]); // Intentionally not including selectedDevice to avoid re-triggering\n\n // Request microphone access\n const requestMicAccess = useCallback(async () => {\n await requestAccess(undefined, audioConstraints);\n await resumeGlobalAudioContext();\n setIsMonitoring(true);\n }, [requestAccess, audioConstraints]);\n\n // Change device\n const changeDevice = useCallback(async (deviceId: string) => {\n setSelectedDevice(deviceId);\n await requestAccess(deviceId, audioConstraints);\n await resumeGlobalAudioContext();\n setIsMonitoring(true);\n }, [requestAccess, audioConstraints]);\n\n return {\n // Recording state\n isRecording,\n isPaused,\n duration,\n level,\n peakLevel,\n error: micError || recError,\n\n // Microphone state\n stream,\n devices,\n hasPermission,\n selectedDevice,\n\n // Recording controls\n startRecording,\n stopRecording,\n pauseRecording,\n resumeRecording,\n requestMicAccess,\n changeDevice,\n\n // Track state\n recordingPeaks: peaks,\n };\n}\n","/**\n * Effect definitions for all available Tone.js effects\n * Each effect has parameters with min/max/default values for UI controls\n */\n\nexport type ParameterType = 'number' | 'select' | 'boolean';\n\nexport interface EffectParameter {\n name: string;\n label: string;\n type: ParameterType;\n min?: number;\n max?: number;\n step?: number;\n default: number | string | boolean;\n unit?: string;\n options?: { value: string | number; label: string }[];\n}\n\nexport interface EffectDefinition {\n id: string;\n name: string;\n category: 'delay' | 'reverb' | 'modulation' | 'distortion' | 'filter' | 'dynamics' | 'spatial';\n description: string;\n parameters: EffectParameter[];\n}\n\nexport const effectDefinitions: EffectDefinition[] = [\n // === REVERB EFFECTS ===\n {\n id: 'reverb',\n name: 'Reverb',\n category: 'reverb',\n description: 'Simple convolution reverb with adjustable decay time',\n parameters: [\n { name: 'decay', label: 'Decay', type: 'number', min: 0.1, max: 10, step: 0.1, default: 1.5, unit: 's' },\n { name: 'wet', label: 'Mix', type: 'number', min: 0, max: 1, step: 0.01, default: 0.5 },\n ],\n },\n {\n id: 'freeverb',\n name: 'Freeverb',\n category: 'reverb',\n description: 'Classic Schroeder/Moorer reverb with room size and dampening',\n parameters: [\n { name: 'roomSize', label: 'Room Size', type: 'number', min: 0, max: 1, step: 0.01, default: 0.7 },\n { name: 'dampening', label: 'Dampening', type: 'number', min: 0, max: 10000, step: 100, default: 3000, unit: 'Hz' },\n { name: 'wet', label: 'Mix', type: 'number', min: 0, max: 1, step: 0.01, default: 0.5 },\n ],\n },\n {\n id: 'jcReverb',\n name: 'JC Reverb',\n category: 'reverb',\n description: 'Attempt at Roland JC-120 chorus reverb emulation',\n parameters: [\n { name: 'roomSize', label: 'Room Size', type: 'number', min: 0, max: 1, step: 0.01, default: 0.5 },\n { name: 'wet', label: 'Mix', type: 'number', min: 0, max: 1, step: 0.01, default: 0.5 },\n ],\n },\n\n // === DELAY EFFECTS ===\n {\n id: 'feedbackDelay',\n name: 'Feedback Delay',\n category: 'delay',\n description: 'Delay line with feedback for echo effects',\n parameters: [\n { name: 'delayTime', label: 'Delay Time', type: 'number', min: 0, max: 1, step: 0.01, default: 0.25, unit: 's' },\n { name: 'feedback', label: 'Feedback', type: 'number', min: 0, max: 0.95, step: 0.01, default: 0.5 },\n { name: 'wet', label: 'Mix', type: 'number', min: 0, max: 1, step: 0.01, default: 0.5 },\n ],\n },\n {\n id: 'pingPongDelay',\n name: 'Ping Pong Delay',\n category: 'delay',\n description: 'Stereo delay bouncing between left and right channels',\n parameters: [\n { name: 'delayTime', label: 'Delay Time', type: 'number', min: 0, max: 1, step: 0.01, default: 0.25, unit: 's' },\n { name: 'feedback', label: 'Feedback', type: 'number', min: 0, max: 0.95, step: 0.01, default: 0.5 },\n { name: 'wet', label: 'Mix', type: 'number', min: 0, max: 1, step: 0.01, default: 0.5 },\n ],\n },\n\n // === MODULATION EFFECTS ===\n {\n id: 'chorus',\n name: 'Chorus',\n category: 'modulation',\n description: 'Creates thickness by layering detuned copies of the signal',\n parameters: [\n { name: 'frequency', label: 'Rate', type: 'number', min: 0.1, max: 10, step: 0.1, default: 1.5, unit: 'Hz' },\n { name: 'delayTime', label: 'Delay', type: 'number', min: 0, max: 20, step: 0.5, default: 3.5, unit: 'ms' },\n { name: 'depth', label: 'Depth', type: 'number', min: 0, max: 1, step: 0.01, default: 0.7 },\n { name: 'wet', label: 'Mix', type: 'number', min: 0, max: 1, step: 0.01, default: 0.5 },\n ],\n },\n {\n id: 'phaser',\n name: 'Phaser',\n category: 'modulation',\n description: 'Classic phaser effect using allpass filters',\n parameters: [\n { name: 'frequency', label: 'Rate', type: 'number', min: 0.1, max: 10, step: 0.1, default: 0.5, unit: 'Hz' },\n { name: 'octaves', label: 'Octaves', type: 'number', min: 1, max: 6, step: 1, default: 3 },\n { name: 'baseFrequency', label: 'Base Freq', type: 'number', min: 100, max: 2000, step: 10, default: 350, unit: 'Hz' },\n { name: 'wet', label: 'Mix', type: 'number', min: 0, max: 1, step: 0.01, default: 0.5 },\n ],\n },\n {\n id: 'tremolo',\n name: 'Tremolo',\n category: 'modulation',\n description: 'Rhythmic volume modulation',\n parameters: [\n { name: 'frequency', label: 'Rate', type: 'number', min: 0.1, max: 20, step: 0.1, default: 4, unit: 'Hz' },\n { name: 'depth', label: 'Depth', type: 'number', min: 0, max: 1, step: 0.01, default: 0.5 },\n { name: 'wet', label: 'Mix', type: 'number', min: 0, max: 1, step: 0.01, default: 1 },\n ],\n },\n {\n id: 'vibrato',\n name: 'Vibrato',\n category: 'modulation',\n description: 'Pitch modulation effect',\n parameters: [\n { name: 'frequency', label: 'Rate', type: 'number', min: 0.1, max: 20, step: 0.1, default: 5, unit: 'Hz' },\n { name: 'depth', label: 'Depth', type: 'number', min: 0, max: 1, step: 0.01, default: 0.1 },\n { name: 'wet', label: 'Mix', type: 'number', min: 0, max: 1, step: 0.01, default: 1 },\n ],\n },\n {\n id: 'autoPanner',\n name: 'Auto Panner',\n category: 'modulation',\n description: 'Automatic left-right panning',\n parameters: [\n { name: 'frequency', label: 'Rate', type: 'number', min: 0.1, max: 10, step: 0.1, default: 1, unit: 'Hz' },\n { name: 'depth', label: 'Depth', type: 'number', min: 0, max: 1, step: 0.01, default: 1 },\n { name: 'wet', label: 'Mix', type: 'number', min: 0, max: 1, step: 0.01, default: 1 },\n ],\n },\n\n // === FILTER EFFECTS ===\n {\n id: 'autoFilter',\n name: 'Auto Filter',\n category: 'filter',\n description: 'Automated filter sweep with LFO',\n parameters: [\n { name: 'frequency', label: 'Rate', type: 'number', min: 0.1, max: 10, step: 0.1, default: 1, unit: 'Hz' },\n { name: 'baseFrequency', label: 'Base Freq', type: 'number', min: 20, max: 2000, step: 10, default: 200, unit: 'Hz' },\n { name: 'octaves', label: 'Octaves', type: 'number', min: 0.5, max: 8, step: 0.5, default: 2.6 },\n { name: 'depth', label: 'Depth', type: 'number', min: 0, max: 1, step: 0.01, default: 1 },\n { name: 'wet', label: 'Mix', type: 'number', min: 0, max: 1, step: 0.01, default: 1 },\n ],\n },\n {\n id: 'autoWah',\n name: 'Auto Wah',\n category: 'filter',\n description: 'Envelope follower filter effect',\n parameters: [\n { name: 'baseFrequency', label: 'Base Freq', type: 'number', min: 20, max: 500, step: 10, default: 100, unit: 'Hz' },\n { name: 'octaves', label: 'Octaves', type: 'number', min: 1, max: 8, step: 1, default: 6 },\n { name: 'sensitivity', label: 'Sensitivity', type: 'number', min: -40, max: 0, step: 1, default: 0, unit: 'dB' },\n { name: 'wet', label: 'Mix', type: 'number', min: 0, max: 1, step: 0.01, default: 1 },\n ],\n },\n {\n id: 'eq3',\n name: '3-Band EQ',\n category: 'filter',\n description: 'Three band equalizer with low, mid, and high controls',\n parameters: [\n { name: 'low', label: 'Low', type: 'number', min: -24, max: 24, step: 0.5, default: 0, unit: 'dB' },\n { name: 'mid', label: 'Mid', type: 'number', min: -24, max: 24, step: 0.5, default: 0, unit: 'dB' },\n { name: 'high', label: 'High', type: 'number', min: -24, max: 24, step: 0.5, default: 0, unit: 'dB' },\n { name: 'lowFrequency', label: 'Low Freq', type: 'number', min: 20, max: 500, step: 10, default: 400, unit: 'Hz' },\n { name: 'highFrequency', label: 'High Freq', type: 'number', min: 1000, max: 10000, step: 100, default: 2500, unit: 'Hz' },\n ],\n },\n\n // === DISTORTION EFFECTS ===\n {\n id: 'distortion',\n name: 'Distortion',\n category: 'distortion',\n description: 'Wave shaping distortion effect',\n parameters: [\n { name: 'distortion', label: 'Drive', type: 'number', min: 0, max: 1, step: 0.01, default: 0.4 },\n { name: 'wet', label: 'Mix', type: 'number', min: 0, max: 1, step: 0.01, default: 1 },\n ],\n },\n {\n id: 'bitCrusher',\n name: 'Bit Crusher',\n category: 'distortion',\n description: 'Reduces bit depth for lo-fi digital texture',\n parameters: [\n { name: 'bits', label: 'Bits', type: 'number', min: 1, max: 16, step: 1, default: 4 },\n { name: 'wet', label: 'Mix', type: 'number', min: 0, max: 1, step: 0.01, default: 1 },\n ],\n },\n {\n id: 'chebyshev',\n name: 'Chebyshev',\n category: 'distortion',\n description: 'Waveshaping distortion using Chebyshev polynomials',\n parameters: [\n { name: 'order', label: 'Order', type: 'number', min: 1, max: 100, step: 1, default: 50 },\n { name: 'wet', label: 'Mix', type: 'number', min: 0, max: 1, step: 0.01, default: 1 },\n ],\n },\n\n // === DYNAMICS EFFECTS ===\n {\n id: 'compressor',\n name: 'Compressor',\n category: 'dynamics',\n description: 'Dynamic range compressor',\n parameters: [\n { name: 'threshold', label: 'Threshold', type: 'number', min: -60, max: 0, step: 1, default: -24, unit: 'dB' },\n { name: 'ratio', label: 'Ratio', type: 'number', min: 1, max: 20, step: 0.5, default: 4 },\n { name: 'attack', label: 'Attack', type: 'number', min: 0, max: 1, step: 0.001, default: 0.003, unit: 's' },\n { name: 'release', label: 'Release', type: 'number', min: 0, max: 1, step: 0.01, default: 0.25, unit: 's' },\n { name: 'knee', label: 'Knee', type: 'number', min: 0, max: 40, step: 1, default: 30, unit: 'dB' },\n ],\n },\n {\n id: 'limiter',\n name: 'Limiter',\n category: 'dynamics',\n description: 'Hard limiter to prevent clipping',\n parameters: [\n { name: 'threshold', label: 'Threshold', type: 'number', min: -12, max: 0, step: 0.5, default: -6, unit: 'dB' },\n ],\n },\n {\n id: 'gate',\n name: 'Gate',\n category: 'dynamics',\n description: 'Noise gate to silence signal below threshold',\n parameters: [\n { name: 'threshold', label: 'Threshold', type: 'number', min: -100, max: 0, step: 1, default: -40, unit: 'dB' },\n { name: 'attack', label: 'Attack', type: 'number', min: 0, max: 0.3, step: 0.001, default: 0.001, unit: 's' },\n { name: 'release', label: 'Release', type: 'number', min: 0, max: 0.5, step: 0.01, default: 0.1, unit: 's' },\n ],\n },\n\n // === SPATIAL EFFECTS ===\n {\n id: 'stereoWidener',\n name: 'Stereo Widener',\n category: 'spatial',\n description: 'Expands or narrows the stereo image',\n parameters: [\n { name: 'width', label: 'Width', type: 'number', min: 0, max: 1, step: 0.01, default: 0.5 },\n ],\n },\n];\n\n// Helper to get effect definition by ID\nexport const getEffectDefinition = (id: string): EffectDefinition | undefined => {\n return effectDefinitions.find((def) => def.id === id);\n};\n\n// Helper to get effects by category\nexport const getEffectsByCategory = (category: EffectDefinition['category']): EffectDefinition[] => {\n return effectDefinitions.filter((def) => def.category === category);\n};\n\n// All categories with their display names\nexport const effectCategories: { id: EffectDefinition['category']; name: string }[] = [\n { id: 'reverb', name: 'Reverb' },\n { id: 'delay', name: 'Delay' },\n { id: 'modulation', name: 'Modulation' },\n { id: 'filter', name: 'Filter' },\n { id: 'distortion', name: 'Distortion' },\n { id: 'dynamics', name: 'Dynamics' },\n { id: 'spatial', name: 'Spatial' },\n];\n","/**\n * Factory for creating Tone.js effect instances from effect definitions\n */\nimport {\n Reverb,\n Freeverb,\n JCReverb,\n FeedbackDelay,\n PingPongDelay,\n Chorus,\n Phaser,\n Tremolo,\n Vibrato,\n AutoPanner,\n AutoFilter,\n AutoWah,\n EQ3,\n Distortion,\n BitCrusher,\n Chebyshev,\n Compressor,\n Limiter,\n Gate,\n StereoWidener,\n} from 'tone';\nimport type { EffectDefinition } from './effectDefinitions';\n\n// Type for effect instance with common methods\nexport interface EffectInstance {\n effect: any; // Tone.js effect instance\n id: string;\n instanceId: string;\n dispose: () => void;\n setParameter: (name: string, value: number | string | boolean) => void;\n getParameter: (name: string) => number | string | boolean | undefined;\n connect: (destination: any) => void;\n disconnect: () => void;\n}\n\n// Map of effect IDs to their Tone.js constructors\nconst effectConstructors: Record<string, new (options?: any) => any> = {\n reverb: Reverb,\n freeverb: Freeverb,\n jcReverb: JCReverb,\n feedbackDelay: FeedbackDelay,\n pingPongDelay: PingPongDelay,\n chorus: Chorus,\n phaser: Phaser,\n tremolo: Tremolo,\n vibrato: Vibrato,\n autoPanner: AutoPanner,\n autoFilter: AutoFilter,\n autoWah: AutoWah,\n eq3: EQ3,\n distortion: Distortion,\n bitCrusher: BitCrusher,\n chebyshev: Chebyshev,\n compressor: Compressor,\n limiter: Limiter,\n gate: Gate,\n stereoWidener: StereoWidener,\n};\n\n// Generate unique instance ID\nlet instanceCounter = 0;\nconst generateInstanceId = (): string => {\n return `effect_${Date.now()}_${++instanceCounter}`;\n};\n\n/**\n * Create an effect instance from a definition with initial parameter values\n */\nexport function createEffectInstance(\n definition: EffectDefinition,\n initialParams?: Record<string, number | string | boolean>\n): EffectInstance {\n const Constructor = effectConstructors[definition.id];\n if (!Constructor) {\n throw new Error(`Unknown effect type: ${definition.id}`);\n }\n\n // Build initial options from definition defaults and any overrides\n const options: Record<string, any> = {};\n definition.parameters.forEach((param) => {\n const value = initialParams?.[param.name] ?? param.default;\n options[param.name] = value;\n });\n\n // Create the effect instance\n const effect = new Constructor(options);\n const instanceId = generateInstanceId();\n\n return {\n effect,\n id: definition.id,\n instanceId,\n\n dispose() {\n try {\n effect.disconnect();\n effect.dispose();\n } catch (e) {\n // Ignore errors during cleanup\n }\n },\n\n setParameter(name: string, value: number | string | boolean) {\n // Handle special cases for different effect types\n if (name === 'wet' && effect.wet) {\n effect.wet.value = value as number;\n } else if (effect[name] !== undefined) {\n // Check if it's a Tone.js Signal (has .value property)\n if (effect[name]?.value !== undefined) {\n effect[name].value = value;\n } else {\n effect[name] = value;\n }\n }\n },\n\n getParameter(name: string): number | string | boolean | undefined {\n if (name === 'wet' && effect.wet) {\n return effect.wet.value;\n }\n if (effect[name] !== undefined) {\n if (effect[name]?.value !== undefined) {\n return effect[name].value;\n }\n return effect[name];\n }\n return undefined;\n },\n\n connect(destination: any) {\n effect.connect(destination);\n },\n\n disconnect() {\n try {\n effect.disconnect();\n } catch (e) {\n // Ignore disconnect errors\n }\n },\n };\n}\n\n/**\n * Create a chain of effects connected in series\n */\nexport function createEffectChain(\n effects: EffectInstance[]\n): {\n input: any;\n output: any;\n dispose: () => void;\n} {\n if (effects.length === 0) {\n throw new Error('Cannot create effect chain with no effects');\n }\n\n // Connect effects in series\n for (let i = 0; i < effects.length - 1; i++) {\n effects[i].effect.connect(effects[i + 1].effect);\n }\n\n return {\n input: effects[0].effect,\n output: effects[effects.length - 1].effect,\n dispose() {\n effects.forEach((e) => e.dispose());\n },\n };\n}\n","import { useState, useCallback, useRef, useEffect } from 'react';\nimport type { EffectsFunction } from '@waveform-playlist/playout';\nimport {\n effectDefinitions,\n getEffectDefinition,\n type EffectDefinition,\n} from '../effects/effectDefinitions';\nimport {\n createEffectInstance,\n type EffectInstance,\n} from '../effects/effectFactory';\nimport { Analyser } from 'tone';\n\nexport interface ActiveEffect {\n instanceId: string;\n effectId: string;\n definition: EffectDefinition;\n params: Record<string, number | string | boolean>;\n bypassed: boolean;\n}\n\nexport interface UseDynamicEffectsReturn {\n // State\n activeEffects: ActiveEffect[];\n availableEffects: EffectDefinition[];\n\n // Actions\n addEffect: (effectId: string) => void;\n removeEffect: (instanceId: string) => void;\n updateParameter: (instanceId: string, paramName: string, value: number | string | boolean) => void;\n toggleBypass: (instanceId: string) => void;\n reorderEffects: (fromIndex: number, toIndex: number) => void;\n clearAllEffects: () => void;\n\n // For connecting to audio graph\n masterEffects: EffectsFunction;\n\n /**\n * Creates a fresh effects function for offline rendering.\n * This creates new effect instances that work in the offline AudioContext.\n */\n createOfflineEffectsFunction: () => EffectsFunction | undefined;\n\n // Analyser for visualization\n analyserRef: React.RefObject<any>;\n}\n\n/**\n * Hook for managing a dynamic chain of audio effects with real-time parameter updates\n */\nexport function useDynamicEffects(fftSize: number = 256): UseDynamicEffectsReturn {\n // Track active effects in state (for UI)\n const [activeEffects, setActiveEffects] = useState<ActiveEffect[]>([]);\n\n // Ref to store current activeEffects for reading in callbacks (avoids stale closures)\n const activeEffectsRef = useRef<ActiveEffect[]>(activeEffects);\n activeEffectsRef.current = activeEffects;\n\n // Track effect instances (for audio processing)\n const effectInstancesRef = useRef<Map<string, EffectInstance>>(new Map());\n\n // Analyser for visualization\n const analyserRef = useRef<any>(null);\n\n // Reference to the current audio graph nodes\n const graphNodesRef = useRef<{\n masterGainNode: any;\n destination: any;\n analyserNode: any;\n } | null>(null);\n\n // Rebuild the effect chain when effects change\n // Note: effects is passed as parameter to avoid stale closure issues\n const rebuildChain = useCallback((effects: ActiveEffect[]) => {\n const nodes = graphNodesRef.current;\n if (!nodes) return;\n\n const { masterGainNode, destination, analyserNode } = nodes;\n\n // Disconnect everything first\n try {\n masterGainNode.disconnect();\n } catch (e) {\n // Ignore disconnect errors\n }\n\n // Get effect instances in order\n const instances = effects\n .map((ae) => effectInstancesRef.current.get(ae.instanceId))\n .filter((inst): inst is EffectInstance => inst !== undefined);\n\n if (instances.length === 0) {\n // No effects - connect directly to analyser -> destination\n masterGainNode.connect(analyserNode);\n analyserNode.connect(destination);\n } else {\n // Connect: masterGain -> effect1 -> effect2 -> ... -> analyser -> destination\n let currentNode: any = masterGainNode;\n\n instances.forEach((inst) => {\n try {\n inst.disconnect();\n } catch (e) {\n // Ignore\n }\n currentNode.connect(inst.effect);\n currentNode = inst.effect;\n });\n\n // Connect last effect to analyser\n currentNode.connect(analyserNode);\n analyserNode.connect(destination);\n }\n }, []);\n\n // Add a new effect\n const addEffect = useCallback((effectId: string) => {\n const definition = getEffectDefinition(effectId);\n if (!definition) {\n console.error(`Unknown effect: ${effectId}`);\n return;\n }\n\n // Build default params\n const params: Record<string, number | string | boolean> = {};\n definition.parameters.forEach((p) => {\n params[p.name] = p.default;\n });\n\n // Create the effect instance\n const instance = createEffectInstance(definition, params);\n effectInstancesRef.current.set(instance.instanceId, instance);\n\n // Add to state\n const newActiveEffect: ActiveEffect = {\n instanceId: instance.instanceId,\n effectId: definition.id,\n definition,\n params,\n bypassed: false,\n };\n\n setActiveEffects((prev) => [...prev, newActiveEffect]);\n }, []);\n\n // Remove an effect\n const removeEffect = useCallback((instanceId: string) => {\n const instance = effectInstancesRef.current.get(instanceId);\n if (instance) {\n instance.dispose();\n effectInstancesRef.current.delete(instanceId);\n }\n\n setActiveEffects((prev) => prev.filter((e) => e.instanceId !== instanceId));\n }, []);\n\n // Update a parameter in real-time\n const updateParameter = useCallback(\n (instanceId: string, paramName: string, value: number | string | boolean) => {\n // Update the actual effect instance\n const instance = effectInstancesRef.current.get(instanceId);\n if (instance) {\n instance.setParameter(paramName, value);\n }\n\n // Update state for UI\n setActiveEffects((prev) =>\n prev.map((e) =>\n e.instanceId === instanceId\n ? { ...e, params: { ...e.params, [paramName]: value } }\n : e\n )\n );\n },\n []\n );\n\n // Toggle bypass for an effect (uses wet parameter - 0 = bypass, restore original for active)\n const toggleBypass = useCallback(\n (instanceId: string) => {\n // Get current state from ref to determine new bypassed value (avoids stale closure)\n const effect = activeEffectsRef.current.find((e) => e.instanceId === instanceId);\n if (!effect) return;\n\n const newBypassed = !effect.bypassed;\n\n // Update the actual effect instance\n // When bypassing: set wet to 0\n // When un-bypassing: restore the original wet value from params\n const instance = effectInstancesRef.current.get(instanceId);\n if (instance) {\n const originalWet = effect.params.wet as number ?? 1;\n instance.setParameter('wet', newBypassed ? 0 : originalWet);\n }\n\n // Update state for UI\n setActiveEffects((prev) =>\n prev.map((e) =>\n e.instanceId === instanceId ? { ...e, bypassed: newBypassed } : e\n )\n );\n },\n []\n );\n\n // Reorder effects in the chain\n const reorderEffects = useCallback((fromIndex: number, toIndex: number) => {\n setActiveEffects((prev) => {\n const newEffects = [...prev];\n const [removed] = newEffects.splice(fromIndex, 1);\n newEffects.splice(toIndex, 0, removed);\n return newEffects;\n });\n }, []);\n\n // Clear all effects\n const clearAllEffects = useCallback(() => {\n // Dispose all instances\n effectInstancesRef.current.forEach((inst) => inst.dispose());\n effectInstancesRef.current.clear();\n\n setActiveEffects([]);\n }, []);\n\n // Rebuild chain when effects change\n useEffect(() => {\n rebuildChain(activeEffects);\n }, [activeEffects, rebuildChain]);\n\n // The effects function that gets passed to WaveformPlaylistProvider\n // This function is stable - it reads from refs at call time to avoid stale closures\n const masterEffects: EffectsFunction = useCallback(\n (masterGainNode, destination, _isOffline) => {\n // Create analyser for visualization\n const analyserNode = new Analyser('fft', fftSize);\n analyserRef.current = analyserNode;\n\n // Store references for rebuilding chain\n graphNodesRef.current = {\n masterGainNode,\n destination,\n analyserNode,\n };\n\n // Build initial chain - read from ref to get current state\n const effects = activeEffectsRef.current;\n const instances = effects\n .map((ae) => effectInstancesRef.current.get(ae.instanceId))\n .filter((inst): inst is EffectInstance => inst !== undefined);\n\n if (instances.length === 0) {\n // No effects - connect directly to analyser -> destination\n masterGainNode.connect(analyserNode);\n analyserNode.connect(destination);\n } else {\n // Connect: masterGain -> effect1 -> effect2 -> ... -> analyser -> destination\n let currentNode: any = masterGainNode;\n\n instances.forEach((inst) => {\n currentNode.connect(inst.effect);\n currentNode = inst.effect;\n });\n\n // Connect last effect to analyser\n currentNode.connect(analyserNode);\n analyserNode.connect(destination);\n }\n\n return function cleanup() {\n analyserNode.dispose();\n analyserRef.current = null;\n graphNodesRef.current = null;\n };\n },\n [fftSize] // Only fftSize - reads effects from ref\n );\n\n // Cleanup on unmount\n useEffect(() => {\n return () => {\n effectInstancesRef.current.forEach((inst) => inst.dispose());\n effectInstancesRef.current.clear();\n };\n }, []);\n\n /**\n * Creates a fresh effects function for offline rendering.\n * This creates new effect instances in the offline context, avoiding the\n * AudioContext mismatch issue that occurs when reusing real-time effects.\n */\n const createOfflineEffectsFunction = useCallback((): EffectsFunction | undefined => {\n // Get non-bypassed effects\n const nonBypassedEffects = activeEffects.filter((e) => !e.bypassed);\n\n if (nonBypassedEffects.length === 0) {\n return undefined;\n }\n\n // Return a function that creates fresh effect instances\n return (masterGainNode: any, destination: any, _isOffline: boolean) => {\n // Create fresh effect instances for offline context\n const offlineInstances: EffectInstance[] = [];\n\n for (const activeEffect of nonBypassedEffects) {\n const instance = createEffectInstance(activeEffect.definition, activeEffect.params);\n offlineInstances.push(instance);\n }\n\n if (offlineInstances.length === 0) {\n // No effects - connect directly\n masterGainNode.connect(destination);\n } else {\n // Connect: masterGain -> effect1 -> effect2 -> ... -> destination\n let currentNode: any = masterGainNode;\n\n offlineInstances.forEach((inst) => {\n currentNode.connect(inst.effect);\n currentNode = inst.effect;\n });\n\n // Connect last effect to destination\n currentNode.connect(destination);\n }\n\n return function cleanup() {\n offlineInstances.forEach((inst) => inst.dispose());\n };\n };\n }, [activeEffects]);\n\n return {\n activeEffects,\n availableEffects: effectDefinitions,\n addEffect,\n removeEffect,\n updateParameter,\n toggleBypass,\n reorderEffects,\n clearAllEffects,\n masterEffects,\n createOfflineEffectsFunction,\n analyserRef,\n };\n}\n","import { useState, useCallback, useRef, useEffect } from 'react';\nimport type { TrackEffectsFunction } from '../index';\nimport {\n effectDefinitions,\n getEffectDefinition,\n type EffectDefinition,\n} from '../effects/effectDefinitions';\nimport {\n createEffectInstance,\n type EffectInstance,\n} from '../effects/effectFactory';\n\nexport interface TrackActiveEffect {\n instanceId: string;\n effectId: string;\n definition: EffectDefinition;\n params: Record<string, number | string | boolean>;\n bypassed: boolean;\n}\n\nexport interface TrackEffectsState {\n trackId: string;\n activeEffects: TrackActiveEffect[];\n}\n\nexport interface UseTrackDynamicEffectsReturn {\n // State per track\n trackEffectsState: Map<string, TrackActiveEffect[]>;\n\n // Actions\n addEffectToTrack: (trackId: string, effectId: string) => void;\n removeEffectFromTrack: (trackId: string, instanceId: string) => void;\n updateTrackEffectParameter: (\n trackId: string,\n instanceId: string,\n paramName: string,\n value: number | string | boolean\n ) => void;\n toggleBypass: (trackId: string, instanceId: string) => void;\n clearTrackEffects: (trackId: string) => void;\n getTrackEffectsFunction: (trackId: string) => TrackEffectsFunction | undefined;\n\n /**\n * Creates a fresh effects function for a track for offline rendering.\n * This creates new effect instances that work in the offline AudioContext.\n */\n createOfflineTrackEffectsFunction: (trackId: string) => TrackEffectsFunction | undefined;\n\n // Available effects\n availableEffects: EffectDefinition[];\n}\n\n/**\n * Hook for managing dynamic effects per track with real-time parameter updates\n */\nexport function useTrackDynamicEffects(): UseTrackDynamicEffectsReturn {\n // Track effects state per track (for UI)\n const [trackEffectsState, setTrackEffectsState] = useState<Map<string, TrackActiveEffect[]>>(\n new Map()\n );\n\n // Track effect instances per track (for audio processing)\n const trackEffectInstancesRef = useRef<Map<string, Map<string, EffectInstance>>>(new Map());\n\n // Track graph nodes per track for rebuilding chains\n const trackGraphNodesRef = useRef<\n Map<\n string,\n {\n graphEnd: any;\n masterGainNode: any;\n }\n >\n >(new Map());\n\n // Rebuild the effect chain for a specific track\n // Note: trackEffects is passed as parameter to avoid stale closure issues\n const rebuildTrackChain = useCallback((trackId: string, trackEffects: TrackActiveEffect[]) => {\n const nodes = trackGraphNodesRef.current.get(trackId);\n if (!nodes) return;\n\n const { graphEnd, masterGainNode } = nodes;\n const instancesMap = trackEffectInstancesRef.current.get(trackId);\n\n // Disconnect everything first\n try {\n graphEnd.disconnect();\n } catch (e) {\n // Ignore disconnect errors\n }\n\n // Get effect instances in order\n const instances = trackEffects\n .map((ae) => instancesMap?.get(ae.instanceId))\n .filter((inst): inst is EffectInstance => inst !== undefined);\n\n if (instances.length === 0) {\n // No effects - connect directly\n graphEnd.connect(masterGainNode);\n } else {\n // Connect: graphEnd -> effect1 -> effect2 -> ... -> masterGainNode\n let currentNode: any = graphEnd;\n\n instances.forEach((inst) => {\n try {\n inst.disconnect();\n } catch (e) {\n // Ignore\n }\n currentNode.connect(inst.effect);\n currentNode = inst.effect;\n });\n\n // Connect last effect to master\n currentNode.connect(masterGainNode);\n }\n }, []);\n\n // Add a new effect to a track\n const addEffectToTrack = useCallback((trackId: string, effectId: string) => {\n const definition = getEffectDefinition(effectId);\n if (!definition) {\n console.error(`Unknown effect: ${effectId}`);\n return;\n }\n\n // Build default params\n const params: Record<string, number | string | boolean> = {};\n definition.parameters.forEach((p) => {\n params[p.name] = p.default;\n });\n\n // Create the effect instance\n const instance = createEffectInstance(definition, params);\n\n // Initialize maps if needed\n if (!trackEffectInstancesRef.current.has(trackId)) {\n trackEffectInstancesRef.current.set(trackId, new Map());\n }\n trackEffectInstancesRef.current.get(trackId)!.set(instance.instanceId, instance);\n\n // Add to state\n const newActiveEffect: TrackActiveEffect = {\n instanceId: instance.instanceId,\n effectId: definition.id,\n definition,\n params,\n bypassed: false,\n };\n\n setTrackEffectsState((prev) => {\n const newState = new Map(prev);\n const existing = newState.get(trackId) || [];\n newState.set(trackId, [...existing, newActiveEffect]);\n return newState;\n });\n }, []);\n\n // Remove an effect from a track\n const removeEffectFromTrack = useCallback((trackId: string, instanceId: string) => {\n const instancesMap = trackEffectInstancesRef.current.get(trackId);\n const instance = instancesMap?.get(instanceId);\n if (instance) {\n instance.dispose();\n instancesMap?.delete(instanceId);\n }\n\n setTrackEffectsState((prev) => {\n const newState = new Map(prev);\n const existing = newState.get(trackId) || [];\n newState.set(trackId, existing.filter((e) => e.instanceId !== instanceId));\n return newState;\n });\n }, []);\n\n // Update a parameter in real-time\n const updateTrackEffectParameter = useCallback(\n (trackId: string, instanceId: string, paramName: string, value: number | string | boolean) => {\n // Update the actual effect instance\n const instancesMap = trackEffectInstancesRef.current.get(trackId);\n const instance = instancesMap?.get(instanceId);\n if (instance) {\n instance.setParameter(paramName, value);\n }\n\n // Update state for UI\n setTrackEffectsState((prev) => {\n const newState = new Map(prev);\n const existing = newState.get(trackId) || [];\n newState.set(\n trackId,\n existing.map((e) =>\n e.instanceId === instanceId\n ? { ...e, params: { ...e.params, [paramName]: value } }\n : e\n )\n );\n return newState;\n });\n },\n []\n );\n\n // Toggle bypass for an effect (uses wet parameter - 0 = bypass, restore original for active)\n const toggleBypass = useCallback(\n (trackId: string, instanceId: string) => {\n // Get current state from ref to determine new bypassed value (avoids stale closure)\n const trackEffects = trackEffectsStateRef.current.get(trackId) || [];\n const effect = trackEffects.find((e) => e.instanceId === instanceId);\n if (!effect) return;\n\n const newBypassed = !effect.bypassed;\n\n // Update the actual effect instance\n // When bypassing: set wet to 0\n // When un-bypassing: restore the original wet value from params\n const instancesMap = trackEffectInstancesRef.current.get(trackId);\n const instance = instancesMap?.get(instanceId);\n if (instance) {\n const originalWet = effect.params.wet as number ?? 1;\n instance.setParameter('wet', newBypassed ? 0 : originalWet);\n }\n\n // Update state for UI\n setTrackEffectsState((prev) => {\n const newState = new Map(prev);\n const existing = newState.get(trackId) || [];\n newState.set(\n trackId,\n existing.map((e) =>\n e.instanceId === instanceId ? { ...e, bypassed: newBypassed } : e\n )\n );\n return newState;\n });\n },\n []\n );\n\n // Clear all effects from a track\n const clearTrackEffects = useCallback((trackId: string) => {\n // Dispose all instances for this track\n const instancesMap = trackEffectInstancesRef.current.get(trackId);\n if (instancesMap) {\n instancesMap.forEach((inst) => inst.dispose());\n instancesMap.clear();\n }\n\n setTrackEffectsState((prev) => {\n const newState = new Map(prev);\n newState.set(trackId, []);\n return newState;\n });\n }, []);\n\n // Ref to store the current trackEffectsState for reading in effects function\n // This avoids stale closure issues when the effects function is called later\n const trackEffectsStateRef = useRef<Map<string, TrackActiveEffect[]>>(trackEffectsState);\n trackEffectsStateRef.current = trackEffectsState;\n\n // Get the effects function for a track to pass to useAudioTracks\n // This function is stable (no dependencies) - it reads from refs at call time\n const getTrackEffectsFunction = useCallback(\n (trackId: string): TrackEffectsFunction | undefined => {\n // Return a function that connects effects when the track is loaded\n return (graphEnd, masterGainNode, _isOffline) => {\n // Store references for rebuilding chain\n trackGraphNodesRef.current.set(trackId, {\n graphEnd,\n masterGainNode,\n });\n\n // Read current state from ref (not stale closure)\n const trackEffects = trackEffectsStateRef.current.get(trackId) || [];\n const instancesMap = trackEffectInstancesRef.current.get(trackId);\n\n // Get effect instances in order\n const instances = trackEffects\n .map((ae) => instancesMap?.get(ae.instanceId))\n .filter((inst): inst is EffectInstance => inst !== undefined);\n\n if (instances.length === 0) {\n // No effects - connect directly\n graphEnd.connect(masterGainNode);\n } else {\n // Connect: graphEnd -> effect1 -> effect2 -> ... -> masterGainNode\n let currentNode: any = graphEnd;\n\n instances.forEach((inst) => {\n currentNode.connect(inst.effect);\n currentNode = inst.effect;\n });\n\n // Connect last effect to master\n currentNode.connect(masterGainNode);\n }\n\n return function cleanup() {\n trackGraphNodesRef.current.delete(trackId);\n };\n };\n },\n [] // No dependencies - stable function that reads from refs\n );\n\n // Rebuild chains when effects change\n useEffect(() => {\n trackEffectsState.forEach((effects, trackId) => {\n rebuildTrackChain(trackId, effects);\n });\n }, [trackEffectsState, rebuildTrackChain]);\n\n // Cleanup on unmount\n useEffect(() => {\n return () => {\n trackEffectInstancesRef.current.forEach((instancesMap) => {\n instancesMap.forEach((inst) => inst.dispose());\n instancesMap.clear();\n });\n trackEffectInstancesRef.current.clear();\n };\n }, []);\n\n /**\n * Creates a fresh effects function for a track for offline rendering.\n * This creates new effect instances in the offline context, avoiding the\n * AudioContext mismatch issue that occurs when reusing real-time effects.\n */\n const createOfflineTrackEffectsFunction = useCallback(\n (trackId: string): TrackEffectsFunction | undefined => {\n const trackEffects = trackEffectsState.get(trackId) || [];\n // Get non-bypassed effects\n const nonBypassedEffects = trackEffects.filter((e) => !e.bypassed);\n\n if (nonBypassedEffects.length === 0) {\n return undefined;\n }\n\n // Return a function that creates fresh effect instances\n return (graphEnd: any, masterGainNode: any, _isOffline: boolean) => {\n // Create fresh effect instances for offline context\n const offlineInstances: EffectInstance[] = [];\n\n for (const activeEffect of nonBypassedEffects) {\n const instance = createEffectInstance(activeEffect.definition, activeEffect.params);\n offlineInstances.push(instance);\n }\n\n if (offlineInstances.length === 0) {\n // No effects - connect directly\n graphEnd.connect(masterGainNode);\n } else {\n // Connect: graphEnd -> effect1 -> effect2 -> ... -> masterGainNode\n let currentNode: any = graphEnd;\n\n offlineInstances.forEach((inst) => {\n currentNode.connect(inst.effect);\n currentNode = inst.effect;\n });\n\n // Connect last effect to master\n currentNode.connect(masterGainNode);\n }\n\n return function cleanup() {\n offlineInstances.forEach((inst) => inst.dispose());\n };\n };\n },\n [trackEffectsState]\n );\n\n return {\n trackEffectsState,\n addEffectToTrack,\n removeEffectFromTrack,\n updateTrackEffectParameter,\n toggleBypass,\n clearTrackEffects,\n getTrackEffectsFunction,\n createOfflineTrackEffectsFunction,\n availableEffects: effectDefinitions,\n };\n}\n","/**\n * WAV file encoder\n * Converts AudioBuffer to WAV format Blob\n */\n\nexport interface WavEncoderOptions {\n /** Bit depth: 16 or 32. Default: 16 */\n bitDepth?: 16 | 32;\n}\n\n/**\n * Encode an AudioBuffer to WAV format\n * @param audioBuffer - The AudioBuffer to encode\n * @param options - Encoding options\n * @returns WAV file as Blob\n */\nexport function encodeWav(\n audioBuffer: AudioBuffer,\n options: WavEncoderOptions = {}\n): Blob {\n const { bitDepth = 16 } = options;\n\n const numChannels = audioBuffer.numberOfChannels;\n const sampleRate = audioBuffer.sampleRate;\n const numSamples = audioBuffer.length;\n const bytesPerSample = bitDepth / 8;\n const blockAlign = numChannels * bytesPerSample;\n const byteRate = sampleRate * blockAlign;\n const dataSize = numSamples * blockAlign;\n\n // WAV header is 44 bytes\n const headerSize = 44;\n const totalSize = headerSize + dataSize;\n\n const buffer = new ArrayBuffer(totalSize);\n const view = new DataView(buffer);\n\n // Write WAV header\n // RIFF chunk descriptor\n writeString(view, 0, 'RIFF');\n view.setUint32(4, totalSize - 8, true); // File size minus RIFF header\n writeString(view, 8, 'WAVE');\n\n // fmt sub-chunk\n writeString(view, 12, 'fmt ');\n view.setUint32(16, 16, true); // Subchunk1Size (16 for PCM)\n view.setUint16(20, bitDepth === 32 ? 3 : 1, true); // AudioFormat (1=PCM, 3=IEEE float)\n view.setUint16(22, numChannels, true);\n view.setUint32(24, sampleRate, true);\n view.setUint32(28, byteRate, true);\n view.setUint16(32, blockAlign, true);\n view.setUint16(34, bitDepth, true);\n\n // data sub-chunk\n writeString(view, 36, 'data');\n view.setUint32(40, dataSize, true);\n\n // Write interleaved audio data\n const channelData: Float32Array[] = [];\n for (let ch = 0; ch < numChannels; ch++) {\n channelData.push(audioBuffer.getChannelData(ch));\n }\n\n let offset = headerSize;\n\n if (bitDepth === 16) {\n // 16-bit PCM\n for (let i = 0; i < numSamples; i++) {\n for (let ch = 0; ch < numChannels; ch++) {\n const sample = channelData[ch][i];\n // Clamp to [-1, 1] and convert to 16-bit signed integer\n const clampedSample = Math.max(-1, Math.min(1, sample));\n const intSample = clampedSample < 0\n ? clampedSample * 0x8000\n : clampedSample * 0x7FFF;\n view.setInt16(offset, intSample, true);\n offset += 2;\n }\n }\n } else {\n // 32-bit IEEE float\n for (let i = 0; i < numSamples; i++) {\n for (let ch = 0; ch < numChannels; ch++) {\n view.setFloat32(offset, channelData[ch][i], true);\n offset += 4;\n }\n }\n }\n\n return new Blob([buffer], { type: 'audio/wav' });\n}\n\n/**\n * Write a string to a DataView at the specified offset\n */\nfunction writeString(view: DataView, offset: number, str: string): void {\n for (let i = 0; i < str.length; i++) {\n view.setUint8(offset + i, str.charCodeAt(i));\n }\n}\n\n/**\n * Trigger a download of a Blob with the specified filename\n */\nexport function downloadBlob(blob: Blob, filename: string): void {\n const url = URL.createObjectURL(blob);\n const a = document.createElement('a');\n a.href = url;\n a.download = filename;\n a.style.display = 'none';\n document.body.appendChild(a);\n a.click();\n document.body.removeChild(a);\n URL.revokeObjectURL(url);\n}\n","import { useState, useCallback } from 'react';\nimport type { ClipTrack, AudioClip, FadeType } from '@waveform-playlist/core';\nimport type { EffectsFunction } from '@waveform-playlist/playout';\nimport { encodeWav, downloadBlob, type WavEncoderOptions } from '../utils/wavEncoder';\n\n/** Function type for per-track effects (same as in @waveform-playlist/core) */\nexport type TrackEffectsFunction = (graphEnd: unknown, destination: unknown, isOffline: boolean) => void | (() => void);\n\nexport interface ExportOptions extends WavEncoderOptions {\n /** Filename for download (without extension) */\n filename?: string;\n /** Export mode: 'master' for stereo mix, 'individual' for single track */\n mode?: 'master' | 'individual';\n /** Track index for individual export (only used when mode is 'individual') */\n trackIndex?: number;\n /** Whether to trigger automatic download */\n autoDownload?: boolean;\n /** Whether to apply effects (fades, etc.) - defaults to true */\n applyEffects?: boolean;\n /**\n * Optional Tone.js effects function for master effects. When provided, export will use Tone.Offline\n * to render through the effects chain. The function receives isOffline=true.\n */\n effectsFunction?: EffectsFunction;\n /**\n * Optional function to create offline track effects.\n * Takes a trackId and returns a TrackEffectsFunction for offline rendering.\n * This is used instead of track.effects to avoid AudioContext mismatch issues.\n */\n createOfflineTrackEffects?: (trackId: string) => TrackEffectsFunction | undefined;\n /** Progress callback (0-1) */\n onProgress?: (progress: number) => void;\n}\n\nexport interface ExportResult {\n /** The rendered audio buffer */\n audioBuffer: AudioBuffer;\n /** The WAV file as a Blob */\n blob: Blob;\n /** Duration in seconds */\n duration: number;\n}\n\nexport interface UseExportWavReturn {\n /** Export the playlist to WAV */\n exportWav: (tracks: ClipTrack[], trackStates: TrackState[], options?: ExportOptions) => Promise<ExportResult>;\n /** Whether export is in progress */\n isExporting: boolean;\n /** Export progress (0-1) */\n progress: number;\n /** Error message if export failed */\n error: string | null;\n}\n\ninterface TrackState {\n muted: boolean;\n soloed: boolean;\n volume: number;\n pan: number;\n}\n\n/**\n * Hook for exporting the waveform playlist to WAV format\n * Uses OfflineAudioContext for fast, non-real-time rendering\n */\nexport function useExportWav(): UseExportWavReturn {\n const [isExporting, setIsExporting] = useState(false);\n const [progress, setProgress] = useState(0);\n const [error, setError] = useState<string | null>(null);\n\n const exportWav = useCallback(async (\n tracks: ClipTrack[],\n trackStates: TrackState[],\n options: ExportOptions = {}\n ): Promise<ExportResult> => {\n const {\n filename = 'export',\n mode = 'master',\n trackIndex,\n autoDownload = true,\n applyEffects = true,\n effectsFunction,\n createOfflineTrackEffects,\n bitDepth = 16,\n onProgress,\n } = options;\n\n setIsExporting(true);\n setProgress(0);\n setError(null);\n\n try {\n // Validate inputs\n if (tracks.length === 0) {\n throw new Error('No tracks to export');\n }\n\n if (mode === 'individual' && (trackIndex === undefined || trackIndex < 0 || trackIndex >= tracks.length)) {\n throw new Error('Invalid track index for individual export');\n }\n\n // Get sample rate from first clip (use clip.sampleRate which is always defined)\n const sampleRate = tracks[0].clips[0]?.sampleRate || 44100;\n\n // Calculate total duration from all clips (in samples)\n let totalDurationSamples = 0;\n for (const track of tracks) {\n for (const clip of track.clips) {\n const clipEndSample = clip.startSample + clip.durationSamples;\n totalDurationSamples = Math.max(totalDurationSamples, clipEndSample);\n }\n }\n\n // Add a small buffer at the end (0.1 seconds) to avoid cutting off\n totalDurationSamples += Math.round(sampleRate * 0.1);\n\n const duration = totalDurationSamples / sampleRate;\n\n // Determine which tracks to render\n const tracksToRender = mode === 'individual'\n ? [{ track: tracks[trackIndex!], state: trackStates[trackIndex!], index: trackIndex! }]\n : tracks.map((track, index) => ({ track, state: trackStates[index], index }));\n\n // Check for solo - if any track is soloed, only play soloed tracks\n const hasSolo = trackStates.some(state => state.soloed);\n\n // Check if per-track effects are provided via the offline creator function\n // Note: We don't use track.effects directly for offline rendering to avoid AudioContext mismatch\n const hasOfflineTrackEffects = !!createOfflineTrackEffects;\n\n let renderedBuffer: AudioBuffer;\n\n if ((effectsFunction || hasOfflineTrackEffects) && applyEffects) {\n // Use Tone.Offline for rendering with effects (master and/or per-track)\n renderedBuffer = await renderWithToneEffects(\n tracksToRender,\n trackStates,\n hasSolo,\n duration,\n sampleRate,\n effectsFunction,\n createOfflineTrackEffects,\n (p) => {\n setProgress(p);\n onProgress?.(p);\n }\n );\n } else {\n // Use standard OfflineAudioContext rendering\n const offlineCtx = new OfflineAudioContext(2, totalDurationSamples, sampleRate);\n\n // Schedule all clips for rendering\n let scheduledClips = 0;\n const totalClips = tracksToRender.reduce((sum, { track }) => sum + track.clips.length, 0);\n\n for (const { track, state } of tracksToRender) {\n // Skip muted tracks (unless soloed)\n if (state.muted && !state.soloed) continue;\n // If there's a solo and this track isn't soloed, skip it\n if (hasSolo && !state.soloed) continue;\n\n for (const clip of track.clips) {\n await scheduleClip(offlineCtx, clip, state, sampleRate, applyEffects);\n scheduledClips++;\n const currentProgress = scheduledClips / totalClips * 0.5; // First 50% is scheduling\n setProgress(currentProgress);\n onProgress?.(currentProgress);\n }\n }\n\n // Render the audio\n setProgress(0.5);\n onProgress?.(0.5);\n\n renderedBuffer = await offlineCtx.startRendering();\n }\n\n setProgress(0.9);\n onProgress?.(0.9);\n\n // Encode to WAV\n const blob = encodeWav(renderedBuffer, { bitDepth });\n\n setProgress(1);\n onProgress?.(1);\n\n // Auto download if requested\n if (autoDownload) {\n const exportFilename = mode === 'individual'\n ? `${filename}_${tracks[trackIndex!].name}`\n : filename;\n downloadBlob(blob, `${exportFilename}.wav`);\n }\n\n return {\n audioBuffer: renderedBuffer,\n blob,\n duration,\n };\n } catch (err) {\n const message = err instanceof Error ? err.message : 'Export failed';\n setError(message);\n throw err;\n } finally {\n setIsExporting(false);\n }\n }, []);\n\n return {\n exportWav,\n isExporting,\n progress,\n error,\n };\n}\n\n/**\n * Render using Tone.Offline with effects chain (master and/or per-track)\n */\nasync function renderWithToneEffects(\n tracksToRender: { track: ClipTrack; state: TrackState; index: number }[],\n _trackStates: TrackState[],\n hasSolo: boolean,\n duration: number,\n sampleRate: number,\n effectsFunction: EffectsFunction | undefined,\n createOfflineTrackEffects: ((trackId: string) => TrackEffectsFunction | undefined) | undefined,\n onProgress: (progress: number) => void\n): Promise<AudioBuffer> {\n // Dynamically import Tone.js modules\n const { Offline, Volume, Gain, Panner, Player, ToneAudioBuffer } = await import('tone');\n\n onProgress(0.1);\n\n // Use Tone.Offline to render with effects\n let buffer;\n try {\n buffer = await Offline(\n async ({ transport, destination }) => {\n // Create master volume node\n const masterVolume = new Volume(0); // 0 dB = unity gain\n\n // Apply master effects chain if provided, otherwise connect directly to destination\n let cleanup: void | (() => void) = undefined;\n if (effectsFunction) {\n cleanup = effectsFunction(masterVolume, destination, true);\n } else {\n masterVolume.connect(destination);\n }\n\n // Schedule all clips\n for (const { track, state } of tracksToRender) {\n // Skip muted tracks (unless soloed)\n if (state.muted && !state.soloed) continue;\n // If there's a solo and this track isn't soloed, skip it\n if (hasSolo && !state.soloed) continue;\n\n // Create track-level nodes\n const trackVolume = new Volume(gainToDb(state.volume));\n const trackPan = new Panner(state.pan);\n const trackMute = new Gain(state.muted ? 0 : 1);\n\n // Get offline track effects using the creator function\n // Note: We use createOfflineTrackEffects instead of track.effects to avoid AudioContext mismatch\n const trackEffects = createOfflineTrackEffects?.(track.id);\n\n if (trackEffects) {\n // Apply per-track effects chain: trackMute -> effects -> masterVolume\n trackEffects(trackMute, masterVolume, true);\n } else {\n // No per-track effects: connect directly to master\n trackMute.connect(masterVolume);\n }\n\n // Connect track chain: clips -> trackVolume -> trackPan -> trackMute\n trackPan.connect(trackMute);\n trackVolume.connect(trackPan);\n\n // Schedule each clip\n for (const clip of track.clips) {\n const { audioBuffer, startSample, durationSamples, offsetSamples, gain: clipGain, fadeIn, fadeOut } = clip;\n\n // Convert samples to seconds\n const startTime = startSample / sampleRate;\n const clipDuration = durationSamples / sampleRate;\n const offset = offsetSamples / sampleRate;\n\n // Create a ToneAudioBuffer from the existing AudioBuffer\n const toneBuffer = new ToneAudioBuffer(audioBuffer);\n\n // Create player for this clip\n const player = new Player(toneBuffer);\n\n // Create fade gain for clip-level effects\n const fadeGain = new Gain(clipGain);\n\n // Connect player -> fadeGain -> trackVolume\n player.connect(fadeGain);\n fadeGain.connect(trackVolume);\n\n // Apply fades using gain automation\n // New simple API: fadeIn starts at clip start, fadeOut ends at clip end\n if (fadeIn) {\n const fadeInStart = startTime;\n const fadeInEnd = startTime + fadeIn.duration;\n const audioParam = (fadeGain.gain as any)._param as AudioParam;\n // Set initial value to 0\n audioParam.setValueAtTime(0, fadeInStart);\n audioParam.linearRampToValueAtTime(clipGain, fadeInEnd);\n }\n\n if (fadeOut) {\n const fadeOutStart = startTime + clipDuration - fadeOut.duration;\n const fadeOutEnd = startTime + clipDuration;\n const audioParam = (fadeGain.gain as any)._param as AudioParam;\n audioParam.setValueAtTime(clipGain, fadeOutStart);\n audioParam.linearRampToValueAtTime(0, fadeOutEnd);\n }\n\n // Schedule the player to start\n player.start(startTime, offset, clipDuration);\n }\n }\n\n // Start the transport\n transport.start(0);\n\n // Clean up effects if cleanup function was provided\n if (cleanup) {\n // Note: cleanup will be called after rendering completes\n }\n },\n duration,\n 2, // stereo\n sampleRate\n );\n } catch (err) {\n // Re-throw with a proper Error object if needed\n if (err instanceof Error) {\n throw err;\n } else {\n throw new Error(`Tone.Offline rendering failed: ${String(err)}`);\n }\n }\n\n onProgress(0.9);\n\n // Convert ToneAudioBuffer to standard AudioBuffer\n return buffer.get() as AudioBuffer;\n}\n\n/**\n * Convert linear gain to decibels\n */\nfunction gainToDb(gain: number): number {\n return 20 * Math.log10(Math.max(gain, 0.0001));\n}\n\n/**\n * Schedule a single clip in the offline context\n */\nasync function scheduleClip(\n ctx: OfflineAudioContext,\n clip: AudioClip,\n trackState: TrackState,\n sampleRate: number,\n applyEffects: boolean\n): Promise<void> {\n const { audioBuffer, startSample, durationSamples, offsetSamples, gain: clipGain, fadeIn, fadeOut } = clip;\n\n // Skip clips without audioBuffer (peaks-only clips can't be exported)\n if (!audioBuffer) {\n console.warn(`Skipping clip \"${clip.name || clip.id}\" - no audioBuffer for export`);\n return;\n }\n\n // Convert samples to seconds for Web Audio API\n const startTime = startSample / sampleRate;\n const duration = durationSamples / sampleRate;\n const offset = offsetSamples / sampleRate;\n\n // Create buffer source\n const source = ctx.createBufferSource();\n source.buffer = audioBuffer;\n\n // Create gain node for clip + track volume\n const gainNode = ctx.createGain();\n const baseGain = clipGain * trackState.volume;\n\n // Create stereo panner for track pan\n const pannerNode = ctx.createStereoPanner();\n pannerNode.pan.value = trackState.pan;\n\n // Connect: source -> gain -> panner -> destination\n source.connect(gainNode);\n gainNode.connect(pannerNode);\n pannerNode.connect(ctx.destination);\n\n // Apply effects (fades) if enabled\n // New simple API: fadeIn starts at clip start, fadeOut ends at clip end\n if (applyEffects) {\n // Set initial gain (may be 0 if fade in exists)\n if (fadeIn) {\n gainNode.gain.setValueAtTime(0, startTime);\n } else {\n gainNode.gain.setValueAtTime(baseGain, startTime);\n }\n\n // Apply fade in\n if (fadeIn) {\n const fadeInStart = startTime;\n const fadeInEnd = startTime + fadeIn.duration;\n applyFadeEnvelope(gainNode.gain, fadeInStart, fadeInEnd, 0, baseGain, fadeIn.type || 'linear');\n }\n\n // Apply fade out\n if (fadeOut) {\n const fadeOutStart = startTime + duration - fadeOut.duration;\n const fadeOutEnd = startTime + duration;\n // Ensure we're at baseGain before fade out starts\n if (!fadeIn || fadeIn.duration < (duration - fadeOut.duration)) {\n gainNode.gain.setValueAtTime(baseGain, fadeOutStart);\n }\n applyFadeEnvelope(gainNode.gain, fadeOutStart, fadeOutEnd, baseGain, 0, fadeOut.type || 'linear');\n }\n } else {\n // No effects - just set constant gain\n gainNode.gain.setValueAtTime(baseGain, startTime);\n }\n\n // Schedule playback\n source.start(startTime, offset, duration);\n}\n\n/**\n * Apply a fade envelope to a gain parameter using Web Audio automation\n */\nfunction applyFadeEnvelope(\n gainParam: AudioParam,\n startTime: number,\n endTime: number,\n startValue: number,\n endValue: number,\n fadeType: FadeType\n): void {\n const duration = endTime - startTime;\n if (duration <= 0) return;\n\n switch (fadeType) {\n case 'linear':\n gainParam.setValueAtTime(startValue, startTime);\n gainParam.linearRampToValueAtTime(endValue, endTime);\n break;\n\n case 'exponential':\n // Exponential can't handle 0 values, use small value instead\n const expStart = Math.max(startValue, 0.0001);\n const expEnd = Math.max(endValue, 0.0001);\n gainParam.setValueAtTime(expStart, startTime);\n gainParam.exponentialRampToValueAtTime(expEnd, endTime);\n // Set to actual 0 if needed\n if (endValue === 0) {\n gainParam.setValueAtTime(0, endTime);\n }\n break;\n\n case 'logarithmic':\n // Logarithmic fade - more aggressive at start, gentler at end\n // Implemented using setValueCurveAtTime with calculated curve\n const logCurve = generateFadeCurve(startValue, endValue, 256, 'logarithmic');\n gainParam.setValueCurveAtTime(logCurve, startTime, duration);\n break;\n\n case 'sCurve':\n // S-curve (ease-in-out) - smooth start and end\n const sCurve = generateFadeCurve(startValue, endValue, 256, 'sCurve');\n gainParam.setValueCurveAtTime(sCurve, startTime, duration);\n break;\n\n default:\n // Default to linear\n gainParam.setValueAtTime(startValue, startTime);\n gainParam.linearRampToValueAtTime(endValue, endTime);\n }\n}\n\n/**\n * Generate a fade curve for setValueCurveAtTime\n */\nfunction generateFadeCurve(\n startValue: number,\n endValue: number,\n numPoints: number,\n curveType: 'logarithmic' | 'sCurve'\n): Float32Array {\n const curve = new Float32Array(numPoints);\n const range = endValue - startValue;\n\n for (let i = 0; i < numPoints; i++) {\n const t = i / (numPoints - 1); // 0 to 1\n\n let curveValue: number;\n if (curveType === 'logarithmic') {\n // Logarithmic: fast at start, slow at end (for fade out)\n // or slow at start, fast at end (for fade in)\n if (range > 0) {\n // Fade in: use log curve\n curveValue = Math.log10(1 + t * 9) / Math.log10(10);\n } else {\n // Fade out: use inverse log curve\n curveValue = 1 - Math.log10(1 + (1 - t) * 9) / Math.log10(10);\n }\n } else {\n // S-curve (smoothstep)\n curveValue = t * t * (3 - 2 * t);\n }\n\n curve[i] = startValue + range * curveValue;\n }\n\n return curve;\n}\n\n/**\n * Export types\n */\nexport type { WavEncoderOptions };\n","import React, { createContext, useContext, useState, useEffect, useRef, useCallback, ReactNode } from 'react';\nimport { ThemeProvider } from 'styled-components';\nimport { TonePlayout, type EffectsFunction, type TrackEffectsFunction } from '@waveform-playlist/playout';\nimport { type Track, type ClipTrack, type Fade } from '@waveform-playlist/core';\nimport { type TimeFormat, type WaveformPlaylistTheme, defaultTheme } from '@waveform-playlist/ui-components';\nimport { start as toneStart, getContext } from 'tone';\nimport { generatePeaks } from './peaksUtil';\nimport { extractPeaksFromWaveformData } from './waveformDataLoader';\nimport type { PeakData } from '@waveform-playlist/webaudio-peaks';\nimport { parseAeneas, type AnnotationData } from '@waveform-playlist/annotations';\nimport { useTimeFormat, useZoomControls, useMasterVolume } from './hooks';\n\n// Types\nexport interface ClipPeaks {\n clipId: string;\n trackName: string;\n peaks: PeakData;\n startSample: number;\n durationSamples: number;\n fadeIn?: Fade;\n fadeOut?: Fade;\n}\n\nexport type TrackClipPeaks = ClipPeaks[];\n\n// Legacy WaveformTrack type - kept for reference but deprecated\n// @deprecated Use ClipTrack from @waveform-playlist/core instead\nexport interface WaveformTrack {\n src: string | AudioBuffer;\n name?: string;\n effects?: TrackEffectsFunction;\n}\n\nexport interface TrackState {\n name: string;\n muted: boolean;\n soloed: boolean;\n volume: number;\n pan: number;\n}\n\nexport interface WaveformPlaylistContextValue {\n // State\n isPlaying: boolean;\n currentTime: number;\n duration: number;\n audioBuffers: AudioBuffer[];\n peaksDataArray: TrackClipPeaks[]; // Array of tracks, each containing array of clip peaks\n trackStates: TrackState[];\n annotations: AnnotationData[];\n activeAnnotationId: string | null;\n selectionStart: number;\n selectionEnd: number;\n isAutomaticScroll: boolean;\n continuousPlay: boolean;\n linkEndpoints: boolean;\n annotationsEditable: boolean;\n\n // Playback controls\n play: (startTime?: number, playDuration?: number) => Promise<void>;\n pause: () => void;\n stop: () => void;\n setCurrentTime: (time: number) => void;\n\n // Track controls\n setTrackMute: (trackIndex: number, muted: boolean) => void;\n setTrackSolo: (trackIndex: number, soloed: boolean) => void;\n setTrackVolume: (trackIndex: number, volume: number) => void;\n setTrackPan: (trackIndex: number, pan: number) => void;\n\n // Selection\n setSelection: (start: number, end: number) => void;\n\n // Time format\n timeFormat: string;\n setTimeFormat: (format: TimeFormat) => void;\n formatTime: (seconds: number) => string;\n\n // Zoom\n samplesPerPixel: number;\n zoomIn: () => void;\n zoomOut: () => void;\n canZoomIn: boolean;\n canZoomOut: boolean;\n\n // Master volume\n masterVolume: number;\n setMasterVolume: (volume: number) => void;\n\n // Automatic scroll\n setAutomaticScroll: (enabled: boolean) => void;\n setScrollContainer: (element: HTMLDivElement | null) => void;\n\n // Annotation controls\n setContinuousPlay: (enabled: boolean) => void;\n setLinkEndpoints: (enabled: boolean) => void;\n setAnnotationsEditable: (enabled: boolean) => void;\n setAnnotations: (annotations: AnnotationData[]) => void;\n setActiveAnnotationId: (id: string | null) => void;\n\n // Refs\n playoutRef: React.RefObject<TonePlayout | null>;\n currentTimeRef: React.RefObject<number>;\n\n // Playlist info\n sampleRate: number;\n waveHeight: number;\n timeScaleHeight: number;\n minimumPlaylistHeight: number;\n controls: { show: boolean; width: number };\n}\n\n// Split contexts for performance optimization\n// High-frequency updates (currentTime) are isolated from low-frequency state changes\n\nexport interface PlaybackAnimationContextValue {\n isPlaying: boolean;\n currentTime: number;\n currentTimeRef: React.RefObject<number>;\n // Refs for direct time calculation in animated components (avoids timing drift)\n playbackStartTimeRef: React.RefObject<number>; // context.currentTime when playback started\n audioStartPositionRef: React.RefObject<number>; // Audio position when playback started\n}\n\nexport interface PlaylistStateContextValue {\n continuousPlay: boolean;\n linkEndpoints: boolean;\n annotationsEditable: boolean;\n isAutomaticScroll: boolean;\n isLoopEnabled: boolean;\n annotations: AnnotationData[];\n activeAnnotationId: string | null;\n selectionStart: number;\n selectionEnd: number;\n selectedTrackId: string | null; // ID of currently selected track for editing operations\n // Loop region (separate from selection) - Audacity-style loop points\n loopStart: number;\n loopEnd: number;\n}\n\nexport interface PlaylistControlsContextValue {\n // Playback controls\n play: (startTime?: number, playDuration?: number) => Promise<void>;\n pause: () => void;\n stop: () => void;\n seekTo: (time: number) => void;\n setCurrentTime: (time: number) => void;\n\n // Track controls\n setTrackMute: (trackIndex: number, muted: boolean) => void;\n setTrackSolo: (trackIndex: number, soloed: boolean) => void;\n setTrackVolume: (trackIndex: number, volume: number) => void;\n setTrackPan: (trackIndex: number, pan: number) => void;\n\n // Selection\n setSelection: (start: number, end: number) => void;\n setSelectedTrackId: (trackId: string | null) => void;\n\n // Time format\n setTimeFormat: (format: TimeFormat) => void;\n formatTime: (seconds: number) => string;\n\n // Zoom\n zoomIn: () => void;\n zoomOut: () => void;\n\n // Master volume\n setMasterVolume: (volume: number) => void;\n\n // Automatic scroll\n setAutomaticScroll: (enabled: boolean) => void;\n setScrollContainer: (element: HTMLDivElement | null) => void;\n scrollContainerRef: React.RefObject<HTMLDivElement | null>;\n\n // Annotation controls\n setContinuousPlay: (enabled: boolean) => void;\n setLinkEndpoints: (enabled: boolean) => void;\n setAnnotationsEditable: (enabled: boolean) => void;\n setAnnotations: (annotations: AnnotationData[]) => void;\n setActiveAnnotationId: (id: string | null) => void;\n\n // Loop controls\n setLoopEnabled: (enabled: boolean) => void;\n setLoopRegion: (start: number, end: number) => void;\n setLoopRegionFromSelection: () => void;\n clearLoopRegion: () => void;\n}\n\nexport interface PlaylistDataContextValue {\n duration: number;\n audioBuffers: AudioBuffer[];\n peaksDataArray: TrackClipPeaks[]; // Array of tracks, each containing array of clip peaks\n trackStates: TrackState[];\n tracks: ClipTrack[]; // Original tracks array with IDs\n sampleRate: number;\n waveHeight: number;\n timeScaleHeight: number;\n minimumPlaylistHeight: number;\n controls: { show: boolean; width: number };\n playoutRef: React.RefObject<TonePlayout | null>;\n samplesPerPixel: number;\n timeFormat: string;\n masterVolume: number;\n canZoomIn: boolean;\n canZoomOut: boolean;\n barWidth: number;\n barGap: number;\n /** Width in pixels of progress bars. Defaults to barWidth + barGap (fills gaps). */\n progressBarWidth: number;\n}\n\n// Create the 4 separate contexts\nconst PlaybackAnimationContext = createContext<PlaybackAnimationContextValue | null>(null);\nconst PlaylistStateContext = createContext<PlaylistStateContextValue | null>(null);\nconst PlaylistControlsContext = createContext<PlaylistControlsContextValue | null>(null);\nconst PlaylistDataContext = createContext<PlaylistDataContextValue | null>(null);\n\n// Keep the original context for backwards compatibility\nconst WaveformPlaylistContext = createContext<WaveformPlaylistContextValue | null>(null);\n\nexport interface WaveformPlaylistProviderProps {\n tracks: ClipTrack[]; // Updated to use clip-based model\n timescale?: boolean;\n mono?: boolean;\n waveHeight?: number;\n samplesPerPixel?: number;\n zoomLevels?: number[]; // Array of zoom levels in samples per pixel (lower = more zoomed in)\n automaticScroll?: boolean;\n theme?: Partial<WaveformPlaylistTheme>;\n controls?: {\n show: boolean;\n width: number;\n };\n annotationList?: {\n annotations?: any[];\n editable?: boolean;\n isContinuousPlay?: boolean;\n linkEndpoints?: boolean;\n controls?: any[];\n };\n effects?: EffectsFunction;\n onReady?: () => void;\n onAnnotationUpdate?: (annotations: AnnotationData[]) => void;\n /** Width in pixels of waveform bars. Default: 1 */\n barWidth?: number;\n /** Spacing in pixels between waveform bars. Default: 0 */\n barGap?: number;\n /** Width in pixels of progress bars. Default: barWidth + barGap (fills gaps). */\n progressBarWidth?: number;\n children: ReactNode;\n}\n\nexport const WaveformPlaylistProvider: React.FC<WaveformPlaylistProviderProps> = ({\n tracks,\n timescale = false,\n mono = false,\n waveHeight = 80,\n samplesPerPixel: initialSamplesPerPixel = 1024,\n zoomLevels,\n automaticScroll = false,\n theme: userTheme,\n controls = { show: false, width: 0 },\n annotationList,\n effects,\n onReady,\n onAnnotationUpdate: _onAnnotationUpdate,\n barWidth = 1,\n barGap = 0,\n progressBarWidth: progressBarWidthProp,\n children,\n}) => {\n // Default progressBarWidth to barWidth + barGap (fills gaps)\n const progressBarWidth = progressBarWidthProp ?? (barWidth + barGap);\n // State\n const [annotations, setAnnotations] = useState<AnnotationData[]>([]);\n const [activeAnnotationId, setActiveAnnotationIdState] = useState<string | null>(null);\n const [isPlaying, setIsPlaying] = useState(false);\n const [currentTime, setCurrentTime] = useState(0);\n const [duration, setDuration] = useState(0);\n const [audioBuffers, setAudioBuffers] = useState<AudioBuffer[]>([]);\n const [peaksDataArray, setPeaksDataArray] = useState<TrackClipPeaks[]>([]); // Updated for clip-based peaks\n const [trackStates, setTrackStates] = useState<TrackState[]>([]);\n const [selectionStart, setSelectionStart] = useState(0);\n const [selectionEnd, setSelectionEnd] = useState(0);\n const [selectedTrackId, setSelectedTrackId] = useState<string | null>(null);\n const [isAutomaticScroll, setIsAutomaticScroll] = useState(automaticScroll);\n const [continuousPlay, setContinuousPlayState] = useState(annotationList?.isContinuousPlay ?? false);\n const [linkEndpoints, setLinkEndpoints] = useState(annotationList?.linkEndpoints ?? true);\n const [annotationsEditable, setAnnotationsEditable] = useState(annotationList?.editable ?? false);\n const [isLoopEnabled, setIsLoopEnabledState] = useState(false);\n const [loopStart, setLoopStartState] = useState(0);\n const [loopEnd, setLoopEndState] = useState(0);\n\n // Refs\n const playoutRef = useRef<TonePlayout | null>(null);\n const playStartPositionRef = useRef<number>(0);\n const currentTimeRef = useRef<number>(0);\n const animationFrameRef = useRef<number | null>(null);\n const trackStatesRef = useRef<TrackState[]>(trackStates);\n const playbackStartTimeRef = useRef<number>(0); // context.currentTime when playback started\n const audioStartPositionRef = useRef<number>(0); // Audio position when playback started\n const playbackEndTimeRef = useRef<number | null>(null); // Audio position where playback should stop (for selections)\n const scrollContainerRef = useRef<HTMLDivElement | null>(null);\n const isAutomaticScrollRef = useRef<boolean>(false);\n const continuousPlayRef = useRef<boolean>(annotationList?.isContinuousPlay ?? false);\n const activeAnnotationIdRef = useRef<string | null>(null);\n const samplesPerPixelRef = useRef<number>(initialSamplesPerPixel);\n const isLoopEnabledRef = useRef<boolean>(false);\n const selectionStartRef = useRef<number>(0);\n const selectionEndRef = useRef<number>(0);\n const loopStartRef = useRef<number>(0);\n const loopEndRef = useRef<number>(0);\n\n // Custom hooks\n const { timeFormat, setTimeFormat, formatTime } = useTimeFormat();\n const zoom = useZoomControls({ initialSamplesPerPixel, zoomLevels });\n const samplesPerPixel = zoom.samplesPerPixel;\n const { masterVolume, setMasterVolume } = useMasterVolume({ playoutRef, initialVolume: 1.0 });\n\n // Custom setter for continuousPlay that updates BOTH state and ref synchronously\n // This ensures the ref is updated immediately, before the animation loop can read it\n const setContinuousPlay = useCallback((value: boolean) => {\n continuousPlayRef.current = value; // Update ref synchronously\n setContinuousPlayState(value); // Update state (triggers re-render)\n }, []);\n\n // Custom setter for activeAnnotationId that updates BOTH state and ref synchronously\n const setActiveAnnotationId = useCallback((value: string | null) => {\n activeAnnotationIdRef.current = value; // Update ref synchronously\n setActiveAnnotationIdState(value); // Update state (triggers re-render)\n }, []);\n\n // Custom setter for isLoopEnabled that updates BOTH state and ref synchronously\n const setLoopEnabled = useCallback((value: boolean) => {\n isLoopEnabledRef.current = value; // Update ref synchronously\n setIsLoopEnabledState(value); // Update state (triggers re-render)\n }, []);\n\n // Loop region setters - Audacity-style separate loop points\n const setLoopRegion = useCallback((start: number, end: number) => {\n loopStartRef.current = start;\n loopEndRef.current = end;\n setLoopStartState(start);\n setLoopEndState(end);\n }, []);\n\n const setLoopRegionFromSelection = useCallback(() => {\n const start = selectionStartRef.current;\n const end = selectionEndRef.current;\n if (start !== end && end > start) {\n setLoopRegion(start, end);\n }\n }, [setLoopRegion]);\n\n const clearLoopRegion = useCallback(() => {\n setLoopRegion(0, 0);\n }, [setLoopRegion]);\n\n // Keep refs in sync with state\n useEffect(() => {\n isAutomaticScrollRef.current = isAutomaticScroll;\n }, [isAutomaticScroll]);\n\n useEffect(() => {\n trackStatesRef.current = trackStates;\n }, [trackStates]);\n\n // Keep selection refs in sync for animation loop access\n useEffect(() => {\n selectionStartRef.current = selectionStart;\n selectionEndRef.current = selectionEnd;\n }, [selectionStart, selectionEnd]);\n\n // Adjust scroll position proportionally when zoom changes\n useEffect(() => {\n if (!scrollContainerRef.current || !audioBuffers.length) return;\n\n const container = scrollContainerRef.current;\n const oldSamplesPerPixel = samplesPerPixelRef.current;\n const newSamplesPerPixel = samplesPerPixel;\n\n if (oldSamplesPerPixel === newSamplesPerPixel) return;\n\n // Calculate the current center time in the viewport\n const controlWidth = controls.show ? controls.width : 0;\n const containerWidth = container.clientWidth;\n const currentScrollLeft = container.scrollLeft;\n const centerPixel = currentScrollLeft + containerWidth / 2 - controlWidth;\n const sr = audioBuffers[0].sampleRate;\n const centerTime = (centerPixel * oldSamplesPerPixel) / sr;\n\n // Calculate new scroll position to keep the same center time\n const newCenterPixel = (centerTime * sr) / newSamplesPerPixel;\n const newScrollLeft = Math.max(0, newCenterPixel + controlWidth - containerWidth / 2);\n\n container.scrollLeft = newScrollLeft;\n samplesPerPixelRef.current = newSamplesPerPixel;\n }, [samplesPerPixel, audioBuffers, controls]);\n\n // Track pending playback resume after tracks change\n const pendingResumeRef = useRef<{ position: number } | null>(null);\n\n // Load audio from clips (only when tracks change)\n useEffect(() => {\n if (tracks.length === 0) {\n // Clear state when all tracks are removed\n setAudioBuffers([]);\n setDuration(0);\n setTrackStates([]);\n setPeaksDataArray([]);\n if (playoutRef.current) {\n playoutRef.current.dispose();\n playoutRef.current = null;\n }\n return;\n }\n\n // Capture playback state before rebuilding playout\n const wasPlaying = isPlaying;\n const resumePosition = currentTimeRef.current;\n\n // Stop current playback and animation before disposing\n if (playoutRef.current && wasPlaying) {\n playoutRef.current.stop();\n if (animationFrameRef.current) {\n cancelAnimationFrame(animationFrameRef.current);\n animationFrameRef.current = null;\n }\n // Mark that we need to resume playback after playout is rebuilt\n pendingResumeRef.current = { position: resumePosition };\n }\n\n const loadAudio = async () => {\n try {\n // Extract all audio buffers from clips (only those that have audioBuffer)\n // For now, collect the first clip's buffer from each track\n const buffers: AudioBuffer[] = [];\n\n tracks.forEach((track) => {\n if (track.clips.length > 0 && track.clips[0].audioBuffer) {\n // Use first clip's buffer for now (full multi-clip support comes in next phase)\n buffers.push(track.clips[0].audioBuffer);\n }\n });\n\n // Calculate total timeline duration from all clips across all tracks\n // Use clip.sampleRate which is always defined (works for peaks-only clips too)\n let maxDuration = 0;\n tracks.forEach((track) => {\n track.clips.forEach((clip) => {\n const sampleRate = clip.sampleRate;\n const clipEndSample = clip.startSample + clip.durationSamples;\n const clipEnd = clipEndSample / sampleRate;\n maxDuration = Math.max(maxDuration, clipEnd);\n });\n });\n\n setAudioBuffers(buffers);\n setDuration(maxDuration);\n\n // Initialize or update track states, preserving existing UI state (mute/solo/volume/pan)\n // Only initialize from ClipTrack props when trackStates is empty or track count changes\n setTrackStates(prevStates => {\n if (prevStates.length === tracks.length) {\n // Same number of tracks - preserve existing UI state, just update names\n return prevStates.map((state, i) => ({\n ...state,\n name: tracks[i].name,\n }));\n }\n // Track count changed - reinitialize from ClipTrack properties\n return tracks.map((track) => ({\n name: track.name,\n muted: track.muted,\n soloed: track.soloed,\n volume: track.volume,\n pan: track.pan,\n }));\n });\n\n // Dispose old playout before creating new one\n if (playoutRef.current) {\n playoutRef.current.dispose();\n }\n\n // Create playout with clips\n const playout = new TonePlayout({\n effects,\n });\n\n // For each track, create a ToneTrack with all clips\n // Use trackStatesRef for current UI state (mute/solo/volume/pan) instead of track props\n const currentTrackStates = trackStatesRef.current;\n tracks.forEach((track, index) => {\n // Filter to only clips with audioBuffer (peaks-only clips can't be played)\n const playableClips = track.clips.filter(clip => clip.audioBuffer);\n\n if (playableClips.length > 0) {\n // Calculate track start and end times from clips (converting samples to seconds)\n // Use clip.sampleRate which is always defined\n const sampleRate = playableClips[0].sampleRate;\n const startTime = Math.min(...playableClips.map(c => c.startSample / sampleRate));\n const endTime = Math.max(...playableClips.map(c => (c.startSample + c.durationSamples) / sampleRate));\n\n // Use current UI state if available, otherwise fall back to track props\n const trackState = currentTrackStates[index];\n const trackObj: Track = {\n id: `track-${index}`, // Use consistent index-based ID for track controls\n name: track.name,\n gain: trackState?.volume ?? track.volume,\n muted: trackState?.muted ?? track.muted,\n soloed: trackState?.soloed ?? track.soloed,\n stereoPan: trackState?.pan ?? track.pan,\n startTime,\n endTime,\n };\n\n // Convert ClipTrack clips to ToneTrack ClipInfo format\n // Note: ClipInfo.startTime is relative to track start, not absolute timeline\n const clipInfos = playableClips.map(clip => {\n const clipSampleRate = clip.sampleRate;\n return {\n buffer: clip.audioBuffer!, // We filtered for audioBuffer above\n startTime: (clip.startSample / clipSampleRate) - startTime, // Make relative to track start\n duration: clip.durationSamples / clipSampleRate,\n offset: clip.offsetSamples / clipSampleRate,\n fadeIn: clip.fadeIn,\n fadeOut: clip.fadeOut,\n gain: clip.gain,\n };\n });\n\n playout.addTrack({\n clips: clipInfos,\n track: trackObj,\n effects: track.effects, // Pass track effects\n });\n }\n });\n\n // Apply solo muting after all tracks are added\n playout.applyInitialSoloState();\n\n playoutRef.current = playout;\n onReady?.();\n } catch (error) {\n console.error('Error loading audio:', error);\n }\n };\n\n loadAudio();\n\n return () => {\n if (animationFrameRef.current) {\n cancelAnimationFrame(animationFrameRef.current);\n }\n if (playoutRef.current) {\n playoutRef.current.dispose();\n }\n };\n }, [tracks, onReady, isPlaying]);\n\n // Regenerate peaks when zoom or mono changes (without reloading audio)\n useEffect(() => {\n if (tracks.length === 0) return;\n\n const bits = 16;\n\n // Generate peaks for each clip in each track\n const allTrackPeaks: TrackClipPeaks[] = tracks.map((track) => {\n const clipPeaks: ClipPeaks[] = track.clips.map((clip) => {\n // Check if clip has pre-computed waveform data\n if (clip.waveformData) {\n // Use waveform-data.js to resample and slice as needed\n // Pass sample values directly for accuracy\n const extractedPeaks = extractPeaksFromWaveformData(\n clip.waveformData as any, // Cast to WaveformData type\n samplesPerPixel,\n 0, // channel index\n clip.offsetSamples,\n clip.durationSamples\n );\n\n return {\n clipId: clip.id,\n trackName: track.name,\n peaks: {\n length: extractedPeaks.length,\n data: [extractedPeaks.data], // Wrap in array for channel compatibility\n bits: extractedPeaks.bits,\n },\n startSample: clip.startSample,\n durationSamples: clip.durationSamples,\n fadeIn: clip.fadeIn,\n fadeOut: clip.fadeOut,\n };\n }\n\n // Fall back to generating peaks from audioBuffer\n // If no audioBuffer either, return empty peaks (clip has no visual data)\n if (!clip.audioBuffer) {\n console.warn(`Clip \"${clip.name || clip.id}\" has neither waveformData nor audioBuffer - rendering empty`);\n return {\n clipId: clip.id,\n trackName: track.name,\n peaks: {\n length: 0,\n data: [],\n bits: bits,\n },\n startSample: clip.startSample,\n durationSamples: clip.durationSamples,\n fadeIn: clip.fadeIn,\n fadeOut: clip.fadeOut,\n };\n }\n\n const peaks = generatePeaks(\n clip.audioBuffer,\n samplesPerPixel,\n mono,\n bits,\n clip.offsetSamples,\n clip.durationSamples\n );\n\n return {\n clipId: clip.id,\n trackName: track.name,\n peaks,\n startSample: clip.startSample,\n durationSamples: clip.durationSamples,\n fadeIn: clip.fadeIn,\n fadeOut: clip.fadeOut,\n };\n });\n\n return clipPeaks;\n });\n\n setPeaksDataArray(allTrackPeaks);\n }, [tracks, samplesPerPixel, mono]);\n\n // Load annotations from annotationList prop\n useEffect(() => {\n if (annotationList?.annotations) {\n // Parse Aeneas format annotations to AnnotationData format\n const parsedAnnotations = annotationList.annotations.map((ann: any) => {\n // If it's already in the correct format, use it\n if (typeof ann.start === 'number') {\n return ann;\n }\n // Otherwise parse from Aeneas format\n return parseAeneas(ann);\n });\n setAnnotations(parsedAnnotations);\n }\n }, [annotationList]);\n\n // Animation loop\n const startAnimationLoop = useCallback(() => {\n // Cancel any existing animation frame before starting a new one\n if (animationFrameRef.current) {\n cancelAnimationFrame(animationFrameRef.current);\n animationFrameRef.current = null;\n }\n\n const updateTime = () => {\n // Calculate current position based on context.currentTime timing\n const elapsed = getContext().currentTime - playbackStartTimeRef.current;\n const time = audioStartPositionRef.current + elapsed;\n currentTimeRef.current = time;\n\n // Update state on every frame - context splitting isolates this from other components\n setCurrentTime(time);\n\n // Handle annotation playback based on continuous play mode\n if (annotations.length > 0) {\n const currentAnnotation = annotations.find(\n (ann) => time >= ann.start && time < ann.end\n );\n\n if (continuousPlayRef.current) {\n // Continuous play ON: update active annotation and stop after last annotation\n if (currentAnnotation && currentAnnotation.id !== activeAnnotationIdRef.current) {\n setActiveAnnotationId(currentAnnotation.id);\n } else if (!currentAnnotation && activeAnnotationIdRef.current !== null) {\n // We're no longer in any annotation - check if we're past the last one\n const lastAnnotation = annotations[annotations.length - 1];\n if (time >= lastAnnotation.end) {\n // Stop playback - we've finished all annotations\n if (playoutRef.current) {\n playoutRef.current.stop();\n }\n setIsPlaying(false);\n currentTimeRef.current = playStartPositionRef.current;\n setCurrentTime(playStartPositionRef.current);\n setActiveAnnotationId(null);\n return;\n }\n }\n } else {\n // Continuous play OFF: stop at end of current annotation\n if (activeAnnotationIdRef.current) {\n const activeAnnotation = annotations.find(ann => ann.id === activeAnnotationIdRef.current);\n if (activeAnnotation && time >= activeAnnotation.end) {\n // Stop playback at end of current annotation\n if (playoutRef.current) {\n playoutRef.current.stop();\n }\n setIsPlaying(false);\n currentTimeRef.current = playStartPositionRef.current;\n setCurrentTime(playStartPositionRef.current);\n return;\n }\n } else {\n // If no active annotation ID is set, use the current annotation\n if (currentAnnotation) {\n setActiveAnnotationId(currentAnnotation.id);\n }\n }\n }\n }\n\n // Handle automatic scroll - continuously center the playhead\n if (isAutomaticScrollRef.current && scrollContainerRef.current && audioBuffers.length > 0) {\n const container = scrollContainerRef.current;\n const sr = audioBuffers[0].sampleRate;\n const pixelPosition = (time * sr) / samplesPerPixelRef.current;\n const containerWidth = container.clientWidth;\n\n // Calculate visual position of playhead (includes controls offset)\n const controlWidth = controls.show ? controls.width : 0;\n const visualPosition = pixelPosition + controlWidth;\n\n // Continuously scroll to keep playhead centered\n const targetScrollLeft = Math.max(0, visualPosition - containerWidth / 2);\n container.scrollLeft = targetScrollLeft;\n }\n\n // Check if we've reached the playback end time (for selection playback)\n if (playbackEndTimeRef.current !== null && time >= playbackEndTimeRef.current) {\n // Stop playback at selection end (selection playback is separate from looping)\n if (playoutRef.current) {\n playoutRef.current.stop();\n }\n setIsPlaying(false);\n currentTimeRef.current = playbackEndTimeRef.current;\n setCurrentTime(playbackEndTimeRef.current);\n playbackEndTimeRef.current = null; // Clear the end time\n return;\n }\n\n // Audacity-style loop region: loop when cursor enters and reaches end of loop region\n const hasValidLoopRegion = loopStartRef.current !== loopEndRef.current &&\n loopEndRef.current > loopStartRef.current;\n\n if (isLoopEnabledRef.current && hasValidLoopRegion) {\n // Check if we've reached or passed the loop end point\n if (time >= loopEndRef.current) {\n // Loop: restart from loop start\n playoutRef.current?.stop();\n\n const context = getContext();\n const timeNow = context.currentTime;\n playbackStartTimeRef.current = timeNow;\n audioStartPositionRef.current = loopStartRef.current;\n currentTimeRef.current = loopStartRef.current;\n\n // Restart playback from loop start (no duration limit - will loop again when reaching loop end)\n playoutRef.current?.play(timeNow, loopStartRef.current);\n\n // Continue animation loop\n animationFrameRef.current = requestAnimationFrame(updateTime);\n return;\n }\n }\n\n if (time >= duration) {\n // Stop playback - inline to avoid circular dependency\n if (playoutRef.current) {\n playoutRef.current.stop();\n }\n setIsPlaying(false);\n currentTimeRef.current = playStartPositionRef.current;\n setCurrentTime(playStartPositionRef.current);\n setActiveAnnotationId(null);\n return;\n }\n animationFrameRef.current = requestAnimationFrame(updateTime);\n };\n animationFrameRef.current = requestAnimationFrame(updateTime);\n }, [duration, audioBuffers, samplesPerPixel, annotations, continuousPlay]);\n\n const stopAnimationLoop = useCallback(() => {\n if (animationFrameRef.current) {\n cancelAnimationFrame(animationFrameRef.current);\n animationFrameRef.current = null;\n }\n }, []);\n\n // Restart animation loop and reschedule playout when continuousPlay changes during playback\n // This ensures the loop always has the current continuousPlay value\n // and removes duration limits when switching to continuous play\n useEffect(() => {\n const reschedulePlayback = async () => {\n if (isPlaying && animationFrameRef.current && playoutRef.current) {\n // When toggling continuous play ON, reschedule playout without duration limit\n // so audio continues past the current annotation boundary\n if (continuousPlay) {\n const currentPos = currentTimeRef.current;\n\n // Stop current playout (which may have duration limit + pause callback)\n playoutRef.current.stop();\n stopAnimationLoop();\n\n // Initialize and restart from current position without duration limit\n await playoutRef.current.init();\n\n // Clear any existing playback complete callback\n playoutRef.current.setOnPlaybackComplete(() => {});\n\n const context = getContext();\n const timeNow = context.currentTime;\n playbackStartTimeRef.current = timeNow;\n audioStartPositionRef.current = currentPos;\n\n // Play without duration - will play to end of track\n playoutRef.current.play(timeNow, currentPos);\n startAnimationLoop();\n } else {\n // Just restart animation loop for continuous play OFF\n stopAnimationLoop();\n startAnimationLoop();\n }\n }\n };\n\n reschedulePlayback();\n }, [continuousPlay, isPlaying, startAnimationLoop, stopAnimationLoop]);\n\n // Resume playback after tracks change (e.g., after splitting a clip during playback)\n useEffect(() => {\n const resumePlayback = async () => {\n if (pendingResumeRef.current && playoutRef.current) {\n const { position } = pendingResumeRef.current;\n pendingResumeRef.current = null;\n\n await playoutRef.current.init();\n playoutRef.current.setOnPlaybackComplete(() => {});\n\n const context = getContext();\n const timeNow = context.currentTime;\n playbackStartTimeRef.current = timeNow;\n audioStartPositionRef.current = position;\n\n playoutRef.current.play(timeNow, position);\n setIsPlaying(true);\n startAnimationLoop();\n }\n };\n\n resumePlayback();\n }, [tracks, startAnimationLoop]);\n\n // Playback controls\n const play = useCallback(async (startTime?: number, playDuration?: number) => {\n if (!playoutRef.current || audioBuffers.length === 0) return;\n\n await playoutRef.current.init();\n\n // Resume Tone.js context if needed (required for Safari and user interaction)\n await toneStart();\n\n const actualStartTime = startTime ?? currentTimeRef.current;\n playStartPositionRef.current = actualStartTime;\n\n // Update currentTimeRef to match the actual start position\n // This ensures the animation loop starts from the correct position\n currentTimeRef.current = actualStartTime;\n\n // Clear any existing playback complete callback before stopping\n // Otherwise stopping will trigger the old callback and interfere with new playback\n playoutRef.current.setOnPlaybackComplete(() => {});\n\n // Stop any existing playback and animation loop before starting\n playoutRef.current.stop();\n stopAnimationLoop();\n\n // Record timing for accurate position tracking using Tone.js context\n const context = getContext();\n // Tone.js context wraps Web Audio - need to use .currentTime from wrapped context\n const startTimeNow = context.currentTime;\n playbackStartTimeRef.current = startTimeNow;\n audioStartPositionRef.current = actualStartTime;\n\n // Set playback end time if playing with duration (e.g., selection playback)\n playbackEndTimeRef.current = playDuration !== undefined ? actualStartTime + playDuration : null;\n\n // Don't set up playback complete callback for annotations\n // The animation loop handles stopping at annotation boundaries\n // This avoids callback timing issues when switching between annotations\n\n playoutRef.current.play(startTimeNow, actualStartTime, playDuration);\n setIsPlaying(true);\n startAnimationLoop();\n }, [audioBuffers.length, startAnimationLoop, stopAnimationLoop]);\n\n const pause = useCallback(() => {\n if (!playoutRef.current) return;\n\n // Calculate exact pause position using context.currentTime timing\n const elapsed = getContext().currentTime - playbackStartTimeRef.current;\n const pauseTime = audioStartPositionRef.current + elapsed;\n\n playoutRef.current.pause();\n setIsPlaying(false);\n stopAnimationLoop();\n\n // Update to the calculated pause position\n currentTimeRef.current = pauseTime;\n setCurrentTime(pauseTime);\n }, [stopAnimationLoop]);\n\n const stop = useCallback(() => {\n if (!playoutRef.current) return;\n\n playoutRef.current.stop();\n setIsPlaying(false);\n stopAnimationLoop();\n\n currentTimeRef.current = playStartPositionRef.current;\n setCurrentTime(playStartPositionRef.current);\n setActiveAnnotationId(null);\n }, [stopAnimationLoop]);\n\n // Seek to a specific time - works whether playing or stopped\n const seekTo = useCallback((time: number) => {\n // Clamp time to valid range\n const clampedTime = Math.max(0, Math.min(time, duration));\n\n // Update the current time state\n currentTimeRef.current = clampedTime;\n setCurrentTime(clampedTime);\n\n // If currently playing, stop and restart at the new position\n if (isPlaying && playoutRef.current) {\n playoutRef.current.stop();\n stopAnimationLoop();\n // Use play() which handles all the timing setup\n play(clampedTime);\n }\n }, [duration, isPlaying, play, stopAnimationLoop]);\n\n // Track controls\n const setTrackMute = useCallback((trackIndex: number, muted: boolean) => {\n const newStates = [...trackStates];\n newStates[trackIndex] = { ...newStates[trackIndex], muted };\n setTrackStates(newStates);\n\n if (playoutRef.current) {\n const trackId = `track-${trackIndex}`;\n playoutRef.current.setMute(trackId, muted);\n }\n }, [trackStates]);\n\n const setTrackSolo = useCallback((trackIndex: number, soloed: boolean) => {\n const newStates = [...trackStates];\n newStates[trackIndex] = { ...newStates[trackIndex], soloed };\n setTrackStates(newStates);\n\n if (playoutRef.current) {\n const trackId = `track-${trackIndex}`;\n playoutRef.current.setSolo(trackId, soloed);\n }\n }, [trackStates]);\n\n const setTrackVolume = useCallback((trackIndex: number, volume: number) => {\n const newStates = [...trackStates];\n newStates[trackIndex] = { ...newStates[trackIndex], volume };\n setTrackStates(newStates);\n\n if (playoutRef.current) {\n const trackId = `track-${trackIndex}`;\n const track = playoutRef.current.getTrack(trackId);\n if (track) {\n track.setVolume(volume);\n }\n }\n }, [trackStates]);\n\n const setTrackPan = useCallback((trackIndex: number, pan: number) => {\n const newStates = [...trackStates];\n newStates[trackIndex] = { ...newStates[trackIndex], pan };\n setTrackStates(newStates);\n\n if (playoutRef.current) {\n const trackId = `track-${trackIndex}`;\n const track = playoutRef.current.getTrack(trackId);\n if (track) {\n track.setPan(pan);\n }\n }\n }, [trackStates]);\n\n // Selection\n const setSelection = useCallback((start: number, end: number) => {\n setSelectionStart(start);\n setSelectionEnd(end);\n currentTimeRef.current = start;\n setCurrentTime(start);\n\n if (isPlaying && playoutRef.current) {\n playoutRef.current.stop();\n playoutRef.current.play(getContext().currentTime, start);\n }\n }, [isPlaying]);\n\n // Memoize setScrollContainer callback\n const setScrollContainer = useCallback((element: HTMLDivElement | null) => {\n scrollContainerRef.current = element;\n }, []);\n\n const sampleRate = audioBuffers[0]?.sampleRate || 44100;\n const timeScaleHeight = timescale ? 30 : 0;\n const minimumPlaylistHeight = (tracks.length * waveHeight) + timeScaleHeight;\n\n // Split context values for performance optimization\n // High-frequency updates (currentTime) isolated from other state\n\n const animationValue: PlaybackAnimationContextValue = {\n isPlaying,\n currentTime,\n currentTimeRef,\n playbackStartTimeRef,\n audioStartPositionRef,\n };\n\n const stateValue: PlaylistStateContextValue = {\n continuousPlay,\n linkEndpoints,\n annotationsEditable,\n isAutomaticScroll,\n isLoopEnabled,\n annotations,\n activeAnnotationId,\n selectionStart,\n selectionEnd,\n selectedTrackId,\n loopStart,\n loopEnd,\n };\n\n const controlsValue: PlaylistControlsContextValue = {\n // Playback controls\n play,\n pause,\n stop,\n seekTo,\n setCurrentTime: (time: number) => {\n currentTimeRef.current = time;\n setCurrentTime(time);\n },\n\n // Track controls\n setTrackMute,\n setTrackSolo,\n setTrackVolume,\n setTrackPan,\n\n // Selection\n setSelection,\n setSelectedTrackId,\n\n // Time format\n setTimeFormat,\n formatTime,\n\n // Zoom\n zoomIn: zoom.zoomIn,\n zoomOut: zoom.zoomOut,\n\n // Master volume\n setMasterVolume,\n\n // Automatic scroll\n setAutomaticScroll: (enabled: boolean) => {\n setIsAutomaticScroll(enabled);\n },\n setScrollContainer,\n scrollContainerRef,\n\n // Annotation controls\n setContinuousPlay,\n setLinkEndpoints,\n setAnnotationsEditable,\n setAnnotations,\n setActiveAnnotationId,\n\n // Loop controls\n setLoopEnabled,\n setLoopRegion,\n setLoopRegionFromSelection,\n clearLoopRegion,\n };\n\n const dataValue: PlaylistDataContextValue = {\n duration,\n audioBuffers,\n peaksDataArray,\n trackStates,\n tracks,\n sampleRate,\n waveHeight,\n timeScaleHeight,\n minimumPlaylistHeight,\n controls,\n playoutRef,\n samplesPerPixel,\n timeFormat,\n masterVolume,\n canZoomIn: zoom.canZoomIn,\n canZoomOut: zoom.canZoomOut,\n barWidth,\n barGap,\n progressBarWidth,\n };\n\n // Combined value for backwards compatibility\n const value: WaveformPlaylistContextValue = {\n ...animationValue,\n ...stateValue,\n ...controlsValue,\n ...dataValue,\n };\n\n // Merge user theme with default theme\n const mergedTheme = { ...defaultTheme, ...userTheme };\n\n return (\n <ThemeProvider theme={mergedTheme}>\n <PlaybackAnimationContext.Provider value={animationValue}>\n <PlaylistStateContext.Provider value={stateValue}>\n <PlaylistControlsContext.Provider value={controlsValue}>\n <PlaylistDataContext.Provider value={dataValue}>\n <WaveformPlaylistContext.Provider value={value}>\n {children}\n </WaveformPlaylistContext.Provider>\n </PlaylistDataContext.Provider>\n </PlaylistControlsContext.Provider>\n </PlaylistStateContext.Provider>\n </PlaybackAnimationContext.Provider>\n </ThemeProvider>\n );\n};\n\n// Individual hooks for each context - use these for optimal performance\n// Components only re-render when their specific context data changes\n\nexport const usePlaybackAnimation = () => {\n const context = useContext(PlaybackAnimationContext);\n if (!context) {\n throw new Error('usePlaybackAnimation must be used within WaveformPlaylistProvider');\n }\n return context;\n};\n\nexport const usePlaylistState = () => {\n const context = useContext(PlaylistStateContext);\n if (!context) {\n throw new Error('usePlaylistState must be used within WaveformPlaylistProvider');\n }\n return context;\n};\n\nexport const usePlaylistControls = () => {\n const context = useContext(PlaylistControlsContext);\n if (!context) {\n throw new Error('usePlaylistControls must be used within WaveformPlaylistProvider');\n }\n return context;\n};\n\nexport const usePlaylistData = () => {\n const context = useContext(PlaylistDataContext);\n if (!context) {\n throw new Error('usePlaylistData must be used within WaveformPlaylistProvider');\n }\n return context;\n};\n\n// Main hook that combines all contexts - use this for backwards compatibility\n// or when you need access to multiple contexts\nexport const useWaveformPlaylist = () => {\n const context = useContext(WaveformPlaylistContext);\n if (!context) {\n throw new Error('useWaveformPlaylist must be used within WaveformPlaylistProvider');\n }\n return context;\n};\n","// src/MediaElementTrack.ts\nvar MediaElementTrack = class {\n constructor(options) {\n this._playbackRate = 1;\n this.handleEnded = () => {\n if (this.onStopCallback) {\n this.onStopCallback();\n }\n };\n this.handleTimeUpdate = () => {\n if (this.onTimeUpdateCallback) {\n this.onTimeUpdateCallback(this.audioElement.currentTime);\n }\n };\n this._peaks = options.peaks;\n this._id = options.id ?? `track-${Date.now()}`;\n this._name = options.name ?? \"Track\";\n this._playbackRate = options.playbackRate ?? 1;\n if (typeof options.source === \"string\") {\n this.audioElement = new Audio(options.source);\n this.ownsElement = true;\n } else {\n this.audioElement = options.source;\n this.ownsElement = false;\n }\n this.audioElement.preload = \"auto\";\n this.audioElement.volume = options.volume ?? 1;\n this.audioElement.playbackRate = this._playbackRate;\n if (\"preservesPitch\" in this.audioElement) {\n this.audioElement.preservesPitch = true;\n } else if (\"mozPreservesPitch\" in this.audioElement) {\n this.audioElement.mozPreservesPitch = true;\n } else if (\"webkitPreservesPitch\" in this.audioElement) {\n this.audioElement.webkitPreservesPitch = true;\n }\n this.audioElement.addEventListener(\"ended\", this.handleEnded);\n this.audioElement.addEventListener(\"timeupdate\", this.handleTimeUpdate);\n }\n /**\n * Start playback from a specific time\n */\n play(offset = 0) {\n this.audioElement.currentTime = offset;\n this.audioElement.play().catch((err) => {\n console.warn(\"MediaElementTrack: play() failed:\", err);\n });\n }\n /**\n * Pause playback\n */\n pause() {\n this.audioElement.pause();\n }\n /**\n * Stop playback and reset to beginning\n */\n stop() {\n this.audioElement.pause();\n this.audioElement.currentTime = 0;\n }\n /**\n * Seek to a specific time\n */\n seekTo(time) {\n this.audioElement.currentTime = Math.max(0, Math.min(time, this.duration));\n }\n /**\n * Set volume (0.0 to 1.0)\n */\n setVolume(volume) {\n this.audioElement.volume = Math.max(0, Math.min(1, volume));\n }\n /**\n * Set playback rate (0.5 to 2.0, pitch preserved)\n */\n setPlaybackRate(rate) {\n const clampedRate = Math.max(0.5, Math.min(2, rate));\n this._playbackRate = clampedRate;\n this.audioElement.playbackRate = clampedRate;\n }\n /**\n * Set muted state\n */\n setMuted(muted) {\n this.audioElement.muted = muted;\n }\n /**\n * Set callback for when playback ends\n */\n setOnStopCallback(callback) {\n this.onStopCallback = callback;\n }\n /**\n * Set callback for time updates\n */\n setOnTimeUpdateCallback(callback) {\n this.onTimeUpdateCallback = callback;\n }\n /**\n * Clean up resources\n */\n dispose() {\n this.audioElement.removeEventListener(\"ended\", this.handleEnded);\n this.audioElement.removeEventListener(\"timeupdate\", this.handleTimeUpdate);\n this.audioElement.pause();\n if (this.ownsElement) {\n this.audioElement.src = \"\";\n this.audioElement.load();\n }\n }\n // Getters\n get id() {\n return this._id;\n }\n get name() {\n return this._name;\n }\n get peaks() {\n return this._peaks;\n }\n get currentTime() {\n return this.audioElement.currentTime;\n }\n get duration() {\n return this.audioElement.duration || this._peaks.duration;\n }\n get isPlaying() {\n return !this.audioElement.paused && !this.audioElement.ended;\n }\n get volume() {\n return this.audioElement.volume;\n }\n get playbackRate() {\n return this._playbackRate;\n }\n get muted() {\n return this.audioElement.muted;\n }\n /**\n * Get the underlying audio element (for advanced use cases)\n */\n get element() {\n return this.audioElement;\n }\n};\n\n// src/MediaElementPlayout.ts\nvar MediaElementPlayout = class {\n constructor(options = {}) {\n this.track = null;\n this._isPlaying = false;\n this._masterVolume = options.masterVolume ?? 1;\n this._playbackRate = options.playbackRate ?? 1;\n }\n /**\n * Initialize the playout engine.\n * For MediaElementPlayout this is a no-op (no AudioContext to start).\n */\n async init() {\n }\n /**\n * Add a track to the playout.\n * Note: Only one track is supported. Adding a second track will dispose the first.\n */\n addTrack(options) {\n if (this.track) {\n console.warn(\n \"MediaElementPlayout: Only one track is supported. Disposing previous track. For multi-track, use TonePlayout.\"\n );\n this.track.dispose();\n }\n this.track = new MediaElementTrack({\n ...options,\n volume: this._masterVolume * (options.volume ?? 1),\n playbackRate: this._playbackRate\n });\n this.track.setOnStopCallback(() => {\n this._isPlaying = false;\n if (this.onPlaybackCompleteCallback) {\n this.onPlaybackCompleteCallback();\n }\n });\n return this.track;\n }\n /**\n * Remove a track by ID.\n */\n removeTrack(trackId) {\n if (this.track && this.track.id === trackId) {\n this.track.dispose();\n this.track = null;\n }\n }\n /**\n * Get a track by ID.\n */\n getTrack(trackId) {\n if (this.track && this.track.id === trackId) {\n return this.track;\n }\n return void 0;\n }\n /**\n * Start playback.\n * @param _when - Ignored (HTMLAudioElement doesn't support scheduled start)\n * @param offset - Start position in seconds\n * @param duration - Duration to play in seconds (optional)\n */\n play(_when, offset, duration) {\n if (!this.track) {\n console.warn(\"MediaElementPlayout: No track to play\");\n return;\n }\n const startPosition = offset ?? 0;\n this._isPlaying = true;\n this.track.play(startPosition);\n if (duration !== void 0) {\n const adjustedDuration = duration / this._playbackRate;\n setTimeout(() => {\n if (this._isPlaying) {\n this.pause();\n if (this.onPlaybackCompleteCallback) {\n this.onPlaybackCompleteCallback();\n }\n }\n }, adjustedDuration * 1e3);\n }\n }\n /**\n * Pause playback.\n */\n pause() {\n if (this.track) {\n this.track.pause();\n }\n this._isPlaying = false;\n }\n /**\n * Stop playback and reset to start.\n */\n stop() {\n if (this.track) {\n this.track.stop();\n }\n this._isPlaying = false;\n }\n /**\n * Seek to a specific time.\n */\n seekTo(time) {\n if (this.track) {\n this.track.seekTo(time);\n }\n }\n /**\n * Get current playback time.\n */\n getCurrentTime() {\n if (this.track) {\n return this.track.currentTime;\n }\n return 0;\n }\n /**\n * Set master volume.\n */\n setMasterVolume(volume) {\n this._masterVolume = Math.max(0, Math.min(1, volume));\n if (this.track) {\n this.track.setVolume(this._masterVolume);\n }\n }\n /**\n * Set playback rate (0.5 to 2.0, pitch preserved).\n */\n setPlaybackRate(rate) {\n this._playbackRate = Math.max(0.5, Math.min(2, rate));\n if (this.track) {\n this.track.setPlaybackRate(this._playbackRate);\n }\n }\n /**\n * Set mute state for a track.\n */\n setMute(trackId, muted) {\n const track = this.getTrack(trackId);\n if (track) {\n track.setMuted(muted);\n }\n }\n /**\n * Set solo state for a track.\n * Note: With single track, solo is effectively the same as unmute.\n */\n setSolo(_trackId, _soloed) {\n console.warn(\"MediaElementPlayout: Solo is not applicable for single-track playback\");\n }\n /**\n * Set callback for when playback completes.\n */\n setOnPlaybackComplete(callback) {\n this.onPlaybackCompleteCallback = callback;\n }\n /**\n * Clean up resources.\n */\n dispose() {\n if (this.track) {\n this.track.dispose();\n this.track = null;\n }\n }\n // Getters\n get isPlaying() {\n return this._isPlaying;\n }\n get masterVolume() {\n return this._masterVolume;\n }\n get playbackRate() {\n return this._playbackRate;\n }\n get duration() {\n return this.track?.duration ?? 0;\n }\n get sampleRate() {\n return this.track?.peaks.sample_rate ?? 44100;\n }\n};\n\n// src/types.ts\nfunction supportsPlaybackRate(engine) {\n return \"setPlaybackRate\" in engine && typeof engine.setPlaybackRate === \"function\";\n}\nexport {\n MediaElementPlayout,\n MediaElementTrack,\n supportsPlaybackRate\n};\n//# sourceMappingURL=index.mjs.map","import React, {\n createContext,\n useContext,\n useState,\n useEffect,\n useRef,\n useCallback,\n useMemo,\n ReactNode,\n} from 'react';\nimport { ThemeProvider } from 'styled-components';\nimport {\n MediaElementPlayout,\n type MediaElementTrackOptions,\n} from '@waveform-playlist/media-element-playout';\nimport { type WaveformDataObject } from '@waveform-playlist/core';\nimport {\n type WaveformPlaylistTheme,\n defaultTheme,\n} from '@waveform-playlist/ui-components';\nimport { parseAeneas, type AnnotationData } from '@waveform-playlist/annotations';\nimport { extractPeaksFromWaveformData } from './waveformDataLoader';\nimport type { PeakData } from '@waveform-playlist/webaudio-peaks';\nimport type { ClipPeaks, TrackClipPeaks } from './WaveformPlaylistContext';\n\n// Configuration for a single media element track\nexport interface MediaElementTrackConfig {\n /** Audio source URL or Blob URL */\n source: string;\n /** Pre-computed waveform data (required for visualization) */\n waveformData: WaveformDataObject;\n /** Track name for display */\n name?: string;\n}\n\n// Context values for animation (high-frequency updates)\nexport interface MediaElementAnimationContextValue {\n isPlaying: boolean;\n currentTime: number;\n currentTimeRef: React.RefObject<number>;\n}\n\n// Context values for playlist state\nexport interface MediaElementStateContextValue {\n continuousPlay: boolean;\n annotations: AnnotationData[];\n activeAnnotationId: string | null;\n playbackRate: number;\n}\n\n// Context values for controls\nexport interface MediaElementControlsContextValue {\n play: (startTime?: number) => void;\n pause: () => void;\n stop: () => void;\n seekTo: (time: number) => void;\n setPlaybackRate: (rate: number) => void;\n setContinuousPlay: (enabled: boolean) => void;\n setAnnotations: (annotations: AnnotationData[]) => void;\n setActiveAnnotationId: (id: string | null) => void;\n}\n\n// Context values for playlist data\nexport interface MediaElementDataContextValue {\n duration: number;\n peaksDataArray: TrackClipPeaks[];\n sampleRate: number;\n waveHeight: number;\n timeScaleHeight: number;\n samplesPerPixel: number;\n playoutRef: React.RefObject<MediaElementPlayout | null>;\n controls: { show: boolean; width: number };\n barWidth: number;\n barGap: number;\n progressBarWidth: number;\n}\n\n// Create contexts\nconst MediaElementAnimationContext =\n createContext<MediaElementAnimationContextValue | null>(null);\nconst MediaElementStateContext =\n createContext<MediaElementStateContextValue | null>(null);\nconst MediaElementControlsContext =\n createContext<MediaElementControlsContextValue | null>(null);\nconst MediaElementDataContext =\n createContext<MediaElementDataContextValue | null>(null);\n\nexport interface MediaElementPlaylistProviderProps {\n /** Single track configuration with source URL and waveform data */\n track: MediaElementTrackConfig;\n /** Initial samples per pixel (zoom level) */\n samplesPerPixel?: number;\n /** Height of each waveform track */\n waveHeight?: number;\n /** Show timescale */\n timescale?: boolean;\n /** Initial playback rate (0.5 to 2.0) */\n playbackRate?: number;\n /** Theme configuration */\n theme?: Partial<WaveformPlaylistTheme>;\n /** Track controls configuration */\n controls?: { show: boolean; width: number };\n /** Annotations */\n annotationList?: {\n annotations?: any[];\n isContinuousPlay?: boolean;\n };\n /** Width of waveform bars */\n barWidth?: number;\n /** Gap between waveform bars */\n barGap?: number;\n /** Width of progress bars */\n progressBarWidth?: number;\n /** Callback when audio is ready */\n onReady?: () => void;\n children: ReactNode;\n}\n\n/**\n * MediaElementPlaylistProvider\n *\n * A simplified playlist provider for single-track playback using HTMLAudioElement.\n * Key features:\n * - Pitch-preserving playback rate (0.5x - 2.0x)\n * - Pre-computed peaks visualization (no AudioBuffer needed)\n * - Simpler API than full WaveformPlaylistProvider\n *\n * Use this for:\n * - Language learning apps (speed control)\n * - Podcast players\n * - Single-track audio viewers\n *\n * For multi-track editing, use WaveformPlaylistProvider instead.\n */\nexport const MediaElementPlaylistProvider: React.FC<\n MediaElementPlaylistProviderProps\n> = ({\n track,\n samplesPerPixel: initialSamplesPerPixel = 1024,\n waveHeight = 100,\n timescale = false,\n playbackRate: initialPlaybackRate = 1,\n theme: userTheme,\n controls = { show: false, width: 0 },\n annotationList,\n barWidth = 1,\n barGap = 0,\n progressBarWidth: progressBarWidthProp,\n onReady,\n children,\n}) => {\n const progressBarWidth = progressBarWidthProp ?? barWidth + barGap;\n\n // State\n const [isPlaying, setIsPlaying] = useState(false);\n const [currentTime, setCurrentTime] = useState(0);\n const [duration, setDuration] = useState(0);\n const [peaksDataArray, setPeaksDataArray] = useState<TrackClipPeaks[]>([]);\n const [playbackRate, setPlaybackRateState] = useState(initialPlaybackRate);\n const [annotations, setAnnotations] = useState<AnnotationData[]>([]);\n const [activeAnnotationId, setActiveAnnotationIdState] = useState<\n string | null\n >(null);\n const [continuousPlay, setContinuousPlayState] = useState(\n annotationList?.isContinuousPlay ?? false\n );\n const [samplesPerPixel] = useState(initialSamplesPerPixel);\n\n // Refs\n const playoutRef = useRef<MediaElementPlayout | null>(null);\n const currentTimeRef = useRef<number>(0);\n const animationFrameRef = useRef<number | null>(null);\n const continuousPlayRef = useRef<boolean>(continuousPlay);\n const activeAnnotationIdRef = useRef<string | null>(null);\n\n // Sync refs\n useEffect(() => {\n continuousPlayRef.current = continuousPlay;\n }, [continuousPlay]);\n\n // Custom setter for activeAnnotationId\n const setActiveAnnotationId = useCallback((value: string | null) => {\n activeAnnotationIdRef.current = value;\n setActiveAnnotationIdState(value);\n }, []);\n\n const setContinuousPlay = useCallback((value: boolean) => {\n continuousPlayRef.current = value;\n setContinuousPlayState(value);\n }, []);\n\n // Get sample rate from waveform data\n const sampleRate = track.waveformData.sample_rate;\n\n // Initialize playout and load track\n useEffect(() => {\n const playout = new MediaElementPlayout({\n playbackRate: initialPlaybackRate,\n });\n\n playout.addTrack({\n source: track.source,\n peaks: track.waveformData,\n name: track.name,\n });\n\n // Set up time update callback\n const mediaTrack = playout.getTrack(playout['track']?.id ?? '');\n if (mediaTrack) {\n mediaTrack.setOnTimeUpdateCallback((time) => {\n currentTimeRef.current = time;\n });\n }\n\n // Set up playback complete callback\n playout.setOnPlaybackComplete(() => {\n setIsPlaying(false);\n });\n\n playoutRef.current = playout;\n setDuration(track.waveformData.duration);\n onReady?.();\n\n return () => {\n if (animationFrameRef.current) {\n cancelAnimationFrame(animationFrameRef.current);\n }\n playout.dispose();\n };\n }, [track.source, track.waveformData, track.name, initialPlaybackRate, onReady]);\n\n // Generate peaks from waveform data\n useEffect(() => {\n const extractedPeaks = extractPeaksFromWaveformData(\n track.waveformData as any,\n samplesPerPixel,\n 0, // channel index\n 0, // offset\n Math.ceil(track.waveformData.duration * sampleRate) // duration in samples\n );\n\n const clipPeaks: ClipPeaks = {\n clipId: 'media-element-clip',\n trackName: track.name ?? 'Track',\n peaks: {\n length: extractedPeaks.length,\n data: [extractedPeaks.data],\n bits: extractedPeaks.bits,\n } as PeakData,\n startSample: 0,\n durationSamples: Math.ceil(track.waveformData.duration * sampleRate),\n };\n\n setPeaksDataArray([[clipPeaks]]);\n }, [track.waveformData, track.name, samplesPerPixel, sampleRate]);\n\n // Load annotations\n useEffect(() => {\n if (annotationList?.annotations) {\n const parsedAnnotations = annotationList.annotations.map((ann: any) => {\n if (typeof ann.start === 'number') {\n return ann;\n }\n return parseAeneas(ann);\n });\n setAnnotations(parsedAnnotations);\n }\n }, [annotationList]);\n\n // Animation loop\n const startAnimationLoop = useCallback(() => {\n if (animationFrameRef.current) {\n cancelAnimationFrame(animationFrameRef.current);\n }\n\n const updateTime = () => {\n const time = playoutRef.current?.getCurrentTime() ?? 0;\n currentTimeRef.current = time;\n setCurrentTime(time);\n\n // Handle annotation playback\n if (annotations.length > 0) {\n const currentAnnotation = annotations.find(\n (ann) => time >= ann.start && time < ann.end\n );\n\n if (continuousPlayRef.current) {\n if (\n currentAnnotation &&\n currentAnnotation.id !== activeAnnotationIdRef.current\n ) {\n setActiveAnnotationId(currentAnnotation.id);\n } else if (!currentAnnotation && activeAnnotationIdRef.current !== null) {\n const lastAnnotation = annotations[annotations.length - 1];\n if (time >= lastAnnotation.end) {\n playoutRef.current?.stop();\n setIsPlaying(false);\n setActiveAnnotationId(null);\n return;\n }\n }\n } else {\n if (activeAnnotationIdRef.current) {\n const activeAnnotation = annotations.find(\n (ann) => ann.id === activeAnnotationIdRef.current\n );\n if (activeAnnotation && time >= activeAnnotation.end) {\n playoutRef.current?.stop();\n setIsPlaying(false);\n return;\n }\n } else if (currentAnnotation) {\n setActiveAnnotationId(currentAnnotation.id);\n }\n }\n }\n\n if (time >= duration) {\n playoutRef.current?.stop();\n setIsPlaying(false);\n setActiveAnnotationId(null);\n return;\n }\n\n animationFrameRef.current = requestAnimationFrame(updateTime);\n };\n\n animationFrameRef.current = requestAnimationFrame(updateTime);\n }, [duration, annotations, setActiveAnnotationId]);\n\n const stopAnimationLoop = useCallback(() => {\n if (animationFrameRef.current) {\n cancelAnimationFrame(animationFrameRef.current);\n animationFrameRef.current = null;\n }\n }, []);\n\n // Playback controls\n const play = useCallback(\n (startTime?: number) => {\n if (!playoutRef.current) return;\n\n const actualStartTime = startTime ?? currentTimeRef.current;\n playoutRef.current.play(undefined, actualStartTime);\n setIsPlaying(true);\n startAnimationLoop();\n },\n [startAnimationLoop]\n );\n\n const pause = useCallback(() => {\n if (!playoutRef.current) return;\n\n playoutRef.current.pause();\n setIsPlaying(false);\n stopAnimationLoop();\n setCurrentTime(playoutRef.current.getCurrentTime());\n }, [stopAnimationLoop]);\n\n const stop = useCallback(() => {\n if (!playoutRef.current) return;\n\n playoutRef.current.stop();\n setIsPlaying(false);\n stopAnimationLoop();\n currentTimeRef.current = 0;\n setCurrentTime(0);\n setActiveAnnotationId(null);\n }, [stopAnimationLoop, setActiveAnnotationId]);\n\n const seekTo = useCallback(\n (time: number) => {\n const clampedTime = Math.max(0, Math.min(time, duration));\n currentTimeRef.current = clampedTime;\n setCurrentTime(clampedTime);\n\n if (playoutRef.current) {\n playoutRef.current.seekTo(clampedTime);\n }\n },\n [duration]\n );\n\n const setPlaybackRate = useCallback((rate: number) => {\n const clampedRate = Math.max(0.5, Math.min(2.0, rate));\n setPlaybackRateState(clampedRate);\n if (playoutRef.current) {\n playoutRef.current.setPlaybackRate(clampedRate);\n }\n }, []);\n\n const timeScaleHeight = timescale ? 30 : 0;\n\n // Context values\n const animationValue: MediaElementAnimationContextValue = useMemo(\n () => ({\n isPlaying,\n currentTime,\n currentTimeRef,\n }),\n [isPlaying, currentTime]\n );\n\n const stateValue: MediaElementStateContextValue = useMemo(\n () => ({\n continuousPlay,\n annotations,\n activeAnnotationId,\n playbackRate,\n }),\n [continuousPlay, annotations, activeAnnotationId, playbackRate]\n );\n\n const controlsValue: MediaElementControlsContextValue = useMemo(\n () => ({\n play,\n pause,\n stop,\n seekTo,\n setPlaybackRate,\n setContinuousPlay,\n setAnnotations,\n setActiveAnnotationId,\n }),\n [play, pause, stop, seekTo, setPlaybackRate, setContinuousPlay, setActiveAnnotationId]\n );\n\n const dataValue: MediaElementDataContextValue = useMemo(\n () => ({\n duration,\n peaksDataArray,\n sampleRate,\n waveHeight,\n timeScaleHeight,\n samplesPerPixel,\n playoutRef,\n controls,\n barWidth,\n barGap,\n progressBarWidth,\n }),\n [\n duration,\n peaksDataArray,\n sampleRate,\n waveHeight,\n timeScaleHeight,\n samplesPerPixel,\n controls,\n barWidth,\n barGap,\n progressBarWidth,\n ]\n );\n\n const mergedTheme = { ...defaultTheme, ...userTheme };\n\n return (\n <ThemeProvider theme={mergedTheme}>\n <MediaElementAnimationContext.Provider value={animationValue}>\n <MediaElementStateContext.Provider value={stateValue}>\n <MediaElementControlsContext.Provider value={controlsValue}>\n <MediaElementDataContext.Provider value={dataValue}>\n {children}\n </MediaElementDataContext.Provider>\n </MediaElementControlsContext.Provider>\n </MediaElementStateContext.Provider>\n </MediaElementAnimationContext.Provider>\n </ThemeProvider>\n );\n};\n\n// Hooks\nexport const useMediaElementAnimation = () => {\n const context = useContext(MediaElementAnimationContext);\n if (!context) {\n throw new Error(\n 'useMediaElementAnimation must be used within MediaElementPlaylistProvider'\n );\n }\n return context;\n};\n\nexport const useMediaElementState = () => {\n const context = useContext(MediaElementStateContext);\n if (!context) {\n throw new Error(\n 'useMediaElementState must be used within MediaElementPlaylistProvider'\n );\n }\n return context;\n};\n\nexport const useMediaElementControls = () => {\n const context = useContext(MediaElementControlsContext);\n if (!context) {\n throw new Error(\n 'useMediaElementControls must be used within MediaElementPlaylistProvider'\n );\n }\n return context;\n};\n\nexport const useMediaElementData = () => {\n const context = useContext(MediaElementDataContext);\n if (!context) {\n throw new Error(\n 'useMediaElementData must be used within MediaElementPlaylistProvider'\n );\n }\n return context;\n};\n","import React from 'react';\nimport { BaseControlButton } from '@waveform-playlist/ui-components';\nimport { usePlaybackAnimation, usePlaylistState, usePlaylistControls, usePlaylistData } from '../WaveformPlaylistContext';\n\nexport const PlayButton: React.FC<{ className?: string }> = ({ className }) => {\n const { isPlaying, currentTimeRef } = usePlaybackAnimation();\n const { selectionStart, selectionEnd, isLoopEnabled } = usePlaylistState();\n const { play } = usePlaylistControls();\n\n const handleClick = async () => {\n const hasSelection = selectionStart !== selectionEnd && selectionEnd > selectionStart;\n\n if (hasSelection) {\n if (isLoopEnabled) {\n // With loop: Start from selection start, let loop logic handle boundaries\n // Playback continues until it gets trapped in loop or reaches end\n await play(selectionStart);\n } else {\n // Without loop: Play selection region only, then stop\n const duration = selectionEnd - selectionStart;\n await play(selectionStart, duration);\n }\n } else {\n // No selection: Play from current position to the end\n await play(currentTimeRef.current ?? 0);\n }\n };\n\n return (\n <BaseControlButton onClick={handleClick} disabled={isPlaying} className={className}>\n Play\n </BaseControlButton>\n );\n};\n\nexport const PauseButton: React.FC<{ className?: string }> = ({ className }) => {\n const { isPlaying } = usePlaybackAnimation();\n const { pause } = usePlaylistControls();\n\n return (\n <BaseControlButton onClick={pause} disabled={!isPlaying} className={className}>\n Pause\n </BaseControlButton>\n );\n};\n\nexport const StopButton: React.FC<{ className?: string }> = ({ className }) => {\n const { isPlaying } = usePlaybackAnimation();\n const { stop } = usePlaylistControls();\n\n return (\n <BaseControlButton onClick={stop} disabled={!isPlaying} className={className}>\n Stop\n </BaseControlButton>\n );\n};\n\nexport const RewindButton: React.FC<{ className?: string }> = ({ className }) => {\n const { isPlaying } = usePlaybackAnimation();\n const { play, setCurrentTime } = usePlaylistControls();\n const { playoutRef } = usePlaylistData();\n\n const handleClick = () => {\n setCurrentTime(0);\n\n if (isPlaying && playoutRef.current) {\n playoutRef.current.stop();\n play(0);\n }\n };\n\n return (\n <BaseControlButton onClick={handleClick} className={className}>\n Rewind\n </BaseControlButton>\n );\n};\n\nexport const FastForwardButton: React.FC<{ className?: string }> = ({ className }) => {\n const { isPlaying } = usePlaybackAnimation();\n const { play, setCurrentTime } = usePlaylistControls();\n const { duration, playoutRef } = usePlaylistData();\n\n const handleClick = () => {\n setCurrentTime(duration);\n\n if (isPlaying && playoutRef.current) {\n playoutRef.current.stop();\n play(duration);\n }\n };\n\n return (\n <BaseControlButton onClick={handleClick} className={className}>\n Fast Forward\n </BaseControlButton>\n );\n};\n\nexport const SkipBackwardButton: React.FC<{ skipAmount?: number; className?: string }> = ({\n skipAmount = 5,\n className\n}) => {\n const { currentTimeRef, isPlaying } = usePlaybackAnimation();\n const { play, setCurrentTime } = usePlaylistControls();\n const { playoutRef } = usePlaylistData();\n\n const handleClick = () => {\n const newTime = Math.max(0, (currentTimeRef.current ?? 0) - skipAmount);\n setCurrentTime(newTime);\n\n if (isPlaying && playoutRef.current) {\n playoutRef.current.stop();\n play(newTime);\n }\n };\n\n return (\n <BaseControlButton onClick={handleClick} className={className}>\n Skip Backward\n </BaseControlButton>\n );\n};\n\nexport const SkipForwardButton: React.FC<{ skipAmount?: number; className?: string }> = ({\n skipAmount = 5,\n className\n}) => {\n const { currentTimeRef, isPlaying } = usePlaybackAnimation();\n const { play, setCurrentTime } = usePlaylistControls();\n const { duration, playoutRef } = usePlaylistData();\n\n const handleClick = () => {\n const newTime = Math.min(duration, (currentTimeRef.current ?? 0) + skipAmount);\n setCurrentTime(newTime);\n\n if (isPlaying && playoutRef.current) {\n playoutRef.current.stop();\n play(newTime);\n }\n };\n\n return (\n <BaseControlButton onClick={handleClick} className={className}>\n Skip Forward\n </BaseControlButton>\n );\n};\n\nexport const LoopButton: React.FC<{ className?: string }> = ({ className }) => {\n const { isLoopEnabled, loopStart, loopEnd } = usePlaylistState();\n const { setLoopEnabled, setLoopRegion } = usePlaylistControls();\n const { duration } = usePlaylistData();\n\n const hasValidLoopRegion = loopStart !== loopEnd && loopEnd > loopStart;\n\n const handleClick = () => {\n if (!isLoopEnabled && !hasValidLoopRegion) {\n // Create a default loop region when enabling loop without one\n // Default to first 10 seconds or 25% of duration, whichever is smaller\n const defaultEnd = Math.min(10, duration * 0.25);\n setLoopRegion(0, Math.max(1, defaultEnd)); // At least 1 second\n }\n setLoopEnabled(!isLoopEnabled);\n };\n\n return (\n <BaseControlButton\n onClick={handleClick}\n className={className}\n title={isLoopEnabled ? 'Disable loop' : 'Enable loop'}\n >\n {isLoopEnabled ? 'Loop On' : 'Loop Off'}\n </BaseControlButton>\n );\n};\n\nexport const SetLoopRegionButton: React.FC<{ className?: string }> = ({ className }) => {\n const { selectionStart, selectionEnd, loopStart, loopEnd } = usePlaylistState();\n const { setLoopRegionFromSelection, clearLoopRegion } = usePlaylistControls();\n\n const hasValidSelection = selectionStart !== selectionEnd && selectionEnd > selectionStart;\n const hasLoopRegion = loopStart !== loopEnd && loopEnd > loopStart;\n\n const handleClick = () => {\n if (hasLoopRegion) {\n clearLoopRegion();\n } else {\n setLoopRegionFromSelection();\n }\n };\n\n return (\n <BaseControlButton\n onClick={handleClick}\n disabled={!hasValidSelection && !hasLoopRegion}\n className={className}\n title={hasLoopRegion ? 'Clear loop region' : (hasValidSelection ? 'Set loop region from selection' : 'Create a selection first')}\n >\n {hasLoopRegion ? 'Clear Loop' : 'Set Loop'}\n </BaseControlButton>\n );\n};\n","import React from 'react';\nimport { BaseControlButton } from '@waveform-playlist/ui-components';\nimport { usePlaylistControls, usePlaylistData } from '../WaveformPlaylistContext';\n\nexport const ZoomInButton: React.FC<{ className?: string; disabled?: boolean }> = ({ className, disabled }) => {\n const { zoomIn } = usePlaylistControls();\n const { canZoomIn } = usePlaylistData();\n\n return (\n <BaseControlButton variant=\"success\" onClick={zoomIn} disabled={disabled || !canZoomIn} className={className}>\n Zoom In\n </BaseControlButton>\n );\n};\n\nexport const ZoomOutButton: React.FC<{ className?: string; disabled?: boolean }> = ({ className, disabled }) => {\n const { zoomOut } = usePlaylistControls();\n const { canZoomOut } = usePlaylistData();\n\n return (\n <BaseControlButton variant=\"success\" onClick={zoomOut} disabled={disabled || !canZoomOut} className={className}>\n Zoom Out\n </BaseControlButton>\n );\n};\n","import React, { useRef, useEffect } from 'react';\nimport { getContext } from 'tone';\nimport {\n MasterVolumeControl as BaseMasterVolumeControl,\n TimeFormatSelect as BaseTimeFormatSelect,\n AutomaticScrollCheckbox as BaseAutomaticScrollCheckbox,\n SelectionTimeInputs as BaseSelectionTimeInputs,\n formatTime,\n type TimeFormat,\n} from '@waveform-playlist/ui-components';\nimport styled from 'styled-components';\nimport { usePlaybackAnimation, usePlaylistState, usePlaylistControls, usePlaylistData } from '../WaveformPlaylistContext';\n\n/**\n * Master volume control that uses the playlist context\n */\nexport const MasterVolumeControl: React.FC<{ className?: string }> = ({ className }) => {\n const { masterVolume } = usePlaylistData();\n const { setMasterVolume } = usePlaylistControls();\n\n return (\n <BaseMasterVolumeControl\n volume={masterVolume}\n onChange={setMasterVolume}\n className={className}\n />\n );\n};\n\n/**\n * Time format selector that uses the playlist context\n */\nexport const TimeFormatSelect: React.FC<{ className?: string }> = ({ className }) => {\n const { timeFormat } = usePlaylistData();\n const { setTimeFormat } = usePlaylistControls();\n\n return (\n <BaseTimeFormatSelect\n value={timeFormat as any}\n onChange={setTimeFormat as any}\n className={className}\n />\n );\n};\n\nconst PositionDisplay = styled.span`\n font-family: 'Courier New', Monaco, monospace;\n font-size: 1rem;\n font-weight: 600;\n color: ${props => props.theme?.textColor || '#333'};\n user-select: none;\n`;\n\n/**\n * Audio position display that uses the playlist context.\n * Uses requestAnimationFrame for smooth 60fps updates during playback.\n * Direct DOM manipulation avoids React re-renders.\n */\nexport const AudioPosition: React.FC<{ className?: string }> = ({ className }) => {\n const timeRef = useRef<HTMLSpanElement>(null);\n const animationFrameRef = useRef<number | null>(null);\n const { isPlaying, currentTimeRef, playbackStartTimeRef, audioStartPositionRef } = usePlaybackAnimation();\n const { timeFormat } = usePlaylistData();\n const format = timeFormat as TimeFormat;\n\n useEffect(() => {\n const updateTime = () => {\n if (timeRef.current) {\n let time: number;\n if (isPlaying) {\n const elapsed = getContext().currentTime - (playbackStartTimeRef.current ?? 0);\n time = (audioStartPositionRef.current ?? 0) + elapsed;\n } else {\n time = currentTimeRef.current ?? 0;\n }\n timeRef.current.textContent = formatTime(time, format);\n }\n\n if (isPlaying) {\n animationFrameRef.current = requestAnimationFrame(updateTime);\n }\n };\n\n if (isPlaying) {\n animationFrameRef.current = requestAnimationFrame(updateTime);\n } else {\n updateTime();\n }\n\n return () => {\n if (animationFrameRef.current) {\n cancelAnimationFrame(animationFrameRef.current);\n animationFrameRef.current = null;\n }\n };\n }, [isPlaying, format, currentTimeRef, playbackStartTimeRef, audioStartPositionRef]);\n\n // Update when stopped (for seeks)\n useEffect(() => {\n if (!isPlaying && timeRef.current) {\n timeRef.current.textContent = formatTime(currentTimeRef.current ?? 0, format);\n }\n });\n\n return (\n <PositionDisplay ref={timeRef} className={className} aria-label=\"Audio position\">\n {formatTime(currentTimeRef.current ?? 0, format)}\n </PositionDisplay>\n );\n};\n\n/**\n * Selection time inputs that use the playlist context\n */\nexport const SelectionTimeInputs: React.FC<{ className?: string }> = ({ className }) => {\n const { selectionStart, selectionEnd } = usePlaylistState();\n const { setSelection } = usePlaylistControls();\n\n return (\n <BaseSelectionTimeInputs\n selectionStart={selectionStart}\n selectionEnd={selectionEnd}\n onSelectionChange={setSelection}\n className={className}\n />\n );\n};\n\n/**\n * Automatic scroll checkbox that uses the playlist context\n * Uses split contexts to avoid re-rendering during animation\n */\nexport const AutomaticScrollCheckbox: React.FC<{ className?: string }> = ({ className }) => {\n const { isAutomaticScroll } = usePlaylistState();\n const { setAutomaticScroll } = usePlaylistControls();\n\n return (\n <BaseAutomaticScrollCheckbox\n checked={isAutomaticScroll}\n onChange={setAutomaticScroll}\n className={className}\n />\n );\n};\n","import React from 'react';\nimport {\n ContinuousPlayCheckbox as BaseContinuousPlayCheckbox,\n LinkEndpointsCheckbox as BaseLinkEndpointsCheckbox,\n EditableCheckbox as BaseEditableCheckbox,\n DownloadAnnotationsButton as BaseDownloadAnnotationsButton,\n} from '@waveform-playlist/annotations';\nimport { usePlaylistState, usePlaylistControls } from '../WaveformPlaylistContext';\n\n/**\n * Continuous play checkbox that uses the playlist context\n * Uses split contexts to avoid re-rendering during animation\n */\nexport const ContinuousPlayCheckbox: React.FC<{ className?: string }> = ({ className }) => {\n const { continuousPlay } = usePlaylistState();\n const { setContinuousPlay } = usePlaylistControls();\n\n return (\n <BaseContinuousPlayCheckbox\n checked={continuousPlay}\n onChange={setContinuousPlay}\n className={className}\n />\n );\n};\n\n/**\n * Link endpoints checkbox that uses the playlist context\n * Uses split contexts to avoid re-rendering during animation\n */\nexport const LinkEndpointsCheckbox: React.FC<{ className?: string }> = ({ className }) => {\n const { linkEndpoints } = usePlaylistState();\n const { setLinkEndpoints } = usePlaylistControls();\n\n return (\n <BaseLinkEndpointsCheckbox\n checked={linkEndpoints}\n onChange={setLinkEndpoints}\n className={className}\n />\n );\n};\n\n/**\n * Editable annotations checkbox that uses the playlist context\n * Uses split contexts to avoid re-rendering during animation\n */\nexport const EditableCheckbox: React.FC<{ className?: string }> = ({ className }) => {\n const { annotationsEditable } = usePlaylistState();\n const { setAnnotationsEditable } = usePlaylistControls();\n\n return (\n <BaseEditableCheckbox\n checked={annotationsEditable}\n onChange={setAnnotationsEditable}\n className={className}\n />\n );\n};\n\n/**\n * Download annotations button that uses the playlist context\n * Uses split contexts to avoid re-rendering during animation\n */\nexport const DownloadAnnotationsButton: React.FC<{ filename?: string; className?: string }> = ({\n filename,\n className,\n}) => {\n const { annotations } = usePlaylistState();\n\n return (\n <BaseDownloadAnnotationsButton\n annotations={annotations}\n filename={filename}\n className={className}\n />\n );\n};\n","import React from 'react';\nimport { BaseControlButton } from '@waveform-playlist/ui-components';\nimport type { EffectsFunction } from '@waveform-playlist/playout';\nimport { usePlaylistData } from '../WaveformPlaylistContext';\nimport { useExportWav, type TrackEffectsFunction } from '../hooks/useExportWav';\n\nexport interface ExportWavButtonProps {\n /** Button label */\n label?: string;\n /** Filename for the downloaded file (without extension) */\n filename?: string;\n /** Export mode: 'master' for stereo mix, 'individual' for single track */\n mode?: 'master' | 'individual';\n /** Track index for individual export */\n trackIndex?: number;\n /** Bit depth: 16 or 32 */\n bitDepth?: 16 | 32;\n /** Whether to apply effects (fades, etc.) - defaults to true */\n applyEffects?: boolean;\n /**\n * Optional Tone.js effects function for master effects. When provided, export will use Tone.Offline\n * to render through the effects chain. The function receives isOffline=true.\n */\n effectsFunction?: EffectsFunction;\n /**\n * Optional function to create offline track effects.\n * Takes a trackId and returns a TrackEffectsFunction for offline rendering.\n */\n createOfflineTrackEffects?: (trackId: string) => TrackEffectsFunction | undefined;\n /** CSS class name */\n className?: string;\n /** Callback when export completes */\n onExportComplete?: (blob: Blob) => void;\n /** Callback when export fails */\n onExportError?: (error: Error) => void;\n}\n\nexport const ExportWavButton: React.FC<ExportWavButtonProps> = ({\n label = 'Export WAV',\n filename = 'export',\n mode = 'master',\n trackIndex,\n bitDepth = 16,\n applyEffects = true,\n effectsFunction,\n createOfflineTrackEffects,\n className,\n onExportComplete,\n onExportError,\n}) => {\n const { tracks, trackStates } = usePlaylistData();\n const { exportWav, isExporting, progress } = useExportWav();\n\n const handleExport = async () => {\n try {\n const result = await exportWav(tracks, trackStates, {\n filename,\n mode,\n trackIndex,\n bitDepth,\n applyEffects,\n effectsFunction,\n createOfflineTrackEffects,\n autoDownload: true,\n });\n onExportComplete?.(result.blob);\n } catch (error) {\n onExportError?.(error instanceof Error ? error : new Error('Export failed'));\n }\n };\n\n const buttonLabel = isExporting\n ? `Exporting ${Math.round(progress * 100)}%`\n : label;\n\n return (\n <BaseControlButton\n onClick={handleExport}\n disabled={isExporting || tracks.length === 0}\n className={className}\n >\n {buttonLabel}\n </BaseControlButton>\n );\n};\n","import React, { useRef, useEffect } from 'react';\nimport styled from 'styled-components';\nimport { getContext } from 'tone';\nimport { usePlaybackAnimation, usePlaylistData } from '../WaveformPlaylistContext';\n\nconst PlayheadLine = styled.div<{ $color: string; $width: number }>`\n position: absolute;\n top: 0;\n left: 0;\n width: ${(props) => props.$width}px;\n background: ${(props) => props.$color};\n height: 100%;\n z-index: 100; /* Below sticky controls (z-index: 101) so playhead is hidden when scrolled behind controls */\n pointer-events: none;\n will-change: transform;\n`;\n\ninterface AnimatedPlayheadProps {\n color?: string;\n controlsOffset?: number;\n}\n\n/**\n * Animated playhead that updates position via direct DOM manipulation.\n * Calculates time directly from audio context for perfect synchronization.\n * Uses requestAnimationFrame for smooth 60fps animation without React re-renders.\n */\nexport const AnimatedPlayhead: React.FC<AnimatedPlayheadProps> = ({\n color = '#ff0000',\n controlsOffset = 0,\n}) => {\n const playheadRef = useRef<HTMLDivElement>(null);\n const animationFrameRef = useRef<number | null>(null);\n\n const { isPlaying, currentTimeRef, playbackStartTimeRef, audioStartPositionRef } = usePlaybackAnimation();\n const { samplesPerPixel, sampleRate, progressBarWidth } = usePlaylistData();\n\n useEffect(() => {\n const updatePosition = () => {\n if (playheadRef.current) {\n // Calculate time directly from audio context for perfect sync\n let time: number;\n if (isPlaying) {\n const elapsed = getContext().currentTime - (playbackStartTimeRef.current ?? 0);\n time = (audioStartPositionRef.current ?? 0) + elapsed;\n } else {\n time = currentTimeRef.current ?? 0;\n }\n const position = (time * sampleRate) / samplesPerPixel + controlsOffset;\n playheadRef.current.style.transform = `translate3d(${position}px, 0, 0)`;\n }\n\n if (isPlaying) {\n animationFrameRef.current = requestAnimationFrame(updatePosition);\n }\n };\n\n if (isPlaying) {\n // Start animation loop\n animationFrameRef.current = requestAnimationFrame(updatePosition);\n } else {\n // When stopped, update once to show final position\n updatePosition();\n }\n\n return () => {\n if (animationFrameRef.current) {\n cancelAnimationFrame(animationFrameRef.current);\n animationFrameRef.current = null;\n }\n };\n }, [isPlaying, sampleRate, samplesPerPixel, controlsOffset, currentTimeRef, playbackStartTimeRef, audioStartPositionRef]);\n\n // Also update position when not playing (for seeks, stops, etc.)\n useEffect(() => {\n if (!isPlaying && playheadRef.current) {\n const time = currentTimeRef.current ?? 0;\n const position = (time * sampleRate) / samplesPerPixel + controlsOffset;\n playheadRef.current.style.transform = `translate3d(${position}px, 0, 0)`;\n }\n });\n\n return <PlayheadLine ref={playheadRef} $color={color} $width={progressBarWidth} data-playhead />;\n};\n","import React, { useRef, useEffect } from 'react';\nimport styled from 'styled-components';\nimport { getContext } from 'tone';\nimport { SmartChannel, type SmartChannelProps, useTheme, usePlaylistInfo, type WaveformPlaylistTheme, waveformColorToCss } from '@waveform-playlist/ui-components';\nimport { usePlaybackAnimation, usePlaylistData } from '../WaveformPlaylistContext';\n\nconst ChannelWrapper = styled.div`\n position: relative;\n`;\n\ninterface BackgroundProps {\n readonly $color: string;\n readonly $height: number;\n readonly $top: number;\n readonly $width: number;\n}\n\nconst Background = styled.div<BackgroundProps>`\n position: absolute;\n top: ${(props) => props.$top}px;\n left: 0;\n width: ${(props) => props.$width}px;\n height: ${(props) => props.$height}px;\n background: ${(props) => props.$color};\n z-index: 0;\n /* Force GPU compositing layer to prevent gradient flickering during scroll */\n transform: translateZ(0);\n backface-visibility: hidden;\n will-change: transform;\n`;\n\ninterface ProgressOverlayProps {\n readonly $color: string;\n readonly $height: number;\n readonly $top: number;\n}\n\nconst ProgressOverlay = styled.div<ProgressOverlayProps>`\n position: absolute;\n top: ${(props) => props.$top}px;\n left: 0;\n height: ${(props) => props.$height}px;\n background: ${(props) => props.$color};\n pointer-events: none;\n z-index: 1;\n will-change: width;\n`;\n\nconst ChannelContainer = styled.div`\n position: relative;\n z-index: 2;\n`;\n\nexport interface ChannelWithProgressProps extends SmartChannelProps {\n /** Start sample of the clip containing this channel (for progress calculation) */\n clipStartSample: number;\n /** Duration in samples of the clip */\n clipDurationSamples: number;\n}\n\n/**\n * SmartChannel wrapper that adds an animated progress overlay.\n * The progress overlay shows the \"played\" portion of the waveform.\n * Uses requestAnimationFrame for smooth 60fps animation without React re-renders.\n */\nexport const ChannelWithProgress: React.FC<ChannelWithProgressProps> = ({\n clipStartSample,\n clipDurationSamples,\n ...smartChannelProps\n}) => {\n const progressRef = useRef<HTMLDivElement>(null);\n const animationFrameRef = useRef<number | null>(null);\n const theme = useTheme() as WaveformPlaylistTheme;\n const { waveHeight } = usePlaylistInfo();\n\n const { isPlaying, currentTimeRef, playbackStartTimeRef, audioStartPositionRef } = usePlaybackAnimation();\n const { samplesPerPixel, sampleRate } = usePlaylistData();\n\n const progressColor = theme?.waveProgressColor || 'rgba(0, 0, 0, 0.1)';\n\n useEffect(() => {\n const updateProgress = () => {\n if (progressRef.current) {\n // Calculate current time from audio context\n let currentTime: number;\n if (isPlaying) {\n const elapsed = getContext().currentTime - (playbackStartTimeRef.current ?? 0);\n currentTime = (audioStartPositionRef.current ?? 0) + elapsed;\n } else {\n currentTime = currentTimeRef.current ?? 0;\n }\n\n // Convert current time to samples\n const currentSample = currentTime * sampleRate;\n\n // Calculate clip bounds in samples\n const clipEndSample = clipStartSample + clipDurationSamples;\n\n // Calculate how much of this clip has been played\n let progressWidth = 0;\n\n if (currentSample <= clipStartSample) {\n // Playhead is before this clip - no progress\n progressWidth = 0;\n } else if (currentSample >= clipEndSample) {\n // Playhead is past this clip - full progress\n progressWidth = smartChannelProps.length;\n } else {\n // Playhead is within this clip - partial progress\n const playedSamples = currentSample - clipStartSample;\n progressWidth = Math.floor(playedSamples / samplesPerPixel);\n }\n\n progressRef.current.style.width = `${progressWidth}px`;\n }\n\n if (isPlaying) {\n animationFrameRef.current = requestAnimationFrame(updateProgress);\n }\n };\n\n if (isPlaying) {\n animationFrameRef.current = requestAnimationFrame(updateProgress);\n } else {\n // When stopped, update once to show final position\n updateProgress();\n }\n\n return () => {\n if (animationFrameRef.current) {\n cancelAnimationFrame(animationFrameRef.current);\n animationFrameRef.current = null;\n }\n };\n }, [isPlaying, sampleRate, samplesPerPixel, clipStartSample, clipDurationSamples, smartChannelProps.length, currentTimeRef, playbackStartTimeRef, audioStartPositionRef]);\n\n // Also update when not playing (for seeks, stops, etc.)\n useEffect(() => {\n if (!isPlaying && progressRef.current) {\n const currentTime = currentTimeRef.current ?? 0;\n const currentSample = currentTime * sampleRate;\n const clipEndSample = clipStartSample + clipDurationSamples;\n\n let progressWidth = 0;\n if (currentSample <= clipStartSample) {\n progressWidth = 0;\n } else if (currentSample >= clipEndSample) {\n progressWidth = smartChannelProps.length;\n } else {\n const playedSamples = currentSample - clipStartSample;\n progressWidth = Math.floor(playedSamples / samplesPerPixel);\n }\n\n progressRef.current.style.width = `${progressWidth}px`;\n }\n });\n\n // Get the draw mode from theme (defaults to 'inverted')\n const drawMode = theme?.waveformDrawMode || 'inverted';\n\n let backgroundColor;\n if (drawMode === 'inverted') {\n\n backgroundColor = smartChannelProps.isSelected && theme\n ? theme.selectedWaveFillColor\n : theme?.waveFillColor || 'white';\n\n } else {\n backgroundColor = smartChannelProps.isSelected && theme\n ? theme.selectedWaveOutlineColor\n : theme?.waveOutlineColor || 'grey';\n }\n\n const backgroundCss = waveformColorToCss(backgroundColor);\n\n return (\n <ChannelWrapper>\n {/* Background layer - color depends on draw mode */}\n <Background\n $color={backgroundCss}\n $height={waveHeight}\n $top={smartChannelProps.index * waveHeight}\n $width={smartChannelProps.length}\n />\n {/* Progress overlay - shows played portion with progress color */}\n <ProgressOverlay\n ref={progressRef}\n $color={progressColor}\n $height={waveHeight}\n $top={smartChannelProps.index * waveHeight}\n />\n {/* Waveform canvas with transparent background */}\n <ChannelContainer>\n <SmartChannel {...smartChannelProps} transparentBackground />\n </ChannelContainer>\n </ChannelWrapper>\n );\n};\n","import React, { useRef, useState, ReactNode, useCallback, useMemo } from 'react';\nimport { getContext } from 'tone';\nimport {\n Playlist,\n Track as TrackComponent,\n Clip,\n Playhead,\n Selection,\n TimescaleLoopRegion,\n PlaylistInfoContext,\n TrackControlsContext,\n DevicePixelRatioProvider,\n StyledTimeScale,\n Controls,\n Header,\n Button,\n ButtonGroup,\n Slider,\n SliderWrapper,\n VolumeDownIcon,\n VolumeUpIcon,\n useTheme,\n waveformColorToCss,\n type RenderPlayheadFunction,\n} from '@waveform-playlist/ui-components';\nimport {\n AnnotationBoxesWrapper,\n AnnotationBox,\n AnnotationText,\n} from '@waveform-playlist/annotations';\nimport type { AnnotationAction, AnnotationActionOptions, RenderAnnotationItemProps } from '@waveform-playlist/annotations';\nimport { usePlaybackAnimation, usePlaylistState, usePlaylistControls, usePlaylistData } from '../WaveformPlaylistContext';\nimport type { Peaks } from '@waveform-playlist/webaudio-peaks';\nimport { AnimatedPlayhead } from './AnimatedPlayhead';\nimport { ChannelWithProgress } from './ChannelWithProgress';\n\n// Default duration in seconds for empty tracks (used for recording workflow)\nconst DEFAULT_EMPTY_TRACK_DURATION = 60;\n\nexport interface WaveformProps {\n renderTrackControls?: (trackIndex: number) => ReactNode;\n renderTimestamp?: (timeMs: number, pixelPosition: number) => ReactNode;\n /** Custom playhead render function. Receives position (pixels) and color from theme. */\n renderPlayhead?: RenderPlayheadFunction;\n annotationControls?: AnnotationAction[];\n annotationListConfig?: AnnotationActionOptions;\n annotationTextHeight?: number; // Height in pixels for the annotation text list\n /**\n * Custom render function for annotation items in the text list.\n * Use this to completely customize how each annotation is displayed.\n */\n renderAnnotationItem?: (props: RenderAnnotationItemProps) => ReactNode;\n /**\n * Custom function to generate the label shown on annotation boxes in the waveform.\n * Receives the annotation data and should return a string label.\n * Default: annotation.id\n */\n getAnnotationBoxLabel?: (annotation: { id: string; start: number; end: number; lines: string[] }) => string;\n className?: string;\n showClipHeaders?: boolean; // Show headers on clips for visual organization\n interactiveClips?: boolean; // Enable dragging/trimming interactions on clips (requires @dnd-kit setup)\n showFades?: boolean; // Show fade in/out overlays on clips\n /**\n * Enable mobile-optimized touch interactions.\n * When true, increases touch target sizes for clip boundaries.\n * Use with useDragSensors({ touchOptimized: true }) for best results.\n */\n touchOptimized?: boolean;\n // Live recording state for real-time waveform preview\n recordingState?: {\n isRecording: boolean;\n trackId: string; // Which track is being recorded into\n startSample: number; // Where recording started\n durationSamples: number; // Current recording length\n peaks: Int8Array | Int16Array; // Live peaks data\n };\n}\n\n/**\n * Waveform visualization component that uses the playlist context\n */\nexport const Waveform: React.FC<WaveformProps> = ({\n renderTrackControls,\n renderTimestamp,\n renderPlayhead,\n annotationControls,\n annotationListConfig: _annotationListConfig,\n annotationTextHeight,\n renderAnnotationItem,\n getAnnotationBoxLabel,\n className,\n showClipHeaders = false,\n interactiveClips = false,\n showFades = false,\n touchOptimized = false,\n recordingState,\n}) => {\n // Get theme from context (typed as WaveformPlaylistTheme)\n const theme = useTheme() as import('@waveform-playlist/ui-components').WaveformPlaylistTheme;\n\n // Split context usage for performance\n // NOTE: We intentionally do NOT subscribe to currentTime here to avoid re-renders during playback.\n // AnimatedPlayhead/AnimatedProgress handle their own positioning via refs for smooth 60fps animation.\n // We pass refs to custom renderPlayhead for smooth animation support.\n const { isPlaying, currentTimeRef, playbackStartTimeRef, audioStartPositionRef } = usePlaybackAnimation();\n const {\n selectionStart,\n selectionEnd,\n annotations,\n activeAnnotationId,\n annotationsEditable,\n linkEndpoints,\n continuousPlay,\n selectedTrackId,\n loopStart,\n loopEnd,\n isLoopEnabled,\n } = usePlaylistState();\n const {\n setAnnotations,\n setActiveAnnotationId,\n setTrackMute,\n setTrackSolo,\n setTrackVolume,\n setTrackPan,\n setSelection,\n play,\n setScrollContainer,\n setSelectedTrackId,\n setCurrentTime,\n setLoopRegion,\n } = usePlaylistControls();\n const {\n audioBuffers,\n peaksDataArray,\n trackStates,\n tracks,\n duration,\n samplesPerPixel,\n sampleRate,\n waveHeight,\n timeScaleHeight,\n controls,\n playoutRef,\n barWidth,\n barGap,\n } = usePlaylistData();\n\n const [isSelecting, setIsSelecting] = useState(false);\n\n // Local ref for scroll container to use in drag handlers\n const scrollContainerRef = useRef<HTMLDivElement | null>(null);\n\n // Callback to set both local ref and context ref\n const handleScrollContainerRef = useCallback((element: HTMLDivElement | null) => {\n scrollContainerRef.current = element;\n setScrollContainer(element);\n }, [setScrollContainer]);\n\n // Calculate dimensions\n // If there are no clips, provide a reasonable default width for recording\n let displayDuration = audioBuffers.length > 0 ? duration : DEFAULT_EMPTY_TRACK_DURATION;\n\n // Extend duration during recording if needed\n if (recordingState?.isRecording) {\n const recordingEndSample = recordingState.startSample + recordingState.durationSamples;\n const recordingEndTime = recordingEndSample / sampleRate;\n displayDuration = Math.max(displayDuration, recordingEndTime + 10); // Add 10s buffer\n }\n\n const tracksFullWidth = Math.floor((displayDuration * sampleRate) / samplesPerPixel);\n\n // Annotation click handler\n const handleAnnotationClick = async (annotation: any) => {\n console.log('Annotation clicked:', annotation.id);\n setActiveAnnotationId(annotation.id);\n const playDuration = !continuousPlay ? annotation.end - annotation.start : undefined;\n await play(annotation.start, playDuration);\n };\n\n // Shared function for track selection\n const selectTrack = useCallback((trackIndex: number) => {\n if (trackIndex >= 0 && trackIndex < tracks.length) {\n const track = tracks[trackIndex];\n setSelectedTrackId(track.id);\n }\n }, [tracks, setSelectedTrackId]);\n\n // Mouse handlers for selection and click-to-seek\n const handleMouseDown = (e: React.MouseEvent<HTMLDivElement>) => {\n const rect = (e.currentTarget as HTMLDivElement).getBoundingClientRect();\n const controlWidth = controls.show ? controls.width : 0;\n const x = e.clientX - rect.left - controlWidth;\n const clickTime = (x * samplesPerPixel) / sampleRate;\n\n // Calculate which track was clicked based on Y position\n // The click overlay covers all tracks, so we need to calculate from Y position\n const y = e.clientY - rect.top;\n\n // The ClickOverlay is inside TracksContainer which is BELOW the timescale,\n // so y is already relative to the tracks area - no need to subtract timeScaleHeight\n const trackY = y;\n\n // Calculate track index based on cumulative heights\n let cumulativeHeight = 0;\n let clickedTrackIndex = -1;\n\n for (let i = 0; i < peaksDataArray.length; i++) {\n const trackClipPeaks = peaksDataArray[i];\n\n // Calculate track height (1 channel for empty tracks, max channels for tracks with clips)\n const maxChannels = trackClipPeaks.length > 0\n ? Math.max(...trackClipPeaks.map(clip => clip.peaks.data.length))\n : 1;\n const trackHeight = maxChannels * waveHeight + (showClipHeaders ? 22 : 0); // CLIP_HEADER_HEIGHT = 22\n\n if (trackY >= cumulativeHeight && trackY < cumulativeHeight + trackHeight) {\n clickedTrackIndex = i;\n break;\n }\n\n cumulativeHeight += trackHeight;\n }\n\n // Select the clicked track\n if (clickedTrackIndex !== -1) {\n selectTrack(clickedTrackIndex);\n }\n\n setIsSelecting(true);\n setCurrentTime(clickTime);\n setSelection(clickTime, clickTime);\n };\n\n const handleMouseMove = (e: React.MouseEvent<HTMLDivElement>) => {\n if (!isSelecting) return;\n\n const rect = (e.currentTarget as HTMLDivElement).getBoundingClientRect();\n const controlWidth = controls.show ? controls.width : 0;\n const x = e.clientX - rect.left - controlWidth;\n const moveTime = (x * samplesPerPixel) / sampleRate;\n\n const start = Math.min(selectionStart, moveTime);\n const end = Math.max(selectionStart, moveTime);\n setSelection(start, end);\n };\n\n const handleMouseUp = (e: React.MouseEvent<HTMLDivElement>) => {\n if (!isSelecting) return;\n\n setIsSelecting(false);\n\n const rect = (e.currentTarget as HTMLDivElement).getBoundingClientRect();\n const controlWidth = controls.show ? controls.width : 0;\n const x = e.clientX - rect.left - controlWidth;\n const endTime = (x * samplesPerPixel) / sampleRate;\n\n const start = Math.min(selectionStart, endTime);\n const end = Math.max(selectionStart, endTime);\n\n // If it's just a click (not a drag), seek to that position\n if (Math.abs(end - start) < 0.1) {\n setCurrentTime(start);\n\n if (isPlaying && playoutRef.current) {\n playoutRef.current.stop();\n play(start);\n } else if (playoutRef.current) {\n playoutRef.current.stop();\n }\n } else {\n // It was a drag - finalize the selection\n setSelection(start, end);\n }\n };\n\n // Only show loading if we have tracks WITH clips but haven't loaded their data yet\n // If tracks are empty or all tracks have no clips, render the empty playlist\n const hasClips = tracks.some(track => track.clips.length > 0);\n if (hasClips && (audioBuffers.length === 0 || peaksDataArray.length === 0)) {\n return <div className={className}>Loading waveform...</div>;\n }\n\n return (\n <DevicePixelRatioProvider>\n <PlaylistInfoContext.Provider\n value={{\n samplesPerPixel,\n sampleRate,\n zoomLevels: [samplesPerPixel],\n waveHeight,\n timeScaleHeight,\n duration: displayDuration,\n controls,\n barWidth,\n barGap,\n }}\n >\n <Playlist\n theme={theme}\n backgroundColor={waveformColorToCss(theme.waveOutlineColor)}\n timescaleBackgroundColor={theme.timescaleBackgroundColor}\n scrollContainerWidth={tracksFullWidth + (controls.show ? controls.width : 0)}\n timescaleWidth={tracksFullWidth}\n tracksWidth={tracksFullWidth}\n controlsWidth={controls.show ? controls.width : 0}\n onTracksMouseDown={handleMouseDown}\n onTracksMouseMove={handleMouseMove}\n onTracksMouseUp={handleMouseUp}\n scrollContainerRef={handleScrollContainerRef}\n isSelecting={isSelecting}\n timescale={\n timeScaleHeight > 0 ? (\n <>\n <StyledTimeScale\n duration={displayDuration * 1000}\n marker={10000}\n bigStep={5000}\n secondStep={1000}\n renderTimestamp={renderTimestamp}\n />\n {/* Draggable loop region in timescale - only shown when looping is enabled */}\n {isLoopEnabled && (\n <TimescaleLoopRegion\n startPosition={\n (Math.min(loopStart, loopEnd) * sampleRate) / samplesPerPixel\n }\n endPosition={\n (Math.max(loopStart, loopEnd) * sampleRate) / samplesPerPixel\n }\n markerColor={theme.loopMarkerColor}\n regionColor={theme.loopRegionColor}\n minPosition={0}\n maxPosition={tracksFullWidth}\n controlsOffset={controls.show ? controls.width : 0}\n onLoopRegionChange={(startPixels, endPixels) => {\n const startSeconds = (startPixels * samplesPerPixel) / sampleRate;\n const endSeconds = (endPixels * samplesPerPixel) / sampleRate;\n setLoopRegion(startSeconds, endSeconds);\n }}\n />\n )}\n </>\n ) : undefined\n }\n >\n <>\n {peaksDataArray.map((trackClipPeaks, trackIndex) => {\n // Skip if track doesn't exist (can happen during track deletion transition)\n const track = tracks[trackIndex];\n if (!track) return null;\n\n const trackState = trackStates[trackIndex] || {\n name: `Track ${trackIndex + 1}`,\n muted: false,\n soloed: false,\n volume: 1.0,\n pan: 0,\n };\n\n // Default track controls if not custom renderer provided\n const trackControls = renderTrackControls ? (\n renderTrackControls(trackIndex)\n ) : (\n <Controls onClick={() => selectTrack(trackIndex)}>\n <Header style={{ justifyContent: 'center' }}>\n {trackState.name || `Track ${trackIndex + 1}`}\n </Header>\n <ButtonGroup>\n <Button\n $variant={trackState.muted ? 'danger' : 'outline'}\n onClick={() => setTrackMute(trackIndex, !trackState.muted)}\n >\n Mute\n </Button>\n <Button\n $variant={trackState.soloed ? 'info' : 'outline'}\n onClick={() => setTrackSolo(trackIndex, !trackState.soloed)}\n >\n Solo\n </Button>\n </ButtonGroup>\n <SliderWrapper>\n <VolumeDownIcon />\n <Slider\n min=\"0\"\n max=\"1\"\n step=\"0.01\"\n value={trackState.volume}\n onChange={(e) =>\n setTrackVolume(trackIndex, parseFloat(e.target.value))\n }\n />\n <VolumeUpIcon />\n </SliderWrapper>\n <SliderWrapper>\n <span>L</span>\n <Slider\n min=\"-1\"\n max=\"1\"\n step=\"0.01\"\n value={trackState.pan}\n onChange={(e) =>\n setTrackPan(trackIndex, parseFloat(e.target.value))\n }\n />\n <span>R</span>\n </SliderWrapper>\n </Controls>\n );\n\n // Determine max number of channels across all clips\n // Default to 1 channel (mono) for empty tracks\n const maxChannels = trackClipPeaks.length > 0\n ? Math.max(...trackClipPeaks.map(clip => clip.peaks.data.length))\n : 1;\n\n return (\n <TrackControlsContext.Provider key={track.id} value={trackControls}>\n <TrackComponent\n numChannels={maxChannels}\n backgroundColor={waveformColorToCss(theme.waveOutlineColor)}\n offset={0}\n width={tracksFullWidth}\n hasClipHeaders={showClipHeaders}\n trackId={track.id}\n isSelected={track.id === selectedTrackId}\n >\n {trackClipPeaks.map((clip, clipIndex) => {\n const peaksData = clip.peaks;\n const width = peaksData.length;\n\n return (\n <Clip\n key={`${trackIndex}-${clipIndex}`}\n clipId={clip.clipId}\n trackIndex={trackIndex}\n clipIndex={clipIndex}\n trackName={clip.trackName}\n startSample={clip.startSample}\n durationSamples={clip.durationSamples}\n samplesPerPixel={samplesPerPixel}\n showHeader={showClipHeaders}\n disableHeaderDrag={!interactiveClips}\n isSelected={track.id === selectedTrackId}\n trackId={track.id}\n fadeIn={clip.fadeIn}\n fadeOut={clip.fadeOut}\n sampleRate={sampleRate}\n showFades={showFades}\n touchOptimized={touchOptimized}\n onMouseDown={(e) => {\n // Only select track if clicking on the waveform, not on draggable elements\n const target = e.target as HTMLElement;\n // Check if click is on a draggable element (header or boundary)\n // @dnd-kit sets role=\"button\" and aria-roledescription=\"draggable\" on drag handles\n const isDraggable = target.closest('[role=\"button\"][aria-roledescription=\"draggable\"]');\n if (isDraggable) {\n // Don't select track - let drag event handler take over\n return;\n }\n selectTrack(trackIndex);\n }}\n >\n {peaksData.data.map((channelPeaks: Peaks, channelIndex: number) => (\n <ChannelWithProgress\n key={`${trackIndex}-${clipIndex}-${channelIndex}`}\n index={channelIndex}\n data={channelPeaks}\n bits={peaksData.bits}\n length={width}\n isSelected={track.id === selectedTrackId}\n clipStartSample={clip.startSample}\n clipDurationSamples={clip.durationSamples}\n />\n ))}\n </Clip>\n );\n })}\n {/* Render live recording preview if this track is being recorded */}\n {recordingState?.isRecording &&\n recordingState.trackId === track.id &&\n recordingState.peaks.length > 0 && (\n <Clip\n key={`${trackIndex}-recording`}\n clipId=\"recording-preview\"\n trackIndex={trackIndex}\n clipIndex={trackClipPeaks.length}\n trackName=\"Recording...\"\n startSample={recordingState.startSample}\n durationSamples={recordingState.durationSamples}\n samplesPerPixel={samplesPerPixel}\n showHeader={showClipHeaders}\n disableHeaderDrag={true}\n isSelected={track.id === selectedTrackId}\n trackId={track.id}\n >\n <ChannelWithProgress\n key={`${trackIndex}-recording-0`}\n index={0}\n data={recordingState.peaks}\n bits={16}\n length={Math.floor(recordingState.peaks.length / 2)}\n isSelected={track.id === selectedTrackId}\n clipStartSample={recordingState.startSample}\n clipDurationSamples={recordingState.durationSamples}\n />\n </Clip>\n )}\n </TrackComponent>\n </TrackControlsContext.Provider>\n );\n })}\n {annotations.length > 0 && (\n <AnnotationBoxesWrapper height={30} width={tracksFullWidth}>\n {annotations.map((annotation, index) => {\n const startPosition = (annotation.start * sampleRate) / samplesPerPixel;\n const endPosition = (annotation.end * sampleRate) / samplesPerPixel;\n const label = getAnnotationBoxLabel\n ? getAnnotationBoxLabel(annotation)\n : annotation.id;\n return (\n <AnnotationBox\n key={annotation.id}\n annotationId={annotation.id}\n annotationIndex={index}\n startPosition={startPosition}\n endPosition={endPosition}\n label={label}\n color=\"#ff9800\"\n isActive={annotation.id === activeAnnotationId}\n onClick={() => handleAnnotationClick(annotation)}\n editable={annotationsEditable}\n />\n );\n })}\n </AnnotationBoxesWrapper>\n )}\n {selectionStart !== selectionEnd && (\n <Selection\n startPosition={\n (Math.min(selectionStart, selectionEnd) * sampleRate) / samplesPerPixel +\n (controls.show ? controls.width : 0)\n }\n endPosition={\n (Math.max(selectionStart, selectionEnd) * sampleRate) / samplesPerPixel +\n (controls.show ? controls.width : 0)\n }\n color={theme.selectionColor}\n />\n )}\n {(isPlaying || selectionStart === selectionEnd) && (\n renderPlayhead ? (\n // Custom playhead - pass all animation refs for smooth 60fps animation\n renderPlayhead({\n position: ((currentTimeRef.current ?? 0) * sampleRate) / samplesPerPixel +\n (controls.show ? controls.width : 0),\n color: theme.playheadColor,\n isPlaying,\n currentTimeRef,\n playbackStartTimeRef,\n audioStartPositionRef,\n samplesPerPixel,\n sampleRate,\n controlsOffset: controls.show ? controls.width : 0,\n getAudioContextTime: () => getContext().currentTime,\n })\n ) : (\n <AnimatedPlayhead\n color={theme.playheadColor}\n controlsOffset={controls.show ? controls.width : 0}\n />\n )\n )}\n </>\n </Playlist>\n {annotations.length > 0 && (\n <AnnotationText\n annotations={annotations}\n activeAnnotationId={activeAnnotationId ?? undefined}\n shouldScrollToActive={true}\n editable={annotationsEditable}\n controls={annotationsEditable ? annotationControls : undefined}\n annotationListConfig={{ linkEndpoints, continuousPlay }}\n height={annotationTextHeight}\n renderAnnotationItem={renderAnnotationItem}\n onAnnotationUpdate={(updatedAnnotations) => {\n setAnnotations(updatedAnnotations);\n }}\n />\n )}\n </PlaylistInfoContext.Provider>\n </DevicePixelRatioProvider>\n );\n};\n","import React, { useRef, useEffect } from 'react';\nimport styled from 'styled-components';\nimport { useMediaElementAnimation, useMediaElementData } from '../MediaElementPlaylistContext';\n\nconst PlayheadLine = styled.div<{ $color: string; $width: number }>`\n position: absolute;\n top: 0;\n left: 0;\n width: ${(props) => props.$width}px;\n background: ${(props) => props.$color};\n height: 100%;\n z-index: 100;\n pointer-events: none;\n will-change: transform;\n`;\n\ninterface AnimatedMediaElementPlayheadProps {\n color?: string;\n controlsOffset?: number;\n}\n\n/**\n * Animated playhead for MediaElementPlaylistProvider.\n * Uses the MediaElement context for time tracking instead of Tone.js audio context.\n * Updates position via direct DOM manipulation for smooth 60fps animation.\n */\nexport const AnimatedMediaElementPlayhead: React.FC<AnimatedMediaElementPlayheadProps> = ({\n color = '#ff0000',\n controlsOffset = 0,\n}) => {\n const playheadRef = useRef<HTMLDivElement>(null);\n const animationFrameRef = useRef<number | null>(null);\n\n const { isPlaying, currentTimeRef } = useMediaElementAnimation();\n const { samplesPerPixel, sampleRate, progressBarWidth } = useMediaElementData();\n\n useEffect(() => {\n const updatePosition = () => {\n if (playheadRef.current) {\n // Get current time from the ref (updated by animation loop in context)\n const time = currentTimeRef.current ?? 0;\n const position = (time * sampleRate) / samplesPerPixel + controlsOffset;\n playheadRef.current.style.transform = `translate3d(${position}px, 0, 0)`;\n }\n\n if (isPlaying) {\n animationFrameRef.current = requestAnimationFrame(updatePosition);\n }\n };\n\n if (isPlaying) {\n // Start animation loop\n animationFrameRef.current = requestAnimationFrame(updatePosition);\n } else {\n // When stopped, update once to show final position\n updatePosition();\n }\n\n return () => {\n if (animationFrameRef.current) {\n cancelAnimationFrame(animationFrameRef.current);\n animationFrameRef.current = null;\n }\n };\n }, [isPlaying, sampleRate, samplesPerPixel, controlsOffset, currentTimeRef]);\n\n // Also update position when not playing (for seeks, stops, etc.)\n useEffect(() => {\n if (!isPlaying && playheadRef.current) {\n const time = currentTimeRef.current ?? 0;\n const position = (time * sampleRate) / samplesPerPixel + controlsOffset;\n playheadRef.current.style.transform = `translate3d(${position}px, 0, 0)`;\n }\n });\n\n return <PlayheadLine ref={playheadRef} $color={color} $width={progressBarWidth} data-playhead />;\n};\n","import React, { useRef, useEffect } from 'react';\nimport styled from 'styled-components';\nimport { SmartChannel, type SmartChannelProps, useTheme, usePlaylistInfo, type WaveformPlaylistTheme, waveformColorToCss } from '@waveform-playlist/ui-components';\nimport { useMediaElementAnimation, useMediaElementData } from '../MediaElementPlaylistContext';\n\nconst ChannelWrapper = styled.div`\n position: relative;\n`;\n\ninterface BackgroundProps {\n readonly $color: string;\n readonly $height: number;\n readonly $top: number;\n readonly $width: number;\n}\n\nconst Background = styled.div<BackgroundProps>`\n position: absolute;\n top: ${(props) => props.$top}px;\n left: 0;\n width: ${(props) => props.$width}px;\n height: ${(props) => props.$height}px;\n background: ${(props) => props.$color};\n z-index: 0;\n transform: translateZ(0);\n backface-visibility: hidden;\n will-change: transform;\n`;\n\ninterface ProgressOverlayProps {\n readonly $color: string;\n readonly $height: number;\n readonly $top: number;\n}\n\nconst ProgressOverlay = styled.div<ProgressOverlayProps>`\n position: absolute;\n top: ${(props) => props.$top}px;\n left: 0;\n height: ${(props) => props.$height}px;\n background: ${(props) => props.$color};\n pointer-events: none;\n z-index: 1;\n will-change: width;\n`;\n\nconst ChannelContainer = styled.div`\n position: relative;\n z-index: 2;\n`;\n\nexport interface ChannelWithMediaElementProgressProps extends Omit<SmartChannelProps, 'isSelected'> {\n /** Start sample of the clip containing this channel (for progress calculation) */\n clipStartSample: number;\n /** Duration in samples of the clip */\n clipDurationSamples: number;\n}\n\n/**\n * SmartChannel wrapper for MediaElementPlaylistProvider with animated progress overlay.\n * Uses MediaElement context for time tracking instead of Tone.js audio context.\n */\nexport const ChannelWithMediaElementProgress: React.FC<ChannelWithMediaElementProgressProps> = ({\n clipStartSample,\n clipDurationSamples,\n ...smartChannelProps\n}) => {\n const progressRef = useRef<HTMLDivElement>(null);\n const animationFrameRef = useRef<number | null>(null);\n const theme = useTheme() as WaveformPlaylistTheme;\n const { waveHeight } = usePlaylistInfo();\n\n const { isPlaying, currentTimeRef } = useMediaElementAnimation();\n const { samplesPerPixel, sampleRate } = useMediaElementData();\n\n const progressColor = theme?.waveProgressColor || 'rgba(0, 0, 0, 0.1)';\n\n useEffect(() => {\n const updateProgress = () => {\n if (progressRef.current) {\n // Get current time from the ref\n const currentTime = currentTimeRef.current ?? 0;\n\n // Convert current time to samples\n const currentSample = currentTime * sampleRate;\n\n // Calculate clip bounds in samples\n const clipEndSample = clipStartSample + clipDurationSamples;\n\n // Calculate how much of this clip has been played\n let progressWidth = 0;\n\n if (currentSample <= clipStartSample) {\n // Playhead is before this clip - no progress\n progressWidth = 0;\n } else if (currentSample >= clipEndSample) {\n // Playhead is past this clip - full progress\n progressWidth = smartChannelProps.length;\n } else {\n // Playhead is within this clip - partial progress\n const playedSamples = currentSample - clipStartSample;\n progressWidth = Math.floor(playedSamples / samplesPerPixel);\n }\n\n progressRef.current.style.width = `${progressWidth}px`;\n }\n\n if (isPlaying) {\n animationFrameRef.current = requestAnimationFrame(updateProgress);\n }\n };\n\n if (isPlaying) {\n animationFrameRef.current = requestAnimationFrame(updateProgress);\n } else {\n // When stopped, update once to show final position\n updateProgress();\n }\n\n return () => {\n if (animationFrameRef.current) {\n cancelAnimationFrame(animationFrameRef.current);\n animationFrameRef.current = null;\n }\n };\n }, [isPlaying, sampleRate, samplesPerPixel, clipStartSample, clipDurationSamples, smartChannelProps.length, currentTimeRef]);\n\n // Also update when not playing (for seeks, stops, etc.)\n useEffect(() => {\n if (!isPlaying && progressRef.current) {\n const currentTime = currentTimeRef.current ?? 0;\n const currentSample = currentTime * sampleRate;\n const clipEndSample = clipStartSample + clipDurationSamples;\n\n let progressWidth = 0;\n if (currentSample <= clipStartSample) {\n progressWidth = 0;\n } else if (currentSample >= clipEndSample) {\n progressWidth = smartChannelProps.length;\n } else {\n const playedSamples = currentSample - clipStartSample;\n progressWidth = Math.floor(playedSamples / samplesPerPixel);\n }\n\n progressRef.current.style.width = `${progressWidth}px`;\n }\n });\n\n // Get the draw mode from theme (defaults to 'inverted')\n const drawMode = theme?.waveformDrawMode || 'inverted';\n\n let backgroundColor;\n if (drawMode === 'inverted') {\n // For MediaElement, always treat as selected (single track)\n backgroundColor = theme?.selectedWaveFillColor || theme?.waveFillColor || 'white';\n } else {\n backgroundColor = theme?.selectedWaveOutlineColor || theme?.waveOutlineColor || 'grey';\n }\n\n const backgroundCss = waveformColorToCss(backgroundColor);\n\n return (\n <ChannelWrapper>\n <Background\n $color={backgroundCss}\n $height={waveHeight}\n $top={smartChannelProps.index * waveHeight}\n $width={smartChannelProps.length}\n />\n <ProgressOverlay\n ref={progressRef}\n $color={progressColor}\n $height={waveHeight}\n $top={smartChannelProps.index * waveHeight}\n />\n <ChannelContainer>\n <SmartChannel {...smartChannelProps} isSelected={true} transparentBackground />\n </ChannelContainer>\n </ChannelWrapper>\n );\n};\n","import React, { useRef, useState, useCallback, useMemo } from 'react';\nimport {\n Playlist,\n Track as TrackComponent,\n Clip,\n Playhead,\n Selection,\n PlaylistInfoContext,\n TrackControlsContext,\n DevicePixelRatioProvider,\n StyledTimeScale,\n useTheme,\n waveformColorToCss,\n} from '@waveform-playlist/ui-components';\nimport {\n AnnotationBoxesWrapper,\n AnnotationBox,\n AnnotationText,\n} from '@waveform-playlist/annotations';\nimport type { RenderAnnotationItemProps } from '@waveform-playlist/annotations';\nimport type { Peaks } from '@waveform-playlist/webaudio-peaks';\nimport {\n useMediaElementAnimation,\n useMediaElementState,\n useMediaElementControls,\n useMediaElementData,\n} from '../MediaElementPlaylistContext';\nimport { AnimatedMediaElementPlayhead } from './AnimatedMediaElementPlayhead';\nimport { ChannelWithMediaElementProgress } from './ChannelWithMediaElementProgress';\n\n// Re-export RenderAnnotationItemProps for convenience\nexport type { RenderAnnotationItemProps } from '@waveform-playlist/annotations';\n\nexport interface MediaElementWaveformProps {\n /** Height in pixels for the annotation text list */\n annotationTextHeight?: number;\n /** Custom function to generate the label shown on annotation boxes */\n getAnnotationBoxLabel?: (annotation: { id: string; start: number; end: number; lines: string[] }) => string;\n /**\n * Custom render function for annotation items in the text list.\n * When provided, completely replaces the default annotation item rendering.\n * Use this to customize the appearance of each annotation (e.g., add furigana).\n */\n renderAnnotationItem?: (props: RenderAnnotationItemProps) => React.ReactNode;\n className?: string;\n}\n\n/**\n * Simplified Waveform component for MediaElementPlaylistProvider\n *\n * This is a stripped-down version of Waveform that works with the\n * MediaElement context. It supports:\n * - Single track visualization\n * - Click to seek\n * - Annotation display and click-to-play\n * - Playhead animation\n *\n * For multi-track editing, use the full Waveform with WaveformPlaylistProvider.\n */\nexport const MediaElementWaveform: React.FC<MediaElementWaveformProps> = ({\n annotationTextHeight,\n getAnnotationBoxLabel,\n renderAnnotationItem,\n className,\n}) => {\n const theme = useTheme() as import('@waveform-playlist/ui-components').WaveformPlaylistTheme;\n\n // MediaElement context hooks\n const { isPlaying, currentTimeRef } = useMediaElementAnimation();\n const { annotations, activeAnnotationId, continuousPlay } = useMediaElementState();\n const { play, seekTo, setActiveAnnotationId } = useMediaElementControls();\n const {\n duration,\n peaksDataArray,\n sampleRate,\n waveHeight,\n timeScaleHeight,\n samplesPerPixel,\n controls,\n playoutRef,\n barWidth,\n barGap,\n } = useMediaElementData();\n\n const [selectionStart, setSelectionStart] = useState(0);\n const [selectionEnd, setSelectionEnd] = useState(0);\n const [isSelecting, setIsSelecting] = useState(false);\n\n // Local ref for scroll container\n const scrollContainerRef = useRef<HTMLDivElement | null>(null);\n\n // Calculate dimensions\n const tracksFullWidth = Math.floor((duration * sampleRate) / samplesPerPixel);\n\n // Annotation click handler\n const handleAnnotationClick = useCallback(async (annotation: any) => {\n setActiveAnnotationId(annotation.id);\n play(annotation.start);\n }, [setActiveAnnotationId, play]);\n\n // Mouse handlers for click-to-seek\n const handleMouseDown = useCallback((e: React.MouseEvent<HTMLDivElement>) => {\n const rect = (e.currentTarget as HTMLDivElement).getBoundingClientRect();\n const controlWidth = controls.show ? controls.width : 0;\n const x = e.clientX - rect.left - controlWidth;\n const clickTime = (x * samplesPerPixel) / sampleRate;\n\n setIsSelecting(true);\n setSelectionStart(clickTime);\n setSelectionEnd(clickTime);\n }, [controls, samplesPerPixel, sampleRate]);\n\n const handleMouseMove = useCallback((e: React.MouseEvent<HTMLDivElement>) => {\n if (!isSelecting) return;\n\n const rect = (e.currentTarget as HTMLDivElement).getBoundingClientRect();\n const controlWidth = controls.show ? controls.width : 0;\n const x = e.clientX - rect.left - controlWidth;\n const moveTime = (x * samplesPerPixel) / sampleRate;\n\n setSelectionEnd(moveTime);\n }, [isSelecting, controls, samplesPerPixel, sampleRate]);\n\n const handleMouseUp = useCallback((e: React.MouseEvent<HTMLDivElement>) => {\n if (!isSelecting) return;\n\n setIsSelecting(false);\n\n const rect = (e.currentTarget as HTMLDivElement).getBoundingClientRect();\n const controlWidth = controls.show ? controls.width : 0;\n const x = e.clientX - rect.left - controlWidth;\n const endTime = (x * samplesPerPixel) / sampleRate;\n\n const start = Math.min(selectionStart, endTime);\n const end = Math.max(selectionStart, endTime);\n\n // If it's just a click (not a drag), seek to that position\n if (Math.abs(end - start) < 0.1) {\n seekTo(start);\n setSelectionStart(start);\n setSelectionEnd(start);\n\n if (isPlaying && playoutRef.current) {\n playoutRef.current.stop();\n play(start);\n }\n } else {\n // It was a drag - finalize the selection\n setSelectionStart(start);\n setSelectionEnd(end);\n }\n }, [isSelecting, selectionStart, samplesPerPixel, sampleRate, controls, seekTo, isPlaying, playoutRef, play]);\n\n // Show loading if peaks not ready\n if (peaksDataArray.length === 0) {\n return <div className={className}>Loading waveform...</div>;\n }\n\n // Empty track controls (MediaElement is single-track, no mute/solo needed)\n const emptyControls = null;\n\n return (\n <DevicePixelRatioProvider>\n <PlaylistInfoContext.Provider\n value={{\n samplesPerPixel,\n sampleRate,\n zoomLevels: [samplesPerPixel],\n waveHeight,\n timeScaleHeight,\n duration,\n controls,\n barWidth,\n barGap,\n }}\n >\n <Playlist\n theme={theme}\n backgroundColor={waveformColorToCss(theme.waveOutlineColor)}\n timescaleBackgroundColor={theme.timescaleBackgroundColor}\n scrollContainerWidth={tracksFullWidth + (controls.show ? controls.width : 0)}\n timescaleWidth={tracksFullWidth}\n tracksWidth={tracksFullWidth}\n controlsWidth={controls.show ? controls.width : 0}\n onTracksMouseDown={handleMouseDown}\n onTracksMouseMove={handleMouseMove}\n onTracksMouseUp={handleMouseUp}\n scrollContainerRef={(el) => { scrollContainerRef.current = el; }}\n isSelecting={isSelecting}\n timescale={\n timeScaleHeight > 0 ? (\n <StyledTimeScale\n duration={duration * 1000}\n marker={10000}\n bigStep={5000}\n secondStep={1000}\n />\n ) : undefined\n }\n >\n <>\n {peaksDataArray.map((trackClipPeaks, trackIndex) => {\n // For MediaElement, we have a single track with a single clip\n const maxChannels = trackClipPeaks.length > 0\n ? Math.max(...trackClipPeaks.map(clip => clip.peaks.data.length))\n : 1;\n\n return (\n <TrackControlsContext.Provider key={trackIndex} value={emptyControls}>\n <TrackComponent\n numChannels={maxChannels}\n backgroundColor={waveformColorToCss(theme.waveOutlineColor)}\n offset={0}\n width={tracksFullWidth}\n hasClipHeaders={false}\n trackId={`media-element-track-${trackIndex}`}\n isSelected={true}\n >\n {trackClipPeaks.map((clip, clipIndex) => {\n const peaksData = clip.peaks;\n const width = peaksData.length;\n\n return (\n <Clip\n key={`${trackIndex}-${clipIndex}`}\n clipId={clip.clipId}\n trackIndex={trackIndex}\n clipIndex={clipIndex}\n trackName={clip.trackName}\n startSample={clip.startSample}\n durationSamples={clip.durationSamples}\n samplesPerPixel={samplesPerPixel}\n showHeader={false}\n disableHeaderDrag={true}\n isSelected={true}\n trackId={`media-element-track-${trackIndex}`}\n >\n {peaksData.data.map((channelPeaks: Peaks, channelIndex: number) => (\n <ChannelWithMediaElementProgress\n key={`${trackIndex}-${clipIndex}-${channelIndex}`}\n index={channelIndex}\n data={channelPeaks}\n bits={peaksData.bits}\n length={width}\n clipStartSample={clip.startSample}\n clipDurationSamples={clip.durationSamples}\n />\n ))}\n </Clip>\n );\n })}\n </TrackComponent>\n </TrackControlsContext.Provider>\n );\n })}\n {annotations.length > 0 && (\n <AnnotationBoxesWrapper height={30} width={tracksFullWidth}>\n {annotations.map((annotation, index) => {\n const startPosition = (annotation.start * sampleRate) / samplesPerPixel;\n const endPosition = (annotation.end * sampleRate) / samplesPerPixel;\n const label = getAnnotationBoxLabel\n ? getAnnotationBoxLabel(annotation)\n : annotation.id;\n return (\n <AnnotationBox\n key={annotation.id}\n annotationId={annotation.id}\n annotationIndex={index}\n startPosition={startPosition}\n endPosition={endPosition}\n label={label}\n color=\"#ff9800\"\n isActive={annotation.id === activeAnnotationId}\n onClick={() => handleAnnotationClick(annotation)}\n editable={false}\n />\n );\n })}\n </AnnotationBoxesWrapper>\n )}\n {selectionStart !== selectionEnd && (\n <Selection\n startPosition={\n (Math.min(selectionStart, selectionEnd) * sampleRate) / samplesPerPixel +\n (controls.show ? controls.width : 0)\n }\n endPosition={\n (Math.max(selectionStart, selectionEnd) * sampleRate) / samplesPerPixel +\n (controls.show ? controls.width : 0)\n }\n color={theme.selectionColor}\n />\n )}\n <AnimatedMediaElementPlayhead\n color={theme.playheadColor}\n controlsOffset={controls.show ? controls.width : 0}\n />\n </>\n </Playlist>\n {annotations.length > 0 && (\n <AnnotationText\n annotations={annotations}\n activeAnnotationId={activeAnnotationId ?? undefined}\n shouldScrollToActive={true}\n editable={false}\n annotationListConfig={{ linkEndpoints: false, continuousPlay }}\n height={annotationTextHeight}\n onAnnotationUpdate={() => {}}\n renderAnnotationItem={renderAnnotationItem}\n />\n )}\n </PlaylistInfoContext.Provider>\n </DevicePixelRatioProvider>\n );\n};\n"],"names":["linearCurve","length","fadeIn","curve","scale","i","x","exponentialCurve","index","sCurveCurve","phase","logarithmicCurve","base","generateCurve","type","applyFadeIn","param","startTime","duration","startValue","endValue","scaledCurve","range","applyFadeOut","ToneTrack","options","Volume","Panner","Gain","destination","getDestination","cleanup","clipInfos","clipInfo","player","Player","fadeGain","clipPlayer","clipStartTime","clipOffset","audioParam","skipTime","fadeInDuration","remainingFadeDuration","fadeProgress","fadeOutStartInClip","absoluteFadeOutStart","elapsedFadeOut","gain","pan","muted","soloed","when","offset","newPlayer","playbackPosition","clipStart","clipEnd","currentTime","now","remainingDuration","clipDuration","delay","elapsed","stopWhen","lastClip","callback","TonePlayout","Volume2","getDestination2","track","start","trackOptions","optionsWithDestination","toneTrack","trackId","now2","currentSessionId","trackStartTime","bufferOffset","getTransport","hasSoloedTracks","id","manuallyMuted","time","getContext","globalToneContext","getGlobalContext","Context","setContext","resumeGlobalAudioContext","context","canUseDOM","useIsomorphicLayoutEffect","useLayoutEffect","useEffect","useEvent","handler","handlerRef","useRef","useCallback","_len","args","_key","useLatestValue","value","dependencies","valueRef","useNodeRef","onChange","onChangeHandler","node","setNodeRef","element","ids","useUniqueId","prefix","useMemo","CSS","transform","y","scaleX","scaleY","_ref","property","easing","Action","noop","defaultCoordinates","Direction","EventName","KeyboardCode","MouseButton","AutoScrollActivator","TraversalOrder","MeasuringStrategy","MeasuringFrequency","useSyntheticListeners","listeners","acc","eventName","event","defaultInternalContext","InternalContext","createContext","ActiveDraggableContext","Status","NullContext","defaultRole","ID_PREFIX","useDraggable","data","disabled","attributes","key","activators","activatorEvent","active","activeNodeRect","ariaDescribedById","draggableNodes","over","useContext","role","roleDescription","tabIndex","isDragging","activatorNode","setActivatorNodeRef","dataRef","memoizedAttributes","e","a","o","r","p","s","t","c","m","d","l","f","g","w","h","styled","props","BaseButton","styled2","BaseCheckboxWrapper","styled3","BaseCheckbox","BaseCheckboxLabel","BaseControlButton","styled4","BaseInput","styled5","BaseLabel","styled6","ScreenReaderOnly","BaseSelect","styled7","BaseSlider","styled8","AutomaticScrollCheckbox","checked","className","handleChange","jsxs","jsx2","isWaveformGradient","color","waveformColorToCss","direction","stops","stop","defaultTheme","MAX_CANVAS_WIDTH","createCanvasFillStyle","ctx","width","height","gradient","Waveform","styled9","Wrapper","Channel","bits","devicePixelRatio","waveHeight","waveOutlineColor","waveFillColor","barWidth","barGap","transparentBackground","drawMode","canvasesRef","canvasRef","canvas","index2","canvases","step","globalPixelOffset","h2","maxValue","canvasWidth","fillColor","canvasStartGlobal","canvasEndGlobal","firstBarGlobal","barGlobal","peakIndex","minPeak","maxPeak","min","max","totalWidth","waveformCount","waveforms","currentWidth","waveform","jsx3","backgroundCss","CLIP_HEADER_HEIGHT","HeaderContainer","styled10","TrackName","ClipHeaderPresentational","trackName","isSelected","jsx4","ClipHeader","clipId","trackIndex","clipIndex","disableDrag","dragHandleProps","CLIP_BOUNDARY_WIDTH","CLIP_BOUNDARY_WIDTH_TOUCH","BoundaryContainer","styled11","ClipBoundary","edge","touchOptimized","isHovered","setIsHovered","React2","jsx5","FadeContainer","styled12","FadeSvg","generateFadePath","curveType","points","numPoints","progress","curvedProgress","FadeOverlay","left","theme","useTheme","jsx6","ClipContainer","styled13","ChannelsWrapper","Clip","children","startSample","durationSamples","samplesPerPixel","showHeader","disableHeaderDrag","isOverlay","onMouseDown","fadeOut","sampleRate","showFades","enableDrag","draggableId","leftBoundaryId","leftBoundaryAttributes","leftBoundaryListeners","setLeftBoundaryActivatorRef","isLeftBoundaryDragging","rightBoundaryId","rightBoundaryAttributes","rightBoundaryListeners","setRightBoundaryActivatorRef","isRightBoundaryDragging","style","jsxs2","jsx7","Fragment","VolumeContainer","styled14","VolumeLabel","VolumeSlider","MasterVolumeControl","volume","jsxs3","jsx8","styled15","Wrapper2","styled16","ScrollContainer","TimescaleWrapper","TracksContainer","ClickOverlay","Playlist","backgroundColor","timescaleBackgroundColor","timescale","timescaleWidth","tracksWidth","scrollContainerWidth","controlsWidth","onTracksClick","onTracksMouseDown","onTracksMouseMove","onTracksMouseUp","scrollContainerRef","isSelecting","jsx10","jsxs5","withTheme","SelectionOverlay","styled17","Selection","startPosition","endPosition","jsx11","styled18","DraggableMarkerHandle","TimescaleLoopShade","LoopRegionMarkers","markerColor","regionColor","onLoopStartChange","onLoopEndChange","onLoopRegionMove","minPosition","maxPosition","draggingMarker","setDraggingMarker","useState","dragStartX","useRef3","dragStartPosition","dragStartEnd","handleMarkerMouseDown","useCallback2","marker","handleMouseMove","moveEvent","delta","newPosition","clampedPosition","handleMouseUp","handleRegionMouseDown","regionWidth","newStart","newEnd","jsxs6","Fragment2","jsx12","TimescaleLoopCreator","TimescaleLoopRegion","onLoopRegionChange","controlsOffset","isCreating","setIsCreating","createStartX","containerRef","hasLoopRegion","handleBackgroundMouseDown","target","rect","clickX","clampedX","currentX","clampedCurrentX","clockFormat","seconds","decimals","hours","minutes","secs","formatTime","format","parseTime","timeStr","parts","TimeInput","label","readOnly","displayValue","setDisplayValue","useState2","useEffect2","formatted","newDisplayValue","handleBlur","parsedValue","handleKeyDown","jsxs7","Fragment3","jsx13","SelectionTimeInputs","selectionStart","selectionEnd","onSelectionChange","timeFormat","setTimeFormat","useState3","useEffect3","timeFormatSelect","handleFormatChange","handleStartChange","handleEndChange","jsxs8","Fragment4","jsx14","getScale","DevicePixelRatioContext","DevicePixelRatioProvider","setScale","useState4","jsx15","useDevicePixelRatio","PlaylistInfoContext","createContext2","usePlaylistInfo","useContext2","useTheme2","useContext3","ThemeContext","TrackControlsContext","createContext3","jsx16","Fragment5","useTrackControls","useContext4","defaultProgress","defaultIsPlaying","defaultSelectionStart","defaultSelectionEnd","defaultPlayout","createContext4","SmartChannel","jsx18","secondsToPixels","formatTime2","milliseconds","PlaylistTimeScaleScroll","styled19","TimeTicks","TimeStamp","TimeScale","timeColor","bigStep","secondStep","renderTimestamp","canvasInfo","timeMarkers","useRef4","timeScaleHeight","showControls","controlWidth","useContext6","useEffect4","pixLeft","scaleHeight","widthX","pixPerSec","counter","pix","timeMs","timestamp","timestampContent","jsx19","React10","jsxs9","StyledTimeScale","withTheme2","SelectWrapper","styled20","TIME_FORMAT_OPTIONS","TimeFormatSelect","jsx21","option","Container","styled21","ChannelContainer","ControlsWrapper","Track","numChannels","hasClipHeaders","onClick","show","controls","jsxs10","jsx22","Button","styled22","ButtonGroup","styled23","Controls","styled24","Header","styled25","VolumeDownIcon","jsx23","SpeakerLowIcon","VolumeUpIcon","jsx24","SpeakerHighIcon","Slider","styled26","SliderWrapper","styled27","styled28","findMinMax","array","curr","convert","n","v","makeTypedArray","extractPeaks","channel","chanLength","numPeaks","peaks","end","segment","extrema","makeMono","channelPeaks","numChan","weight","extractPeaksFromBuffer","source","isMono","cueIn","cueOut","actualCueOut","slice","generatePeaks","audioBuffer","offsetSamples","WaveformDataChannel","waveformData","channelIndex","sample","values","INT8_MAX","INT8_MIN","INT16_MAX","INT16_MIN","calculateWaveformDataLength","audio_sample_count","data_length","samples_remaining","generateWaveformData","amplitude_scale","split_channels","sample_rate","channels","output_channels","header_size","bytes_per_sample","total_size","buffer","data_view","scale_counter","min_value","max_value","range_min","range_max","_channel","_channel2","_channel3","_channel4","_typeof","isJsonWaveformData","isBinaryWaveformData","isCompatible","view","version","convertJsonToBinary","expected_length","array_buffer","data_object","_i","isNullOrUndefined","decodeBase64","base64","enableUnicode","binaryString","createURL","sourcemapArg","enableUnicodeArg","body","blob","createBase64WorkerFactory","url","WorkerFactory","WaveformData","defaultOptions","getOptions","opts","getChannelData","audio_buffer","createFromAudioBuffer","worker","evt","createFromArrayBuffer","audioContext","audioData","errorCallback","error","promise","WaveformResampler","input_buffer_length_samples","output_buffer_length_samples","output_header_size","count","total","_i2","_i3","resampler","self","otherWaveforms","otherWaveform","combinedBuffer","headerSize","totalSize","totalDataLength","bufferCollection","dataSize","totalBuffer","sourceHeader","totalBufferView","_i4","dataOfTotalBuffer","_i5","_buffer","startIndex","endIndex","output_data","output_dataview","loadWaveformData","src","response","arrayBuffer","json","waveformDataToPeaks","minArray","maxArray","loadPeaksFromWaveformData","getWaveformDataMetadata","extractPeaksFromWaveformData","processedData","sourceScale","parseAeneas","serializeAeneas","annotation","Box","Label","ResizeHandle","AnnotationBox","annotationId","annotationIndex","isActive","editable","leftAttributes","leftListeners","setLeftActivatorRef","isLeftDragging","rightAttributes","rightListeners","setRightActivatorRef","isRightDragging","createPointerDownHandler","dndKitHandler","handleHandleClick","ControlsPlaceholder","BoxesContainer","AnnotationBoxesWrapper","Container3","AnnotationItem","AnnotationHeader","AnnotationInfo","AnnotationIdLabel","TimeRange","AnnotationControls","ControlButton2","AnnotationTextContent","AnnotationTextComponent","annotations","activeAnnotationId","shouldScrollToActive","annotationListConfig","onAnnotationClick","onAnnotationUpdate","renderAnnotationItem","activeAnnotationRef","prevActiveIdRef","container","handleScroll","mins","handleTextEdit","newText","updatedAnnotations","handleIdEdit","newId","trimmedId","handleControlClick","control","annotationsCopy","getIconClass","classString","handleClick","idx","AnnotationText2","ContinuousPlayCheckbox","LinkEndpointsCheckbox","BaseCheckboxWrapper2","BaseCheckbox2","BaseCheckboxLabel2","EditableCheckbox","BaseCheckboxWrapper3","BaseCheckbox3","BaseCheckboxLabel3","StyledButton","DownloadAnnotationsButton","filename","handleDownload","jsonData","jsonString","link","jsx9","useTimeFormat","formatTimeUtil","timeString","parseTimeUtil","DEFAULT_ZOOM_LEVELS","useZoomControls","initialSamplesPerPixel","zoomLevels","zoomIndex","setZoomIndex","canZoomIn","canZoomOut","zoomIn","prev","zoomOut","useMasterVolume","playoutRef","initialVolume","onVolumeChange","masterVolume","setMasterVolumeState","setMasterVolume","useMasterAnalyser","fftSize","analyserRef","masterEffects","masterGainNode","_isOffline","analyserNode","Analyser","createClip","name","sourceDurationSamples","generateId","createClipFromSeconds","sourceDuration","createTrack","clips","useAudioTracks","configs","progressive","tracks","setTracks","loading","setLoading","setError","loadedCount","setLoadedCount","totalCount","cancelled","loadedTracksMap","createTrackFromConfig","config","clip","Tone","loadPromises","_","loadedTracks","err","errorMessage","useClipDragHandlers","onTracksChange","originalClipStateRef","React","collisionModifier","boundary","timeDelta","newStartTime","sortedClips","b","sortedIndex","previousClip","previousEndTime","nextClip","newEndTime","nextClipStartTime","constrainedX","onDragStart","onDragMove","sampleDelta","MIN_DURATION_SAMPLES","originalClip","newTracks","tIdx","newClips","cIdx","audioBufferDurationSamples","constrainedDelta","minDeltaForStart","minDeltaForOffset","minDeltaForPrevious","maxDeltaForMinDuration","newOffsetSamples","newDurationSamples","newStartSample","onDragEnd","previousEndSample","LINK_THRESHOLD","useAnnotationDragHandlers","onAnnotationsChange","linkEndpoints","originalAnnotationStateRef","originalState","newTime","updateAnnotationBoundaries","isDraggingStart","shouldLinkEndpoints","constrainedStart","prevAnnotation","constrainedEnd","nextAnnotation","currentIndex","current","next","nextDelta","isWindow","elementString","isNode","getWindow","_target$ownerDocument","_target$ownerDocument2","isDocument","Document","isHTMLElement","isSVGElement","getOwnerDocument","createAdjustmentFn","modifier","object","adjustments","accumulator","adjustment","entries","valueAdjustment","subtract","hasViewportRelativeCoordinates","isTouchEvent","TouchEvent","getEventCoordinates","useSensor","sensor","useSensors","sensors","Listeners","listener","_this$target","_this$target2","getEventListenerTarget","EventTarget","hasExceededDistance","measurement","dx","dy","preventDefault","stopPropagation","isDistanceConstraint","constraint","isDelayConstraint","AbstractPointerSensor","events","listenerTarget","_getEventCoordinates","activationConstraint","bypassActivationConstraint","onPending","initialCoordinates","onStart","_getEventCoordinates2","activated","onMove","coordinates","onAbort","onEnd","onCancel","_this$document$getSel","PointerSensor","_ref2","onActivation","events$1","MouseSensor","events$2","TouchSensor","touches","useDragSensors","touchDelay","touchTolerance","mouseDistance","mouseSensor","touchSensor","pointerSensor","useClipSplitting","currentTimeRef","usePlaybackAnimation","selectedTrackId","usePlaylistState","splitClipAt","splitTime","clipEndTime","splitSample","splitPixel","clipEndSample","snappedSplitSample","firstClipStartSample","firstClipDurationSamples","secondClipStartSample","secondClipDurationSamples","offsetIncrement","firstClip","secondClip","useKeyboardShortcuts","shortcuts","enabled","matchingShortcut","shortcut","keyMatch","ctrlMatch","shiftMatch","metaMatch","altMatch","getShortcutLabel","isMac","usePlaybackShortcuts","additionalShortcuts","overrideShortcuts","isPlaying","setCurrentTime","play","pause","usePlaylistControls","usePlaylistData","togglePlayPause","stopPlayback","rewindToStart","activeShortcuts","TIME_DELTA","useAnnotationKeyboardControls","onActiveAnnotationChange","continuousPlay","onPlay","activeIndex","scrollToAnnotation","containerWidth","startPixel","endPixel","annotationCenter","scrollLeft","visibleStart","visibleEnd","targetScrollLeft","moveStartBoundary","actualDelta","moveEndBoundary","newNextStart","selectPrevious","selectNext","selectFirst","selectLast","clearSelection","playActiveAnnotation","playDuration","activeAnnotationShortcuts","navigationShortcuts","concatenateAudioData","chunks","totalLength","sum","chunk","result","createAudioBuffer","samples","channelCount","typedSamples","peakArray","j","appendPeaks","existingPeaks","newSamples","totalSamplesProcessed","remainder","samplesToComplete","updated","newPeaks2","result2","newPeaks","useRecording","stream","isRecording","setIsRecording","isPaused","setIsPaused","setDuration","setPeaks","setAudioBuffer","level","setLevel","peakLevel","setPeakLevel","workletLoadedRef","workletNodeRef","mediaStreamSourceRef","recordedChunksRef","totalSamplesRef","animationFrameRef","startTimeRef","isRecordingRef","isPausedRef","loadWorklet","workletUrl","_documentCurrentScript","startRecording","workletNode","prevPeaks","updateDuration","stopRecording","allSamples","rawContext","pauseRecording","resumeRecording","useMicrophoneAccess","setStream","devices","setDevices","hasPermission","setHasPermission","isLoading","setIsLoading","enumerateDevices","audioInputs","device","requestAccess","deviceId","audioConstraints","constraints","newStream","stopStream","useMicrophoneLevel","updateRate","smoothingTimeConstant","meterRef","useRef2","sourceRef","resetPeak","isMounted","getContext2","meter","Meter","connect","updateInterval","lastUpdateTime","updateLevel","db","dbValue","normalized","MeterContainer","getLevelGradient","MeterFill","PeakIndicator","ScaleMarkers","ScaleMark","VUMeterComponent","clampedLevel","clampedPeak","jsxs4","useIntegratedRecording","recordingOptions","isMonitoring","setIsMonitoring","selectedDevice","setSelectedDevice","micError","startRec","stopRec","recError","selectedTrackIndex","selectedTrack","currentTimeSamples","lastClipEndSample","endSamples","newClip","requestMicAccess","changeDevice","effectDefinitions","getEffectDefinition","def","getEffectsByCategory","category","effectCategories","effectConstructors","Reverb","Freeverb","JCReverb","FeedbackDelay","PingPongDelay","Chorus","Phaser","Tremolo","Vibrato","AutoPanner","AutoFilter","AutoWah","EQ3","Distortion","BitCrusher","Chebyshev","Compressor","Limiter","Gate","StereoWidener","instanceCounter","generateInstanceId","createEffectInstance","definition","initialParams","Constructor","effect","instanceId","createEffectChain","effects","useDynamicEffects","activeEffects","setActiveEffects","activeEffectsRef","effectInstancesRef","graphNodesRef","rebuildChain","nodes","instances","ae","inst","currentNode","addEffect","effectId","params","instance","newActiveEffect","removeEffect","updateParameter","paramName","toggleBypass","newBypassed","originalWet","reorderEffects","fromIndex","toIndex","newEffects","removed","clearAllEffects","createOfflineEffectsFunction","nonBypassedEffects","offlineInstances","activeEffect","useTrackDynamicEffects","trackEffectsState","setTrackEffectsState","trackEffectInstancesRef","trackGraphNodesRef","rebuildTrackChain","trackEffects","graphEnd","instancesMap","addEffectToTrack","newState","existing","removeEffectFromTrack","updateTrackEffectParameter","trackEffectsStateRef","clearTrackEffects","getTrackEffectsFunction","createOfflineTrackEffectsFunction","encodeWav","bitDepth","numSamples","bytesPerSample","blockAlign","byteRate","writeString","channelData","ch","clampedSample","intSample","str","downloadBlob","useExportWav","isExporting","setIsExporting","setProgress","trackStates","mode","autoDownload","applyEffects","effectsFunction","createOfflineTrackEffects","onProgress","totalDurationSamples","tracksToRender","hasSolo","state","hasOfflineTrackEffects","renderedBuffer","renderWithToneEffects","offlineCtx","scheduledClips","totalClips","scheduleClip","currentProgress","exportFilename","message","_trackStates","Offline","ToneAudioBuffer","transport","trackVolume","gainToDb","trackPan","trackMute","clipGain","toneBuffer","fadeInStart","fadeInEnd","fadeOutStart","fadeOutEnd","trackState","gainNode","baseGain","pannerNode","applyFadeEnvelope","gainParam","endTime","fadeType","expStart","expEnd","logCurve","generateFadeCurve","sCurve","curveValue","PlaybackAnimationContext","PlaylistStateContext","PlaylistControlsContext","PlaylistDataContext","WaveformPlaylistContext","WaveformPlaylistProvider","mono","automaticScroll","userTheme","annotationList","onReady","_onAnnotationUpdate","progressBarWidthProp","progressBarWidth","setAnnotations","setActiveAnnotationIdState","setIsPlaying","audioBuffers","setAudioBuffers","peaksDataArray","setPeaksDataArray","setTrackStates","setSelectionStart","setSelectionEnd","setSelectedTrackId","isAutomaticScroll","setIsAutomaticScroll","setContinuousPlayState","setLinkEndpoints","annotationsEditable","setAnnotationsEditable","isLoopEnabled","setIsLoopEnabledState","loopStart","setLoopStartState","loopEnd","setLoopEndState","playStartPositionRef","trackStatesRef","playbackStartTimeRef","audioStartPositionRef","playbackEndTimeRef","isAutomaticScrollRef","continuousPlayRef","activeAnnotationIdRef","samplesPerPixelRef","isLoopEnabledRef","selectionStartRef","selectionEndRef","loopStartRef","loopEndRef","zoom","setContinuousPlay","setActiveAnnotationId","setLoopEnabled","setLoopRegion","setLoopRegionFromSelection","clearLoopRegion","oldSamplesPerPixel","newSamplesPerPixel","centerPixel","sr","newCenterPixel","newScrollLeft","pendingResumeRef","wasPlaying","resumePosition","buffers","maxDuration","prevStates","playout","currentTrackStates","playableClips","trackObj","clipSampleRate","allTrackPeaks","extractedPeaks","parsedAnnotations","ann","startAnimationLoop","updateTime","currentAnnotation","lastAnnotation","activeAnnotation","pixelPosition","visualPosition","hasValidLoopRegion","timeNow","stopAnimationLoop","currentPos","position","toneStart","actualStartTime","startTimeNow","pauseTime","seekTo","clampedTime","setTrackMute","newStates","setTrackSolo","setTrackVolume","setTrackPan","setSelection","setScrollContainer","minimumPlaylistHeight","animationValue","stateValue","controlsValue","dataValue","mergedTheme","ThemeProvider","jsx","useWaveformPlaylist","MediaElementTrack","rate","clampedRate","MediaElementPlayout","_when","adjustedDuration","_trackId","_soloed","MediaElementAnimationContext","MediaElementStateContext","MediaElementControlsContext","MediaElementDataContext","MediaElementPlaylistProvider","initialPlaybackRate","playbackRate","setPlaybackRateState","mediaTrack","clipPeaks","setPlaybackRate","useMediaElementAnimation","useMediaElementState","useMediaElementControls","useMediaElementData","PlayButton","PauseButton","StopButton","RewindButton","FastForwardButton","SkipBackwardButton","skipAmount","SkipForwardButton","LoopButton","defaultEnd","SetLoopRegionButton","hasValidSelection","ZoomInButton","ZoomOutButton","BaseMasterVolumeControl","BaseTimeFormatSelect","PositionDisplay","AudioPosition","timeRef","BaseSelectionTimeInputs","setAutomaticScroll","BaseAutomaticScrollCheckbox","BaseContinuousPlayCheckbox","BaseLinkEndpointsCheckbox","BaseEditableCheckbox","BaseDownloadAnnotationsButton","ExportWavButton","onExportComplete","onExportError","exportWav","handleExport","buttonLabel","PlayheadLine","AnimatedPlayhead","playheadRef","updatePosition","ChannelWrapper","Background","ProgressOverlay","ChannelWithProgress","clipStartSample","clipDurationSamples","smartChannelProps","progressRef","progressColor","updateProgress","currentSample","progressWidth","playedSamples","DEFAULT_EMPTY_TRACK_DURATION","renderTrackControls","renderPlayhead","annotationControls","_annotationListConfig","annotationTextHeight","getAnnotationBoxLabel","showClipHeaders","interactiveClips","recordingState","setIsSelecting","handleScrollContainerRef","displayDuration","recordingEndTime","tracksFullWidth","handleAnnotationClick","selectTrack","handleMouseDown","clickTime","trackY","cumulativeHeight","clickedTrackIndex","trackClipPeaks","trackHeight","moveTime","startPixels","endPixels","startSeconds","endSeconds","trackControls","maxChannels","TrackComponent","peaksData","AnnotationText","AnimatedMediaElementPlayhead","ChannelWithMediaElementProgress","MediaElementWaveform","emptyControls","el"],"mappings":"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","x_google_ignoreList":[1,2,3,4,5,6,7,8,12,14,24,25]}
1
+ {"version":3,"file":"index.js","sources":["../../playout/dist/index.mjs","../../../node_modules/.pnpm/@dnd-kit+utilities@3.2.2_react@18.3.1/node_modules/@dnd-kit/utilities/dist/utilities.esm.js","../../../node_modules/.pnpm/@phosphor-icons+react@2.1.10_react-dom@18.3.1_react@18.3.1/node_modules/@phosphor-icons/react/dist/defs/SpeakerHigh.es.js","../../../node_modules/.pnpm/@phosphor-icons+react@2.1.10_react-dom@18.3.1_react@18.3.1/node_modules/@phosphor-icons/react/dist/defs/SpeakerLow.es.js","../../../node_modules/.pnpm/@phosphor-icons+react@2.1.10_react-dom@18.3.1_react@18.3.1/node_modules/@phosphor-icons/react/dist/lib/context.es.js","../../../node_modules/.pnpm/@phosphor-icons+react@2.1.10_react-dom@18.3.1_react@18.3.1/node_modules/@phosphor-icons/react/dist/lib/IconBase.es.js","../../../node_modules/.pnpm/@phosphor-icons+react@2.1.10_react-dom@18.3.1_react@18.3.1/node_modules/@phosphor-icons/react/dist/csr/SpeakerHigh.es.js","../../../node_modules/.pnpm/@phosphor-icons+react@2.1.10_react-dom@18.3.1_react@18.3.1/node_modules/@phosphor-icons/react/dist/csr/SpeakerLow.es.js","../../ui-components/dist/index.mjs","../../webaudio-peaks/dist/index.mjs","../src/peaksUtil.ts","../../../node_modules/.pnpm/waveform-data@4.5.2/node_modules/waveform-data/dist/waveform-data.esm.js","../src/waveformDataLoader.ts","../../annotations/dist/index.mjs","../src/hooks/useTimeFormat.ts","../src/hooks/useZoomControls.ts","../src/hooks/useMasterVolume.ts","../src/hooks/useAudioEffects.ts","../../core/dist/index.mjs","../src/hooks/useAudioTracks.ts","../src/hooks/useClipDragHandlers.ts","../src/hooks/useAnnotationDragHandlers.ts","../src/hooks/useDragSensors.ts","../src/hooks/useClipSplitting.ts","../src/hooks/useKeyboardShortcuts.ts","../src/hooks/usePlaybackShortcuts.ts","../src/hooks/useAnnotationKeyboardControls.ts","../../recording/dist/index.mjs","../src/hooks/useIntegratedRecording.ts","../src/effects/effectDefinitions.ts","../src/effects/effectFactory.ts","../src/hooks/useDynamicEffects.ts","../src/hooks/useTrackDynamicEffects.ts","../src/utils/wavEncoder.ts","../src/hooks/useExportWav.ts","../src/WaveformPlaylistContext.tsx","../../media-element-playout/dist/index.mjs","../src/MediaElementPlaylistContext.tsx","../src/components/PlaybackControls.tsx","../src/components/ZoomControls.tsx","../src/components/ContextualControls.tsx","../src/components/AnnotationControls.tsx","../src/components/ExportControls.tsx","../src/components/AnimatedPlayhead.tsx","../src/components/ChannelWithProgress.tsx","../src/components/Waveform.tsx","../src/components/AnimatedMediaElementPlayhead.tsx","../src/components/ChannelWithMediaElementProgress.tsx","../src/components/MediaElementWaveform.tsx"],"sourcesContent":["// src/TonePlayout.ts\nimport {\n Volume as Volume2,\n getDestination as getDestination2,\n start,\n now as now2,\n getTransport,\n getContext\n} from \"tone\";\n\n// src/ToneTrack.ts\nimport {\n Player,\n Volume,\n Gain,\n Panner,\n getDestination,\n now\n} from \"tone\";\n\n// src/fades.ts\nfunction linearCurve(length, fadeIn) {\n const curve = new Float32Array(length);\n const scale = length - 1;\n for (let i = 0; i < length; i++) {\n const x = i / scale;\n curve[i] = fadeIn ? x : 1 - x;\n }\n return curve;\n}\nfunction exponentialCurve(length, fadeIn) {\n const curve = new Float32Array(length);\n const scale = length - 1;\n for (let i = 0; i < length; i++) {\n const x = i / scale;\n const index = fadeIn ? i : length - 1 - i;\n curve[index] = Math.exp(2 * x - 1) / Math.E;\n }\n return curve;\n}\nfunction sCurveCurve(length, fadeIn) {\n const curve = new Float32Array(length);\n const phase = fadeIn ? Math.PI / 2 : -Math.PI / 2;\n for (let i = 0; i < length; i++) {\n curve[i] = Math.sin(Math.PI * i / length - phase) / 2 + 0.5;\n }\n return curve;\n}\nfunction logarithmicCurve(length, fadeIn, base = 10) {\n const curve = new Float32Array(length);\n for (let i = 0; i < length; i++) {\n const index = fadeIn ? i : length - 1 - i;\n const x = i / length;\n curve[index] = Math.log(1 + base * x) / Math.log(1 + base);\n }\n return curve;\n}\nfunction generateCurve(type, length, fadeIn) {\n switch (type) {\n case \"linear\":\n return linearCurve(length, fadeIn);\n case \"exponential\":\n return exponentialCurve(length, fadeIn);\n case \"sCurve\":\n return sCurveCurve(length, fadeIn);\n case \"logarithmic\":\n return logarithmicCurve(length, fadeIn);\n default:\n return linearCurve(length, fadeIn);\n }\n}\nfunction applyFadeIn(param, startTime, duration, type = \"linear\", startValue = 0, endValue = 1) {\n if (duration <= 0) return;\n if (type === \"linear\") {\n param.setValueAtTime(startValue, startTime);\n param.linearRampToValueAtTime(endValue, startTime + duration);\n } else if (type === \"exponential\") {\n param.setValueAtTime(Math.max(startValue, 1e-3), startTime);\n param.exponentialRampToValueAtTime(Math.max(endValue, 1e-3), startTime + duration);\n } else {\n const curve = generateCurve(type, 1e4, true);\n const scaledCurve = new Float32Array(curve.length);\n const range = endValue - startValue;\n for (let i = 0; i < curve.length; i++) {\n scaledCurve[i] = startValue + curve[i] * range;\n }\n param.setValueCurveAtTime(scaledCurve, startTime, duration);\n }\n}\nfunction applyFadeOut(param, startTime, duration, type = \"linear\", startValue = 1, endValue = 0) {\n if (duration <= 0) return;\n if (type === \"linear\") {\n param.setValueAtTime(startValue, startTime);\n param.linearRampToValueAtTime(endValue, startTime + duration);\n } else if (type === \"exponential\") {\n param.setValueAtTime(Math.max(startValue, 1e-3), startTime);\n param.exponentialRampToValueAtTime(Math.max(endValue, 1e-3), startTime + duration);\n } else {\n const curve = generateCurve(type, 1e4, false);\n const scaledCurve = new Float32Array(curve.length);\n const range = startValue - endValue;\n for (let i = 0; i < curve.length; i++) {\n scaledCurve[i] = endValue + curve[i] * range;\n }\n param.setValueCurveAtTime(scaledCurve, startTime, duration);\n }\n}\n\n// src/ToneTrack.ts\nvar ToneTrack = class {\n // Count of currently playing clips\n constructor(options) {\n this.activePlayers = 0;\n this.track = options.track;\n this.volumeNode = new Volume(this.gainToDb(options.track.gain));\n this.panNode = new Panner(options.track.stereoPan);\n this.muteGain = new Gain(options.track.muted ? 0 : 1);\n const destination = options.destination || getDestination();\n if (options.effects) {\n const cleanup = options.effects(this.muteGain, destination, false);\n if (cleanup) {\n this.effectsCleanup = cleanup;\n }\n } else {\n this.muteGain.connect(destination);\n }\n const clipInfos = options.clips || (options.buffer ? [{\n buffer: options.buffer,\n startTime: 0,\n // Legacy: single buffer starts at timeline position 0\n duration: options.buffer.duration,\n // Legacy: play full buffer duration\n offset: 0,\n fadeIn: options.track.fadeIn,\n fadeOut: options.track.fadeOut,\n gain: 1\n }] : []);\n this.clips = clipInfos.map((clipInfo) => {\n const player = new Player({\n url: clipInfo.buffer,\n loop: false,\n onstop: () => {\n this.activePlayers--;\n if (this.activePlayers === 0 && this.onStopCallback) {\n this.onStopCallback();\n }\n }\n });\n const fadeGain = new Gain(clipInfo.gain);\n player.connect(fadeGain);\n fadeGain.chain(this.volumeNode, this.panNode, this.muteGain);\n return {\n player,\n clipInfo,\n fadeGain,\n pausedPosition: 0,\n playStartTime: 0\n };\n });\n }\n /**\n * Schedule fade envelopes for a clip at the given start time\n */\n scheduleFades(clipPlayer, clipStartTime, clipOffset = 0) {\n const { clipInfo, fadeGain } = clipPlayer;\n const audioParam = fadeGain.gain._param;\n audioParam.cancelScheduledValues(0);\n const skipTime = clipOffset - clipInfo.offset;\n if (clipInfo.fadeIn && skipTime < clipInfo.fadeIn.duration) {\n const fadeInDuration = clipInfo.fadeIn.duration;\n if (skipTime <= 0) {\n applyFadeIn(\n audioParam,\n clipStartTime,\n fadeInDuration,\n clipInfo.fadeIn.type || \"linear\",\n 0,\n clipInfo.gain\n );\n } else {\n const remainingFadeDuration = fadeInDuration - skipTime;\n const fadeProgress = skipTime / fadeInDuration;\n const startValue = clipInfo.gain * fadeProgress;\n applyFadeIn(\n audioParam,\n clipStartTime,\n remainingFadeDuration,\n clipInfo.fadeIn.type || \"linear\",\n startValue,\n clipInfo.gain\n );\n }\n } else {\n audioParam.setValueAtTime(clipInfo.gain, clipStartTime);\n }\n if (clipInfo.fadeOut) {\n const fadeOutStart = clipInfo.duration - clipInfo.fadeOut.duration;\n const fadeOutStartInClip = fadeOutStart - skipTime;\n if (fadeOutStartInClip > 0) {\n const absoluteFadeOutStart = clipStartTime + fadeOutStartInClip;\n applyFadeOut(\n audioParam,\n absoluteFadeOutStart,\n clipInfo.fadeOut.duration,\n clipInfo.fadeOut.type || \"linear\",\n clipInfo.gain,\n 0\n );\n } else if (fadeOutStartInClip > -clipInfo.fadeOut.duration) {\n const elapsedFadeOut = -fadeOutStartInClip;\n const remainingFadeDuration = clipInfo.fadeOut.duration - elapsedFadeOut;\n const fadeProgress = elapsedFadeOut / clipInfo.fadeOut.duration;\n const startValue = clipInfo.gain * (1 - fadeProgress);\n applyFadeOut(\n audioParam,\n clipStartTime,\n remainingFadeDuration,\n clipInfo.fadeOut.type || \"linear\",\n startValue,\n 0\n );\n }\n }\n }\n gainToDb(gain) {\n return 20 * Math.log10(gain);\n }\n setVolume(gain) {\n this.track.gain = gain;\n this.volumeNode.volume.value = this.gainToDb(gain);\n }\n setPan(pan) {\n this.track.stereoPan = pan;\n this.panNode.pan.value = pan;\n }\n setMute(muted) {\n this.track.muted = muted;\n this.muteGain.gain.value = muted ? 0 : 1;\n }\n setSolo(soloed) {\n this.track.soloed = soloed;\n }\n play(when, offset = 0, duration) {\n this.clips.forEach((clipPlayer) => {\n clipPlayer.player.stop();\n clipPlayer.player.disconnect();\n clipPlayer.player.dispose();\n const newPlayer = new Player({\n url: clipPlayer.clipInfo.buffer,\n loop: false,\n onstop: () => {\n this.activePlayers--;\n if (this.activePlayers === 0 && this.onStopCallback) {\n this.onStopCallback();\n }\n }\n });\n newPlayer.connect(clipPlayer.fadeGain);\n clipPlayer.player = newPlayer;\n clipPlayer.pausedPosition = 0;\n });\n this.activePlayers = 0;\n this.clips.forEach((clipPlayer) => {\n const { player, clipInfo } = clipPlayer;\n const playbackPosition = offset;\n const clipStart = clipInfo.startTime;\n const clipEnd = clipInfo.startTime + clipInfo.duration;\n if (playbackPosition < clipEnd) {\n this.activePlayers++;\n const currentTime = when ?? now();\n clipPlayer.playStartTime = currentTime;\n if (playbackPosition >= clipStart) {\n const clipOffset = playbackPosition - clipStart + clipInfo.offset;\n const remainingDuration = clipInfo.duration - (playbackPosition - clipStart);\n const clipDuration = duration ? Math.min(duration, remainingDuration) : remainingDuration;\n clipPlayer.pausedPosition = clipOffset;\n this.scheduleFades(clipPlayer, currentTime, clipOffset);\n player.start(currentTime, clipOffset, clipDuration);\n } else {\n const delay = clipStart - playbackPosition;\n const clipDuration = duration ? Math.min(duration - delay, clipInfo.duration) : clipInfo.duration;\n if (delay < (duration ?? Infinity)) {\n clipPlayer.pausedPosition = clipInfo.offset;\n this.scheduleFades(clipPlayer, currentTime + delay, clipInfo.offset);\n player.start(currentTime + delay, clipInfo.offset, clipDuration);\n } else {\n this.activePlayers--;\n }\n }\n }\n });\n }\n pause() {\n this.clips.forEach((clipPlayer) => {\n if (clipPlayer.player.state === \"started\") {\n const elapsed = (now() - clipPlayer.playStartTime) * clipPlayer.player.playbackRate;\n clipPlayer.pausedPosition = clipPlayer.pausedPosition + elapsed;\n }\n clipPlayer.player.stop();\n });\n this.activePlayers = 0;\n }\n stop(when) {\n const stopWhen = when ?? now();\n this.clips.forEach((clipPlayer) => {\n clipPlayer.player.stop(stopWhen);\n clipPlayer.pausedPosition = 0;\n });\n this.activePlayers = 0;\n }\n dispose() {\n if (this.effectsCleanup) {\n this.effectsCleanup();\n }\n this.clips.forEach((clipPlayer) => {\n clipPlayer.player.dispose();\n clipPlayer.fadeGain.dispose();\n });\n this.volumeNode.dispose();\n this.panNode.dispose();\n this.muteGain.dispose();\n }\n get id() {\n return this.track.id;\n }\n get duration() {\n if (this.clips.length === 0) return 0;\n const lastClip = this.clips[this.clips.length - 1];\n return lastClip.clipInfo.startTime + lastClip.clipInfo.duration;\n }\n get buffer() {\n return this.clips[0]?.clipInfo.buffer;\n }\n get isPlaying() {\n return this.clips.some((clipPlayer) => clipPlayer.player.state === \"started\");\n }\n get muted() {\n return this.track.muted;\n }\n get startTime() {\n return this.track.startTime;\n }\n setOnStopCallback(callback) {\n this.onStopCallback = callback;\n }\n};\n\n// src/TonePlayout.ts\nvar TonePlayout = class {\n constructor(options = {}) {\n this.tracks = /* @__PURE__ */ new Map();\n this.isInitialized = false;\n this.soloedTracks = /* @__PURE__ */ new Set();\n this.manualMuteState = /* @__PURE__ */ new Map();\n this.activeTracks = /* @__PURE__ */ new Map();\n // Map track ID to session ID\n this.playbackSessionId = 0;\n this.masterVolume = new Volume2(this.gainToDb(options.masterGain ?? 1));\n if (options.effects) {\n const cleanup = options.effects(this.masterVolume, getDestination2(), false);\n if (cleanup) {\n this.effectsCleanup = cleanup;\n }\n } else {\n this.masterVolume.toDestination();\n }\n if (options.tracks) {\n options.tracks.forEach((track) => {\n this.tracks.set(track.id, track);\n this.manualMuteState.set(track.id, track.muted);\n });\n }\n }\n gainToDb(gain) {\n return 20 * Math.log10(gain);\n }\n async init() {\n if (this.isInitialized) return;\n await start();\n this.isInitialized = true;\n }\n addTrack(trackOptions) {\n const optionsWithDestination = {\n ...trackOptions,\n destination: this.masterVolume\n };\n const toneTrack = new ToneTrack(optionsWithDestination);\n this.tracks.set(toneTrack.id, toneTrack);\n this.manualMuteState.set(toneTrack.id, trackOptions.track.muted ?? false);\n if (trackOptions.track.soloed) {\n this.soloedTracks.add(toneTrack.id);\n }\n return toneTrack;\n }\n /**\n * Apply solo muting after all tracks have been added.\n * Call this after adding all tracks to ensure solo logic is applied correctly.\n */\n applyInitialSoloState() {\n this.updateSoloMuting();\n }\n removeTrack(trackId) {\n const track = this.tracks.get(trackId);\n if (track) {\n track.dispose();\n this.tracks.delete(trackId);\n this.manualMuteState.delete(trackId);\n this.soloedTracks.delete(trackId);\n }\n }\n getTrack(trackId) {\n return this.tracks.get(trackId);\n }\n play(when, offset, duration) {\n if (!this.isInitialized) {\n console.warn(\"TonePlayout not initialized. Call init() first.\");\n return;\n }\n const startTime = when ?? now2();\n const playbackPosition = offset ?? 0;\n this.playbackSessionId++;\n const currentSessionId = this.playbackSessionId;\n this.activeTracks.clear();\n this.tracks.forEach((toneTrack) => {\n const trackStartTime = toneTrack.startTime;\n if (playbackPosition >= trackStartTime) {\n const bufferOffset = playbackPosition - trackStartTime;\n if (duration !== void 0) {\n this.activeTracks.set(toneTrack.id, currentSessionId);\n toneTrack.setOnStopCallback(() => {\n if (this.activeTracks.get(toneTrack.id) === currentSessionId) {\n this.activeTracks.delete(toneTrack.id);\n if (this.activeTracks.size === 0 && this.onPlaybackCompleteCallback) {\n this.onPlaybackCompleteCallback();\n }\n }\n });\n }\n toneTrack.play(startTime, bufferOffset, duration);\n } else {\n const delay = trackStartTime - playbackPosition;\n if (duration !== void 0) {\n this.activeTracks.set(toneTrack.id, currentSessionId);\n toneTrack.setOnStopCallback(() => {\n if (this.activeTracks.get(toneTrack.id) === currentSessionId) {\n this.activeTracks.delete(toneTrack.id);\n if (this.activeTracks.size === 0 && this.onPlaybackCompleteCallback) {\n this.onPlaybackCompleteCallback();\n }\n }\n });\n }\n toneTrack.play(startTime + delay, 0, duration);\n }\n });\n if (offset !== void 0) {\n getTransport().start(startTime, offset);\n } else {\n getTransport().start(startTime);\n }\n }\n pause() {\n getTransport().pause();\n this.tracks.forEach((track) => {\n track.pause();\n });\n }\n stop() {\n getTransport().stop();\n this.tracks.forEach((track) => {\n track.stop();\n });\n }\n setMasterGain(gain) {\n this.masterVolume.volume.value = this.gainToDb(gain);\n }\n setSolo(trackId, soloed) {\n const track = this.tracks.get(trackId);\n if (track) {\n track.setSolo(soloed);\n if (soloed) {\n this.soloedTracks.add(trackId);\n } else {\n this.soloedTracks.delete(trackId);\n }\n this.updateSoloMuting();\n }\n }\n updateSoloMuting() {\n const hasSoloedTracks = this.soloedTracks.size > 0;\n this.tracks.forEach((track, id) => {\n if (hasSoloedTracks) {\n if (!this.soloedTracks.has(id)) {\n track.setMute(true);\n } else {\n const manuallyMuted = this.manualMuteState.get(id) ?? false;\n track.setMute(manuallyMuted);\n }\n } else {\n const manuallyMuted = this.manualMuteState.get(id) ?? false;\n track.setMute(manuallyMuted);\n }\n });\n }\n setMute(trackId, muted) {\n const track = this.tracks.get(trackId);\n if (track) {\n this.manualMuteState.set(trackId, muted);\n track.setMute(muted);\n }\n }\n getCurrentTime() {\n return getTransport().seconds;\n }\n seekTo(time) {\n getTransport().seconds = time;\n }\n dispose() {\n this.tracks.forEach((track) => {\n track.dispose();\n });\n this.tracks.clear();\n if (this.effectsCleanup) {\n this.effectsCleanup();\n }\n this.masterVolume.dispose();\n }\n get context() {\n return getContext();\n }\n get sampleRate() {\n return getContext().sampleRate;\n }\n setOnPlaybackComplete(callback) {\n this.onPlaybackCompleteCallback = callback;\n }\n};\n\n// src/audioContext.ts\nimport { Context, setContext } from \"tone\";\nvar globalToneContext = null;\nfunction getGlobalContext() {\n if (!globalToneContext) {\n globalToneContext = new Context();\n setContext(globalToneContext);\n }\n return globalToneContext;\n}\nfunction getGlobalAudioContext() {\n return getGlobalContext().rawContext;\n}\nfunction getGlobalToneContext() {\n return getGlobalContext();\n}\nasync function resumeGlobalAudioContext() {\n const context = getGlobalContext();\n if (context.state !== \"running\") {\n await context.resume();\n }\n}\nfunction getGlobalAudioContextState() {\n return globalToneContext?.rawContext.state || \"suspended\";\n}\nasync function closeGlobalAudioContext() {\n if (globalToneContext && globalToneContext.rawContext.state !== \"closed\") {\n await globalToneContext.close();\n globalToneContext = null;\n }\n}\n\n// src/mediaStreamSourceManager.ts\nimport { getContext as getContext2 } from \"tone\";\nvar streamSources = /* @__PURE__ */ new Map();\nvar streamCleanupHandlers = /* @__PURE__ */ new Map();\nfunction getMediaStreamSource(stream) {\n if (streamSources.has(stream)) {\n return streamSources.get(stream);\n }\n const context = getContext2();\n const source = context.createMediaStreamSource(stream);\n streamSources.set(stream, source);\n const cleanup = () => {\n source.disconnect();\n streamSources.delete(stream);\n streamCleanupHandlers.delete(stream);\n stream.removeEventListener(\"ended\", cleanup);\n stream.removeEventListener(\"inactive\", cleanup);\n };\n streamCleanupHandlers.set(stream, cleanup);\n stream.addEventListener(\"ended\", cleanup);\n stream.addEventListener(\"inactive\", cleanup);\n return source;\n}\nfunction releaseMediaStreamSource(stream) {\n const cleanup = streamCleanupHandlers.get(stream);\n if (cleanup) {\n cleanup();\n }\n}\nfunction hasMediaStreamSource(stream) {\n return streamSources.has(stream);\n}\nexport {\n TonePlayout,\n ToneTrack,\n applyFadeIn,\n applyFadeOut,\n closeGlobalAudioContext,\n getGlobalAudioContext,\n getGlobalAudioContextState,\n getGlobalContext,\n getGlobalToneContext,\n getMediaStreamSource,\n hasMediaStreamSource,\n releaseMediaStreamSource,\n resumeGlobalAudioContext\n};\n//# sourceMappingURL=index.mjs.map","import { useMemo, useLayoutEffect, useEffect, useRef, useCallback } from 'react';\n\nfunction useCombinedRefs() {\n for (var _len = arguments.length, refs = new Array(_len), _key = 0; _key < _len; _key++) {\n refs[_key] = arguments[_key];\n }\n\n return useMemo(() => node => {\n refs.forEach(ref => ref(node));\n }, // eslint-disable-next-line react-hooks/exhaustive-deps\n refs);\n}\n\n// https://github.com/facebook/react/blob/master/packages/shared/ExecutionEnvironment.js\nconst canUseDOM = typeof window !== 'undefined' && typeof window.document !== 'undefined' && typeof window.document.createElement !== 'undefined';\n\nfunction isWindow(element) {\n const elementString = Object.prototype.toString.call(element);\n return elementString === '[object Window]' || // In Electron context the Window object serializes to [object global]\n elementString === '[object global]';\n}\n\nfunction isNode(node) {\n return 'nodeType' in node;\n}\n\nfunction getWindow(target) {\n var _target$ownerDocument, _target$ownerDocument2;\n\n if (!target) {\n return window;\n }\n\n if (isWindow(target)) {\n return target;\n }\n\n if (!isNode(target)) {\n return window;\n }\n\n return (_target$ownerDocument = (_target$ownerDocument2 = target.ownerDocument) == null ? void 0 : _target$ownerDocument2.defaultView) != null ? _target$ownerDocument : window;\n}\n\nfunction isDocument(node) {\n const {\n Document\n } = getWindow(node);\n return node instanceof Document;\n}\n\nfunction isHTMLElement(node) {\n if (isWindow(node)) {\n return false;\n }\n\n return node instanceof getWindow(node).HTMLElement;\n}\n\nfunction isSVGElement(node) {\n return node instanceof getWindow(node).SVGElement;\n}\n\nfunction getOwnerDocument(target) {\n if (!target) {\n return document;\n }\n\n if (isWindow(target)) {\n return target.document;\n }\n\n if (!isNode(target)) {\n return document;\n }\n\n if (isDocument(target)) {\n return target;\n }\n\n if (isHTMLElement(target) || isSVGElement(target)) {\n return target.ownerDocument;\n }\n\n return document;\n}\n\n/**\r\n * A hook that resolves to useEffect on the server and useLayoutEffect on the client\r\n * @param callback {function} Callback function that is invoked when the dependencies of the hook change\r\n */\n\nconst useIsomorphicLayoutEffect = canUseDOM ? useLayoutEffect : useEffect;\n\nfunction useEvent(handler) {\n const handlerRef = useRef(handler);\n useIsomorphicLayoutEffect(() => {\n handlerRef.current = handler;\n });\n return useCallback(function () {\n for (var _len = arguments.length, args = new Array(_len), _key = 0; _key < _len; _key++) {\n args[_key] = arguments[_key];\n }\n\n return handlerRef.current == null ? void 0 : handlerRef.current(...args);\n }, []);\n}\n\nfunction useInterval() {\n const intervalRef = useRef(null);\n const set = useCallback((listener, duration) => {\n intervalRef.current = setInterval(listener, duration);\n }, []);\n const clear = useCallback(() => {\n if (intervalRef.current !== null) {\n clearInterval(intervalRef.current);\n intervalRef.current = null;\n }\n }, []);\n return [set, clear];\n}\n\nfunction useLatestValue(value, dependencies) {\n if (dependencies === void 0) {\n dependencies = [value];\n }\n\n const valueRef = useRef(value);\n useIsomorphicLayoutEffect(() => {\n if (valueRef.current !== value) {\n valueRef.current = value;\n }\n }, dependencies);\n return valueRef;\n}\n\nfunction useLazyMemo(callback, dependencies) {\n const valueRef = useRef();\n return useMemo(() => {\n const newValue = callback(valueRef.current);\n valueRef.current = newValue;\n return newValue;\n }, // eslint-disable-next-line react-hooks/exhaustive-deps\n [...dependencies]);\n}\n\nfunction useNodeRef(onChange) {\n const onChangeHandler = useEvent(onChange);\n const node = useRef(null);\n const setNodeRef = useCallback(element => {\n if (element !== node.current) {\n onChangeHandler == null ? void 0 : onChangeHandler(element, node.current);\n }\n\n node.current = element;\n }, //eslint-disable-next-line\n []);\n return [node, setNodeRef];\n}\n\nfunction usePrevious(value) {\n const ref = useRef();\n useEffect(() => {\n ref.current = value;\n }, [value]);\n return ref.current;\n}\n\nlet ids = {};\nfunction useUniqueId(prefix, value) {\n return useMemo(() => {\n if (value) {\n return value;\n }\n\n const id = ids[prefix] == null ? 0 : ids[prefix] + 1;\n ids[prefix] = id;\n return prefix + \"-\" + id;\n }, [prefix, value]);\n}\n\nfunction createAdjustmentFn(modifier) {\n return function (object) {\n for (var _len = arguments.length, adjustments = new Array(_len > 1 ? _len - 1 : 0), _key = 1; _key < _len; _key++) {\n adjustments[_key - 1] = arguments[_key];\n }\n\n return adjustments.reduce((accumulator, adjustment) => {\n const entries = Object.entries(adjustment);\n\n for (const [key, valueAdjustment] of entries) {\n const value = accumulator[key];\n\n if (value != null) {\n accumulator[key] = value + modifier * valueAdjustment;\n }\n }\n\n return accumulator;\n }, { ...object\n });\n };\n}\n\nconst add = /*#__PURE__*/createAdjustmentFn(1);\nconst subtract = /*#__PURE__*/createAdjustmentFn(-1);\n\nfunction hasViewportRelativeCoordinates(event) {\n return 'clientX' in event && 'clientY' in event;\n}\n\nfunction isKeyboardEvent(event) {\n if (!event) {\n return false;\n }\n\n const {\n KeyboardEvent\n } = getWindow(event.target);\n return KeyboardEvent && event instanceof KeyboardEvent;\n}\n\nfunction isTouchEvent(event) {\n if (!event) {\n return false;\n }\n\n const {\n TouchEvent\n } = getWindow(event.target);\n return TouchEvent && event instanceof TouchEvent;\n}\n\n/**\r\n * Returns the normalized x and y coordinates for mouse and touch events.\r\n */\n\nfunction getEventCoordinates(event) {\n if (isTouchEvent(event)) {\n if (event.touches && event.touches.length) {\n const {\n clientX: x,\n clientY: y\n } = event.touches[0];\n return {\n x,\n y\n };\n } else if (event.changedTouches && event.changedTouches.length) {\n const {\n clientX: x,\n clientY: y\n } = event.changedTouches[0];\n return {\n x,\n y\n };\n }\n }\n\n if (hasViewportRelativeCoordinates(event)) {\n return {\n x: event.clientX,\n y: event.clientY\n };\n }\n\n return null;\n}\n\nconst CSS = /*#__PURE__*/Object.freeze({\n Translate: {\n toString(transform) {\n if (!transform) {\n return;\n }\n\n const {\n x,\n y\n } = transform;\n return \"translate3d(\" + (x ? Math.round(x) : 0) + \"px, \" + (y ? Math.round(y) : 0) + \"px, 0)\";\n }\n\n },\n Scale: {\n toString(transform) {\n if (!transform) {\n return;\n }\n\n const {\n scaleX,\n scaleY\n } = transform;\n return \"scaleX(\" + scaleX + \") scaleY(\" + scaleY + \")\";\n }\n\n },\n Transform: {\n toString(transform) {\n if (!transform) {\n return;\n }\n\n return [CSS.Translate.toString(transform), CSS.Scale.toString(transform)].join(' ');\n }\n\n },\n Transition: {\n toString(_ref) {\n let {\n property,\n duration,\n easing\n } = _ref;\n return property + \" \" + duration + \"ms \" + easing;\n }\n\n }\n});\n\nconst SELECTOR = 'a,frame,iframe,input:not([type=hidden]):not(:disabled),select:not(:disabled),textarea:not(:disabled),button:not(:disabled),*[tabindex]';\nfunction findFirstFocusableNode(element) {\n if (element.matches(SELECTOR)) {\n return element;\n }\n\n return element.querySelector(SELECTOR);\n}\n\nexport { CSS, add, canUseDOM, findFirstFocusableNode, getEventCoordinates, getOwnerDocument, getWindow, hasViewportRelativeCoordinates, isDocument, isHTMLElement, isKeyboardEvent, isNode, isSVGElement, isTouchEvent, isWindow, subtract, useCombinedRefs, useEvent, useInterval, useIsomorphicLayoutEffect, useLatestValue, useLazyMemo, useNodeRef, usePrevious, useUniqueId };\n//# sourceMappingURL=utilities.esm.js.map\n","import * as a from \"react\";\nconst e = /* @__PURE__ */ new Map([\n [\n \"bold\",\n /* @__PURE__ */ a.createElement(a.Fragment, null, /* @__PURE__ */ a.createElement(\"path\", { d: \"M157.27,21.22a12,12,0,0,0-12.64,1.31L75.88,76H32A20,20,0,0,0,12,96v64a20,20,0,0,0,20,20H75.88l68.75,53.47A12,12,0,0,0,164,224V32A12,12,0,0,0,157.27,21.22ZM36,100H68v56H36Zm104,99.46L92,162.13V93.87l48-37.33ZM212,128a44,44,0,0,1-11,29.11,12,12,0,1,1-18-15.88,20,20,0,0,0,0-26.43,12,12,0,0,1,18-15.86A43.94,43.94,0,0,1,212,128Zm40,0a83.87,83.87,0,0,1-21.39,56,12,12,0,0,1-17.89-16,60,60,0,0,0,0-80,12,12,0,1,1,17.88-16A83.87,83.87,0,0,1,252,128Z\" }))\n ],\n [\n \"duotone\",\n /* @__PURE__ */ a.createElement(a.Fragment, null, /* @__PURE__ */ a.createElement(\"path\", { d: \"M80,88v80H32a8,8,0,0,1-8-8V96a8,8,0,0,1,8-8Z\", opacity: \"0.2\" }), /* @__PURE__ */ a.createElement(\"path\", { d: \"M155.51,24.81a8,8,0,0,0-8.42.88L77.25,80H32A16,16,0,0,0,16,96v64a16,16,0,0,0,16,16H77.25l69.84,54.31A8,8,0,0,0,160,224V32A8,8,0,0,0,155.51,24.81ZM32,96H72v64H32ZM144,207.64,88,164.09V91.91l56-43.55Zm54-106.08a40,40,0,0,1,0,52.88,8,8,0,0,1-12-10.58,24,24,0,0,0,0-31.72,8,8,0,0,1,12-10.58ZM248,128a79.9,79.9,0,0,1-20.37,53.34,8,8,0,0,1-11.92-10.67,64,64,0,0,0,0-85.33,8,8,0,1,1,11.92-10.67A79.83,79.83,0,0,1,248,128Z\" }))\n ],\n [\n \"fill\",\n /* @__PURE__ */ a.createElement(a.Fragment, null, /* @__PURE__ */ a.createElement(\"path\", { d: \"M160,32.25V223.69a8.29,8.29,0,0,1-3.91,7.18,8,8,0,0,1-9-.56l-65.57-51A4,4,0,0,1,80,176.16V79.84a4,4,0,0,1,1.55-3.15l65.57-51a8,8,0,0,1,10,.16A8.27,8.27,0,0,1,160,32.25ZM60,80H32A16,16,0,0,0,16,96v64a16,16,0,0,0,16,16H60a4,4,0,0,0,4-4V84A4,4,0,0,0,60,80Zm126.77,20.84a8,8,0,0,0-.72,11.3,24,24,0,0,1,0,31.72,8,8,0,1,0,12,10.58,40,40,0,0,0,0-52.88A8,8,0,0,0,186.74,100.84Zm40.89-26.17a8,8,0,1,0-11.92,10.66,64,64,0,0,1,0,85.34,8,8,0,1,0,11.92,10.66,80,80,0,0,0,0-106.66Z\" }))\n ],\n [\n \"light\",\n /* @__PURE__ */ a.createElement(a.Fragment, null, /* @__PURE__ */ a.createElement(\"path\", { d: \"M154.64,26.61a6,6,0,0,0-6.32.65L77.94,82H32A14,14,0,0,0,18,96v64a14,14,0,0,0,14,14H77.94l70.38,54.74A6,6,0,0,0,158,224V32A6,6,0,0,0,154.64,26.61ZM30,160V96a2,2,0,0,1,2-2H74v68H32A2,2,0,0,1,30,160Zm116,51.73L86,165.07V90.93l60-46.66Zm50.53-108.85a38,38,0,0,1,0,50.24,6,6,0,1,1-9-7.94,26,26,0,0,0,0-34.37,6,6,0,0,1,9-7.93ZM246,128a77.86,77.86,0,0,1-19.86,52,6,6,0,1,1-8.94-8,66,66,0,0,0,0-88,6,6,0,1,1,8.94-8A77.86,77.86,0,0,1,246,128Z\" }))\n ],\n [\n \"regular\",\n /* @__PURE__ */ a.createElement(a.Fragment, null, /* @__PURE__ */ a.createElement(\"path\", { d: \"M155.51,24.81a8,8,0,0,0-8.42.88L77.25,80H32A16,16,0,0,0,16,96v64a16,16,0,0,0,16,16H77.25l69.84,54.31A8,8,0,0,0,160,224V32A8,8,0,0,0,155.51,24.81ZM32,96H72v64H32ZM144,207.64,88,164.09V91.91l56-43.55Zm54-106.08a40,40,0,0,1,0,52.88,8,8,0,0,1-12-10.58,24,24,0,0,0,0-31.72,8,8,0,0,1,12-10.58ZM248,128a79.9,79.9,0,0,1-20.37,53.34,8,8,0,0,1-11.92-10.67,64,64,0,0,0,0-85.33,8,8,0,1,1,11.92-10.67A79.83,79.83,0,0,1,248,128Z\" }))\n ],\n [\n \"thin\",\n /* @__PURE__ */ a.createElement(a.Fragment, null, /* @__PURE__ */ a.createElement(\"path\", { d: \"M153.76,28.41a4,4,0,0,0-4.22.43L78.63,84H32A12,12,0,0,0,20,96v64a12,12,0,0,0,12,12H78.63l70.91,55.16A4.07,4.07,0,0,0,152,228a3.92,3.92,0,0,0,1.76-.41A4,4,0,0,0,156,224V32A4,4,0,0,0,153.76,28.41ZM28,160V96a4,4,0,0,1,4-4H76v72H32A4,4,0,0,1,28,160Zm120,55.82L84,166V90l64-49.78Zm47-111.61a36,36,0,0,1,0,47.59,4,4,0,1,1-6-5.3,28,28,0,0,0,0-37,4,4,0,0,1,6-5.28ZM244,128a75.88,75.88,0,0,1-19.35,50.67,4,4,0,0,1-6-5.34,68,68,0,0,0,0-90.66,4,4,0,0,1,6-5.34A75.88,75.88,0,0,1,244,128Z\" }))\n ]\n]);\nexport {\n e as default\n};\n","import * as e from \"react\";\nconst a = /* @__PURE__ */ new Map([\n [\n \"bold\",\n /* @__PURE__ */ e.createElement(e.Fragment, null, /* @__PURE__ */ e.createElement(\"path\", { d: \"M157.27,21.22a12,12,0,0,0-12.64,1.31L75.88,76H32A20,20,0,0,0,12,96v64a20,20,0,0,0,20,20H75.88l68.75,53.47A12,12,0,0,0,164,224V32A12,12,0,0,0,157.27,21.22ZM36,100H68v56H36Zm104,99.46L92,162.13V93.87l48-37.33ZM212,128a44,44,0,0,1-11,29.11,12,12,0,0,1-18-15.88,20,20,0,0,0,0-26.44,12,12,0,0,1,18-15.85A43.94,43.94,0,0,1,212,128Z\" }))\n ],\n [\n \"duotone\",\n /* @__PURE__ */ e.createElement(e.Fragment, null, /* @__PURE__ */ e.createElement(\"path\", { d: \"M80,88v80H32a8,8,0,0,1-8-8V96a8,8,0,0,1,8-8Z\", opacity: \"0.2\" }), /* @__PURE__ */ e.createElement(\"path\", { d: \"M155.51,24.81a8,8,0,0,0-8.42.88L77.25,80H32A16,16,0,0,0,16,96v64a16,16,0,0,0,16,16H77.25l69.84,54.31A8,8,0,0,0,160,224V32A8,8,0,0,0,155.51,24.81ZM32,96H72v64H32ZM144,207.64,88,164.09V91.91l56-43.55ZM208,128a39.93,39.93,0,0,1-10,26.46,8,8,0,0,1-12-10.58,24,24,0,0,0,0-31.72,8,8,0,1,1,12-10.58A40,40,0,0,1,208,128Z\" }))\n ],\n [\n \"fill\",\n /* @__PURE__ */ e.createElement(e.Fragment, null, /* @__PURE__ */ e.createElement(\"path\", { d: \"M160,32.25V223.69a8.29,8.29,0,0,1-3.91,7.18,8,8,0,0,1-9-.56l-65.57-51A4,4,0,0,1,80,176.16V79.84a4,4,0,0,1,1.55-3.15l65.57-51a8,8,0,0,1,10,.16A8.27,8.27,0,0,1,160,32.25ZM60,80H32A16,16,0,0,0,16,96v64a16,16,0,0,0,16,16H60a4,4,0,0,0,4-4V84A4,4,0,0,0,60,80ZM198,101.56a8,8,0,1,0-12,10.58,24,24,0,0,1,0,31.72,8,8,0,1,0,12,10.58,40,40,0,0,0,0-52.88Z\" }))\n ],\n [\n \"light\",\n /* @__PURE__ */ e.createElement(e.Fragment, null, /* @__PURE__ */ e.createElement(\"path\", { d: \"M154.64,26.61a6,6,0,0,0-6.32.65L77.94,82H32A14,14,0,0,0,18,96v64a14,14,0,0,0,14,14H77.94l70.38,54.74A6,6,0,0,0,158,224V32A6,6,0,0,0,154.64,26.61ZM30,160V96a2,2,0,0,1,2-2H74v68H32A2,2,0,0,1,30,160Zm116,51.73L86,165.07V90.93l60-46.66ZM206,128a37.94,37.94,0,0,1-9.5,25.14,6,6,0,1,1-9-7.94,26,26,0,0,0,0-34.37,6,6,0,0,1,9-7.93A38,38,0,0,1,206,128Z\" }))\n ],\n [\n \"regular\",\n /* @__PURE__ */ e.createElement(e.Fragment, null, /* @__PURE__ */ e.createElement(\"path\", { d: \"M155.51,24.81a8,8,0,0,0-8.42.88L77.25,80H32A16,16,0,0,0,16,96v64a16,16,0,0,0,16,16H77.25l69.84,54.31A8,8,0,0,0,160,224V32A8,8,0,0,0,155.51,24.81ZM32,96H72v64H32ZM144,207.64,88,164.09V91.91l56-43.55ZM208,128a39.93,39.93,0,0,1-10,26.46,8,8,0,0,1-12-10.58,24,24,0,0,0,0-31.72,8,8,0,1,1,12-10.58A40,40,0,0,1,208,128Z\" }))\n ],\n [\n \"thin\",\n /* @__PURE__ */ e.createElement(e.Fragment, null, /* @__PURE__ */ e.createElement(\"path\", { d: \"M153.76,28.41a4,4,0,0,0-4.22.43L78.63,84H32A12,12,0,0,0,20,96v64a12,12,0,0,0,12,12H78.63l70.91,55.16A4.07,4.07,0,0,0,152,228a3.92,3.92,0,0,0,1.76-.41A4,4,0,0,0,156,224V32A4,4,0,0,0,153.76,28.41ZM28,160V96a4,4,0,0,1,4-4H76v72H32A4,4,0,0,1,28,160Zm120,55.82L84,166V90l64-49.78ZM204,128a36,36,0,0,1-9,23.82,4,4,0,1,1-6-5.3,28,28,0,0,0,0-37,4,4,0,0,1,6-5.28A36,36,0,0,1,204,128Z\" }))\n ]\n]);\nexport {\n a as default\n};\n","import { createContext as r } from \"react\";\nconst o = r({\n color: \"currentColor\",\n size: \"1em\",\n weight: \"regular\",\n mirrored: !1\n});\nexport {\n o as IconContext\n};\n","import * as e from \"react\";\nimport { IconContext as h } from \"./context.es.js\";\nconst p = e.forwardRef(\n (s, a) => {\n const {\n alt: n,\n color: r,\n size: t,\n weight: o,\n mirrored: c,\n children: i,\n weights: m,\n ...x\n } = s, {\n color: d = \"currentColor\",\n size: l,\n weight: f = \"regular\",\n mirrored: g = !1,\n ...w\n } = e.useContext(h);\n return /* @__PURE__ */ e.createElement(\n \"svg\",\n {\n ref: a,\n xmlns: \"http://www.w3.org/2000/svg\",\n width: t != null ? t : l,\n height: t != null ? t : l,\n fill: r != null ? r : d,\n viewBox: \"0 0 256 256\",\n transform: c || g ? \"scale(-1, 1)\" : void 0,\n ...w,\n ...x\n },\n !!n && /* @__PURE__ */ e.createElement(\"title\", null, n),\n i,\n m.get(o != null ? o : f)\n );\n }\n);\np.displayName = \"IconBase\";\nexport {\n p as default\n};\n","import * as e from \"react\";\nimport t from \"../lib/IconBase.es.js\";\nimport i from \"../defs/SpeakerHigh.es.js\";\nconst o = e.forwardRef((r, a) => /* @__PURE__ */ e.createElement(t, { ref: a, ...r, weights: i }));\no.displayName = \"SpeakerHighIcon\";\nconst c = o;\nexport {\n c as SpeakerHigh,\n o as SpeakerHighIcon\n};\n","import * as e from \"react\";\nimport t from \"../lib/IconBase.es.js\";\nimport m from \"../defs/SpeakerLow.es.js\";\nconst o = e.forwardRef((r, a) => /* @__PURE__ */ e.createElement(t, { ref: a, ...r, weights: m }));\no.displayName = \"SpeakerLowIcon\";\nconst s = o;\nexport {\n s as SpeakerLow,\n o as SpeakerLowIcon\n};\n","// src/components/AudioPosition.tsx\nimport styled from \"styled-components\";\nimport { jsx } from \"react/jsx-runtime\";\nvar PositionDisplay = styled.span`\n font-family: 'Courier New', Monaco, monospace;\n font-size: 1rem;\n font-weight: 600;\n color: ${(props) => props.theme?.textColor || \"#333\"};\n user-select: none;\n`;\nvar AudioPosition = ({\n formattedTime,\n className\n}) => {\n return /* @__PURE__ */ jsx(PositionDisplay, { className, \"aria-label\": \"Audio position\", children: formattedTime });\n};\n\n// src/styled/BaseButton.tsx\nimport styled2 from \"styled-components\";\nvar BaseButton = styled2.button`\n display: inline-flex;\n align-items: center;\n justify-content: center;\n padding: 0.5rem 1rem;\n font-family: ${(props) => props.theme.fontFamily};\n font-size: ${(props) => props.theme.fontSize};\n font-weight: 500;\n color: ${(props) => props.theme.buttonText};\n background-color: ${(props) => props.theme.buttonBackground};\n border: 1px solid ${(props) => props.theme.buttonBorder};\n border-radius: ${(props) => props.theme.borderRadius};\n cursor: pointer;\n outline: none;\n transition: background-color 0.15s ease-in-out, border-color 0.15s ease-in-out,\n box-shadow 0.15s ease-in-out;\n\n &:hover:not(:disabled) {\n background-color: ${(props) => props.theme.buttonHoverBackground};\n }\n\n &:focus {\n box-shadow: 0 0 0 2px ${(props) => props.theme.inputFocusBorder}33;\n }\n\n &:disabled {\n opacity: 0.6;\n cursor: not-allowed;\n }\n`;\nvar BaseButtonSmall = styled2(BaseButton)`\n padding: 0.25rem 0.5rem;\n font-size: ${(props) => props.theme.fontSizeSmall};\n`;\nvar IconButton = styled2(BaseButton)`\n padding: 0.5rem;\n min-width: 2.25rem;\n min-height: 2.25rem;\n`;\nvar IconButtonSmall = styled2(BaseButton)`\n padding: 0.25rem;\n min-width: 1.75rem;\n min-height: 1.75rem;\n font-size: ${(props) => props.theme.fontSizeSmall};\n`;\n\n// src/styled/BaseCheckbox.tsx\nimport styled3 from \"styled-components\";\nvar BaseCheckboxWrapper = styled3.div`\n display: inline-flex;\n align-items: center;\n gap: 0.5rem;\n`;\nvar BaseCheckbox = styled3.input`\n cursor: pointer;\n accent-color: ${(props) => props.theme.inputFocusBorder};\n\n &:disabled {\n cursor: not-allowed;\n }\n`;\nvar BaseCheckboxLabel = styled3.label`\n margin: 0;\n cursor: pointer;\n user-select: none;\n font-family: ${(props) => props.theme.fontFamily};\n font-size: ${(props) => props.theme.fontSize};\n color: ${(props) => props.theme.textColor};\n`;\n\n// src/styled/BaseControlButton.tsx\nimport styled4 from \"styled-components\";\nvar BaseControlButton = styled4.button`\n padding: 0.5rem 1rem;\n background: ${(props) => props.theme.buttonBackground || \"#007bff\"};\n color: ${(props) => props.theme.buttonText || \"white\"};\n border: none;\n border-radius: ${(props) => props.theme.borderRadius};\n cursor: pointer;\n font-family: ${(props) => props.theme.fontFamily};\n font-size: ${(props) => props.theme.fontSize};\n font-weight: 500;\n transition: background-color 0.15s ease-in-out;\n\n &:hover:not(:disabled) {\n background: ${(props) => props.theme.buttonHoverBackground || \"#0056b3\"};\n }\n\n &:focus {\n outline: none;\n box-shadow: 0 0 0 2px ${(props) => props.theme.buttonBackground || \"#007bff\"}66;\n }\n\n &:disabled {\n background: #6c757d;\n cursor: not-allowed;\n opacity: 0.6;\n }\n`;\n\n// src/styled/BaseInput.tsx\nimport styled5 from \"styled-components\";\nvar BaseInput = styled5.input`\n padding: 0.5rem 0.75rem;\n font-family: ${(props) => props.theme.fontFamily};\n font-size: ${(props) => props.theme.fontSize};\n color: ${(props) => props.theme.inputText};\n background-color: ${(props) => props.theme.inputBackground};\n border: 1px solid ${(props) => props.theme.inputBorder};\n border-radius: ${(props) => props.theme.borderRadius};\n outline: none;\n transition: border-color 0.15s ease-in-out, box-shadow 0.15s ease-in-out;\n\n &::placeholder {\n color: ${(props) => props.theme.inputPlaceholder};\n }\n\n &:focus {\n border-color: ${(props) => props.theme.inputFocusBorder};\n box-shadow: 0 0 0 2px ${(props) => props.theme.inputFocusBorder}33;\n }\n\n &:disabled {\n opacity: 0.6;\n cursor: not-allowed;\n }\n`;\nvar BaseInputSmall = styled5(BaseInput)`\n padding: 0.25rem 0.5rem;\n font-size: ${(props) => props.theme.fontSizeSmall};\n`;\n\n// src/styled/BaseLabel.tsx\nimport styled6 from \"styled-components\";\nvar BaseLabel = styled6.label`\n font-family: ${(props) => props.theme.fontFamily};\n font-size: ${(props) => props.theme.fontSizeSmall};\n font-weight: 500;\n color: ${(props) => props.theme.textColorMuted};\n margin-bottom: 0.25rem;\n display: block;\n`;\nvar InlineLabel = styled6.label`\n font-family: ${(props) => props.theme.fontFamily};\n font-size: ${(props) => props.theme.fontSize};\n color: ${(props) => props.theme.textColor};\n display: inline-flex;\n align-items: center;\n gap: 0.5rem;\n cursor: pointer;\n`;\nvar ScreenReaderOnly = styled6.span`\n position: absolute;\n width: 1px;\n height: 1px;\n padding: 0;\n margin: -1px;\n overflow: hidden;\n clip: rect(0, 0, 0, 0);\n white-space: nowrap;\n border: 0;\n`;\n\n// src/styled/BaseSelect.tsx\nimport styled7 from \"styled-components\";\nvar BaseSelect = styled7.select`\n padding: 0.5rem 2rem 0.5rem 0.75rem;\n font-family: ${(props) => props.theme.fontFamily};\n font-size: ${(props) => props.theme.fontSize};\n color: ${(props) => props.theme.inputText};\n background-color: ${(props) => props.theme.inputBackground};\n border: 1px solid ${(props) => props.theme.inputBorder};\n border-radius: ${(props) => props.theme.borderRadius};\n outline: none;\n cursor: pointer;\n appearance: none;\n background-image: url(\"data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='12' height='12' viewBox='0 0 12 12'%3E%3Cpath fill='%23666' d='M6 8L1 3h10z'/%3E%3C/svg%3E\");\n background-repeat: no-repeat;\n background-position: right 0.75rem center;\n transition: border-color 0.15s ease-in-out, box-shadow 0.15s ease-in-out;\n\n &:focus {\n border-color: ${(props) => props.theme.inputFocusBorder};\n box-shadow: 0 0 0 2px ${(props) => props.theme.inputFocusBorder}33;\n }\n\n &:disabled {\n opacity: 0.6;\n cursor: not-allowed;\n }\n\n /* Style native option elements for dark mode support */\n option {\n color: ${(props) => props.theme.inputText};\n background-color: ${(props) => props.theme.inputBackground};\n }\n`;\nvar BaseSelectSmall = styled7(BaseSelect)`\n padding: 0.25rem 1.75rem 0.25rem 0.5rem;\n font-size: ${(props) => props.theme.fontSizeSmall};\n`;\n\n// src/styled/BaseSlider.tsx\nimport styled8 from \"styled-components\";\nvar BaseSlider = styled8.input.attrs({ type: \"range\" })`\n -webkit-appearance: none;\n appearance: none;\n width: 100%;\n height: 6px;\n background: ${(props) => props.theme.sliderTrackColor};\n border-radius: 3px;\n cursor: pointer;\n outline: none;\n\n /* WebKit (Chrome, Safari) */\n &::-webkit-slider-thumb {\n -webkit-appearance: none;\n appearance: none;\n width: 16px;\n height: 16px;\n background: ${(props) => props.theme.sliderThumbColor};\n border: 2px solid ${(props) => props.theme.inputBackground};\n border-radius: 50%;\n cursor: pointer;\n box-shadow: 0 1px 3px rgba(0, 0, 0, 0.2);\n transition: transform 0.15s ease, box-shadow 0.15s ease;\n }\n\n &::-webkit-slider-thumb:hover {\n transform: scale(1.1);\n box-shadow: 0 2px 4px rgba(0, 0, 0, 0.3);\n }\n\n /* Firefox */\n &::-moz-range-thumb {\n width: 16px;\n height: 16px;\n background: ${(props) => props.theme.sliderThumbColor};\n border: 2px solid ${(props) => props.theme.inputBackground};\n border-radius: 50%;\n cursor: pointer;\n box-shadow: 0 1px 3px rgba(0, 0, 0, 0.2);\n transition: transform 0.15s ease, box-shadow 0.15s ease;\n }\n\n &::-moz-range-thumb:hover {\n transform: scale(1.1);\n box-shadow: 0 2px 4px rgba(0, 0, 0, 0.3);\n }\n\n &::-moz-range-track {\n background: ${(props) => props.theme.sliderTrackColor};\n border-radius: 3px;\n height: 6px;\n }\n\n &:focus {\n outline: none;\n }\n\n &:focus::-webkit-slider-thumb {\n box-shadow: 0 0 0 3px ${(props) => props.theme.inputFocusBorder}33;\n }\n\n &:focus::-moz-range-thumb {\n box-shadow: 0 0 0 3px ${(props) => props.theme.inputFocusBorder}33;\n }\n\n &:disabled {\n cursor: not-allowed;\n opacity: 0.5;\n }\n\n &:disabled::-webkit-slider-thumb {\n cursor: not-allowed;\n }\n\n &:disabled::-moz-range-thumb {\n cursor: not-allowed;\n }\n`;\n\n// src/components/AutomaticScrollCheckbox.tsx\nimport { jsx as jsx2, jsxs } from \"react/jsx-runtime\";\nvar AutomaticScrollCheckbox = ({\n checked,\n onChange,\n disabled = false,\n className\n}) => {\n const handleChange = (e) => {\n onChange(e.target.checked);\n };\n return /* @__PURE__ */ jsxs(BaseCheckboxWrapper, { className, children: [\n /* @__PURE__ */ jsx2(\n BaseCheckbox,\n {\n type: \"checkbox\",\n id: \"automatic-scroll\",\n className: \"automatic-scroll\",\n checked,\n onChange: handleChange,\n disabled\n }\n ),\n /* @__PURE__ */ jsx2(BaseCheckboxLabel, { htmlFor: \"automatic-scroll\", children: \"Automatic Scroll\" })\n ] });\n};\n\n// src/components/Channel.tsx\nimport { useLayoutEffect, useCallback, useRef } from \"react\";\nimport styled9 from \"styled-components\";\n\n// src/wfpl-theme.ts\nfunction isWaveformGradient(color) {\n return typeof color === \"object\" && color !== null && \"type\" in color;\n}\nfunction waveformColorToCss(color) {\n if (!isWaveformGradient(color)) {\n return color;\n }\n const direction = color.direction === \"vertical\" ? \"to bottom\" : \"to right\";\n const stops = color.stops.map((stop) => `${stop.color} ${stop.offset * 100}%`).join(\", \");\n return `linear-gradient(${direction}, ${stops})`;\n}\nvar defaultTheme = {\n waveformDrawMode: \"inverted\",\n waveOutlineColor: \"#ffffff\",\n waveFillColor: \"#1a7f8e\",\n // White background for crisp look\n waveProgressColor: \"rgba(0, 0, 0, 0.10)\",\n // Subtle dark overlay for light mode\n selectedWaveOutlineColor: \"#ffffff\",\n selectedWaveFillColor: \"#00b4d8\",\n // Selected: brighter cyan\n selectedTrackControlsBackground: \"#d9e9ff\",\n // Light blue background for selected track controls\n timeColor: \"#000\",\n timescaleBackgroundColor: \"#fff\",\n playheadColor: \"#f00\",\n selectionColor: \"rgba(255, 105, 180, 0.7)\",\n // hot pink - high contrast on light backgrounds\n loopRegionColor: \"rgba(59, 130, 246, 0.3)\",\n // Blue - distinct from pink selection\n loopMarkerColor: \"#3b82f6\",\n // Blue marker triangles\n clipHeaderBackgroundColor: \"rgba(0, 0, 0, 0.1)\",\n clipHeaderBorderColor: \"rgba(0, 0, 0, 0.2)\",\n clipHeaderTextColor: \"#333\",\n clipHeaderFontFamily: \"inherit\",\n selectedClipHeaderBackgroundColor: \"#b3d9ff\",\n // Brighter blue for selected track clip headers\n // Fade overlay colors\n fadeOverlayColor: \"rgba(0, 0, 0, 0.4)\",\n // Semi-transparent overlay for fade regions\n // UI component colors\n backgroundColor: \"#ffffff\",\n surfaceColor: \"#f5f5f5\",\n borderColor: \"#ddd\",\n textColor: \"#333\",\n textColorMuted: \"#666\",\n // Interactive element colors\n inputBackground: \"#ffffff\",\n inputBorder: \"#ccc\",\n inputText: \"#333\",\n inputPlaceholder: \"#999\",\n inputFocusBorder: \"#0066cc\",\n // Button colors - blue to match common UI patterns\n buttonBackground: \"#0091ff\",\n buttonText: \"#ffffff\",\n buttonBorder: \"#0081e6\",\n buttonHoverBackground: \"#0081e6\",\n // Slider colors\n sliderTrackColor: \"#ddd\",\n sliderThumbColor: \"#daa520\",\n // goldenrod\n // Annotation colors\n annotationBoxBackground: \"rgba(255, 255, 255, 0.85)\",\n annotationBoxActiveBackground: \"rgba(255, 255, 255, 0.95)\",\n annotationBoxHoverBackground: \"rgba(255, 255, 255, 0.98)\",\n annotationBoxBorder: \"#ff9800\",\n annotationBoxActiveBorder: \"#d67600\",\n annotationLabelColor: \"#2a2a2a\",\n annotationResizeHandleColor: \"rgba(0, 0, 0, 0.4)\",\n annotationResizeHandleActiveColor: \"rgba(0, 0, 0, 0.8)\",\n annotationTextItemHoverBackground: \"rgba(0, 0, 0, 0.03)\",\n // Spacing and sizing\n borderRadius: \"4px\",\n fontFamily: '-apple-system, BlinkMacSystemFont, \"Segoe UI\", Roboto, Oxygen, Ubuntu, sans-serif',\n fontSize: \"14px\",\n fontSizeSmall: \"12px\"\n};\nvar darkTheme = {\n // Normal mode: waveOutlineColor = bars, waveFillColor = background\n waveformDrawMode: \"inverted\",\n // Dark bars on warm amber background\n waveOutlineColor: \"#c49a6c\",\n // Solid warm amber for background\n waveFillColor: \"#1a1612\",\n // Very dark warm brown for bars\n waveProgressColor: \"rgba(100, 70, 40, 0.6)\",\n // Warm brown progress overlay\n // Selected: slightly lighter bars on brighter amber background\n selectedWaveFillColor: \"#241c14\",\n // Slightly lighter warm brown bars when selected\n selectedWaveOutlineColor: \"#e8c090\",\n // Brighter amber background when selected\n selectedTrackControlsBackground: \"#2a2218\",\n // Dark warm brown for selected track controls\n timeColor: \"#d8c0a8\",\n // Warm amber for timescale text\n timescaleBackgroundColor: \"#1a1612\",\n // Dark warm brown background\n playheadColor: \"#3a8838\",\n // Darker Ampelmännchen green playhead\n selectionColor: \"rgba(60, 140, 58, 0.6)\",\n // Darker Ampelmännchen green selection - visible on dark backgrounds\n loopRegionColor: \"rgba(96, 165, 250, 0.35)\",\n // Light blue - distinct from green selection\n loopMarkerColor: \"#60a5fa\",\n // Light blue marker triangles\n clipHeaderBackgroundColor: \"rgba(20, 16, 12, 0.85)\",\n // Dark background for clip headers\n clipHeaderBorderColor: \"rgba(200, 160, 120, 0.25)\",\n clipHeaderTextColor: \"#d8c0a8\",\n // Warm amber text\n clipHeaderFontFamily: \"inherit\",\n selectedClipHeaderBackgroundColor: \"#3a2c20\",\n // Darker warm brown for selected clip headers\n // Fade overlay colors\n fadeOverlayColor: \"rgba(200, 100, 80, 0.5)\",\n // Warm red-orange overlay visible on dark backgrounds\n // UI component colors\n backgroundColor: \"#1e1e1e\",\n surfaceColor: \"#2d2d2d\",\n borderColor: \"#444\",\n textColor: \"#e0e0e0\",\n textColorMuted: \"#999\",\n // Interactive element colors\n inputBackground: \"#2d2d2d\",\n inputBorder: \"#555\",\n inputText: \"#e0e0e0\",\n inputPlaceholder: \"#777\",\n inputFocusBorder: \"#4A9EFF\",\n // Button colors - Ampelmännchen green (#63C75F) with black text\n buttonBackground: \"#63C75F\",\n buttonText: \"#0a0a0f\",\n buttonBorder: \"#52b84e\",\n buttonHoverBackground: \"#78d074\",\n // Slider colors\n sliderTrackColor: \"#555\",\n sliderThumbColor: \"#f0c040\",\n // brighter goldenrod for dark mode\n // Annotation colors (dark mode - warm amber theme)\n annotationBoxBackground: \"rgba(40, 32, 24, 0.9)\",\n annotationBoxActiveBackground: \"rgba(50, 40, 30, 0.95)\",\n annotationBoxHoverBackground: \"rgba(60, 48, 36, 0.98)\",\n annotationBoxBorder: \"#c49a6c\",\n annotationBoxActiveBorder: \"#d4a87c\",\n annotationLabelColor: \"#d8c0a8\",\n annotationResizeHandleColor: \"rgba(200, 160, 120, 0.5)\",\n annotationResizeHandleActiveColor: \"rgba(220, 180, 140, 0.8)\",\n annotationTextItemHoverBackground: \"rgba(200, 160, 120, 0.08)\",\n // Spacing and sizing\n borderRadius: \"4px\",\n fontFamily: '-apple-system, BlinkMacSystemFont, \"Segoe UI\", Roboto, Oxygen, Ubuntu, sans-serif',\n fontSize: \"14px\",\n fontSizeSmall: \"12px\"\n};\n\n// src/components/Channel.tsx\nimport { jsx as jsx3 } from \"react/jsx-runtime\";\nvar MAX_CANVAS_WIDTH = 1e3;\nfunction createCanvasFillStyle(ctx, color, width, height) {\n if (!isWaveformGradient(color)) {\n return color;\n }\n let gradient;\n if (color.direction === \"vertical\") {\n gradient = ctx.createLinearGradient(0, 0, 0, height);\n } else {\n gradient = ctx.createLinearGradient(0, 0, width, 0);\n }\n for (const stop of color.stops) {\n gradient.addColorStop(stop.offset, stop.color);\n }\n return gradient;\n}\nvar Waveform = styled9.canvas.attrs((props) => ({\n style: {\n width: `${props.$cssWidth}px`,\n height: `${props.$waveHeight}px`\n }\n}))`\n float: left;\n position: relative;\n /* Promote to own compositing layer for smoother scrolling */\n will-change: transform;\n /* Disable image rendering interpolation */\n image-rendering: pixelated;\n image-rendering: crisp-edges;\n`;\nvar Wrapper = styled9.div.attrs((props) => ({\n style: {\n top: `${props.$waveHeight * props.$index}px`,\n width: `${props.$cssWidth}px`,\n height: `${props.$waveHeight}px`\n }\n}))`\n position: absolute;\n background: ${(props) => props.$waveFillColor};\n /* Force GPU compositing layer to reduce scroll flickering */\n transform: translateZ(0);\n backface-visibility: hidden;\n`;\nvar Channel = (props) => {\n const {\n data,\n bits,\n length,\n index,\n className,\n devicePixelRatio = 1,\n waveHeight = 80,\n waveOutlineColor = \"#E0EFF1\",\n waveFillColor = \"grey\",\n barWidth = 1,\n barGap = 0,\n transparentBackground = false,\n drawMode = \"inverted\"\n } = props;\n const canvasesRef = useRef([]);\n const canvasRef = useCallback(\n (canvas) => {\n if (canvas !== null) {\n const index2 = parseInt(canvas.dataset.index, 10);\n canvasesRef.current[index2] = canvas;\n }\n },\n []\n );\n useLayoutEffect(() => {\n const canvases = canvasesRef.current;\n const step = barWidth + barGap;\n let globalPixelOffset = 0;\n for (let i = 0; i < canvases.length; i++) {\n const canvas = canvases[i];\n const ctx = canvas.getContext(\"2d\");\n const h2 = Math.floor(waveHeight / 2);\n const maxValue = 2 ** (bits - 1);\n if (ctx) {\n ctx.resetTransform();\n ctx.clearRect(0, 0, canvas.width, canvas.height);\n ctx.imageSmoothingEnabled = false;\n ctx.scale(devicePixelRatio, devicePixelRatio);\n const canvasWidth = canvas.width / devicePixelRatio;\n let fillColor;\n if (drawMode === \"normal\") {\n fillColor = waveFillColor;\n } else {\n fillColor = waveOutlineColor;\n }\n ctx.fillStyle = createCanvasFillStyle(\n ctx,\n fillColor,\n canvasWidth,\n waveHeight\n );\n const canvasStartGlobal = globalPixelOffset;\n const canvasEndGlobal = globalPixelOffset + canvasWidth;\n const firstBarGlobal = Math.floor((canvasStartGlobal - barWidth + step) / step) * step;\n for (let barGlobal = Math.max(0, firstBarGlobal); barGlobal < canvasEndGlobal; barGlobal += step) {\n const x = barGlobal - canvasStartGlobal;\n if (x + barWidth <= 0) continue;\n const peakIndex = barGlobal;\n if (peakIndex * 2 + 1 < data.length) {\n const minPeak = data[peakIndex * 2] / maxValue;\n const maxPeak = data[peakIndex * 2 + 1] / maxValue;\n const min = Math.abs(minPeak * h2);\n const max = Math.abs(maxPeak * h2);\n if (drawMode === \"normal\") {\n ctx.fillRect(x, h2 - max, barWidth, max + min);\n } else {\n ctx.fillRect(x, 0, barWidth, h2 - max);\n ctx.fillRect(x, h2 + min, barWidth, h2 - min);\n }\n }\n }\n }\n globalPixelOffset += canvas.width / devicePixelRatio;\n }\n }, [\n data,\n bits,\n waveHeight,\n waveOutlineColor,\n waveFillColor,\n devicePixelRatio,\n length,\n barWidth,\n barGap,\n drawMode\n ]);\n let totalWidth = length;\n let waveformCount = 0;\n const waveforms = [];\n while (totalWidth > 0) {\n const currentWidth = Math.min(totalWidth, MAX_CANVAS_WIDTH);\n const waveform = /* @__PURE__ */ jsx3(\n Waveform,\n {\n $cssWidth: currentWidth,\n width: currentWidth * devicePixelRatio,\n height: waveHeight * devicePixelRatio,\n $waveHeight: waveHeight,\n \"data-index\": waveformCount,\n ref: canvasRef\n },\n `${length}-${waveformCount}`\n );\n waveforms.push(waveform);\n totalWidth -= currentWidth;\n waveformCount += 1;\n }\n const bgColor = waveFillColor;\n const backgroundCss = transparentBackground ? \"transparent\" : waveformColorToCss(bgColor);\n return /* @__PURE__ */ jsx3(\n Wrapper,\n {\n $index: index,\n $cssWidth: length,\n className,\n $waveHeight: waveHeight,\n $waveFillColor: backgroundCss,\n children: waveforms\n }\n );\n};\n\n// src/components/Clip.tsx\nimport styled13 from \"styled-components\";\nimport { useDraggable } from \"@dnd-kit/core\";\nimport { CSS } from \"@dnd-kit/utilities\";\n\n// src/components/ClipHeader.tsx\nimport styled10 from \"styled-components\";\nimport { jsx as jsx4 } from \"react/jsx-runtime\";\nvar CLIP_HEADER_HEIGHT = 22;\nvar HeaderContainer = styled10.div`\n position: relative;\n height: ${CLIP_HEADER_HEIGHT}px;\n background: ${(props) => props.$isSelected ? props.theme.selectedClipHeaderBackgroundColor : props.theme.clipHeaderBackgroundColor};\n border-bottom: 1px solid ${(props) => props.theme.clipHeaderBorderColor};\n display: flex;\n align-items: center;\n padding: 0 8px;\n cursor: ${(props) => props.$interactive ? props.$isDragging ? \"grabbing\" : \"grab\" : \"default\"};\n user-select: none;\n z-index: 110;\n flex-shrink: 0;\n pointer-events: auto; /* Re-enable pointer events (parent ClipContainer has pointer-events: none) */\n touch-action: ${(props) => props.$interactive ? \"none\" : \"auto\"}; /* Prevent browser scroll during drag on touch devices */\n\n ${(props) => props.$interactive && `\n &:hover {\n background: ${props.theme.clipHeaderBackgroundColor}dd;\n }\n\n &:active {\n cursor: grabbing;\n }\n `}\n`;\nvar TrackName = styled10.span`\n font-size: 11px;\n font-weight: 600;\n font-family: ${(props) => props.theme.clipHeaderFontFamily};\n color: ${(props) => props.theme.clipHeaderTextColor};\n white-space: nowrap;\n overflow: hidden;\n text-overflow: ellipsis;\n`;\nvar ClipHeaderPresentational = ({\n trackName,\n isSelected = false\n}) => {\n return /* @__PURE__ */ jsx4(\n HeaderContainer,\n {\n $isDragging: false,\n $interactive: false,\n $isSelected: isSelected,\n children: /* @__PURE__ */ jsx4(TrackName, { children: trackName })\n }\n );\n};\nvar ClipHeader = ({\n clipId,\n trackIndex,\n clipIndex,\n trackName,\n isSelected = false,\n disableDrag = false,\n dragHandleProps\n}) => {\n if (disableDrag || !dragHandleProps) {\n return /* @__PURE__ */ jsx4(\n ClipHeaderPresentational,\n {\n trackName,\n isSelected\n }\n );\n }\n const { attributes, listeners, setActivatorNodeRef } = dragHandleProps;\n return /* @__PURE__ */ jsx4(\n HeaderContainer,\n {\n ref: setActivatorNodeRef,\n \"data-clip-id\": clipId,\n $interactive: true,\n $isSelected: isSelected,\n ...listeners,\n ...attributes,\n children: /* @__PURE__ */ jsx4(TrackName, { children: trackName })\n }\n );\n};\n\n// src/components/ClipBoundary.tsx\nimport React2 from \"react\";\nimport styled11 from \"styled-components\";\nimport { jsx as jsx5 } from \"react/jsx-runtime\";\nvar CLIP_BOUNDARY_WIDTH = 8;\nvar CLIP_BOUNDARY_WIDTH_TOUCH = 24;\nvar BoundaryContainer = styled11.div`\n position: absolute;\n ${(props) => props.$edge === \"left\" ? \"left: 0;\" : \"right: 0;\"}\n top: 0;\n bottom: 0;\n width: ${(props) => props.$touchOptimized ? CLIP_BOUNDARY_WIDTH_TOUCH : CLIP_BOUNDARY_WIDTH}px;\n cursor: col-resize;\n user-select: none;\n z-index: 105; /* Above waveform, below header */\n pointer-events: auto; /* Re-enable pointer events (parent ClipContainer has pointer-events: none) */\n touch-action: none; /* Prevent browser scroll during drag on touch devices */\n\n /* Invisible by default, visible on hover */\n background: ${(props) => props.$isDragging ? \"rgba(255, 255, 255, 0.4)\" : props.$isHovered ? \"rgba(255, 255, 255, 0.2)\" : \"transparent\"};\n\n ${(props) => props.$edge === \"left\" ? `border-left: 2px solid ${props.$isDragging ? \"rgba(255, 255, 255, 0.8)\" : props.$isHovered ? \"rgba(255, 255, 255, 0.5)\" : \"transparent\"};` : `border-right: 2px solid ${props.$isDragging ? \"rgba(255, 255, 255, 0.8)\" : props.$isHovered ? \"rgba(255, 255, 255, 0.5)\" : \"transparent\"};`}\n\n transition: background 0.15s ease, border-color 0.15s ease;\n\n &:hover {\n background: rgba(255, 255, 255, 0.2);\n ${(props) => props.$edge === \"left\" ? \"border-left: 2px solid rgba(255, 255, 255, 0.5);\" : \"border-right: 2px solid rgba(255, 255, 255, 0.5);\"}\n }\n\n &:active {\n background: rgba(255, 255, 255, 0.4);\n ${(props) => props.$edge === \"left\" ? \"border-left: 2px solid rgba(255, 255, 255, 0.8);\" : \"border-right: 2px solid rgba(255, 255, 255, 0.8);\"}\n }\n`;\nvar ClipBoundary = ({\n clipId,\n trackIndex,\n clipIndex,\n edge,\n dragHandleProps,\n touchOptimized = false\n}) => {\n const [isHovered, setIsHovered] = React2.useState(false);\n if (!dragHandleProps) {\n return null;\n }\n const { attributes, listeners, setActivatorNodeRef, isDragging } = dragHandleProps;\n return /* @__PURE__ */ jsx5(\n BoundaryContainer,\n {\n ref: setActivatorNodeRef,\n \"data-clip-id\": clipId,\n \"data-boundary-edge\": edge,\n $edge: edge,\n $isDragging: isDragging,\n $isHovered: isHovered,\n $touchOptimized: touchOptimized,\n onMouseEnter: () => setIsHovered(true),\n onMouseLeave: () => setIsHovered(false),\n ...listeners,\n ...attributes\n }\n );\n};\n\n// src/components/FadeOverlay.tsx\nimport styled12, { useTheme } from \"styled-components\";\nimport { jsx as jsx6 } from \"react/jsx-runtime\";\nvar FadeContainer = styled12.div.attrs((props) => ({\n style: {\n left: `${props.$left}px`,\n width: `${props.$width}px`\n }\n}))`\n position: absolute;\n top: 0;\n bottom: 0;\n pointer-events: none;\n z-index: 50;\n`;\nvar FadeSvg = styled12.svg`\n width: 100%;\n height: 100%;\n display: block;\n /* Flip horizontally for fadeOut - makes it mirror of fadeIn */\n transform: ${(props) => props.$type === \"fadeOut\" ? \"scaleX(-1)\" : \"none\"};\n`;\nfunction generateFadePath(width, height, curveType = \"logarithmic\") {\n const points = [];\n const numPoints = Math.max(20, Math.min(width, 100));\n for (let i = 0; i <= numPoints; i++) {\n const x = i / numPoints * width;\n const progress = i / numPoints;\n let curvedProgress;\n switch (curveType) {\n case \"linear\":\n curvedProgress = progress;\n break;\n case \"exponential\":\n curvedProgress = progress * progress;\n break;\n case \"sCurve\":\n curvedProgress = (1 - Math.cos(progress * Math.PI)) / 2;\n break;\n case \"logarithmic\":\n default:\n curvedProgress = Math.log10(1 + progress * 9) / Math.log10(10);\n break;\n }\n const y = (1 - curvedProgress) * height;\n points.push(`${x},${y}`);\n }\n return `M 0,${height} L ${points.join(\" L \")} L ${width},0 L 0,0 Z`;\n}\nvar FadeOverlay = ({\n left,\n width,\n type,\n curveType = \"logarithmic\",\n color\n}) => {\n const theme = useTheme();\n if (width < 1) return null;\n const fillColor = color || theme?.fadeOverlayColor || \"rgba(0, 0, 0, 0.4)\";\n return /* @__PURE__ */ jsx6(FadeContainer, { $left: left, $width: width, $type: type, children: /* @__PURE__ */ jsx6(FadeSvg, { $type: type, viewBox: `0 0 ${width} 100`, preserveAspectRatio: \"none\", children: /* @__PURE__ */ jsx6(\n \"path\",\n {\n d: generateFadePath(width, 100, curveType),\n fill: fillColor\n }\n ) }) });\n};\n\n// src/components/Clip.tsx\nimport { Fragment, jsx as jsx7, jsxs as jsxs2 } from \"react/jsx-runtime\";\nvar ClipContainer = styled13.div.attrs((props) => ({\n style: props.$isOverlay ? {} : {\n left: `${props.$left}px`,\n width: `${props.$width}px`\n }\n}))`\n position: ${(props) => props.$isOverlay ? \"relative\" : \"absolute\"};\n top: 0;\n height: ${(props) => props.$isOverlay ? \"auto\" : \"100%\"};\n width: ${(props) => props.$isOverlay ? `${props.$width}px` : \"auto\"};\n display: flex;\n flex-direction: column;\n background: rgba(255, 255, 255, 0.05);\n z-index: 10; /* Above progress overlay (z-index: 2) but below controls/playhead */\n pointer-events: none; /* Let clicks pass through to ClickOverlay for playhead positioning */\n\n &:hover {\n background: rgba(255, 255, 255, 0.08);\n }\n`;\nvar ChannelsWrapper = styled13.div`\n flex: 1;\n position: relative;\n overflow: ${(props) => props.$isOverlay ? \"visible\" : \"hidden\"};\n`;\nvar Clip = ({\n children,\n className,\n clipId,\n trackIndex,\n clipIndex,\n trackName,\n startSample,\n durationSamples,\n samplesPerPixel,\n showHeader = false,\n disableHeaderDrag = false,\n isOverlay = false,\n isSelected = false,\n onMouseDown,\n trackId,\n fadeIn,\n fadeOut,\n sampleRate = 44100,\n showFades = false,\n touchOptimized = false\n}) => {\n const left = Math.floor(startSample / samplesPerPixel);\n const endPixel = Math.floor((startSample + durationSamples) / samplesPerPixel);\n const width = endPixel - left;\n const enableDrag = showHeader && !disableHeaderDrag && !isOverlay;\n const draggableId = `clip-${trackIndex}-${clipIndex}`;\n const { attributes, listeners, setNodeRef, setActivatorNodeRef, transform, isDragging } = useDraggable({\n id: draggableId,\n data: { clipId, trackIndex, clipIndex },\n disabled: !enableDrag\n });\n const leftBoundaryId = `clip-boundary-left-${trackIndex}-${clipIndex}`;\n const {\n attributes: leftBoundaryAttributes,\n listeners: leftBoundaryListeners,\n setActivatorNodeRef: setLeftBoundaryActivatorRef,\n isDragging: isLeftBoundaryDragging\n } = useDraggable({\n id: leftBoundaryId,\n data: { clipId, trackIndex, clipIndex, boundary: \"left\" },\n disabled: !enableDrag\n });\n const rightBoundaryId = `clip-boundary-right-${trackIndex}-${clipIndex}`;\n const {\n attributes: rightBoundaryAttributes,\n listeners: rightBoundaryListeners,\n setActivatorNodeRef: setRightBoundaryActivatorRef,\n isDragging: isRightBoundaryDragging\n } = useDraggable({\n id: rightBoundaryId,\n data: { clipId, trackIndex, clipIndex, boundary: \"right\" },\n disabled: !enableDrag\n });\n const style = transform ? {\n transform: CSS.Translate.toString(transform),\n zIndex: isDragging ? 100 : void 0\n // Below controls (z-index: 999) but above other clips\n } : void 0;\n return /* @__PURE__ */ jsxs2(\n ClipContainer,\n {\n ref: setNodeRef,\n style,\n className,\n $left: left,\n $width: width,\n $isOverlay: isOverlay,\n \"data-clip-container\": \"true\",\n \"data-track-id\": trackId,\n onMouseDown,\n children: [\n showHeader && /* @__PURE__ */ jsx7(\n ClipHeader,\n {\n clipId,\n trackIndex,\n clipIndex,\n trackName,\n isSelected,\n disableDrag: disableHeaderDrag,\n dragHandleProps: enableDrag ? { attributes, listeners, setActivatorNodeRef } : void 0\n }\n ),\n /* @__PURE__ */ jsxs2(ChannelsWrapper, { $isOverlay: isOverlay, children: [\n children,\n showFades && fadeIn && fadeIn.duration > 0 && /* @__PURE__ */ jsx7(\n FadeOverlay,\n {\n left: 0,\n width: Math.floor(fadeIn.duration * sampleRate / samplesPerPixel),\n type: \"fadeIn\",\n curveType: fadeIn.type\n }\n ),\n showFades && fadeOut && fadeOut.duration > 0 && /* @__PURE__ */ jsx7(\n FadeOverlay,\n {\n left: width - Math.floor(fadeOut.duration * sampleRate / samplesPerPixel),\n width: Math.floor(fadeOut.duration * sampleRate / samplesPerPixel),\n type: \"fadeOut\",\n curveType: fadeOut.type\n }\n )\n ] }),\n showHeader && !disableHeaderDrag && !isOverlay && /* @__PURE__ */ jsxs2(Fragment, { children: [\n /* @__PURE__ */ jsx7(\n ClipBoundary,\n {\n clipId,\n trackIndex,\n clipIndex,\n edge: \"left\",\n touchOptimized,\n dragHandleProps: {\n attributes: leftBoundaryAttributes,\n listeners: leftBoundaryListeners,\n setActivatorNodeRef: setLeftBoundaryActivatorRef,\n isDragging: isLeftBoundaryDragging\n }\n }\n ),\n /* @__PURE__ */ jsx7(\n ClipBoundary,\n {\n clipId,\n trackIndex,\n clipIndex,\n edge: \"right\",\n touchOptimized,\n dragHandleProps: {\n attributes: rightBoundaryAttributes,\n listeners: rightBoundaryListeners,\n setActivatorNodeRef: setRightBoundaryActivatorRef,\n isDragging: isRightBoundaryDragging\n }\n }\n )\n ] })\n ]\n }\n );\n};\n\n// src/components/MasterVolumeControl.tsx\nimport styled14 from \"styled-components\";\nimport { jsx as jsx8, jsxs as jsxs3 } from \"react/jsx-runtime\";\nvar VolumeContainer = styled14.div`\n display: inline-flex;\n align-items: center;\n gap: 0.5rem;\n`;\nvar VolumeLabel = styled14(BaseLabel)`\n margin: 0;\n white-space: nowrap;\n`;\nvar VolumeSlider = styled14(BaseSlider)`\n width: 120px;\n`;\nvar MasterVolumeControl = ({\n volume,\n onChange,\n disabled = false,\n className\n}) => {\n const handleChange = (e) => {\n onChange(parseFloat(e.target.value) / 100);\n };\n return /* @__PURE__ */ jsxs3(VolumeContainer, { className, children: [\n /* @__PURE__ */ jsx8(VolumeLabel, { htmlFor: \"master-gain\", children: \"Master Volume\" }),\n /* @__PURE__ */ jsx8(\n VolumeSlider,\n {\n min: \"0\",\n max: \"100\",\n value: volume * 100,\n onChange: handleChange,\n disabled,\n id: \"master-gain\"\n }\n )\n ] });\n};\n\n// src/components/Playhead.tsx\nimport { useRef as useRef2, useEffect } from \"react\";\nimport styled15 from \"styled-components\";\nimport { jsx as jsx9, jsxs as jsxs4 } from \"react/jsx-runtime\";\nvar PlayheadLine = styled15.div.attrs((props) => ({\n style: {\n transform: `translate3d(${props.$position}px, 0, 0)`\n }\n}))`\n position: absolute;\n top: 0;\n left: 0;\n width: 2px;\n background: ${(props) => props.$color};\n height: 100%;\n z-index: 100; /* Below sticky controls (z-index: 101) so playhead is hidden when scrolled behind controls */\n pointer-events: none;\n will-change: transform;\n`;\nvar Playhead = ({ position, color = \"#ff0000\" }) => {\n return /* @__PURE__ */ jsx9(PlayheadLine, { $position: position, $color: color });\n};\nvar PlayheadWithMarkerContainer = styled15.div`\n position: absolute;\n top: 0;\n left: 0;\n height: 100%;\n z-index: 100; /* Below sticky controls (z-index: 101) so playhead is hidden when scrolled behind controls */\n pointer-events: none;\n will-change: transform;\n`;\nvar MarkerTriangle = styled15.div`\n position: absolute;\n top: -10px;\n left: -6px;\n width: 0;\n height: 0;\n border-left: 7px solid transparent;\n border-right: 7px solid transparent;\n border-top: 10px solid ${(props) => props.$color};\n`;\nvar MarkerLine = styled15.div`\n position: absolute;\n top: 0;\n left: 0;\n width: 2px;\n height: 100%;\n background: ${(props) => props.$color};\n`;\nvar PlayheadWithMarker = ({\n color = \"#ff0000\",\n isPlaying,\n currentTimeRef,\n playbackStartTimeRef,\n audioStartPositionRef,\n samplesPerPixel,\n sampleRate,\n controlsOffset,\n getAudioContextTime\n}) => {\n const containerRef = useRef2(null);\n const animationFrameRef = useRef2(null);\n useEffect(() => {\n const updatePosition = () => {\n if (containerRef.current) {\n let time;\n if (isPlaying && getAudioContextTime) {\n const elapsed = getAudioContextTime() - (playbackStartTimeRef.current ?? 0);\n time = (audioStartPositionRef.current ?? 0) + elapsed;\n } else {\n time = currentTimeRef.current ?? 0;\n }\n const pos = time * sampleRate / samplesPerPixel + controlsOffset;\n containerRef.current.style.transform = `translate3d(${pos}px, 0, 0)`;\n }\n if (isPlaying) {\n animationFrameRef.current = requestAnimationFrame(updatePosition);\n }\n };\n if (isPlaying) {\n animationFrameRef.current = requestAnimationFrame(updatePosition);\n } else {\n updatePosition();\n }\n return () => {\n if (animationFrameRef.current) {\n cancelAnimationFrame(animationFrameRef.current);\n animationFrameRef.current = null;\n }\n };\n }, [isPlaying, sampleRate, samplesPerPixel, controlsOffset, currentTimeRef, playbackStartTimeRef, audioStartPositionRef, getAudioContextTime]);\n useEffect(() => {\n if (!isPlaying && containerRef.current) {\n const time = currentTimeRef.current ?? 0;\n const pos = time * sampleRate / samplesPerPixel + controlsOffset;\n containerRef.current.style.transform = `translate3d(${pos}px, 0, 0)`;\n }\n });\n return /* @__PURE__ */ jsxs4(PlayheadWithMarkerContainer, { ref: containerRef, $color: color, children: [\n /* @__PURE__ */ jsx9(MarkerTriangle, { $color: color }),\n /* @__PURE__ */ jsx9(MarkerLine, { $color: color })\n ] });\n};\n\n// src/components/Playlist.tsx\nimport styled16, { withTheme } from \"styled-components\";\nimport { jsx as jsx10, jsxs as jsxs5 } from \"react/jsx-runtime\";\nvar Wrapper2 = styled16.div`\n overflow-y: hidden;\n overflow-x: auto;\n position: relative;\n`;\nvar ScrollContainer = styled16.div.attrs((props) => ({\n style: props.$width !== void 0 ? { width: `${props.$width}px` } : {}\n}))`\n position: relative;\n background: ${(props) => props.$backgroundColor || \"transparent\"};\n`;\nvar TimescaleWrapper = styled16.div.attrs((props) => ({\n style: props.$width ? { minWidth: `${props.$width}px` } : {}\n}))`\n background: ${(props) => props.$backgroundColor || \"white\"};\n width: 100%;\n position: relative;\n overflow: hidden; /* Constrain loop region to timescale area */\n`;\nvar TracksContainer = styled16.div.attrs((props) => ({\n style: props.$width !== void 0 ? { minWidth: `${props.$width}px` } : {}\n}))`\n position: relative;\n background: ${(props) => props.$backgroundColor || \"transparent\"};\n width: 100%;\n`;\nvar ClickOverlay = styled16.div`\n position: absolute;\n top: 0;\n left: 0;\n right: 0;\n bottom: 0;\n cursor: crosshair;\n /* When selecting, raise z-index above clip boundaries (z-index: 105) to prevent interference */\n z-index: ${(props) => props.$isSelecting ? 110 : 1};\n`;\nvar Playlist = ({\n children,\n backgroundColor,\n timescaleBackgroundColor,\n timescale,\n timescaleWidth,\n tracksWidth,\n scrollContainerWidth,\n controlsWidth,\n onTracksClick,\n onTracksMouseDown,\n onTracksMouseMove,\n onTracksMouseUp,\n scrollContainerRef,\n isSelecting\n}) => {\n return /* @__PURE__ */ jsx10(Wrapper2, { \"data-scroll-container\": \"true\", ref: scrollContainerRef, children: /* @__PURE__ */ jsxs5(\n ScrollContainer,\n {\n $backgroundColor: backgroundColor,\n $width: scrollContainerWidth,\n children: [\n timescale && /* @__PURE__ */ jsx10(TimescaleWrapper, { $width: timescaleWidth, $backgroundColor: timescaleBackgroundColor, children: timescale }),\n /* @__PURE__ */ jsxs5(TracksContainer, { $width: tracksWidth, $backgroundColor: backgroundColor, children: [\n children,\n (onTracksClick || onTracksMouseDown) && /* @__PURE__ */ jsx10(\n ClickOverlay,\n {\n $controlsWidth: controlsWidth,\n $isSelecting: isSelecting,\n onClick: onTracksClick,\n onMouseDown: onTracksMouseDown,\n onMouseMove: onTracksMouseMove,\n onMouseUp: onTracksMouseUp\n }\n )\n ] })\n ]\n }\n ) });\n};\nvar StyledPlaylist = withTheme(Playlist);\n\n// src/components/Selection.tsx\nimport styled17 from \"styled-components\";\nimport { jsx as jsx11 } from \"react/jsx-runtime\";\nvar SelectionOverlay = styled17.div.attrs((props) => ({\n style: {\n left: `${props.$left}px`,\n width: `${props.$width}px`\n }\n}))`\n position: absolute;\n top: 0;\n background: ${(props) => props.$color};\n height: 100%;\n z-index: 60; /* Above clips (z-index: 10) and fades (z-index: 50), below playhead (z-index: 100) */\n pointer-events: none;\n opacity: 0.3;\n`;\nvar Selection = ({\n startPosition,\n endPosition,\n color = \"#00ff00\"\n}) => {\n const width = Math.max(0, endPosition - startPosition);\n if (width <= 0) {\n return null;\n }\n return /* @__PURE__ */ jsx11(SelectionOverlay, { $left: startPosition, $width: width, $color: color, \"data-selection\": true });\n};\n\n// src/components/LoopRegion.tsx\nimport { useCallback as useCallback2, useRef as useRef3, useState } from \"react\";\nimport styled18 from \"styled-components\";\nimport { Fragment as Fragment2, jsx as jsx12, jsxs as jsxs6 } from \"react/jsx-runtime\";\nvar LoopRegionOverlayDiv = styled18.div.attrs((props) => ({\n style: {\n left: `${props.$left}px`,\n width: `${props.$width}px`\n }\n}))`\n position: absolute;\n top: 0;\n background: ${(props) => props.$color};\n height: 100%;\n z-index: 55; /* Between clips (z-index: 50) and selection (z-index: 60) */\n pointer-events: none;\n`;\nvar LoopMarker = styled18.div.attrs((props) => ({\n style: {\n left: `${props.$left}px`\n }\n}))`\n position: absolute;\n top: 0;\n width: 2px;\n height: 100%;\n background: ${(props) => props.$color};\n z-index: 90; /* Below playhead (z-index: 100) */\n pointer-events: none;\n\n /* Triangle marker at top */\n &::before {\n content: '';\n position: absolute;\n top: 0;\n ${(props) => props.$isStart ? \"left: 0\" : \"right: 0\"};\n width: 0;\n height: 0;\n border-top: 8px solid ${(props) => props.$color};\n ${(props) => props.$isStart ? \"border-right: 8px solid transparent;\" : \"border-left: 8px solid transparent;\"}\n }\n`;\nvar LoopRegion = ({\n startPosition,\n endPosition,\n regionColor = \"rgba(59, 130, 246, 0.3)\",\n markerColor = \"#3b82f6\"\n}) => {\n const width = Math.max(0, endPosition - startPosition);\n if (width <= 0) {\n return null;\n }\n return /* @__PURE__ */ jsxs6(Fragment2, { children: [\n /* @__PURE__ */ jsx12(\n LoopRegionOverlayDiv,\n {\n $left: startPosition,\n $width: width,\n $color: regionColor,\n \"data-loop-region\": true\n }\n ),\n /* @__PURE__ */ jsx12(\n LoopMarker,\n {\n $left: startPosition,\n $color: markerColor,\n $isStart: true,\n \"data-loop-marker\": \"start\"\n }\n ),\n /* @__PURE__ */ jsx12(\n LoopMarker,\n {\n $left: endPosition - 2,\n $color: markerColor,\n $isStart: false,\n \"data-loop-marker\": \"end\"\n }\n )\n ] });\n};\nvar DraggableMarkerHandle = styled18.div.attrs((props) => ({\n style: {\n left: `${props.$left}px`\n }\n}))`\n position: absolute;\n top: 0;\n width: 12px;\n height: 100%;\n cursor: ew-resize;\n z-index: 100;\n /* Center the handle on the marker position */\n transform: translateX(-5px);\n\n /* Visual marker line */\n &::before {\n content: '';\n position: absolute;\n top: 0;\n left: 5px;\n width: 2px;\n height: 100%;\n background: ${(props) => props.$color};\n opacity: ${(props) => props.$isDragging ? 1 : 0.8};\n }\n\n /* Triangle marker at top */\n &::after {\n content: '';\n position: absolute;\n top: 0;\n ${(props) => props.$isStart ? \"left: 5px\" : \"left: -1px\"};\n width: 0;\n height: 0;\n border-top: 10px solid ${(props) => props.$color};\n ${(props) => props.$isStart ? \"border-right: 10px solid transparent;\" : \"border-left: 10px solid transparent;\"}\n }\n\n &:hover::before {\n opacity: 1;\n }\n`;\nvar TimescaleLoopShade = styled18.div.attrs((props) => ({\n style: {\n left: `${props.$left}px`,\n width: `${props.$width}px`\n }\n}))`\n position: absolute;\n top: 0;\n height: 100%;\n background: ${(props) => props.$color};\n z-index: 50;\n cursor: grab;\n\n &:active {\n cursor: grabbing;\n }\n`;\nvar LoopRegionMarkers = ({\n startPosition,\n endPosition,\n markerColor = \"#3b82f6\",\n regionColor = \"rgba(59, 130, 246, 0.3)\",\n onLoopStartChange,\n onLoopEndChange,\n onLoopRegionMove,\n minPosition = 0,\n maxPosition = Infinity\n}) => {\n const [draggingMarker, setDraggingMarker] = useState(null);\n const dragStartX = useRef3(0);\n const dragStartPosition = useRef3(0);\n const dragStartEnd = useRef3(0);\n const width = Math.max(0, endPosition - startPosition);\n const handleMarkerMouseDown = useCallback2((e, marker) => {\n e.preventDefault();\n e.stopPropagation();\n setDraggingMarker(marker);\n dragStartX.current = e.clientX;\n dragStartPosition.current = marker === \"start\" ? startPosition : endPosition;\n const handleMouseMove = (moveEvent) => {\n const delta = moveEvent.clientX - dragStartX.current;\n const newPosition = dragStartPosition.current + delta;\n if (marker === \"start\") {\n const clampedPosition = Math.max(minPosition, Math.min(endPosition - 10, newPosition));\n onLoopStartChange?.(clampedPosition);\n } else {\n const clampedPosition = Math.max(startPosition + 10, Math.min(maxPosition, newPosition));\n onLoopEndChange?.(clampedPosition);\n }\n };\n const handleMouseUp = () => {\n setDraggingMarker(null);\n document.removeEventListener(\"mousemove\", handleMouseMove);\n document.removeEventListener(\"mouseup\", handleMouseUp);\n };\n document.addEventListener(\"mousemove\", handleMouseMove);\n document.addEventListener(\"mouseup\", handleMouseUp);\n }, [startPosition, endPosition, minPosition, maxPosition, onLoopStartChange, onLoopEndChange]);\n const handleRegionMouseDown = useCallback2((e) => {\n e.preventDefault();\n e.stopPropagation();\n setDraggingMarker(\"region\");\n dragStartX.current = e.clientX;\n dragStartPosition.current = startPosition;\n dragStartEnd.current = endPosition;\n const regionWidth = endPosition - startPosition;\n const handleMouseMove = (moveEvent) => {\n const delta = moveEvent.clientX - dragStartX.current;\n let newStart = dragStartPosition.current + delta;\n let newEnd = dragStartEnd.current + delta;\n if (newStart < minPosition) {\n newStart = minPosition;\n newEnd = minPosition + regionWidth;\n }\n if (newEnd > maxPosition) {\n newEnd = maxPosition;\n newStart = maxPosition - regionWidth;\n }\n onLoopRegionMove?.(newStart, newEnd);\n };\n const handleMouseUp = () => {\n setDraggingMarker(null);\n document.removeEventListener(\"mousemove\", handleMouseMove);\n document.removeEventListener(\"mouseup\", handleMouseUp);\n };\n document.addEventListener(\"mousemove\", handleMouseMove);\n document.addEventListener(\"mouseup\", handleMouseUp);\n }, [startPosition, endPosition, minPosition, maxPosition, onLoopRegionMove]);\n if (width <= 0) {\n return null;\n }\n return /* @__PURE__ */ jsxs6(Fragment2, { children: [\n /* @__PURE__ */ jsx12(\n TimescaleLoopShade,\n {\n $left: startPosition,\n $width: width,\n $color: regionColor,\n $isDragging: draggingMarker === \"region\",\n onMouseDown: handleRegionMouseDown,\n \"data-loop-region-timescale\": true\n }\n ),\n /* @__PURE__ */ jsx12(\n DraggableMarkerHandle,\n {\n $left: startPosition,\n $color: markerColor,\n $isStart: true,\n $isDragging: draggingMarker === \"start\",\n onMouseDown: (e) => handleMarkerMouseDown(e, \"start\"),\n \"data-loop-marker-handle\": \"start\"\n }\n ),\n /* @__PURE__ */ jsx12(\n DraggableMarkerHandle,\n {\n $left: endPosition,\n $color: markerColor,\n $isStart: false,\n $isDragging: draggingMarker === \"end\",\n onMouseDown: (e) => handleMarkerMouseDown(e, \"end\"),\n \"data-loop-marker-handle\": \"end\"\n }\n )\n ] });\n};\nvar TimescaleLoopCreator = styled18.div.attrs((props) => ({\n style: {\n left: `${props.$leftOffset || 0}px`\n }\n}))`\n position: absolute;\n top: 0;\n right: 0;\n height: 100%; /* Stay within timescale bounds, don't extend into tracks */\n cursor: crosshair;\n z-index: 40; /* Below markers and shading */\n`;\nvar TimescaleLoopRegion = ({\n startPosition,\n endPosition,\n markerColor = \"#3b82f6\",\n regionColor = \"rgba(59, 130, 246, 0.3)\",\n onLoopRegionChange,\n minPosition = 0,\n maxPosition = Infinity,\n controlsOffset = 0\n}) => {\n const [isCreating, setIsCreating] = useState(false);\n const createStartX = useRef3(0);\n const containerRef = useRef3(null);\n const hasLoopRegion = endPosition > startPosition;\n const handleBackgroundMouseDown = useCallback2((e) => {\n const target = e.target;\n if (target.closest(\"[data-loop-marker-handle]\") || target.closest(\"[data-loop-region-timescale]\")) {\n return;\n }\n e.preventDefault();\n setIsCreating(true);\n const rect = containerRef.current?.getBoundingClientRect();\n if (!rect) return;\n const clickX = e.clientX - rect.left;\n const clampedX = Math.max(minPosition, Math.min(maxPosition, clickX));\n createStartX.current = clampedX;\n onLoopRegionChange?.(clampedX, clampedX);\n const handleMouseMove = (moveEvent) => {\n const currentX = moveEvent.clientX - rect.left;\n const clampedCurrentX = Math.max(minPosition, Math.min(maxPosition, currentX));\n const newStart = Math.min(createStartX.current, clampedCurrentX);\n const newEnd = Math.max(createStartX.current, clampedCurrentX);\n onLoopRegionChange?.(newStart, newEnd);\n };\n const handleMouseUp = () => {\n setIsCreating(false);\n document.removeEventListener(\"mousemove\", handleMouseMove);\n document.removeEventListener(\"mouseup\", handleMouseUp);\n };\n document.addEventListener(\"mousemove\", handleMouseMove);\n document.addEventListener(\"mouseup\", handleMouseUp);\n }, [minPosition, maxPosition, onLoopRegionChange]);\n return /* @__PURE__ */ jsx12(\n TimescaleLoopCreator,\n {\n ref: containerRef,\n $leftOffset: controlsOffset,\n onMouseDown: handleBackgroundMouseDown,\n \"data-timescale-loop-creator\": true,\n children: hasLoopRegion && /* @__PURE__ */ jsx12(\n LoopRegionMarkers,\n {\n startPosition,\n endPosition,\n markerColor,\n regionColor,\n minPosition,\n maxPosition,\n onLoopStartChange: (newStart) => onLoopRegionChange?.(newStart, endPosition),\n onLoopEndChange: (newEnd) => onLoopRegionChange?.(startPosition, newEnd),\n onLoopRegionMove: (newStart, newEnd) => onLoopRegionChange?.(newStart, newEnd)\n }\n )\n }\n );\n};\n\n// src/components/SelectionTimeInputs.tsx\nimport { useEffect as useEffect3, useState as useState3 } from \"react\";\n\n// src/components/TimeInput.tsx\nimport { useEffect as useEffect2, useState as useState2 } from \"react\";\n\n// src/utils/timeFormat.ts\nfunction clockFormat(seconds, decimals) {\n const hours = Math.floor(seconds / 3600) % 24;\n const minutes = Math.floor(seconds / 60) % 60;\n const secs = (seconds % 60).toFixed(decimals);\n return String(hours).padStart(2, \"0\") + \":\" + String(minutes).padStart(2, \"0\") + \":\" + secs.padStart(decimals + 3, \"0\");\n}\nfunction formatTime(seconds, format) {\n switch (format) {\n case \"seconds\":\n return seconds.toFixed(0);\n case \"thousandths\":\n return seconds.toFixed(3);\n case \"hh:mm:ss\":\n return clockFormat(seconds, 0);\n case \"hh:mm:ss.u\":\n return clockFormat(seconds, 1);\n case \"hh:mm:ss.uu\":\n return clockFormat(seconds, 2);\n case \"hh:mm:ss.uuu\":\n return clockFormat(seconds, 3);\n default:\n return clockFormat(seconds, 3);\n }\n}\nfunction parseTime(timeStr, format) {\n if (!timeStr) return 0;\n switch (format) {\n case \"seconds\":\n case \"thousandths\":\n return parseFloat(timeStr) || 0;\n case \"hh:mm:ss\":\n case \"hh:mm:ss.u\":\n case \"hh:mm:ss.uu\":\n case \"hh:mm:ss.uuu\": {\n const parts = timeStr.split(\":\");\n if (parts.length !== 3) return 0;\n const hours = parseInt(parts[0], 10) || 0;\n const minutes = parseInt(parts[1], 10) || 0;\n const seconds = parseFloat(parts[2]) || 0;\n return hours * 3600 + minutes * 60 + seconds;\n }\n default:\n return 0;\n }\n}\n\n// src/components/TimeInput.tsx\nimport { Fragment as Fragment3, jsx as jsx13, jsxs as jsxs7 } from \"react/jsx-runtime\";\nvar TimeInput = ({\n id,\n label,\n value,\n format,\n className,\n onChange,\n readOnly = false\n}) => {\n const [displayValue, setDisplayValue] = useState2(\"\");\n useEffect2(() => {\n const formatted = formatTime(value, format);\n setDisplayValue(formatted);\n }, [value, format, id]);\n const handleChange = (e) => {\n const newDisplayValue = e.target.value;\n setDisplayValue(newDisplayValue);\n };\n const handleBlur = () => {\n if (onChange) {\n const parsedValue = parseTime(displayValue, format);\n onChange(parsedValue);\n }\n setDisplayValue(formatTime(value, format));\n };\n const handleKeyDown = (e) => {\n if (e.key === \"Enter\") {\n e.currentTarget.blur();\n }\n };\n return /* @__PURE__ */ jsxs7(Fragment3, { children: [\n /* @__PURE__ */ jsx13(ScreenReaderOnly, { as: \"label\", htmlFor: id, children: label }),\n /* @__PURE__ */ jsx13(\n BaseInput,\n {\n type: \"text\",\n className,\n id,\n value: displayValue,\n onChange: handleChange,\n onBlur: handleBlur,\n onKeyDown: handleKeyDown,\n readOnly\n }\n )\n ] });\n};\n\n// src/components/SelectionTimeInputs.tsx\nimport { Fragment as Fragment4, jsx as jsx14, jsxs as jsxs8 } from \"react/jsx-runtime\";\nvar SelectionTimeInputs = ({\n selectionStart,\n selectionEnd,\n onSelectionChange,\n className\n}) => {\n const [timeFormat, setTimeFormat] = useState3(\"hh:mm:ss.uuu\");\n useEffect3(() => {\n const timeFormatSelect = document.querySelector(\".time-format\");\n const handleFormatChange = () => {\n if (timeFormatSelect) {\n setTimeFormat(timeFormatSelect.value);\n }\n };\n if (timeFormatSelect) {\n setTimeFormat(timeFormatSelect.value);\n timeFormatSelect.addEventListener(\"change\", handleFormatChange);\n }\n return () => {\n timeFormatSelect?.removeEventListener(\"change\", handleFormatChange);\n };\n }, []);\n const handleStartChange = (value) => {\n if (onSelectionChange) {\n onSelectionChange(value, selectionEnd);\n }\n };\n const handleEndChange = (value) => {\n if (onSelectionChange) {\n onSelectionChange(selectionStart, value);\n }\n };\n return /* @__PURE__ */ jsxs8(Fragment4, { children: [\n /* @__PURE__ */ jsx14(\n TimeInput,\n {\n id: \"audio_start\",\n label: \"Start of audio selection\",\n value: selectionStart,\n format: timeFormat,\n className: \"audio-start form-control mr-sm-2\",\n onChange: handleStartChange\n }\n ),\n /* @__PURE__ */ jsx14(\n TimeInput,\n {\n id: \"audio_end\",\n label: \"End of audio selection\",\n value: selectionEnd,\n format: timeFormat,\n className: \"audio-end form-control mr-sm-2\",\n onChange: handleEndChange\n }\n )\n ] });\n};\n\n// src/contexts/DevicePixelRatio.tsx\nimport { useState as useState4, createContext, useContext } from \"react\";\nimport { jsx as jsx15 } from \"react/jsx-runtime\";\nfunction getScale() {\n return window.devicePixelRatio;\n}\nvar DevicePixelRatioContext = createContext(getScale());\nvar DevicePixelRatioProvider = ({ children }) => {\n const [scale, setScale] = useState4(getScale());\n matchMedia(`(resolution: ${getScale()}dppx)`).addEventListener(\n \"change\",\n () => {\n setScale(getScale());\n },\n { once: true }\n );\n return /* @__PURE__ */ jsx15(DevicePixelRatioContext.Provider, { value: Math.ceil(scale), children });\n};\nvar useDevicePixelRatio = () => useContext(DevicePixelRatioContext);\n\n// src/contexts/PlaylistInfo.tsx\nimport { createContext as createContext2, useContext as useContext2 } from \"react\";\nvar PlaylistInfoContext = createContext2({\n sampleRate: 48e3,\n samplesPerPixel: 1e3,\n zoomLevels: [1e3, 1500, 2e3, 2500],\n waveHeight: 80,\n timeScaleHeight: 15,\n controls: {\n show: false,\n width: 150\n },\n duration: 3e4,\n barWidth: 1,\n barGap: 0\n});\nvar usePlaylistInfo = () => useContext2(PlaylistInfoContext);\n\n// src/contexts/Theme.tsx\nimport { useContext as useContext3 } from \"react\";\nimport { ThemeContext } from \"styled-components\";\nvar useTheme2 = () => useContext3(ThemeContext);\n\n// src/contexts/TrackControls.tsx\nimport { createContext as createContext3, useContext as useContext4, Fragment as Fragment5 } from \"react\";\nimport { jsx as jsx16 } from \"react/jsx-runtime\";\nvar TrackControlsContext = createContext3(/* @__PURE__ */ jsx16(Fragment5, {}));\nvar useTrackControls = () => useContext4(TrackControlsContext);\n\n// src/contexts/Playout.tsx\nimport {\n useState as useState5,\n createContext as createContext4,\n useContext as useContext5\n} from \"react\";\nimport { jsx as jsx17 } from \"react/jsx-runtime\";\nvar defaultProgress = 0;\nvar defaultIsPlaying = false;\nvar defaultSelectionStart = 0;\nvar defaultSelectionEnd = 0;\nvar defaultPlayout = {\n progress: defaultProgress,\n isPlaying: defaultIsPlaying,\n selectionStart: defaultSelectionStart,\n selectionEnd: defaultSelectionEnd\n};\nvar PlayoutStatusContext = createContext4(defaultPlayout);\nvar PlayoutStatusUpdateContext = createContext4({\n setIsPlaying: () => {\n },\n setProgress: () => {\n },\n setSelection: () => {\n }\n});\nvar PlayoutProvider = ({ children }) => {\n const [isPlaying, setIsPlaying] = useState5(defaultIsPlaying);\n const [progress, setProgress] = useState5(defaultProgress);\n const [selectionStart, setSelectionStart] = useState5(defaultSelectionStart);\n const [selectionEnd, setSelectionEnd] = useState5(defaultSelectionEnd);\n const setSelection = (start, end) => {\n setSelectionStart(start);\n setSelectionEnd(end);\n };\n return /* @__PURE__ */ jsx17(PlayoutStatusUpdateContext.Provider, { value: { setIsPlaying, setProgress, setSelection }, children: /* @__PURE__ */ jsx17(PlayoutStatusContext.Provider, { value: { isPlaying, progress, selectionStart, selectionEnd }, children }) });\n};\nvar usePlayoutStatus = () => useContext5(PlayoutStatusContext);\nvar usePlayoutStatusUpdate = () => useContext5(PlayoutStatusUpdateContext);\n\n// src/components/SmartChannel.tsx\nimport { jsx as jsx18 } from \"react/jsx-runtime\";\nvar SmartChannel = ({ isSelected, transparentBackground, ...props }) => {\n const theme = useTheme2();\n const { waveHeight, barWidth, barGap } = usePlaylistInfo();\n const devicePixelRatio = useDevicePixelRatio();\n const waveOutlineColor = isSelected && theme ? theme.selectedWaveOutlineColor : theme?.waveOutlineColor;\n const waveFillColor = isSelected && theme ? theme.selectedWaveFillColor : theme?.waveFillColor;\n const drawMode = theme?.waveformDrawMode || \"inverted\";\n return /* @__PURE__ */ jsx18(\n Channel,\n {\n ...props,\n ...theme,\n waveOutlineColor,\n waveFillColor,\n waveHeight,\n devicePixelRatio,\n barWidth,\n barGap,\n transparentBackground,\n drawMode\n }\n );\n};\n\n// src/components/SmartScale.tsx\nimport { useContext as useContext7 } from \"react\";\n\n// src/components/TimeScale.tsx\nimport React10, { useRef as useRef4, useEffect as useEffect4, useContext as useContext6 } from \"react\";\nimport styled19, { withTheme as withTheme2 } from \"styled-components\";\n\n// src/utils/conversions.ts\nfunction samplesToSeconds(samples, sampleRate) {\n return samples / sampleRate;\n}\nfunction secondsToSamples(seconds, sampleRate) {\n return Math.ceil(seconds * sampleRate);\n}\nfunction samplesToPixels(samples, samplesPerPixel) {\n return Math.floor(samples / samplesPerPixel);\n}\nfunction pixelsToSamples(pixels, samplesPerPixel) {\n return Math.floor(pixels * samplesPerPixel);\n}\nfunction pixelsToSeconds(pixels, samplesPerPixel, sampleRate) {\n return pixels * samplesPerPixel / sampleRate;\n}\nfunction secondsToPixels(seconds, samplesPerPixel, sampleRate) {\n return Math.ceil(seconds * sampleRate / samplesPerPixel);\n}\n\n// src/components/TimeScale.tsx\nimport { jsx as jsx19, jsxs as jsxs9 } from \"react/jsx-runtime\";\nfunction formatTime2(milliseconds) {\n const seconds = Math.floor(milliseconds / 1e3);\n const s = seconds % 60;\n const m = (seconds - s) / 60;\n return `${m}:${String(s).padStart(2, \"0\")}`;\n}\nvar PlaylistTimeScaleScroll = styled19.div.attrs((props) => ({\n style: {\n width: `${props.$cssWidth}px`,\n marginLeft: `${props.$controlWidth}px`,\n height: `${props.$timeScaleHeight}px`\n }\n}))`\n position: relative;\n overflow: visible; /* Allow time labels to render above the container */\n border-bottom: 1px solid ${(props) => props.theme.timeColor};\n box-sizing: border-box;\n`;\nvar TimeTicks = styled19.canvas.attrs((props) => ({\n style: {\n width: `${props.$cssWidth}px`,\n height: `${props.$timeScaleHeight}px`\n }\n}))`\n position: absolute;\n left: 0;\n right: 0;\n bottom: 0;\n`;\nvar TimeStamp = styled19.div.attrs((props) => ({\n style: {\n left: `${props.$left + 4}px`\n // Offset 4px to the right of the tick\n }\n}))`\n position: absolute;\n font-size: 0.75rem; /* Smaller font to prevent overflow */\n white-space: nowrap; /* Prevent text wrapping */\n color: ${(props) => props.theme.timeColor}; /* Use theme color instead of inheriting */\n`;\nvar TimeScale = (props) => {\n const {\n theme: { timeColor },\n duration,\n marker,\n bigStep,\n secondStep,\n renderTimestamp\n } = props;\n const canvasInfo = /* @__PURE__ */ new Map();\n const timeMarkers = [];\n const canvasRef = useRef4(null);\n const {\n sampleRate,\n samplesPerPixel,\n timeScaleHeight,\n controls: { show: showControls, width: controlWidth }\n } = useContext6(PlaylistInfoContext);\n const devicePixelRatio = useDevicePixelRatio();\n useEffect4(() => {\n if (canvasRef.current !== null) {\n const canvas = canvasRef.current;\n const ctx = canvas.getContext(\"2d\");\n if (ctx) {\n ctx.resetTransform();\n ctx.clearRect(0, 0, canvas.width, canvas.height);\n ctx.imageSmoothingEnabled = false;\n ctx.fillStyle = timeColor;\n ctx.scale(devicePixelRatio, devicePixelRatio);\n for (const [pixLeft, scaleHeight] of canvasInfo.entries()) {\n const scaleY = timeScaleHeight - scaleHeight;\n ctx.fillRect(pixLeft, scaleY, 1, scaleHeight);\n }\n }\n }\n }, [\n duration,\n devicePixelRatio,\n timeColor,\n timeScaleHeight,\n bigStep,\n secondStep,\n marker,\n canvasInfo\n ]);\n const widthX = secondsToPixels(duration / 1e3, samplesPerPixel, sampleRate);\n const pixPerSec = sampleRate / samplesPerPixel;\n let counter = 0;\n for (let i = 0; i < widthX; i += pixPerSec * secondStep / 1e3) {\n const pix = Math.floor(i);\n if (counter % marker === 0) {\n const timeMs = counter;\n const timestamp = formatTime2(timeMs);\n const timestampContent = renderTimestamp ? /* @__PURE__ */ jsx19(React10.Fragment, { children: renderTimestamp(timeMs, pix) }, `timestamp-${counter}`) : /* @__PURE__ */ jsx19(TimeStamp, { $left: pix, children: timestamp }, timestamp);\n timeMarkers.push(timestampContent);\n canvasInfo.set(pix, timeScaleHeight);\n } else if (counter % bigStep === 0) {\n canvasInfo.set(pix, Math.floor(timeScaleHeight / 2));\n } else if (counter % secondStep === 0) {\n canvasInfo.set(pix, Math.floor(timeScaleHeight / 5));\n }\n counter += secondStep;\n }\n return /* @__PURE__ */ jsxs9(\n PlaylistTimeScaleScroll,\n {\n $cssWidth: widthX,\n $controlWidth: showControls ? controlWidth : 0,\n $timeScaleHeight: timeScaleHeight,\n children: [\n timeMarkers,\n /* @__PURE__ */ jsx19(\n TimeTicks,\n {\n $cssWidth: widthX,\n $timeScaleHeight: timeScaleHeight,\n width: widthX * devicePixelRatio,\n height: timeScaleHeight * devicePixelRatio,\n ref: canvasRef\n }\n )\n ]\n }\n );\n};\nvar StyledTimeScale = withTheme2(TimeScale);\n\n// src/components/SmartScale.tsx\nimport { jsx as jsx20 } from \"react/jsx-runtime\";\nvar timeinfo = /* @__PURE__ */ new Map([\n [\n 700,\n {\n marker: 1e3,\n bigStep: 500,\n smallStep: 100\n }\n ],\n [\n 1500,\n {\n marker: 2e3,\n bigStep: 1e3,\n smallStep: 200\n }\n ],\n [\n 2500,\n {\n marker: 2e3,\n bigStep: 1e3,\n smallStep: 500\n }\n ],\n [\n 5e3,\n {\n marker: 5e3,\n bigStep: 1e3,\n smallStep: 500\n }\n ],\n [\n 1e4,\n {\n marker: 1e4,\n bigStep: 5e3,\n smallStep: 1e3\n }\n ],\n [\n 12e3,\n {\n marker: 15e3,\n bigStep: 5e3,\n smallStep: 1e3\n }\n ],\n [\n Infinity,\n {\n marker: 3e4,\n bigStep: 1e4,\n smallStep: 5e3\n }\n ]\n]);\nfunction getScaleInfo(samplesPerPixel) {\n const keys = timeinfo.keys();\n let config;\n for (const resolution of keys) {\n if (samplesPerPixel < resolution) {\n config = timeinfo.get(resolution);\n break;\n }\n }\n if (config === void 0) {\n config = { marker: 3e4, bigStep: 1e4, smallStep: 5e3 };\n }\n return config;\n}\nvar SmartScale = () => {\n const { samplesPerPixel, duration } = useContext7(PlaylistInfoContext);\n let config = getScaleInfo(samplesPerPixel);\n return /* @__PURE__ */ jsx20(\n StyledTimeScale,\n {\n marker: config.marker,\n bigStep: config.bigStep,\n secondStep: config.smallStep,\n duration\n }\n );\n};\n\n// src/components/TimeFormatSelect.tsx\nimport styled20 from \"styled-components\";\nimport { jsx as jsx21 } from \"react/jsx-runtime\";\nvar SelectWrapper = styled20.div`\n display: inline-flex;\n align-items: center;\n gap: 0.5rem;\n`;\nvar TIME_FORMAT_OPTIONS = [\n { value: \"seconds\", label: \"seconds\" },\n { value: \"thousandths\", label: \"thousandths\" },\n { value: \"hh:mm:ss\", label: \"hh:mm:ss\" },\n { value: \"hh:mm:ss.u\", label: \"hh:mm:ss + tenths\" },\n { value: \"hh:mm:ss.uu\", label: \"hh:mm:ss + hundredths\" },\n { value: \"hh:mm:ss.uuu\", label: \"hh:mm:ss + milliseconds\" }\n];\nvar TimeFormatSelect = ({\n value,\n onChange,\n disabled = false,\n className\n}) => {\n const handleChange = (e) => {\n onChange(e.target.value);\n };\n return /* @__PURE__ */ jsx21(SelectWrapper, { className, children: /* @__PURE__ */ jsx21(\n BaseSelect,\n {\n className: \"time-format\",\n value,\n onChange: handleChange,\n disabled,\n \"aria-label\": \"Time format selection\",\n children: TIME_FORMAT_OPTIONS.map((option) => /* @__PURE__ */ jsx21(\"option\", { value: option.value, children: option.label }, option.value))\n }\n ) });\n};\n\n// src/components/Track.tsx\nimport styled21 from \"styled-components\";\nimport { jsx as jsx22, jsxs as jsxs10 } from \"react/jsx-runtime\";\nvar Container = styled21.div.attrs((props) => ({\n style: {\n height: `${props.$waveHeight * props.$numChannels + (props.$hasClipHeaders ? CLIP_HEADER_HEIGHT : 0)}px`\n }\n}))`\n position: relative;\n display: flex;\n ${(props) => props.$width !== void 0 && `width: ${props.$width}px;`}\n`;\nvar ChannelContainer = styled21.div.attrs((props) => ({\n style: {\n paddingLeft: `${props.$offset || 0}px`\n }\n}))`\n position: relative;\n background: ${(props) => props.$backgroundColor || \"transparent\"};\n flex: 1;\n`;\nvar ControlsWrapper = styled21.div.attrs((props) => ({\n style: {\n width: `${props.$controlWidth}px`\n }\n}))`\n position: sticky;\n z-index: 101; /* Above waveform content, below Docusaurus navbar (z-index: 200) */\n left: 0;\n height: 100%;\n flex-shrink: 0;\n pointer-events: auto;\n background: ${(props) => props.theme.surfaceColor};\n transition: background 0.15s ease-in-out;\n\n /* Selected track: highlighted background */\n ${(props) => props.$isSelected && `\n background: ${props.theme.selectedTrackControlsBackground};\n `}\n`;\nvar Track = ({\n numChannels,\n children,\n className,\n backgroundColor,\n offset = 0,\n width,\n hasClipHeaders = false,\n onClick,\n trackId,\n isSelected = false\n}) => {\n const {\n waveHeight,\n controls: { show, width: controlWidth }\n } = usePlaylistInfo();\n const controls = useTrackControls();\n return /* @__PURE__ */ jsxs10(\n Container,\n {\n $numChannels: numChannels,\n className,\n $waveHeight: waveHeight,\n $controlWidth: show ? controlWidth : 0,\n $width: width,\n $hasClipHeaders: hasClipHeaders,\n $isSelected: isSelected,\n children: [\n /* @__PURE__ */ jsx22(\n ControlsWrapper,\n {\n $controlWidth: show ? controlWidth : 0,\n $isSelected: isSelected,\n children: controls\n }\n ),\n /* @__PURE__ */ jsx22(\n ChannelContainer,\n {\n $controlWidth: show ? controlWidth : 0,\n $backgroundColor: backgroundColor,\n $offset: offset,\n onClick,\n \"data-track-id\": trackId,\n children\n }\n )\n ]\n }\n );\n};\n\n// src/components/TrackControls/Button.tsx\nimport styled22 from \"styled-components\";\nvar Button = styled22.button.attrs({\n type: \"button\"\n})`\n display: inline-block;\n font-family: ${(props) => props.theme.fontFamily};\n font-weight: 500;\n text-align: center;\n vertical-align: middle;\n user-select: none;\n padding: 0.25rem 0.4rem;\n font-size: ${(props) => props.theme.fontSizeSmall};\n line-height: 1;\n border-radius: ${(props) => props.theme.borderRadius};\n transition: color 0.15s ease-in-out, background-color 0.15s ease-in-out,\n border-color 0.15s ease-in-out, box-shadow 0.15s ease-in-out;\n cursor: pointer;\n\n ${(props) => {\n if (props.$variant === \"danger\") {\n return `\n color: #fff;\n background-color: #dc3545;\n border: 1px solid #dc3545;\n\n &:hover {\n background-color: #c82333;\n border-color: #bd2130;\n }\n\n &:focus {\n outline: none;\n box-shadow: 0 0 0 0.2rem rgba(225, 83, 97, 0.5);\n }\n `;\n } else if (props.$variant === \"info\") {\n return `\n color: #fff;\n background-color: #17a2b8;\n border: 1px solid #17a2b8;\n\n &:hover {\n background-color: #138496;\n border-color: #117a8b;\n }\n\n &:focus {\n outline: none;\n box-shadow: 0 0 0 0.2rem rgba(58, 176, 195, 0.5);\n }\n `;\n } else {\n return `\n color: ${props.theme.textColor};\n background-color: transparent;\n border: 1px solid ${props.theme.borderColor};\n\n &:hover {\n color: #fff;\n background-color: ${props.theme.textColor};\n border-color: ${props.theme.textColor};\n }\n\n &:focus {\n outline: none;\n box-shadow: 0 0 0 0.2rem ${props.theme.inputFocusBorder}33;\n }\n `;\n }\n}}\n`;\n\n// src/components/TrackControls/ButtonGroup.tsx\nimport styled23 from \"styled-components\";\nvar ButtonGroup = styled23.div`\n margin-bottom: 0.3rem;\n\n button:not(:first-child) {\n border-top-left-radius: 0;\n border-bottom-left-radius: 0;\n }\n\n button:not(:last-child) {\n border-top-right-radius: 0;\n border-bottom-right-radius: 0;\n }\n`;\n\n// src/components/TrackControls/Controls.tsx\nimport styled24 from \"styled-components\";\nvar Controls = styled24.div`\n background: transparent;\n width: 100%;\n height: 100%;\n display: flex;\n flex-direction: column;\n align-items: center;\n justify-content: flex-start;\n overflow: hidden;\n box-sizing: border-box;\n text-align: center;\n border: 1px solid ${(props) => props.theme.borderColor};\n border-radius: ${(props) => props.theme.borderRadius};\n`;\n\n// src/components/TrackControls/Header.tsx\nimport styled25 from \"styled-components\";\nvar Header = styled25.header`\n overflow: hidden;\n height: 26px;\n width: 100%;\n display: flex;\n align-items: center;\n justify-content: space-between;\n padding: 0 0.2rem;\n font-size: ${(props) => props.theme.fontSizeSmall};\n color: ${(props) => props.theme.textColor};\n background-color: transparent;\n`;\n\n// src/components/TrackControls/VolumeDownIcon.tsx\nimport { SpeakerLowIcon } from \"@phosphor-icons/react\";\nimport { jsx as jsx23 } from \"react/jsx-runtime\";\nvar VolumeDownIcon = (props) => /* @__PURE__ */ jsx23(SpeakerLowIcon, { weight: \"light\", ...props });\n\n// src/components/TrackControls/VolumeUpIcon.tsx\nimport { SpeakerHighIcon } from \"@phosphor-icons/react\";\nimport { jsx as jsx24 } from \"react/jsx-runtime\";\nvar VolumeUpIcon = (props) => /* @__PURE__ */ jsx24(SpeakerHighIcon, { weight: \"light\", ...props });\n\n// src/components/TrackControls/TrashIcon.tsx\nimport { TrashIcon as PhosphorTrashIcon } from \"@phosphor-icons/react\";\nimport { jsx as jsx25 } from \"react/jsx-runtime\";\nvar TrashIcon = (props) => /* @__PURE__ */ jsx25(PhosphorTrashIcon, { weight: \"light\", ...props });\n\n// src/components/TrackControls/Slider.tsx\nimport styled26 from \"styled-components\";\nvar Slider = styled26(BaseSlider)`\n width: 75%;\n height: 5px;\n background: ${(props) => props.theme.sliderTrackColor};\n\n &::-webkit-slider-thumb {\n width: 12px;\n height: 12px;\n background: ${(props) => props.theme.sliderThumbColor};\n border: none;\n margin-top: -4px;\n cursor: ew-resize;\n }\n\n &::-moz-range-thumb {\n width: 12px;\n height: 12px;\n background: ${(props) => props.theme.sliderThumbColor};\n border: none;\n cursor: ew-resize;\n }\n\n &::-webkit-slider-runnable-track {\n height: 5px;\n background: ${(props) => props.theme.sliderTrackColor};\n border-radius: 3px;\n }\n\n &::-moz-range-track {\n height: 5px;\n background: ${(props) => props.theme.sliderTrackColor};\n border-radius: 3px;\n }\n\n &:focus::-webkit-slider-runnable-track {\n background: ${(props) => props.theme.inputBorder};\n }\n\n &:focus::-moz-range-track {\n background: ${(props) => props.theme.inputBorder};\n }\n\n &:focus::-webkit-slider-thumb {\n border: 2px solid ${(props) => props.theme.textColor};\n }\n\n &:focus::-moz-range-thumb {\n border: 2px solid ${(props) => props.theme.textColor};\n }\n`;\n\n// src/components/TrackControls/SliderWrapper.tsx\nimport styled27 from \"styled-components\";\nvar SliderWrapper = styled27.label`\n width: 100%;\n display: flex;\n justify-content: space-between;\n align-items: center;\n padding: 0 1rem;\n margin-bottom: 0.2rem;\n font-size: 14px;\n`;\n\n// src/components/TrackControlsWithDelete.tsx\nimport styled28 from \"styled-components\";\nimport { jsx as jsx26, jsxs as jsxs11 } from \"react/jsx-runtime\";\nvar HeaderContainer2 = styled28.div`\n display: flex;\n align-items: center;\n gap: 0.25rem;\n padding: 0.5rem 0.5rem 0.25rem 0.5rem;\n`;\nvar TrackNameSpan = styled28.span`\n flex: 1;\n font-weight: 600;\n font-size: 0.875rem;\n overflow: hidden;\n text-overflow: ellipsis;\n white-space: nowrap;\n margin: 0 0.25rem;\n`;\nvar DeleteIconButton = styled28.button`\n display: flex;\n align-items: center;\n justify-content: center;\n width: 20px;\n height: 20px;\n padding: 0;\n border: none;\n background: transparent;\n color: #999;\n cursor: pointer;\n font-size: 16px;\n line-height: 1;\n border-radius: 3px;\n transition: all 0.2s ease-in-out;\n flex-shrink: 0;\n\n &:hover {\n background: #dc3545;\n color: white;\n }\n\n &:active {\n transform: scale(0.9);\n }\n`;\nvar TrackControlsWithDelete = ({\n trackName,\n muted,\n soloed,\n volume,\n pan,\n onMuteChange,\n onSoloChange,\n onVolumeChange,\n onPanChange,\n onDelete\n}) => {\n return /* @__PURE__ */ jsxs11(Controls, { children: [\n /* @__PURE__ */ jsxs11(HeaderContainer2, { children: [\n /* @__PURE__ */ jsx26(DeleteIconButton, { onClick: onDelete, title: \"Delete track\", children: /* @__PURE__ */ jsx26(TrashIcon, {}) }),\n /* @__PURE__ */ jsx26(TrackNameSpan, { children: trackName })\n ] }),\n /* @__PURE__ */ jsxs11(ButtonGroup, { children: [\n /* @__PURE__ */ jsx26(\n Button,\n {\n $variant: muted ? \"danger\" : \"outline\",\n onClick: () => onMuteChange(!muted),\n children: \"Mute\"\n }\n ),\n /* @__PURE__ */ jsx26(\n Button,\n {\n $variant: soloed ? \"info\" : \"outline\",\n onClick: () => onSoloChange(!soloed),\n children: \"Solo\"\n }\n )\n ] }),\n /* @__PURE__ */ jsxs11(SliderWrapper, { children: [\n /* @__PURE__ */ jsx26(VolumeDownIcon, {}),\n /* @__PURE__ */ jsx26(\n Slider,\n {\n min: \"0\",\n max: \"1\",\n step: \"0.01\",\n value: volume,\n onChange: (e) => onVolumeChange(parseFloat(e.target.value))\n }\n ),\n /* @__PURE__ */ jsx26(VolumeUpIcon, {})\n ] }),\n /* @__PURE__ */ jsxs11(SliderWrapper, { children: [\n /* @__PURE__ */ jsx26(\"span\", { children: \"L\" }),\n /* @__PURE__ */ jsx26(\n Slider,\n {\n min: \"-1\",\n max: \"1\",\n step: \"0.01\",\n value: pan,\n onChange: (e) => onPanChange(parseFloat(e.target.value))\n }\n ),\n /* @__PURE__ */ jsx26(\"span\", { children: \"R\" })\n ] })\n ] });\n};\nexport {\n AudioPosition,\n AutomaticScrollCheckbox,\n BaseButton,\n BaseCheckbox,\n BaseCheckboxLabel,\n BaseCheckboxWrapper,\n BaseControlButton,\n BaseInput,\n BaseLabel,\n BaseSelect,\n BaseSlider,\n Button,\n ButtonGroup,\n CLIP_BOUNDARY_WIDTH,\n CLIP_BOUNDARY_WIDTH_TOUCH,\n CLIP_HEADER_HEIGHT,\n Channel,\n Clip,\n ClipBoundary,\n ClipHeader,\n ClipHeaderPresentational,\n Controls,\n DevicePixelRatioProvider,\n FadeOverlay,\n Header,\n InlineLabel,\n LoopRegion,\n LoopRegionMarkers,\n MasterVolumeControl,\n Playhead,\n PlayheadWithMarker,\n Playlist,\n PlaylistInfoContext,\n PlayoutProvider,\n ScreenReaderOnly,\n Selection,\n SelectionTimeInputs,\n Slider,\n SliderWrapper,\n SmartChannel,\n SmartScale,\n StyledPlaylist,\n StyledTimeScale,\n TimeFormatSelect,\n TimeInput,\n TimeScale,\n TimescaleLoopRegion,\n Track,\n TrackControlsContext,\n TrackControlsWithDelete,\n TrashIcon,\n VolumeDownIcon,\n VolumeUpIcon,\n darkTheme,\n defaultTheme,\n formatTime,\n isWaveformGradient,\n parseTime,\n pixelsToSamples,\n pixelsToSeconds,\n samplesToPixels,\n samplesToSeconds,\n secondsToPixels,\n secondsToSamples,\n useDevicePixelRatio,\n usePlaylistInfo,\n usePlayoutStatus,\n usePlayoutStatusUpdate,\n useTheme2 as useTheme,\n useTrackControls,\n waveformColorToCss\n};\n//# sourceMappingURL=index.mjs.map","// src/index.ts\nfunction findMinMax(array) {\n let min = Infinity;\n let max = -Infinity;\n for (let i = 0; i < array.length; i++) {\n const curr = array[i];\n if (min > curr) {\n min = curr;\n }\n if (max < curr) {\n max = curr;\n }\n }\n return { min, max };\n}\nfunction convert(n, bits) {\n const maxValue = Math.pow(2, bits - 1);\n const v = n < 0 ? n * maxValue : n * (maxValue - 1);\n return Math.max(-maxValue, Math.min(maxValue - 1, v));\n}\nfunction makeTypedArray(bits, length) {\n switch (bits) {\n case 8:\n return new Int8Array(length);\n case 16:\n return new Int16Array(length);\n }\n}\nfunction extractPeaks(channel, samplesPerPixel, bits) {\n const chanLength = channel.length;\n const numPeaks = Math.ceil(chanLength / samplesPerPixel);\n const peaks = makeTypedArray(bits, numPeaks * 2);\n for (let i = 0; i < numPeaks; i++) {\n const start = i * samplesPerPixel;\n const end = Math.min((i + 1) * samplesPerPixel, chanLength);\n const segment = channel.subarray(start, end);\n const extrema = findMinMax(segment);\n const min = convert(extrema.min, bits);\n const max = convert(extrema.max, bits);\n peaks[i * 2] = min;\n peaks[i * 2 + 1] = max;\n }\n return peaks;\n}\nfunction makeMono(channelPeaks, bits) {\n const numChan = channelPeaks.length;\n const weight = 1 / numChan;\n const numPeaks = channelPeaks[0].length / 2;\n const peaks = makeTypedArray(bits, numPeaks * 2);\n for (let i = 0; i < numPeaks; i++) {\n let min = 0;\n let max = 0;\n for (let c = 0; c < numChan; c++) {\n min += weight * channelPeaks[c][i * 2];\n max += weight * channelPeaks[c][i * 2 + 1];\n }\n peaks[i * 2] = min;\n peaks[i * 2 + 1] = max;\n }\n return [peaks];\n}\nfunction extractPeaksFromBuffer(source, samplesPerPixel = 1e3, isMono = true, cueIn = 0, cueOut, bits = 16) {\n if (bits !== 8 && bits !== 16) {\n throw new Error(\"Invalid number of bits specified for peaks. Must be 8 or 16.\");\n }\n let peaks = [];\n if (\"getChannelData\" in source) {\n const numChan = source.numberOfChannels;\n const actualCueOut = cueOut ?? source.length;\n for (let c = 0; c < numChan; c++) {\n const channel = source.getChannelData(c);\n const slice = channel.subarray(cueIn, actualCueOut);\n peaks.push(extractPeaks(slice, samplesPerPixel, bits));\n }\n } else {\n const actualCueOut = cueOut ?? source.length;\n const slice = source.subarray(cueIn, actualCueOut);\n peaks.push(extractPeaks(slice, samplesPerPixel, bits));\n }\n if (isMono && peaks.length > 1) {\n peaks = makeMono(peaks, bits);\n }\n const numPeaks = peaks[0].length / 2;\n return {\n length: numPeaks,\n data: peaks,\n bits\n };\n}\nexport {\n extractPeaksFromBuffer as default\n};\n//# sourceMappingURL=index.mjs.map","import extractPeaks, { type PeakData } from '@waveform-playlist/webaudio-peaks';\n\n/**\n * Generate peaks from an AudioBuffer for waveform visualization\n * This is a thin wrapper around the webaudio-peaks package\n *\n * @param audioBuffer - The audio buffer to extract peaks from\n * @param samplesPerPixel - Number of samples per pixel\n * @param isMono - Whether to merge channels to mono\n * @param bits - Bit depth for peak data (8 or 16)\n * @param offsetSamples - Start offset in samples (for trimming)\n * @param durationSamples - Duration in samples (for trimming)\n */\nexport function generatePeaks(\n audioBuffer: AudioBuffer,\n samplesPerPixel: number = 1000,\n isMono: boolean = true,\n bits: 8 | 16 = 8,\n offsetSamples: number = 0,\n durationSamples?: number\n): PeakData {\n // Calculate cueOut from offset + duration (both in samples)\n const cueOut = durationSamples !== undefined\n ? offsetSamples + durationSamples\n : undefined;\n\n return extractPeaks(audioBuffer, samplesPerPixel, isMono, offsetSamples, cueOut, bits);\n}\n","/**\n * Provides access to the waveform data for a single audio channel.\n */\n\nfunction WaveformDataChannel(waveformData, channelIndex) {\n this._waveformData = waveformData;\n this._channelIndex = channelIndex;\n}\n\n/**\n * Returns the waveform minimum at the given index position.\n */\n\nWaveformDataChannel.prototype.min_sample = function (index) {\n var offset = (index * this._waveformData.channels + this._channelIndex) * 2;\n return this._waveformData._at(offset);\n};\n\n/**\n * Returns the waveform maximum at the given index position.\n */\n\nWaveformDataChannel.prototype.max_sample = function (index) {\n var offset = (index * this._waveformData.channels + this._channelIndex) * 2 + 1;\n return this._waveformData._at(offset);\n};\n\n/**\n * Sets the waveform minimum at the given index position.\n */\n\nWaveformDataChannel.prototype.set_min_sample = function (index, sample) {\n var offset = (index * this._waveformData.channels + this._channelIndex) * 2;\n return this._waveformData._set_at(offset, sample);\n};\n\n/**\n * Sets the waveform maximum at the given index position.\n */\n\nWaveformDataChannel.prototype.set_max_sample = function (index, sample) {\n var offset = (index * this._waveformData.channels + this._channelIndex) * 2 + 1;\n return this._waveformData._set_at(offset, sample);\n};\n\n/**\n * Returns all the waveform minimum values as an array.\n */\n\nWaveformDataChannel.prototype.min_array = function () {\n var length = this._waveformData.length;\n var values = [];\n for (var i = 0; i < length; i++) {\n values.push(this.min_sample(i));\n }\n return values;\n};\n\n/**\n * Returns all the waveform maximum values as an array.\n */\n\nWaveformDataChannel.prototype.max_array = function () {\n var length = this._waveformData.length;\n var values = [];\n for (var i = 0; i < length; i++) {\n values.push(this.max_sample(i));\n }\n return values;\n};\n\n/**\n * AudioBuffer-based WaveformData generator\n *\n * Adapted from BlockFile::CalcSummary in Audacity, with permission.\n * See https://github.com/audacity/audacity/blob/\n * 1108c1376c09166162335fab4743008cba57c4ee/src/BlockFile.cpp#L198\n */\n\nvar INT8_MAX = 127;\nvar INT8_MIN = -128;\nvar INT16_MAX = 32767;\nvar INT16_MIN = -32768;\nfunction calculateWaveformDataLength(audio_sample_count, scale) {\n var data_length = Math.floor(audio_sample_count / scale);\n var samples_remaining = audio_sample_count - data_length * scale;\n if (samples_remaining > 0) {\n data_length++;\n }\n return data_length;\n}\nfunction generateWaveformData(options) {\n var scale = options.scale;\n var amplitude_scale = options.amplitude_scale;\n var split_channels = options.split_channels;\n var length = options.length;\n var sample_rate = options.sample_rate;\n var channels = options.channels.map(function (channel) {\n return new Float32Array(channel);\n });\n var output_channels = split_channels ? channels.length : 1;\n var header_size = 24;\n var data_length = calculateWaveformDataLength(length, scale);\n var bytes_per_sample = options.bits === 8 ? 1 : 2;\n var total_size = header_size + data_length * 2 * bytes_per_sample * output_channels;\n var buffer = new ArrayBuffer(total_size);\n var data_view = new DataView(buffer);\n var scale_counter = 0;\n var offset = header_size;\n var min_value = new Array(output_channels);\n var max_value = new Array(output_channels);\n for (var channel = 0; channel < output_channels; channel++) {\n min_value[channel] = Infinity;\n max_value[channel] = -Infinity;\n }\n var range_min = options.bits === 8 ? INT8_MIN : INT16_MIN;\n var range_max = options.bits === 8 ? INT8_MAX : INT16_MAX;\n data_view.setInt32(0, 2, true); // Version\n data_view.setUint32(4, options.bits === 8, true); // Is 8 bit?\n data_view.setInt32(8, sample_rate, true); // Sample rate\n data_view.setInt32(12, scale, true); // Scale\n data_view.setInt32(16, data_length, true); // Length\n data_view.setInt32(20, output_channels, true);\n for (var i = 0; i < length; i++) {\n var sample = 0;\n if (output_channels === 1) {\n for (var _channel = 0; _channel < channels.length; ++_channel) {\n sample += channels[_channel][i];\n }\n sample = Math.floor(range_max * sample * amplitude_scale / channels.length);\n if (sample < min_value[0]) {\n min_value[0] = sample;\n if (min_value[0] < range_min) {\n min_value[0] = range_min;\n }\n }\n if (sample > max_value[0]) {\n max_value[0] = sample;\n if (max_value[0] > range_max) {\n max_value[0] = range_max;\n }\n }\n } else {\n for (var _channel2 = 0; _channel2 < output_channels; ++_channel2) {\n sample = Math.floor(range_max * channels[_channel2][i] * amplitude_scale);\n if (sample < min_value[_channel2]) {\n min_value[_channel2] = sample;\n if (min_value[_channel2] < range_min) {\n min_value[_channel2] = range_min;\n }\n }\n if (sample > max_value[_channel2]) {\n max_value[_channel2] = sample;\n if (max_value[_channel2] > range_max) {\n max_value[_channel2] = range_max;\n }\n }\n }\n }\n if (++scale_counter === scale) {\n for (var _channel3 = 0; _channel3 < output_channels; _channel3++) {\n if (options.bits === 8) {\n data_view.setInt8(offset++, min_value[_channel3]);\n data_view.setInt8(offset++, max_value[_channel3]);\n } else {\n data_view.setInt16(offset, min_value[_channel3], true);\n data_view.setInt16(offset + 2, max_value[_channel3], true);\n offset += 4;\n }\n min_value[_channel3] = Infinity;\n max_value[_channel3] = -Infinity;\n }\n scale_counter = 0;\n }\n }\n if (scale_counter > 0) {\n for (var _channel4 = 0; _channel4 < output_channels; _channel4++) {\n if (options.bits === 8) {\n data_view.setInt8(offset++, min_value[_channel4]);\n data_view.setInt8(offset++, max_value[_channel4]);\n } else {\n data_view.setInt16(offset, min_value[_channel4], true);\n data_view.setInt16(offset + 2, max_value[_channel4], true);\n }\n }\n }\n return buffer;\n}\n\nfunction _typeof(o) {\n \"@babel/helpers - typeof\";\n\n return _typeof = \"function\" == typeof Symbol && \"symbol\" == typeof Symbol.iterator ? function (o) {\n return typeof o;\n } : function (o) {\n return o && \"function\" == typeof Symbol && o.constructor === Symbol && o !== Symbol.prototype ? \"symbol\" : typeof o;\n }, _typeof(o);\n}\n\nfunction isJsonWaveformData(data) {\n return data && _typeof(data) === 'object' && 'sample_rate' in data && 'samples_per_pixel' in data && 'bits' in data && 'length' in data && 'data' in data;\n}\nfunction isBinaryWaveformData(data) {\n var isCompatible = data && _typeof(data) === 'object' && 'byteLength' in data;\n if (isCompatible) {\n var view = new DataView(data);\n var version = view.getInt32(0, true);\n if (version !== 1 && version !== 2) {\n throw new TypeError('WaveformData.create(): This waveform data version not supported');\n }\n }\n return isCompatible;\n}\nfunction convertJsonToBinary(data) {\n var waveformData = data.data;\n var channels = data.channels || 1;\n var header_size = 24; // version 2\n var bytes_per_sample = data.bits === 8 ? 1 : 2;\n var expected_length = data.length * 2 * channels;\n if (waveformData.length !== expected_length) {\n throw new Error('WaveformData.create(): Length mismatch in JSON waveform data');\n }\n var total_size = header_size + waveformData.length * bytes_per_sample;\n var array_buffer = new ArrayBuffer(total_size);\n var data_object = new DataView(array_buffer);\n data_object.setInt32(0, 2, true); // Version\n data_object.setUint32(4, data.bits === 8, true);\n data_object.setInt32(8, data.sample_rate, true);\n data_object.setInt32(12, data.samples_per_pixel, true);\n data_object.setInt32(16, data.length, true);\n data_object.setInt32(20, channels, true);\n var index = header_size;\n if (data.bits === 8) {\n for (var i = 0; i < waveformData.length; i++) {\n data_object.setInt8(index++, waveformData[i], true);\n }\n } else {\n for (var _i = 0; _i < waveformData.length; _i++) {\n data_object.setInt16(index, waveformData[_i], true);\n index += 2;\n }\n }\n return array_buffer;\n}\n\nfunction isNullOrUndefined(value) {\n return value === undefined || value === null;\n}\n\nfunction decodeBase64(base64, enableUnicode) {\n var binaryString = atob(base64);\n if (enableUnicode) {\n var binaryView = new Uint8Array(binaryString.length);\n for (var i = 0, n = binaryString.length; i < n; ++i) {\n binaryView[i] = binaryString.charCodeAt(i);\n }\n return String.fromCharCode.apply(null, new Uint16Array(binaryView.buffer));\n }\n return binaryString;\n}\n\nfunction createURL(base64, sourcemapArg, enableUnicodeArg) {\n var sourcemap = sourcemapArg === undefined ? null : sourcemapArg;\n var enableUnicode = enableUnicodeArg === undefined ? false : enableUnicodeArg;\n var source = decodeBase64(base64, enableUnicode);\n var start = source.indexOf('\\n', 10) + 1;\n var body = source.substring(start) + (sourcemap ? '\\/\\/# sourceMappingURL=' + sourcemap : '');\n var blob = new Blob([body], { type: 'application/javascript' });\n return URL.createObjectURL(blob);\n}\n\nfunction createBase64WorkerFactory(base64, sourcemapArg, enableUnicodeArg) {\n var url;\n return function WorkerFactory(options) {\n url = url || createURL(base64, sourcemapArg, enableUnicodeArg);\n return new Worker(url, options);\n };\n}\n\nvar WorkerFactory = /*#__PURE__*/createBase64WorkerFactory('Lyogcm9sbHVwLXBsdWdpbi13ZWItd29ya2VyLWxvYWRlciAqLwooZnVuY3Rpb24gKCkgewogICd1c2Ugc3RyaWN0JzsKCiAgLyoqCiAgICogQXVkaW9CdWZmZXItYmFzZWQgV2F2ZWZvcm1EYXRhIGdlbmVyYXRvcgogICAqCiAgICogQWRhcHRlZCBmcm9tIEJsb2NrRmlsZTo6Q2FsY1N1bW1hcnkgaW4gQXVkYWNpdHksIHdpdGggcGVybWlzc2lvbi4KICAgKiBTZWUgaHR0cHM6Ly9naXRodWIuY29tL2F1ZGFjaXR5L2F1ZGFjaXR5L2Jsb2IvCiAgICogICAxMTA4YzEzNzZjMDkxNjYxNjIzMzVmYWI0NzQzMDA4Y2JhNTdjNGVlL3NyYy9CbG9ja0ZpbGUuY3BwI0wxOTgKICAgKi8KCiAgdmFyIElOVDhfTUFYID0gMTI3OwogIHZhciBJTlQ4X01JTiA9IC0xMjg7CiAgdmFyIElOVDE2X01BWCA9IDMyNzY3OwogIHZhciBJTlQxNl9NSU4gPSAtMzI3Njg7CiAgZnVuY3Rpb24gY2FsY3VsYXRlV2F2ZWZvcm1EYXRhTGVuZ3RoKGF1ZGlvX3NhbXBsZV9jb3VudCwgc2NhbGUpIHsKICAgIHZhciBkYXRhX2xlbmd0aCA9IE1hdGguZmxvb3IoYXVkaW9fc2FtcGxlX2NvdW50IC8gc2NhbGUpOwogICAgdmFyIHNhbXBsZXNfcmVtYWluaW5nID0gYXVkaW9fc2FtcGxlX2NvdW50IC0gZGF0YV9sZW5ndGggKiBzY2FsZTsKICAgIGlmIChzYW1wbGVzX3JlbWFpbmluZyA+IDApIHsKICAgICAgZGF0YV9sZW5ndGgrKzsKICAgIH0KICAgIHJldHVybiBkYXRhX2xlbmd0aDsKICB9CiAgZnVuY3Rpb24gZ2VuZXJhdGVXYXZlZm9ybURhdGEob3B0aW9ucykgewogICAgdmFyIHNjYWxlID0gb3B0aW9ucy5zY2FsZTsKICAgIHZhciBhbXBsaXR1ZGVfc2NhbGUgPSBvcHRpb25zLmFtcGxpdHVkZV9zY2FsZTsKICAgIHZhciBzcGxpdF9jaGFubmVscyA9IG9wdGlvbnMuc3BsaXRfY2hhbm5lbHM7CiAgICB2YXIgbGVuZ3RoID0gb3B0aW9ucy5sZW5ndGg7CiAgICB2YXIgc2FtcGxlX3JhdGUgPSBvcHRpb25zLnNhbXBsZV9yYXRlOwogICAgdmFyIGNoYW5uZWxzID0gb3B0aW9ucy5jaGFubmVscy5tYXAoZnVuY3Rpb24gKGNoYW5uZWwpIHsKICAgICAgcmV0dXJuIG5ldyBGbG9hdDMyQXJyYXkoY2hhbm5lbCk7CiAgICB9KTsKICAgIHZhciBvdXRwdXRfY2hhbm5lbHMgPSBzcGxpdF9jaGFubmVscyA/IGNoYW5uZWxzLmxlbmd0aCA6IDE7CiAgICB2YXIgaGVhZGVyX3NpemUgPSAyNDsKICAgIHZhciBkYXRhX2xlbmd0aCA9IGNhbGN1bGF0ZVdhdmVmb3JtRGF0YUxlbmd0aChsZW5ndGgsIHNjYWxlKTsKICAgIHZhciBieXRlc19wZXJfc2FtcGxlID0gb3B0aW9ucy5iaXRzID09PSA4ID8gMSA6IDI7CiAgICB2YXIgdG90YWxfc2l6ZSA9IGhlYWRlcl9zaXplICsgZGF0YV9sZW5ndGggKiAyICogYnl0ZXNfcGVyX3NhbXBsZSAqIG91dHB1dF9jaGFubmVsczsKICAgIHZhciBidWZmZXIgPSBuZXcgQXJyYXlCdWZmZXIodG90YWxfc2l6ZSk7CiAgICB2YXIgZGF0YV92aWV3ID0gbmV3IERhdGFWaWV3KGJ1ZmZlcik7CiAgICB2YXIgc2NhbGVfY291bnRlciA9IDA7CiAgICB2YXIgb2Zmc2V0ID0gaGVhZGVyX3NpemU7CiAgICB2YXIgbWluX3ZhbHVlID0gbmV3IEFycmF5KG91dHB1dF9jaGFubmVscyk7CiAgICB2YXIgbWF4X3ZhbHVlID0gbmV3IEFycmF5KG91dHB1dF9jaGFubmVscyk7CiAgICBmb3IgKHZhciBjaGFubmVsID0gMDsgY2hhbm5lbCA8IG91dHB1dF9jaGFubmVsczsgY2hhbm5lbCsrKSB7CiAgICAgIG1pbl92YWx1ZVtjaGFubmVsXSA9IEluZmluaXR5OwogICAgICBtYXhfdmFsdWVbY2hhbm5lbF0gPSAtSW5maW5pdHk7CiAgICB9CiAgICB2YXIgcmFuZ2VfbWluID0gb3B0aW9ucy5iaXRzID09PSA4ID8gSU5UOF9NSU4gOiBJTlQxNl9NSU47CiAgICB2YXIgcmFuZ2VfbWF4ID0gb3B0aW9ucy5iaXRzID09PSA4ID8gSU5UOF9NQVggOiBJTlQxNl9NQVg7CiAgICBkYXRhX3ZpZXcuc2V0SW50MzIoMCwgMiwgdHJ1ZSk7IC8vIFZlcnNpb24KICAgIGRhdGFfdmlldy5zZXRVaW50MzIoNCwgb3B0aW9ucy5iaXRzID09PSA4LCB0cnVlKTsgLy8gSXMgOCBiaXQ/CiAgICBkYXRhX3ZpZXcuc2V0SW50MzIoOCwgc2FtcGxlX3JhdGUsIHRydWUpOyAvLyBTYW1wbGUgcmF0ZQogICAgZGF0YV92aWV3LnNldEludDMyKDEyLCBzY2FsZSwgdHJ1ZSk7IC8vIFNjYWxlCiAgICBkYXRhX3ZpZXcuc2V0SW50MzIoMTYsIGRhdGFfbGVuZ3RoLCB0cnVlKTsgLy8gTGVuZ3RoCiAgICBkYXRhX3ZpZXcuc2V0SW50MzIoMjAsIG91dHB1dF9jaGFubmVscywgdHJ1ZSk7CiAgICBmb3IgKHZhciBpID0gMDsgaSA8IGxlbmd0aDsgaSsrKSB7CiAgICAgIHZhciBzYW1wbGUgPSAwOwogICAgICBpZiAob3V0cHV0X2NoYW5uZWxzID09PSAxKSB7CiAgICAgICAgZm9yICh2YXIgX2NoYW5uZWwgPSAwOyBfY2hhbm5lbCA8IGNoYW5uZWxzLmxlbmd0aDsgKytfY2hhbm5lbCkgewogICAgICAgICAgc2FtcGxlICs9IGNoYW5uZWxzW19jaGFubmVsXVtpXTsKICAgICAgICB9CiAgICAgICAgc2FtcGxlID0gTWF0aC5mbG9vcihyYW5nZV9tYXggKiBzYW1wbGUgKiBhbXBsaXR1ZGVfc2NhbGUgLyBjaGFubmVscy5sZW5ndGgpOwogICAgICAgIGlmIChzYW1wbGUgPCBtaW5fdmFsdWVbMF0pIHsKICAgICAgICAgIG1pbl92YWx1ZVswXSA9IHNhbXBsZTsKICAgICAgICAgIGlmIChtaW5fdmFsdWVbMF0gPCByYW5nZV9taW4pIHsKICAgICAgICAgICAgbWluX3ZhbHVlWzBdID0gcmFuZ2VfbWluOwogICAgICAgICAgfQogICAgICAgIH0KICAgICAgICBpZiAoc2FtcGxlID4gbWF4X3ZhbHVlWzBdKSB7CiAgICAgICAgICBtYXhfdmFsdWVbMF0gPSBzYW1wbGU7CiAgICAgICAgICBpZiAobWF4X3ZhbHVlWzBdID4gcmFuZ2VfbWF4KSB7CiAgICAgICAgICAgIG1heF92YWx1ZVswXSA9IHJhbmdlX21heDsKICAgICAgICAgIH0KICAgICAgICB9CiAgICAgIH0gZWxzZSB7CiAgICAgICAgZm9yICh2YXIgX2NoYW5uZWwyID0gMDsgX2NoYW5uZWwyIDwgb3V0cHV0X2NoYW5uZWxzOyArK19jaGFubmVsMikgewogICAgICAgICAgc2FtcGxlID0gTWF0aC5mbG9vcihyYW5nZV9tYXggKiBjaGFubmVsc1tfY2hhbm5lbDJdW2ldICogYW1wbGl0dWRlX3NjYWxlKTsKICAgICAgICAgIGlmIChzYW1wbGUgPCBtaW5fdmFsdWVbX2NoYW5uZWwyXSkgewogICAgICAgICAgICBtaW5fdmFsdWVbX2NoYW5uZWwyXSA9IHNhbXBsZTsKICAgICAgICAgICAgaWYgKG1pbl92YWx1ZVtfY2hhbm5lbDJdIDwgcmFuZ2VfbWluKSB7CiAgICAgICAgICAgICAgbWluX3ZhbHVlW19jaGFubmVsMl0gPSByYW5nZV9taW47CiAgICAgICAgICAgIH0KICAgICAgICAgIH0KICAgICAgICAgIGlmIChzYW1wbGUgPiBtYXhfdmFsdWVbX2NoYW5uZWwyXSkgewogICAgICAgICAgICBtYXhfdmFsdWVbX2NoYW5uZWwyXSA9IHNhbXBsZTsKICAgICAgICAgICAgaWYgKG1heF92YWx1ZVtfY2hhbm5lbDJdID4gcmFuZ2VfbWF4KSB7CiAgICAgICAgICAgICAgbWF4X3ZhbHVlW19jaGFubmVsMl0gPSByYW5nZV9tYXg7CiAgICAgICAgICAgIH0KICAgICAgICAgIH0KICAgICAgICB9CiAgICAgIH0KICAgICAgaWYgKCsrc2NhbGVfY291bnRlciA9PT0gc2NhbGUpIHsKICAgICAgICBmb3IgKHZhciBfY2hhbm5lbDMgPSAwOyBfY2hhbm5lbDMgPCBvdXRwdXRfY2hhbm5lbHM7IF9jaGFubmVsMysrKSB7CiAgICAgICAgICBpZiAob3B0aW9ucy5iaXRzID09PSA4KSB7CiAgICAgICAgICAgIGRhdGFfdmlldy5zZXRJbnQ4KG9mZnNldCsrLCBtaW5fdmFsdWVbX2NoYW5uZWwzXSk7CiAgICAgICAgICAgIGRhdGFfdmlldy5zZXRJbnQ4KG9mZnNldCsrLCBtYXhfdmFsdWVbX2NoYW5uZWwzXSk7CiAgICAgICAgICB9IGVsc2UgewogICAgICAgICAgICBkYXRhX3ZpZXcuc2V0SW50MTYob2Zmc2V0LCBtaW5fdmFsdWVbX2NoYW5uZWwzXSwgdHJ1ZSk7CiAgICAgICAgICAgIGRhdGFfdmlldy5zZXRJbnQxNihvZmZzZXQgKyAyLCBtYXhfdmFsdWVbX2NoYW5uZWwzXSwgdHJ1ZSk7CiAgICAgICAgICAgIG9mZnNldCArPSA0OwogICAgICAgICAgfQogICAgICAgICAgbWluX3ZhbHVlW19jaGFubmVsM10gPSBJbmZpbml0eTsKICAgICAgICAgIG1heF92YWx1ZVtfY2hhbm5lbDNdID0gLUluZmluaXR5OwogICAgICAgIH0KICAgICAgICBzY2FsZV9jb3VudGVyID0gMDsKICAgICAgfQogICAgfQogICAgaWYgKHNjYWxlX2NvdW50ZXIgPiAwKSB7CiAgICAgIGZvciAodmFyIF9jaGFubmVsNCA9IDA7IF9jaGFubmVsNCA8IG91dHB1dF9jaGFubmVsczsgX2NoYW5uZWw0KyspIHsKICAgICAgICBpZiAob3B0aW9ucy5iaXRzID09PSA4KSB7CiAgICAgICAgICBkYXRhX3ZpZXcuc2V0SW50OChvZmZzZXQrKywgbWluX3ZhbHVlW19jaGFubmVsNF0pOwogICAgICAgICAgZGF0YV92aWV3LnNldEludDgob2Zmc2V0KyssIG1heF92YWx1ZVtfY2hhbm5lbDRdKTsKICAgICAgICB9IGVsc2UgewogICAgICAgICAgZGF0YV92aWV3LnNldEludDE2KG9mZnNldCwgbWluX3ZhbHVlW19jaGFubmVsNF0sIHRydWUpOwogICAgICAgICAgZGF0YV92aWV3LnNldEludDE2KG9mZnNldCArIDIsIG1heF92YWx1ZVtfY2hhbm5lbDRdLCB0cnVlKTsKICAgICAgICB9CiAgICAgIH0KICAgIH0KICAgIHJldHVybiBidWZmZXI7CiAgfQoKICBvbm1lc3NhZ2UgPSBmdW5jdGlvbiBvbm1lc3NhZ2UoZXZ0KSB7CiAgICB2YXIgYnVmZmVyID0gZ2VuZXJhdGVXYXZlZm9ybURhdGEoZXZ0LmRhdGEpOwoKICAgIC8vIFRyYW5zZmVyIGJ1ZmZlciB0byB0aGUgY2FsbGluZyB0aHJlYWQKICAgIHRoaXMucG9zdE1lc3NhZ2UoYnVmZmVyLCBbYnVmZmVyXSk7CiAgICB0aGlzLmNsb3NlKCk7CiAgfTsKCn0pKCk7Ci8vIyBzb3VyY2VNYXBwaW5nVVJMPXdhdmVmb3JtLWRhdGEtd29ya2VyLmpzLm1hcAoK', null, false);\n/* eslint-enable */\n\n/**\n * Provides access to waveform data.\n */\n\nfunction WaveformData(data) {\n if (isJsonWaveformData(data)) {\n data = convertJsonToBinary(data);\n }\n if (isBinaryWaveformData(data)) {\n this._data = new DataView(data);\n this._offset = this._version() === 2 ? 24 : 20;\n this._channels = [];\n for (var channel = 0; channel < this.channels; channel++) {\n this._channels[channel] = new WaveformDataChannel(this, channel);\n }\n } else {\n throw new TypeError('WaveformData.create(): Unknown data format');\n }\n}\nvar defaultOptions = {\n scale: 512,\n bits: 8,\n amplitude_scale: 1.0,\n split_channels: false,\n disable_worker: false\n};\nfunction getOptions(options) {\n var opts = {\n scale: options.scale || defaultOptions.scale,\n bits: options.bits || defaultOptions.bits,\n amplitude_scale: options.amplitude_scale || defaultOptions.amplitude_scale,\n split_channels: options.split_channels || defaultOptions.split_channels,\n disable_worker: options.disable_worker || defaultOptions.disable_worker\n };\n return opts;\n}\nfunction getChannelData(audio_buffer) {\n var channels = [];\n for (var i = 0; i < audio_buffer.numberOfChannels; ++i) {\n channels.push(audio_buffer.getChannelData(i).buffer);\n }\n return channels;\n}\nfunction createFromAudioBuffer(audio_buffer, options, callback) {\n var channels = getChannelData(audio_buffer);\n if (options.disable_worker) {\n var buffer = generateWaveformData({\n scale: options.scale,\n bits: options.bits,\n amplitude_scale: options.amplitude_scale,\n split_channels: options.split_channels,\n length: audio_buffer.length,\n sample_rate: audio_buffer.sampleRate,\n channels: channels\n });\n callback(undefined, new WaveformData(buffer), audio_buffer);\n } else {\n var worker = new WorkerFactory();\n worker.onmessage = function (evt) {\n callback(undefined, new WaveformData(evt.data), audio_buffer);\n };\n worker.postMessage({\n scale: options.scale,\n bits: options.bits,\n amplitude_scale: options.amplitude_scale,\n split_channels: options.split_channels,\n length: audio_buffer.length,\n sample_rate: audio_buffer.sampleRate,\n channels: channels\n }, channels);\n }\n}\nfunction createFromArrayBuffer(audioContext, audioData, options, callback) {\n // The following function is a workaround for a Webkit bug where decodeAudioData\n // invokes the errorCallback with null instead of a DOMException.\n // See https://webaudio.github.io/web-audio-api/#dom-baseaudiocontext-decodeaudiodata\n // and http://stackoverflow.com/q/10365335/103396\n\n function errorCallback(error) {\n if (!error) {\n error = new DOMException('EncodingError');\n }\n callback(error);\n // prevent double-calling the callback on errors:\n callback = function callback() {};\n }\n var promise = audioContext.decodeAudioData(audioData, function (audio_buffer) {\n createFromAudioBuffer(audio_buffer, options, callback);\n }, errorCallback);\n if (promise) {\n promise.catch(errorCallback);\n }\n}\n\n/**\n * Creates and returns a WaveformData instance from the given waveform data.\n */\n\nWaveformData.create = function create(data) {\n return new WaveformData(data);\n};\n\n/**\n * Creates a WaveformData instance from audio.\n */\n\nWaveformData.createFromAudio = function (options, callback) {\n var opts = getOptions(options);\n if (options.audio_context && options.array_buffer) {\n return createFromArrayBuffer(options.audio_context, options.array_buffer, opts, callback);\n } else if (options.audio_buffer) {\n return createFromAudioBuffer(options.audio_buffer, opts, callback);\n } else {\n throw new TypeError(\n // eslint-disable-next-line\n 'WaveformData.createFromAudio(): Pass either an AudioContext and ArrayBuffer, or an AudioBuffer object');\n }\n};\nfunction WaveformResampler(options) {\n this._inputData = options.waveformData;\n\n // Scale we want to reach\n this._output_samples_per_pixel = options.scale;\n this._scale = this._inputData.scale; // scale we are coming from\n\n // The amount of data we want to resample i.e. final zoom want to resample\n // all data but for intermediate zoom we want to resample subset\n this._input_buffer_size = this._inputData.length;\n var input_buffer_length_samples = this._input_buffer_size * this._inputData.scale;\n var output_buffer_length_samples = Math.ceil(input_buffer_length_samples / this._output_samples_per_pixel);\n var output_header_size = 24; // version 2\n var bytes_per_sample = this._inputData.bits === 8 ? 1 : 2;\n var total_size = output_header_size + output_buffer_length_samples * 2 * this._inputData.channels * bytes_per_sample;\n this._output_data = new ArrayBuffer(total_size);\n this.output_dataview = new DataView(this._output_data);\n this.output_dataview.setInt32(0, 2, true); // Version\n this.output_dataview.setUint32(4, this._inputData.bits === 8, true); // Is 8 bit?\n this.output_dataview.setInt32(8, this._inputData.sample_rate, true);\n this.output_dataview.setInt32(12, this._output_samples_per_pixel, true);\n this.output_dataview.setInt32(16, output_buffer_length_samples, true);\n this.output_dataview.setInt32(20, this._inputData.channels, true);\n this._outputWaveformData = new WaveformData(this._output_data);\n this._input_index = 0;\n this._output_index = 0;\n var channels = this._inputData.channels;\n this._min = new Array(channels);\n this._max = new Array(channels);\n for (var channel = 0; channel < channels; ++channel) {\n if (this._input_buffer_size > 0) {\n this._min[channel] = this._inputData.channel(channel).min_sample(this._input_index);\n this._max[channel] = this._inputData.channel(channel).max_sample(this._input_index);\n } else {\n this._min[channel] = 0;\n this._max[channel] = 0;\n }\n }\n this._min_value = this._inputData.bits === 8 ? -128 : -32768;\n this._max_value = this._inputData.bits === 8 ? 127 : 32767;\n this._where = 0;\n this._prev_where = 0;\n this._stop = 0;\n this._last_input_index = 0;\n}\nWaveformResampler.prototype.sample_at_pixel = function (x) {\n return Math.floor(x * this._output_samples_per_pixel);\n};\nWaveformResampler.prototype.next = function () {\n var count = 0;\n var total = 1000;\n var channels = this._inputData.channels;\n var channel;\n while (this._input_index < this._input_buffer_size && count < total) {\n while (Math.floor(this.sample_at_pixel(this._output_index) / this._scale) === this._input_index) {\n if (this._output_index > 0) {\n for (var i = 0; i < channels; ++i) {\n channel = this._outputWaveformData.channel(i);\n channel.set_min_sample(this._output_index - 1, this._min[i]);\n channel.set_max_sample(this._output_index - 1, this._max[i]);\n }\n }\n this._last_input_index = this._input_index;\n this._output_index++;\n this._where = this.sample_at_pixel(this._output_index);\n this._prev_where = this.sample_at_pixel(this._output_index - 1);\n if (this._where !== this._prev_where) {\n for (var _i = 0; _i < channels; ++_i) {\n this._min[_i] = this._max_value;\n this._max[_i] = this._min_value;\n }\n }\n }\n this._where = this.sample_at_pixel(this._output_index);\n this._stop = Math.floor(this._where / this._scale);\n if (this._stop > this._input_buffer_size) {\n this._stop = this._input_buffer_size;\n }\n while (this._input_index < this._stop) {\n for (var _i2 = 0; _i2 < channels; ++_i2) {\n channel = this._inputData.channel(_i2);\n var value = channel.min_sample(this._input_index);\n if (value < this._min[_i2]) {\n this._min[_i2] = value;\n }\n value = channel.max_sample(this._input_index);\n if (value > this._max[_i2]) {\n this._max[_i2] = value;\n }\n }\n this._input_index++;\n }\n count++;\n }\n if (this._input_index < this._input_buffer_size) {\n // More to do\n return false;\n } else {\n // Done\n if (this._input_index !== this._last_input_index) {\n for (var _i3 = 0; _i3 < channels; ++_i3) {\n channel = this._outputWaveformData.channel(_i3);\n channel.set_min_sample(this._output_index - 1, this._min[_i3]);\n channel.set_max_sample(this._output_index - 1, this._max[_i3]);\n }\n }\n return true;\n }\n};\nWaveformResampler.prototype.getOutputData = function () {\n return this._output_data;\n};\nWaveformData.prototype = {\n _getResampleOptions: function _getResampleOptions(options) {\n var opts = {};\n opts.scale = options.scale;\n opts.width = options.width;\n if (!isNullOrUndefined(opts.width) && (typeof opts.width !== 'number' || opts.width <= 0)) {\n throw new RangeError('WaveformData.resample(): width should be a positive integer value');\n }\n if (!isNullOrUndefined(opts.scale) && (typeof opts.scale !== 'number' || opts.scale <= 0)) {\n throw new RangeError('WaveformData.resample(): scale should be a positive integer value');\n }\n if (!opts.scale && !opts.width) {\n throw new Error('WaveformData.resample(): Missing scale or width option');\n }\n if (opts.width) {\n // Calculate the target scale for the resampled waveform\n opts.scale = Math.floor(this.duration * this.sample_rate / opts.width);\n }\n if (opts.scale < this.scale) {\n throw new Error('WaveformData.resample(): Zoom level ' + opts.scale + ' too low, minimum: ' + this.scale);\n }\n opts.abortSignal = options.abortSignal;\n return opts;\n },\n resample: function resample(options) {\n options = this._getResampleOptions(options);\n options.waveformData = this;\n var resampler = new WaveformResampler(options);\n while (!resampler.next()) {\n // nothing\n }\n return new WaveformData(resampler.getOutputData());\n },\n /**\n * Concatenates with one or more other waveforms, returning a new WaveformData object.\n */\n\n concat: function concat() {\n var self = this;\n var otherWaveforms = Array.prototype.slice.call(arguments);\n\n // Check that all the supplied waveforms are compatible\n otherWaveforms.forEach(function (otherWaveform) {\n if (self.channels !== otherWaveform.channels || self.sample_rate !== otherWaveform.sample_rate || self.bits !== otherWaveform.bits || self.scale !== otherWaveform.scale) {\n throw new Error('WaveformData.concat(): Waveforms are incompatible');\n }\n });\n var combinedBuffer = this._concatBuffers.apply(this, otherWaveforms);\n return WaveformData.create(combinedBuffer);\n },\n /**\n * Returns a new ArrayBuffer with the concatenated waveform.\n * All waveforms must have identical metadata (version, channels, etc)\n */\n\n _concatBuffers: function _concatBuffers() {\n var otherWaveforms = Array.prototype.slice.call(arguments);\n var headerSize = this._offset;\n var totalSize = headerSize;\n var totalDataLength = 0;\n var bufferCollection = [this].concat(otherWaveforms).map(function (w) {\n return w._data.buffer;\n });\n for (var i = 0; i < bufferCollection.length; i++) {\n var buffer = bufferCollection[i];\n var dataSize = new DataView(buffer).getInt32(16, true);\n totalSize += buffer.byteLength - headerSize;\n totalDataLength += dataSize;\n }\n var totalBuffer = new ArrayBuffer(totalSize);\n var sourceHeader = new DataView(bufferCollection[0]);\n var totalBufferView = new DataView(totalBuffer);\n\n // Copy the header from the first chunk\n for (var _i4 = 0; _i4 < headerSize; _i4++) {\n totalBufferView.setUint8(_i4, sourceHeader.getUint8(_i4));\n }\n\n // Rewrite the data-length header item to reflect all of the samples concatenated together\n totalBufferView.setInt32(16, totalDataLength, true);\n var offset = 0;\n var dataOfTotalBuffer = new Uint8Array(totalBuffer, headerSize);\n for (var _i5 = 0; _i5 < bufferCollection.length; _i5++) {\n var _buffer = bufferCollection[_i5];\n dataOfTotalBuffer.set(new Uint8Array(_buffer, headerSize), offset);\n offset += _buffer.byteLength - headerSize;\n }\n return totalBuffer;\n },\n slice: function slice(options) {\n var startIndex = 0;\n var endIndex = 0;\n if (!isNullOrUndefined(options.startIndex) && !isNullOrUndefined(options.endIndex)) {\n startIndex = options.startIndex;\n endIndex = options.endIndex;\n } else if (!isNullOrUndefined(options.startTime) && !isNullOrUndefined(options.endTime)) {\n startIndex = this.at_time(options.startTime);\n endIndex = this.at_time(options.endTime);\n }\n if (startIndex < 0) {\n throw new RangeError('startIndex or startTime must not be negative');\n }\n if (endIndex < 0) {\n throw new RangeError('endIndex or endTime must not be negative');\n }\n if (startIndex > this.length) {\n startIndex = this.length;\n }\n if (endIndex > this.length) {\n endIndex = this.length;\n }\n if (startIndex > endIndex) {\n startIndex = endIndex;\n }\n var length = endIndex - startIndex;\n var header_size = 24; // Version 2\n var bytes_per_sample = this.bits === 8 ? 1 : 2;\n var total_size = header_size + length * 2 * this.channels * bytes_per_sample;\n var output_data = new ArrayBuffer(total_size);\n var output_dataview = new DataView(output_data);\n output_dataview.setInt32(0, 2, true); // Version\n output_dataview.setUint32(4, this.bits === 8, true); // Is 8 bit?\n output_dataview.setInt32(8, this.sample_rate, true);\n output_dataview.setInt32(12, this.scale, true);\n output_dataview.setInt32(16, length, true);\n output_dataview.setInt32(20, this.channels, true);\n for (var i = 0; i < length * this.channels * 2; i++) {\n var sample = this._at(startIndex * this.channels * 2 + i);\n if (this.bits === 8) {\n output_dataview.setInt8(header_size + i, sample);\n } else {\n output_dataview.setInt16(header_size + i * 2, sample, true);\n }\n }\n return new WaveformData(output_data);\n },\n /**\n * Returns the data format version number.\n */\n\n _version: function _version() {\n return this._data.getInt32(0, true);\n },\n /**\n * Returns the length of the waveform, in pixels.\n */\n\n get length() {\n return this._data.getUint32(16, true);\n },\n /**\n * Returns the number of bits per sample, either 8 or 16.\n */\n\n get bits() {\n var bits = Boolean(this._data.getUint32(4, true));\n return bits ? 8 : 16;\n },\n /**\n * Returns the (approximate) duration of the audio file, in seconds.\n */\n\n get duration() {\n return this.length * this.scale / this.sample_rate;\n },\n /**\n * Returns the number of pixels per second.\n */\n\n get pixels_per_second() {\n return this.sample_rate / this.scale;\n },\n /**\n * Returns the amount of time represented by a single pixel, in seconds.\n */\n\n get seconds_per_pixel() {\n return this.scale / this.sample_rate;\n },\n /**\n * Returns the number of waveform channels.\n */\n\n get channels() {\n if (this._version() === 2) {\n return this._data.getInt32(20, true);\n } else {\n return 1;\n }\n },\n /**\n * Returns a waveform channel.\n */\n\n channel: function channel(index) {\n if (index >= 0 && index < this._channels.length) {\n return this._channels[index];\n } else {\n throw new RangeError('Invalid channel: ' + index);\n }\n },\n /**\n * Returns the number of audio samples per second.\n */\n\n get sample_rate() {\n return this._data.getInt32(8, true);\n },\n /**\n * Returns the number of audio samples per pixel.\n */\n\n get scale() {\n return this._data.getInt32(12, true);\n },\n /**\n * Returns a waveform data value at a specific offset.\n */\n\n _at: function at_sample(index) {\n if (this.bits === 8) {\n return this._data.getInt8(this._offset + index);\n } else {\n return this._data.getInt16(this._offset + index * 2, true);\n }\n },\n /**\n * Sets a waveform data value at a specific offset.\n */\n\n _set_at: function set_at(index, sample) {\n if (this.bits === 8) {\n return this._data.setInt8(this._offset + index, sample);\n } else {\n return this._data.setInt16(this._offset + index * 2, sample, true);\n }\n },\n /**\n * Returns the waveform data index position for a given time.\n */\n\n at_time: function at_time(time) {\n return Math.floor(time * this.sample_rate / this.scale);\n },\n /**\n * Returns the time in seconds for a given index.\n */\n\n time: function time(index) {\n return index * this.scale / this.sample_rate;\n },\n /**\n * Returns an object containing the waveform data.\n */\n\n toJSON: function toJSON() {\n var waveform = {\n version: 2,\n channels: this.channels,\n sample_rate: this.sample_rate,\n samples_per_pixel: this.scale,\n bits: this.bits,\n length: this.length,\n data: []\n };\n for (var i = 0; i < this.length; i++) {\n for (var channel = 0; channel < this.channels; channel++) {\n waveform.data.push(this.channel(channel).min_sample(i));\n waveform.data.push(this.channel(channel).max_sample(i));\n }\n }\n return waveform;\n },\n /**\n * Returns the waveform data in binary format as an ArrayBuffer.\n */\n\n toArrayBuffer: function toArrayBuffer() {\n return this._data.buffer;\n }\n};\n\nexport { WaveformData as default };\n","/**\n * Waveform Data Loader\n *\n * Utilities for loading pre-computed waveform data in waveform-data.js format.\n * Supports both binary (.dat) and JSON formats from BBC's audiowaveform tool.\n */\n\nimport WaveformData from 'waveform-data';\n\n/**\n * Load waveform data from a .dat or .json file\n *\n * @param src - URL to waveform data file (.dat or .json)\n * @returns WaveformData instance\n */\nexport async function loadWaveformData(src: string): Promise<WaveformData> {\n const response = await fetch(src);\n\n if (!response.ok) {\n throw new Error(`Failed to fetch waveform data: ${response.statusText}`);\n }\n\n // Check file extension to determine format\n const isBinary = src.endsWith('.dat');\n\n if (isBinary) {\n const arrayBuffer = await response.arrayBuffer();\n return WaveformData.create(arrayBuffer);\n } else {\n const json = await response.json();\n return WaveformData.create(json);\n }\n}\n\n/**\n * Convert WaveformData to our internal Peaks format\n *\n * @param waveformData - WaveformData instance from waveform-data.js\n * @param channelIndex - Channel index (0 for mono/left, 1 for right)\n * @returns Peaks data with alternating min/max values, preserving original bit depth\n */\nexport function waveformDataToPeaks(\n waveformData: WaveformData,\n channelIndex: number = 0\n): { data: Int8Array | Int16Array; bits: 8 | 16; length: number; sampleRate: number } {\n const channel = waveformData.channel(channelIndex);\n const bits = waveformData.bits as 8 | 16;\n\n // Get the min/max arrays to determine length\n const minArray = channel.min_array();\n const maxArray = channel.max_array();\n const length = minArray.length;\n\n // Use appropriate typed array based on source file bit depth\n // 8-bit: values range from -128 to 127\n // 16-bit: values range from -32768 to 32767\n const peaks = bits === 8\n ? new Int8Array(length * 2)\n : new Int16Array(length * 2);\n\n // Interleave min/max pairs\n for (let i = 0; i < length; i++) {\n peaks[i * 2] = minArray[i];\n peaks[i * 2 + 1] = maxArray[i];\n }\n\n return {\n data: peaks,\n bits,\n length,\n sampleRate: waveformData.sample_rate,\n };\n}\n\n/**\n * Load waveform data file and convert to Peaks format in one step\n *\n * @param src - URL to waveform data file (.dat or .json)\n * @param channelIndex - Channel index (default: 0)\n * @returns Peaks data ready for rendering\n */\nexport async function loadPeaksFromWaveformData(\n src: string,\n channelIndex: number = 0\n): Promise<{ data: Int8Array | Int16Array; bits: 8 | 16; length: number; sampleRate: number }> {\n const waveformData = await loadWaveformData(src);\n return waveformDataToPeaks(waveformData, channelIndex);\n}\n\n/**\n * Get metadata from waveform data file without converting to peaks\n *\n * @param src - URL to waveform data file\n * @returns Metadata (sample rate, channels, duration, bits, etc.)\n */\nexport async function getWaveformDataMetadata(src: string): Promise<{\n sampleRate: number;\n channels: number;\n duration: number;\n samplesPerPixel: number;\n length: number;\n bits: 8 | 16;\n}> {\n const waveformData = await loadWaveformData(src);\n\n return {\n sampleRate: waveformData.sample_rate,\n channels: waveformData.channels,\n duration: waveformData.duration,\n samplesPerPixel: waveformData.scale,\n length: waveformData.length,\n bits: waveformData.bits as 8 | 16,\n };\n}\n\n/**\n * Extract peaks from a WaveformData object at a specific scale (samplesPerPixel)\n * and optionally slice to a sample range.\n *\n * @param waveformData - WaveformData instance from waveform-data.js\n * @param samplesPerPixel - Target samples per pixel (will resample if different)\n * @param channelIndex - Channel index (default: 0)\n * @param offsetSamples - Optional start offset in samples (for clip trimming)\n * @param durationSamples - Optional duration in samples (for clip trimming)\n * @returns Peaks data ready for rendering\n */\nexport function extractPeaksFromWaveformData(\n waveformData: WaveformData,\n samplesPerPixel: number,\n channelIndex: number = 0,\n offsetSamples?: number,\n durationSamples?: number\n): { data: Int8Array | Int16Array; bits: 8 | 16; length: number } {\n let processedData = waveformData;\n\n // Slice if offset/duration specified (using index-based slicing for sample accuracy)\n if (offsetSamples !== undefined && durationSamples !== undefined) {\n // Convert samples to waveform data indices\n // waveformData.scale is the samples per pixel of the source data\n const sourceScale = waveformData.scale;\n const startIndex = Math.floor(offsetSamples / sourceScale);\n const endIndex = Math.ceil((offsetSamples + durationSamples) / sourceScale);\n processedData = processedData.slice({ startIndex, endIndex });\n }\n\n // Resample to target scale if different\n if (processedData.scale !== samplesPerPixel) {\n processedData = processedData.resample({ scale: samplesPerPixel });\n }\n\n // Convert to our peaks format\n const channel = processedData.channel(channelIndex);\n const bits = processedData.bits as 8 | 16;\n const minArray = channel.min_array();\n const maxArray = channel.max_array();\n const length = minArray.length;\n\n const peaks = bits === 8\n ? new Int8Array(length * 2)\n : new Int16Array(length * 2);\n\n for (let i = 0; i < length; i++) {\n peaks[i * 2] = minArray[i];\n peaks[i * 2 + 1] = maxArray[i];\n }\n\n return { data: peaks, bits, length };\n}\n","// src/parsers/aeneas.ts\nfunction parseAeneas(data) {\n return {\n id: data.id,\n start: parseFloat(data.begin),\n end: parseFloat(data.end),\n lines: data.lines,\n lang: data.language\n };\n}\nfunction serializeAeneas(annotation) {\n return {\n id: annotation.id,\n begin: annotation.start.toFixed(3),\n end: annotation.end.toFixed(3),\n lines: annotation.lines,\n language: annotation.lang || \"en\"\n };\n}\n\n// src/components/Annotation.tsx\nimport { useState } from \"react\";\nimport styled from \"styled-components\";\nimport { jsx, jsxs } from \"react/jsx-runtime\";\nvar AnnotationOverlay = styled.div.attrs((props) => ({\n style: {\n left: `${props.$left}px`,\n width: `${props.$width}px`\n }\n}))`\n position: absolute;\n top: 0;\n background: ${(props) => props.$color};\n height: 100%;\n z-index: 10;\n pointer-events: auto;\n opacity: 0.3;\n border: 2px solid ${(props) => props.$color};\n border-radius: 4px;\n cursor: pointer;\n\n &:hover {\n opacity: 0.5;\n border-color: ${(props) => props.$color};\n }\n`;\nvar AnnotationText = styled.div`\n position: absolute;\n bottom: 0;\n left: 0;\n right: 0;\n background: rgba(0, 0, 0, 0.7);\n color: white;\n padding: 4px 8px;\n font-size: 12px;\n line-height: 1.3;\n max-height: 60%;\n overflow: hidden;\n text-overflow: ellipsis;\n pointer-events: none;\n white-space: pre-wrap;\n word-break: break-word;\n`;\nvar EditableText = styled.textarea`\n position: absolute;\n bottom: 0;\n left: 0;\n right: 0;\n background: rgba(0, 0, 0, 0.9);\n color: white;\n padding: 4px 8px;\n font-size: 12px;\n line-height: 1.3;\n max-height: 60%;\n overflow: auto;\n border: 1px solid #fff;\n resize: none;\n font-family: inherit;\n\n &:focus {\n outline: none;\n border-color: #4CAF50;\n }\n`;\nvar ControlsBar = styled.div`\n position: absolute;\n top: 0;\n left: 0;\n right: 0;\n background: rgba(0, 0, 0, 0.8);\n display: flex;\n gap: 4px;\n padding: 4px;\n justify-content: flex-start;\n align-items: center;\n`;\nvar ControlButton = styled.button`\n background: transparent;\n border: 1px solid rgba(255, 255, 255, 0.5);\n color: white;\n padding: 4px 8px;\n font-size: 10px;\n cursor: pointer;\n border-radius: 3px;\n display: flex;\n align-items: center;\n justify-content: center;\n min-width: 24px;\n height: 24px;\n\n &:hover {\n background: rgba(255, 255, 255, 0.2);\n border-color: white;\n }\n\n &:active {\n background: rgba(255, 255, 255, 0.3);\n }\n`;\nvar Annotation = ({\n annotation,\n index,\n allAnnotations,\n startPosition,\n endPosition,\n color = \"#ff9800\",\n editable = false,\n controls = [],\n onAnnotationUpdate,\n annotationListConfig,\n onClick\n}) => {\n const [isEditing, setIsEditing] = useState(false);\n const [editedText, setEditedText] = useState(annotation.lines.join(\"\\n\"));\n const width = Math.max(0, endPosition - startPosition);\n if (width <= 0) {\n return null;\n }\n const handleClick = () => {\n if (onClick) {\n onClick(annotation);\n }\n };\n const handleDoubleClick = () => {\n if (editable) {\n setIsEditing(true);\n }\n };\n const handleTextChange = (e) => {\n setEditedText(e.target.value);\n };\n const handleTextBlur = () => {\n setIsEditing(false);\n const newLines = editedText.split(\"\\n\");\n if (newLines.join(\"\\n\") !== annotation.lines.join(\"\\n\")) {\n const updatedAnnotations = [...allAnnotations];\n updatedAnnotations[index] = { ...annotation, lines: newLines };\n if (onAnnotationUpdate) {\n onAnnotationUpdate(updatedAnnotations);\n }\n }\n };\n const handleControlClick = (control) => {\n const annotationsCopy = [...allAnnotations];\n control.action(annotationsCopy[index], index, annotationsCopy, annotationListConfig || {});\n if (onAnnotationUpdate) {\n onAnnotationUpdate(annotationsCopy);\n }\n };\n const getIconClass = (classString) => {\n return classString.replace(/\\./g, \" \");\n };\n return /* @__PURE__ */ jsxs(\n AnnotationOverlay,\n {\n $left: startPosition,\n $width: width,\n $color: color,\n onClick: handleClick,\n onDoubleClick: handleDoubleClick,\n children: [\n controls.length > 0 && /* @__PURE__ */ jsx(ControlsBar, { children: controls.map((control, idx) => /* @__PURE__ */ jsx(\n ControlButton,\n {\n title: control.title,\n onClick: (e) => {\n e.stopPropagation();\n handleControlClick(control);\n },\n children: control.text ? control.text : /* @__PURE__ */ jsx(\"i\", { className: getIconClass(control.class || \"\") })\n },\n idx\n )) }),\n isEditing ? /* @__PURE__ */ jsx(\n EditableText,\n {\n value: editedText,\n onChange: handleTextChange,\n onBlur: handleTextBlur,\n autoFocus: true,\n onClick: (e) => e.stopPropagation(),\n onDoubleClick: (e) => e.stopPropagation()\n }\n ) : /* @__PURE__ */ jsx(AnnotationText, { children: annotation.lines.join(\"\\n\") })\n ]\n }\n );\n};\n\n// src/components/AnnotationBox.tsx\nimport styled2 from \"styled-components\";\nimport { useDraggable } from \"@dnd-kit/core\";\nimport { jsx as jsx2, jsxs as jsxs2 } from \"react/jsx-runtime\";\nvar Wrapper = styled2.div.attrs((props) => ({\n style: {\n left: `${props.$left}px`,\n width: `${props.$width}px`\n }\n}))`\n position: absolute;\n top: 0;\n height: 100%;\n pointer-events: none; /* Let events pass through to children */\n`;\nvar Box = styled2.div`\n position: absolute;\n top: 0;\n left: 0;\n right: 0;\n height: 100%;\n background: ${(props) => props.$isActive ? props.theme?.annotationBoxActiveBackground || \"rgba(255, 200, 100, 0.95)\" : props.theme?.annotationBoxBackground || \"rgba(255, 255, 255, 0.85)\"};\n border: ${(props) => props.$isActive ? \"3px\" : \"2px\"} solid ${(props) => props.$isActive ? props.theme?.annotationBoxActiveBorder || \"#ff9800\" : props.$color};\n border-radius: 4px;\n cursor: pointer;\n pointer-events: auto;\n display: flex;\n align-items: center;\n justify-content: center;\n overflow: hidden;\n transition: all 0.2s ease;\n box-shadow: ${(props) => props.$isActive ? \"0 2px 8px rgba(255, 152, 0, 0.4), inset 0 0 0 1px rgba(255, 152, 0, 0.2)\" : \"0 1px 3px rgba(0, 0, 0, 0.1)\"};\n\n &:hover {\n background: ${(props) => props.theme?.annotationBoxHoverBackground || \"rgba(255, 255, 255, 0.98)\"};\n border-color: ${(props) => props.theme?.annotationBoxActiveBorder || \"#ff9800\"};\n border-width: 3px;\n box-shadow: 0 2px 6px rgba(0, 0, 0, 0.15);\n }\n`;\nvar Label = styled2.span`\n font-size: 12px;\n font-weight: 600;\n color: ${(props) => props.theme?.annotationLabelColor || \"#2a2a2a\"};\n white-space: nowrap;\n overflow: hidden;\n text-overflow: ellipsis;\n padding: 0 6px;\n letter-spacing: 0.3px;\n user-select: none;\n`;\nvar ResizeHandle = styled2.div`\n position: absolute;\n top: 0;\n ${(props) => props.$position === \"left\" ? \"left: -8px\" : \"right: -8px\"};\n width: 16px;\n height: 100%;\n cursor: ew-resize;\n z-index: 120; /* Above ClickOverlay (z-index: 100) and AnnotationBoxesWrapper (z-index: 110) */\n background: ${(props) => props.$isDragging ? props.theme?.annotationResizeHandleColor || \"rgba(0, 0, 0, 0.2)\" : \"transparent\"};\n border-radius: 4px;\n touch-action: none; /* Important for @dnd-kit on touch devices */\n pointer-events: auto;\n\n &::before {\n content: '';\n position: absolute;\n top: 50%;\n left: 50%;\n transform: translate(-50%, -50%);\n width: 4px;\n height: 60%;\n background: ${(props) => props.$isDragging ? props.theme?.annotationResizeHandleActiveColor || \"rgba(0, 0, 0, 0.8)\" : props.theme?.annotationResizeHandleColor || \"rgba(0, 0, 0, 0.4)\"};\n border-radius: 2px;\n opacity: ${(props) => props.$isDragging ? 1 : 0.6};\n transition: opacity 0.2s, background 0.2s;\n }\n\n &:hover {\n background: ${(props) => props.theme?.annotationResizeHandleColor || \"rgba(0, 0, 0, 0.1)\"};\n }\n\n &:hover::before {\n opacity: 1;\n background: ${(props) => props.theme?.annotationResizeHandleActiveColor || \"rgba(0, 0, 0, 0.7)\"};\n }\n`;\nvar AnnotationBox = ({\n annotationId,\n annotationIndex,\n startPosition,\n endPosition,\n label,\n color = \"#ff9800\",\n isActive = false,\n onClick,\n editable = true\n}) => {\n const width = Math.max(0, endPosition - startPosition);\n const leftBoundaryId = `annotation-boundary-start-${annotationIndex}`;\n const {\n attributes: leftAttributes,\n listeners: leftListeners,\n setActivatorNodeRef: setLeftActivatorRef,\n isDragging: isLeftDragging\n } = useDraggable({\n id: leftBoundaryId,\n data: { annotationId, annotationIndex, edge: \"start\" },\n disabled: !editable\n });\n const rightBoundaryId = `annotation-boundary-end-${annotationIndex}`;\n const {\n attributes: rightAttributes,\n listeners: rightListeners,\n setActivatorNodeRef: setRightActivatorRef,\n isDragging: isRightDragging\n } = useDraggable({\n id: rightBoundaryId,\n data: { annotationId, annotationIndex, edge: \"end\" },\n disabled: !editable\n });\n if (width <= 0) {\n return null;\n }\n const createPointerDownHandler = (dndKitHandler) => {\n return (e) => {\n e.stopPropagation();\n dndKitHandler?.(e);\n };\n };\n const handleHandleClick = (e) => {\n e.stopPropagation();\n };\n return /* @__PURE__ */ jsxs2(Wrapper, { $left: startPosition, $width: width, children: [\n /* @__PURE__ */ jsx2(\n Box,\n {\n $color: color,\n $isActive: isActive,\n onClick,\n children: label && /* @__PURE__ */ jsx2(Label, { children: label })\n }\n ),\n editable && /* @__PURE__ */ jsx2(\n ResizeHandle,\n {\n ref: setLeftActivatorRef,\n $position: \"left\",\n $isDragging: isLeftDragging,\n onClick: handleHandleClick,\n ...leftListeners,\n onPointerDown: createPointerDownHandler(leftListeners?.onPointerDown),\n ...leftAttributes\n }\n ),\n editable && /* @__PURE__ */ jsx2(\n ResizeHandle,\n {\n ref: setRightActivatorRef,\n $position: \"right\",\n $isDragging: isRightDragging,\n onClick: handleHandleClick,\n ...rightListeners,\n onPointerDown: createPointerDownHandler(rightListeners?.onPointerDown),\n ...rightAttributes\n }\n )\n ] });\n};\n\n// src/components/AnnotationBoxesWrapper.tsx\nimport styled3 from \"styled-components\";\nimport { usePlaylistInfo } from \"@waveform-playlist/ui-components\";\nimport { jsx as jsx3, jsxs as jsxs3 } from \"react/jsx-runtime\";\nvar Container = styled3.div.attrs((props) => ({\n style: {\n height: `${props.$height}px`\n }\n}))`\n position: relative;\n display: flex;\n ${(props) => props.$width !== void 0 && `width: ${props.$width}px;`}\n background: transparent;\n z-index: 110;\n`;\nvar ControlsPlaceholder = styled3.div`\n position: sticky;\n z-index: 200;\n left: 0;\n height: 100%;\n width: ${(props) => props.$controlWidth}px;\n flex-shrink: 0;\n background: transparent;\n`;\nvar BoxesContainer = styled3.div`\n position: relative;\n flex: 1;\n padding-left: ${(props) => props.$offset || 0}px;\n`;\nvar AnnotationBoxesWrapper = ({\n children,\n className,\n height = 30,\n offset = 0,\n width\n}) => {\n const {\n controls: { show, width: controlWidth }\n } = usePlaylistInfo();\n return /* @__PURE__ */ jsxs3(\n Container,\n {\n className,\n $height: height,\n $controlWidth: show ? controlWidth : 0,\n $width: width,\n children: [\n /* @__PURE__ */ jsx3(ControlsPlaceholder, { $controlWidth: show ? controlWidth : 0 }),\n /* @__PURE__ */ jsx3(BoxesContainer, { $offset: offset, children })\n ]\n }\n );\n};\n\n// src/components/AnnotationsTrack.tsx\nimport styled4 from \"styled-components\";\nimport { usePlaylistInfo as usePlaylistInfo2 } from \"@waveform-playlist/ui-components\";\nimport { jsx as jsx4, jsxs as jsxs4 } from \"react/jsx-runtime\";\nvar Container2 = styled4.div.attrs((props) => ({\n style: {\n height: `${props.$height}px`\n }\n}))`\n position: relative;\n display: flex;\n ${(props) => props.$width !== void 0 && `width: ${props.$width}px;`}\n background: transparent;\n`;\nvar ControlsPlaceholder2 = styled4.div`\n position: sticky;\n z-index: 200;\n left: 0;\n height: 100%;\n width: ${(props) => props.$controlWidth}px;\n flex-shrink: 0;\n background: transparent;\n display: flex;\n align-items: center;\n justify-content: center;\n font-size: 12px;\n color: ${(props) => props.theme?.textColorMuted || \"#666\"};\n font-weight: bold;\n`;\nvar AnnotationsContainer = styled4.div`\n position: relative;\n flex: 1;\n padding-left: ${(props) => props.$offset || 0}px;\n`;\nvar AnnotationsTrack = ({\n children,\n className,\n height = 100,\n offset = 0,\n width\n}) => {\n const {\n controls: { show, width: controlWidth }\n } = usePlaylistInfo2();\n return /* @__PURE__ */ jsxs4(\n Container2,\n {\n className,\n $height: height,\n $controlWidth: show ? controlWidth : 0,\n $width: width,\n children: [\n /* @__PURE__ */ jsx4(ControlsPlaceholder2, { $controlWidth: show ? controlWidth : 0, children: \"Annotations\" }),\n /* @__PURE__ */ jsx4(AnnotationsContainer, { $offset: offset, children })\n ]\n }\n );\n};\n\n// src/components/AnnotationText.tsx\nimport React2, { useRef, useEffect } from \"react\";\nimport styled5 from \"styled-components\";\nimport { jsx as jsx5, jsxs as jsxs5 } from \"react/jsx-runtime\";\nvar Container3 = styled5.div`\n background: ${(props) => props.theme?.backgroundColor || \"#fff\"};\n ${(props) => props.$height ? `height: ${props.$height}px;` : \"max-height: 200px;\"}\n overflow-y: auto;\n padding: 8px;\n`;\nvar AnnotationItem = styled5.div`\n padding: 12px;\n margin-bottom: 6px;\n border-left: 4px solid ${(props) => props.$isActive ? \"#ff9800\" : \"transparent\"};\n background: ${(props) => props.$isActive ? \"rgba(255, 152, 0, 0.15)\" : \"transparent\"};\n border-radius: 4px;\n transition: all 0.2s;\n cursor: pointer;\n box-shadow: ${(props) => props.$isActive ? \"0 2px 8px rgba(255, 152, 0, 0.25), inset 0 0 0 1px rgba(255, 152, 0, 0.3)\" : \"none\"};\n\n &:hover {\n background: ${(props) => props.$isActive ? \"rgba(255, 152, 0, 0.2)\" : props.theme?.annotationTextItemHoverBackground || \"rgba(0, 0, 0, 0.05)\"};\n border-left-color: ${(props) => props.$isActive ? \"#ff9800\" : props.theme?.borderColor || \"#ddd\"};\n }\n\n &:focus-visible {\n outline: 2px solid #ff9800;\n outline-offset: 2px;\n }\n`;\nvar AnnotationHeader = styled5.div`\n display: flex;\n justify-content: space-between;\n align-items: center;\n margin-bottom: 6px;\n`;\nvar AnnotationInfo = styled5.div`\n display: flex;\n align-items: center;\n gap: 8px;\n`;\nvar AnnotationIdLabel = styled5.span`\n font-size: 11px;\n font-weight: 600;\n color: ${(props) => props.theme?.textColorMuted || \"#666\"};\n background: transparent;\n padding: 2px 6px;\n border-radius: 3px;\n min-width: 20px;\n outline: ${(props) => props.$isEditable ? `1px dashed ${props.theme?.borderColor || \"#ddd\"}` : \"none\"};\n\n &[contenteditable='true']:focus {\n outline: 2px solid #ff9800;\n background: rgba(255, 152, 0, 0.1);\n }\n`;\nvar TimeRange = styled5.span`\n font-size: 12px;\n font-weight: 500;\n color: ${(props) => props.theme?.textColorMuted || \"#555\"};\n font-family: 'Monaco', 'Menlo', 'Ubuntu Mono', monospace;\n letter-spacing: 0.5px;\n`;\nvar AnnotationControls = styled5.div`\n display: flex;\n gap: 6px;\n`;\nvar ControlButton2 = styled5.button`\n background: ${(props) => props.theme?.surfaceColor || \"#f5f5f5\"};\n border: 1px solid ${(props) => props.theme?.borderColor || \"#ccc\"};\n color: ${(props) => props.theme?.textColor || \"#333\"};\n padding: 4px 8px;\n font-size: 14px;\n cursor: pointer;\n border-radius: 4px;\n transition: all 0.15s ease;\n\n &:hover {\n background: ${(props) => props.theme?.inputBackground || \"#3d3d3d\"};\n border-color: ${(props) => props.theme?.textColorMuted || \"#999\"};\n transform: scale(1.05);\n }\n\n &:active {\n transform: scale(0.95);\n }\n`;\nvar AnnotationTextContent = styled5.div`\n font-size: 14px;\n line-height: 1.6;\n color: ${(props) => props.theme?.textColor || \"#2a2a2a\"};\n white-space: pre-wrap;\n word-break: break-word;\n outline: ${(props) => props.$isEditable ? `1px dashed ${props.theme?.borderColor || \"#ddd\"}` : \"none\"};\n padding: ${(props) => props.$isEditable ? \"6px\" : \"0\"};\n border-radius: 3px;\n min-height: 20px;\n\n &[contenteditable='true']:focus {\n outline: 2px solid #ff9800;\n background: rgba(255, 152, 0, 0.1);\n }\n`;\nvar AnnotationTextComponent = ({\n annotations,\n activeAnnotationId,\n shouldScrollToActive = false,\n editable = false,\n controls = [],\n annotationListConfig,\n height,\n onAnnotationClick,\n onAnnotationUpdate,\n renderAnnotationItem\n}) => {\n const activeAnnotationRef = useRef(null);\n const containerRef = useRef(null);\n const prevActiveIdRef = useRef(void 0);\n useEffect(() => {\n });\n useEffect(() => {\n const container = containerRef.current;\n if (!container) return;\n const handleScroll = () => {\n };\n container.addEventListener(\"scroll\", handleScroll);\n return () => container.removeEventListener(\"scroll\", handleScroll);\n }, []);\n useEffect(() => {\n if (activeAnnotationId && activeAnnotationRef.current && shouldScrollToActive) {\n activeAnnotationRef.current.scrollIntoView({\n behavior: \"smooth\",\n block: \"nearest\"\n });\n }\n prevActiveIdRef.current = activeAnnotationId;\n }, [activeAnnotationId, shouldScrollToActive]);\n const formatTime = (seconds) => {\n if (isNaN(seconds) || !isFinite(seconds)) {\n return \"0:00.000\";\n }\n const mins = Math.floor(seconds / 60);\n const secs = (seconds % 60).toFixed(3);\n return `${mins}:${secs.padStart(6, \"0\")}`;\n };\n const handleTextEdit = (index, newText) => {\n if (!editable || !onAnnotationUpdate) return;\n const updatedAnnotations = [...annotations];\n updatedAnnotations[index] = {\n ...updatedAnnotations[index],\n lines: newText.split(\"\\n\")\n };\n onAnnotationUpdate(updatedAnnotations);\n };\n const handleIdEdit = (index, newId) => {\n if (!editable || !onAnnotationUpdate) return;\n const trimmedId = newId.trim();\n if (!trimmedId) return;\n const updatedAnnotations = [...annotations];\n updatedAnnotations[index] = {\n ...updatedAnnotations[index],\n id: trimmedId\n };\n onAnnotationUpdate(updatedAnnotations);\n };\n const handleControlClick = (control, annotation, index) => {\n if (!onAnnotationUpdate) return;\n const annotationsCopy = [...annotations];\n control.action(annotationsCopy[index], index, annotationsCopy, annotationListConfig || {});\n onAnnotationUpdate(annotationsCopy);\n };\n const getIconClass = (classString) => {\n return classString.replace(/\\./g, \" \");\n };\n return /* @__PURE__ */ jsx5(Container3, { ref: containerRef, $height: height, children: annotations.map((annotation, index) => {\n const isActive = annotation.id === activeAnnotationId;\n const handleClick = () => onAnnotationClick?.(annotation);\n if (renderAnnotationItem) {\n return /* @__PURE__ */ jsx5(\n \"div\",\n {\n ref: isActive ? activeAnnotationRef : null,\n children: renderAnnotationItem({\n annotation,\n index,\n isActive,\n onClick: handleClick,\n formatTime\n })\n },\n annotation.id\n );\n }\n return /* @__PURE__ */ jsxs5(\n AnnotationItem,\n {\n ref: isActive ? activeAnnotationRef : null,\n $isActive: isActive,\n onClick: handleClick,\n children: [\n /* @__PURE__ */ jsxs5(AnnotationHeader, { children: [\n /* @__PURE__ */ jsxs5(AnnotationInfo, { children: [\n /* @__PURE__ */ jsx5(\n AnnotationIdLabel,\n {\n $isEditable: editable,\n contentEditable: editable,\n suppressContentEditableWarning: true,\n onBlur: (e) => handleIdEdit(index, e.currentTarget.textContent || \"\"),\n children: annotation.id\n }\n ),\n /* @__PURE__ */ jsxs5(TimeRange, { children: [\n formatTime(annotation.start),\n \" - \",\n formatTime(annotation.end)\n ] })\n ] }),\n controls.length > 0 && /* @__PURE__ */ jsx5(AnnotationControls, { onClick: (e) => e.stopPropagation(), children: controls.map((control, idx) => /* @__PURE__ */ jsx5(\n ControlButton2,\n {\n title: control.title,\n onClick: () => handleControlClick(control, annotation, index),\n children: control.text ? control.text : /* @__PURE__ */ jsx5(\"i\", { className: getIconClass(control.class || \"\") })\n },\n idx\n )) })\n ] }),\n /* @__PURE__ */ jsx5(\n AnnotationTextContent,\n {\n $isEditable: editable,\n contentEditable: editable,\n suppressContentEditableWarning: true,\n onBlur: (e) => handleTextEdit(index, e.currentTarget.textContent || \"\"),\n children: annotation.lines.join(\"\\n\")\n }\n )\n ]\n },\n annotation.id\n );\n }) });\n};\nvar AnnotationText2 = React2.memo(AnnotationTextComponent);\n\n// src/components/ContinuousPlayCheckbox.tsx\nimport { BaseCheckboxWrapper, BaseCheckbox, BaseCheckboxLabel } from \"@waveform-playlist/ui-components\";\nimport { jsx as jsx6, jsxs as jsxs6 } from \"react/jsx-runtime\";\nvar ContinuousPlayCheckbox = ({\n checked,\n onChange,\n disabled = false,\n className\n}) => {\n const handleChange = (e) => {\n onChange(e.target.checked);\n };\n return /* @__PURE__ */ jsxs6(BaseCheckboxWrapper, { className, children: [\n /* @__PURE__ */ jsx6(\n BaseCheckbox,\n {\n type: \"checkbox\",\n id: \"continuous-play\",\n className: \"continuous-play\",\n checked,\n onChange: handleChange,\n disabled\n }\n ),\n /* @__PURE__ */ jsx6(BaseCheckboxLabel, { htmlFor: \"continuous-play\", children: \"Continuous Play\" })\n ] });\n};\n\n// src/components/LinkEndpointsCheckbox.tsx\nimport { BaseCheckboxWrapper as BaseCheckboxWrapper2, BaseCheckbox as BaseCheckbox2, BaseCheckboxLabel as BaseCheckboxLabel2 } from \"@waveform-playlist/ui-components\";\nimport { jsx as jsx7, jsxs as jsxs7 } from \"react/jsx-runtime\";\nvar LinkEndpointsCheckbox = ({\n checked,\n onChange,\n disabled = false,\n className\n}) => {\n const handleChange = (e) => {\n onChange(e.target.checked);\n };\n return /* @__PURE__ */ jsxs7(BaseCheckboxWrapper2, { className, children: [\n /* @__PURE__ */ jsx7(\n BaseCheckbox2,\n {\n type: \"checkbox\",\n id: \"link-endpoints\",\n className: \"link-endpoints\",\n checked,\n onChange: handleChange,\n disabled\n }\n ),\n /* @__PURE__ */ jsx7(BaseCheckboxLabel2, { htmlFor: \"link-endpoints\", children: \"Link Endpoints\" })\n ] });\n};\n\n// src/components/EditableCheckbox.tsx\nimport { BaseCheckboxWrapper as BaseCheckboxWrapper3, BaseCheckbox as BaseCheckbox3, BaseCheckboxLabel as BaseCheckboxLabel3 } from \"@waveform-playlist/ui-components\";\nimport { jsx as jsx8, jsxs as jsxs8 } from \"react/jsx-runtime\";\nvar EditableCheckbox = ({\n checked,\n onChange,\n className\n}) => {\n return /* @__PURE__ */ jsxs8(BaseCheckboxWrapper3, { className, children: [\n /* @__PURE__ */ jsx8(\n BaseCheckbox3,\n {\n type: \"checkbox\",\n id: \"editable-annotations\",\n checked,\n onChange: (e) => onChange(e.target.checked)\n }\n ),\n /* @__PURE__ */ jsx8(BaseCheckboxLabel3, { htmlFor: \"editable-annotations\", children: \"Editable Annotations\" })\n ] });\n};\n\n// src/components/DownloadAnnotationsButton.tsx\nimport styled6 from \"styled-components\";\nimport { jsx as jsx9 } from \"react/jsx-runtime\";\nvar StyledButton = styled6.button`\n padding: 0.5rem 1rem;\n background: ${(props) => props.theme?.surfaceColor || \"#f5f5f5\"};\n color: ${(props) => props.theme?.textColor || \"#333\"};\n border: 1px solid ${(props) => props.theme?.borderColor || \"#ccc\"};\n border-radius: ${(props) => props.theme?.borderRadius || \"4px\"};\n cursor: pointer;\n font-family: ${(props) => props.theme?.fontFamily || \"inherit\"};\n font-size: ${(props) => props.theme?.fontSize || \"14px\"};\n font-weight: 500;\n transition: all 0.15s ease;\n\n &:hover:not(:disabled) {\n background: ${(props) => props.theme?.inputBackground || \"#3d3d3d\"};\n border-color: ${(props) => props.theme?.textColorMuted || \"#999\"};\n }\n\n &:focus {\n outline: none;\n box-shadow: 0 0 0 2px ${(props) => props.theme?.inputFocusBorder || \"#007bff\"}44;\n }\n\n &:disabled {\n opacity: 0.6;\n cursor: not-allowed;\n }\n`;\nvar DownloadAnnotationsButton = ({\n annotations,\n filename = \"annotations.json\",\n disabled = false,\n className,\n children = \"Download JSON\"\n}) => {\n const handleDownload = () => {\n if (annotations.length === 0) {\n return;\n }\n const jsonData = annotations.map((annotation) => serializeAeneas(annotation));\n const jsonString = JSON.stringify(jsonData, null, 2);\n const blob = new Blob([jsonString], { type: \"application/json\" });\n const url = URL.createObjectURL(blob);\n const link = document.createElement(\"a\");\n link.href = url;\n link.download = filename;\n document.body.appendChild(link);\n link.click();\n document.body.removeChild(link);\n URL.revokeObjectURL(url);\n };\n return /* @__PURE__ */ jsx9(\n StyledButton,\n {\n onClick: handleDownload,\n disabled: disabled || annotations.length === 0,\n className,\n title: annotations.length === 0 ? \"No annotations to download\" : \"Download the annotations as JSON\",\n children\n }\n );\n};\n\n// src/hooks/useAnnotationControls.ts\nimport { useState as useState2, useCallback } from \"react\";\nvar LINK_THRESHOLD = 0.01;\nvar useAnnotationControls = (options = {}) => {\n const {\n initialContinuousPlay = false,\n initialLinkEndpoints = true\n } = options;\n const [continuousPlay, setContinuousPlay] = useState2(initialContinuousPlay);\n const [linkEndpoints, setLinkEndpoints] = useState2(initialLinkEndpoints);\n const updateAnnotationBoundaries = useCallback(\n ({\n annotationIndex,\n newTime,\n isDraggingStart,\n annotations,\n duration,\n linkEndpoints: shouldLinkEndpoints\n }) => {\n const updatedAnnotations = [...annotations];\n const annotation = annotations[annotationIndex];\n if (isDraggingStart) {\n const constrainedStart = Math.min(annotation.end - 0.1, Math.max(0, newTime));\n const delta = constrainedStart - annotation.start;\n updatedAnnotations[annotationIndex] = {\n ...annotation,\n start: constrainedStart\n };\n if (shouldLinkEndpoints && annotationIndex > 0) {\n const prevAnnotation = updatedAnnotations[annotationIndex - 1];\n if (Math.abs(prevAnnotation.end - annotation.start) < LINK_THRESHOLD) {\n updatedAnnotations[annotationIndex - 1] = {\n ...prevAnnotation,\n end: Math.max(prevAnnotation.start + 0.1, prevAnnotation.end + delta)\n };\n } else if (constrainedStart <= prevAnnotation.end) {\n updatedAnnotations[annotationIndex] = {\n ...updatedAnnotations[annotationIndex],\n start: prevAnnotation.end\n };\n }\n } else if (!shouldLinkEndpoints && annotationIndex > 0 && constrainedStart < updatedAnnotations[annotationIndex - 1].end) {\n updatedAnnotations[annotationIndex - 1] = {\n ...updatedAnnotations[annotationIndex - 1],\n end: constrainedStart\n };\n }\n } else {\n const constrainedEnd = Math.max(annotation.start + 0.1, Math.min(newTime, duration));\n const delta = constrainedEnd - annotation.end;\n updatedAnnotations[annotationIndex] = {\n ...annotation,\n end: constrainedEnd\n };\n if (shouldLinkEndpoints && annotationIndex < updatedAnnotations.length - 1) {\n const nextAnnotation = updatedAnnotations[annotationIndex + 1];\n if (Math.abs(nextAnnotation.start - annotation.end) < LINK_THRESHOLD) {\n const newStart = nextAnnotation.start + delta;\n updatedAnnotations[annotationIndex + 1] = {\n ...nextAnnotation,\n start: Math.min(nextAnnotation.end - 0.1, newStart)\n };\n let currentIndex = annotationIndex + 1;\n while (currentIndex < updatedAnnotations.length - 1) {\n const current = updatedAnnotations[currentIndex];\n const next = updatedAnnotations[currentIndex + 1];\n if (Math.abs(next.start - current.end) < LINK_THRESHOLD) {\n const nextDelta = current.end - annotations[currentIndex].end;\n updatedAnnotations[currentIndex + 1] = {\n ...next,\n start: Math.min(next.end - 0.1, next.start + nextDelta)\n };\n currentIndex++;\n } else {\n break;\n }\n }\n } else if (constrainedEnd >= nextAnnotation.start) {\n updatedAnnotations[annotationIndex] = {\n ...updatedAnnotations[annotationIndex],\n end: nextAnnotation.start\n };\n }\n } else if (!shouldLinkEndpoints && annotationIndex < updatedAnnotations.length - 1 && constrainedEnd > updatedAnnotations[annotationIndex + 1].start) {\n const nextAnnotation = updatedAnnotations[annotationIndex + 1];\n updatedAnnotations[annotationIndex + 1] = {\n ...nextAnnotation,\n start: constrainedEnd\n };\n let currentIndex = annotationIndex + 1;\n while (currentIndex < updatedAnnotations.length - 1) {\n const current = updatedAnnotations[currentIndex];\n const next = updatedAnnotations[currentIndex + 1];\n if (current.end > next.start) {\n updatedAnnotations[currentIndex + 1] = {\n ...next,\n start: current.end\n };\n currentIndex++;\n } else {\n break;\n }\n }\n }\n }\n return updatedAnnotations;\n },\n []\n );\n return {\n continuousPlay,\n linkEndpoints,\n setContinuousPlay,\n setLinkEndpoints,\n updateAnnotationBoundaries\n };\n};\nexport {\n Annotation,\n AnnotationBox,\n AnnotationBoxesWrapper,\n AnnotationText2 as AnnotationText,\n AnnotationsTrack,\n ContinuousPlayCheckbox,\n DownloadAnnotationsButton,\n EditableCheckbox,\n LinkEndpointsCheckbox,\n parseAeneas,\n serializeAeneas,\n useAnnotationControls\n};\n//# sourceMappingURL=index.mjs.map","import { useState } from 'react';\nimport { formatTime as formatTimeUtil, parseTime as parseTimeUtil, type TimeFormat } from '@waveform-playlist/ui-components';\n\nexport interface TimeFormatControls {\n timeFormat: TimeFormat;\n setTimeFormat: (format: TimeFormat) => void;\n formatTime: (seconds: number) => string;\n parseTime: (timeString: string) => number;\n}\n\n/**\n * Hook to manage time format state\n *\n * @example\n * ```tsx\n * const { timeFormat, setTimeFormat, formatTime, parseTime } = useTimeFormat();\n *\n * <TimeFormatSelect\n * value={timeFormat}\n * onChange={setTimeFormat}\n * />\n * <span>{formatTime(currentTime)}</span>\n * <input onChange={(e) => seekTo(parseTime(e.target.value))} />\n * ```\n */\nexport function useTimeFormat(): TimeFormatControls {\n const [timeFormat, setTimeFormat] = useState<TimeFormat>('hh:mm:ss.uuu');\n\n const formatTime = (seconds: number) => {\n return formatTimeUtil(seconds, timeFormat);\n };\n\n const parseTime = (timeString: string) => {\n return parseTimeUtil(timeString, timeFormat);\n };\n\n return {\n timeFormat,\n setTimeFormat,\n formatTime,\n parseTime,\n };\n}\n","import { useState, useCallback } from 'react';\n\nexport interface ZoomControls {\n samplesPerPixel: number;\n zoomIn: () => void;\n zoomOut: () => void;\n canZoomIn: boolean;\n canZoomOut: boolean;\n}\n\nexport interface UseZoomControlsProps {\n initialSamplesPerPixel: number;\n zoomLevels?: number[]; // Array of samples per pixel values (lower = more zoomed in)\n}\n\nconst DEFAULT_ZOOM_LEVELS = [256, 512, 1024, 2048, 4096, 8192];\n\nexport function useZoomControls({\n initialSamplesPerPixel,\n zoomLevels = DEFAULT_ZOOM_LEVELS,\n}: UseZoomControlsProps): ZoomControls {\n const [zoomIndex, setZoomIndex] = useState(() => {\n const index = zoomLevels.indexOf(initialSamplesPerPixel);\n return index !== -1 ? index : Math.floor(zoomLevels.length / 2);\n });\n\n const samplesPerPixel = zoomLevels[zoomIndex];\n const canZoomIn = zoomIndex > 0;\n const canZoomOut = zoomIndex < zoomLevels.length - 1;\n\n const zoomIn = useCallback(() => {\n setZoomIndex((prev) => Math.max(0, prev - 1));\n }, []);\n\n const zoomOut = useCallback(() => {\n setZoomIndex((prev) => Math.min(zoomLevels.length - 1, prev + 1));\n }, [zoomLevels.length]);\n\n return {\n samplesPerPixel,\n zoomIn,\n zoomOut,\n canZoomIn,\n canZoomOut,\n };\n}\n","import { useState, useCallback, RefObject } from 'react';\nimport { TonePlayout } from '@waveform-playlist/playout';\n\nexport interface UseMasterVolumeProps {\n playoutRef: RefObject<TonePlayout | null>;\n initialVolume?: number; // 0-1.0 (linear gain, consistent with Web Audio API)\n onVolumeChange?: (volume: number) => void;\n}\n\nexport interface MasterVolumeControls {\n masterVolume: number;\n setMasterVolume: (volume: number) => void;\n}\n\n/**\n * Hook for managing master volume control\n *\n * @example\n * ```tsx\n * const { masterVolume, setMasterVolume } = useMasterVolume({\n * playoutRef,\n * initialVolume: 1.0,\n * });\n *\n * <MasterVolumeControl\n * volume={masterVolume}\n * onChange={setMasterVolume}\n * />\n * ```\n */\nexport function useMasterVolume({\n playoutRef,\n initialVolume = 1.0,\n onVolumeChange,\n}: UseMasterVolumeProps): MasterVolumeControls {\n const [masterVolume, setMasterVolumeState] = useState(initialVolume);\n\n const setMasterVolume = useCallback((volume: number) => {\n setMasterVolumeState(volume);\n\n // Update the playout with linear gain (0-1.0 range)\n if (playoutRef.current) {\n playoutRef.current.setMasterGain(volume);\n }\n\n // Call optional callback\n onVolumeChange?.(volume);\n }, [playoutRef, onVolumeChange]);\n\n return {\n masterVolume,\n setMasterVolume,\n };\n}\n","import { useRef, useCallback } from 'react';\nimport type { EffectsFunction } from '@waveform-playlist/playout';\n// Import Tone.js classes directly for tree-shaking\nimport { Analyser } from 'tone';\n\n/**\n * Hook for master effects with frequency analyzer\n * Returns the analyser ref and the effects function to pass to WaveformPlaylistProvider\n *\n * For more advanced effects (reverb, delay, filters, etc.), use useDynamicEffects instead.\n */\nexport const useMasterAnalyser = (fftSize: number = 256) => {\n const analyserRef = useRef<any>(null);\n\n const masterEffects: EffectsFunction = useCallback((masterGainNode, destination, _isOffline) => {\n // Create analyser and connect it in parallel to monitor the output\n const analyserNode = new Analyser('fft', fftSize);\n masterGainNode.connect(analyserNode);\n\n // Connect master to destination as normal\n masterGainNode.connect(destination);\n\n // Store analyser for visualization\n analyserRef.current = analyserNode;\n\n return function cleanup() {\n // Cleanup when playlist is destroyed\n analyserNode.dispose();\n analyserRef.current = null;\n };\n }, [fftSize]);\n\n return { analyserRef, masterEffects };\n};\n","// src/types/clip.ts\nfunction createClip(options) {\n const {\n audioBuffer,\n startSample,\n offsetSamples = 0,\n gain = 1,\n name,\n color,\n fadeIn,\n fadeOut,\n waveformData\n } = options;\n const sampleRate = audioBuffer?.sampleRate ?? options.sampleRate ?? waveformData?.sample_rate;\n const sourceDurationSamples = audioBuffer?.length ?? options.sourceDurationSamples ?? (waveformData && sampleRate ? Math.ceil(waveformData.duration * sampleRate) : void 0);\n if (sampleRate === void 0) {\n throw new Error(\"createClip: sampleRate is required when audioBuffer is not provided (can use waveformData.sample_rate)\");\n }\n if (sourceDurationSamples === void 0) {\n throw new Error(\"createClip: sourceDurationSamples is required when audioBuffer is not provided (can use waveformData.duration)\");\n }\n if (audioBuffer && waveformData && audioBuffer.sampleRate !== waveformData.sample_rate) {\n console.warn(\n `Sample rate mismatch: audioBuffer (${audioBuffer.sampleRate}) vs waveformData (${waveformData.sample_rate}). Using audioBuffer sample rate. Waveform visualization may be slightly off.`\n );\n }\n const durationSamples = options.durationSamples ?? sourceDurationSamples;\n return {\n id: generateId(),\n audioBuffer,\n startSample,\n durationSamples,\n offsetSamples,\n sampleRate,\n sourceDurationSamples,\n gain,\n name,\n color,\n fadeIn,\n fadeOut,\n waveformData\n };\n}\nfunction createClipFromSeconds(options) {\n const {\n audioBuffer,\n startTime,\n offset = 0,\n gain = 1,\n name,\n color,\n fadeIn,\n fadeOut,\n waveformData\n } = options;\n const sampleRate = audioBuffer?.sampleRate ?? options.sampleRate ?? waveformData?.sample_rate;\n if (sampleRate === void 0) {\n throw new Error(\"createClipFromSeconds: sampleRate is required when audioBuffer is not provided (can use waveformData.sample_rate)\");\n }\n const sourceDuration = audioBuffer?.duration ?? options.sourceDuration ?? waveformData?.duration;\n if (sourceDuration === void 0) {\n throw new Error(\"createClipFromSeconds: sourceDuration is required when audioBuffer is not provided (can use waveformData.duration)\");\n }\n if (audioBuffer && waveformData && audioBuffer.sampleRate !== waveformData.sample_rate) {\n console.warn(\n `Sample rate mismatch: audioBuffer (${audioBuffer.sampleRate}) vs waveformData (${waveformData.sample_rate}). Using audioBuffer sample rate. Waveform visualization may be slightly off.`\n );\n }\n const duration = options.duration ?? sourceDuration;\n return createClip({\n audioBuffer,\n startSample: Math.round(startTime * sampleRate),\n durationSamples: Math.round(duration * sampleRate),\n offsetSamples: Math.round(offset * sampleRate),\n sampleRate,\n sourceDurationSamples: Math.ceil(sourceDuration * sampleRate),\n gain,\n name,\n color,\n fadeIn,\n fadeOut,\n waveformData\n });\n}\nfunction createTrack(options) {\n const {\n name,\n clips = [],\n muted = false,\n soloed = false,\n volume = 1,\n pan = 0,\n color,\n height\n } = options;\n return {\n id: generateId(),\n name,\n clips,\n muted,\n soloed,\n volume,\n pan,\n color,\n height\n };\n}\nfunction createTimeline(tracks, sampleRate = 44100, options) {\n const durationSamples = tracks.reduce((maxSamples, track) => {\n const trackSamples = track.clips.reduce((max, clip) => {\n return Math.max(max, clip.startSample + clip.durationSamples);\n }, 0);\n return Math.max(maxSamples, trackSamples);\n }, 0);\n const duration = durationSamples / sampleRate;\n return {\n tracks,\n duration,\n sampleRate,\n name: options?.name,\n tempo: options?.tempo,\n timeSignature: options?.timeSignature\n };\n}\nfunction generateId() {\n return `${Date.now()}-${Math.random().toString(36).substr(2, 9)}`;\n}\nfunction getClipsInRange(track, startSample, endSample) {\n return track.clips.filter((clip) => {\n const clipEnd = clip.startSample + clip.durationSamples;\n return clip.startSample < endSample && clipEnd > startSample;\n });\n}\nfunction getClipsAtSample(track, sample) {\n return track.clips.filter((clip) => {\n const clipEnd = clip.startSample + clip.durationSamples;\n return sample >= clip.startSample && sample < clipEnd;\n });\n}\nfunction clipsOverlap(clip1, clip2) {\n const clip1End = clip1.startSample + clip1.durationSamples;\n const clip2End = clip2.startSample + clip2.durationSamples;\n return clip1.startSample < clip2End && clip1End > clip2.startSample;\n}\nfunction sortClipsByTime(clips) {\n return [...clips].sort((a, b) => a.startSample - b.startSample);\n}\nfunction findGaps(track) {\n if (track.clips.length === 0) return [];\n const sorted = sortClipsByTime(track.clips);\n const gaps = [];\n for (let i = 0; i < sorted.length - 1; i++) {\n const currentClipEnd = sorted[i].startSample + sorted[i].durationSamples;\n const nextClipStart = sorted[i + 1].startSample;\n if (nextClipStart > currentClipEnd) {\n gaps.push({\n startSample: currentClipEnd,\n endSample: nextClipStart,\n durationSamples: nextClipStart - currentClipEnd\n });\n }\n }\n return gaps;\n}\n\n// src/types/index.ts\nvar InteractionState = /* @__PURE__ */ ((InteractionState2) => {\n InteractionState2[\"Cursor\"] = \"cursor\";\n InteractionState2[\"Select\"] = \"select\";\n InteractionState2[\"Shift\"] = \"shift\";\n InteractionState2[\"FadeIn\"] = \"fadein\";\n InteractionState2[\"FadeOut\"] = \"fadeout\";\n return InteractionState2;\n})(InteractionState || {});\n\n// src/utils/conversions.ts\nfunction samplesToSeconds(samples, sampleRate) {\n return samples / sampleRate;\n}\nfunction secondsToSamples(seconds, sampleRate) {\n return Math.ceil(seconds * sampleRate);\n}\nfunction samplesToPixels(samples, samplesPerPixel) {\n return Math.floor(samples / samplesPerPixel);\n}\nfunction pixelsToSamples(pixels, samplesPerPixel) {\n return Math.floor(pixels * samplesPerPixel);\n}\nfunction pixelsToSeconds(pixels, samplesPerPixel, sampleRate) {\n return pixels * samplesPerPixel / sampleRate;\n}\nfunction secondsToPixels(seconds, samplesPerPixel, sampleRate) {\n return Math.ceil(seconds * sampleRate / samplesPerPixel);\n}\nexport {\n InteractionState,\n clipsOverlap,\n createClip,\n createClipFromSeconds,\n createTimeline,\n createTrack,\n findGaps,\n getClipsAtSample,\n getClipsInRange,\n pixelsToSamples,\n pixelsToSeconds,\n samplesToPixels,\n samplesToSeconds,\n secondsToPixels,\n secondsToSamples,\n sortClipsByTime\n};\n//# sourceMappingURL=index.mjs.map","import { useState, useEffect, useRef, useCallback } from 'react';\nimport { ClipTrack, createTrack, createClipFromSeconds, type Fade, type TrackEffectsFunction, type WaveformDataObject } from '@waveform-playlist/core';\nimport * as Tone from 'tone';\n\n/**\n * Configuration for a single audio track to load\n *\n * Audio can be provided in three ways:\n * 1. `src` - URL to fetch and decode (standard loading)\n * 2. `audioBuffer` - Pre-loaded AudioBuffer (skip fetch/decode)\n * 3. `waveformData` only - Peaks-first rendering (audio loads later)\n *\n * For peaks-first rendering, just provide `waveformData` - the sample rate\n * and duration are derived from the waveform data automatically.\n */\nexport interface AudioTrackConfig {\n /** URL to audio file - used if audioBuffer not provided */\n src?: string;\n /** Pre-loaded AudioBuffer - skips fetch/decode if provided */\n audioBuffer?: AudioBuffer;\n name?: string;\n muted?: boolean;\n soloed?: boolean;\n volume?: number;\n pan?: number;\n color?: string;\n effects?: TrackEffectsFunction;\n // Multi-clip support\n startTime?: number; // When the clip starts on the timeline (default: 0)\n duration?: number; // Duration of the clip (default: full audio duration)\n offset?: number; // Offset into the source audio file (default: 0)\n // Fade support\n fadeIn?: Fade; // Fade in configuration\n fadeOut?: Fade; // Fade out configuration\n // Pre-computed waveform data (BBC audiowaveform format)\n // For peaks-first rendering, provide this without audioBuffer/src\n // Sample rate and duration are derived from waveformData.sample_rate and waveformData.duration\n waveformData?: WaveformDataObject;\n}\n\n/**\n * Options for useAudioTracks hook\n */\nexport interface UseAudioTracksOptions {\n /**\n * When true, tracks are added to the playlist progressively as they load,\n * rather than waiting for all tracks to finish loading.\n * Default: false (wait for all tracks)\n */\n progressive?: boolean;\n}\n\n/**\n * Hook to load audio from URLs and convert to ClipTrack format\n *\n * This hook fetches audio files, decodes them, and creates ClipTrack objects\n * with a single clip per track. Supports custom positioning for multi-clip arrangements.\n *\n * @param configs - Array of audio track configurations\n * @param options - Optional configuration for loading behavior\n * @returns Object with tracks array, loading state, and progress info\n *\n * @example\n * ```typescript\n * // Basic usage (clips positioned at start)\n * const { tracks, loading, error } = useAudioTracks([\n * { src: 'audio/vocals.mp3', name: 'Vocals' },\n * { src: 'audio/drums.mp3', name: 'Drums' },\n * ]);\n *\n * // Progressive loading (tracks appear as they load)\n * const { tracks, loading, loadedCount, totalCount } = useAudioTracks(\n * [{ src: 'audio/vocals.mp3' }, { src: 'audio/drums.mp3' }],\n * { progressive: true }\n * );\n *\n * // Pre-loaded AudioBuffer (skip fetch/decode)\n * const { tracks } = useAudioTracks([\n * { audioBuffer: myPreloadedBuffer, name: 'Pre-loaded' },\n * ]);\n *\n * // Peaks-first rendering (instant visual, audio loads later)\n * const { tracks } = useAudioTracks([\n * { waveformData: preloadedPeaks, name: 'Peaks Only' }, // Renders immediately\n * ]);\n *\n * if (loading) return <div>Loading {loadedCount}/{totalCount}...</div>;\n * if (error) return <div>Error: {error}</div>;\n *\n * return <WaveformPlaylistProvider tracks={tracks}>...</WaveformPlaylistProvider>;\n * ```\n */\nexport function useAudioTracks(\n configs: AudioTrackConfig[],\n options: UseAudioTracksOptions = {}\n) {\n const { progressive = false } = options;\n const [tracks, setTracks] = useState<ClipTrack[]>([]);\n const [loading, setLoading] = useState(true);\n const [error, setError] = useState<string | null>(null);\n const [loadedCount, setLoadedCount] = useState(0);\n\n // Track which configs need audio loading vs already have data\n const totalCount = configs.length;\n\n useEffect(() => {\n if (configs.length === 0) {\n setTracks([]);\n setLoading(false);\n setLoadedCount(0);\n return;\n }\n\n let cancelled = false;\n // Track loaded tracks by their config index for progressive mode\n const loadedTracksMap = new Map<number, ClipTrack>();\n\n const createTrackFromConfig = (\n config: AudioTrackConfig,\n index: number,\n audioBuffer?: AudioBuffer\n ): ClipTrack => {\n // Use provided audioBuffer, config's audioBuffer, or undefined for peaks-only\n const buffer = audioBuffer ?? config.audioBuffer;\n\n // For peaks-first rendering, we need waveformData if no buffer\n if (!buffer && !config.waveformData) {\n throw new Error(\n `Track ${index + 1}: Must provide src, audioBuffer, or waveformData`\n );\n }\n\n // Determine source duration for clip creation\n const sourceDuration = buffer?.duration ?? config.waveformData?.duration;\n\n // Create clip - createClipFromSeconds handles deriving sampleRate from waveformData\n const clip = createClipFromSeconds({\n audioBuffer: buffer,\n startTime: config.startTime ?? 0,\n duration: config.duration ?? sourceDuration,\n offset: config.offset ?? 0,\n name: config.name || `Track ${index + 1}`,\n fadeIn: config.fadeIn,\n fadeOut: config.fadeOut,\n waveformData: config.waveformData,\n });\n\n // Validate clip values\n if (isNaN(clip.startSample) || isNaN(clip.durationSamples) || isNaN(clip.offsetSamples)) {\n console.error('Invalid clip values:', clip);\n throw new Error(`Invalid clip values for track ${index + 1}`);\n }\n\n // Create the track with the single clip\n const track: ClipTrack = {\n ...createTrack({\n name: config.name || `Track ${index + 1}`,\n clips: [clip],\n muted: config.muted ?? false,\n soloed: config.soloed ?? false,\n volume: config.volume ?? 1.0,\n pan: config.pan ?? 0,\n color: config.color,\n }),\n effects: config.effects,\n };\n\n return track;\n };\n\n const loadTracks = async () => {\n try {\n setLoading(true);\n setError(null);\n setLoadedCount(0);\n\n const audioContext = Tone.getContext().rawContext as AudioContext;\n\n // Process each config\n const loadPromises = configs.map(async (config, index) => {\n // Case 1: Already have audioBuffer - no loading needed\n if (config.audioBuffer) {\n const track = createTrackFromConfig(config, index, config.audioBuffer);\n\n if (progressive && !cancelled) {\n loadedTracksMap.set(index, track);\n setLoadedCount(prev => prev + 1);\n // Update tracks maintaining order\n setTracks(\n Array.from({ length: configs.length }, (_, i) => loadedTracksMap.get(i))\n .filter((t): t is ClipTrack => t !== undefined)\n );\n }\n\n return track;\n }\n\n // Case 2: Have waveformData but no src - peaks-only (no audio to load)\n if (!config.src && config.waveformData) {\n const track = createTrackFromConfig(config, index);\n\n if (progressive && !cancelled) {\n loadedTracksMap.set(index, track);\n setLoadedCount(prev => prev + 1);\n setTracks(\n Array.from({ length: configs.length }, (_, i) => loadedTracksMap.get(i))\n .filter((t): t is ClipTrack => t !== undefined)\n );\n }\n\n return track;\n }\n\n // Case 3: Need to fetch and decode audio from src\n if (!config.src) {\n throw new Error(`Track ${index + 1}: Must provide src, audioBuffer, or waveformData`);\n }\n\n const response = await fetch(config.src);\n if (!response.ok) {\n throw new Error(`Failed to fetch ${config.src}: ${response.statusText}`);\n }\n\n const arrayBuffer = await response.arrayBuffer();\n const audioBuffer = await audioContext.decodeAudioData(arrayBuffer);\n\n // Validate audioBuffer\n if (!audioBuffer || !audioBuffer.sampleRate || !audioBuffer.duration) {\n throw new Error(`Invalid audio buffer for ${config.src}`);\n }\n\n const track = createTrackFromConfig(config, index, audioBuffer);\n\n if (progressive && !cancelled) {\n loadedTracksMap.set(index, track);\n setLoadedCount(prev => prev + 1);\n // Update tracks maintaining original config order\n setTracks(\n Array.from({ length: configs.length }, (_, i) => loadedTracksMap.get(i))\n .filter((t): t is ClipTrack => t !== undefined)\n );\n }\n\n return track;\n });\n\n const loadedTracks = await Promise.all(loadPromises);\n\n if (!cancelled) {\n // For non-progressive mode, set all tracks at once\n if (!progressive) {\n setTracks(loadedTracks);\n setLoadedCount(loadedTracks.length);\n }\n setLoading(false);\n }\n } catch (err) {\n if (!cancelled) {\n const errorMessage = err instanceof Error ? err.message : 'Unknown error loading audio';\n setError(errorMessage);\n setLoading(false);\n console.error('Error loading audio tracks:', err);\n }\n }\n };\n\n loadTracks();\n\n // Cleanup function to prevent state updates if component unmounts\n return () => {\n cancelled = true;\n };\n }, [configs, progressive]);\n\n return { tracks, loading, error, loadedCount, totalCount };\n}\n","import React from 'react';\nimport type { DragEndEvent } from '@dnd-kit/core';\nimport type { ClipTrack } from '@waveform-playlist/core';\n\ninterface UseClipDragHandlersOptions {\n tracks: ClipTrack[];\n onTracksChange: (tracks: ClipTrack[]) => void;\n samplesPerPixel: number;\n sampleRate: number;\n}\n\n/**\n * Custom hook for handling clip drag operations (movement and trimming)\n *\n * Provides drag handlers and collision modifier for use with @dnd-kit/core DndContext.\n * Handles both clip movement (dragging entire clips) and boundary trimming (adjusting clip edges).\n *\n * @example\n * ```tsx\n * const { onDragStart, onDragMove, onDragEnd, collisionModifier } = useClipDragHandlers({\n * tracks,\n * onTracksChange: setTracks,\n * samplesPerPixel,\n * sampleRate,\n * });\n *\n * return (\n * <DndContext\n * onDragStart={onDragStart}\n * onDragMove={onDragMove}\n * onDragEnd={onDragEnd}\n * modifiers={[restrictToHorizontalAxis, collisionModifier]}\n * >\n * <Waveform showClipHeaders={true} />\n * </DndContext>\n * );\n * ```\n */\nexport function useClipDragHandlers({\n tracks,\n onTracksChange,\n samplesPerPixel,\n sampleRate,\n}: UseClipDragHandlersOptions) {\n // Store original clip state when drag starts (for cumulative delta application)\n const originalClipStateRef = React.useRef<{\n offsetSamples: number;\n durationSamples: number;\n startSample: number;\n } | null>(null);\n\n // Custom modifier for real-time collision detection during clip movement\n const collisionModifier = React.useCallback(\n (args: { transform: { x: number; y: number }; active: any }) => {\n const { transform, active } = args;\n\n if (!active?.data?.current) return { ...transform, scaleX: 1, scaleY: 1 };\n\n const { trackIndex, clipIndex, boundary } = active.data.current as {\n clipId: string;\n trackIndex: number;\n clipIndex: number;\n boundary?: 'left' | 'right';\n };\n\n // For boundary trimming, skip modifier - onDragMove handles constraints\n if (boundary) {\n return { ...transform, scaleX: 1, scaleY: 1 };\n }\n\n const track = tracks[trackIndex];\n if (!track) return { ...transform, scaleX: 1, scaleY: 1 };\n\n const clip = track.clips[clipIndex];\n if (!clip) return { ...transform, scaleX: 1, scaleY: 1 };\n\n // Convert sample-based properties to time for calculations\n const clipStartTime = clip.startSample / sampleRate;\n const clipDuration = clip.durationSamples / sampleRate;\n\n // Convert pixel delta to time delta\n const timeDelta = (transform.x * samplesPerPixel) / sampleRate;\n\n // Handle clip movement (not trimming)\n let newStartTime = clipStartTime + timeDelta;\n\n // Get sorted clips for collision detection\n const sortedClips = [...track.clips].sort((a, b) => (a.startSample - b.startSample));\n const sortedIndex = sortedClips.findIndex((c) => c === clip);\n\n // Constraint 1: Cannot go before time 0\n newStartTime = Math.max(0, newStartTime);\n\n // Constraint 2: Cannot overlap with previous clip\n const previousClip = sortedIndex > 0 ? sortedClips[sortedIndex - 1] : null;\n if (previousClip) {\n const previousEndTime = (previousClip.startSample + previousClip.durationSamples) / sampleRate;\n newStartTime = Math.max(newStartTime, previousEndTime);\n }\n\n // Constraint 3: Cannot overlap with next clip\n const nextClip = sortedIndex < sortedClips.length - 1 ? sortedClips[sortedIndex + 1] : null;\n if (nextClip) {\n const newEndTime = newStartTime + clipDuration;\n const nextClipStartTime = nextClip.startSample / sampleRate;\n if (newEndTime > nextClipStartTime) {\n newStartTime = nextClipStartTime - clipDuration;\n }\n }\n\n // Convert constrained time back to pixel delta\n const constrainedTimeDelta = newStartTime - clipStartTime;\n const constrainedX = (constrainedTimeDelta * sampleRate) / samplesPerPixel;\n\n return {\n ...transform,\n x: constrainedX,\n scaleX: 1,\n scaleY: 1,\n };\n },\n [tracks, samplesPerPixel, sampleRate]\n );\n\n const onDragStart = React.useCallback(\n (event: { active: any }) => {\n const { active } = event;\n const { boundary } = active.data.current as { boundary?: 'left' | 'right' };\n\n // Only store state for boundary trimming operations\n if (!boundary) {\n originalClipStateRef.current = null;\n return;\n }\n\n const { trackIndex, clipIndex } = active.data.current as {\n clipId: string;\n trackIndex: number;\n clipIndex: number;\n boundary: 'left' | 'right';\n };\n\n const track = tracks[trackIndex];\n const clip = track?.clips[clipIndex];\n\n if (clip) {\n // Store original clip state for cumulative delta application\n originalClipStateRef.current = {\n offsetSamples: clip.offsetSamples,\n durationSamples: clip.durationSamples,\n startSample: clip.startSample,\n };\n }\n },\n [tracks]\n );\n\n const onDragMove = React.useCallback(\n (event: { active: any; delta: { x: number; y: number } }) => {\n const { active, delta } = event;\n\n // Only update for boundary trimming operations (not clip movement)\n const { boundary } = active.data.current as { boundary?: 'left' | 'right' };\n if (!boundary) return;\n\n // Need original clip state to apply cumulative delta\n if (!originalClipStateRef.current) return;\n\n // Extract clip metadata\n const { trackIndex, clipIndex } = active.data.current as {\n clipId: string;\n trackIndex: number;\n clipIndex: number;\n boundary: 'left' | 'right';\n };\n\n const sampleDelta = delta.x * samplesPerPixel;\n const MIN_DURATION_SAMPLES = Math.floor(0.1 * sampleRate); // 0.1 seconds minimum\n\n // Get original clip state (stored on drag start)\n const originalClip = originalClipStateRef.current;\n\n // Update tracks in real-time during drag\n const newTracks = tracks.map((track, tIdx) => {\n if (tIdx !== trackIndex) return track;\n\n const sortedClips = [...track.clips].sort((a, b) => a.startSample - b.startSample);\n const sortedIndex = sortedClips.findIndex((clip) => clip === track.clips[clipIndex]);\n\n const newClips = track.clips.map((clip, cIdx) => {\n if (cIdx !== clipIndex) return clip;\n\n // Use sourceDurationSamples (works for both audio and peaks-only clips)\n const audioBufferDurationSamples = clip.sourceDurationSamples;\n\n if (boundary === 'left') {\n // Left boundary drag: moving left (negative delta) expands clip, moving right shrinks it\n // The RIGHT edge stays fixed. We're moving the LEFT edge.\n //\n // When dragging left (sampleDelta < 0):\n // - startSample decreases (moves left)\n // - durationSamples increases (clip gets longer)\n // - offsetSamples decreases (reveal earlier audio from buffer)\n //\n // When dragging right (sampleDelta > 0):\n // - startSample increases (moves right)\n // - durationSamples decreases (clip gets shorter)\n // - offsetSamples increases (hide earlier audio)\n\n // Calculate the constrained delta first, then apply it uniformly\n let constrainedDelta = Math.floor(sampleDelta);\n\n // Constraint 1: startSample cannot go below 0 (dragging left limit)\n // newStartSample = originalClip.startSample + delta >= 0\n // delta >= -originalClip.startSample\n const minDeltaForStart = -originalClip.startSample;\n if (constrainedDelta < minDeltaForStart) {\n constrainedDelta = minDeltaForStart;\n }\n\n // Constraint 2: offsetSamples cannot go below 0 (can't reveal audio before buffer start)\n // newOffsetSamples = originalClip.offsetSamples + delta >= 0\n // delta >= -originalClip.offsetSamples\n const minDeltaForOffset = -originalClip.offsetSamples;\n if (constrainedDelta < minDeltaForOffset) {\n constrainedDelta = minDeltaForOffset;\n }\n\n // Constraint 3: Cannot overlap with previous clip (dragging left limit)\n const previousClip = sortedIndex > 0 ? sortedClips[sortedIndex - 1] : null;\n if (previousClip) {\n const previousEndSample = previousClip.startSample + previousClip.durationSamples;\n // newStartSample = originalClip.startSample + delta >= previousEndSample\n // delta >= previousEndSample - originalClip.startSample\n const minDeltaForPrevious = previousEndSample - originalClip.startSample;\n if (constrainedDelta < minDeltaForPrevious) {\n constrainedDelta = minDeltaForPrevious;\n }\n }\n\n // Constraint 4: Minimum duration (dragging right limit)\n // newDurationSamples = originalClip.durationSamples - delta >= MIN_DURATION_SAMPLES\n // -delta >= MIN_DURATION_SAMPLES - originalClip.durationSamples\n // delta <= originalClip.durationSamples - MIN_DURATION_SAMPLES\n const maxDeltaForMinDuration = originalClip.durationSamples - MIN_DURATION_SAMPLES;\n if (constrainedDelta > maxDeltaForMinDuration) {\n constrainedDelta = maxDeltaForMinDuration;\n }\n\n // Constraint 5: Cannot exceed audio buffer length\n // newOffsetSamples + newDurationSamples <= audioBufferDurationSamples\n // (originalClip.offsetSamples + delta) + (originalClip.durationSamples - delta) <= audioBufferDurationSamples\n // This simplifies to: originalClip.offsetSamples + originalClip.durationSamples <= audioBufferDurationSamples\n // This is always true if the clip was valid to begin with, so no constraint needed here\n\n // Now apply the constrained delta\n const newOffsetSamples = originalClip.offsetSamples + constrainedDelta;\n const newDurationSamples = originalClip.durationSamples - constrainedDelta;\n const newStartSample = originalClip.startSample + constrainedDelta;\n\n return {\n ...clip,\n offsetSamples: newOffsetSamples,\n durationSamples: newDurationSamples,\n startSample: newStartSample\n };\n } else {\n // Right boundary - only update duration\n // Apply cumulative delta to ORIGINAL state (not current state)\n let newDurationSamples = Math.floor(originalClip.durationSamples + sampleDelta);\n newDurationSamples = Math.max(MIN_DURATION_SAMPLES, newDurationSamples);\n\n if (originalClip.offsetSamples + newDurationSamples > audioBufferDurationSamples) {\n newDurationSamples = audioBufferDurationSamples - originalClip.offsetSamples;\n }\n\n const nextClip = sortedIndex < sortedClips.length - 1 ? sortedClips[sortedIndex + 1] : null;\n if (nextClip) {\n const newEndSample = originalClip.startSample + newDurationSamples;\n if (newEndSample > nextClip.startSample) {\n newDurationSamples = nextClip.startSample - originalClip.startSample;\n newDurationSamples = Math.max(MIN_DURATION_SAMPLES, newDurationSamples);\n }\n }\n\n return { ...clip, durationSamples: newDurationSamples };\n }\n });\n\n return { ...track, clips: newClips };\n });\n\n onTracksChange(newTracks);\n },\n [tracks, onTracksChange, samplesPerPixel, sampleRate]\n );\n\n const onDragEnd = React.useCallback(\n (event: DragEndEvent) => {\n const { active, delta } = event;\n\n // Extract clip metadata from drag data\n const { trackIndex, clipIndex, boundary } = active.data.current as {\n clipId: string;\n trackIndex: number;\n clipIndex: number;\n boundary?: 'left' | 'right';\n };\n\n // Convert pixel delta to samples\n const sampleDelta = delta.x * samplesPerPixel;\n\n // Check if this is a boundary trim operation\n if (boundary) {\n // For boundary trimming, onDragMove already updated the tracks\n // onDragEnd doesn't need to do anything (state is already correct)\n // Just clear the original clip state ref\n originalClipStateRef.current = null;\n return;\n }\n\n // Handle clip movement (not trimming)\n const newTracks = tracks.map((track, tIdx) => {\n if (tIdx !== trackIndex) return track;\n\n // Get sorted clips for collision detection\n const sortedClips = [...track.clips].sort((a, b) => a.startSample - b.startSample);\n const sortedIndex = sortedClips.findIndex((clip) => clip === track.clips[clipIndex]);\n\n // Update the specific clip in this track\n const newClips = track.clips.map((clip, cIdx) => {\n if (cIdx !== clipIndex) return clip;\n\n // Calculate desired new start sample\n let newStartSample = Math.floor(clip.startSample + sampleDelta);\n\n // Collision detection constraints:\n // 1. Cannot go before sample 0\n newStartSample = Math.max(0, newStartSample);\n\n // 2. Cannot overlap with previous clip\n const previousClip = sortedIndex > 0 ? sortedClips[sortedIndex - 1] : null;\n if (previousClip) {\n const previousEndSample = previousClip.startSample + previousClip.durationSamples;\n newStartSample = Math.max(newStartSample, previousEndSample);\n }\n\n // 3. Cannot overlap with next clip\n const nextClip = sortedIndex < sortedClips.length - 1 ? sortedClips[sortedIndex + 1] : null;\n if (nextClip) {\n const newEndSample = newStartSample + clip.durationSamples;\n if (newEndSample > nextClip.startSample) {\n // Push back to be adjacent to next clip\n newStartSample = nextClip.startSample - clip.durationSamples;\n }\n }\n\n return {\n ...clip,\n startSample: newStartSample,\n };\n });\n\n return {\n ...track,\n clips: newClips,\n };\n });\n\n onTracksChange(newTracks);\n },\n [tracks, onTracksChange, samplesPerPixel, sampleRate]\n );\n\n return {\n onDragStart,\n onDragMove,\n onDragEnd,\n collisionModifier,\n };\n}\n","import React from 'react';\nimport type { AnnotationType } from '@waveform-playlist/annotations';\n\nconst LINK_THRESHOLD = 0.01; // Consider edges \"linked\" if within 10ms\n\ninterface UseAnnotationDragHandlersOptions {\n annotations: AnnotationType[];\n onAnnotationsChange: (annotations: AnnotationType[]) => void;\n samplesPerPixel: number;\n sampleRate: number;\n duration: number;\n linkEndpoints: boolean;\n}\n\n/**\n * Custom hook for handling annotation drag operations (boundary trimming)\n *\n * Provides drag handlers for use with @dnd-kit/core DndContext.\n * Handles annotation boundary resizing with linked endpoints support.\n *\n * @example\n * ```tsx\n * const { onDragStart, onDragMove, onDragEnd } = useAnnotationDragHandlers({\n * annotations,\n * onAnnotationsChange: setAnnotations,\n * samplesPerPixel,\n * sampleRate,\n * duration,\n * linkEndpoints,\n * });\n *\n * return (\n * <DndContext\n * onDragStart={onDragStart}\n * onDragMove={onDragMove}\n * onDragEnd={onDragEnd}\n * modifiers={[restrictToHorizontalAxis]}\n * >\n * {renderAnnotations()}\n * </DndContext>\n * );\n * ```\n */\nexport function useAnnotationDragHandlers({\n annotations,\n onAnnotationsChange,\n samplesPerPixel,\n sampleRate,\n duration,\n linkEndpoints,\n}: UseAnnotationDragHandlersOptions) {\n // Store original annotation state when drag starts (for cumulative delta application)\n const originalAnnotationStateRef = React.useRef<{\n start: number;\n end: number;\n annotationIndex: number;\n } | null>(null);\n\n const onDragStart = React.useCallback(\n (event: { active: any }) => {\n const { active } = event;\n const data = active.data.current as {\n annotationId: string;\n annotationIndex: number;\n edge: 'start' | 'end';\n };\n\n if (!data || data.annotationIndex === undefined) {\n originalAnnotationStateRef.current = null;\n return;\n }\n\n const annotation = annotations[data.annotationIndex];\n if (annotation) {\n originalAnnotationStateRef.current = {\n start: annotation.start,\n end: annotation.end,\n annotationIndex: data.annotationIndex,\n };\n }\n },\n [annotations]\n );\n\n const onDragMove = React.useCallback(\n (event: { active: any; delta: { x: number; y: number } }) => {\n const { active, delta } = event;\n\n if (!originalAnnotationStateRef.current) {\n return;\n }\n\n const data = active.data.current as {\n annotationId: string;\n annotationIndex: number;\n edge: 'start' | 'end';\n };\n\n if (!data) return;\n\n const { edge, annotationIndex } = data;\n const originalState = originalAnnotationStateRef.current;\n\n // Convert pixel delta to time delta\n const timeDelta = (delta.x * samplesPerPixel) / sampleRate;\n\n // Apply delta to original state\n const newTime = edge === 'start'\n ? originalState.start + timeDelta\n : originalState.end + timeDelta;\n\n // Update annotations using the boundary logic\n const updatedAnnotations = updateAnnotationBoundaries({\n annotationIndex,\n newTime,\n isDraggingStart: edge === 'start',\n annotations,\n duration,\n linkEndpoints,\n });\n\n onAnnotationsChange(updatedAnnotations);\n },\n [annotations, onAnnotationsChange, samplesPerPixel, sampleRate, duration, linkEndpoints]\n );\n\n const onDragEnd = React.useCallback(() => {\n originalAnnotationStateRef.current = null;\n }, []);\n\n return {\n onDragStart,\n onDragMove,\n onDragEnd,\n };\n}\n\n/**\n * Updates annotation boundaries based on drag operations.\n * Handles linked endpoints and collision detection.\n */\nfunction updateAnnotationBoundaries({\n annotationIndex,\n newTime,\n isDraggingStart,\n annotations,\n duration,\n linkEndpoints: shouldLinkEndpoints,\n}: {\n annotationIndex: number;\n newTime: number;\n isDraggingStart: boolean;\n annotations: AnnotationType[];\n duration: number;\n linkEndpoints: boolean;\n}): AnnotationType[] {\n const updatedAnnotations = [...annotations];\n const annotation = annotations[annotationIndex];\n\n if (isDraggingStart) {\n // Dragging start edge\n const constrainedStart = Math.min(annotation.end - 0.1, Math.max(0, newTime));\n const delta = constrainedStart - annotation.start;\n\n updatedAnnotations[annotationIndex] = {\n ...annotation,\n start: constrainedStart,\n };\n\n if (shouldLinkEndpoints && annotationIndex > 0) {\n // Link Endpoints mode: handle both already-linked and collision scenarios\n const prevAnnotation = updatedAnnotations[annotationIndex - 1];\n\n if (Math.abs(prevAnnotation.end - annotation.start) < LINK_THRESHOLD) {\n // Already linked: move previous annotation's end together with this start\n updatedAnnotations[annotationIndex - 1] = {\n ...prevAnnotation,\n end: Math.max(prevAnnotation.start + 0.1, prevAnnotation.end + delta),\n };\n } else if (constrainedStart <= prevAnnotation.end) {\n // Dragged past previous annotation: snap to link them together\n updatedAnnotations[annotationIndex] = {\n ...updatedAnnotations[annotationIndex],\n start: prevAnnotation.end,\n };\n }\n } else if (!shouldLinkEndpoints && annotationIndex > 0 && constrainedStart < updatedAnnotations[annotationIndex - 1].end) {\n // Collision detection: push previous annotation's end back\n updatedAnnotations[annotationIndex - 1] = {\n ...updatedAnnotations[annotationIndex - 1],\n end: constrainedStart,\n };\n }\n } else {\n // Dragging end edge\n const constrainedEnd = Math.max(annotation.start + 0.1, Math.min(newTime, duration));\n const delta = constrainedEnd - annotation.end;\n\n updatedAnnotations[annotationIndex] = {\n ...annotation,\n end: constrainedEnd,\n };\n\n if (shouldLinkEndpoints && annotationIndex < updatedAnnotations.length - 1) {\n // Link Endpoints mode: handle both already-linked and collision scenarios\n const nextAnnotation = updatedAnnotations[annotationIndex + 1];\n\n if (Math.abs(nextAnnotation.start - annotation.end) < LINK_THRESHOLD) {\n // Already linked: move next annotation's start together with this end\n const newStart = nextAnnotation.start + delta;\n updatedAnnotations[annotationIndex + 1] = {\n ...nextAnnotation,\n start: Math.min(nextAnnotation.end - 0.1, newStart),\n };\n\n // Cascade linked endpoints\n let currentIndex = annotationIndex + 1;\n while (currentIndex < updatedAnnotations.length - 1) {\n const current = updatedAnnotations[currentIndex];\n const next = updatedAnnotations[currentIndex + 1];\n\n if (Math.abs(next.start - current.end) < LINK_THRESHOLD) {\n const nextDelta = current.end - annotations[currentIndex].end;\n updatedAnnotations[currentIndex + 1] = {\n ...next,\n start: Math.min(next.end - 0.1, next.start + nextDelta),\n };\n currentIndex++;\n } else {\n break; // No more linked endpoints\n }\n }\n } else if (constrainedEnd >= nextAnnotation.start) {\n // Dragged past next annotation: snap to link them together\n updatedAnnotations[annotationIndex] = {\n ...updatedAnnotations[annotationIndex],\n end: nextAnnotation.start,\n };\n }\n } else if (!shouldLinkEndpoints && annotationIndex < updatedAnnotations.length - 1 && constrainedEnd > updatedAnnotations[annotationIndex + 1].start) {\n // Collision detection: push next annotation's start forward\n const nextAnnotation = updatedAnnotations[annotationIndex + 1];\n\n updatedAnnotations[annotationIndex + 1] = {\n ...nextAnnotation,\n start: constrainedEnd,\n };\n\n // Cascade collisions\n let currentIndex = annotationIndex + 1;\n while (currentIndex < updatedAnnotations.length - 1) {\n const current = updatedAnnotations[currentIndex];\n const next = updatedAnnotations[currentIndex + 1];\n\n if (current.end > next.start) {\n updatedAnnotations[currentIndex + 1] = {\n ...next,\n start: current.end,\n };\n currentIndex++;\n } else {\n break; // No more collisions\n }\n }\n }\n }\n\n return updatedAnnotations;\n}\n","/**\n * Hook for configuring @dnd-kit sensors for clip dragging\n *\n * Provides consistent drag activation behavior across all examples.\n * Supports both desktop (immediate feedback) and mobile (delay-based) interactions.\n */\n\nimport { useSensor, useSensors, PointerSensor, TouchSensor, MouseSensor } from '@dnd-kit/core';\n\nexport interface DragSensorOptions {\n /**\n * Enable mobile-optimized touch handling with delay-based activation.\n * When true, uses TouchSensor with 250ms delay to distinguish drag from scroll.\n * When false (default), uses PointerSensor with 1px activation for immediate feedback.\n */\n touchOptimized?: boolean;\n /**\n * Delay in milliseconds before touch drag activates (only when touchOptimized is true).\n * Default: 250ms - long enough to distinguish from scroll intent\n */\n touchDelay?: number;\n /**\n * Distance tolerance during touch delay (only when touchOptimized is true).\n * If finger moves more than this during delay, drag is cancelled.\n * Default: 5px - allows slight finger movement\n */\n touchTolerance?: number;\n /**\n * Distance in pixels before mouse drag activates.\n * Default: 1px for immediate feedback on desktop\n */\n mouseDistance?: number;\n}\n\n/**\n * Returns configured sensors for @dnd-kit drag operations\n *\n * @param options - Configuration options for drag sensors\n * @returns Configured sensors appropriate for the interaction mode\n *\n * @example\n * // Desktop-optimized (default)\n * const sensors = useDragSensors();\n *\n * @example\n * // Mobile-optimized with touch delay\n * const sensors = useDragSensors({ touchOptimized: true });\n *\n * @example\n * // Custom touch settings\n * const sensors = useDragSensors({\n * touchOptimized: true,\n * touchDelay: 300,\n * touchTolerance: 8\n * });\n */\nexport function useDragSensors(options: DragSensorOptions = {}) {\n const {\n touchOptimized = false,\n touchDelay = 250,\n touchTolerance = 5,\n mouseDistance = 1,\n } = options;\n\n // Touch-optimized: Use separate MouseSensor and TouchSensor\n // This allows different activation constraints for each input type\n const mouseSensor = useSensor(MouseSensor, {\n activationConstraint: {\n distance: mouseDistance,\n },\n });\n\n const touchSensor = useSensor(TouchSensor, {\n activationConstraint: touchOptimized\n ? {\n // Delay-based activation for mobile - wait before starting drag\n // This allows users to scroll without accidentally triggering drag\n delay: touchDelay,\n tolerance: touchTolerance,\n }\n : {\n // Distance-based activation for non-optimized mode\n distance: mouseDistance,\n },\n });\n\n // Non-optimized: Use PointerSensor for unified handling (original behavior)\n const pointerSensor = useSensor(PointerSensor, {\n activationConstraint: {\n distance: mouseDistance,\n },\n });\n\n // When touch-optimized, use separate sensors for better control\n // Otherwise, use unified PointerSensor for backwards compatibility\n return useSensors(\n ...(touchOptimized ? [mouseSensor, touchSensor] : [pointerSensor])\n );\n}\n","import { useCallback } from 'react';\nimport { type ClipTrack, createClip } from '@waveform-playlist/core';\nimport { usePlaybackAnimation, usePlaylistState } from '../WaveformPlaylistContext';\n\nexport interface UseClipSplittingOptions {\n tracks: ClipTrack[];\n onTracksChange: (tracks: ClipTrack[]) => void;\n sampleRate: number;\n samplesPerPixel: number;\n}\n\nexport interface UseClipSplittingResult {\n splitClipAtPlayhead: () => boolean;\n splitClipAt: (trackIndex: number, clipIndex: number, splitTime: number) => boolean;\n}\n\n/**\n * Hook for splitting clips at the playhead or at a specific time\n *\n * @param options - Configuration options\n * @returns Object with split functions\n *\n * @example\n * ```tsx\n * const { splitClipAtPlayhead } = useClipSplitting({\n * tracks,\n * onTracksChange: setTracks,\n * currentTime,\n * });\n *\n * // In keyboard handler\n * const handleKeyPress = (e: KeyboardEvent) => {\n * if (e.key === 's' || e.key === 'S') {\n * splitClipAtPlayhead();\n * }\n * };\n * ```\n */\nexport const useClipSplitting = (options: UseClipSplittingOptions): UseClipSplittingResult => {\n const { tracks, onTracksChange, sampleRate } = options;\n const { currentTimeRef } = usePlaybackAnimation();\n const { selectedTrackId } = usePlaylistState();\n\n /**\n * Split a specific clip at a given time\n *\n * @param trackIndex - Index of the track containing the clip\n * @param clipIndex - Index of the clip within the track\n * @param splitTime - Timeline position where to split (in seconds)\n * @returns true if split was successful, false otherwise\n */\n const splitClipAt = useCallback(\n (trackIndex: number, clipIndex: number, splitTime: number): boolean => {\n // Work with samples and pixels (all integers!) to avoid floating-point precision issues\n // Key insight: A pixel represents a RANGE of samples (samplesPerPixel samples)\n // By working in samples, we eliminate all floating-point errors\n const { sampleRate, samplesPerPixel } = options;\n\n const track = tracks[trackIndex];\n if (!track) return false;\n\n const clip = track.clips[clipIndex];\n if (!clip) return false;\n\n // Convert clip positions from samples to seconds for bounds checking\n const clipStartTime = clip.startSample / sampleRate;\n const clipEndTime = (clip.startSample + clip.durationSamples) / sampleRate;\n\n // Validate that split time is within clip bounds\n if (splitTime <= clipStartTime || splitTime >= clipEndTime) {\n console.warn('Split time is outside clip bounds');\n return false;\n }\n\n // Convert split time from seconds to samples (round to nearest sample)\n const splitSample = Math.round(splitTime * sampleRate);\n\n // Calculate pixel positions from sample positions using integer division\n const splitPixel = Math.floor(splitSample / samplesPerPixel);\n const clipEndSample = clip.startSample + clip.durationSamples;\n\n // Calculate sample positions from exact pixel boundaries\n // Both clips share the same boundary: the start of the split pixel\n const snappedSplitSample = splitPixel * samplesPerPixel;\n\n // First clip: starts at clip's original start, ends at split pixel boundary\n const firstClipStartSample = clip.startSample;\n const firstClipDurationSamples = snappedSplitSample - firstClipStartSample;\n\n // Second clip: starts at split pixel boundary, ends at clip's original end\n const secondClipStartSample = snappedSplitSample;\n const secondClipDurationSamples = clipEndSample - secondClipStartSample;\n\n // Calculate offset increment for second clip (in samples)\n const offsetIncrement = snappedSplitSample - clip.startSample;\n\n // Create first clip (from start to split point)\n const firstClip = createClip({\n audioBuffer: clip.audioBuffer,\n startSample: firstClipStartSample,\n durationSamples: firstClipDurationSamples,\n offsetSamples: clip.offsetSamples,\n sampleRate: clip.sampleRate,\n sourceDurationSamples: clip.sourceDurationSamples,\n gain: clip.gain,\n name: clip.name ? `${clip.name} (1)` : undefined,\n color: clip.color,\n fadeIn: clip.fadeIn,\n waveformData: clip.waveformData, // Share waveformData - slicing happens at render time\n // Note: fadeOut removed for first clip since it's cut\n });\n\n // Create second clip (from split point to end)\n const secondClip = createClip({\n audioBuffer: clip.audioBuffer,\n startSample: secondClipStartSample,\n durationSamples: secondClipDurationSamples,\n offsetSamples: clip.offsetSamples + offsetIncrement,\n sampleRate: clip.sampleRate,\n sourceDurationSamples: clip.sourceDurationSamples,\n gain: clip.gain,\n name: clip.name ? `${clip.name} (2)` : undefined,\n color: clip.color,\n waveformData: clip.waveformData, // Share waveformData - slicing happens at render time\n // Note: fadeIn removed for second clip since it's cut\n fadeOut: clip.fadeOut,\n });\n\n // Create new clips array with the split clips\n const newClips = [...track.clips];\n newClips.splice(clipIndex, 1, firstClip, secondClip);\n\n // Update the track with new clips\n const newTracks = [...tracks];\n newTracks[trackIndex] = {\n ...track,\n clips: newClips,\n };\n\n onTracksChange(newTracks);\n return true;\n },\n [tracks, onTracksChange, options]\n );\n\n /**\n * Split clip at the current playhead position on the selected track\n * If no track is selected, does nothing\n *\n * @returns true if a clip was split, false otherwise\n */\n const splitClipAtPlayhead = useCallback((): boolean => {\n // If no track is selected, cannot split\n if (!selectedTrackId) {\n console.log('No track selected - click a clip to select a track first');\n return false;\n }\n\n // Find the selected track\n const trackIndex = tracks.findIndex(track => track.id === selectedTrackId);\n if (trackIndex === -1) {\n console.warn('Selected track not found');\n return false;\n }\n\n const track = tracks[trackIndex];\n\n // Use ref for real-time position during playback (state updates are throttled)\n const currentTime = currentTimeRef.current ?? 0;\n\n // Find clip at current time on the selected track\n for (let clipIndex = 0; clipIndex < track.clips.length; clipIndex++) {\n const clip = track.clips[clipIndex];\n const clipStartTime = clip.startSample / sampleRate;\n const clipEndTime = (clip.startSample + clip.durationSamples) / sampleRate;\n\n // Check if currentTime is within this clip (not at boundaries)\n if (currentTime > clipStartTime && currentTime < clipEndTime) {\n // Found a clip! Split it\n console.log(`Splitting clip on track \"${track.name}\" at ${currentTime}s`);\n return splitClipAt(trackIndex, clipIndex, currentTime);\n }\n }\n\n console.log(`No clip found at playhead position on track \"${track.name}\"`);\n return false;\n }, [tracks, currentTimeRef, selectedTrackId, splitClipAt, sampleRate]);\n\n return {\n splitClipAtPlayhead,\n splitClipAt,\n };\n};\n","import { useEffect, useCallback } from 'react';\n\nexport interface KeyboardShortcut {\n key: string;\n ctrlKey?: boolean;\n shiftKey?: boolean;\n metaKey?: boolean;\n altKey?: boolean;\n action: () => void;\n description?: string;\n preventDefault?: boolean;\n}\n\nexport interface UseKeyboardShortcutsOptions {\n shortcuts: KeyboardShortcut[];\n enabled?: boolean;\n}\n\n/**\n * Hook for managing keyboard shortcuts\n *\n * @param options - Configuration options\n *\n * @example\n * ```tsx\n * const { splitClipAtPlayhead } = useClipSplitting({ ... });\n *\n * useKeyboardShortcuts({\n * shortcuts: [\n * {\n * key: 's',\n * action: splitClipAtPlayhead,\n * description: 'Split clip at playhead',\n * preventDefault: true,\n * },\n * {\n * key: 'S',\n * shiftKey: true,\n * action: () => splitAtSelection(),\n * description: 'Split at selection boundaries',\n * preventDefault: true,\n * },\n * ],\n * });\n * ```\n */\nexport const useKeyboardShortcuts = (options: UseKeyboardShortcutsOptions): void => {\n const { shortcuts, enabled = true } = options;\n\n const handleKeyDown = useCallback(\n (event: KeyboardEvent) => {\n if (!enabled) return;\n\n // Check if we're in an input/textarea element\n const target = event.target as HTMLElement;\n if (\n target.tagName === 'INPUT' ||\n target.tagName === 'TEXTAREA' ||\n target.isContentEditable\n ) {\n // Don't trigger shortcuts when typing in input fields\n return;\n }\n\n // Find matching shortcut\n const matchingShortcut = shortcuts.find((shortcut) => {\n const keyMatch =\n event.key.toLowerCase() === shortcut.key.toLowerCase() ||\n event.key === shortcut.key;\n\n const ctrlMatch = shortcut.ctrlKey === undefined || event.ctrlKey === shortcut.ctrlKey;\n const shiftMatch =\n shortcut.shiftKey === undefined || event.shiftKey === shortcut.shiftKey;\n const metaMatch = shortcut.metaKey === undefined || event.metaKey === shortcut.metaKey;\n const altMatch = shortcut.altKey === undefined || event.altKey === shortcut.altKey;\n\n return keyMatch && ctrlMatch && shiftMatch && metaMatch && altMatch;\n });\n\n if (matchingShortcut) {\n if (matchingShortcut.preventDefault !== false) {\n event.preventDefault();\n }\n matchingShortcut.action();\n }\n },\n [shortcuts, enabled]\n );\n\n useEffect(() => {\n if (!enabled) return;\n\n window.addEventListener('keydown', handleKeyDown);\n\n return () => {\n window.removeEventListener('keydown', handleKeyDown);\n };\n }, [handleKeyDown, enabled]);\n};\n\n/**\n * Get a human-readable string representation of a keyboard shortcut\n *\n * @param shortcut - The keyboard shortcut\n * @returns Human-readable string (e.g., \"Cmd+Shift+S\")\n */\nexport const getShortcutLabel = (shortcut: KeyboardShortcut): string => {\n const parts: string[] = [];\n\n // Use Cmd on Mac, Ctrl on other platforms\n const isMac = typeof navigator !== 'undefined' && navigator.platform.includes('Mac');\n\n if (shortcut.metaKey) {\n parts.push(isMac ? 'Cmd' : 'Ctrl');\n }\n\n if (shortcut.ctrlKey && !shortcut.metaKey) {\n parts.push('Ctrl');\n }\n\n if (shortcut.altKey) {\n parts.push(isMac ? 'Option' : 'Alt');\n }\n\n if (shortcut.shiftKey) {\n parts.push('Shift');\n }\n\n parts.push(shortcut.key.toUpperCase());\n\n return parts.join('+');\n};\n","import { useCallback } from 'react';\nimport { usePlaybackAnimation, usePlaylistControls, usePlaylistData } from '../WaveformPlaylistContext';\nimport { useKeyboardShortcuts, type KeyboardShortcut } from './useKeyboardShortcuts';\n\nexport interface UsePlaybackShortcutsOptions {\n /**\n * Enable the shortcuts. Defaults to true.\n */\n enabled?: boolean;\n /**\n * Additional shortcuts to include alongside the default playback shortcuts.\n */\n additionalShortcuts?: KeyboardShortcut[];\n /**\n * Override default shortcuts. If provided, only these shortcuts will be used.\n */\n shortcuts?: KeyboardShortcut[];\n}\n\nexport interface UsePlaybackShortcutsReturn {\n /** Rewind to the beginning (time = 0) */\n rewindToStart: () => void;\n /** Toggle play/pause */\n togglePlayPause: () => void;\n /** Stop playback and return to start position */\n stopPlayback: () => void;\n /** The list of active keyboard shortcuts */\n shortcuts: KeyboardShortcut[];\n}\n\n/**\n * Hook that provides common playback keyboard shortcuts for the playlist.\n *\n * Default shortcuts:\n * - `Space` - Toggle play/pause\n * - `Escape` - Stop playback\n * - `0` - Rewind to start (seek to time 0)\n *\n * @example\n * ```tsx\n * // Basic usage - enables default shortcuts\n * usePlaybackShortcuts();\n *\n * // With additional custom shortcuts\n * usePlaybackShortcuts({\n * additionalShortcuts: [\n * { key: 's', action: splitClipAtPlayhead, description: 'Split clip' },\n * ],\n * });\n *\n * // Completely override shortcuts\n * usePlaybackShortcuts({\n * shortcuts: [\n * { key: 'Home', action: rewindToStart, description: 'Go to start' },\n * ],\n * });\n * ```\n */\nexport const usePlaybackShortcuts = (\n options: UsePlaybackShortcutsOptions = {}\n): UsePlaybackShortcutsReturn => {\n const { enabled = true, additionalShortcuts = [], shortcuts: overrideShortcuts } = options;\n\n const { isPlaying } = usePlaybackAnimation();\n const { setCurrentTime, play, pause, stop } = usePlaylistControls();\n const { playoutRef } = usePlaylistData();\n\n /**\n * Toggle between play and pause.\n */\n const togglePlayPause = useCallback(() => {\n if (isPlaying) {\n pause();\n } else {\n play();\n }\n }, [isPlaying, play, pause]);\n\n /**\n * Stop playback and return to start position.\n */\n const stopPlayback = useCallback(() => {\n stop();\n }, [stop]);\n\n /**\n * Rewind to the beginning of the timeline.\n * If playing, stops and restarts playback from the beginning.\n */\n const rewindToStart = useCallback(() => {\n if (isPlaying && playoutRef.current) {\n playoutRef.current.stop();\n setCurrentTime(0);\n play(0);\n } else {\n setCurrentTime(0);\n }\n }, [isPlaying, playoutRef, setCurrentTime, play]);\n\n // Default playback shortcuts\n const defaultShortcuts: KeyboardShortcut[] = [\n {\n key: ' ',\n action: togglePlayPause,\n description: 'Play/Pause',\n preventDefault: true,\n },\n {\n key: 'Escape',\n action: stopPlayback,\n description: 'Stop',\n preventDefault: true,\n },\n {\n key: '0',\n action: rewindToStart,\n description: 'Rewind to start',\n preventDefault: true,\n },\n ];\n\n // Use override shortcuts if provided, otherwise combine defaults with additional\n const activeShortcuts = overrideShortcuts ?? [...defaultShortcuts, ...additionalShortcuts];\n\n // Register the keyboard shortcuts\n useKeyboardShortcuts({\n shortcuts: activeShortcuts,\n enabled,\n });\n\n return {\n rewindToStart,\n togglePlayPause,\n stopPlayback,\n shortcuts: activeShortcuts,\n };\n};\n","import { useCallback, useMemo, useEffect } from 'react';\nimport type { AnnotationType } from '@waveform-playlist/annotations';\nimport { useKeyboardShortcuts } from './useKeyboardShortcuts';\n\nconst LINK_THRESHOLD = 0.01; // Consider edges \"linked\" if within 10ms\nconst TIME_DELTA = 0.01; // 10ms adjustment per keypress\n\ninterface UseAnnotationKeyboardControlsOptions {\n annotations: AnnotationType[];\n activeAnnotationId: string | null;\n onAnnotationsChange: (annotations: AnnotationType[]) => void;\n /** Callback to set the active annotation ID for selection */\n onActiveAnnotationChange?: (id: string | null) => void;\n duration: number;\n linkEndpoints: boolean;\n /** Whether continuous play is enabled (affects playback duration) */\n continuousPlay?: boolean;\n enabled?: boolean;\n /** Optional: scroll container ref for auto-scrolling to annotation */\n scrollContainerRef?: React.RefObject<HTMLDivElement | null>;\n /** Optional: samples per pixel for scroll position calculation */\n samplesPerPixel?: number;\n /** Optional: sample rate for scroll position calculation */\n sampleRate?: number;\n /** Optional: controls width offset for scroll position calculation */\n controlsWidth?: number;\n /** Optional: callback to start playback at a time with optional duration */\n onPlay?: (startTime: number, duration?: number) => void;\n}\n\n/**\n * Hook for keyboard-based annotation navigation and boundary editing\n *\n * Navigation Shortcuts:\n * - ArrowUp / ArrowLeft = Select previous annotation\n * - ArrowDown / ArrowRight = Select next annotation\n * - Home = Select first annotation\n * - End = Select last annotation\n * - Escape = Deselect annotation\n * - Enter = Play selected annotation\n *\n * Boundary Editing Shortcuts (requires active annotation):\n * - [ = Move start boundary earlier (left)\n * - ] = Move start boundary later (right)\n * - Shift+[ = Move end boundary earlier (left)\n * - Shift+] = Move end boundary later (right)\n *\n * Respects linkEndpoints and continuousPlay settings.\n *\n * @example\n * ```tsx\n * useAnnotationKeyboardControls({\n * annotations,\n * activeAnnotationId,\n * onAnnotationsChange: setAnnotations,\n * onActiveAnnotationChange: setActiveAnnotationId,\n * duration,\n * linkEndpoints,\n * });\n * ```\n */\nexport function useAnnotationKeyboardControls({\n annotations,\n activeAnnotationId,\n onAnnotationsChange,\n onActiveAnnotationChange,\n duration,\n linkEndpoints,\n continuousPlay = false,\n enabled = true,\n scrollContainerRef,\n samplesPerPixel,\n sampleRate,\n controlsWidth = 0,\n onPlay,\n}: UseAnnotationKeyboardControlsOptions) {\n const activeIndex = useMemo(() => {\n if (!activeAnnotationId) return -1;\n return annotations.findIndex((a) => a.id === activeAnnotationId);\n }, [annotations, activeAnnotationId]);\n\n // Scroll waveform to show a specific annotation\n const scrollToAnnotation = useCallback(\n (annotationId: string) => {\n if (!scrollContainerRef?.current || !samplesPerPixel || !sampleRate) return;\n\n const annotation = annotations.find((a) => a.id === annotationId);\n if (!annotation) return;\n\n const container = scrollContainerRef.current;\n const containerWidth = container.clientWidth;\n\n // Calculate pixel positions for annotation start and center\n const startPixel = (annotation.start * sampleRate) / samplesPerPixel + controlsWidth;\n const endPixel = (annotation.end * sampleRate) / samplesPerPixel + controlsWidth;\n const annotationCenter = (startPixel + endPixel) / 2;\n\n // Check if annotation is currently visible\n const scrollLeft = container.scrollLeft;\n const visibleStart = scrollLeft;\n const visibleEnd = scrollLeft + containerWidth;\n\n // If annotation is not fully visible, scroll to center it\n if (startPixel < visibleStart || endPixel > visibleEnd) {\n const targetScrollLeft = Math.max(0, annotationCenter - containerWidth / 2);\n container.scrollTo({\n left: targetScrollLeft,\n behavior: 'smooth',\n });\n }\n },\n [annotations, scrollContainerRef, samplesPerPixel, sampleRate, controlsWidth]\n );\n\n // Auto-scroll when active annotation changes via keyboard navigation\n useEffect(() => {\n if (activeAnnotationId && scrollContainerRef?.current && samplesPerPixel && sampleRate) {\n scrollToAnnotation(activeAnnotationId);\n }\n }, [activeAnnotationId, scrollToAnnotation, scrollContainerRef, samplesPerPixel, sampleRate]);\n\n const moveStartBoundary = useCallback(\n (delta: number) => {\n if (activeIndex < 0) return;\n\n const annotation = annotations[activeIndex];\n const newStart = Math.max(0, Math.min(annotation.end - 0.1, annotation.start + delta));\n const actualDelta = newStart - annotation.start;\n\n const updatedAnnotations = [...annotations];\n updatedAnnotations[activeIndex] = {\n ...annotation,\n start: newStart,\n };\n\n // Handle linked endpoints\n if (linkEndpoints && activeIndex > 0) {\n const prevAnnotation = updatedAnnotations[activeIndex - 1];\n if (Math.abs(prevAnnotation.end - annotation.start) < LINK_THRESHOLD) {\n // Already linked: move previous annotation's end together\n updatedAnnotations[activeIndex - 1] = {\n ...prevAnnotation,\n end: Math.max(prevAnnotation.start + 0.1, prevAnnotation.end + actualDelta),\n };\n }\n } else if (!linkEndpoints && activeIndex > 0) {\n // Non-linked mode: don't overlap previous annotation\n const prevAnnotation = updatedAnnotations[activeIndex - 1];\n if (newStart < prevAnnotation.end) {\n // Push back previous annotation's end\n updatedAnnotations[activeIndex - 1] = {\n ...prevAnnotation,\n end: newStart,\n };\n }\n }\n\n onAnnotationsChange(updatedAnnotations);\n },\n [annotations, activeIndex, linkEndpoints, onAnnotationsChange]\n );\n\n const moveEndBoundary = useCallback(\n (delta: number) => {\n if (activeIndex < 0) return;\n\n const annotation = annotations[activeIndex];\n const newEnd = Math.max(annotation.start + 0.1, Math.min(duration, annotation.end + delta));\n const actualDelta = newEnd - annotation.end;\n\n const updatedAnnotations = [...annotations];\n updatedAnnotations[activeIndex] = {\n ...annotation,\n end: newEnd,\n };\n\n // Handle linked endpoints\n if (linkEndpoints && activeIndex < annotations.length - 1) {\n const nextAnnotation = updatedAnnotations[activeIndex + 1];\n if (Math.abs(nextAnnotation.start - annotation.end) < LINK_THRESHOLD) {\n // Already linked: move next annotation's start together\n const newNextStart = Math.min(nextAnnotation.end - 0.1, nextAnnotation.start + actualDelta);\n updatedAnnotations[activeIndex + 1] = {\n ...nextAnnotation,\n start: newNextStart,\n };\n\n // Cascade linked endpoints\n let currentIndex = activeIndex + 1;\n while (currentIndex < updatedAnnotations.length - 1) {\n const current = updatedAnnotations[currentIndex];\n const next = updatedAnnotations[currentIndex + 1];\n\n if (Math.abs(next.start - annotations[currentIndex].end) < LINK_THRESHOLD) {\n const nextDelta = current.end - annotations[currentIndex].end;\n updatedAnnotations[currentIndex + 1] = {\n ...next,\n start: Math.min(next.end - 0.1, next.start + nextDelta),\n };\n currentIndex++;\n } else {\n break;\n }\n }\n }\n } else if (!linkEndpoints && activeIndex < annotations.length - 1) {\n // Non-linked mode: don't overlap next annotation\n const nextAnnotation = updatedAnnotations[activeIndex + 1];\n if (newEnd > nextAnnotation.start) {\n // Push forward next annotation's start\n updatedAnnotations[activeIndex + 1] = {\n ...nextAnnotation,\n start: newEnd,\n };\n\n // Cascade collisions\n let currentIndex = activeIndex + 1;\n while (currentIndex < updatedAnnotations.length - 1) {\n const current = updatedAnnotations[currentIndex];\n const next = updatedAnnotations[currentIndex + 1];\n\n if (current.end > next.start) {\n updatedAnnotations[currentIndex + 1] = {\n ...next,\n start: current.end,\n };\n currentIndex++;\n } else {\n break;\n }\n }\n }\n }\n\n onAnnotationsChange(updatedAnnotations);\n },\n [annotations, activeIndex, duration, linkEndpoints, onAnnotationsChange]\n );\n\n // Navigation functions\n const selectPrevious = useCallback(() => {\n if (!onActiveAnnotationChange || annotations.length === 0) return;\n\n if (activeIndex <= 0) {\n // If no selection or at first, select last annotation\n onActiveAnnotationChange(annotations[annotations.length - 1].id);\n } else {\n onActiveAnnotationChange(annotations[activeIndex - 1].id);\n }\n }, [annotations, activeIndex, onActiveAnnotationChange]);\n\n const selectNext = useCallback(() => {\n if (!onActiveAnnotationChange || annotations.length === 0) return;\n\n if (activeIndex < 0 || activeIndex >= annotations.length - 1) {\n // If no selection or at last, select first annotation\n onActiveAnnotationChange(annotations[0].id);\n } else {\n onActiveAnnotationChange(annotations[activeIndex + 1].id);\n }\n }, [annotations, activeIndex, onActiveAnnotationChange]);\n\n const selectFirst = useCallback(() => {\n if (!onActiveAnnotationChange || annotations.length === 0) return;\n onActiveAnnotationChange(annotations[0].id);\n }, [annotations, onActiveAnnotationChange]);\n\n const selectLast = useCallback(() => {\n if (!onActiveAnnotationChange || annotations.length === 0) return;\n onActiveAnnotationChange(annotations[annotations.length - 1].id);\n }, [annotations, onActiveAnnotationChange]);\n\n const clearSelection = useCallback(() => {\n if (!onActiveAnnotationChange) return;\n onActiveAnnotationChange(null);\n }, [onActiveAnnotationChange]);\n\n // Play the currently selected annotation\n const playActiveAnnotation = useCallback(() => {\n if (activeIndex < 0 || !onPlay) return;\n\n const annotation = annotations[activeIndex];\n // If continuous play is off, play just this annotation's duration\n const playDuration = !continuousPlay ? annotation.end - annotation.start : undefined;\n onPlay(annotation.start, playDuration);\n }, [annotations, activeIndex, continuousPlay, onPlay]);\n\n // Shortcuts that require an active annotation (boundary editing + playback)\n const activeAnnotationShortcuts = useMemo(\n () => [\n {\n key: '[',\n action: () => moveStartBoundary(-TIME_DELTA),\n description: 'Move annotation start earlier',\n preventDefault: true,\n },\n {\n key: ']',\n action: () => moveStartBoundary(TIME_DELTA),\n description: 'Move annotation start later',\n preventDefault: true,\n },\n {\n key: '{',\n shiftKey: true,\n action: () => moveEndBoundary(-TIME_DELTA),\n description: 'Move annotation end earlier',\n preventDefault: true,\n },\n {\n key: '}',\n shiftKey: true,\n action: () => moveEndBoundary(TIME_DELTA),\n description: 'Move annotation end later',\n preventDefault: true,\n },\n {\n key: 'Enter',\n action: playActiveAnnotation,\n description: 'Play selected annotation',\n preventDefault: true,\n },\n ],\n [moveStartBoundary, moveEndBoundary, playActiveAnnotation]\n );\n\n // Navigation shortcuts (always active when enabled and there are annotations)\n const navigationShortcuts = useMemo(\n () => [\n {\n key: 'ArrowUp',\n action: selectPrevious,\n description: 'Select previous annotation',\n preventDefault: true,\n },\n {\n key: 'ArrowLeft',\n action: selectPrevious,\n description: 'Select previous annotation',\n preventDefault: true,\n },\n {\n key: 'ArrowDown',\n action: selectNext,\n description: 'Select next annotation',\n preventDefault: true,\n },\n {\n key: 'ArrowRight',\n action: selectNext,\n description: 'Select next annotation',\n preventDefault: true,\n },\n {\n key: 'Home',\n action: selectFirst,\n description: 'Select first annotation',\n preventDefault: true,\n },\n {\n key: 'End',\n action: selectLast,\n description: 'Select last annotation',\n preventDefault: true,\n },\n {\n key: 'Escape',\n action: clearSelection,\n description: 'Deselect annotation',\n preventDefault: true,\n },\n ],\n [selectPrevious, selectNext, selectFirst, selectLast, clearSelection]\n );\n\n // Active annotation shortcuts only work when an annotation is selected\n useKeyboardShortcuts({\n shortcuts: activeAnnotationShortcuts,\n enabled: enabled && activeIndex >= 0,\n });\n\n // Navigation shortcuts work whenever there are annotations\n useKeyboardShortcuts({\n shortcuts: navigationShortcuts,\n enabled: enabled && annotations.length > 0 && !!onActiveAnnotationChange,\n });\n\n return {\n moveStartBoundary,\n moveEndBoundary,\n selectPrevious,\n selectNext,\n selectFirst,\n selectLast,\n clearSelection,\n scrollToAnnotation,\n playActiveAnnotation,\n };\n}\n","// src/hooks/useRecording.ts\nimport { useState, useRef, useCallback, useEffect } from \"react\";\n\n// src/utils/audioBufferUtils.ts\nfunction concatenateAudioData(chunks) {\n const totalLength = chunks.reduce((sum, chunk) => sum + chunk.length, 0);\n const result = new Float32Array(totalLength);\n let offset = 0;\n for (const chunk of chunks) {\n result.set(chunk, offset);\n offset += chunk.length;\n }\n return result;\n}\nfunction createAudioBuffer(audioContext, samples, sampleRate, channelCount = 1) {\n const buffer = audioContext.createBuffer(\n channelCount,\n samples.length,\n sampleRate\n );\n const typedSamples = new Float32Array(samples);\n buffer.copyToChannel(typedSamples, 0);\n return buffer;\n}\n\n// src/utils/peaksGenerator.ts\nfunction generatePeaks(samples, samplesPerPixel, bits = 16) {\n const numPeaks = Math.ceil(samples.length / samplesPerPixel);\n const peakArray = bits === 8 ? new Int8Array(numPeaks * 2) : new Int16Array(numPeaks * 2);\n const maxValue = 2 ** (bits - 1);\n for (let i = 0; i < numPeaks; i++) {\n const start = i * samplesPerPixel;\n const end = Math.min(start + samplesPerPixel, samples.length);\n let min = 0;\n let max = 0;\n for (let j = start; j < end; j++) {\n const value = samples[j];\n if (value < min) min = value;\n if (value > max) max = value;\n }\n peakArray[i * 2] = Math.floor(min * maxValue);\n peakArray[i * 2 + 1] = Math.floor(max * maxValue);\n }\n return peakArray;\n}\nfunction appendPeaks(existingPeaks, newSamples, samplesPerPixel, totalSamplesProcessed, bits = 16) {\n const maxValue = 2 ** (bits - 1);\n const remainder = totalSamplesProcessed % samplesPerPixel;\n let offset = 0;\n if (remainder > 0 && existingPeaks.length > 0) {\n const samplesToComplete = samplesPerPixel - remainder;\n const endIndex = Math.min(samplesToComplete, newSamples.length);\n let min = existingPeaks[existingPeaks.length - 2] / maxValue;\n let max = existingPeaks[existingPeaks.length - 1] / maxValue;\n for (let i = 0; i < endIndex; i++) {\n const value = newSamples[i];\n if (value < min) min = value;\n if (value > max) max = value;\n }\n const updated = new (bits === 8 ? Int8Array : Int16Array)(existingPeaks.length);\n updated.set(existingPeaks);\n updated[existingPeaks.length - 2] = Math.floor(min * maxValue);\n updated[existingPeaks.length - 1] = Math.floor(max * maxValue);\n offset = endIndex;\n const newPeaks2 = generatePeaks(newSamples.slice(offset), samplesPerPixel, bits);\n const result2 = new (bits === 8 ? Int8Array : Int16Array)(updated.length + newPeaks2.length);\n result2.set(updated);\n result2.set(newPeaks2, updated.length);\n return result2;\n }\n const newPeaks = generatePeaks(newSamples.slice(offset), samplesPerPixel, bits);\n const result = new (bits === 8 ? Int8Array : Int16Array)(existingPeaks.length + newPeaks.length);\n result.set(existingPeaks);\n result.set(newPeaks, existingPeaks.length);\n return result;\n}\n\n// src/hooks/useRecording.ts\nimport { getContext } from \"tone\";\nfunction useRecording(stream, options = {}) {\n const {\n channelCount = 1,\n samplesPerPixel = 1024\n } = options;\n const [isRecording, setIsRecording] = useState(false);\n const [isPaused, setIsPaused] = useState(false);\n const [duration, setDuration] = useState(0);\n const [peaks, setPeaks] = useState(new Int16Array(0));\n const [audioBuffer, setAudioBuffer] = useState(null);\n const [error, setError] = useState(null);\n const [level, setLevel] = useState(0);\n const [peakLevel, setPeakLevel] = useState(0);\n const bits = 16;\n const workletLoadedRef = useRef(false);\n const workletNodeRef = useRef(null);\n const mediaStreamSourceRef = useRef(null);\n const recordedChunksRef = useRef([]);\n const totalSamplesRef = useRef(0);\n const animationFrameRef = useRef(null);\n const startTimeRef = useRef(0);\n const isRecordingRef = useRef(false);\n const isPausedRef = useRef(false);\n const loadWorklet = useCallback(async () => {\n if (workletLoadedRef.current) {\n return;\n }\n try {\n const context = getContext();\n const workletUrl = new URL(\n \"./worklet/recording-processor.worklet.js\",\n import.meta.url\n ).href;\n await context.addAudioWorkletModule(workletUrl);\n workletLoadedRef.current = true;\n } catch (err) {\n console.error(\"Failed to load AudioWorklet module:\", err);\n throw new Error(\"Failed to load recording processor\");\n }\n }, []);\n const startRecording = useCallback(async () => {\n if (!stream) {\n setError(new Error(\"No microphone stream available\"));\n return;\n }\n try {\n setError(null);\n const context = getContext();\n if (context.state === \"suspended\") {\n await context.resume();\n }\n await loadWorklet();\n const source = context.createMediaStreamSource(stream);\n mediaStreamSourceRef.current = source;\n const workletNode = context.createAudioWorkletNode(\"recording-processor\");\n workletNodeRef.current = workletNode;\n source.connect(workletNode);\n workletNode.port.onmessage = (event) => {\n const { samples } = event.data;\n recordedChunksRef.current.push(samples);\n totalSamplesRef.current += samples.length;\n setPeaks(\n (prevPeaks) => appendPeaks(\n prevPeaks,\n samples,\n samplesPerPixel,\n totalSamplesRef.current - samples.length,\n bits\n )\n );\n };\n workletNode.port.postMessage({\n command: \"start\",\n sampleRate: context.sampleRate,\n channelCount\n });\n recordedChunksRef.current = [];\n totalSamplesRef.current = 0;\n setPeaks(new Int16Array(0));\n setAudioBuffer(null);\n setLevel(0);\n setPeakLevel(0);\n isRecordingRef.current = true;\n isPausedRef.current = false;\n setIsRecording(true);\n setIsPaused(false);\n startTimeRef.current = performance.now();\n const updateDuration = () => {\n if (isRecordingRef.current && !isPausedRef.current) {\n const elapsed = (performance.now() - startTimeRef.current) / 1e3;\n setDuration(elapsed);\n animationFrameRef.current = requestAnimationFrame(updateDuration);\n }\n };\n updateDuration();\n } catch (err) {\n console.error(\"Failed to start recording:\", err);\n setError(err instanceof Error ? err : new Error(\"Failed to start recording\"));\n }\n }, [stream, channelCount, samplesPerPixel, loadWorklet, isRecording, isPaused]);\n const stopRecording = useCallback(async () => {\n if (!isRecording) {\n return null;\n }\n try {\n if (workletNodeRef.current) {\n workletNodeRef.current.port.postMessage({ command: \"stop\" });\n if (mediaStreamSourceRef.current) {\n try {\n mediaStreamSourceRef.current.disconnect(workletNodeRef.current);\n } catch (e) {\n }\n }\n workletNodeRef.current.disconnect();\n }\n if (animationFrameRef.current !== null) {\n cancelAnimationFrame(animationFrameRef.current);\n animationFrameRef.current = null;\n }\n const allSamples = concatenateAudioData(recordedChunksRef.current);\n const context = getContext();\n const rawContext = context.rawContext;\n const buffer = createAudioBuffer(\n rawContext,\n allSamples,\n rawContext.sampleRate,\n channelCount\n );\n setAudioBuffer(buffer);\n setDuration(buffer.duration);\n isRecordingRef.current = false;\n isPausedRef.current = false;\n setIsRecording(false);\n setIsPaused(false);\n setLevel(0);\n return buffer;\n } catch (err) {\n console.error(\"Failed to stop recording:\", err);\n setError(err instanceof Error ? err : new Error(\"Failed to stop recording\"));\n return null;\n }\n }, [isRecording, channelCount]);\n const pauseRecording = useCallback(() => {\n if (isRecording && !isPaused) {\n if (animationFrameRef.current !== null) {\n cancelAnimationFrame(animationFrameRef.current);\n animationFrameRef.current = null;\n }\n isPausedRef.current = true;\n setIsPaused(true);\n }\n }, [isRecording, isPaused]);\n const resumeRecording = useCallback(() => {\n if (isRecording && isPaused) {\n isPausedRef.current = false;\n setIsPaused(false);\n startTimeRef.current = performance.now() - duration * 1e3;\n const updateDuration = () => {\n if (isRecordingRef.current && !isPausedRef.current) {\n const elapsed = (performance.now() - startTimeRef.current) / 1e3;\n setDuration(elapsed);\n animationFrameRef.current = requestAnimationFrame(updateDuration);\n }\n };\n updateDuration();\n }\n }, [isRecording, isPaused, duration]);\n useEffect(() => {\n return () => {\n if (workletNodeRef.current) {\n workletNodeRef.current.port.postMessage({ command: \"stop\" });\n if (mediaStreamSourceRef.current) {\n try {\n mediaStreamSourceRef.current.disconnect(workletNodeRef.current);\n } catch (e) {\n }\n }\n workletNodeRef.current.disconnect();\n }\n if (animationFrameRef.current !== null) {\n cancelAnimationFrame(animationFrameRef.current);\n }\n };\n }, []);\n return {\n isRecording,\n isPaused,\n duration,\n peaks,\n audioBuffer,\n level,\n peakLevel,\n startRecording,\n stopRecording,\n pauseRecording,\n resumeRecording,\n error\n };\n}\n\n// src/hooks/useMicrophoneAccess.ts\nimport { useState as useState2, useEffect as useEffect2, useCallback as useCallback2 } from \"react\";\nfunction useMicrophoneAccess() {\n const [stream, setStream] = useState2(null);\n const [devices, setDevices] = useState2([]);\n const [hasPermission, setHasPermission] = useState2(false);\n const [isLoading, setIsLoading] = useState2(false);\n const [error, setError] = useState2(null);\n const enumerateDevices = useCallback2(async () => {\n try {\n const allDevices = await navigator.mediaDevices.enumerateDevices();\n const audioInputs = allDevices.filter((device) => device.kind === \"audioinput\").map((device) => ({\n deviceId: device.deviceId,\n label: device.label || `Microphone ${device.deviceId.slice(0, 8)}`,\n groupId: device.groupId\n }));\n setDevices(audioInputs);\n } catch (err) {\n console.error(\"Failed to enumerate devices:\", err);\n setError(err instanceof Error ? err : new Error(\"Failed to enumerate devices\"));\n }\n }, []);\n const requestAccess = useCallback2(async (deviceId, audioConstraints) => {\n setIsLoading(true);\n setError(null);\n try {\n if (stream) {\n stream.getTracks().forEach((track) => track.stop());\n }\n const audio = {\n // Recording-optimized defaults: prioritize raw audio quality and low latency\n echoCancellation: false,\n noiseSuppression: false,\n autoGainControl: false,\n latency: 0,\n // Low latency mode (not in TS types yet, but supported in modern browsers)\n // User-provided constraints override defaults\n ...audioConstraints,\n // Device ID override (if specified)\n ...deviceId && { deviceId: { exact: deviceId } }\n };\n const constraints = {\n audio,\n video: false\n };\n const newStream = await navigator.mediaDevices.getUserMedia(constraints);\n setStream(newStream);\n setHasPermission(true);\n await enumerateDevices();\n } catch (err) {\n console.error(\"Failed to access microphone:\", err);\n setError(\n err instanceof Error ? err : new Error(\"Failed to access microphone\")\n );\n setHasPermission(false);\n } finally {\n setIsLoading(false);\n }\n }, [stream, enumerateDevices]);\n const stopStream = useCallback2(() => {\n if (stream) {\n stream.getTracks().forEach((track) => track.stop());\n setStream(null);\n setHasPermission(false);\n }\n }, [stream]);\n useEffect2(() => {\n enumerateDevices();\n return () => {\n if (stream) {\n stream.getTracks().forEach((track) => track.stop());\n }\n };\n }, []);\n return {\n stream,\n devices,\n hasPermission,\n isLoading,\n requestAccess,\n stopStream,\n error\n };\n}\n\n// src/hooks/useMicrophoneLevel.ts\nimport { useEffect as useEffect3, useState as useState3, useRef as useRef2 } from \"react\";\nimport { Meter, getContext as getContext2, connect } from \"tone\";\nfunction useMicrophoneLevel(stream, options = {}) {\n const {\n updateRate = 60,\n smoothingTimeConstant = 0.8\n } = options;\n const [level, setLevel] = useState3(0);\n const [peakLevel, setPeakLevel] = useState3(0);\n const meterRef = useRef2(null);\n const sourceRef = useRef2(null);\n const animationFrameRef = useRef2(null);\n const resetPeak = () => setPeakLevel(0);\n useEffect3(() => {\n if (!stream) {\n setLevel(0);\n setPeakLevel(0);\n return;\n }\n let isMounted = true;\n const setupMonitoring = async () => {\n if (!isMounted) return;\n const context = getContext2();\n if (context.state === \"suspended\") {\n await context.resume();\n }\n if (!isMounted) return;\n const meter = new Meter({ smoothing: smoothingTimeConstant, context });\n meterRef.current = meter;\n const source = context.createMediaStreamSource(stream);\n sourceRef.current = source;\n connect(source, meter);\n const updateInterval = 1e3 / updateRate;\n let lastUpdateTime = 0;\n const updateLevel = (timestamp) => {\n if (!isMounted || !meterRef.current) return;\n if (timestamp - lastUpdateTime >= updateInterval) {\n lastUpdateTime = timestamp;\n const db = meterRef.current.getValue();\n const dbValue = typeof db === \"number\" ? db : db[0];\n const normalized = Math.max(0, Math.min(1, (dbValue + 100) / 100));\n setLevel(normalized);\n setPeakLevel((prev) => Math.max(prev, normalized));\n }\n animationFrameRef.current = requestAnimationFrame(updateLevel);\n };\n animationFrameRef.current = requestAnimationFrame(updateLevel);\n };\n setupMonitoring();\n return () => {\n isMounted = false;\n if (animationFrameRef.current) {\n cancelAnimationFrame(animationFrameRef.current);\n animationFrameRef.current = null;\n }\n if (sourceRef.current) {\n try {\n sourceRef.current.disconnect();\n } catch (e) {\n }\n sourceRef.current = null;\n }\n if (meterRef.current) {\n meterRef.current.dispose();\n meterRef.current = null;\n }\n };\n }, [stream, smoothingTimeConstant, updateRate]);\n return {\n level,\n peakLevel,\n resetPeak\n };\n}\n\n// src/components/RecordButton.tsx\nimport styled from \"styled-components\";\nimport { jsx, jsxs } from \"react/jsx-runtime\";\nvar Button = styled.button`\n padding: 0.5rem 1rem;\n font-size: 0.875rem;\n font-weight: 500;\n border: none;\n border-radius: 0.25rem;\n cursor: pointer;\n transition: all 0.2s ease-in-out;\n background: ${(props) => props.$isRecording ? \"#dc3545\" : \"#e74c3c\"};\n color: white;\n\n &:hover:not(:disabled) {\n background: ${(props) => props.$isRecording ? \"#c82333\" : \"#c0392b\"};\n transform: translateY(-1px);\n box-shadow: 0 2px 4px rgba(0, 0, 0, 0.2);\n }\n\n &:active:not(:disabled) {\n transform: translateY(0);\n }\n\n &:disabled {\n opacity: 0.5;\n cursor: not-allowed;\n }\n\n &:focus {\n outline: none;\n box-shadow: 0 0 0 3px rgba(231, 76, 60, 0.3);\n }\n`;\nvar RecordingIndicator = styled.span`\n display: inline-block;\n width: 8px;\n height: 8px;\n border-radius: 50%;\n background: white;\n margin-right: 0.5rem;\n animation: pulse 1.5s ease-in-out infinite;\n\n @keyframes pulse {\n 0%,\n 100% {\n opacity: 1;\n }\n 50% {\n opacity: 0.3;\n }\n }\n`;\nvar RecordButton = ({\n isRecording,\n onClick,\n disabled = false,\n className\n}) => {\n return /* @__PURE__ */ jsxs(\n Button,\n {\n $isRecording: isRecording,\n onClick,\n disabled,\n className,\n \"aria-label\": isRecording ? \"Stop recording\" : \"Start recording\",\n children: [\n isRecording && /* @__PURE__ */ jsx(RecordingIndicator, {}),\n isRecording ? \"Stop Recording\" : \"Record\"\n ]\n }\n );\n};\n\n// src/components/MicrophoneSelector.tsx\nimport styled2 from \"styled-components\";\nimport { BaseSelect, BaseLabel } from \"@waveform-playlist/ui-components\";\nimport { jsx as jsx2, jsxs as jsxs2 } from \"react/jsx-runtime\";\nvar Select = styled2(BaseSelect)`\n min-width: 200px;\n`;\nvar Label = styled2(BaseLabel)`\n display: flex;\n flex-direction: column;\n gap: 0.25rem;\n`;\nvar MicrophoneSelector = ({\n devices,\n selectedDeviceId,\n onDeviceChange,\n disabled = false,\n className\n}) => {\n const handleChange = (event) => {\n onDeviceChange(event.target.value);\n };\n const currentValue = selectedDeviceId || (devices.length > 0 ? devices[0].deviceId : \"\");\n return /* @__PURE__ */ jsxs2(Label, { className, children: [\n \"Microphone\",\n /* @__PURE__ */ jsx2(\n Select,\n {\n value: currentValue,\n onChange: handleChange,\n disabled: disabled || devices.length === 0,\n children: devices.length === 0 ? /* @__PURE__ */ jsx2(\"option\", { value: \"\", children: \"No microphones found\" }) : devices.map((device) => /* @__PURE__ */ jsx2(\"option\", { value: device.deviceId, children: device.label }, device.deviceId))\n }\n )\n ] });\n};\n\n// src/components/RecordingIndicator.tsx\nimport styled3 from \"styled-components\";\nimport { jsx as jsx3, jsxs as jsxs3 } from \"react/jsx-runtime\";\nvar Container = styled3.div`\n display: flex;\n align-items: center;\n gap: 0.75rem;\n padding: 0.5rem 0.75rem;\n background: ${(props) => props.$isRecording ? \"#fff3cd\" : \"transparent\"};\n border-radius: 0.25rem;\n transition: background 0.2s ease-in-out;\n`;\nvar Dot = styled3.div`\n width: 12px;\n height: 12px;\n border-radius: 50%;\n background: ${(props) => props.$isPaused ? \"#ffc107\" : \"#dc3545\"};\n opacity: ${(props) => props.$isRecording ? 1 : 0};\n transition: opacity 0.2s ease-in-out;\n\n ${(props) => props.$isRecording && !props.$isPaused && `\n animation: blink 1.5s ease-in-out infinite;\n\n @keyframes blink {\n 0%, 100% {\n opacity: 1;\n }\n 50% {\n opacity: 0.3;\n }\n }\n `}\n`;\nvar Duration = styled3.span`\n font-family: 'Courier New', Monaco, monospace;\n font-size: 1rem;\n font-weight: 600;\n color: #495057;\n min-width: 70px;\n`;\nvar Status = styled3.span`\n font-size: 0.75rem;\n font-weight: 500;\n color: ${(props) => props.$isPaused ? \"#ffc107\" : \"#dc3545\"};\n text-transform: uppercase;\n`;\nvar defaultFormatTime = (seconds) => {\n const mins = Math.floor(seconds / 60);\n const secs = Math.floor(seconds % 60);\n return `${mins.toString().padStart(2, \"0\")}:${secs.toString().padStart(2, \"0\")}`;\n};\nvar RecordingIndicator2 = ({\n isRecording,\n isPaused = false,\n duration,\n formatTime = defaultFormatTime,\n className\n}) => {\n return /* @__PURE__ */ jsxs3(Container, { $isRecording: isRecording, className, children: [\n /* @__PURE__ */ jsx3(Dot, { $isRecording: isRecording, $isPaused: isPaused }),\n /* @__PURE__ */ jsx3(Duration, { children: formatTime(duration) }),\n isRecording && /* @__PURE__ */ jsx3(Status, { $isPaused: isPaused, children: isPaused ? \"Paused\" : \"Recording\" })\n ] });\n};\n\n// src/components/VUMeter.tsx\nimport React from \"react\";\nimport styled4 from \"styled-components\";\nimport { jsx as jsx4, jsxs as jsxs4 } from \"react/jsx-runtime\";\nvar MeterContainer = styled4.div`\n position: relative;\n width: ${(props) => props.$width}px;\n height: ${(props) => props.$height}px;\n background: #2c3e50;\n border-radius: 4px;\n overflow: hidden;\n box-shadow: inset 0 2px 4px rgba(0, 0, 0, 0.3);\n`;\nvar getLevelGradient = (level) => {\n if (level < 0.6) return \"linear-gradient(90deg, #27ae60, #2ecc71)\";\n if (level < 0.85) return \"linear-gradient(90deg, #f39c12, #f1c40f)\";\n return \"linear-gradient(90deg, #c0392b, #e74c3c)\";\n};\nvar MeterFill = styled4.div.attrs((props) => ({\n style: {\n width: `${props.$level * 100}%`,\n height: `${props.$height}px`,\n background: getLevelGradient(props.$level),\n boxShadow: props.$level > 0.01 ? \"0 0 8px rgba(255, 255, 255, 0.3)\" : \"none\"\n }\n}))`\n position: absolute;\n left: 0;\n top: 0;\n transition: width 0.05s ease-out, background 0.1s ease-out;\n`;\nvar PeakIndicator = styled4.div.attrs((props) => ({\n style: {\n left: `${props.$peakLevel * 100}%`,\n height: `${props.$height}px`\n }\n}))`\n position: absolute;\n top: 0;\n width: 2px;\n background: #ecf0f1;\n box-shadow: 0 0 4px rgba(236, 240, 241, 0.8);\n transition: left 0.1s ease-out;\n`;\nvar ScaleMarkers = styled4.div`\n position: absolute;\n top: 0;\n left: 0;\n width: 100%;\n height: ${(props) => props.$height}px;\n pointer-events: none;\n`;\nvar ScaleMark = styled4.div`\n position: absolute;\n left: ${(props) => props.$position}%;\n top: 0;\n width: 1px;\n height: ${(props) => props.$height}px;\n background: rgba(255, 255, 255, 0.2);\n`;\nvar VUMeterComponent = ({\n level,\n peakLevel,\n width = 200,\n height = 20,\n className\n}) => {\n const clampedLevel = Math.max(0, Math.min(1, level));\n const clampedPeak = peakLevel !== void 0 ? Math.max(0, Math.min(1, peakLevel)) : 0;\n return /* @__PURE__ */ jsxs4(MeterContainer, { $width: width, $height: height, className, children: [\n /* @__PURE__ */ jsx4(MeterFill, { $level: clampedLevel, $height: height }),\n peakLevel !== void 0 && clampedPeak > 0 && /* @__PURE__ */ jsx4(PeakIndicator, { $peakLevel: clampedPeak, $height: height }),\n /* @__PURE__ */ jsxs4(ScaleMarkers, { $height: height, children: [\n /* @__PURE__ */ jsx4(ScaleMark, { $position: 60, $height: height }),\n /* @__PURE__ */ jsx4(ScaleMark, { $position: 85, $height: height })\n ] })\n ] });\n};\nvar VUMeter = React.memo(VUMeterComponent);\nexport {\n MicrophoneSelector,\n RecordButton,\n RecordingIndicator2 as RecordingIndicator,\n VUMeter,\n concatenateAudioData,\n createAudioBuffer,\n generatePeaks,\n useMicrophoneAccess,\n useMicrophoneLevel,\n useRecording\n};\n//# sourceMappingURL=index.mjs.map","/**\n * Hook for integrated multi-track recording\n * Combines recording functionality with track management\n */\n\nimport { useState, useCallback, useEffect } from 'react';\nimport {\n useRecording,\n useMicrophoneAccess,\n useMicrophoneLevel,\n type MicrophoneDevice,\n} from '@waveform-playlist/recording';\nimport { type ClipTrack, type AudioClip } from '@waveform-playlist/core';\nimport { resumeGlobalAudioContext } from '@waveform-playlist/playout';\n\nexport interface IntegratedRecordingOptions {\n /**\n * Current playback/cursor position in seconds\n * Recording will start from max(currentTime, lastClipEndTime)\n */\n currentTime?: number;\n\n /**\n * MediaTrackConstraints for audio recording\n * These will override the recording-optimized defaults (echo cancellation off, low latency)\n */\n audioConstraints?: MediaTrackConstraints;\n\n /**\n * Number of channels to record (1 = mono, 2 = stereo)\n * Default: 1 (mono)\n */\n channelCount?: number;\n\n /**\n * Samples per pixel for peak generation\n * Default: 1024\n */\n samplesPerPixel?: number;\n}\n\nexport interface UseIntegratedRecordingReturn {\n // Recording state\n isRecording: boolean;\n isPaused: boolean;\n duration: number;\n level: number;\n peakLevel: number;\n error: Error | null;\n\n // Microphone state\n stream: MediaStream | null;\n devices: MicrophoneDevice[];\n hasPermission: boolean;\n selectedDevice: string | null;\n\n // Recording controls\n startRecording: () => void;\n stopRecording: () => void;\n pauseRecording: () => void;\n resumeRecording: () => void;\n requestMicAccess: () => Promise<void>;\n changeDevice: (deviceId: string) => Promise<void>;\n\n // Track state (for live waveform during recording)\n recordingPeaks: Int8Array | Int16Array;\n}\n\nexport function useIntegratedRecording(\n tracks: ClipTrack[],\n setTracks: (tracks: ClipTrack[]) => void,\n selectedTrackId: string | null,\n options: IntegratedRecordingOptions = {}\n): UseIntegratedRecordingReturn {\n const { currentTime = 0, audioConstraints, ...recordingOptions } = options;\n\n // Track if we're currently monitoring (for auto-resume audio context)\n const [isMonitoring, setIsMonitoring] = useState(false);\n const [selectedDevice, setSelectedDevice] = useState<string | null>(null);\n\n // Microphone access\n const {\n stream,\n devices,\n hasPermission,\n requestAccess,\n error: micError,\n } = useMicrophoneAccess();\n\n // Microphone level (for VU meter)\n const { level, peakLevel } = useMicrophoneLevel(stream);\n\n // Recording\n const {\n isRecording,\n isPaused,\n duration,\n peaks,\n audioBuffer: _audioBuffer,\n startRecording: startRec,\n stopRecording: stopRec,\n pauseRecording,\n resumeRecording,\n error: recError,\n } = useRecording(stream, recordingOptions);\n\n // Start recording handler\n const startRecording = useCallback(async () => {\n if (!selectedTrackId) {\n // No track selected - UI should handle creating/selecting track before calling this\n return;\n }\n\n // Resume audio context if needed\n if (!isMonitoring) {\n await resumeGlobalAudioContext();\n setIsMonitoring(true);\n }\n\n await startRec();\n }, [selectedTrackId, isMonitoring, startRec]);\n\n // Stop recording and add clip to selected track\n const stopRecording = useCallback(async () => {\n const buffer = await stopRec();\n\n // Add clip to track after recording completes\n if (buffer && selectedTrackId) {\n const selectedTrackIndex = tracks.findIndex(t => t.id === selectedTrackId);\n if (selectedTrackIndex === -1) return;\n\n const selectedTrack = tracks[selectedTrackIndex];\n\n // Calculate start position: max(currentTime, lastClipEndTime)\n const currentTimeSamples = Math.floor(currentTime * buffer.sampleRate);\n\n let lastClipEndSample = 0;\n if (selectedTrack.clips.length > 0) {\n // Find the end time of the last clip (in samples)\n const endSamples = selectedTrack.clips.map(clip =>\n clip.startSample + clip.durationSamples\n );\n lastClipEndSample = Math.max(...endSamples);\n }\n\n // Use whichever is greater: cursor position or last clip end\n const startSample = Math.max(currentTimeSamples, lastClipEndSample);\n\n // Create new clip from recording\n const newClip: AudioClip = {\n id: `clip-${Date.now()}`,\n audioBuffer: buffer,\n startSample,\n durationSamples: buffer.length,\n offsetSamples: 0,\n sampleRate: buffer.sampleRate,\n sourceDurationSamples: buffer.length,\n gain: 1.0,\n name: `Recording ${new Date().toLocaleTimeString()}`,\n };\n\n // Add clip to track\n const newTracks = tracks.map((track, index) => {\n if (index === selectedTrackIndex) {\n return {\n ...track,\n clips: [...track.clips, newClip],\n };\n }\n return track;\n });\n\n setTracks(newTracks);\n }\n }, [selectedTrackId, tracks, setTracks, currentTime, stopRec]);\n\n // Auto-select the first device when devices become available\n useEffect(() => {\n // Only auto-select if we have permission, devices are available, and nothing is selected yet\n if (hasPermission && devices.length > 0 && selectedDevice === null) {\n setSelectedDevice(devices[0].deviceId);\n }\n }, [hasPermission, devices.length]); // Intentionally not including selectedDevice to avoid re-triggering\n\n // Request microphone access\n const requestMicAccess = useCallback(async () => {\n await requestAccess(undefined, audioConstraints);\n await resumeGlobalAudioContext();\n setIsMonitoring(true);\n }, [requestAccess, audioConstraints]);\n\n // Change device\n const changeDevice = useCallback(async (deviceId: string) => {\n setSelectedDevice(deviceId);\n await requestAccess(deviceId, audioConstraints);\n await resumeGlobalAudioContext();\n setIsMonitoring(true);\n }, [requestAccess, audioConstraints]);\n\n return {\n // Recording state\n isRecording,\n isPaused,\n duration,\n level,\n peakLevel,\n error: micError || recError,\n\n // Microphone state\n stream,\n devices,\n hasPermission,\n selectedDevice,\n\n // Recording controls\n startRecording,\n stopRecording,\n pauseRecording,\n resumeRecording,\n requestMicAccess,\n changeDevice,\n\n // Track state\n recordingPeaks: peaks,\n };\n}\n","/**\n * Effect definitions for all available Tone.js effects\n * Each effect has parameters with min/max/default values for UI controls\n */\n\nexport type ParameterType = 'number' | 'select' | 'boolean';\n\nexport interface EffectParameter {\n name: string;\n label: string;\n type: ParameterType;\n min?: number;\n max?: number;\n step?: number;\n default: number | string | boolean;\n unit?: string;\n options?: { value: string | number; label: string }[];\n}\n\nexport interface EffectDefinition {\n id: string;\n name: string;\n category: 'delay' | 'reverb' | 'modulation' | 'distortion' | 'filter' | 'dynamics' | 'spatial';\n description: string;\n parameters: EffectParameter[];\n}\n\nexport const effectDefinitions: EffectDefinition[] = [\n // === REVERB EFFECTS ===\n {\n id: 'reverb',\n name: 'Reverb',\n category: 'reverb',\n description: 'Simple convolution reverb with adjustable decay time',\n parameters: [\n { name: 'decay', label: 'Decay', type: 'number', min: 0.1, max: 10, step: 0.1, default: 1.5, unit: 's' },\n { name: 'wet', label: 'Mix', type: 'number', min: 0, max: 1, step: 0.01, default: 0.5 },\n ],\n },\n {\n id: 'freeverb',\n name: 'Freeverb',\n category: 'reverb',\n description: 'Classic Schroeder/Moorer reverb with room size and dampening',\n parameters: [\n { name: 'roomSize', label: 'Room Size', type: 'number', min: 0, max: 1, step: 0.01, default: 0.7 },\n { name: 'dampening', label: 'Dampening', type: 'number', min: 0, max: 10000, step: 100, default: 3000, unit: 'Hz' },\n { name: 'wet', label: 'Mix', type: 'number', min: 0, max: 1, step: 0.01, default: 0.5 },\n ],\n },\n {\n id: 'jcReverb',\n name: 'JC Reverb',\n category: 'reverb',\n description: 'Attempt at Roland JC-120 chorus reverb emulation',\n parameters: [\n { name: 'roomSize', label: 'Room Size', type: 'number', min: 0, max: 1, step: 0.01, default: 0.5 },\n { name: 'wet', label: 'Mix', type: 'number', min: 0, max: 1, step: 0.01, default: 0.5 },\n ],\n },\n\n // === DELAY EFFECTS ===\n {\n id: 'feedbackDelay',\n name: 'Feedback Delay',\n category: 'delay',\n description: 'Delay line with feedback for echo effects',\n parameters: [\n { name: 'delayTime', label: 'Delay Time', type: 'number', min: 0, max: 1, step: 0.01, default: 0.25, unit: 's' },\n { name: 'feedback', label: 'Feedback', type: 'number', min: 0, max: 0.95, step: 0.01, default: 0.5 },\n { name: 'wet', label: 'Mix', type: 'number', min: 0, max: 1, step: 0.01, default: 0.5 },\n ],\n },\n {\n id: 'pingPongDelay',\n name: 'Ping Pong Delay',\n category: 'delay',\n description: 'Stereo delay bouncing between left and right channels',\n parameters: [\n { name: 'delayTime', label: 'Delay Time', type: 'number', min: 0, max: 1, step: 0.01, default: 0.25, unit: 's' },\n { name: 'feedback', label: 'Feedback', type: 'number', min: 0, max: 0.95, step: 0.01, default: 0.5 },\n { name: 'wet', label: 'Mix', type: 'number', min: 0, max: 1, step: 0.01, default: 0.5 },\n ],\n },\n\n // === MODULATION EFFECTS ===\n {\n id: 'chorus',\n name: 'Chorus',\n category: 'modulation',\n description: 'Creates thickness by layering detuned copies of the signal',\n parameters: [\n { name: 'frequency', label: 'Rate', type: 'number', min: 0.1, max: 10, step: 0.1, default: 1.5, unit: 'Hz' },\n { name: 'delayTime', label: 'Delay', type: 'number', min: 0, max: 20, step: 0.5, default: 3.5, unit: 'ms' },\n { name: 'depth', label: 'Depth', type: 'number', min: 0, max: 1, step: 0.01, default: 0.7 },\n { name: 'wet', label: 'Mix', type: 'number', min: 0, max: 1, step: 0.01, default: 0.5 },\n ],\n },\n {\n id: 'phaser',\n name: 'Phaser',\n category: 'modulation',\n description: 'Classic phaser effect using allpass filters',\n parameters: [\n { name: 'frequency', label: 'Rate', type: 'number', min: 0.1, max: 10, step: 0.1, default: 0.5, unit: 'Hz' },\n { name: 'octaves', label: 'Octaves', type: 'number', min: 1, max: 6, step: 1, default: 3 },\n { name: 'baseFrequency', label: 'Base Freq', type: 'number', min: 100, max: 2000, step: 10, default: 350, unit: 'Hz' },\n { name: 'wet', label: 'Mix', type: 'number', min: 0, max: 1, step: 0.01, default: 0.5 },\n ],\n },\n {\n id: 'tremolo',\n name: 'Tremolo',\n category: 'modulation',\n description: 'Rhythmic volume modulation',\n parameters: [\n { name: 'frequency', label: 'Rate', type: 'number', min: 0.1, max: 20, step: 0.1, default: 4, unit: 'Hz' },\n { name: 'depth', label: 'Depth', type: 'number', min: 0, max: 1, step: 0.01, default: 0.5 },\n { name: 'wet', label: 'Mix', type: 'number', min: 0, max: 1, step: 0.01, default: 1 },\n ],\n },\n {\n id: 'vibrato',\n name: 'Vibrato',\n category: 'modulation',\n description: 'Pitch modulation effect',\n parameters: [\n { name: 'frequency', label: 'Rate', type: 'number', min: 0.1, max: 20, step: 0.1, default: 5, unit: 'Hz' },\n { name: 'depth', label: 'Depth', type: 'number', min: 0, max: 1, step: 0.01, default: 0.1 },\n { name: 'wet', label: 'Mix', type: 'number', min: 0, max: 1, step: 0.01, default: 1 },\n ],\n },\n {\n id: 'autoPanner',\n name: 'Auto Panner',\n category: 'modulation',\n description: 'Automatic left-right panning',\n parameters: [\n { name: 'frequency', label: 'Rate', type: 'number', min: 0.1, max: 10, step: 0.1, default: 1, unit: 'Hz' },\n { name: 'depth', label: 'Depth', type: 'number', min: 0, max: 1, step: 0.01, default: 1 },\n { name: 'wet', label: 'Mix', type: 'number', min: 0, max: 1, step: 0.01, default: 1 },\n ],\n },\n\n // === FILTER EFFECTS ===\n {\n id: 'autoFilter',\n name: 'Auto Filter',\n category: 'filter',\n description: 'Automated filter sweep with LFO',\n parameters: [\n { name: 'frequency', label: 'Rate', type: 'number', min: 0.1, max: 10, step: 0.1, default: 1, unit: 'Hz' },\n { name: 'baseFrequency', label: 'Base Freq', type: 'number', min: 20, max: 2000, step: 10, default: 200, unit: 'Hz' },\n { name: 'octaves', label: 'Octaves', type: 'number', min: 0.5, max: 8, step: 0.5, default: 2.6 },\n { name: 'depth', label: 'Depth', type: 'number', min: 0, max: 1, step: 0.01, default: 1 },\n { name: 'wet', label: 'Mix', type: 'number', min: 0, max: 1, step: 0.01, default: 1 },\n ],\n },\n {\n id: 'autoWah',\n name: 'Auto Wah',\n category: 'filter',\n description: 'Envelope follower filter effect',\n parameters: [\n { name: 'baseFrequency', label: 'Base Freq', type: 'number', min: 20, max: 500, step: 10, default: 100, unit: 'Hz' },\n { name: 'octaves', label: 'Octaves', type: 'number', min: 1, max: 8, step: 1, default: 6 },\n { name: 'sensitivity', label: 'Sensitivity', type: 'number', min: -40, max: 0, step: 1, default: 0, unit: 'dB' },\n { name: 'wet', label: 'Mix', type: 'number', min: 0, max: 1, step: 0.01, default: 1 },\n ],\n },\n {\n id: 'eq3',\n name: '3-Band EQ',\n category: 'filter',\n description: 'Three band equalizer with low, mid, and high controls',\n parameters: [\n { name: 'low', label: 'Low', type: 'number', min: -24, max: 24, step: 0.5, default: 0, unit: 'dB' },\n { name: 'mid', label: 'Mid', type: 'number', min: -24, max: 24, step: 0.5, default: 0, unit: 'dB' },\n { name: 'high', label: 'High', type: 'number', min: -24, max: 24, step: 0.5, default: 0, unit: 'dB' },\n { name: 'lowFrequency', label: 'Low Freq', type: 'number', min: 20, max: 500, step: 10, default: 400, unit: 'Hz' },\n { name: 'highFrequency', label: 'High Freq', type: 'number', min: 1000, max: 10000, step: 100, default: 2500, unit: 'Hz' },\n ],\n },\n\n // === DISTORTION EFFECTS ===\n {\n id: 'distortion',\n name: 'Distortion',\n category: 'distortion',\n description: 'Wave shaping distortion effect',\n parameters: [\n { name: 'distortion', label: 'Drive', type: 'number', min: 0, max: 1, step: 0.01, default: 0.4 },\n { name: 'wet', label: 'Mix', type: 'number', min: 0, max: 1, step: 0.01, default: 1 },\n ],\n },\n {\n id: 'bitCrusher',\n name: 'Bit Crusher',\n category: 'distortion',\n description: 'Reduces bit depth for lo-fi digital texture',\n parameters: [\n { name: 'bits', label: 'Bits', type: 'number', min: 1, max: 16, step: 1, default: 4 },\n { name: 'wet', label: 'Mix', type: 'number', min: 0, max: 1, step: 0.01, default: 1 },\n ],\n },\n {\n id: 'chebyshev',\n name: 'Chebyshev',\n category: 'distortion',\n description: 'Waveshaping distortion using Chebyshev polynomials',\n parameters: [\n { name: 'order', label: 'Order', type: 'number', min: 1, max: 100, step: 1, default: 50 },\n { name: 'wet', label: 'Mix', type: 'number', min: 0, max: 1, step: 0.01, default: 1 },\n ],\n },\n\n // === DYNAMICS EFFECTS ===\n {\n id: 'compressor',\n name: 'Compressor',\n category: 'dynamics',\n description: 'Dynamic range compressor',\n parameters: [\n { name: 'threshold', label: 'Threshold', type: 'number', min: -60, max: 0, step: 1, default: -24, unit: 'dB' },\n { name: 'ratio', label: 'Ratio', type: 'number', min: 1, max: 20, step: 0.5, default: 4 },\n { name: 'attack', label: 'Attack', type: 'number', min: 0, max: 1, step: 0.001, default: 0.003, unit: 's' },\n { name: 'release', label: 'Release', type: 'number', min: 0, max: 1, step: 0.01, default: 0.25, unit: 's' },\n { name: 'knee', label: 'Knee', type: 'number', min: 0, max: 40, step: 1, default: 30, unit: 'dB' },\n ],\n },\n {\n id: 'limiter',\n name: 'Limiter',\n category: 'dynamics',\n description: 'Hard limiter to prevent clipping',\n parameters: [\n { name: 'threshold', label: 'Threshold', type: 'number', min: -12, max: 0, step: 0.5, default: -6, unit: 'dB' },\n ],\n },\n {\n id: 'gate',\n name: 'Gate',\n category: 'dynamics',\n description: 'Noise gate to silence signal below threshold',\n parameters: [\n { name: 'threshold', label: 'Threshold', type: 'number', min: -100, max: 0, step: 1, default: -40, unit: 'dB' },\n { name: 'attack', label: 'Attack', type: 'number', min: 0, max: 0.3, step: 0.001, default: 0.001, unit: 's' },\n { name: 'release', label: 'Release', type: 'number', min: 0, max: 0.5, step: 0.01, default: 0.1, unit: 's' },\n ],\n },\n\n // === SPATIAL EFFECTS ===\n {\n id: 'stereoWidener',\n name: 'Stereo Widener',\n category: 'spatial',\n description: 'Expands or narrows the stereo image',\n parameters: [\n { name: 'width', label: 'Width', type: 'number', min: 0, max: 1, step: 0.01, default: 0.5 },\n ],\n },\n];\n\n// Helper to get effect definition by ID\nexport const getEffectDefinition = (id: string): EffectDefinition | undefined => {\n return effectDefinitions.find((def) => def.id === id);\n};\n\n// Helper to get effects by category\nexport const getEffectsByCategory = (category: EffectDefinition['category']): EffectDefinition[] => {\n return effectDefinitions.filter((def) => def.category === category);\n};\n\n// All categories with their display names\nexport const effectCategories: { id: EffectDefinition['category']; name: string }[] = [\n { id: 'reverb', name: 'Reverb' },\n { id: 'delay', name: 'Delay' },\n { id: 'modulation', name: 'Modulation' },\n { id: 'filter', name: 'Filter' },\n { id: 'distortion', name: 'Distortion' },\n { id: 'dynamics', name: 'Dynamics' },\n { id: 'spatial', name: 'Spatial' },\n];\n","/**\n * Factory for creating Tone.js effect instances from effect definitions\n */\nimport {\n Reverb,\n Freeverb,\n JCReverb,\n FeedbackDelay,\n PingPongDelay,\n Chorus,\n Phaser,\n Tremolo,\n Vibrato,\n AutoPanner,\n AutoFilter,\n AutoWah,\n EQ3,\n Distortion,\n BitCrusher,\n Chebyshev,\n Compressor,\n Limiter,\n Gate,\n StereoWidener,\n} from 'tone';\nimport type { EffectDefinition } from './effectDefinitions';\n\n// Type for effect instance with common methods\nexport interface EffectInstance {\n effect: any; // Tone.js effect instance\n id: string;\n instanceId: string;\n dispose: () => void;\n setParameter: (name: string, value: number | string | boolean) => void;\n getParameter: (name: string) => number | string | boolean | undefined;\n connect: (destination: any) => void;\n disconnect: () => void;\n}\n\n// Map of effect IDs to their Tone.js constructors\nconst effectConstructors: Record<string, new (options?: any) => any> = {\n reverb: Reverb,\n freeverb: Freeverb,\n jcReverb: JCReverb,\n feedbackDelay: FeedbackDelay,\n pingPongDelay: PingPongDelay,\n chorus: Chorus,\n phaser: Phaser,\n tremolo: Tremolo,\n vibrato: Vibrato,\n autoPanner: AutoPanner,\n autoFilter: AutoFilter,\n autoWah: AutoWah,\n eq3: EQ3,\n distortion: Distortion,\n bitCrusher: BitCrusher,\n chebyshev: Chebyshev,\n compressor: Compressor,\n limiter: Limiter,\n gate: Gate,\n stereoWidener: StereoWidener,\n};\n\n// Generate unique instance ID\nlet instanceCounter = 0;\nconst generateInstanceId = (): string => {\n return `effect_${Date.now()}_${++instanceCounter}`;\n};\n\n/**\n * Create an effect instance from a definition with initial parameter values\n */\nexport function createEffectInstance(\n definition: EffectDefinition,\n initialParams?: Record<string, number | string | boolean>\n): EffectInstance {\n const Constructor = effectConstructors[definition.id];\n if (!Constructor) {\n throw new Error(`Unknown effect type: ${definition.id}`);\n }\n\n // Build initial options from definition defaults and any overrides\n const options: Record<string, any> = {};\n definition.parameters.forEach((param) => {\n const value = initialParams?.[param.name] ?? param.default;\n options[param.name] = value;\n });\n\n // Create the effect instance\n const effect = new Constructor(options);\n const instanceId = generateInstanceId();\n\n return {\n effect,\n id: definition.id,\n instanceId,\n\n dispose() {\n try {\n effect.disconnect();\n effect.dispose();\n } catch (e) {\n // Ignore errors during cleanup\n }\n },\n\n setParameter(name: string, value: number | string | boolean) {\n // Handle special cases for different effect types\n if (name === 'wet' && effect.wet) {\n effect.wet.value = value as number;\n } else if (effect[name] !== undefined) {\n // Check if it's a Tone.js Signal (has .value property)\n if (effect[name]?.value !== undefined) {\n effect[name].value = value;\n } else {\n effect[name] = value;\n }\n }\n },\n\n getParameter(name: string): number | string | boolean | undefined {\n if (name === 'wet' && effect.wet) {\n return effect.wet.value;\n }\n if (effect[name] !== undefined) {\n if (effect[name]?.value !== undefined) {\n return effect[name].value;\n }\n return effect[name];\n }\n return undefined;\n },\n\n connect(destination: any) {\n effect.connect(destination);\n },\n\n disconnect() {\n try {\n effect.disconnect();\n } catch (e) {\n // Ignore disconnect errors\n }\n },\n };\n}\n\n/**\n * Create a chain of effects connected in series\n */\nexport function createEffectChain(\n effects: EffectInstance[]\n): {\n input: any;\n output: any;\n dispose: () => void;\n} {\n if (effects.length === 0) {\n throw new Error('Cannot create effect chain with no effects');\n }\n\n // Connect effects in series\n for (let i = 0; i < effects.length - 1; i++) {\n effects[i].effect.connect(effects[i + 1].effect);\n }\n\n return {\n input: effects[0].effect,\n output: effects[effects.length - 1].effect,\n dispose() {\n effects.forEach((e) => e.dispose());\n },\n };\n}\n","import { useState, useCallback, useRef, useEffect } from 'react';\nimport type { EffectsFunction } from '@waveform-playlist/playout';\nimport {\n effectDefinitions,\n getEffectDefinition,\n type EffectDefinition,\n} from '../effects/effectDefinitions';\nimport {\n createEffectInstance,\n type EffectInstance,\n} from '../effects/effectFactory';\nimport { Analyser } from 'tone';\n\nexport interface ActiveEffect {\n instanceId: string;\n effectId: string;\n definition: EffectDefinition;\n params: Record<string, number | string | boolean>;\n bypassed: boolean;\n}\n\nexport interface UseDynamicEffectsReturn {\n // State\n activeEffects: ActiveEffect[];\n availableEffects: EffectDefinition[];\n\n // Actions\n addEffect: (effectId: string) => void;\n removeEffect: (instanceId: string) => void;\n updateParameter: (instanceId: string, paramName: string, value: number | string | boolean) => void;\n toggleBypass: (instanceId: string) => void;\n reorderEffects: (fromIndex: number, toIndex: number) => void;\n clearAllEffects: () => void;\n\n // For connecting to audio graph\n masterEffects: EffectsFunction;\n\n /**\n * Creates a fresh effects function for offline rendering.\n * This creates new effect instances that work in the offline AudioContext.\n */\n createOfflineEffectsFunction: () => EffectsFunction | undefined;\n\n // Analyser for visualization\n analyserRef: React.RefObject<any>;\n}\n\n/**\n * Hook for managing a dynamic chain of audio effects with real-time parameter updates\n */\nexport function useDynamicEffects(fftSize: number = 256): UseDynamicEffectsReturn {\n // Track active effects in state (for UI)\n const [activeEffects, setActiveEffects] = useState<ActiveEffect[]>([]);\n\n // Ref to store current activeEffects for reading in callbacks (avoids stale closures)\n const activeEffectsRef = useRef<ActiveEffect[]>(activeEffects);\n activeEffectsRef.current = activeEffects;\n\n // Track effect instances (for audio processing)\n const effectInstancesRef = useRef<Map<string, EffectInstance>>(new Map());\n\n // Analyser for visualization\n const analyserRef = useRef<any>(null);\n\n // Reference to the current audio graph nodes\n const graphNodesRef = useRef<{\n masterGainNode: any;\n destination: any;\n analyserNode: any;\n } | null>(null);\n\n // Rebuild the effect chain when effects change\n // Note: effects is passed as parameter to avoid stale closure issues\n const rebuildChain = useCallback((effects: ActiveEffect[]) => {\n const nodes = graphNodesRef.current;\n if (!nodes) return;\n\n const { masterGainNode, destination, analyserNode } = nodes;\n\n // Disconnect everything first\n try {\n masterGainNode.disconnect();\n } catch (e) {\n // Ignore disconnect errors\n }\n\n // Get effect instances in order\n const instances = effects\n .map((ae) => effectInstancesRef.current.get(ae.instanceId))\n .filter((inst): inst is EffectInstance => inst !== undefined);\n\n if (instances.length === 0) {\n // No effects - connect directly to analyser -> destination\n masterGainNode.connect(analyserNode);\n analyserNode.connect(destination);\n } else {\n // Connect: masterGain -> effect1 -> effect2 -> ... -> analyser -> destination\n let currentNode: any = masterGainNode;\n\n instances.forEach((inst) => {\n try {\n inst.disconnect();\n } catch (e) {\n // Ignore\n }\n currentNode.connect(inst.effect);\n currentNode = inst.effect;\n });\n\n // Connect last effect to analyser\n currentNode.connect(analyserNode);\n analyserNode.connect(destination);\n }\n }, []);\n\n // Add a new effect\n const addEffect = useCallback((effectId: string) => {\n const definition = getEffectDefinition(effectId);\n if (!definition) {\n console.error(`Unknown effect: ${effectId}`);\n return;\n }\n\n // Build default params\n const params: Record<string, number | string | boolean> = {};\n definition.parameters.forEach((p) => {\n params[p.name] = p.default;\n });\n\n // Create the effect instance\n const instance = createEffectInstance(definition, params);\n effectInstancesRef.current.set(instance.instanceId, instance);\n\n // Add to state\n const newActiveEffect: ActiveEffect = {\n instanceId: instance.instanceId,\n effectId: definition.id,\n definition,\n params,\n bypassed: false,\n };\n\n setActiveEffects((prev) => [...prev, newActiveEffect]);\n }, []);\n\n // Remove an effect\n const removeEffect = useCallback((instanceId: string) => {\n const instance = effectInstancesRef.current.get(instanceId);\n if (instance) {\n instance.dispose();\n effectInstancesRef.current.delete(instanceId);\n }\n\n setActiveEffects((prev) => prev.filter((e) => e.instanceId !== instanceId));\n }, []);\n\n // Update a parameter in real-time\n const updateParameter = useCallback(\n (instanceId: string, paramName: string, value: number | string | boolean) => {\n // Update the actual effect instance\n const instance = effectInstancesRef.current.get(instanceId);\n if (instance) {\n instance.setParameter(paramName, value);\n }\n\n // Update state for UI\n setActiveEffects((prev) =>\n prev.map((e) =>\n e.instanceId === instanceId\n ? { ...e, params: { ...e.params, [paramName]: value } }\n : e\n )\n );\n },\n []\n );\n\n // Toggle bypass for an effect (uses wet parameter - 0 = bypass, restore original for active)\n const toggleBypass = useCallback(\n (instanceId: string) => {\n // Get current state from ref to determine new bypassed value (avoids stale closure)\n const effect = activeEffectsRef.current.find((e) => e.instanceId === instanceId);\n if (!effect) return;\n\n const newBypassed = !effect.bypassed;\n\n // Update the actual effect instance\n // When bypassing: set wet to 0\n // When un-bypassing: restore the original wet value from params\n const instance = effectInstancesRef.current.get(instanceId);\n if (instance) {\n const originalWet = effect.params.wet as number ?? 1;\n instance.setParameter('wet', newBypassed ? 0 : originalWet);\n }\n\n // Update state for UI\n setActiveEffects((prev) =>\n prev.map((e) =>\n e.instanceId === instanceId ? { ...e, bypassed: newBypassed } : e\n )\n );\n },\n []\n );\n\n // Reorder effects in the chain\n const reorderEffects = useCallback((fromIndex: number, toIndex: number) => {\n setActiveEffects((prev) => {\n const newEffects = [...prev];\n const [removed] = newEffects.splice(fromIndex, 1);\n newEffects.splice(toIndex, 0, removed);\n return newEffects;\n });\n }, []);\n\n // Clear all effects\n const clearAllEffects = useCallback(() => {\n // Dispose all instances\n effectInstancesRef.current.forEach((inst) => inst.dispose());\n effectInstancesRef.current.clear();\n\n setActiveEffects([]);\n }, []);\n\n // Rebuild chain when effects change\n useEffect(() => {\n rebuildChain(activeEffects);\n }, [activeEffects, rebuildChain]);\n\n // The effects function that gets passed to WaveformPlaylistProvider\n // This function is stable - it reads from refs at call time to avoid stale closures\n const masterEffects: EffectsFunction = useCallback(\n (masterGainNode, destination, _isOffline) => {\n // Create analyser for visualization\n const analyserNode = new Analyser('fft', fftSize);\n analyserRef.current = analyserNode;\n\n // Store references for rebuilding chain\n graphNodesRef.current = {\n masterGainNode,\n destination,\n analyserNode,\n };\n\n // Build initial chain - read from ref to get current state\n const effects = activeEffectsRef.current;\n const instances = effects\n .map((ae) => effectInstancesRef.current.get(ae.instanceId))\n .filter((inst): inst is EffectInstance => inst !== undefined);\n\n if (instances.length === 0) {\n // No effects - connect directly to analyser -> destination\n masterGainNode.connect(analyserNode);\n analyserNode.connect(destination);\n } else {\n // Connect: masterGain -> effect1 -> effect2 -> ... -> analyser -> destination\n let currentNode: any = masterGainNode;\n\n instances.forEach((inst) => {\n currentNode.connect(inst.effect);\n currentNode = inst.effect;\n });\n\n // Connect last effect to analyser\n currentNode.connect(analyserNode);\n analyserNode.connect(destination);\n }\n\n return function cleanup() {\n analyserNode.dispose();\n analyserRef.current = null;\n graphNodesRef.current = null;\n };\n },\n [fftSize] // Only fftSize - reads effects from ref\n );\n\n // Cleanup on unmount\n useEffect(() => {\n return () => {\n effectInstancesRef.current.forEach((inst) => inst.dispose());\n effectInstancesRef.current.clear();\n };\n }, []);\n\n /**\n * Creates a fresh effects function for offline rendering.\n * This creates new effect instances in the offline context, avoiding the\n * AudioContext mismatch issue that occurs when reusing real-time effects.\n */\n const createOfflineEffectsFunction = useCallback((): EffectsFunction | undefined => {\n // Get non-bypassed effects\n const nonBypassedEffects = activeEffects.filter((e) => !e.bypassed);\n\n if (nonBypassedEffects.length === 0) {\n return undefined;\n }\n\n // Return a function that creates fresh effect instances\n return (masterGainNode: any, destination: any, _isOffline: boolean) => {\n // Create fresh effect instances for offline context\n const offlineInstances: EffectInstance[] = [];\n\n for (const activeEffect of nonBypassedEffects) {\n const instance = createEffectInstance(activeEffect.definition, activeEffect.params);\n offlineInstances.push(instance);\n }\n\n if (offlineInstances.length === 0) {\n // No effects - connect directly\n masterGainNode.connect(destination);\n } else {\n // Connect: masterGain -> effect1 -> effect2 -> ... -> destination\n let currentNode: any = masterGainNode;\n\n offlineInstances.forEach((inst) => {\n currentNode.connect(inst.effect);\n currentNode = inst.effect;\n });\n\n // Connect last effect to destination\n currentNode.connect(destination);\n }\n\n return function cleanup() {\n offlineInstances.forEach((inst) => inst.dispose());\n };\n };\n }, [activeEffects]);\n\n return {\n activeEffects,\n availableEffects: effectDefinitions,\n addEffect,\n removeEffect,\n updateParameter,\n toggleBypass,\n reorderEffects,\n clearAllEffects,\n masterEffects,\n createOfflineEffectsFunction,\n analyserRef,\n };\n}\n","import { useState, useCallback, useRef, useEffect } from 'react';\nimport type { TrackEffectsFunction } from '../index';\nimport {\n effectDefinitions,\n getEffectDefinition,\n type EffectDefinition,\n} from '../effects/effectDefinitions';\nimport {\n createEffectInstance,\n type EffectInstance,\n} from '../effects/effectFactory';\n\nexport interface TrackActiveEffect {\n instanceId: string;\n effectId: string;\n definition: EffectDefinition;\n params: Record<string, number | string | boolean>;\n bypassed: boolean;\n}\n\nexport interface TrackEffectsState {\n trackId: string;\n activeEffects: TrackActiveEffect[];\n}\n\nexport interface UseTrackDynamicEffectsReturn {\n // State per track\n trackEffectsState: Map<string, TrackActiveEffect[]>;\n\n // Actions\n addEffectToTrack: (trackId: string, effectId: string) => void;\n removeEffectFromTrack: (trackId: string, instanceId: string) => void;\n updateTrackEffectParameter: (\n trackId: string,\n instanceId: string,\n paramName: string,\n value: number | string | boolean\n ) => void;\n toggleBypass: (trackId: string, instanceId: string) => void;\n clearTrackEffects: (trackId: string) => void;\n getTrackEffectsFunction: (trackId: string) => TrackEffectsFunction | undefined;\n\n /**\n * Creates a fresh effects function for a track for offline rendering.\n * This creates new effect instances that work in the offline AudioContext.\n */\n createOfflineTrackEffectsFunction: (trackId: string) => TrackEffectsFunction | undefined;\n\n // Available effects\n availableEffects: EffectDefinition[];\n}\n\n/**\n * Hook for managing dynamic effects per track with real-time parameter updates\n */\nexport function useTrackDynamicEffects(): UseTrackDynamicEffectsReturn {\n // Track effects state per track (for UI)\n const [trackEffectsState, setTrackEffectsState] = useState<Map<string, TrackActiveEffect[]>>(\n new Map()\n );\n\n // Track effect instances per track (for audio processing)\n const trackEffectInstancesRef = useRef<Map<string, Map<string, EffectInstance>>>(new Map());\n\n // Track graph nodes per track for rebuilding chains\n const trackGraphNodesRef = useRef<\n Map<\n string,\n {\n graphEnd: any;\n masterGainNode: any;\n }\n >\n >(new Map());\n\n // Rebuild the effect chain for a specific track\n // Note: trackEffects is passed as parameter to avoid stale closure issues\n const rebuildTrackChain = useCallback((trackId: string, trackEffects: TrackActiveEffect[]) => {\n const nodes = trackGraphNodesRef.current.get(trackId);\n if (!nodes) return;\n\n const { graphEnd, masterGainNode } = nodes;\n const instancesMap = trackEffectInstancesRef.current.get(trackId);\n\n // Disconnect everything first\n try {\n graphEnd.disconnect();\n } catch (e) {\n // Ignore disconnect errors\n }\n\n // Get effect instances in order\n const instances = trackEffects\n .map((ae) => instancesMap?.get(ae.instanceId))\n .filter((inst): inst is EffectInstance => inst !== undefined);\n\n if (instances.length === 0) {\n // No effects - connect directly\n graphEnd.connect(masterGainNode);\n } else {\n // Connect: graphEnd -> effect1 -> effect2 -> ... -> masterGainNode\n let currentNode: any = graphEnd;\n\n instances.forEach((inst) => {\n try {\n inst.disconnect();\n } catch (e) {\n // Ignore\n }\n currentNode.connect(inst.effect);\n currentNode = inst.effect;\n });\n\n // Connect last effect to master\n currentNode.connect(masterGainNode);\n }\n }, []);\n\n // Add a new effect to a track\n const addEffectToTrack = useCallback((trackId: string, effectId: string) => {\n const definition = getEffectDefinition(effectId);\n if (!definition) {\n console.error(`Unknown effect: ${effectId}`);\n return;\n }\n\n // Build default params\n const params: Record<string, number | string | boolean> = {};\n definition.parameters.forEach((p) => {\n params[p.name] = p.default;\n });\n\n // Create the effect instance\n const instance = createEffectInstance(definition, params);\n\n // Initialize maps if needed\n if (!trackEffectInstancesRef.current.has(trackId)) {\n trackEffectInstancesRef.current.set(trackId, new Map());\n }\n trackEffectInstancesRef.current.get(trackId)!.set(instance.instanceId, instance);\n\n // Add to state\n const newActiveEffect: TrackActiveEffect = {\n instanceId: instance.instanceId,\n effectId: definition.id,\n definition,\n params,\n bypassed: false,\n };\n\n setTrackEffectsState((prev) => {\n const newState = new Map(prev);\n const existing = newState.get(trackId) || [];\n newState.set(trackId, [...existing, newActiveEffect]);\n return newState;\n });\n }, []);\n\n // Remove an effect from a track\n const removeEffectFromTrack = useCallback((trackId: string, instanceId: string) => {\n const instancesMap = trackEffectInstancesRef.current.get(trackId);\n const instance = instancesMap?.get(instanceId);\n if (instance) {\n instance.dispose();\n instancesMap?.delete(instanceId);\n }\n\n setTrackEffectsState((prev) => {\n const newState = new Map(prev);\n const existing = newState.get(trackId) || [];\n newState.set(trackId, existing.filter((e) => e.instanceId !== instanceId));\n return newState;\n });\n }, []);\n\n // Update a parameter in real-time\n const updateTrackEffectParameter = useCallback(\n (trackId: string, instanceId: string, paramName: string, value: number | string | boolean) => {\n // Update the actual effect instance\n const instancesMap = trackEffectInstancesRef.current.get(trackId);\n const instance = instancesMap?.get(instanceId);\n if (instance) {\n instance.setParameter(paramName, value);\n }\n\n // Update state for UI\n setTrackEffectsState((prev) => {\n const newState = new Map(prev);\n const existing = newState.get(trackId) || [];\n newState.set(\n trackId,\n existing.map((e) =>\n e.instanceId === instanceId\n ? { ...e, params: { ...e.params, [paramName]: value } }\n : e\n )\n );\n return newState;\n });\n },\n []\n );\n\n // Toggle bypass for an effect (uses wet parameter - 0 = bypass, restore original for active)\n const toggleBypass = useCallback(\n (trackId: string, instanceId: string) => {\n // Get current state from ref to determine new bypassed value (avoids stale closure)\n const trackEffects = trackEffectsStateRef.current.get(trackId) || [];\n const effect = trackEffects.find((e) => e.instanceId === instanceId);\n if (!effect) return;\n\n const newBypassed = !effect.bypassed;\n\n // Update the actual effect instance\n // When bypassing: set wet to 0\n // When un-bypassing: restore the original wet value from params\n const instancesMap = trackEffectInstancesRef.current.get(trackId);\n const instance = instancesMap?.get(instanceId);\n if (instance) {\n const originalWet = effect.params.wet as number ?? 1;\n instance.setParameter('wet', newBypassed ? 0 : originalWet);\n }\n\n // Update state for UI\n setTrackEffectsState((prev) => {\n const newState = new Map(prev);\n const existing = newState.get(trackId) || [];\n newState.set(\n trackId,\n existing.map((e) =>\n e.instanceId === instanceId ? { ...e, bypassed: newBypassed } : e\n )\n );\n return newState;\n });\n },\n []\n );\n\n // Clear all effects from a track\n const clearTrackEffects = useCallback((trackId: string) => {\n // Dispose all instances for this track\n const instancesMap = trackEffectInstancesRef.current.get(trackId);\n if (instancesMap) {\n instancesMap.forEach((inst) => inst.dispose());\n instancesMap.clear();\n }\n\n setTrackEffectsState((prev) => {\n const newState = new Map(prev);\n newState.set(trackId, []);\n return newState;\n });\n }, []);\n\n // Ref to store the current trackEffectsState for reading in effects function\n // This avoids stale closure issues when the effects function is called later\n const trackEffectsStateRef = useRef<Map<string, TrackActiveEffect[]>>(trackEffectsState);\n trackEffectsStateRef.current = trackEffectsState;\n\n // Get the effects function for a track to pass to useAudioTracks\n // This function is stable (no dependencies) - it reads from refs at call time\n const getTrackEffectsFunction = useCallback(\n (trackId: string): TrackEffectsFunction | undefined => {\n // Return a function that connects effects when the track is loaded\n return (graphEnd, masterGainNode, _isOffline) => {\n // Store references for rebuilding chain\n trackGraphNodesRef.current.set(trackId, {\n graphEnd,\n masterGainNode,\n });\n\n // Read current state from ref (not stale closure)\n const trackEffects = trackEffectsStateRef.current.get(trackId) || [];\n const instancesMap = trackEffectInstancesRef.current.get(trackId);\n\n // Get effect instances in order\n const instances = trackEffects\n .map((ae) => instancesMap?.get(ae.instanceId))\n .filter((inst): inst is EffectInstance => inst !== undefined);\n\n if (instances.length === 0) {\n // No effects - connect directly\n graphEnd.connect(masterGainNode);\n } else {\n // Connect: graphEnd -> effect1 -> effect2 -> ... -> masterGainNode\n let currentNode: any = graphEnd;\n\n instances.forEach((inst) => {\n currentNode.connect(inst.effect);\n currentNode = inst.effect;\n });\n\n // Connect last effect to master\n currentNode.connect(masterGainNode);\n }\n\n return function cleanup() {\n trackGraphNodesRef.current.delete(trackId);\n };\n };\n },\n [] // No dependencies - stable function that reads from refs\n );\n\n // Rebuild chains when effects change\n useEffect(() => {\n trackEffectsState.forEach((effects, trackId) => {\n rebuildTrackChain(trackId, effects);\n });\n }, [trackEffectsState, rebuildTrackChain]);\n\n // Cleanup on unmount\n useEffect(() => {\n return () => {\n trackEffectInstancesRef.current.forEach((instancesMap) => {\n instancesMap.forEach((inst) => inst.dispose());\n instancesMap.clear();\n });\n trackEffectInstancesRef.current.clear();\n };\n }, []);\n\n /**\n * Creates a fresh effects function for a track for offline rendering.\n * This creates new effect instances in the offline context, avoiding the\n * AudioContext mismatch issue that occurs when reusing real-time effects.\n */\n const createOfflineTrackEffectsFunction = useCallback(\n (trackId: string): TrackEffectsFunction | undefined => {\n const trackEffects = trackEffectsState.get(trackId) || [];\n // Get non-bypassed effects\n const nonBypassedEffects = trackEffects.filter((e) => !e.bypassed);\n\n if (nonBypassedEffects.length === 0) {\n return undefined;\n }\n\n // Return a function that creates fresh effect instances\n return (graphEnd: any, masterGainNode: any, _isOffline: boolean) => {\n // Create fresh effect instances for offline context\n const offlineInstances: EffectInstance[] = [];\n\n for (const activeEffect of nonBypassedEffects) {\n const instance = createEffectInstance(activeEffect.definition, activeEffect.params);\n offlineInstances.push(instance);\n }\n\n if (offlineInstances.length === 0) {\n // No effects - connect directly\n graphEnd.connect(masterGainNode);\n } else {\n // Connect: graphEnd -> effect1 -> effect2 -> ... -> masterGainNode\n let currentNode: any = graphEnd;\n\n offlineInstances.forEach((inst) => {\n currentNode.connect(inst.effect);\n currentNode = inst.effect;\n });\n\n // Connect last effect to master\n currentNode.connect(masterGainNode);\n }\n\n return function cleanup() {\n offlineInstances.forEach((inst) => inst.dispose());\n };\n };\n },\n [trackEffectsState]\n );\n\n return {\n trackEffectsState,\n addEffectToTrack,\n removeEffectFromTrack,\n updateTrackEffectParameter,\n toggleBypass,\n clearTrackEffects,\n getTrackEffectsFunction,\n createOfflineTrackEffectsFunction,\n availableEffects: effectDefinitions,\n };\n}\n","/**\n * WAV file encoder\n * Converts AudioBuffer to WAV format Blob\n */\n\nexport interface WavEncoderOptions {\n /** Bit depth: 16 or 32. Default: 16 */\n bitDepth?: 16 | 32;\n}\n\n/**\n * Encode an AudioBuffer to WAV format\n * @param audioBuffer - The AudioBuffer to encode\n * @param options - Encoding options\n * @returns WAV file as Blob\n */\nexport function encodeWav(\n audioBuffer: AudioBuffer,\n options: WavEncoderOptions = {}\n): Blob {\n const { bitDepth = 16 } = options;\n\n const numChannels = audioBuffer.numberOfChannels;\n const sampleRate = audioBuffer.sampleRate;\n const numSamples = audioBuffer.length;\n const bytesPerSample = bitDepth / 8;\n const blockAlign = numChannels * bytesPerSample;\n const byteRate = sampleRate * blockAlign;\n const dataSize = numSamples * blockAlign;\n\n // WAV header is 44 bytes\n const headerSize = 44;\n const totalSize = headerSize + dataSize;\n\n const buffer = new ArrayBuffer(totalSize);\n const view = new DataView(buffer);\n\n // Write WAV header\n // RIFF chunk descriptor\n writeString(view, 0, 'RIFF');\n view.setUint32(4, totalSize - 8, true); // File size minus RIFF header\n writeString(view, 8, 'WAVE');\n\n // fmt sub-chunk\n writeString(view, 12, 'fmt ');\n view.setUint32(16, 16, true); // Subchunk1Size (16 for PCM)\n view.setUint16(20, bitDepth === 32 ? 3 : 1, true); // AudioFormat (1=PCM, 3=IEEE float)\n view.setUint16(22, numChannels, true);\n view.setUint32(24, sampleRate, true);\n view.setUint32(28, byteRate, true);\n view.setUint16(32, blockAlign, true);\n view.setUint16(34, bitDepth, true);\n\n // data sub-chunk\n writeString(view, 36, 'data');\n view.setUint32(40, dataSize, true);\n\n // Write interleaved audio data\n const channelData: Float32Array[] = [];\n for (let ch = 0; ch < numChannels; ch++) {\n channelData.push(audioBuffer.getChannelData(ch));\n }\n\n let offset = headerSize;\n\n if (bitDepth === 16) {\n // 16-bit PCM\n for (let i = 0; i < numSamples; i++) {\n for (let ch = 0; ch < numChannels; ch++) {\n const sample = channelData[ch][i];\n // Clamp to [-1, 1] and convert to 16-bit signed integer\n const clampedSample = Math.max(-1, Math.min(1, sample));\n const intSample = clampedSample < 0\n ? clampedSample * 0x8000\n : clampedSample * 0x7FFF;\n view.setInt16(offset, intSample, true);\n offset += 2;\n }\n }\n } else {\n // 32-bit IEEE float\n for (let i = 0; i < numSamples; i++) {\n for (let ch = 0; ch < numChannels; ch++) {\n view.setFloat32(offset, channelData[ch][i], true);\n offset += 4;\n }\n }\n }\n\n return new Blob([buffer], { type: 'audio/wav' });\n}\n\n/**\n * Write a string to a DataView at the specified offset\n */\nfunction writeString(view: DataView, offset: number, str: string): void {\n for (let i = 0; i < str.length; i++) {\n view.setUint8(offset + i, str.charCodeAt(i));\n }\n}\n\n/**\n * Trigger a download of a Blob with the specified filename\n */\nexport function downloadBlob(blob: Blob, filename: string): void {\n const url = URL.createObjectURL(blob);\n const a = document.createElement('a');\n a.href = url;\n a.download = filename;\n a.style.display = 'none';\n document.body.appendChild(a);\n a.click();\n document.body.removeChild(a);\n URL.revokeObjectURL(url);\n}\n","import { useState, useCallback } from 'react';\nimport type { ClipTrack, AudioClip, FadeType } from '@waveform-playlist/core';\nimport type { EffectsFunction } from '@waveform-playlist/playout';\nimport { encodeWav, downloadBlob, type WavEncoderOptions } from '../utils/wavEncoder';\n\n/** Function type for per-track effects (same as in @waveform-playlist/core) */\nexport type TrackEffectsFunction = (graphEnd: unknown, destination: unknown, isOffline: boolean) => void | (() => void);\n\nexport interface ExportOptions extends WavEncoderOptions {\n /** Filename for download (without extension) */\n filename?: string;\n /** Export mode: 'master' for stereo mix, 'individual' for single track */\n mode?: 'master' | 'individual';\n /** Track index for individual export (only used when mode is 'individual') */\n trackIndex?: number;\n /** Whether to trigger automatic download */\n autoDownload?: boolean;\n /** Whether to apply effects (fades, etc.) - defaults to true */\n applyEffects?: boolean;\n /**\n * Optional Tone.js effects function for master effects. When provided, export will use Tone.Offline\n * to render through the effects chain. The function receives isOffline=true.\n */\n effectsFunction?: EffectsFunction;\n /**\n * Optional function to create offline track effects.\n * Takes a trackId and returns a TrackEffectsFunction for offline rendering.\n * This is used instead of track.effects to avoid AudioContext mismatch issues.\n */\n createOfflineTrackEffects?: (trackId: string) => TrackEffectsFunction | undefined;\n /** Progress callback (0-1) */\n onProgress?: (progress: number) => void;\n}\n\nexport interface ExportResult {\n /** The rendered audio buffer */\n audioBuffer: AudioBuffer;\n /** The WAV file as a Blob */\n blob: Blob;\n /** Duration in seconds */\n duration: number;\n}\n\nexport interface UseExportWavReturn {\n /** Export the playlist to WAV */\n exportWav: (tracks: ClipTrack[], trackStates: TrackState[], options?: ExportOptions) => Promise<ExportResult>;\n /** Whether export is in progress */\n isExporting: boolean;\n /** Export progress (0-1) */\n progress: number;\n /** Error message if export failed */\n error: string | null;\n}\n\ninterface TrackState {\n muted: boolean;\n soloed: boolean;\n volume: number;\n pan: number;\n}\n\n/**\n * Hook for exporting the waveform playlist to WAV format\n * Uses OfflineAudioContext for fast, non-real-time rendering\n */\nexport function useExportWav(): UseExportWavReturn {\n const [isExporting, setIsExporting] = useState(false);\n const [progress, setProgress] = useState(0);\n const [error, setError] = useState<string | null>(null);\n\n const exportWav = useCallback(async (\n tracks: ClipTrack[],\n trackStates: TrackState[],\n options: ExportOptions = {}\n ): Promise<ExportResult> => {\n const {\n filename = 'export',\n mode = 'master',\n trackIndex,\n autoDownload = true,\n applyEffects = true,\n effectsFunction,\n createOfflineTrackEffects,\n bitDepth = 16,\n onProgress,\n } = options;\n\n setIsExporting(true);\n setProgress(0);\n setError(null);\n\n try {\n // Validate inputs\n if (tracks.length === 0) {\n throw new Error('No tracks to export');\n }\n\n if (mode === 'individual' && (trackIndex === undefined || trackIndex < 0 || trackIndex >= tracks.length)) {\n throw new Error('Invalid track index for individual export');\n }\n\n // Get sample rate from first clip (use clip.sampleRate which is always defined)\n const sampleRate = tracks[0].clips[0]?.sampleRate || 44100;\n\n // Calculate total duration from all clips (in samples)\n let totalDurationSamples = 0;\n for (const track of tracks) {\n for (const clip of track.clips) {\n const clipEndSample = clip.startSample + clip.durationSamples;\n totalDurationSamples = Math.max(totalDurationSamples, clipEndSample);\n }\n }\n\n // Add a small buffer at the end (0.1 seconds) to avoid cutting off\n totalDurationSamples += Math.round(sampleRate * 0.1);\n\n const duration = totalDurationSamples / sampleRate;\n\n // Determine which tracks to render\n const tracksToRender = mode === 'individual'\n ? [{ track: tracks[trackIndex!], state: trackStates[trackIndex!], index: trackIndex! }]\n : tracks.map((track, index) => ({ track, state: trackStates[index], index }));\n\n // Check for solo - if any track is soloed, only play soloed tracks\n const hasSolo = trackStates.some(state => state.soloed);\n\n // Check if per-track effects are provided via the offline creator function\n // Note: We don't use track.effects directly for offline rendering to avoid AudioContext mismatch\n const hasOfflineTrackEffects = !!createOfflineTrackEffects;\n\n let renderedBuffer: AudioBuffer;\n\n if ((effectsFunction || hasOfflineTrackEffects) && applyEffects) {\n // Use Tone.Offline for rendering with effects (master and/or per-track)\n renderedBuffer = await renderWithToneEffects(\n tracksToRender,\n trackStates,\n hasSolo,\n duration,\n sampleRate,\n effectsFunction,\n createOfflineTrackEffects,\n (p) => {\n setProgress(p);\n onProgress?.(p);\n }\n );\n } else {\n // Use standard OfflineAudioContext rendering\n const offlineCtx = new OfflineAudioContext(2, totalDurationSamples, sampleRate);\n\n // Schedule all clips for rendering\n let scheduledClips = 0;\n const totalClips = tracksToRender.reduce((sum, { track }) => sum + track.clips.length, 0);\n\n for (const { track, state } of tracksToRender) {\n // Skip muted tracks (unless soloed)\n if (state.muted && !state.soloed) continue;\n // If there's a solo and this track isn't soloed, skip it\n if (hasSolo && !state.soloed) continue;\n\n for (const clip of track.clips) {\n await scheduleClip(offlineCtx, clip, state, sampleRate, applyEffects);\n scheduledClips++;\n const currentProgress = scheduledClips / totalClips * 0.5; // First 50% is scheduling\n setProgress(currentProgress);\n onProgress?.(currentProgress);\n }\n }\n\n // Render the audio\n setProgress(0.5);\n onProgress?.(0.5);\n\n renderedBuffer = await offlineCtx.startRendering();\n }\n\n setProgress(0.9);\n onProgress?.(0.9);\n\n // Encode to WAV\n const blob = encodeWav(renderedBuffer, { bitDepth });\n\n setProgress(1);\n onProgress?.(1);\n\n // Auto download if requested\n if (autoDownload) {\n const exportFilename = mode === 'individual'\n ? `${filename}_${tracks[trackIndex!].name}`\n : filename;\n downloadBlob(blob, `${exportFilename}.wav`);\n }\n\n return {\n audioBuffer: renderedBuffer,\n blob,\n duration,\n };\n } catch (err) {\n const message = err instanceof Error ? err.message : 'Export failed';\n setError(message);\n throw err;\n } finally {\n setIsExporting(false);\n }\n }, []);\n\n return {\n exportWav,\n isExporting,\n progress,\n error,\n };\n}\n\n/**\n * Render using Tone.Offline with effects chain (master and/or per-track)\n */\nasync function renderWithToneEffects(\n tracksToRender: { track: ClipTrack; state: TrackState; index: number }[],\n _trackStates: TrackState[],\n hasSolo: boolean,\n duration: number,\n sampleRate: number,\n effectsFunction: EffectsFunction | undefined,\n createOfflineTrackEffects: ((trackId: string) => TrackEffectsFunction | undefined) | undefined,\n onProgress: (progress: number) => void\n): Promise<AudioBuffer> {\n // Dynamically import Tone.js modules\n const { Offline, Volume, Gain, Panner, Player, ToneAudioBuffer } = await import('tone');\n\n onProgress(0.1);\n\n // Use Tone.Offline to render with effects\n let buffer;\n try {\n buffer = await Offline(\n async ({ transport, destination }) => {\n // Create master volume node\n const masterVolume = new Volume(0); // 0 dB = unity gain\n\n // Apply master effects chain if provided, otherwise connect directly to destination\n let cleanup: void | (() => void) = undefined;\n if (effectsFunction) {\n cleanup = effectsFunction(masterVolume, destination, true);\n } else {\n masterVolume.connect(destination);\n }\n\n // Schedule all clips\n for (const { track, state } of tracksToRender) {\n // Skip muted tracks (unless soloed)\n if (state.muted && !state.soloed) continue;\n // If there's a solo and this track isn't soloed, skip it\n if (hasSolo && !state.soloed) continue;\n\n // Create track-level nodes\n const trackVolume = new Volume(gainToDb(state.volume));\n const trackPan = new Panner(state.pan);\n const trackMute = new Gain(state.muted ? 0 : 1);\n\n // Get offline track effects using the creator function\n // Note: We use createOfflineTrackEffects instead of track.effects to avoid AudioContext mismatch\n const trackEffects = createOfflineTrackEffects?.(track.id);\n\n if (trackEffects) {\n // Apply per-track effects chain: trackMute -> effects -> masterVolume\n trackEffects(trackMute, masterVolume, true);\n } else {\n // No per-track effects: connect directly to master\n trackMute.connect(masterVolume);\n }\n\n // Connect track chain: clips -> trackVolume -> trackPan -> trackMute\n trackPan.connect(trackMute);\n trackVolume.connect(trackPan);\n\n // Schedule each clip\n for (const clip of track.clips) {\n const { audioBuffer, startSample, durationSamples, offsetSamples, gain: clipGain, fadeIn, fadeOut } = clip;\n\n // Convert samples to seconds\n const startTime = startSample / sampleRate;\n const clipDuration = durationSamples / sampleRate;\n const offset = offsetSamples / sampleRate;\n\n // Create a ToneAudioBuffer from the existing AudioBuffer\n const toneBuffer = new ToneAudioBuffer(audioBuffer);\n\n // Create player for this clip\n const player = new Player(toneBuffer);\n\n // Create fade gain for clip-level effects\n const fadeGain = new Gain(clipGain);\n\n // Connect player -> fadeGain -> trackVolume\n player.connect(fadeGain);\n fadeGain.connect(trackVolume);\n\n // Apply fades using gain automation\n // New simple API: fadeIn starts at clip start, fadeOut ends at clip end\n if (fadeIn) {\n const fadeInStart = startTime;\n const fadeInEnd = startTime + fadeIn.duration;\n const audioParam = (fadeGain.gain as any)._param as AudioParam;\n // Set initial value to 0\n audioParam.setValueAtTime(0, fadeInStart);\n audioParam.linearRampToValueAtTime(clipGain, fadeInEnd);\n }\n\n if (fadeOut) {\n const fadeOutStart = startTime + clipDuration - fadeOut.duration;\n const fadeOutEnd = startTime + clipDuration;\n const audioParam = (fadeGain.gain as any)._param as AudioParam;\n audioParam.setValueAtTime(clipGain, fadeOutStart);\n audioParam.linearRampToValueAtTime(0, fadeOutEnd);\n }\n\n // Schedule the player to start\n player.start(startTime, offset, clipDuration);\n }\n }\n\n // Start the transport\n transport.start(0);\n\n // Clean up effects if cleanup function was provided\n if (cleanup) {\n // Note: cleanup will be called after rendering completes\n }\n },\n duration,\n 2, // stereo\n sampleRate\n );\n } catch (err) {\n // Re-throw with a proper Error object if needed\n if (err instanceof Error) {\n throw err;\n } else {\n throw new Error(`Tone.Offline rendering failed: ${String(err)}`);\n }\n }\n\n onProgress(0.9);\n\n // Convert ToneAudioBuffer to standard AudioBuffer\n return buffer.get() as AudioBuffer;\n}\n\n/**\n * Convert linear gain to decibels\n */\nfunction gainToDb(gain: number): number {\n return 20 * Math.log10(Math.max(gain, 0.0001));\n}\n\n/**\n * Schedule a single clip in the offline context\n */\nasync function scheduleClip(\n ctx: OfflineAudioContext,\n clip: AudioClip,\n trackState: TrackState,\n sampleRate: number,\n applyEffects: boolean\n): Promise<void> {\n const { audioBuffer, startSample, durationSamples, offsetSamples, gain: clipGain, fadeIn, fadeOut } = clip;\n\n // Skip clips without audioBuffer (peaks-only clips can't be exported)\n if (!audioBuffer) {\n console.warn(`Skipping clip \"${clip.name || clip.id}\" - no audioBuffer for export`);\n return;\n }\n\n // Convert samples to seconds for Web Audio API\n const startTime = startSample / sampleRate;\n const duration = durationSamples / sampleRate;\n const offset = offsetSamples / sampleRate;\n\n // Create buffer source\n const source = ctx.createBufferSource();\n source.buffer = audioBuffer;\n\n // Create gain node for clip + track volume\n const gainNode = ctx.createGain();\n const baseGain = clipGain * trackState.volume;\n\n // Create stereo panner for track pan\n const pannerNode = ctx.createStereoPanner();\n pannerNode.pan.value = trackState.pan;\n\n // Connect: source -> gain -> panner -> destination\n source.connect(gainNode);\n gainNode.connect(pannerNode);\n pannerNode.connect(ctx.destination);\n\n // Apply effects (fades) if enabled\n // New simple API: fadeIn starts at clip start, fadeOut ends at clip end\n if (applyEffects) {\n // Set initial gain (may be 0 if fade in exists)\n if (fadeIn) {\n gainNode.gain.setValueAtTime(0, startTime);\n } else {\n gainNode.gain.setValueAtTime(baseGain, startTime);\n }\n\n // Apply fade in\n if (fadeIn) {\n const fadeInStart = startTime;\n const fadeInEnd = startTime + fadeIn.duration;\n applyFadeEnvelope(gainNode.gain, fadeInStart, fadeInEnd, 0, baseGain, fadeIn.type || 'linear');\n }\n\n // Apply fade out\n if (fadeOut) {\n const fadeOutStart = startTime + duration - fadeOut.duration;\n const fadeOutEnd = startTime + duration;\n // Ensure we're at baseGain before fade out starts\n if (!fadeIn || fadeIn.duration < (duration - fadeOut.duration)) {\n gainNode.gain.setValueAtTime(baseGain, fadeOutStart);\n }\n applyFadeEnvelope(gainNode.gain, fadeOutStart, fadeOutEnd, baseGain, 0, fadeOut.type || 'linear');\n }\n } else {\n // No effects - just set constant gain\n gainNode.gain.setValueAtTime(baseGain, startTime);\n }\n\n // Schedule playback\n source.start(startTime, offset, duration);\n}\n\n/**\n * Apply a fade envelope to a gain parameter using Web Audio automation\n */\nfunction applyFadeEnvelope(\n gainParam: AudioParam,\n startTime: number,\n endTime: number,\n startValue: number,\n endValue: number,\n fadeType: FadeType\n): void {\n const duration = endTime - startTime;\n if (duration <= 0) return;\n\n switch (fadeType) {\n case 'linear':\n gainParam.setValueAtTime(startValue, startTime);\n gainParam.linearRampToValueAtTime(endValue, endTime);\n break;\n\n case 'exponential':\n // Exponential can't handle 0 values, use small value instead\n const expStart = Math.max(startValue, 0.0001);\n const expEnd = Math.max(endValue, 0.0001);\n gainParam.setValueAtTime(expStart, startTime);\n gainParam.exponentialRampToValueAtTime(expEnd, endTime);\n // Set to actual 0 if needed\n if (endValue === 0) {\n gainParam.setValueAtTime(0, endTime);\n }\n break;\n\n case 'logarithmic':\n // Logarithmic fade - more aggressive at start, gentler at end\n // Implemented using setValueCurveAtTime with calculated curve\n const logCurve = generateFadeCurve(startValue, endValue, 256, 'logarithmic');\n gainParam.setValueCurveAtTime(logCurve, startTime, duration);\n break;\n\n case 'sCurve':\n // S-curve (ease-in-out) - smooth start and end\n const sCurve = generateFadeCurve(startValue, endValue, 256, 'sCurve');\n gainParam.setValueCurveAtTime(sCurve, startTime, duration);\n break;\n\n default:\n // Default to linear\n gainParam.setValueAtTime(startValue, startTime);\n gainParam.linearRampToValueAtTime(endValue, endTime);\n }\n}\n\n/**\n * Generate a fade curve for setValueCurveAtTime\n */\nfunction generateFadeCurve(\n startValue: number,\n endValue: number,\n numPoints: number,\n curveType: 'logarithmic' | 'sCurve'\n): Float32Array {\n const curve = new Float32Array(numPoints);\n const range = endValue - startValue;\n\n for (let i = 0; i < numPoints; i++) {\n const t = i / (numPoints - 1); // 0 to 1\n\n let curveValue: number;\n if (curveType === 'logarithmic') {\n // Logarithmic: fast at start, slow at end (for fade out)\n // or slow at start, fast at end (for fade in)\n if (range > 0) {\n // Fade in: use log curve\n curveValue = Math.log10(1 + t * 9) / Math.log10(10);\n } else {\n // Fade out: use inverse log curve\n curveValue = 1 - Math.log10(1 + (1 - t) * 9) / Math.log10(10);\n }\n } else {\n // S-curve (smoothstep)\n curveValue = t * t * (3 - 2 * t);\n }\n\n curve[i] = startValue + range * curveValue;\n }\n\n return curve;\n}\n\n/**\n * Export types\n */\nexport type { WavEncoderOptions };\n","import React, { createContext, useContext, useState, useEffect, useRef, useCallback, ReactNode } from 'react';\nimport { ThemeProvider } from 'styled-components';\nimport { TonePlayout, type EffectsFunction, type TrackEffectsFunction } from '@waveform-playlist/playout';\nimport { type Track, type ClipTrack, type Fade } from '@waveform-playlist/core';\nimport { type TimeFormat, type WaveformPlaylistTheme, defaultTheme } from '@waveform-playlist/ui-components';\nimport { start as toneStart, getContext } from 'tone';\nimport { generatePeaks } from './peaksUtil';\nimport { extractPeaksFromWaveformData } from './waveformDataLoader';\nimport type { PeakData } from '@waveform-playlist/webaudio-peaks';\nimport { parseAeneas, type AnnotationData } from '@waveform-playlist/annotations';\nimport { useTimeFormat, useZoomControls, useMasterVolume } from './hooks';\n\n// Types\nexport interface ClipPeaks {\n clipId: string;\n trackName: string;\n peaks: PeakData;\n startSample: number;\n durationSamples: number;\n fadeIn?: Fade;\n fadeOut?: Fade;\n}\n\nexport type TrackClipPeaks = ClipPeaks[];\n\n// Legacy WaveformTrack type - kept for reference but deprecated\n// @deprecated Use ClipTrack from @waveform-playlist/core instead\nexport interface WaveformTrack {\n src: string | AudioBuffer;\n name?: string;\n effects?: TrackEffectsFunction;\n}\n\nexport interface TrackState {\n name: string;\n muted: boolean;\n soloed: boolean;\n volume: number;\n pan: number;\n}\n\nexport interface WaveformPlaylistContextValue {\n // State\n isPlaying: boolean;\n currentTime: number;\n duration: number;\n audioBuffers: AudioBuffer[];\n peaksDataArray: TrackClipPeaks[]; // Array of tracks, each containing array of clip peaks\n trackStates: TrackState[];\n annotations: AnnotationData[];\n activeAnnotationId: string | null;\n selectionStart: number;\n selectionEnd: number;\n isAutomaticScroll: boolean;\n continuousPlay: boolean;\n linkEndpoints: boolean;\n annotationsEditable: boolean;\n\n // Playback controls\n play: (startTime?: number, playDuration?: number) => Promise<void>;\n pause: () => void;\n stop: () => void;\n setCurrentTime: (time: number) => void;\n\n // Track controls\n setTrackMute: (trackIndex: number, muted: boolean) => void;\n setTrackSolo: (trackIndex: number, soloed: boolean) => void;\n setTrackVolume: (trackIndex: number, volume: number) => void;\n setTrackPan: (trackIndex: number, pan: number) => void;\n\n // Selection\n setSelection: (start: number, end: number) => void;\n\n // Time format\n timeFormat: string;\n setTimeFormat: (format: TimeFormat) => void;\n formatTime: (seconds: number) => string;\n\n // Zoom\n samplesPerPixel: number;\n zoomIn: () => void;\n zoomOut: () => void;\n canZoomIn: boolean;\n canZoomOut: boolean;\n\n // Master volume\n masterVolume: number;\n setMasterVolume: (volume: number) => void;\n\n // Automatic scroll\n setAutomaticScroll: (enabled: boolean) => void;\n setScrollContainer: (element: HTMLDivElement | null) => void;\n\n // Annotation controls\n setContinuousPlay: (enabled: boolean) => void;\n setLinkEndpoints: (enabled: boolean) => void;\n setAnnotationsEditable: (enabled: boolean) => void;\n setAnnotations: (annotations: AnnotationData[]) => void;\n setActiveAnnotationId: (id: string | null) => void;\n\n // Refs\n playoutRef: React.RefObject<TonePlayout | null>;\n currentTimeRef: React.RefObject<number>;\n\n // Playlist info\n sampleRate: number;\n waveHeight: number;\n timeScaleHeight: number;\n minimumPlaylistHeight: number;\n controls: { show: boolean; width: number };\n}\n\n// Split contexts for performance optimization\n// High-frequency updates (currentTime) are isolated from low-frequency state changes\n\nexport interface PlaybackAnimationContextValue {\n isPlaying: boolean;\n currentTime: number;\n currentTimeRef: React.RefObject<number>;\n // Refs for direct time calculation in animated components (avoids timing drift)\n playbackStartTimeRef: React.RefObject<number>; // context.currentTime when playback started\n audioStartPositionRef: React.RefObject<number>; // Audio position when playback started\n}\n\nexport interface PlaylistStateContextValue {\n continuousPlay: boolean;\n linkEndpoints: boolean;\n annotationsEditable: boolean;\n isAutomaticScroll: boolean;\n isLoopEnabled: boolean;\n annotations: AnnotationData[];\n activeAnnotationId: string | null;\n selectionStart: number;\n selectionEnd: number;\n selectedTrackId: string | null; // ID of currently selected track for editing operations\n // Loop region (separate from selection) - Audacity-style loop points\n loopStart: number;\n loopEnd: number;\n}\n\nexport interface PlaylistControlsContextValue {\n // Playback controls\n play: (startTime?: number, playDuration?: number) => Promise<void>;\n pause: () => void;\n stop: () => void;\n seekTo: (time: number) => void;\n setCurrentTime: (time: number) => void;\n\n // Track controls\n setTrackMute: (trackIndex: number, muted: boolean) => void;\n setTrackSolo: (trackIndex: number, soloed: boolean) => void;\n setTrackVolume: (trackIndex: number, volume: number) => void;\n setTrackPan: (trackIndex: number, pan: number) => void;\n\n // Selection\n setSelection: (start: number, end: number) => void;\n setSelectedTrackId: (trackId: string | null) => void;\n\n // Time format\n setTimeFormat: (format: TimeFormat) => void;\n formatTime: (seconds: number) => string;\n\n // Zoom\n zoomIn: () => void;\n zoomOut: () => void;\n\n // Master volume\n setMasterVolume: (volume: number) => void;\n\n // Automatic scroll\n setAutomaticScroll: (enabled: boolean) => void;\n setScrollContainer: (element: HTMLDivElement | null) => void;\n scrollContainerRef: React.RefObject<HTMLDivElement | null>;\n\n // Annotation controls\n setContinuousPlay: (enabled: boolean) => void;\n setLinkEndpoints: (enabled: boolean) => void;\n setAnnotationsEditable: (enabled: boolean) => void;\n setAnnotations: (annotations: AnnotationData[]) => void;\n setActiveAnnotationId: (id: string | null) => void;\n\n // Loop controls\n setLoopEnabled: (enabled: boolean) => void;\n setLoopRegion: (start: number, end: number) => void;\n setLoopRegionFromSelection: () => void;\n clearLoopRegion: () => void;\n}\n\nexport interface PlaylistDataContextValue {\n duration: number;\n audioBuffers: AudioBuffer[];\n peaksDataArray: TrackClipPeaks[]; // Array of tracks, each containing array of clip peaks\n trackStates: TrackState[];\n tracks: ClipTrack[]; // Original tracks array with IDs\n sampleRate: number;\n waveHeight: number;\n timeScaleHeight: number;\n minimumPlaylistHeight: number;\n controls: { show: boolean; width: number };\n playoutRef: React.RefObject<TonePlayout | null>;\n samplesPerPixel: number;\n timeFormat: string;\n masterVolume: number;\n canZoomIn: boolean;\n canZoomOut: boolean;\n barWidth: number;\n barGap: number;\n /** Width in pixels of progress bars. Defaults to barWidth + barGap (fills gaps). */\n progressBarWidth: number;\n}\n\n// Create the 4 separate contexts\nconst PlaybackAnimationContext = createContext<PlaybackAnimationContextValue | null>(null);\nconst PlaylistStateContext = createContext<PlaylistStateContextValue | null>(null);\nconst PlaylistControlsContext = createContext<PlaylistControlsContextValue | null>(null);\nconst PlaylistDataContext = createContext<PlaylistDataContextValue | null>(null);\n\n// Keep the original context for backwards compatibility\nconst WaveformPlaylistContext = createContext<WaveformPlaylistContextValue | null>(null);\n\nexport interface WaveformPlaylistProviderProps {\n tracks: ClipTrack[]; // Updated to use clip-based model\n timescale?: boolean;\n mono?: boolean;\n waveHeight?: number;\n samplesPerPixel?: number;\n zoomLevels?: number[]; // Array of zoom levels in samples per pixel (lower = more zoomed in)\n automaticScroll?: boolean;\n theme?: Partial<WaveformPlaylistTheme>;\n controls?: {\n show: boolean;\n width: number;\n };\n annotationList?: {\n annotations?: any[];\n editable?: boolean;\n isContinuousPlay?: boolean;\n linkEndpoints?: boolean;\n controls?: any[];\n };\n effects?: EffectsFunction;\n onReady?: () => void;\n onAnnotationUpdate?: (annotations: AnnotationData[]) => void;\n /** Width in pixels of waveform bars. Default: 1 */\n barWidth?: number;\n /** Spacing in pixels between waveform bars. Default: 0 */\n barGap?: number;\n /** Width in pixels of progress bars. Default: barWidth + barGap (fills gaps). */\n progressBarWidth?: number;\n children: ReactNode;\n}\n\nexport const WaveformPlaylistProvider: React.FC<WaveformPlaylistProviderProps> = ({\n tracks,\n timescale = false,\n mono = false,\n waveHeight = 80,\n samplesPerPixel: initialSamplesPerPixel = 1024,\n zoomLevels,\n automaticScroll = false,\n theme: userTheme,\n controls = { show: false, width: 0 },\n annotationList,\n effects,\n onReady,\n onAnnotationUpdate: _onAnnotationUpdate,\n barWidth = 1,\n barGap = 0,\n progressBarWidth: progressBarWidthProp,\n children,\n}) => {\n // Default progressBarWidth to barWidth + barGap (fills gaps)\n const progressBarWidth = progressBarWidthProp ?? (barWidth + barGap);\n // State\n const [annotations, setAnnotations] = useState<AnnotationData[]>([]);\n const [activeAnnotationId, setActiveAnnotationIdState] = useState<string | null>(null);\n const [isPlaying, setIsPlaying] = useState(false);\n const [currentTime, setCurrentTime] = useState(0);\n const [duration, setDuration] = useState(0);\n const [audioBuffers, setAudioBuffers] = useState<AudioBuffer[]>([]);\n const [peaksDataArray, setPeaksDataArray] = useState<TrackClipPeaks[]>([]); // Updated for clip-based peaks\n const [trackStates, setTrackStates] = useState<TrackState[]>([]);\n const [selectionStart, setSelectionStart] = useState(0);\n const [selectionEnd, setSelectionEnd] = useState(0);\n const [selectedTrackId, setSelectedTrackId] = useState<string | null>(null);\n const [isAutomaticScroll, setIsAutomaticScroll] = useState(automaticScroll);\n const [continuousPlay, setContinuousPlayState] = useState(annotationList?.isContinuousPlay ?? false);\n const [linkEndpoints, setLinkEndpoints] = useState(annotationList?.linkEndpoints ?? true);\n const [annotationsEditable, setAnnotationsEditable] = useState(annotationList?.editable ?? false);\n const [isLoopEnabled, setIsLoopEnabledState] = useState(false);\n const [loopStart, setLoopStartState] = useState(0);\n const [loopEnd, setLoopEndState] = useState(0);\n\n // Refs\n const playoutRef = useRef<TonePlayout | null>(null);\n const playStartPositionRef = useRef<number>(0);\n const currentTimeRef = useRef<number>(0);\n const animationFrameRef = useRef<number | null>(null);\n const trackStatesRef = useRef<TrackState[]>(trackStates);\n const playbackStartTimeRef = useRef<number>(0); // context.currentTime when playback started\n const audioStartPositionRef = useRef<number>(0); // Audio position when playback started\n const playbackEndTimeRef = useRef<number | null>(null); // Audio position where playback should stop (for selections)\n const scrollContainerRef = useRef<HTMLDivElement | null>(null);\n const isAutomaticScrollRef = useRef<boolean>(false);\n const continuousPlayRef = useRef<boolean>(annotationList?.isContinuousPlay ?? false);\n const activeAnnotationIdRef = useRef<string | null>(null);\n const samplesPerPixelRef = useRef<number>(initialSamplesPerPixel);\n const isLoopEnabledRef = useRef<boolean>(false);\n const selectionStartRef = useRef<number>(0);\n const selectionEndRef = useRef<number>(0);\n const loopStartRef = useRef<number>(0);\n const loopEndRef = useRef<number>(0);\n\n // Custom hooks\n const { timeFormat, setTimeFormat, formatTime } = useTimeFormat();\n const zoom = useZoomControls({ initialSamplesPerPixel, zoomLevels });\n const samplesPerPixel = zoom.samplesPerPixel;\n const { masterVolume, setMasterVolume } = useMasterVolume({ playoutRef, initialVolume: 1.0 });\n\n // Custom setter for continuousPlay that updates BOTH state and ref synchronously\n // This ensures the ref is updated immediately, before the animation loop can read it\n const setContinuousPlay = useCallback((value: boolean) => {\n continuousPlayRef.current = value; // Update ref synchronously\n setContinuousPlayState(value); // Update state (triggers re-render)\n }, []);\n\n // Custom setter for activeAnnotationId that updates BOTH state and ref synchronously\n const setActiveAnnotationId = useCallback((value: string | null) => {\n activeAnnotationIdRef.current = value; // Update ref synchronously\n setActiveAnnotationIdState(value); // Update state (triggers re-render)\n }, []);\n\n // Custom setter for isLoopEnabled that updates BOTH state and ref synchronously\n const setLoopEnabled = useCallback((value: boolean) => {\n isLoopEnabledRef.current = value; // Update ref synchronously\n setIsLoopEnabledState(value); // Update state (triggers re-render)\n }, []);\n\n // Loop region setters - Audacity-style separate loop points\n const setLoopRegion = useCallback((start: number, end: number) => {\n loopStartRef.current = start;\n loopEndRef.current = end;\n setLoopStartState(start);\n setLoopEndState(end);\n }, []);\n\n const setLoopRegionFromSelection = useCallback(() => {\n const start = selectionStartRef.current;\n const end = selectionEndRef.current;\n if (start !== end && end > start) {\n setLoopRegion(start, end);\n }\n }, [setLoopRegion]);\n\n const clearLoopRegion = useCallback(() => {\n setLoopRegion(0, 0);\n }, [setLoopRegion]);\n\n // Keep refs in sync with state\n useEffect(() => {\n isAutomaticScrollRef.current = isAutomaticScroll;\n }, [isAutomaticScroll]);\n\n useEffect(() => {\n trackStatesRef.current = trackStates;\n }, [trackStates]);\n\n // Keep selection refs in sync for animation loop access\n useEffect(() => {\n selectionStartRef.current = selectionStart;\n selectionEndRef.current = selectionEnd;\n }, [selectionStart, selectionEnd]);\n\n // Adjust scroll position proportionally when zoom changes\n useEffect(() => {\n if (!scrollContainerRef.current || !audioBuffers.length) return;\n\n const container = scrollContainerRef.current;\n const oldSamplesPerPixel = samplesPerPixelRef.current;\n const newSamplesPerPixel = samplesPerPixel;\n\n if (oldSamplesPerPixel === newSamplesPerPixel) return;\n\n // Calculate the current center time in the viewport\n const controlWidth = controls.show ? controls.width : 0;\n const containerWidth = container.clientWidth;\n const currentScrollLeft = container.scrollLeft;\n const centerPixel = currentScrollLeft + containerWidth / 2 - controlWidth;\n const sr = audioBuffers[0].sampleRate;\n const centerTime = (centerPixel * oldSamplesPerPixel) / sr;\n\n // Calculate new scroll position to keep the same center time\n const newCenterPixel = (centerTime * sr) / newSamplesPerPixel;\n const newScrollLeft = Math.max(0, newCenterPixel + controlWidth - containerWidth / 2);\n\n container.scrollLeft = newScrollLeft;\n samplesPerPixelRef.current = newSamplesPerPixel;\n }, [samplesPerPixel, audioBuffers, controls]);\n\n // Track pending playback resume after tracks change\n const pendingResumeRef = useRef<{ position: number } | null>(null);\n\n // Load audio from clips (only when tracks change)\n useEffect(() => {\n if (tracks.length === 0) {\n // Clear state when all tracks are removed\n setAudioBuffers([]);\n setDuration(0);\n setTrackStates([]);\n setPeaksDataArray([]);\n if (playoutRef.current) {\n playoutRef.current.dispose();\n playoutRef.current = null;\n }\n return;\n }\n\n // Capture playback state before rebuilding playout\n const wasPlaying = isPlaying;\n const resumePosition = currentTimeRef.current;\n\n // Stop current playback and animation before disposing\n if (playoutRef.current && wasPlaying) {\n playoutRef.current.stop();\n if (animationFrameRef.current) {\n cancelAnimationFrame(animationFrameRef.current);\n animationFrameRef.current = null;\n }\n // Mark that we need to resume playback after playout is rebuilt\n pendingResumeRef.current = { position: resumePosition };\n }\n\n const loadAudio = async () => {\n try {\n // Extract all audio buffers from clips (only those that have audioBuffer)\n // For now, collect the first clip's buffer from each track\n const buffers: AudioBuffer[] = [];\n\n tracks.forEach((track) => {\n if (track.clips.length > 0 && track.clips[0].audioBuffer) {\n // Use first clip's buffer for now (full multi-clip support comes in next phase)\n buffers.push(track.clips[0].audioBuffer);\n }\n });\n\n // Calculate total timeline duration from all clips across all tracks\n // Use clip.sampleRate which is always defined (works for peaks-only clips too)\n let maxDuration = 0;\n tracks.forEach((track) => {\n track.clips.forEach((clip) => {\n const sampleRate = clip.sampleRate;\n const clipEndSample = clip.startSample + clip.durationSamples;\n const clipEnd = clipEndSample / sampleRate;\n maxDuration = Math.max(maxDuration, clipEnd);\n });\n });\n\n setAudioBuffers(buffers);\n setDuration(maxDuration);\n\n // Initialize or update track states, preserving existing UI state (mute/solo/volume/pan)\n // Only initialize from ClipTrack props when trackStates is empty or track count changes\n setTrackStates(prevStates => {\n if (prevStates.length === tracks.length) {\n // Same number of tracks - preserve existing UI state, just update names\n return prevStates.map((state, i) => ({\n ...state,\n name: tracks[i].name,\n }));\n }\n // Track count changed - reinitialize from ClipTrack properties\n return tracks.map((track) => ({\n name: track.name,\n muted: track.muted,\n soloed: track.soloed,\n volume: track.volume,\n pan: track.pan,\n }));\n });\n\n // Dispose old playout before creating new one\n if (playoutRef.current) {\n playoutRef.current.dispose();\n }\n\n // Create playout with clips\n const playout = new TonePlayout({\n effects,\n });\n\n // For each track, create a ToneTrack with all clips\n // Use trackStatesRef for current UI state (mute/solo/volume/pan) instead of track props\n const currentTrackStates = trackStatesRef.current;\n tracks.forEach((track, index) => {\n // Filter to only clips with audioBuffer (peaks-only clips can't be played)\n const playableClips = track.clips.filter(clip => clip.audioBuffer);\n\n if (playableClips.length > 0) {\n // Calculate track start and end times from clips (converting samples to seconds)\n // Use clip.sampleRate which is always defined\n const sampleRate = playableClips[0].sampleRate;\n const startTime = Math.min(...playableClips.map(c => c.startSample / sampleRate));\n const endTime = Math.max(...playableClips.map(c => (c.startSample + c.durationSamples) / sampleRate));\n\n // Use current UI state if available, otherwise fall back to track props\n const trackState = currentTrackStates[index];\n const trackObj: Track = {\n id: `track-${index}`, // Use consistent index-based ID for track controls\n name: track.name,\n gain: trackState?.volume ?? track.volume,\n muted: trackState?.muted ?? track.muted,\n soloed: trackState?.soloed ?? track.soloed,\n stereoPan: trackState?.pan ?? track.pan,\n startTime,\n endTime,\n };\n\n // Convert ClipTrack clips to ToneTrack ClipInfo format\n // Note: ClipInfo.startTime is relative to track start, not absolute timeline\n const clipInfos = playableClips.map(clip => {\n const clipSampleRate = clip.sampleRate;\n return {\n buffer: clip.audioBuffer!, // We filtered for audioBuffer above\n startTime: (clip.startSample / clipSampleRate) - startTime, // Make relative to track start\n duration: clip.durationSamples / clipSampleRate,\n offset: clip.offsetSamples / clipSampleRate,\n fadeIn: clip.fadeIn,\n fadeOut: clip.fadeOut,\n gain: clip.gain,\n };\n });\n\n playout.addTrack({\n clips: clipInfos,\n track: trackObj,\n effects: track.effects, // Pass track effects\n });\n }\n });\n\n // Apply solo muting after all tracks are added\n playout.applyInitialSoloState();\n\n playoutRef.current = playout;\n onReady?.();\n } catch (error) {\n console.error('Error loading audio:', error);\n }\n };\n\n loadAudio();\n\n return () => {\n if (animationFrameRef.current) {\n cancelAnimationFrame(animationFrameRef.current);\n }\n if (playoutRef.current) {\n playoutRef.current.dispose();\n }\n };\n }, [tracks, onReady, isPlaying]);\n\n // Regenerate peaks when zoom or mono changes (without reloading audio)\n useEffect(() => {\n if (tracks.length === 0) return;\n\n const bits = 16;\n\n // Generate peaks for each clip in each track\n const allTrackPeaks: TrackClipPeaks[] = tracks.map((track) => {\n const clipPeaks: ClipPeaks[] = track.clips.map((clip) => {\n // Check if clip has pre-computed waveform data\n if (clip.waveformData) {\n // Use waveform-data.js to resample and slice as needed\n // Pass sample values directly for accuracy\n const extractedPeaks = extractPeaksFromWaveformData(\n clip.waveformData as any, // Cast to WaveformData type\n samplesPerPixel,\n 0, // channel index\n clip.offsetSamples,\n clip.durationSamples\n );\n\n return {\n clipId: clip.id,\n trackName: track.name,\n peaks: {\n length: extractedPeaks.length,\n data: [extractedPeaks.data], // Wrap in array for channel compatibility\n bits: extractedPeaks.bits,\n },\n startSample: clip.startSample,\n durationSamples: clip.durationSamples,\n fadeIn: clip.fadeIn,\n fadeOut: clip.fadeOut,\n };\n }\n\n // Fall back to generating peaks from audioBuffer\n // If no audioBuffer either, return empty peaks (clip has no visual data)\n if (!clip.audioBuffer) {\n console.warn(`Clip \"${clip.name || clip.id}\" has neither waveformData nor audioBuffer - rendering empty`);\n return {\n clipId: clip.id,\n trackName: track.name,\n peaks: {\n length: 0,\n data: [],\n bits: bits,\n },\n startSample: clip.startSample,\n durationSamples: clip.durationSamples,\n fadeIn: clip.fadeIn,\n fadeOut: clip.fadeOut,\n };\n }\n\n const peaks = generatePeaks(\n clip.audioBuffer,\n samplesPerPixel,\n mono,\n bits,\n clip.offsetSamples,\n clip.durationSamples\n );\n\n return {\n clipId: clip.id,\n trackName: track.name,\n peaks,\n startSample: clip.startSample,\n durationSamples: clip.durationSamples,\n fadeIn: clip.fadeIn,\n fadeOut: clip.fadeOut,\n };\n });\n\n return clipPeaks;\n });\n\n setPeaksDataArray(allTrackPeaks);\n }, [tracks, samplesPerPixel, mono]);\n\n // Load annotations from annotationList prop\n useEffect(() => {\n if (annotationList?.annotations) {\n // Parse Aeneas format annotations to AnnotationData format\n const parsedAnnotations = annotationList.annotations.map((ann: any) => {\n // If it's already in the correct format, use it\n if (typeof ann.start === 'number') {\n return ann;\n }\n // Otherwise parse from Aeneas format\n return parseAeneas(ann);\n });\n setAnnotations(parsedAnnotations);\n }\n }, [annotationList]);\n\n // Animation loop\n const startAnimationLoop = useCallback(() => {\n // Cancel any existing animation frame before starting a new one\n if (animationFrameRef.current) {\n cancelAnimationFrame(animationFrameRef.current);\n animationFrameRef.current = null;\n }\n\n const updateTime = () => {\n // Calculate current position based on context.currentTime timing\n const elapsed = getContext().currentTime - playbackStartTimeRef.current;\n const time = audioStartPositionRef.current + elapsed;\n currentTimeRef.current = time;\n\n // Update state on every frame - context splitting isolates this from other components\n setCurrentTime(time);\n\n // Handle annotation playback based on continuous play mode\n if (annotations.length > 0) {\n const currentAnnotation = annotations.find(\n (ann) => time >= ann.start && time < ann.end\n );\n\n if (continuousPlayRef.current) {\n // Continuous play ON: update active annotation and stop after last annotation\n if (currentAnnotation && currentAnnotation.id !== activeAnnotationIdRef.current) {\n setActiveAnnotationId(currentAnnotation.id);\n } else if (!currentAnnotation && activeAnnotationIdRef.current !== null) {\n // We're no longer in any annotation - check if we're past the last one\n const lastAnnotation = annotations[annotations.length - 1];\n if (time >= lastAnnotation.end) {\n // Stop playback - we've finished all annotations\n if (playoutRef.current) {\n playoutRef.current.stop();\n }\n setIsPlaying(false);\n currentTimeRef.current = playStartPositionRef.current;\n setCurrentTime(playStartPositionRef.current);\n setActiveAnnotationId(null);\n return;\n }\n }\n } else {\n // Continuous play OFF: stop at end of current annotation\n if (activeAnnotationIdRef.current) {\n const activeAnnotation = annotations.find(ann => ann.id === activeAnnotationIdRef.current);\n if (activeAnnotation && time >= activeAnnotation.end) {\n // Stop playback at end of current annotation\n if (playoutRef.current) {\n playoutRef.current.stop();\n }\n setIsPlaying(false);\n currentTimeRef.current = playStartPositionRef.current;\n setCurrentTime(playStartPositionRef.current);\n return;\n }\n } else {\n // If no active annotation ID is set, use the current annotation\n if (currentAnnotation) {\n setActiveAnnotationId(currentAnnotation.id);\n }\n }\n }\n }\n\n // Handle automatic scroll - continuously center the playhead\n if (isAutomaticScrollRef.current && scrollContainerRef.current && audioBuffers.length > 0) {\n const container = scrollContainerRef.current;\n const sr = audioBuffers[0].sampleRate;\n const pixelPosition = (time * sr) / samplesPerPixelRef.current;\n const containerWidth = container.clientWidth;\n\n // Calculate visual position of playhead (includes controls offset)\n const controlWidth = controls.show ? controls.width : 0;\n const visualPosition = pixelPosition + controlWidth;\n\n // Continuously scroll to keep playhead centered\n const targetScrollLeft = Math.max(0, visualPosition - containerWidth / 2);\n container.scrollLeft = targetScrollLeft;\n }\n\n // Check if we've reached the playback end time (for selection playback)\n if (playbackEndTimeRef.current !== null && time >= playbackEndTimeRef.current) {\n // Stop playback at selection end (selection playback is separate from looping)\n if (playoutRef.current) {\n playoutRef.current.stop();\n }\n setIsPlaying(false);\n currentTimeRef.current = playbackEndTimeRef.current;\n setCurrentTime(playbackEndTimeRef.current);\n playbackEndTimeRef.current = null; // Clear the end time\n return;\n }\n\n // Audacity-style loop region: loop when cursor enters and reaches end of loop region\n const hasValidLoopRegion = loopStartRef.current !== loopEndRef.current &&\n loopEndRef.current > loopStartRef.current;\n\n if (isLoopEnabledRef.current && hasValidLoopRegion) {\n // Check if we've reached or passed the loop end point\n if (time >= loopEndRef.current) {\n // Loop: restart from loop start\n playoutRef.current?.stop();\n\n const context = getContext();\n const timeNow = context.currentTime;\n playbackStartTimeRef.current = timeNow;\n audioStartPositionRef.current = loopStartRef.current;\n currentTimeRef.current = loopStartRef.current;\n\n // Restart playback from loop start (no duration limit - will loop again when reaching loop end)\n playoutRef.current?.play(timeNow, loopStartRef.current);\n\n // Continue animation loop\n animationFrameRef.current = requestAnimationFrame(updateTime);\n return;\n }\n }\n\n if (time >= duration) {\n // Stop playback - inline to avoid circular dependency\n if (playoutRef.current) {\n playoutRef.current.stop();\n }\n setIsPlaying(false);\n currentTimeRef.current = playStartPositionRef.current;\n setCurrentTime(playStartPositionRef.current);\n setActiveAnnotationId(null);\n return;\n }\n animationFrameRef.current = requestAnimationFrame(updateTime);\n };\n animationFrameRef.current = requestAnimationFrame(updateTime);\n }, [duration, audioBuffers, samplesPerPixel, annotations, continuousPlay]);\n\n const stopAnimationLoop = useCallback(() => {\n if (animationFrameRef.current) {\n cancelAnimationFrame(animationFrameRef.current);\n animationFrameRef.current = null;\n }\n }, []);\n\n // Restart animation loop and reschedule playout when continuousPlay changes during playback\n // This ensures the loop always has the current continuousPlay value\n // and removes duration limits when switching to continuous play\n useEffect(() => {\n const reschedulePlayback = async () => {\n if (isPlaying && animationFrameRef.current && playoutRef.current) {\n // When toggling continuous play ON, reschedule playout without duration limit\n // so audio continues past the current annotation boundary\n if (continuousPlay) {\n const currentPos = currentTimeRef.current;\n\n // Stop current playout (which may have duration limit + pause callback)\n playoutRef.current.stop();\n stopAnimationLoop();\n\n // Initialize and restart from current position without duration limit\n await playoutRef.current.init();\n\n // Clear any existing playback complete callback\n playoutRef.current.setOnPlaybackComplete(() => {});\n\n const context = getContext();\n const timeNow = context.currentTime;\n playbackStartTimeRef.current = timeNow;\n audioStartPositionRef.current = currentPos;\n\n // Play without duration - will play to end of track\n playoutRef.current.play(timeNow, currentPos);\n startAnimationLoop();\n } else {\n // Just restart animation loop for continuous play OFF\n stopAnimationLoop();\n startAnimationLoop();\n }\n }\n };\n\n reschedulePlayback();\n }, [continuousPlay, isPlaying, startAnimationLoop, stopAnimationLoop]);\n\n // Resume playback after tracks change (e.g., after splitting a clip during playback)\n useEffect(() => {\n const resumePlayback = async () => {\n if (pendingResumeRef.current && playoutRef.current) {\n const { position } = pendingResumeRef.current;\n pendingResumeRef.current = null;\n\n await playoutRef.current.init();\n playoutRef.current.setOnPlaybackComplete(() => {});\n\n const context = getContext();\n const timeNow = context.currentTime;\n playbackStartTimeRef.current = timeNow;\n audioStartPositionRef.current = position;\n\n playoutRef.current.play(timeNow, position);\n setIsPlaying(true);\n startAnimationLoop();\n }\n };\n\n resumePlayback();\n }, [tracks, startAnimationLoop]);\n\n // Playback controls\n const play = useCallback(async (startTime?: number, playDuration?: number) => {\n if (!playoutRef.current || audioBuffers.length === 0) return;\n\n await playoutRef.current.init();\n\n // Resume Tone.js context if needed (required for Safari and user interaction)\n await toneStart();\n\n const actualStartTime = startTime ?? currentTimeRef.current;\n playStartPositionRef.current = actualStartTime;\n\n // Update currentTimeRef to match the actual start position\n // This ensures the animation loop starts from the correct position\n currentTimeRef.current = actualStartTime;\n\n // Clear any existing playback complete callback before stopping\n // Otherwise stopping will trigger the old callback and interfere with new playback\n playoutRef.current.setOnPlaybackComplete(() => {});\n\n // Stop any existing playback and animation loop before starting\n playoutRef.current.stop();\n stopAnimationLoop();\n\n // Record timing for accurate position tracking using Tone.js context\n const context = getContext();\n // Tone.js context wraps Web Audio - need to use .currentTime from wrapped context\n const startTimeNow = context.currentTime;\n playbackStartTimeRef.current = startTimeNow;\n audioStartPositionRef.current = actualStartTime;\n\n // Set playback end time if playing with duration (e.g., selection playback)\n playbackEndTimeRef.current = playDuration !== undefined ? actualStartTime + playDuration : null;\n\n // Don't set up playback complete callback for annotations\n // The animation loop handles stopping at annotation boundaries\n // This avoids callback timing issues when switching between annotations\n\n playoutRef.current.play(startTimeNow, actualStartTime, playDuration);\n setIsPlaying(true);\n startAnimationLoop();\n }, [audioBuffers.length, startAnimationLoop, stopAnimationLoop]);\n\n const pause = useCallback(() => {\n if (!playoutRef.current) return;\n\n // Calculate exact pause position using context.currentTime timing\n const elapsed = getContext().currentTime - playbackStartTimeRef.current;\n const pauseTime = audioStartPositionRef.current + elapsed;\n\n playoutRef.current.pause();\n setIsPlaying(false);\n stopAnimationLoop();\n\n // Update to the calculated pause position\n currentTimeRef.current = pauseTime;\n setCurrentTime(pauseTime);\n }, [stopAnimationLoop]);\n\n const stop = useCallback(() => {\n if (!playoutRef.current) return;\n\n playoutRef.current.stop();\n setIsPlaying(false);\n stopAnimationLoop();\n\n currentTimeRef.current = playStartPositionRef.current;\n setCurrentTime(playStartPositionRef.current);\n setActiveAnnotationId(null);\n }, [stopAnimationLoop]);\n\n // Seek to a specific time - works whether playing or stopped\n const seekTo = useCallback((time: number) => {\n // Clamp time to valid range\n const clampedTime = Math.max(0, Math.min(time, duration));\n\n // Update the current time state\n currentTimeRef.current = clampedTime;\n setCurrentTime(clampedTime);\n\n // If currently playing, stop and restart at the new position\n if (isPlaying && playoutRef.current) {\n playoutRef.current.stop();\n stopAnimationLoop();\n // Use play() which handles all the timing setup\n play(clampedTime);\n }\n }, [duration, isPlaying, play, stopAnimationLoop]);\n\n // Track controls\n const setTrackMute = useCallback((trackIndex: number, muted: boolean) => {\n const newStates = [...trackStates];\n newStates[trackIndex] = { ...newStates[trackIndex], muted };\n setTrackStates(newStates);\n\n if (playoutRef.current) {\n const trackId = `track-${trackIndex}`;\n playoutRef.current.setMute(trackId, muted);\n }\n }, [trackStates]);\n\n const setTrackSolo = useCallback((trackIndex: number, soloed: boolean) => {\n const newStates = [...trackStates];\n newStates[trackIndex] = { ...newStates[trackIndex], soloed };\n setTrackStates(newStates);\n\n if (playoutRef.current) {\n const trackId = `track-${trackIndex}`;\n playoutRef.current.setSolo(trackId, soloed);\n }\n }, [trackStates]);\n\n const setTrackVolume = useCallback((trackIndex: number, volume: number) => {\n const newStates = [...trackStates];\n newStates[trackIndex] = { ...newStates[trackIndex], volume };\n setTrackStates(newStates);\n\n if (playoutRef.current) {\n const trackId = `track-${trackIndex}`;\n const track = playoutRef.current.getTrack(trackId);\n if (track) {\n track.setVolume(volume);\n }\n }\n }, [trackStates]);\n\n const setTrackPan = useCallback((trackIndex: number, pan: number) => {\n const newStates = [...trackStates];\n newStates[trackIndex] = { ...newStates[trackIndex], pan };\n setTrackStates(newStates);\n\n if (playoutRef.current) {\n const trackId = `track-${trackIndex}`;\n const track = playoutRef.current.getTrack(trackId);\n if (track) {\n track.setPan(pan);\n }\n }\n }, [trackStates]);\n\n // Selection\n const setSelection = useCallback((start: number, end: number) => {\n setSelectionStart(start);\n setSelectionEnd(end);\n currentTimeRef.current = start;\n setCurrentTime(start);\n\n if (isPlaying && playoutRef.current) {\n playoutRef.current.stop();\n playoutRef.current.play(getContext().currentTime, start);\n }\n }, [isPlaying]);\n\n // Memoize setScrollContainer callback\n const setScrollContainer = useCallback((element: HTMLDivElement | null) => {\n scrollContainerRef.current = element;\n }, []);\n\n const sampleRate = audioBuffers[0]?.sampleRate || 44100;\n const timeScaleHeight = timescale ? 30 : 0;\n const minimumPlaylistHeight = (tracks.length * waveHeight) + timeScaleHeight;\n\n // Split context values for performance optimization\n // High-frequency updates (currentTime) isolated from other state\n\n const animationValue: PlaybackAnimationContextValue = {\n isPlaying,\n currentTime,\n currentTimeRef,\n playbackStartTimeRef,\n audioStartPositionRef,\n };\n\n const stateValue: PlaylistStateContextValue = {\n continuousPlay,\n linkEndpoints,\n annotationsEditable,\n isAutomaticScroll,\n isLoopEnabled,\n annotations,\n activeAnnotationId,\n selectionStart,\n selectionEnd,\n selectedTrackId,\n loopStart,\n loopEnd,\n };\n\n const controlsValue: PlaylistControlsContextValue = {\n // Playback controls\n play,\n pause,\n stop,\n seekTo,\n setCurrentTime: (time: number) => {\n currentTimeRef.current = time;\n setCurrentTime(time);\n },\n\n // Track controls\n setTrackMute,\n setTrackSolo,\n setTrackVolume,\n setTrackPan,\n\n // Selection\n setSelection,\n setSelectedTrackId,\n\n // Time format\n setTimeFormat,\n formatTime,\n\n // Zoom\n zoomIn: zoom.zoomIn,\n zoomOut: zoom.zoomOut,\n\n // Master volume\n setMasterVolume,\n\n // Automatic scroll\n setAutomaticScroll: (enabled: boolean) => {\n setIsAutomaticScroll(enabled);\n },\n setScrollContainer,\n scrollContainerRef,\n\n // Annotation controls\n setContinuousPlay,\n setLinkEndpoints,\n setAnnotationsEditable,\n setAnnotations,\n setActiveAnnotationId,\n\n // Loop controls\n setLoopEnabled,\n setLoopRegion,\n setLoopRegionFromSelection,\n clearLoopRegion,\n };\n\n const dataValue: PlaylistDataContextValue = {\n duration,\n audioBuffers,\n peaksDataArray,\n trackStates,\n tracks,\n sampleRate,\n waveHeight,\n timeScaleHeight,\n minimumPlaylistHeight,\n controls,\n playoutRef,\n samplesPerPixel,\n timeFormat,\n masterVolume,\n canZoomIn: zoom.canZoomIn,\n canZoomOut: zoom.canZoomOut,\n barWidth,\n barGap,\n progressBarWidth,\n };\n\n // Combined value for backwards compatibility\n const value: WaveformPlaylistContextValue = {\n ...animationValue,\n ...stateValue,\n ...controlsValue,\n ...dataValue,\n };\n\n // Merge user theme with default theme\n const mergedTheme = { ...defaultTheme, ...userTheme };\n\n return (\n <ThemeProvider theme={mergedTheme}>\n <PlaybackAnimationContext.Provider value={animationValue}>\n <PlaylistStateContext.Provider value={stateValue}>\n <PlaylistControlsContext.Provider value={controlsValue}>\n <PlaylistDataContext.Provider value={dataValue}>\n <WaveformPlaylistContext.Provider value={value}>\n {children}\n </WaveformPlaylistContext.Provider>\n </PlaylistDataContext.Provider>\n </PlaylistControlsContext.Provider>\n </PlaylistStateContext.Provider>\n </PlaybackAnimationContext.Provider>\n </ThemeProvider>\n );\n};\n\n// Individual hooks for each context - use these for optimal performance\n// Components only re-render when their specific context data changes\n\nexport const usePlaybackAnimation = () => {\n const context = useContext(PlaybackAnimationContext);\n if (!context) {\n throw new Error('usePlaybackAnimation must be used within WaveformPlaylistProvider');\n }\n return context;\n};\n\nexport const usePlaylistState = () => {\n const context = useContext(PlaylistStateContext);\n if (!context) {\n throw new Error('usePlaylistState must be used within WaveformPlaylistProvider');\n }\n return context;\n};\n\nexport const usePlaylistControls = () => {\n const context = useContext(PlaylistControlsContext);\n if (!context) {\n throw new Error('usePlaylistControls must be used within WaveformPlaylistProvider');\n }\n return context;\n};\n\nexport const usePlaylistData = () => {\n const context = useContext(PlaylistDataContext);\n if (!context) {\n throw new Error('usePlaylistData must be used within WaveformPlaylistProvider');\n }\n return context;\n};\n\n// Main hook that combines all contexts - use this for backwards compatibility\n// or when you need access to multiple contexts\nexport const useWaveformPlaylist = () => {\n const context = useContext(WaveformPlaylistContext);\n if (!context) {\n throw new Error('useWaveformPlaylist must be used within WaveformPlaylistProvider');\n }\n return context;\n};\n","// src/MediaElementTrack.ts\nvar MediaElementTrack = class {\n constructor(options) {\n this._playbackRate = 1;\n this.handleEnded = () => {\n if (this.onStopCallback) {\n this.onStopCallback();\n }\n };\n this.handleTimeUpdate = () => {\n if (this.onTimeUpdateCallback) {\n this.onTimeUpdateCallback(this.audioElement.currentTime);\n }\n };\n this._peaks = options.peaks;\n this._id = options.id ?? `track-${Date.now()}`;\n this._name = options.name ?? \"Track\";\n this._playbackRate = options.playbackRate ?? 1;\n if (typeof options.source === \"string\") {\n this.audioElement = new Audio(options.source);\n this.ownsElement = true;\n } else {\n this.audioElement = options.source;\n this.ownsElement = false;\n }\n this.audioElement.preload = \"auto\";\n this.audioElement.volume = options.volume ?? 1;\n this.audioElement.playbackRate = this._playbackRate;\n if (\"preservesPitch\" in this.audioElement) {\n this.audioElement.preservesPitch = true;\n } else if (\"mozPreservesPitch\" in this.audioElement) {\n this.audioElement.mozPreservesPitch = true;\n } else if (\"webkitPreservesPitch\" in this.audioElement) {\n this.audioElement.webkitPreservesPitch = true;\n }\n this.audioElement.addEventListener(\"ended\", this.handleEnded);\n this.audioElement.addEventListener(\"timeupdate\", this.handleTimeUpdate);\n }\n /**\n * Start playback from a specific time\n */\n play(offset = 0) {\n this.audioElement.currentTime = offset;\n this.audioElement.play().catch((err) => {\n console.warn(\"MediaElementTrack: play() failed:\", err);\n });\n }\n /**\n * Pause playback\n */\n pause() {\n this.audioElement.pause();\n }\n /**\n * Stop playback and reset to beginning\n */\n stop() {\n this.audioElement.pause();\n this.audioElement.currentTime = 0;\n }\n /**\n * Seek to a specific time\n */\n seekTo(time) {\n this.audioElement.currentTime = Math.max(0, Math.min(time, this.duration));\n }\n /**\n * Set volume (0.0 to 1.0)\n */\n setVolume(volume) {\n this.audioElement.volume = Math.max(0, Math.min(1, volume));\n }\n /**\n * Set playback rate (0.5 to 2.0, pitch preserved)\n */\n setPlaybackRate(rate) {\n const clampedRate = Math.max(0.5, Math.min(2, rate));\n this._playbackRate = clampedRate;\n this.audioElement.playbackRate = clampedRate;\n }\n /**\n * Set muted state\n */\n setMuted(muted) {\n this.audioElement.muted = muted;\n }\n /**\n * Set callback for when playback ends\n */\n setOnStopCallback(callback) {\n this.onStopCallback = callback;\n }\n /**\n * Set callback for time updates\n */\n setOnTimeUpdateCallback(callback) {\n this.onTimeUpdateCallback = callback;\n }\n /**\n * Clean up resources\n */\n dispose() {\n this.audioElement.removeEventListener(\"ended\", this.handleEnded);\n this.audioElement.removeEventListener(\"timeupdate\", this.handleTimeUpdate);\n this.audioElement.pause();\n if (this.ownsElement) {\n this.audioElement.src = \"\";\n this.audioElement.load();\n }\n }\n // Getters\n get id() {\n return this._id;\n }\n get name() {\n return this._name;\n }\n get peaks() {\n return this._peaks;\n }\n get currentTime() {\n return this.audioElement.currentTime;\n }\n get duration() {\n return this.audioElement.duration || this._peaks.duration;\n }\n get isPlaying() {\n return !this.audioElement.paused && !this.audioElement.ended;\n }\n get volume() {\n return this.audioElement.volume;\n }\n get playbackRate() {\n return this._playbackRate;\n }\n get muted() {\n return this.audioElement.muted;\n }\n /**\n * Get the underlying audio element (for advanced use cases)\n */\n get element() {\n return this.audioElement;\n }\n};\n\n// src/MediaElementPlayout.ts\nvar MediaElementPlayout = class {\n constructor(options = {}) {\n this.track = null;\n this._isPlaying = false;\n this._masterVolume = options.masterVolume ?? 1;\n this._playbackRate = options.playbackRate ?? 1;\n }\n /**\n * Initialize the playout engine.\n * For MediaElementPlayout this is a no-op (no AudioContext to start).\n */\n async init() {\n }\n /**\n * Add a track to the playout.\n * Note: Only one track is supported. Adding a second track will dispose the first.\n */\n addTrack(options) {\n if (this.track) {\n console.warn(\n \"MediaElementPlayout: Only one track is supported. Disposing previous track. For multi-track, use TonePlayout.\"\n );\n this.track.dispose();\n }\n this.track = new MediaElementTrack({\n ...options,\n volume: this._masterVolume * (options.volume ?? 1),\n playbackRate: this._playbackRate\n });\n this.track.setOnStopCallback(() => {\n this._isPlaying = false;\n if (this.onPlaybackCompleteCallback) {\n this.onPlaybackCompleteCallback();\n }\n });\n return this.track;\n }\n /**\n * Remove a track by ID.\n */\n removeTrack(trackId) {\n if (this.track && this.track.id === trackId) {\n this.track.dispose();\n this.track = null;\n }\n }\n /**\n * Get a track by ID.\n */\n getTrack(trackId) {\n if (this.track && this.track.id === trackId) {\n return this.track;\n }\n return void 0;\n }\n /**\n * Start playback.\n * @param _when - Ignored (HTMLAudioElement doesn't support scheduled start)\n * @param offset - Start position in seconds\n * @param duration - Duration to play in seconds (optional)\n */\n play(_when, offset, duration) {\n if (!this.track) {\n console.warn(\"MediaElementPlayout: No track to play\");\n return;\n }\n const startPosition = offset ?? 0;\n this._isPlaying = true;\n this.track.play(startPosition);\n if (duration !== void 0) {\n const adjustedDuration = duration / this._playbackRate;\n setTimeout(() => {\n if (this._isPlaying) {\n this.pause();\n if (this.onPlaybackCompleteCallback) {\n this.onPlaybackCompleteCallback();\n }\n }\n }, adjustedDuration * 1e3);\n }\n }\n /**\n * Pause playback.\n */\n pause() {\n if (this.track) {\n this.track.pause();\n }\n this._isPlaying = false;\n }\n /**\n * Stop playback and reset to start.\n */\n stop() {\n if (this.track) {\n this.track.stop();\n }\n this._isPlaying = false;\n }\n /**\n * Seek to a specific time.\n */\n seekTo(time) {\n if (this.track) {\n this.track.seekTo(time);\n }\n }\n /**\n * Get current playback time.\n */\n getCurrentTime() {\n if (this.track) {\n return this.track.currentTime;\n }\n return 0;\n }\n /**\n * Set master volume.\n */\n setMasterVolume(volume) {\n this._masterVolume = Math.max(0, Math.min(1, volume));\n if (this.track) {\n this.track.setVolume(this._masterVolume);\n }\n }\n /**\n * Set playback rate (0.5 to 2.0, pitch preserved).\n */\n setPlaybackRate(rate) {\n this._playbackRate = Math.max(0.5, Math.min(2, rate));\n if (this.track) {\n this.track.setPlaybackRate(this._playbackRate);\n }\n }\n /**\n * Set mute state for a track.\n */\n setMute(trackId, muted) {\n const track = this.getTrack(trackId);\n if (track) {\n track.setMuted(muted);\n }\n }\n /**\n * Set solo state for a track.\n * Note: With single track, solo is effectively the same as unmute.\n */\n setSolo(_trackId, _soloed) {\n console.warn(\"MediaElementPlayout: Solo is not applicable for single-track playback\");\n }\n /**\n * Set callback for when playback completes.\n */\n setOnPlaybackComplete(callback) {\n this.onPlaybackCompleteCallback = callback;\n }\n /**\n * Clean up resources.\n */\n dispose() {\n if (this.track) {\n this.track.dispose();\n this.track = null;\n }\n }\n // Getters\n get isPlaying() {\n return this._isPlaying;\n }\n get masterVolume() {\n return this._masterVolume;\n }\n get playbackRate() {\n return this._playbackRate;\n }\n get duration() {\n return this.track?.duration ?? 0;\n }\n get sampleRate() {\n return this.track?.peaks.sample_rate ?? 44100;\n }\n};\n\n// src/types.ts\nfunction supportsPlaybackRate(engine) {\n return \"setPlaybackRate\" in engine && typeof engine.setPlaybackRate === \"function\";\n}\nexport {\n MediaElementPlayout,\n MediaElementTrack,\n supportsPlaybackRate\n};\n//# sourceMappingURL=index.mjs.map","import React, {\n createContext,\n useContext,\n useState,\n useEffect,\n useRef,\n useCallback,\n useMemo,\n ReactNode,\n} from 'react';\nimport { ThemeProvider } from 'styled-components';\nimport {\n MediaElementPlayout,\n type MediaElementTrackOptions,\n} from '@waveform-playlist/media-element-playout';\nimport { type WaveformDataObject } from '@waveform-playlist/core';\nimport {\n type WaveformPlaylistTheme,\n defaultTheme,\n} from '@waveform-playlist/ui-components';\nimport { parseAeneas, type AnnotationData } from '@waveform-playlist/annotations';\nimport { extractPeaksFromWaveformData } from './waveformDataLoader';\nimport type { PeakData } from '@waveform-playlist/webaudio-peaks';\nimport type { ClipPeaks, TrackClipPeaks } from './WaveformPlaylistContext';\n\n// Configuration for a single media element track\nexport interface MediaElementTrackConfig {\n /** Audio source URL or Blob URL */\n source: string;\n /** Pre-computed waveform data (required for visualization) */\n waveformData: WaveformDataObject;\n /** Track name for display */\n name?: string;\n}\n\n// Context values for animation (high-frequency updates)\nexport interface MediaElementAnimationContextValue {\n isPlaying: boolean;\n currentTime: number;\n currentTimeRef: React.RefObject<number>;\n}\n\n// Context values for playlist state\nexport interface MediaElementStateContextValue {\n continuousPlay: boolean;\n annotations: AnnotationData[];\n activeAnnotationId: string | null;\n playbackRate: number;\n}\n\n// Context values for controls\nexport interface MediaElementControlsContextValue {\n play: (startTime?: number) => void;\n pause: () => void;\n stop: () => void;\n seekTo: (time: number) => void;\n setPlaybackRate: (rate: number) => void;\n setContinuousPlay: (enabled: boolean) => void;\n setAnnotations: (annotations: AnnotationData[]) => void;\n setActiveAnnotationId: (id: string | null) => void;\n}\n\n// Context values for playlist data\nexport interface MediaElementDataContextValue {\n duration: number;\n peaksDataArray: TrackClipPeaks[];\n sampleRate: number;\n waveHeight: number;\n timeScaleHeight: number;\n samplesPerPixel: number;\n playoutRef: React.RefObject<MediaElementPlayout | null>;\n controls: { show: boolean; width: number };\n barWidth: number;\n barGap: number;\n progressBarWidth: number;\n}\n\n// Create contexts\nconst MediaElementAnimationContext =\n createContext<MediaElementAnimationContextValue | null>(null);\nconst MediaElementStateContext =\n createContext<MediaElementStateContextValue | null>(null);\nconst MediaElementControlsContext =\n createContext<MediaElementControlsContextValue | null>(null);\nconst MediaElementDataContext =\n createContext<MediaElementDataContextValue | null>(null);\n\nexport interface MediaElementPlaylistProviderProps {\n /** Single track configuration with source URL and waveform data */\n track: MediaElementTrackConfig;\n /** Initial samples per pixel (zoom level) */\n samplesPerPixel?: number;\n /** Height of each waveform track */\n waveHeight?: number;\n /** Show timescale */\n timescale?: boolean;\n /** Initial playback rate (0.5 to 2.0) */\n playbackRate?: number;\n /** Theme configuration */\n theme?: Partial<WaveformPlaylistTheme>;\n /** Track controls configuration */\n controls?: { show: boolean; width: number };\n /** Annotations */\n annotationList?: {\n annotations?: any[];\n isContinuousPlay?: boolean;\n };\n /** Width of waveform bars */\n barWidth?: number;\n /** Gap between waveform bars */\n barGap?: number;\n /** Width of progress bars */\n progressBarWidth?: number;\n /** Callback when audio is ready */\n onReady?: () => void;\n children: ReactNode;\n}\n\n/**\n * MediaElementPlaylistProvider\n *\n * A simplified playlist provider for single-track playback using HTMLAudioElement.\n * Key features:\n * - Pitch-preserving playback rate (0.5x - 2.0x)\n * - Pre-computed peaks visualization (no AudioBuffer needed)\n * - Simpler API than full WaveformPlaylistProvider\n *\n * Use this for:\n * - Language learning apps (speed control)\n * - Podcast players\n * - Single-track audio viewers\n *\n * For multi-track editing, use WaveformPlaylistProvider instead.\n */\nexport const MediaElementPlaylistProvider: React.FC<\n MediaElementPlaylistProviderProps\n> = ({\n track,\n samplesPerPixel: initialSamplesPerPixel = 1024,\n waveHeight = 100,\n timescale = false,\n playbackRate: initialPlaybackRate = 1,\n theme: userTheme,\n controls = { show: false, width: 0 },\n annotationList,\n barWidth = 1,\n barGap = 0,\n progressBarWidth: progressBarWidthProp,\n onReady,\n children,\n}) => {\n const progressBarWidth = progressBarWidthProp ?? barWidth + barGap;\n\n // State\n const [isPlaying, setIsPlaying] = useState(false);\n const [currentTime, setCurrentTime] = useState(0);\n const [duration, setDuration] = useState(0);\n const [peaksDataArray, setPeaksDataArray] = useState<TrackClipPeaks[]>([]);\n const [playbackRate, setPlaybackRateState] = useState(initialPlaybackRate);\n const [annotations, setAnnotations] = useState<AnnotationData[]>([]);\n const [activeAnnotationId, setActiveAnnotationIdState] = useState<\n string | null\n >(null);\n const [continuousPlay, setContinuousPlayState] = useState(\n annotationList?.isContinuousPlay ?? false\n );\n const [samplesPerPixel] = useState(initialSamplesPerPixel);\n\n // Refs\n const playoutRef = useRef<MediaElementPlayout | null>(null);\n const currentTimeRef = useRef<number>(0);\n const animationFrameRef = useRef<number | null>(null);\n const continuousPlayRef = useRef<boolean>(continuousPlay);\n const activeAnnotationIdRef = useRef<string | null>(null);\n\n // Sync refs\n useEffect(() => {\n continuousPlayRef.current = continuousPlay;\n }, [continuousPlay]);\n\n // Custom setter for activeAnnotationId\n const setActiveAnnotationId = useCallback((value: string | null) => {\n activeAnnotationIdRef.current = value;\n setActiveAnnotationIdState(value);\n }, []);\n\n const setContinuousPlay = useCallback((value: boolean) => {\n continuousPlayRef.current = value;\n setContinuousPlayState(value);\n }, []);\n\n // Get sample rate from waveform data\n const sampleRate = track.waveformData.sample_rate;\n\n // Initialize playout and load track\n useEffect(() => {\n const playout = new MediaElementPlayout({\n playbackRate: initialPlaybackRate,\n });\n\n playout.addTrack({\n source: track.source,\n peaks: track.waveformData,\n name: track.name,\n });\n\n // Set up time update callback\n const mediaTrack = playout.getTrack(playout['track']?.id ?? '');\n if (mediaTrack) {\n mediaTrack.setOnTimeUpdateCallback((time) => {\n currentTimeRef.current = time;\n });\n }\n\n // Set up playback complete callback\n playout.setOnPlaybackComplete(() => {\n setIsPlaying(false);\n });\n\n playoutRef.current = playout;\n setDuration(track.waveformData.duration);\n onReady?.();\n\n return () => {\n if (animationFrameRef.current) {\n cancelAnimationFrame(animationFrameRef.current);\n }\n playout.dispose();\n };\n }, [track.source, track.waveformData, track.name, initialPlaybackRate, onReady]);\n\n // Generate peaks from waveform data\n useEffect(() => {\n const extractedPeaks = extractPeaksFromWaveformData(\n track.waveformData as any,\n samplesPerPixel,\n 0, // channel index\n 0, // offset\n Math.ceil(track.waveformData.duration * sampleRate) // duration in samples\n );\n\n const clipPeaks: ClipPeaks = {\n clipId: 'media-element-clip',\n trackName: track.name ?? 'Track',\n peaks: {\n length: extractedPeaks.length,\n data: [extractedPeaks.data],\n bits: extractedPeaks.bits,\n } as PeakData,\n startSample: 0,\n durationSamples: Math.ceil(track.waveformData.duration * sampleRate),\n };\n\n setPeaksDataArray([[clipPeaks]]);\n }, [track.waveformData, track.name, samplesPerPixel, sampleRate]);\n\n // Load annotations\n useEffect(() => {\n if (annotationList?.annotations) {\n const parsedAnnotations = annotationList.annotations.map((ann: any) => {\n if (typeof ann.start === 'number') {\n return ann;\n }\n return parseAeneas(ann);\n });\n setAnnotations(parsedAnnotations);\n }\n }, [annotationList]);\n\n // Animation loop\n const startAnimationLoop = useCallback(() => {\n if (animationFrameRef.current) {\n cancelAnimationFrame(animationFrameRef.current);\n }\n\n const updateTime = () => {\n const time = playoutRef.current?.getCurrentTime() ?? 0;\n currentTimeRef.current = time;\n setCurrentTime(time);\n\n // Handle annotation playback\n if (annotations.length > 0) {\n const currentAnnotation = annotations.find(\n (ann) => time >= ann.start && time < ann.end\n );\n\n if (continuousPlayRef.current) {\n if (\n currentAnnotation &&\n currentAnnotation.id !== activeAnnotationIdRef.current\n ) {\n setActiveAnnotationId(currentAnnotation.id);\n } else if (!currentAnnotation && activeAnnotationIdRef.current !== null) {\n const lastAnnotation = annotations[annotations.length - 1];\n if (time >= lastAnnotation.end) {\n playoutRef.current?.stop();\n setIsPlaying(false);\n setActiveAnnotationId(null);\n return;\n }\n }\n } else {\n if (activeAnnotationIdRef.current) {\n const activeAnnotation = annotations.find(\n (ann) => ann.id === activeAnnotationIdRef.current\n );\n if (activeAnnotation && time >= activeAnnotation.end) {\n playoutRef.current?.stop();\n setIsPlaying(false);\n return;\n }\n } else if (currentAnnotation) {\n setActiveAnnotationId(currentAnnotation.id);\n }\n }\n }\n\n if (time >= duration) {\n playoutRef.current?.stop();\n setIsPlaying(false);\n setActiveAnnotationId(null);\n return;\n }\n\n animationFrameRef.current = requestAnimationFrame(updateTime);\n };\n\n animationFrameRef.current = requestAnimationFrame(updateTime);\n }, [duration, annotations, setActiveAnnotationId]);\n\n const stopAnimationLoop = useCallback(() => {\n if (animationFrameRef.current) {\n cancelAnimationFrame(animationFrameRef.current);\n animationFrameRef.current = null;\n }\n }, []);\n\n // Playback controls\n const play = useCallback(\n (startTime?: number) => {\n if (!playoutRef.current) return;\n\n const actualStartTime = startTime ?? currentTimeRef.current;\n playoutRef.current.play(undefined, actualStartTime);\n setIsPlaying(true);\n startAnimationLoop();\n },\n [startAnimationLoop]\n );\n\n const pause = useCallback(() => {\n if (!playoutRef.current) return;\n\n playoutRef.current.pause();\n setIsPlaying(false);\n stopAnimationLoop();\n setCurrentTime(playoutRef.current.getCurrentTime());\n }, [stopAnimationLoop]);\n\n const stop = useCallback(() => {\n if (!playoutRef.current) return;\n\n playoutRef.current.stop();\n setIsPlaying(false);\n stopAnimationLoop();\n currentTimeRef.current = 0;\n setCurrentTime(0);\n setActiveAnnotationId(null);\n }, [stopAnimationLoop, setActiveAnnotationId]);\n\n const seekTo = useCallback(\n (time: number) => {\n const clampedTime = Math.max(0, Math.min(time, duration));\n currentTimeRef.current = clampedTime;\n setCurrentTime(clampedTime);\n\n if (playoutRef.current) {\n playoutRef.current.seekTo(clampedTime);\n }\n },\n [duration]\n );\n\n const setPlaybackRate = useCallback((rate: number) => {\n const clampedRate = Math.max(0.5, Math.min(2.0, rate));\n setPlaybackRateState(clampedRate);\n if (playoutRef.current) {\n playoutRef.current.setPlaybackRate(clampedRate);\n }\n }, []);\n\n const timeScaleHeight = timescale ? 30 : 0;\n\n // Context values\n const animationValue: MediaElementAnimationContextValue = useMemo(\n () => ({\n isPlaying,\n currentTime,\n currentTimeRef,\n }),\n [isPlaying, currentTime]\n );\n\n const stateValue: MediaElementStateContextValue = useMemo(\n () => ({\n continuousPlay,\n annotations,\n activeAnnotationId,\n playbackRate,\n }),\n [continuousPlay, annotations, activeAnnotationId, playbackRate]\n );\n\n const controlsValue: MediaElementControlsContextValue = useMemo(\n () => ({\n play,\n pause,\n stop,\n seekTo,\n setPlaybackRate,\n setContinuousPlay,\n setAnnotations,\n setActiveAnnotationId,\n }),\n [play, pause, stop, seekTo, setPlaybackRate, setContinuousPlay, setActiveAnnotationId]\n );\n\n const dataValue: MediaElementDataContextValue = useMemo(\n () => ({\n duration,\n peaksDataArray,\n sampleRate,\n waveHeight,\n timeScaleHeight,\n samplesPerPixel,\n playoutRef,\n controls,\n barWidth,\n barGap,\n progressBarWidth,\n }),\n [\n duration,\n peaksDataArray,\n sampleRate,\n waveHeight,\n timeScaleHeight,\n samplesPerPixel,\n controls,\n barWidth,\n barGap,\n progressBarWidth,\n ]\n );\n\n const mergedTheme = { ...defaultTheme, ...userTheme };\n\n return (\n <ThemeProvider theme={mergedTheme}>\n <MediaElementAnimationContext.Provider value={animationValue}>\n <MediaElementStateContext.Provider value={stateValue}>\n <MediaElementControlsContext.Provider value={controlsValue}>\n <MediaElementDataContext.Provider value={dataValue}>\n {children}\n </MediaElementDataContext.Provider>\n </MediaElementControlsContext.Provider>\n </MediaElementStateContext.Provider>\n </MediaElementAnimationContext.Provider>\n </ThemeProvider>\n );\n};\n\n// Hooks\nexport const useMediaElementAnimation = () => {\n const context = useContext(MediaElementAnimationContext);\n if (!context) {\n throw new Error(\n 'useMediaElementAnimation must be used within MediaElementPlaylistProvider'\n );\n }\n return context;\n};\n\nexport const useMediaElementState = () => {\n const context = useContext(MediaElementStateContext);\n if (!context) {\n throw new Error(\n 'useMediaElementState must be used within MediaElementPlaylistProvider'\n );\n }\n return context;\n};\n\nexport const useMediaElementControls = () => {\n const context = useContext(MediaElementControlsContext);\n if (!context) {\n throw new Error(\n 'useMediaElementControls must be used within MediaElementPlaylistProvider'\n );\n }\n return context;\n};\n\nexport const useMediaElementData = () => {\n const context = useContext(MediaElementDataContext);\n if (!context) {\n throw new Error(\n 'useMediaElementData must be used within MediaElementPlaylistProvider'\n );\n }\n return context;\n};\n","import React from 'react';\nimport { BaseControlButton } from '@waveform-playlist/ui-components';\nimport { usePlaybackAnimation, usePlaylistState, usePlaylistControls, usePlaylistData } from '../WaveformPlaylistContext';\n\nexport const PlayButton: React.FC<{ className?: string }> = ({ className }) => {\n const { isPlaying, currentTimeRef } = usePlaybackAnimation();\n const { selectionStart, selectionEnd, isLoopEnabled } = usePlaylistState();\n const { play } = usePlaylistControls();\n\n const handleClick = async () => {\n const hasSelection = selectionStart !== selectionEnd && selectionEnd > selectionStart;\n\n if (hasSelection) {\n if (isLoopEnabled) {\n // With loop: Start from selection start, let loop logic handle boundaries\n // Playback continues until it gets trapped in loop or reaches end\n await play(selectionStart);\n } else {\n // Without loop: Play selection region only, then stop\n const duration = selectionEnd - selectionStart;\n await play(selectionStart, duration);\n }\n } else {\n // No selection: Play from current position to the end\n await play(currentTimeRef.current ?? 0);\n }\n };\n\n return (\n <BaseControlButton onClick={handleClick} disabled={isPlaying} className={className}>\n Play\n </BaseControlButton>\n );\n};\n\nexport const PauseButton: React.FC<{ className?: string }> = ({ className }) => {\n const { isPlaying } = usePlaybackAnimation();\n const { pause } = usePlaylistControls();\n\n return (\n <BaseControlButton onClick={pause} disabled={!isPlaying} className={className}>\n Pause\n </BaseControlButton>\n );\n};\n\nexport const StopButton: React.FC<{ className?: string }> = ({ className }) => {\n const { isPlaying } = usePlaybackAnimation();\n const { stop } = usePlaylistControls();\n\n return (\n <BaseControlButton onClick={stop} disabled={!isPlaying} className={className}>\n Stop\n </BaseControlButton>\n );\n};\n\nexport const RewindButton: React.FC<{ className?: string }> = ({ className }) => {\n const { isPlaying } = usePlaybackAnimation();\n const { play, setCurrentTime } = usePlaylistControls();\n const { playoutRef } = usePlaylistData();\n\n const handleClick = () => {\n setCurrentTime(0);\n\n if (isPlaying && playoutRef.current) {\n playoutRef.current.stop();\n play(0);\n }\n };\n\n return (\n <BaseControlButton onClick={handleClick} className={className}>\n Rewind\n </BaseControlButton>\n );\n};\n\nexport const FastForwardButton: React.FC<{ className?: string }> = ({ className }) => {\n const { isPlaying } = usePlaybackAnimation();\n const { play, setCurrentTime } = usePlaylistControls();\n const { duration, playoutRef } = usePlaylistData();\n\n const handleClick = () => {\n setCurrentTime(duration);\n\n if (isPlaying && playoutRef.current) {\n playoutRef.current.stop();\n play(duration);\n }\n };\n\n return (\n <BaseControlButton onClick={handleClick} className={className}>\n Fast Forward\n </BaseControlButton>\n );\n};\n\nexport const SkipBackwardButton: React.FC<{ skipAmount?: number; className?: string }> = ({\n skipAmount = 5,\n className\n}) => {\n const { currentTimeRef, isPlaying } = usePlaybackAnimation();\n const { play, setCurrentTime } = usePlaylistControls();\n const { playoutRef } = usePlaylistData();\n\n const handleClick = () => {\n const newTime = Math.max(0, (currentTimeRef.current ?? 0) - skipAmount);\n setCurrentTime(newTime);\n\n if (isPlaying && playoutRef.current) {\n playoutRef.current.stop();\n play(newTime);\n }\n };\n\n return (\n <BaseControlButton onClick={handleClick} className={className}>\n Skip Backward\n </BaseControlButton>\n );\n};\n\nexport const SkipForwardButton: React.FC<{ skipAmount?: number; className?: string }> = ({\n skipAmount = 5,\n className\n}) => {\n const { currentTimeRef, isPlaying } = usePlaybackAnimation();\n const { play, setCurrentTime } = usePlaylistControls();\n const { duration, playoutRef } = usePlaylistData();\n\n const handleClick = () => {\n const newTime = Math.min(duration, (currentTimeRef.current ?? 0) + skipAmount);\n setCurrentTime(newTime);\n\n if (isPlaying && playoutRef.current) {\n playoutRef.current.stop();\n play(newTime);\n }\n };\n\n return (\n <BaseControlButton onClick={handleClick} className={className}>\n Skip Forward\n </BaseControlButton>\n );\n};\n\nexport const LoopButton: React.FC<{ className?: string }> = ({ className }) => {\n const { isLoopEnabled, loopStart, loopEnd } = usePlaylistState();\n const { setLoopEnabled, setLoopRegion } = usePlaylistControls();\n const { duration } = usePlaylistData();\n\n const hasValidLoopRegion = loopStart !== loopEnd && loopEnd > loopStart;\n\n const handleClick = () => {\n if (!isLoopEnabled && !hasValidLoopRegion) {\n // Create a default loop region when enabling loop without one\n // Default to first 10 seconds or 25% of duration, whichever is smaller\n const defaultEnd = Math.min(10, duration * 0.25);\n setLoopRegion(0, Math.max(1, defaultEnd)); // At least 1 second\n }\n setLoopEnabled(!isLoopEnabled);\n };\n\n return (\n <BaseControlButton\n onClick={handleClick}\n className={className}\n title={isLoopEnabled ? 'Disable loop' : 'Enable loop'}\n >\n {isLoopEnabled ? 'Loop On' : 'Loop Off'}\n </BaseControlButton>\n );\n};\n\nexport const SetLoopRegionButton: React.FC<{ className?: string }> = ({ className }) => {\n const { selectionStart, selectionEnd, loopStart, loopEnd } = usePlaylistState();\n const { setLoopRegionFromSelection, clearLoopRegion } = usePlaylistControls();\n\n const hasValidSelection = selectionStart !== selectionEnd && selectionEnd > selectionStart;\n const hasLoopRegion = loopStart !== loopEnd && loopEnd > loopStart;\n\n const handleClick = () => {\n if (hasLoopRegion) {\n clearLoopRegion();\n } else {\n setLoopRegionFromSelection();\n }\n };\n\n return (\n <BaseControlButton\n onClick={handleClick}\n disabled={!hasValidSelection && !hasLoopRegion}\n className={className}\n title={hasLoopRegion ? 'Clear loop region' : (hasValidSelection ? 'Set loop region from selection' : 'Create a selection first')}\n >\n {hasLoopRegion ? 'Clear Loop' : 'Set Loop'}\n </BaseControlButton>\n );\n};\n","import React from 'react';\nimport { BaseControlButton } from '@waveform-playlist/ui-components';\nimport { usePlaylistControls, usePlaylistData } from '../WaveformPlaylistContext';\n\nexport const ZoomInButton: React.FC<{ className?: string; disabled?: boolean }> = ({ className, disabled }) => {\n const { zoomIn } = usePlaylistControls();\n const { canZoomIn } = usePlaylistData();\n\n return (\n <BaseControlButton variant=\"success\" onClick={zoomIn} disabled={disabled || !canZoomIn} className={className}>\n Zoom In\n </BaseControlButton>\n );\n};\n\nexport const ZoomOutButton: React.FC<{ className?: string; disabled?: boolean }> = ({ className, disabled }) => {\n const { zoomOut } = usePlaylistControls();\n const { canZoomOut } = usePlaylistData();\n\n return (\n <BaseControlButton variant=\"success\" onClick={zoomOut} disabled={disabled || !canZoomOut} className={className}>\n Zoom Out\n </BaseControlButton>\n );\n};\n","import React, { useRef, useEffect } from 'react';\nimport { getContext } from 'tone';\nimport {\n MasterVolumeControl as BaseMasterVolumeControl,\n TimeFormatSelect as BaseTimeFormatSelect,\n AutomaticScrollCheckbox as BaseAutomaticScrollCheckbox,\n SelectionTimeInputs as BaseSelectionTimeInputs,\n formatTime,\n type TimeFormat,\n} from '@waveform-playlist/ui-components';\nimport styled from 'styled-components';\nimport { usePlaybackAnimation, usePlaylistState, usePlaylistControls, usePlaylistData } from '../WaveformPlaylistContext';\n\n/**\n * Master volume control that uses the playlist context\n */\nexport const MasterVolumeControl: React.FC<{ className?: string }> = ({ className }) => {\n const { masterVolume } = usePlaylistData();\n const { setMasterVolume } = usePlaylistControls();\n\n return (\n <BaseMasterVolumeControl\n volume={masterVolume}\n onChange={setMasterVolume}\n className={className}\n />\n );\n};\n\n/**\n * Time format selector that uses the playlist context\n */\nexport const TimeFormatSelect: React.FC<{ className?: string }> = ({ className }) => {\n const { timeFormat } = usePlaylistData();\n const { setTimeFormat } = usePlaylistControls();\n\n return (\n <BaseTimeFormatSelect\n value={timeFormat as any}\n onChange={setTimeFormat as any}\n className={className}\n />\n );\n};\n\nconst PositionDisplay = styled.span`\n font-family: 'Courier New', Monaco, monospace;\n font-size: 1rem;\n font-weight: 600;\n color: ${props => props.theme?.textColor || '#333'};\n user-select: none;\n`;\n\n/**\n * Audio position display that uses the playlist context.\n * Uses requestAnimationFrame for smooth 60fps updates during playback.\n * Direct DOM manipulation avoids React re-renders.\n */\nexport const AudioPosition: React.FC<{ className?: string }> = ({ className }) => {\n const timeRef = useRef<HTMLSpanElement>(null);\n const animationFrameRef = useRef<number | null>(null);\n const { isPlaying, currentTimeRef, playbackStartTimeRef, audioStartPositionRef } = usePlaybackAnimation();\n const { timeFormat } = usePlaylistData();\n const format = timeFormat as TimeFormat;\n\n useEffect(() => {\n const updateTime = () => {\n if (timeRef.current) {\n let time: number;\n if (isPlaying) {\n const elapsed = getContext().currentTime - (playbackStartTimeRef.current ?? 0);\n time = (audioStartPositionRef.current ?? 0) + elapsed;\n } else {\n time = currentTimeRef.current ?? 0;\n }\n timeRef.current.textContent = formatTime(time, format);\n }\n\n if (isPlaying) {\n animationFrameRef.current = requestAnimationFrame(updateTime);\n }\n };\n\n if (isPlaying) {\n animationFrameRef.current = requestAnimationFrame(updateTime);\n } else {\n updateTime();\n }\n\n return () => {\n if (animationFrameRef.current) {\n cancelAnimationFrame(animationFrameRef.current);\n animationFrameRef.current = null;\n }\n };\n }, [isPlaying, format, currentTimeRef, playbackStartTimeRef, audioStartPositionRef]);\n\n // Update when stopped (for seeks)\n useEffect(() => {\n if (!isPlaying && timeRef.current) {\n timeRef.current.textContent = formatTime(currentTimeRef.current ?? 0, format);\n }\n });\n\n return (\n <PositionDisplay ref={timeRef} className={className} aria-label=\"Audio position\">\n {formatTime(currentTimeRef.current ?? 0, format)}\n </PositionDisplay>\n );\n};\n\n/**\n * Selection time inputs that use the playlist context\n */\nexport const SelectionTimeInputs: React.FC<{ className?: string }> = ({ className }) => {\n const { selectionStart, selectionEnd } = usePlaylistState();\n const { setSelection } = usePlaylistControls();\n\n return (\n <BaseSelectionTimeInputs\n selectionStart={selectionStart}\n selectionEnd={selectionEnd}\n onSelectionChange={setSelection}\n className={className}\n />\n );\n};\n\n/**\n * Automatic scroll checkbox that uses the playlist context\n * Uses split contexts to avoid re-rendering during animation\n */\nexport const AutomaticScrollCheckbox: React.FC<{ className?: string }> = ({ className }) => {\n const { isAutomaticScroll } = usePlaylistState();\n const { setAutomaticScroll } = usePlaylistControls();\n\n return (\n <BaseAutomaticScrollCheckbox\n checked={isAutomaticScroll}\n onChange={setAutomaticScroll}\n className={className}\n />\n );\n};\n","import React from 'react';\nimport {\n ContinuousPlayCheckbox as BaseContinuousPlayCheckbox,\n LinkEndpointsCheckbox as BaseLinkEndpointsCheckbox,\n EditableCheckbox as BaseEditableCheckbox,\n DownloadAnnotationsButton as BaseDownloadAnnotationsButton,\n} from '@waveform-playlist/annotations';\nimport { usePlaylistState, usePlaylistControls } from '../WaveformPlaylistContext';\n\n/**\n * Continuous play checkbox that uses the playlist context\n * Uses split contexts to avoid re-rendering during animation\n */\nexport const ContinuousPlayCheckbox: React.FC<{ className?: string }> = ({ className }) => {\n const { continuousPlay } = usePlaylistState();\n const { setContinuousPlay } = usePlaylistControls();\n\n return (\n <BaseContinuousPlayCheckbox\n checked={continuousPlay}\n onChange={setContinuousPlay}\n className={className}\n />\n );\n};\n\n/**\n * Link endpoints checkbox that uses the playlist context\n * Uses split contexts to avoid re-rendering during animation\n */\nexport const LinkEndpointsCheckbox: React.FC<{ className?: string }> = ({ className }) => {\n const { linkEndpoints } = usePlaylistState();\n const { setLinkEndpoints } = usePlaylistControls();\n\n return (\n <BaseLinkEndpointsCheckbox\n checked={linkEndpoints}\n onChange={setLinkEndpoints}\n className={className}\n />\n );\n};\n\n/**\n * Editable annotations checkbox that uses the playlist context\n * Uses split contexts to avoid re-rendering during animation\n */\nexport const EditableCheckbox: React.FC<{ className?: string }> = ({ className }) => {\n const { annotationsEditable } = usePlaylistState();\n const { setAnnotationsEditable } = usePlaylistControls();\n\n return (\n <BaseEditableCheckbox\n checked={annotationsEditable}\n onChange={setAnnotationsEditable}\n className={className}\n />\n );\n};\n\n/**\n * Download annotations button that uses the playlist context\n * Uses split contexts to avoid re-rendering during animation\n */\nexport const DownloadAnnotationsButton: React.FC<{ filename?: string; className?: string }> = ({\n filename,\n className,\n}) => {\n const { annotations } = usePlaylistState();\n\n return (\n <BaseDownloadAnnotationsButton\n annotations={annotations}\n filename={filename}\n className={className}\n />\n );\n};\n","import React from 'react';\nimport { BaseControlButton } from '@waveform-playlist/ui-components';\nimport type { EffectsFunction } from '@waveform-playlist/playout';\nimport { usePlaylistData } from '../WaveformPlaylistContext';\nimport { useExportWav, type TrackEffectsFunction } from '../hooks/useExportWav';\n\nexport interface ExportWavButtonProps {\n /** Button label */\n label?: string;\n /** Filename for the downloaded file (without extension) */\n filename?: string;\n /** Export mode: 'master' for stereo mix, 'individual' for single track */\n mode?: 'master' | 'individual';\n /** Track index for individual export */\n trackIndex?: number;\n /** Bit depth: 16 or 32 */\n bitDepth?: 16 | 32;\n /** Whether to apply effects (fades, etc.) - defaults to true */\n applyEffects?: boolean;\n /**\n * Optional Tone.js effects function for master effects. When provided, export will use Tone.Offline\n * to render through the effects chain. The function receives isOffline=true.\n */\n effectsFunction?: EffectsFunction;\n /**\n * Optional function to create offline track effects.\n * Takes a trackId and returns a TrackEffectsFunction for offline rendering.\n */\n createOfflineTrackEffects?: (trackId: string) => TrackEffectsFunction | undefined;\n /** CSS class name */\n className?: string;\n /** Callback when export completes */\n onExportComplete?: (blob: Blob) => void;\n /** Callback when export fails */\n onExportError?: (error: Error) => void;\n}\n\nexport const ExportWavButton: React.FC<ExportWavButtonProps> = ({\n label = 'Export WAV',\n filename = 'export',\n mode = 'master',\n trackIndex,\n bitDepth = 16,\n applyEffects = true,\n effectsFunction,\n createOfflineTrackEffects,\n className,\n onExportComplete,\n onExportError,\n}) => {\n const { tracks, trackStates } = usePlaylistData();\n const { exportWav, isExporting, progress } = useExportWav();\n\n const handleExport = async () => {\n try {\n const result = await exportWav(tracks, trackStates, {\n filename,\n mode,\n trackIndex,\n bitDepth,\n applyEffects,\n effectsFunction,\n createOfflineTrackEffects,\n autoDownload: true,\n });\n onExportComplete?.(result.blob);\n } catch (error) {\n onExportError?.(error instanceof Error ? error : new Error('Export failed'));\n }\n };\n\n const buttonLabel = isExporting\n ? `Exporting ${Math.round(progress * 100)}%`\n : label;\n\n return (\n <BaseControlButton\n onClick={handleExport}\n disabled={isExporting || tracks.length === 0}\n className={className}\n >\n {buttonLabel}\n </BaseControlButton>\n );\n};\n","import React, { useRef, useEffect } from 'react';\nimport styled from 'styled-components';\nimport { getContext } from 'tone';\nimport { usePlaybackAnimation, usePlaylistData } from '../WaveformPlaylistContext';\n\nconst PlayheadLine = styled.div<{ $color: string; $width: number }>`\n position: absolute;\n top: 0;\n left: 0;\n width: ${(props) => props.$width}px;\n background: ${(props) => props.$color};\n height: 100%;\n z-index: 100; /* Below sticky controls (z-index: 101) so playhead is hidden when scrolled behind controls */\n pointer-events: none;\n will-change: transform;\n`;\n\ninterface AnimatedPlayheadProps {\n color?: string;\n controlsOffset?: number;\n}\n\n/**\n * Animated playhead that updates position via direct DOM manipulation.\n * Calculates time directly from audio context for perfect synchronization.\n * Uses requestAnimationFrame for smooth 60fps animation without React re-renders.\n */\nexport const AnimatedPlayhead: React.FC<AnimatedPlayheadProps> = ({\n color = '#ff0000',\n controlsOffset = 0,\n}) => {\n const playheadRef = useRef<HTMLDivElement>(null);\n const animationFrameRef = useRef<number | null>(null);\n\n const { isPlaying, currentTimeRef, playbackStartTimeRef, audioStartPositionRef } = usePlaybackAnimation();\n const { samplesPerPixel, sampleRate, progressBarWidth } = usePlaylistData();\n\n useEffect(() => {\n const updatePosition = () => {\n if (playheadRef.current) {\n // Calculate time directly from audio context for perfect sync\n let time: number;\n if (isPlaying) {\n const elapsed = getContext().currentTime - (playbackStartTimeRef.current ?? 0);\n time = (audioStartPositionRef.current ?? 0) + elapsed;\n } else {\n time = currentTimeRef.current ?? 0;\n }\n const position = (time * sampleRate) / samplesPerPixel + controlsOffset;\n playheadRef.current.style.transform = `translate3d(${position}px, 0, 0)`;\n }\n\n if (isPlaying) {\n animationFrameRef.current = requestAnimationFrame(updatePosition);\n }\n };\n\n if (isPlaying) {\n // Start animation loop\n animationFrameRef.current = requestAnimationFrame(updatePosition);\n } else {\n // When stopped, update once to show final position\n updatePosition();\n }\n\n return () => {\n if (animationFrameRef.current) {\n cancelAnimationFrame(animationFrameRef.current);\n animationFrameRef.current = null;\n }\n };\n }, [isPlaying, sampleRate, samplesPerPixel, controlsOffset, currentTimeRef, playbackStartTimeRef, audioStartPositionRef]);\n\n // Also update position when not playing (for seeks, stops, etc.)\n useEffect(() => {\n if (!isPlaying && playheadRef.current) {\n const time = currentTimeRef.current ?? 0;\n const position = (time * sampleRate) / samplesPerPixel + controlsOffset;\n playheadRef.current.style.transform = `translate3d(${position}px, 0, 0)`;\n }\n });\n\n return <PlayheadLine ref={playheadRef} $color={color} $width={progressBarWidth} data-playhead />;\n};\n","import React, { useRef, useEffect } from 'react';\nimport styled from 'styled-components';\nimport { getContext } from 'tone';\nimport { SmartChannel, type SmartChannelProps, useTheme, usePlaylistInfo, type WaveformPlaylistTheme, waveformColorToCss } from '@waveform-playlist/ui-components';\nimport { usePlaybackAnimation, usePlaylistData } from '../WaveformPlaylistContext';\n\nconst ChannelWrapper = styled.div`\n position: relative;\n`;\n\ninterface BackgroundProps {\n readonly $color: string;\n readonly $height: number;\n readonly $top: number;\n readonly $width: number;\n}\n\nconst Background = styled.div<BackgroundProps>`\n position: absolute;\n top: ${(props) => props.$top}px;\n left: 0;\n width: ${(props) => props.$width}px;\n height: ${(props) => props.$height}px;\n background: ${(props) => props.$color};\n z-index: 0;\n /* Force GPU compositing layer to prevent gradient flickering during scroll */\n transform: translateZ(0);\n backface-visibility: hidden;\n will-change: transform;\n`;\n\ninterface ProgressOverlayProps {\n readonly $color: string;\n readonly $height: number;\n readonly $top: number;\n}\n\nconst ProgressOverlay = styled.div<ProgressOverlayProps>`\n position: absolute;\n top: ${(props) => props.$top}px;\n left: 0;\n height: ${(props) => props.$height}px;\n background: ${(props) => props.$color};\n pointer-events: none;\n z-index: 1;\n will-change: width;\n`;\n\nconst ChannelContainer = styled.div`\n position: relative;\n z-index: 2;\n`;\n\nexport interface ChannelWithProgressProps extends SmartChannelProps {\n /** Start sample of the clip containing this channel (for progress calculation) */\n clipStartSample: number;\n /** Duration in samples of the clip */\n clipDurationSamples: number;\n}\n\n/**\n * SmartChannel wrapper that adds an animated progress overlay.\n * The progress overlay shows the \"played\" portion of the waveform.\n * Uses requestAnimationFrame for smooth 60fps animation without React re-renders.\n */\nexport const ChannelWithProgress: React.FC<ChannelWithProgressProps> = ({\n clipStartSample,\n clipDurationSamples,\n ...smartChannelProps\n}) => {\n const progressRef = useRef<HTMLDivElement>(null);\n const animationFrameRef = useRef<number | null>(null);\n const theme = useTheme() as WaveformPlaylistTheme;\n const { waveHeight } = usePlaylistInfo();\n\n const { isPlaying, currentTimeRef, playbackStartTimeRef, audioStartPositionRef } = usePlaybackAnimation();\n const { samplesPerPixel, sampleRate } = usePlaylistData();\n\n const progressColor = theme?.waveProgressColor || 'rgba(0, 0, 0, 0.1)';\n\n useEffect(() => {\n const updateProgress = () => {\n if (progressRef.current) {\n // Calculate current time from audio context\n let currentTime: number;\n if (isPlaying) {\n const elapsed = getContext().currentTime - (playbackStartTimeRef.current ?? 0);\n currentTime = (audioStartPositionRef.current ?? 0) + elapsed;\n } else {\n currentTime = currentTimeRef.current ?? 0;\n }\n\n // Convert current time to samples\n const currentSample = currentTime * sampleRate;\n\n // Calculate clip bounds in samples\n const clipEndSample = clipStartSample + clipDurationSamples;\n\n // Calculate how much of this clip has been played\n let progressWidth = 0;\n\n if (currentSample <= clipStartSample) {\n // Playhead is before this clip - no progress\n progressWidth = 0;\n } else if (currentSample >= clipEndSample) {\n // Playhead is past this clip - full progress\n progressWidth = smartChannelProps.length;\n } else {\n // Playhead is within this clip - partial progress\n const playedSamples = currentSample - clipStartSample;\n progressWidth = Math.floor(playedSamples / samplesPerPixel);\n }\n\n progressRef.current.style.width = `${progressWidth}px`;\n }\n\n if (isPlaying) {\n animationFrameRef.current = requestAnimationFrame(updateProgress);\n }\n };\n\n if (isPlaying) {\n animationFrameRef.current = requestAnimationFrame(updateProgress);\n } else {\n // When stopped, update once to show final position\n updateProgress();\n }\n\n return () => {\n if (animationFrameRef.current) {\n cancelAnimationFrame(animationFrameRef.current);\n animationFrameRef.current = null;\n }\n };\n }, [isPlaying, sampleRate, samplesPerPixel, clipStartSample, clipDurationSamples, smartChannelProps.length, currentTimeRef, playbackStartTimeRef, audioStartPositionRef]);\n\n // Also update when not playing (for seeks, stops, etc.)\n useEffect(() => {\n if (!isPlaying && progressRef.current) {\n const currentTime = currentTimeRef.current ?? 0;\n const currentSample = currentTime * sampleRate;\n const clipEndSample = clipStartSample + clipDurationSamples;\n\n let progressWidth = 0;\n if (currentSample <= clipStartSample) {\n progressWidth = 0;\n } else if (currentSample >= clipEndSample) {\n progressWidth = smartChannelProps.length;\n } else {\n const playedSamples = currentSample - clipStartSample;\n progressWidth = Math.floor(playedSamples / samplesPerPixel);\n }\n\n progressRef.current.style.width = `${progressWidth}px`;\n }\n });\n\n // Get the draw mode from theme (defaults to 'inverted')\n const drawMode = theme?.waveformDrawMode || 'inverted';\n\n let backgroundColor;\n if (drawMode === 'inverted') {\n\n backgroundColor = smartChannelProps.isSelected && theme\n ? theme.selectedWaveFillColor\n : theme?.waveFillColor || 'white';\n\n } else {\n backgroundColor = smartChannelProps.isSelected && theme\n ? theme.selectedWaveOutlineColor\n : theme?.waveOutlineColor || 'grey';\n }\n\n const backgroundCss = waveformColorToCss(backgroundColor);\n\n return (\n <ChannelWrapper>\n {/* Background layer - color depends on draw mode */}\n <Background\n $color={backgroundCss}\n $height={waveHeight}\n $top={smartChannelProps.index * waveHeight}\n $width={smartChannelProps.length}\n />\n {/* Progress overlay - shows played portion with progress color */}\n <ProgressOverlay\n ref={progressRef}\n $color={progressColor}\n $height={waveHeight}\n $top={smartChannelProps.index * waveHeight}\n />\n {/* Waveform canvas with transparent background */}\n <ChannelContainer>\n <SmartChannel {...smartChannelProps} transparentBackground />\n </ChannelContainer>\n </ChannelWrapper>\n );\n};\n","import React, { useRef, useState, ReactNode, useCallback, useMemo } from 'react';\nimport { getContext } from 'tone';\nimport {\n Playlist,\n Track as TrackComponent,\n Clip,\n Playhead,\n Selection,\n TimescaleLoopRegion,\n PlaylistInfoContext,\n TrackControlsContext,\n DevicePixelRatioProvider,\n StyledTimeScale,\n Controls,\n Header,\n Button,\n ButtonGroup,\n Slider,\n SliderWrapper,\n VolumeDownIcon,\n VolumeUpIcon,\n useTheme,\n waveformColorToCss,\n type RenderPlayheadFunction,\n} from '@waveform-playlist/ui-components';\nimport {\n AnnotationBoxesWrapper,\n AnnotationBox,\n AnnotationText,\n} from '@waveform-playlist/annotations';\nimport type { AnnotationAction, AnnotationActionOptions, RenderAnnotationItemProps } from '@waveform-playlist/annotations';\nimport { usePlaybackAnimation, usePlaylistState, usePlaylistControls, usePlaylistData } from '../WaveformPlaylistContext';\nimport type { Peaks } from '@waveform-playlist/webaudio-peaks';\nimport { AnimatedPlayhead } from './AnimatedPlayhead';\nimport { ChannelWithProgress } from './ChannelWithProgress';\n\n// Default duration in seconds for empty tracks (used for recording workflow)\nconst DEFAULT_EMPTY_TRACK_DURATION = 60;\n\nexport interface WaveformProps {\n renderTrackControls?: (trackIndex: number) => ReactNode;\n renderTimestamp?: (timeMs: number, pixelPosition: number) => ReactNode;\n /** Custom playhead render function. Receives position (pixels) and color from theme. */\n renderPlayhead?: RenderPlayheadFunction;\n annotationControls?: AnnotationAction[];\n annotationListConfig?: AnnotationActionOptions;\n annotationTextHeight?: number; // Height in pixels for the annotation text list\n /**\n * Custom render function for annotation items in the text list.\n * Use this to completely customize how each annotation is displayed.\n */\n renderAnnotationItem?: (props: RenderAnnotationItemProps) => ReactNode;\n /**\n * Custom function to generate the label shown on annotation boxes in the waveform.\n * Receives the annotation data and should return a string label.\n * Default: annotation.id\n */\n getAnnotationBoxLabel?: (annotation: { id: string; start: number; end: number; lines: string[] }) => string;\n className?: string;\n showClipHeaders?: boolean; // Show headers on clips for visual organization\n interactiveClips?: boolean; // Enable dragging/trimming interactions on clips (requires @dnd-kit setup)\n showFades?: boolean; // Show fade in/out overlays on clips\n /**\n * Enable mobile-optimized touch interactions.\n * When true, increases touch target sizes for clip boundaries.\n * Use with useDragSensors({ touchOptimized: true }) for best results.\n */\n touchOptimized?: boolean;\n // Live recording state for real-time waveform preview\n recordingState?: {\n isRecording: boolean;\n trackId: string; // Which track is being recorded into\n startSample: number; // Where recording started\n durationSamples: number; // Current recording length\n peaks: Int8Array | Int16Array; // Live peaks data\n };\n}\n\n/**\n * Waveform visualization component that uses the playlist context\n */\nexport const Waveform: React.FC<WaveformProps> = ({\n renderTrackControls,\n renderTimestamp,\n renderPlayhead,\n annotationControls,\n annotationListConfig: _annotationListConfig,\n annotationTextHeight,\n renderAnnotationItem,\n getAnnotationBoxLabel,\n className,\n showClipHeaders = false,\n interactiveClips = false,\n showFades = false,\n touchOptimized = false,\n recordingState,\n}) => {\n // Get theme from context (typed as WaveformPlaylistTheme)\n const theme = useTheme() as import('@waveform-playlist/ui-components').WaveformPlaylistTheme;\n\n // Split context usage for performance\n // NOTE: We intentionally do NOT subscribe to currentTime here to avoid re-renders during playback.\n // AnimatedPlayhead/AnimatedProgress handle their own positioning via refs for smooth 60fps animation.\n // We pass refs to custom renderPlayhead for smooth animation support.\n const { isPlaying, currentTimeRef, playbackStartTimeRef, audioStartPositionRef } = usePlaybackAnimation();\n const {\n selectionStart,\n selectionEnd,\n annotations,\n activeAnnotationId,\n annotationsEditable,\n linkEndpoints,\n continuousPlay,\n selectedTrackId,\n loopStart,\n loopEnd,\n isLoopEnabled,\n } = usePlaylistState();\n const {\n setAnnotations,\n setActiveAnnotationId,\n setTrackMute,\n setTrackSolo,\n setTrackVolume,\n setTrackPan,\n setSelection,\n play,\n setScrollContainer,\n setSelectedTrackId,\n setCurrentTime,\n setLoopRegion,\n } = usePlaylistControls();\n const {\n audioBuffers,\n peaksDataArray,\n trackStates,\n tracks,\n duration,\n samplesPerPixel,\n sampleRate,\n waveHeight,\n timeScaleHeight,\n controls,\n playoutRef,\n barWidth,\n barGap,\n } = usePlaylistData();\n\n const [isSelecting, setIsSelecting] = useState(false);\n\n // Local ref for scroll container to use in drag handlers\n const scrollContainerRef = useRef<HTMLDivElement | null>(null);\n\n // Callback to set both local ref and context ref\n const handleScrollContainerRef = useCallback((element: HTMLDivElement | null) => {\n scrollContainerRef.current = element;\n setScrollContainer(element);\n }, [setScrollContainer]);\n\n // Calculate dimensions\n // If there are no clips, provide a reasonable default width for recording\n let displayDuration = audioBuffers.length > 0 ? duration : DEFAULT_EMPTY_TRACK_DURATION;\n\n // Extend duration during recording if needed\n if (recordingState?.isRecording) {\n const recordingEndSample = recordingState.startSample + recordingState.durationSamples;\n const recordingEndTime = recordingEndSample / sampleRate;\n displayDuration = Math.max(displayDuration, recordingEndTime + 10); // Add 10s buffer\n }\n\n const tracksFullWidth = Math.floor((displayDuration * sampleRate) / samplesPerPixel);\n\n // Annotation click handler\n const handleAnnotationClick = async (annotation: any) => {\n console.log('Annotation clicked:', annotation.id);\n setActiveAnnotationId(annotation.id);\n const playDuration = !continuousPlay ? annotation.end - annotation.start : undefined;\n await play(annotation.start, playDuration);\n };\n\n // Shared function for track selection\n const selectTrack = useCallback((trackIndex: number) => {\n if (trackIndex >= 0 && trackIndex < tracks.length) {\n const track = tracks[trackIndex];\n setSelectedTrackId(track.id);\n }\n }, [tracks, setSelectedTrackId]);\n\n // Mouse handlers for selection and click-to-seek\n const handleMouseDown = (e: React.MouseEvent<HTMLDivElement>) => {\n const rect = (e.currentTarget as HTMLDivElement).getBoundingClientRect();\n const controlWidth = controls.show ? controls.width : 0;\n const x = e.clientX - rect.left - controlWidth;\n const clickTime = (x * samplesPerPixel) / sampleRate;\n\n // Calculate which track was clicked based on Y position\n // The click overlay covers all tracks, so we need to calculate from Y position\n const y = e.clientY - rect.top;\n\n // The ClickOverlay is inside TracksContainer which is BELOW the timescale,\n // so y is already relative to the tracks area - no need to subtract timeScaleHeight\n const trackY = y;\n\n // Calculate track index based on cumulative heights\n let cumulativeHeight = 0;\n let clickedTrackIndex = -1;\n\n for (let i = 0; i < peaksDataArray.length; i++) {\n const trackClipPeaks = peaksDataArray[i];\n\n // Calculate track height (1 channel for empty tracks, max channels for tracks with clips)\n const maxChannels = trackClipPeaks.length > 0\n ? Math.max(...trackClipPeaks.map(clip => clip.peaks.data.length))\n : 1;\n const trackHeight = maxChannels * waveHeight + (showClipHeaders ? 22 : 0); // CLIP_HEADER_HEIGHT = 22\n\n if (trackY >= cumulativeHeight && trackY < cumulativeHeight + trackHeight) {\n clickedTrackIndex = i;\n break;\n }\n\n cumulativeHeight += trackHeight;\n }\n\n // Select the clicked track\n if (clickedTrackIndex !== -1) {\n selectTrack(clickedTrackIndex);\n }\n\n setIsSelecting(true);\n setCurrentTime(clickTime);\n setSelection(clickTime, clickTime);\n };\n\n const handleMouseMove = (e: React.MouseEvent<HTMLDivElement>) => {\n if (!isSelecting) return;\n\n const rect = (e.currentTarget as HTMLDivElement).getBoundingClientRect();\n const controlWidth = controls.show ? controls.width : 0;\n const x = e.clientX - rect.left - controlWidth;\n const moveTime = (x * samplesPerPixel) / sampleRate;\n\n const start = Math.min(selectionStart, moveTime);\n const end = Math.max(selectionStart, moveTime);\n setSelection(start, end);\n };\n\n const handleMouseUp = (e: React.MouseEvent<HTMLDivElement>) => {\n if (!isSelecting) return;\n\n setIsSelecting(false);\n\n const rect = (e.currentTarget as HTMLDivElement).getBoundingClientRect();\n const controlWidth = controls.show ? controls.width : 0;\n const x = e.clientX - rect.left - controlWidth;\n const endTime = (x * samplesPerPixel) / sampleRate;\n\n const start = Math.min(selectionStart, endTime);\n const end = Math.max(selectionStart, endTime);\n\n // If it's just a click (not a drag), seek to that position\n if (Math.abs(end - start) < 0.1) {\n setCurrentTime(start);\n\n if (isPlaying && playoutRef.current) {\n playoutRef.current.stop();\n play(start);\n } else if (playoutRef.current) {\n playoutRef.current.stop();\n }\n } else {\n // It was a drag - finalize the selection\n setSelection(start, end);\n }\n };\n\n // Only show loading if we have tracks WITH clips but haven't loaded their data yet\n // If tracks are empty or all tracks have no clips, render the empty playlist\n const hasClips = tracks.some(track => track.clips.length > 0);\n if (hasClips && (audioBuffers.length === 0 || peaksDataArray.length === 0)) {\n return <div className={className}>Loading waveform...</div>;\n }\n\n return (\n <DevicePixelRatioProvider>\n <PlaylistInfoContext.Provider\n value={{\n samplesPerPixel,\n sampleRate,\n zoomLevels: [samplesPerPixel],\n waveHeight,\n timeScaleHeight,\n duration: displayDuration,\n controls,\n barWidth,\n barGap,\n }}\n >\n <Playlist\n theme={theme}\n backgroundColor={waveformColorToCss(theme.waveOutlineColor)}\n timescaleBackgroundColor={theme.timescaleBackgroundColor}\n scrollContainerWidth={tracksFullWidth + (controls.show ? controls.width : 0)}\n timescaleWidth={tracksFullWidth}\n tracksWidth={tracksFullWidth}\n controlsWidth={controls.show ? controls.width : 0}\n onTracksMouseDown={handleMouseDown}\n onTracksMouseMove={handleMouseMove}\n onTracksMouseUp={handleMouseUp}\n scrollContainerRef={handleScrollContainerRef}\n isSelecting={isSelecting}\n timescale={\n timeScaleHeight > 0 ? (\n <>\n <StyledTimeScale\n duration={displayDuration * 1000}\n marker={10000}\n bigStep={5000}\n secondStep={1000}\n renderTimestamp={renderTimestamp}\n />\n {/* Draggable loop region in timescale - only shown when looping is enabled */}\n {isLoopEnabled && (\n <TimescaleLoopRegion\n startPosition={\n (Math.min(loopStart, loopEnd) * sampleRate) / samplesPerPixel\n }\n endPosition={\n (Math.max(loopStart, loopEnd) * sampleRate) / samplesPerPixel\n }\n markerColor={theme.loopMarkerColor}\n regionColor={theme.loopRegionColor}\n minPosition={0}\n maxPosition={tracksFullWidth}\n controlsOffset={controls.show ? controls.width : 0}\n onLoopRegionChange={(startPixels, endPixels) => {\n const startSeconds = (startPixels * samplesPerPixel) / sampleRate;\n const endSeconds = (endPixels * samplesPerPixel) / sampleRate;\n setLoopRegion(startSeconds, endSeconds);\n }}\n />\n )}\n </>\n ) : undefined\n }\n >\n <>\n {peaksDataArray.map((trackClipPeaks, trackIndex) => {\n // Skip if track doesn't exist (can happen during track deletion transition)\n const track = tracks[trackIndex];\n if (!track) return null;\n\n const trackState = trackStates[trackIndex] || {\n name: `Track ${trackIndex + 1}`,\n muted: false,\n soloed: false,\n volume: 1.0,\n pan: 0,\n };\n\n // Default track controls if not custom renderer provided\n const trackControls = renderTrackControls ? (\n renderTrackControls(trackIndex)\n ) : (\n <Controls onClick={() => selectTrack(trackIndex)}>\n <Header style={{ justifyContent: 'center' }}>\n {trackState.name || `Track ${trackIndex + 1}`}\n </Header>\n <ButtonGroup>\n <Button\n $variant={trackState.muted ? 'danger' : 'outline'}\n onClick={() => setTrackMute(trackIndex, !trackState.muted)}\n >\n Mute\n </Button>\n <Button\n $variant={trackState.soloed ? 'info' : 'outline'}\n onClick={() => setTrackSolo(trackIndex, !trackState.soloed)}\n >\n Solo\n </Button>\n </ButtonGroup>\n <SliderWrapper>\n <VolumeDownIcon />\n <Slider\n min=\"0\"\n max=\"1\"\n step=\"0.01\"\n value={trackState.volume}\n onChange={(e) =>\n setTrackVolume(trackIndex, parseFloat(e.target.value))\n }\n />\n <VolumeUpIcon />\n </SliderWrapper>\n <SliderWrapper>\n <span>L</span>\n <Slider\n min=\"-1\"\n max=\"1\"\n step=\"0.01\"\n value={trackState.pan}\n onChange={(e) =>\n setTrackPan(trackIndex, parseFloat(e.target.value))\n }\n />\n <span>R</span>\n </SliderWrapper>\n </Controls>\n );\n\n // Determine max number of channels across all clips\n // Default to 1 channel (mono) for empty tracks\n const maxChannels = trackClipPeaks.length > 0\n ? Math.max(...trackClipPeaks.map(clip => clip.peaks.data.length))\n : 1;\n\n return (\n <TrackControlsContext.Provider key={track.id} value={trackControls}>\n <TrackComponent\n numChannels={maxChannels}\n backgroundColor={waveformColorToCss(theme.waveOutlineColor)}\n offset={0}\n width={tracksFullWidth}\n hasClipHeaders={showClipHeaders}\n trackId={track.id}\n isSelected={track.id === selectedTrackId}\n >\n {trackClipPeaks.map((clip, clipIndex) => {\n const peaksData = clip.peaks;\n const width = peaksData.length;\n\n return (\n <Clip\n key={`${trackIndex}-${clipIndex}`}\n clipId={clip.clipId}\n trackIndex={trackIndex}\n clipIndex={clipIndex}\n trackName={clip.trackName}\n startSample={clip.startSample}\n durationSamples={clip.durationSamples}\n samplesPerPixel={samplesPerPixel}\n showHeader={showClipHeaders}\n disableHeaderDrag={!interactiveClips}\n isSelected={track.id === selectedTrackId}\n trackId={track.id}\n fadeIn={clip.fadeIn}\n fadeOut={clip.fadeOut}\n sampleRate={sampleRate}\n showFades={showFades}\n touchOptimized={touchOptimized}\n onMouseDown={(e) => {\n // Only select track if clicking on the waveform, not on draggable elements\n const target = e.target as HTMLElement;\n // Check if click is on a draggable element (header or boundary)\n // @dnd-kit sets role=\"button\" and aria-roledescription=\"draggable\" on drag handles\n const isDraggable = target.closest('[role=\"button\"][aria-roledescription=\"draggable\"]');\n if (isDraggable) {\n // Don't select track - let drag event handler take over\n return;\n }\n selectTrack(trackIndex);\n }}\n >\n {peaksData.data.map((channelPeaks: Peaks, channelIndex: number) => (\n <ChannelWithProgress\n key={`${trackIndex}-${clipIndex}-${channelIndex}`}\n index={channelIndex}\n data={channelPeaks}\n bits={peaksData.bits}\n length={width}\n isSelected={track.id === selectedTrackId}\n clipStartSample={clip.startSample}\n clipDurationSamples={clip.durationSamples}\n />\n ))}\n </Clip>\n );\n })}\n {/* Render live recording preview if this track is being recorded */}\n {recordingState?.isRecording &&\n recordingState.trackId === track.id &&\n recordingState.peaks.length > 0 && (\n <Clip\n key={`${trackIndex}-recording`}\n clipId=\"recording-preview\"\n trackIndex={trackIndex}\n clipIndex={trackClipPeaks.length}\n trackName=\"Recording...\"\n startSample={recordingState.startSample}\n durationSamples={recordingState.durationSamples}\n samplesPerPixel={samplesPerPixel}\n showHeader={showClipHeaders}\n disableHeaderDrag={true}\n isSelected={track.id === selectedTrackId}\n trackId={track.id}\n >\n <ChannelWithProgress\n key={`${trackIndex}-recording-0`}\n index={0}\n data={recordingState.peaks}\n bits={16}\n length={Math.floor(recordingState.peaks.length / 2)}\n isSelected={track.id === selectedTrackId}\n clipStartSample={recordingState.startSample}\n clipDurationSamples={recordingState.durationSamples}\n />\n </Clip>\n )}\n </TrackComponent>\n </TrackControlsContext.Provider>\n );\n })}\n {annotations.length > 0 && (\n <AnnotationBoxesWrapper height={30} width={tracksFullWidth}>\n {annotations.map((annotation, index) => {\n const startPosition = (annotation.start * sampleRate) / samplesPerPixel;\n const endPosition = (annotation.end * sampleRate) / samplesPerPixel;\n const label = getAnnotationBoxLabel\n ? getAnnotationBoxLabel(annotation)\n : annotation.id;\n return (\n <AnnotationBox\n key={annotation.id}\n annotationId={annotation.id}\n annotationIndex={index}\n startPosition={startPosition}\n endPosition={endPosition}\n label={label}\n color=\"#ff9800\"\n isActive={annotation.id === activeAnnotationId}\n onClick={() => handleAnnotationClick(annotation)}\n editable={annotationsEditable}\n />\n );\n })}\n </AnnotationBoxesWrapper>\n )}\n {selectionStart !== selectionEnd && (\n <Selection\n startPosition={\n (Math.min(selectionStart, selectionEnd) * sampleRate) / samplesPerPixel +\n (controls.show ? controls.width : 0)\n }\n endPosition={\n (Math.max(selectionStart, selectionEnd) * sampleRate) / samplesPerPixel +\n (controls.show ? controls.width : 0)\n }\n color={theme.selectionColor}\n />\n )}\n {(isPlaying || selectionStart === selectionEnd) && (\n renderPlayhead ? (\n // Custom playhead - pass all animation refs for smooth 60fps animation\n renderPlayhead({\n position: ((currentTimeRef.current ?? 0) * sampleRate) / samplesPerPixel +\n (controls.show ? controls.width : 0),\n color: theme.playheadColor,\n isPlaying,\n currentTimeRef,\n playbackStartTimeRef,\n audioStartPositionRef,\n samplesPerPixel,\n sampleRate,\n controlsOffset: controls.show ? controls.width : 0,\n getAudioContextTime: () => getContext().currentTime,\n })\n ) : (\n <AnimatedPlayhead\n color={theme.playheadColor}\n controlsOffset={controls.show ? controls.width : 0}\n />\n )\n )}\n </>\n </Playlist>\n {annotations.length > 0 && (\n <AnnotationText\n annotations={annotations}\n activeAnnotationId={activeAnnotationId ?? undefined}\n shouldScrollToActive={true}\n editable={annotationsEditable}\n controls={annotationsEditable ? annotationControls : undefined}\n annotationListConfig={{ linkEndpoints, continuousPlay }}\n height={annotationTextHeight}\n renderAnnotationItem={renderAnnotationItem}\n onAnnotationUpdate={(updatedAnnotations) => {\n setAnnotations(updatedAnnotations);\n }}\n />\n )}\n </PlaylistInfoContext.Provider>\n </DevicePixelRatioProvider>\n );\n};\n","import React, { useRef, useEffect } from 'react';\nimport styled from 'styled-components';\nimport { useMediaElementAnimation, useMediaElementData } from '../MediaElementPlaylistContext';\n\nconst PlayheadLine = styled.div<{ $color: string; $width: number }>`\n position: absolute;\n top: 0;\n left: 0;\n width: ${(props) => props.$width}px;\n background: ${(props) => props.$color};\n height: 100%;\n z-index: 100;\n pointer-events: none;\n will-change: transform;\n`;\n\ninterface AnimatedMediaElementPlayheadProps {\n color?: string;\n controlsOffset?: number;\n}\n\n/**\n * Animated playhead for MediaElementPlaylistProvider.\n * Uses the MediaElement context for time tracking instead of Tone.js audio context.\n * Updates position via direct DOM manipulation for smooth 60fps animation.\n */\nexport const AnimatedMediaElementPlayhead: React.FC<AnimatedMediaElementPlayheadProps> = ({\n color = '#ff0000',\n controlsOffset = 0,\n}) => {\n const playheadRef = useRef<HTMLDivElement>(null);\n const animationFrameRef = useRef<number | null>(null);\n\n const { isPlaying, currentTimeRef } = useMediaElementAnimation();\n const { samplesPerPixel, sampleRate, progressBarWidth } = useMediaElementData();\n\n useEffect(() => {\n const updatePosition = () => {\n if (playheadRef.current) {\n // Get current time from the ref (updated by animation loop in context)\n const time = currentTimeRef.current ?? 0;\n const position = (time * sampleRate) / samplesPerPixel + controlsOffset;\n playheadRef.current.style.transform = `translate3d(${position}px, 0, 0)`;\n }\n\n if (isPlaying) {\n animationFrameRef.current = requestAnimationFrame(updatePosition);\n }\n };\n\n if (isPlaying) {\n // Start animation loop\n animationFrameRef.current = requestAnimationFrame(updatePosition);\n } else {\n // When stopped, update once to show final position\n updatePosition();\n }\n\n return () => {\n if (animationFrameRef.current) {\n cancelAnimationFrame(animationFrameRef.current);\n animationFrameRef.current = null;\n }\n };\n }, [isPlaying, sampleRate, samplesPerPixel, controlsOffset, currentTimeRef]);\n\n // Also update position when not playing (for seeks, stops, etc.)\n useEffect(() => {\n if (!isPlaying && playheadRef.current) {\n const time = currentTimeRef.current ?? 0;\n const position = (time * sampleRate) / samplesPerPixel + controlsOffset;\n playheadRef.current.style.transform = `translate3d(${position}px, 0, 0)`;\n }\n });\n\n return <PlayheadLine ref={playheadRef} $color={color} $width={progressBarWidth} data-playhead />;\n};\n","import React, { useRef, useEffect } from 'react';\nimport styled from 'styled-components';\nimport { SmartChannel, type SmartChannelProps, useTheme, usePlaylistInfo, type WaveformPlaylistTheme, waveformColorToCss } from '@waveform-playlist/ui-components';\nimport { useMediaElementAnimation, useMediaElementData } from '../MediaElementPlaylistContext';\n\nconst ChannelWrapper = styled.div`\n position: relative;\n`;\n\ninterface BackgroundProps {\n readonly $color: string;\n readonly $height: number;\n readonly $top: number;\n readonly $width: number;\n}\n\nconst Background = styled.div<BackgroundProps>`\n position: absolute;\n top: ${(props) => props.$top}px;\n left: 0;\n width: ${(props) => props.$width}px;\n height: ${(props) => props.$height}px;\n background: ${(props) => props.$color};\n z-index: 0;\n transform: translateZ(0);\n backface-visibility: hidden;\n will-change: transform;\n`;\n\ninterface ProgressOverlayProps {\n readonly $color: string;\n readonly $height: number;\n readonly $top: number;\n}\n\nconst ProgressOverlay = styled.div<ProgressOverlayProps>`\n position: absolute;\n top: ${(props) => props.$top}px;\n left: 0;\n height: ${(props) => props.$height}px;\n background: ${(props) => props.$color};\n pointer-events: none;\n z-index: 1;\n will-change: width;\n`;\n\nconst ChannelContainer = styled.div`\n position: relative;\n z-index: 2;\n`;\n\nexport interface ChannelWithMediaElementProgressProps extends Omit<SmartChannelProps, 'isSelected'> {\n /** Start sample of the clip containing this channel (for progress calculation) */\n clipStartSample: number;\n /** Duration in samples of the clip */\n clipDurationSamples: number;\n}\n\n/**\n * SmartChannel wrapper for MediaElementPlaylistProvider with animated progress overlay.\n * Uses MediaElement context for time tracking instead of Tone.js audio context.\n */\nexport const ChannelWithMediaElementProgress: React.FC<ChannelWithMediaElementProgressProps> = ({\n clipStartSample,\n clipDurationSamples,\n ...smartChannelProps\n}) => {\n const progressRef = useRef<HTMLDivElement>(null);\n const animationFrameRef = useRef<number | null>(null);\n const theme = useTheme() as WaveformPlaylistTheme;\n const { waveHeight } = usePlaylistInfo();\n\n const { isPlaying, currentTimeRef } = useMediaElementAnimation();\n const { samplesPerPixel, sampleRate } = useMediaElementData();\n\n const progressColor = theme?.waveProgressColor || 'rgba(0, 0, 0, 0.1)';\n\n useEffect(() => {\n const updateProgress = () => {\n if (progressRef.current) {\n // Get current time from the ref\n const currentTime = currentTimeRef.current ?? 0;\n\n // Convert current time to samples\n const currentSample = currentTime * sampleRate;\n\n // Calculate clip bounds in samples\n const clipEndSample = clipStartSample + clipDurationSamples;\n\n // Calculate how much of this clip has been played\n let progressWidth = 0;\n\n if (currentSample <= clipStartSample) {\n // Playhead is before this clip - no progress\n progressWidth = 0;\n } else if (currentSample >= clipEndSample) {\n // Playhead is past this clip - full progress\n progressWidth = smartChannelProps.length;\n } else {\n // Playhead is within this clip - partial progress\n const playedSamples = currentSample - clipStartSample;\n progressWidth = Math.floor(playedSamples / samplesPerPixel);\n }\n\n progressRef.current.style.width = `${progressWidth}px`;\n }\n\n if (isPlaying) {\n animationFrameRef.current = requestAnimationFrame(updateProgress);\n }\n };\n\n if (isPlaying) {\n animationFrameRef.current = requestAnimationFrame(updateProgress);\n } else {\n // When stopped, update once to show final position\n updateProgress();\n }\n\n return () => {\n if (animationFrameRef.current) {\n cancelAnimationFrame(animationFrameRef.current);\n animationFrameRef.current = null;\n }\n };\n }, [isPlaying, sampleRate, samplesPerPixel, clipStartSample, clipDurationSamples, smartChannelProps.length, currentTimeRef]);\n\n // Also update when not playing (for seeks, stops, etc.)\n useEffect(() => {\n if (!isPlaying && progressRef.current) {\n const currentTime = currentTimeRef.current ?? 0;\n const currentSample = currentTime * sampleRate;\n const clipEndSample = clipStartSample + clipDurationSamples;\n\n let progressWidth = 0;\n if (currentSample <= clipStartSample) {\n progressWidth = 0;\n } else if (currentSample >= clipEndSample) {\n progressWidth = smartChannelProps.length;\n } else {\n const playedSamples = currentSample - clipStartSample;\n progressWidth = Math.floor(playedSamples / samplesPerPixel);\n }\n\n progressRef.current.style.width = `${progressWidth}px`;\n }\n });\n\n // Get the draw mode from theme (defaults to 'inverted')\n const drawMode = theme?.waveformDrawMode || 'inverted';\n\n let backgroundColor;\n if (drawMode === 'inverted') {\n // For MediaElement, always treat as selected (single track)\n backgroundColor = theme?.selectedWaveFillColor || theme?.waveFillColor || 'white';\n } else {\n backgroundColor = theme?.selectedWaveOutlineColor || theme?.waveOutlineColor || 'grey';\n }\n\n const backgroundCss = waveformColorToCss(backgroundColor);\n\n return (\n <ChannelWrapper>\n <Background\n $color={backgroundCss}\n $height={waveHeight}\n $top={smartChannelProps.index * waveHeight}\n $width={smartChannelProps.length}\n />\n <ProgressOverlay\n ref={progressRef}\n $color={progressColor}\n $height={waveHeight}\n $top={smartChannelProps.index * waveHeight}\n />\n <ChannelContainer>\n <SmartChannel {...smartChannelProps} isSelected={true} transparentBackground />\n </ChannelContainer>\n </ChannelWrapper>\n );\n};\n","import React, { useRef, useState, useCallback, useMemo } from 'react';\nimport { DndContext } from '@dnd-kit/core';\nimport { restrictToHorizontalAxis } from '@dnd-kit/modifiers';\nimport {\n Playlist,\n Track as TrackComponent,\n Clip,\n Playhead,\n Selection,\n PlaylistInfoContext,\n TrackControlsContext,\n DevicePixelRatioProvider,\n StyledTimeScale,\n useTheme,\n waveformColorToCss,\n} from '@waveform-playlist/ui-components';\nimport {\n AnnotationBoxesWrapper,\n AnnotationBox,\n AnnotationText,\n} from '@waveform-playlist/annotations';\nimport type { RenderAnnotationItemProps } from '@waveform-playlist/annotations';\nimport type { Peaks } from '@waveform-playlist/webaudio-peaks';\nimport {\n useMediaElementAnimation,\n useMediaElementState,\n useMediaElementControls,\n useMediaElementData,\n} from '../MediaElementPlaylistContext';\nimport { useAnnotationDragHandlers } from '../hooks/useAnnotationDragHandlers';\nimport { AnimatedMediaElementPlayhead } from './AnimatedMediaElementPlayhead';\nimport { ChannelWithMediaElementProgress } from './ChannelWithMediaElementProgress';\n\n// Re-export RenderAnnotationItemProps for convenience\nexport type { RenderAnnotationItemProps } from '@waveform-playlist/annotations';\n\nexport interface MediaElementWaveformProps {\n /** Height in pixels for the annotation text list */\n annotationTextHeight?: number;\n /** Custom function to generate the label shown on annotation boxes */\n getAnnotationBoxLabel?: (annotation: { id: string; start: number; end: number; lines: string[] }) => string;\n /**\n * Custom render function for annotation items in the text list.\n * When provided, completely replaces the default annotation item rendering.\n * Use this to customize the appearance of each annotation (e.g., add furigana).\n */\n renderAnnotationItem?: (props: RenderAnnotationItemProps) => React.ReactNode;\n /** Whether annotation boundaries can be edited by dragging. Defaults to false. */\n editable?: boolean;\n /**\n * Callback when annotations are updated (e.g., boundaries dragged).\n * Called with the full updated annotations array.\n */\n onAnnotationUpdate?: (annotations: { id: string; start: number; end: number; lines: string[] }[]) => void;\n className?: string;\n}\n\n/**\n * Simplified Waveform component for MediaElementPlaylistProvider\n *\n * This is a stripped-down version of Waveform that works with the\n * MediaElement context. It supports:\n * - Single track visualization\n * - Click to seek\n * - Annotation display and click-to-play\n * - Playhead animation\n *\n * For multi-track editing, use the full Waveform with WaveformPlaylistProvider.\n */\nexport const MediaElementWaveform: React.FC<MediaElementWaveformProps> = ({\n annotationTextHeight,\n getAnnotationBoxLabel,\n renderAnnotationItem,\n editable = false,\n onAnnotationUpdate,\n className,\n}) => {\n const theme = useTheme() as import('@waveform-playlist/ui-components').WaveformPlaylistTheme;\n\n // MediaElement context hooks\n const { isPlaying, currentTimeRef } = useMediaElementAnimation();\n const { annotations, activeAnnotationId, continuousPlay } = useMediaElementState();\n const { play, seekTo, setActiveAnnotationId, setAnnotations } = useMediaElementControls();\n const {\n duration,\n peaksDataArray,\n sampleRate,\n waveHeight,\n timeScaleHeight,\n samplesPerPixel,\n controls,\n playoutRef,\n barWidth,\n barGap,\n } = useMediaElementData();\n\n const [selectionStart, setSelectionStart] = useState(0);\n const [selectionEnd, setSelectionEnd] = useState(0);\n const [isSelecting, setIsSelecting] = useState(false);\n\n // Local ref for scroll container\n const scrollContainerRef = useRef<HTMLDivElement | null>(null);\n\n // Calculate dimensions\n const tracksFullWidth = Math.floor((duration * sampleRate) / samplesPerPixel);\n\n // Annotation click handler\n const handleAnnotationClick = useCallback(async (annotation: any) => {\n setActiveAnnotationId(annotation.id);\n play(annotation.start);\n }, [setActiveAnnotationId, play]);\n\n // Handle annotation boundary updates\n const handleAnnotationUpdate = useCallback((updatedAnnotations: any[]) => {\n setAnnotations(updatedAnnotations);\n onAnnotationUpdate?.(updatedAnnotations);\n }, [setAnnotations, onAnnotationUpdate]);\n\n // Drag handlers for annotation boundary editing\n const { onDragStart, onDragMove, onDragEnd } = useAnnotationDragHandlers({\n annotations,\n onAnnotationsChange: handleAnnotationUpdate,\n samplesPerPixel,\n sampleRate,\n duration,\n linkEndpoints: true,\n });\n\n // Mouse handlers for click-to-seek\n const handleMouseDown = useCallback((e: React.MouseEvent<HTMLDivElement>) => {\n const rect = (e.currentTarget as HTMLDivElement).getBoundingClientRect();\n const controlWidth = controls.show ? controls.width : 0;\n const x = e.clientX - rect.left - controlWidth;\n const clickTime = (x * samplesPerPixel) / sampleRate;\n\n setIsSelecting(true);\n setSelectionStart(clickTime);\n setSelectionEnd(clickTime);\n }, [controls, samplesPerPixel, sampleRate]);\n\n const handleMouseMove = useCallback((e: React.MouseEvent<HTMLDivElement>) => {\n if (!isSelecting) return;\n\n const rect = (e.currentTarget as HTMLDivElement).getBoundingClientRect();\n const controlWidth = controls.show ? controls.width : 0;\n const x = e.clientX - rect.left - controlWidth;\n const moveTime = (x * samplesPerPixel) / sampleRate;\n\n setSelectionEnd(moveTime);\n }, [isSelecting, controls, samplesPerPixel, sampleRate]);\n\n const handleMouseUp = useCallback((e: React.MouseEvent<HTMLDivElement>) => {\n if (!isSelecting) return;\n\n setIsSelecting(false);\n\n const rect = (e.currentTarget as HTMLDivElement).getBoundingClientRect();\n const controlWidth = controls.show ? controls.width : 0;\n const x = e.clientX - rect.left - controlWidth;\n const endTime = (x * samplesPerPixel) / sampleRate;\n\n const start = Math.min(selectionStart, endTime);\n const end = Math.max(selectionStart, endTime);\n\n // If it's just a click (not a drag), seek to that position\n if (Math.abs(end - start) < 0.1) {\n seekTo(start);\n setSelectionStart(start);\n setSelectionEnd(start);\n\n if (isPlaying && playoutRef.current) {\n playoutRef.current.stop();\n play(start);\n }\n } else {\n // It was a drag - finalize the selection\n setSelectionStart(start);\n setSelectionEnd(end);\n }\n }, [isSelecting, selectionStart, samplesPerPixel, sampleRate, controls, seekTo, isPlaying, playoutRef, play]);\n\n // Show loading if peaks not ready\n if (peaksDataArray.length === 0) {\n return <div className={className}>Loading waveform...</div>;\n }\n\n // Empty track controls (MediaElement is single-track, no mute/solo needed)\n const emptyControls = null;\n\n return (\n <DevicePixelRatioProvider>\n <PlaylistInfoContext.Provider\n value={{\n samplesPerPixel,\n sampleRate,\n zoomLevels: [samplesPerPixel],\n waveHeight,\n timeScaleHeight,\n duration,\n controls,\n barWidth,\n barGap,\n }}\n >\n <Playlist\n theme={theme}\n backgroundColor={waveformColorToCss(theme.waveOutlineColor)}\n timescaleBackgroundColor={theme.timescaleBackgroundColor}\n scrollContainerWidth={tracksFullWidth + (controls.show ? controls.width : 0)}\n timescaleWidth={tracksFullWidth}\n tracksWidth={tracksFullWidth}\n controlsWidth={controls.show ? controls.width : 0}\n onTracksMouseDown={handleMouseDown}\n onTracksMouseMove={handleMouseMove}\n onTracksMouseUp={handleMouseUp}\n scrollContainerRef={(el) => { scrollContainerRef.current = el; }}\n isSelecting={isSelecting}\n timescale={\n timeScaleHeight > 0 ? (\n <StyledTimeScale\n duration={duration * 1000}\n marker={10000}\n bigStep={5000}\n secondStep={1000}\n />\n ) : undefined\n }\n >\n <>\n {peaksDataArray.map((trackClipPeaks, trackIndex) => {\n // For MediaElement, we have a single track with a single clip\n const maxChannels = trackClipPeaks.length > 0\n ? Math.max(...trackClipPeaks.map(clip => clip.peaks.data.length))\n : 1;\n\n return (\n <TrackControlsContext.Provider key={trackIndex} value={emptyControls}>\n <TrackComponent\n numChannels={maxChannels}\n backgroundColor={waveformColorToCss(theme.waveOutlineColor)}\n offset={0}\n width={tracksFullWidth}\n hasClipHeaders={false}\n trackId={`media-element-track-${trackIndex}`}\n isSelected={true}\n >\n {trackClipPeaks.map((clip, clipIndex) => {\n const peaksData = clip.peaks;\n const width = peaksData.length;\n\n return (\n <Clip\n key={`${trackIndex}-${clipIndex}`}\n clipId={clip.clipId}\n trackIndex={trackIndex}\n clipIndex={clipIndex}\n trackName={clip.trackName}\n startSample={clip.startSample}\n durationSamples={clip.durationSamples}\n samplesPerPixel={samplesPerPixel}\n showHeader={false}\n disableHeaderDrag={true}\n isSelected={true}\n trackId={`media-element-track-${trackIndex}`}\n >\n {peaksData.data.map((channelPeaks: Peaks, channelIndex: number) => (\n <ChannelWithMediaElementProgress\n key={`${trackIndex}-${clipIndex}-${channelIndex}`}\n index={channelIndex}\n data={channelPeaks}\n bits={peaksData.bits}\n length={width}\n clipStartSample={clip.startSample}\n clipDurationSamples={clip.durationSamples}\n />\n ))}\n </Clip>\n );\n })}\n </TrackComponent>\n </TrackControlsContext.Provider>\n );\n })}\n {annotations.length > 0 && (\n <DndContext\n onDragStart={onDragStart}\n onDragMove={onDragMove}\n onDragEnd={onDragEnd}\n modifiers={editable ? [restrictToHorizontalAxis] : []}\n >\n <AnnotationBoxesWrapper height={30} width={tracksFullWidth}>\n {annotations.map((annotation, index) => {\n const startPosition = (annotation.start * sampleRate) / samplesPerPixel;\n const endPosition = (annotation.end * sampleRate) / samplesPerPixel;\n const label = getAnnotationBoxLabel\n ? getAnnotationBoxLabel(annotation)\n : annotation.id;\n return (\n <AnnotationBox\n key={annotation.id}\n annotationId={annotation.id}\n annotationIndex={index}\n startPosition={startPosition}\n endPosition={endPosition}\n label={label}\n color=\"#ff9800\"\n isActive={annotation.id === activeAnnotationId}\n onClick={() => handleAnnotationClick(annotation)}\n editable={editable}\n />\n );\n })}\n </AnnotationBoxesWrapper>\n </DndContext>\n )}\n {selectionStart !== selectionEnd && (\n <Selection\n startPosition={\n (Math.min(selectionStart, selectionEnd) * sampleRate) / samplesPerPixel +\n (controls.show ? controls.width : 0)\n }\n endPosition={\n (Math.max(selectionStart, selectionEnd) * sampleRate) / samplesPerPixel +\n (controls.show ? controls.width : 0)\n }\n color={theme.selectionColor}\n />\n )}\n <AnimatedMediaElementPlayhead\n color={theme.playheadColor}\n controlsOffset={controls.show ? controls.width : 0}\n />\n </>\n </Playlist>\n {annotations.length > 0 && (\n <AnnotationText\n annotations={annotations}\n activeAnnotationId={activeAnnotationId ?? undefined}\n shouldScrollToActive={true}\n editable={editable}\n annotationListConfig={{ linkEndpoints: true, continuousPlay }}\n height={annotationTextHeight}\n onAnnotationUpdate={handleAnnotationUpdate}\n renderAnnotationItem={renderAnnotationItem}\n />\n )}\n </PlaylistInfoContext.Provider>\n </DevicePixelRatioProvider>\n );\n};\n"],"names":["linearCurve","length","fadeIn","curve","scale","i","x","exponentialCurve","index","sCurveCurve","phase","logarithmicCurve","base","generateCurve","type","applyFadeIn","param","startTime","duration","startValue","endValue","scaledCurve","range","applyFadeOut","ToneTrack","options","Volume","Panner","Gain","destination","getDestination","cleanup","clipInfos","clipInfo","player","Player","fadeGain","clipPlayer","clipStartTime","clipOffset","audioParam","skipTime","fadeInDuration","remainingFadeDuration","fadeProgress","fadeOutStartInClip","absoluteFadeOutStart","elapsedFadeOut","gain","pan","muted","soloed","when","offset","newPlayer","playbackPosition","clipStart","clipEnd","currentTime","now","remainingDuration","clipDuration","delay","elapsed","stopWhen","lastClip","callback","TonePlayout","Volume2","getDestination2","track","start","trackOptions","optionsWithDestination","toneTrack","trackId","now2","currentSessionId","trackStartTime","bufferOffset","getTransport","hasSoloedTracks","id","manuallyMuted","time","getContext","globalToneContext","getGlobalContext","Context","setContext","resumeGlobalAudioContext","context","CSS","transform","y","scaleX","scaleY","_ref","property","easing","e","a","o","r","p","s","t","c","m","d","l","f","g","w","h","styled","props","BaseButton","styled2","BaseCheckboxWrapper","styled3","BaseCheckbox","BaseCheckboxLabel","BaseControlButton","styled4","BaseInput","styled5","BaseLabel","styled6","ScreenReaderOnly","BaseSelect","styled7","BaseSlider","styled8","AutomaticScrollCheckbox","checked","onChange","disabled","className","handleChange","jsxs","jsx2","isWaveformGradient","color","waveformColorToCss","direction","stops","stop","defaultTheme","MAX_CANVAS_WIDTH","createCanvasFillStyle","ctx","width","height","gradient","Waveform","styled9","Wrapper","Channel","data","bits","devicePixelRatio","waveHeight","waveOutlineColor","waveFillColor","barWidth","barGap","transparentBackground","drawMode","canvasesRef","useRef","canvasRef","useCallback","canvas","index2","useLayoutEffect","canvases","step","globalPixelOffset","h2","maxValue","canvasWidth","fillColor","canvasStartGlobal","canvasEndGlobal","firstBarGlobal","barGlobal","peakIndex","minPeak","maxPeak","min","max","totalWidth","waveformCount","waveforms","currentWidth","waveform","jsx3","backgroundCss","CLIP_HEADER_HEIGHT","HeaderContainer","styled10","TrackName","ClipHeaderPresentational","trackName","isSelected","jsx4","ClipHeader","clipId","trackIndex","clipIndex","disableDrag","dragHandleProps","attributes","listeners","setActivatorNodeRef","CLIP_BOUNDARY_WIDTH","CLIP_BOUNDARY_WIDTH_TOUCH","BoundaryContainer","styled11","ClipBoundary","edge","touchOptimized","isHovered","setIsHovered","React2","isDragging","jsx5","FadeContainer","styled12","FadeSvg","generateFadePath","curveType","points","numPoints","progress","curvedProgress","FadeOverlay","left","theme","useTheme","jsx6","ClipContainer","styled13","ChannelsWrapper","Clip","children","startSample","durationSamples","samplesPerPixel","showHeader","disableHeaderDrag","isOverlay","onMouseDown","fadeOut","sampleRate","showFades","enableDrag","draggableId","setNodeRef","useDraggable","leftBoundaryId","leftBoundaryAttributes","leftBoundaryListeners","setLeftBoundaryActivatorRef","isLeftBoundaryDragging","rightBoundaryId","rightBoundaryAttributes","rightBoundaryListeners","setRightBoundaryActivatorRef","isRightBoundaryDragging","style","jsxs2","jsx7","Fragment","VolumeContainer","styled14","VolumeLabel","VolumeSlider","MasterVolumeControl","volume","jsxs3","jsx8","styled15","Wrapper2","styled16","ScrollContainer","TimescaleWrapper","TracksContainer","ClickOverlay","Playlist","backgroundColor","timescaleBackgroundColor","timescale","timescaleWidth","tracksWidth","scrollContainerWidth","controlsWidth","onTracksClick","onTracksMouseDown","onTracksMouseMove","onTracksMouseUp","scrollContainerRef","isSelecting","jsx10","jsxs5","withTheme","SelectionOverlay","styled17","Selection","startPosition","endPosition","jsx11","styled18","DraggableMarkerHandle","TimescaleLoopShade","LoopRegionMarkers","markerColor","regionColor","onLoopStartChange","onLoopEndChange","onLoopRegionMove","minPosition","maxPosition","draggingMarker","setDraggingMarker","useState","dragStartX","useRef3","dragStartPosition","dragStartEnd","handleMarkerMouseDown","useCallback2","marker","handleMouseMove","moveEvent","delta","newPosition","clampedPosition","handleMouseUp","handleRegionMouseDown","regionWidth","newStart","newEnd","jsxs6","Fragment2","jsx12","TimescaleLoopCreator","TimescaleLoopRegion","onLoopRegionChange","controlsOffset","isCreating","setIsCreating","createStartX","containerRef","hasLoopRegion","handleBackgroundMouseDown","target","rect","clickX","clampedX","currentX","clampedCurrentX","clockFormat","seconds","decimals","hours","minutes","secs","formatTime","format","parseTime","timeStr","parts","TimeInput","label","value","readOnly","displayValue","setDisplayValue","useState2","useEffect2","formatted","newDisplayValue","handleBlur","parsedValue","handleKeyDown","jsxs7","Fragment3","jsx13","SelectionTimeInputs","selectionStart","selectionEnd","onSelectionChange","timeFormat","setTimeFormat","useState3","useEffect3","timeFormatSelect","handleFormatChange","handleStartChange","handleEndChange","jsxs8","Fragment4","jsx14","getScale","DevicePixelRatioContext","createContext","DevicePixelRatioProvider","setScale","useState4","jsx15","useDevicePixelRatio","useContext","PlaylistInfoContext","createContext2","usePlaylistInfo","useContext2","useTheme2","useContext3","ThemeContext","TrackControlsContext","createContext3","jsx16","Fragment5","useTrackControls","useContext4","defaultProgress","defaultIsPlaying","defaultSelectionStart","defaultSelectionEnd","defaultPlayout","createContext4","SmartChannel","jsx18","secondsToPixels","formatTime2","milliseconds","PlaylistTimeScaleScroll","styled19","TimeTicks","TimeStamp","TimeScale","timeColor","bigStep","secondStep","renderTimestamp","canvasInfo","timeMarkers","useRef4","timeScaleHeight","showControls","controlWidth","useContext6","useEffect4","pixLeft","scaleHeight","widthX","pixPerSec","counter","pix","timeMs","timestamp","timestampContent","jsx19","React10","jsxs9","StyledTimeScale","withTheme2","SelectWrapper","styled20","TIME_FORMAT_OPTIONS","TimeFormatSelect","jsx21","option","Container","styled21","ChannelContainer","ControlsWrapper","Track","numChannels","hasClipHeaders","onClick","show","controls","jsxs10","jsx22","Button","styled22","ButtonGroup","styled23","Controls","styled24","Header","styled25","VolumeDownIcon","jsx23","SpeakerLowIcon","VolumeUpIcon","jsx24","SpeakerHighIcon","Slider","styled26","SliderWrapper","styled27","styled28","findMinMax","array","curr","convert","n","v","makeTypedArray","extractPeaks","channel","chanLength","numPeaks","peaks","end","segment","extrema","makeMono","channelPeaks","numChan","weight","extractPeaksFromBuffer","source","isMono","cueIn","cueOut","actualCueOut","slice","generatePeaks","audioBuffer","offsetSamples","WaveformDataChannel","waveformData","channelIndex","sample","values","INT8_MAX","INT8_MIN","INT16_MAX","INT16_MIN","calculateWaveformDataLength","audio_sample_count","data_length","samples_remaining","generateWaveformData","amplitude_scale","split_channels","sample_rate","channels","output_channels","header_size","bytes_per_sample","total_size","buffer","data_view","scale_counter","min_value","max_value","range_min","range_max","_channel","_channel2","_channel3","_channel4","_typeof","isJsonWaveformData","isBinaryWaveformData","isCompatible","view","version","convertJsonToBinary","expected_length","array_buffer","data_object","_i","isNullOrUndefined","decodeBase64","base64","enableUnicode","binaryString","createURL","sourcemapArg","enableUnicodeArg","body","blob","createBase64WorkerFactory","url","WorkerFactory","WaveformData","defaultOptions","getOptions","opts","getChannelData","audio_buffer","createFromAudioBuffer","worker","evt","createFromArrayBuffer","audioContext","audioData","errorCallback","error","promise","WaveformResampler","input_buffer_length_samples","output_buffer_length_samples","output_header_size","count","total","_i2","_i3","resampler","self","otherWaveforms","otherWaveform","combinedBuffer","headerSize","totalSize","totalDataLength","bufferCollection","dataSize","totalBuffer","sourceHeader","totalBufferView","_i4","dataOfTotalBuffer","_i5","_buffer","startIndex","endIndex","output_data","output_dataview","loadWaveformData","src","response","arrayBuffer","json","waveformDataToPeaks","minArray","maxArray","loadPeaksFromWaveformData","getWaveformDataMetadata","extractPeaksFromWaveformData","processedData","sourceScale","parseAeneas","serializeAeneas","annotation","Box","Label","ResizeHandle","AnnotationBox","annotationId","annotationIndex","isActive","editable","leftAttributes","leftListeners","setLeftActivatorRef","isLeftDragging","rightAttributes","rightListeners","setRightActivatorRef","isRightDragging","createPointerDownHandler","dndKitHandler","handleHandleClick","ControlsPlaceholder","BoxesContainer","AnnotationBoxesWrapper","Container3","AnnotationItem","AnnotationHeader","AnnotationInfo","AnnotationIdLabel","TimeRange","AnnotationControls","ControlButton2","AnnotationTextContent","AnnotationTextComponent","annotations","activeAnnotationId","shouldScrollToActive","annotationListConfig","onAnnotationClick","onAnnotationUpdate","renderAnnotationItem","activeAnnotationRef","prevActiveIdRef","useEffect","container","handleScroll","mins","handleTextEdit","newText","updatedAnnotations","handleIdEdit","newId","trimmedId","handleControlClick","control","annotationsCopy","getIconClass","classString","handleClick","idx","AnnotationText2","ContinuousPlayCheckbox","LinkEndpointsCheckbox","BaseCheckboxWrapper2","BaseCheckbox2","BaseCheckboxLabel2","EditableCheckbox","BaseCheckboxWrapper3","BaseCheckbox3","BaseCheckboxLabel3","StyledButton","DownloadAnnotationsButton","filename","handleDownload","jsonData","jsonString","link","jsx9","useTimeFormat","formatTimeUtil","timeString","parseTimeUtil","DEFAULT_ZOOM_LEVELS","useZoomControls","initialSamplesPerPixel","zoomLevels","zoomIndex","setZoomIndex","canZoomIn","canZoomOut","zoomIn","prev","zoomOut","useMasterVolume","playoutRef","initialVolume","onVolumeChange","masterVolume","setMasterVolumeState","setMasterVolume","useMasterAnalyser","fftSize","analyserRef","masterEffects","masterGainNode","_isOffline","analyserNode","Analyser","createClip","name","sourceDurationSamples","generateId","createClipFromSeconds","sourceDuration","createTrack","clips","useAudioTracks","configs","progressive","tracks","setTracks","loading","setLoading","setError","loadedCount","setLoadedCount","totalCount","cancelled","loadedTracksMap","createTrackFromConfig","config","clip","Tone","loadPromises","_","loadedTracks","err","errorMessage","useClipDragHandlers","onTracksChange","originalClipStateRef","React","collisionModifier","args","active","boundary","timeDelta","newStartTime","sortedClips","b","sortedIndex","previousClip","previousEndTime","nextClip","newEndTime","nextClipStartTime","constrainedX","onDragStart","event","onDragMove","sampleDelta","MIN_DURATION_SAMPLES","originalClip","newTracks","tIdx","newClips","cIdx","audioBufferDurationSamples","constrainedDelta","minDeltaForStart","minDeltaForOffset","minDeltaForPrevious","maxDeltaForMinDuration","newOffsetSamples","newDurationSamples","newStartSample","onDragEnd","previousEndSample","LINK_THRESHOLD","useAnnotationDragHandlers","onAnnotationsChange","linkEndpoints","originalAnnotationStateRef","originalState","newTime","updateAnnotationBoundaries","isDraggingStart","shouldLinkEndpoints","constrainedStart","prevAnnotation","constrainedEnd","nextAnnotation","currentIndex","current","next","nextDelta","useDragSensors","touchDelay","touchTolerance","mouseDistance","mouseSensor","useSensor","MouseSensor","touchSensor","TouchSensor","pointerSensor","PointerSensor","useSensors","useClipSplitting","currentTimeRef","usePlaybackAnimation","selectedTrackId","usePlaylistState","splitClipAt","splitTime","clipEndTime","splitSample","splitPixel","clipEndSample","snappedSplitSample","firstClipStartSample","firstClipDurationSamples","secondClipStartSample","secondClipDurationSamples","offsetIncrement","firstClip","secondClip","useKeyboardShortcuts","shortcuts","enabled","matchingShortcut","shortcut","keyMatch","ctrlMatch","shiftMatch","metaMatch","altMatch","getShortcutLabel","isMac","usePlaybackShortcuts","additionalShortcuts","overrideShortcuts","isPlaying","setCurrentTime","play","pause","usePlaylistControls","usePlaylistData","togglePlayPause","stopPlayback","rewindToStart","activeShortcuts","TIME_DELTA","useAnnotationKeyboardControls","onActiveAnnotationChange","continuousPlay","onPlay","activeIndex","useMemo","scrollToAnnotation","containerWidth","startPixel","endPixel","annotationCenter","scrollLeft","visibleStart","visibleEnd","targetScrollLeft","moveStartBoundary","actualDelta","moveEndBoundary","newNextStart","selectPrevious","selectNext","selectFirst","selectLast","clearSelection","playActiveAnnotation","playDuration","activeAnnotationShortcuts","navigationShortcuts","concatenateAudioData","chunks","totalLength","sum","chunk","result","createAudioBuffer","samples","channelCount","typedSamples","peakArray","j","appendPeaks","existingPeaks","newSamples","totalSamplesProcessed","remainder","samplesToComplete","updated","newPeaks2","result2","newPeaks","useRecording","stream","isRecording","setIsRecording","isPaused","setIsPaused","setDuration","setPeaks","setAudioBuffer","level","setLevel","peakLevel","setPeakLevel","workletLoadedRef","workletNodeRef","mediaStreamSourceRef","recordedChunksRef","totalSamplesRef","animationFrameRef","startTimeRef","isRecordingRef","isPausedRef","loadWorklet","workletUrl","_documentCurrentScript","startRecording","workletNode","prevPeaks","updateDuration","stopRecording","allSamples","rawContext","pauseRecording","resumeRecording","useMicrophoneAccess","setStream","devices","setDevices","hasPermission","setHasPermission","isLoading","setIsLoading","enumerateDevices","audioInputs","device","requestAccess","deviceId","audioConstraints","constraints","newStream","stopStream","useMicrophoneLevel","updateRate","smoothingTimeConstant","meterRef","useRef2","sourceRef","resetPeak","isMounted","getContext2","meter","Meter","connect","updateInterval","lastUpdateTime","updateLevel","db","dbValue","normalized","MeterContainer","getLevelGradient","MeterFill","PeakIndicator","ScaleMarkers","ScaleMark","VUMeterComponent","clampedLevel","clampedPeak","jsxs4","useIntegratedRecording","recordingOptions","isMonitoring","setIsMonitoring","selectedDevice","setSelectedDevice","micError","startRec","stopRec","recError","selectedTrackIndex","selectedTrack","currentTimeSamples","lastClipEndSample","endSamples","newClip","requestMicAccess","changeDevice","effectDefinitions","getEffectDefinition","def","getEffectsByCategory","category","effectCategories","effectConstructors","Reverb","Freeverb","JCReverb","FeedbackDelay","PingPongDelay","Chorus","Phaser","Tremolo","Vibrato","AutoPanner","AutoFilter","AutoWah","EQ3","Distortion","BitCrusher","Chebyshev","Compressor","Limiter","Gate","StereoWidener","instanceCounter","generateInstanceId","createEffectInstance","definition","initialParams","Constructor","effect","instanceId","createEffectChain","effects","useDynamicEffects","activeEffects","setActiveEffects","activeEffectsRef","effectInstancesRef","graphNodesRef","rebuildChain","nodes","instances","ae","inst","currentNode","addEffect","effectId","params","instance","newActiveEffect","removeEffect","updateParameter","paramName","toggleBypass","newBypassed","originalWet","reorderEffects","fromIndex","toIndex","newEffects","removed","clearAllEffects","createOfflineEffectsFunction","nonBypassedEffects","offlineInstances","activeEffect","useTrackDynamicEffects","trackEffectsState","setTrackEffectsState","trackEffectInstancesRef","trackGraphNodesRef","rebuildTrackChain","trackEffects","graphEnd","instancesMap","addEffectToTrack","newState","existing","removeEffectFromTrack","updateTrackEffectParameter","trackEffectsStateRef","clearTrackEffects","getTrackEffectsFunction","createOfflineTrackEffectsFunction","encodeWav","bitDepth","numSamples","bytesPerSample","blockAlign","byteRate","writeString","channelData","ch","clampedSample","intSample","str","downloadBlob","useExportWav","isExporting","setIsExporting","setProgress","trackStates","mode","autoDownload","applyEffects","effectsFunction","createOfflineTrackEffects","onProgress","totalDurationSamples","tracksToRender","hasSolo","state","hasOfflineTrackEffects","renderedBuffer","renderWithToneEffects","offlineCtx","scheduledClips","totalClips","scheduleClip","currentProgress","exportFilename","message","_trackStates","Offline","ToneAudioBuffer","transport","trackVolume","gainToDb","trackPan","trackMute","clipGain","toneBuffer","fadeInStart","fadeInEnd","fadeOutStart","fadeOutEnd","trackState","gainNode","baseGain","pannerNode","applyFadeEnvelope","gainParam","endTime","fadeType","expStart","expEnd","logCurve","generateFadeCurve","sCurve","curveValue","PlaybackAnimationContext","PlaylistStateContext","PlaylistControlsContext","PlaylistDataContext","WaveformPlaylistContext","WaveformPlaylistProvider","mono","automaticScroll","userTheme","annotationList","onReady","_onAnnotationUpdate","progressBarWidthProp","progressBarWidth","setAnnotations","setActiveAnnotationIdState","setIsPlaying","audioBuffers","setAudioBuffers","peaksDataArray","setPeaksDataArray","setTrackStates","setSelectionStart","setSelectionEnd","setSelectedTrackId","isAutomaticScroll","setIsAutomaticScroll","setContinuousPlayState","setLinkEndpoints","annotationsEditable","setAnnotationsEditable","isLoopEnabled","setIsLoopEnabledState","loopStart","setLoopStartState","loopEnd","setLoopEndState","playStartPositionRef","trackStatesRef","playbackStartTimeRef","audioStartPositionRef","playbackEndTimeRef","isAutomaticScrollRef","continuousPlayRef","activeAnnotationIdRef","samplesPerPixelRef","isLoopEnabledRef","selectionStartRef","selectionEndRef","loopStartRef","loopEndRef","zoom","setContinuousPlay","setActiveAnnotationId","setLoopEnabled","setLoopRegion","setLoopRegionFromSelection","clearLoopRegion","oldSamplesPerPixel","newSamplesPerPixel","centerPixel","sr","newCenterPixel","newScrollLeft","pendingResumeRef","wasPlaying","resumePosition","buffers","maxDuration","prevStates","playout","currentTrackStates","playableClips","trackObj","clipSampleRate","allTrackPeaks","extractedPeaks","parsedAnnotations","ann","startAnimationLoop","updateTime","currentAnnotation","lastAnnotation","activeAnnotation","pixelPosition","visualPosition","hasValidLoopRegion","timeNow","stopAnimationLoop","currentPos","position","toneStart","actualStartTime","startTimeNow","pauseTime","seekTo","clampedTime","setTrackMute","newStates","setTrackSolo","setTrackVolume","setTrackPan","setSelection","setScrollContainer","element","minimumPlaylistHeight","animationValue","stateValue","controlsValue","dataValue","mergedTheme","ThemeProvider","jsx","useWaveformPlaylist","MediaElementTrack","rate","clampedRate","MediaElementPlayout","_when","adjustedDuration","_trackId","_soloed","MediaElementAnimationContext","MediaElementStateContext","MediaElementControlsContext","MediaElementDataContext","MediaElementPlaylistProvider","initialPlaybackRate","playbackRate","setPlaybackRateState","mediaTrack","clipPeaks","setPlaybackRate","useMediaElementAnimation","useMediaElementState","useMediaElementControls","useMediaElementData","PlayButton","PauseButton","StopButton","RewindButton","FastForwardButton","SkipBackwardButton","skipAmount","SkipForwardButton","LoopButton","defaultEnd","SetLoopRegionButton","hasValidSelection","ZoomInButton","ZoomOutButton","BaseMasterVolumeControl","BaseTimeFormatSelect","PositionDisplay","AudioPosition","timeRef","BaseSelectionTimeInputs","setAutomaticScroll","BaseAutomaticScrollCheckbox","BaseContinuousPlayCheckbox","BaseLinkEndpointsCheckbox","BaseEditableCheckbox","BaseDownloadAnnotationsButton","ExportWavButton","onExportComplete","onExportError","exportWav","handleExport","buttonLabel","PlayheadLine","AnimatedPlayhead","playheadRef","updatePosition","ChannelWrapper","Background","ProgressOverlay","ChannelWithProgress","clipStartSample","clipDurationSamples","smartChannelProps","progressRef","progressColor","updateProgress","currentSample","progressWidth","playedSamples","DEFAULT_EMPTY_TRACK_DURATION","renderTrackControls","renderPlayhead","annotationControls","_annotationListConfig","annotationTextHeight","getAnnotationBoxLabel","showClipHeaders","interactiveClips","recordingState","setIsSelecting","handleScrollContainerRef","displayDuration","recordingEndTime","tracksFullWidth","handleAnnotationClick","selectTrack","handleMouseDown","clickTime","trackY","cumulativeHeight","clickedTrackIndex","trackClipPeaks","trackHeight","moveTime","startPixels","endPixels","startSeconds","endSeconds","trackControls","maxChannels","TrackComponent","peaksData","AnnotationText","AnimatedMediaElementPlayhead","ChannelWithMediaElementProgress","MediaElementWaveform","handleAnnotationUpdate","emptyControls","el","DndContext","restrictToHorizontalAxis"],"mappings":"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","x_google_ignoreList":[1,2,3,4,5,6,7,11]}