zusound
Version:
Sound feedback middleware for Zustand state management
101 lines (86 loc) • 21.5 kB
JavaScript
"use strict";var C=Object.defineProperty;var j=Object.getOwnPropertyDescriptor;var Y=Object.getOwnPropertyNames;var K=Object.prototype.hasOwnProperty;var X=(t,e,n)=>e in t?C(t,e,{enumerable:!0,configurable:!0,writable:!0,value:n}):t[e]=n;var Q=(t,e)=>{for(var n in e)C(t,n,{get:e[n],enumerable:!0})},J=(t,e,n,o)=>{if(e&&typeof e=="object"||typeof e=="function")for(let i of Y(e))!K.call(t,i)&&i!==n&&C(t,i,{get:()=>e[i],enumerable:!(o=j(e,i))||o.enumerable});return t};var ee=t=>J(C({},"__esModule",{value:!0}),t);var l=(t,e,n)=>X(t,typeof e!="symbol"?e+"":e,n);var ce={};Q(ce,{AUDIO_CONFIG:()=>v,AudioContextManager:()=>E,calculateDetailedDiff:()=>O,calculateDiff:()=>z,calculateDiffBase:()=>A,calculateSimpleDiff:()=>M,ensureVisualizerReady:()=>q,hidePersistentVisualizer:()=>F,initSonificationListener:()=>R,playSonicChunk:()=>L,removeSonificationListener:()=>ae,showPersistentVisualizer:()=>P,sonifyChanges:()=>S,visualizeSonicChunk:()=>H,zusound:()=>N});module.exports=ee(ce);var V=require("zustand/shallow"),te={detailed:!1,trackAdded:!0,trackRemoved:!0};function A(t,e,n=te){if(t===e)return{};if(typeof t!="object"||t===null||typeof e!="object"||e===null)return n.detailed?{value:e,type:t===void 0?"add":"change"}:e;let o=new Set([...Object.keys(t),...Object.keys(e)]),i={};for(let r of o){let s=t[r],a=e[r],u=null;!(r in t)&&r in e&&n.trackAdded?u="add":r in t&&!(r in e)&&n.trackRemoved?u="remove":(0,V.shallow)(s,a)||(u="change"),u!==null&&(n.detailed?i[r]={value:a,previousValue:u!=="add"?s:void 0,type:u}:i[r]=a)}return i}function M(t,e){return A(t,e,{detailed:!1})}function O(t,e){return A(t,e,{detailed:!0})}var z=M;var ne=(t,e,n,o,i)=>({diff:i(t,e),timestampStart:n,duration:o-n}),ie=(t,e)=>{try{e(t)}catch(n){console.error("Error in trace middleware 'onTrace' callback:",n)}},oe=(t,e,n)=>{let o=t.setState,{getState:i}=t;return(s,a,u)=>{let g=Date.now(),h=i();o(s,a,u);let x=i(),p=Date.now();if(h===x)return;let c=ne(h,x,g,p,e);ie(c,n)}},U=(t,e={})=>(n,o,i)=>{let{onTrace:r=()=>{},diffFn:s=z}=e,a=oe(i,s,r);return i.setState=a,t(a,o,i)};var B=U;var I=()=>!!(typeof process<"u"&&process.env||(typeof globalThis<"u"?globalThis:{})?.import?.meta?.env?.PROD===!0);var v={BASE_FREQUENCY:110,MIN_DURATION_MS:50,DEFAULT_MAGNITUDE:{CHANGE:.5,REMOVE:.3},SCALE:[1,1.122,1.335,1.498,1.682],STAGGER_DELAY_MS:50};var w=class w{constructor(){l(this,"audioContext",null);l(this,"isAutoplayBlocked",!1);l(this,"hasUserInteracted",!1);if(typeof window<"u"){let e=()=>{this.hasUserInteracted=!0,this.audioContext?.state==="suspended"&&this.tryResumeAudioContext(),window.removeEventListener("click",e,{capture:!0}),window.removeEventListener("keydown",e,{capture:!0}),window.removeEventListener("touchstart",e,{capture:!0})};window.addEventListener("click",e,{capture:!0}),window.addEventListener("keydown",e,{capture:!0}),window.addEventListener("touchstart",e,{capture:!0})}}static getInstance(){return w.instance===null&&(w.instance=new w),w.instance}getContext(){if(this.audioContext===null||this.audioContext.state==="closed"){this.isAutoplayBlocked=!1;try{let e=this.hasUserInteracted?{}:{latencyHint:"interactive"};this.audioContext=new AudioContext(e),this.audioContext.state==="suspended"&&console.warn("AudioContext created in suspended state. Autoplay likely restricted.")}catch(e){this.audioContext=null;let n=e instanceof Error?e.message:String(e);throw console.error("Failed to create AudioContext:",n),new Error(`Web Audio API is not supported or could not be initialized: ${n}`)}}return this.audioContext}isAudioBlocked(){return this.isAutoplayBlocked||!!this.audioContext&&this.audioContext.state==="suspended"}async tryResumeAudioContext(){if(!this.audioContext)try{this.getContext()}catch{return console.error("Cannot resume: AudioContext failed to initialize."),{resumed:!1,blocked:!0}}if(!this.audioContext)return console.error("Cannot resume: AudioContext is null unexpectedly."),{resumed:!1,blocked:!0};if(this.audioContext.state==="closed")return console.warn("Cannot resume: AudioContext is closed."),{resumed:!1,blocked:!1};if(this.audioContext.state==="running")return this.isAutoplayBlocked=!1,{resumed:!0,blocked:!1};if(this.audioContext.state==="suspended"){console.log("Attempting to resume suspended AudioContext...");try{if(!this.audioContext)throw new Error("AudioContext became null before resume");let e=this.audioContext.resume(),n=new Promise((o,i)=>setTimeout(()=>i(new Error("AudioContext resume timed out after 1000ms")),1e3));if(await Promise.race([e,n]),!this.audioContext)throw new Error("AudioContext became null after resume");return console.log(`AudioContext resumed successfully, state: ${this.audioContext.state}`),this.isAutoplayBlocked=!1,{resumed:!0,blocked:!1}}catch(e){let n=e instanceof Error?e.message:String(e);return console.warn(`AudioContext resume failed: ${n}. Autoplay likely blocked.`),this.isAutoplayBlocked=!0,{resumed:!1,blocked:!0}}}return console.warn(`Cannot resume: AudioContext is in an unexpected state: ${this.audioContext?.state}`),{resumed:!1,blocked:this.isAudioBlocked()}}async cleanup(){if(this.audioContext&&this.audioContext.state!=="closed")try{await this.audioContext.close(),console.log("AudioContext closed successfully.")}catch(e){console.warn("Error closing audio context:",e instanceof Error?e.message:String(e))}finally{this.audioContext=null}else this.audioContext=null;this.isAutoplayBlocked=!1}};l(w,"instance",null);var E=w,$=t=>{let e=0;for(let n=0;n<t.length;n++)e=(e<<5)-e+t.charCodeAt(n),e|=0;return Math.abs(e)};function re(t,e){if(!t||Object.keys(t).length===0)return[];let o=((i,r="")=>Object.keys(i).reduce((s,a)=>{let u=r.length?`${r}.`:"";return typeof i[a]=="object"&&i[a]!==null&&Array.isArray(i[a]),s[u+a]=i[a],s},{}))(t);return Object.entries(o).map(([i,r])=>{let s=r==null?"remove":"change",a=$(i),u=Math.floor(a/100)%3,g=a%v.SCALE.length,h=v.BASE_FREQUENCY*Math.pow(2,u)*v.SCALE[g],x=i.split(".").length-1;h*=1+x*.05;let p=0,c=typeof r;s==="change"&&(c==="number"?p=Math.min(Math.log1p(Math.abs(r))*50,600):c==="string"?p=Math.min(Math.log1p(r.length)*25,300):c==="boolean"&&(p=r?25:-25));let m="sine";s==="remove"?m="triangle":c==="number"?m="sine":c==="string"?m="square":c==="boolean"?m="sawtooth":m="triangle";let W=s==="remove"?v.DEFAULT_MAGNITUDE.REMOVE:v.DEFAULT_MAGNITUDE.CHANGE;return{id:i,type:m,valueType:s,frequency:h,magnitude:W,duration:Math.max(e,v.MIN_DURATION_MS),detune:p}})}async function L(t){try{let e=E.getInstance(),n=e.getContext();if(typeof window<"u"){let i=new CustomEvent("zusound",{detail:{chunk:t}});window.dispatchEvent(i)}let o=!1;if(n.state==="running")o=!0;else if(n.state==="suspended"){console.log(`Audio context suspended before playing chunk ${t.id}. Attempting resume...`);let{resumed:i}=await e.tryResumeAudioContext();if(i)o=!0;else return console.warn(`Audio playback skipped for chunk ${t.id} - context still suspended.`),!1}else return console.warn(`Audio context in unexpected state (${n.state}) for chunk ${t.id}. Cannot play.`),!1;if(o&&n.state==="running"){let i=n.currentTime,r=t.duration/1e3,s=n.createOscillator();s.type=t.type,s.frequency.setValueAtTime(t.frequency,i),s.detune.setValueAtTime(t.detune,i);let a=n.createGain();a.gain.setValueAtTime(0,i),s.connect(a),a.connect(n.destination);let u=Math.min(.01,r*.2),g=Math.min(.08,r*.3),h=Math.max(0,r-u-g);return r>.02?(a.gain.exponentialRampToValueAtTime(t.magnitude,i+u),h>.001&&a.gain.setValueAtTime(t.magnitude,i+u+h),a.gain.exponentialRampToValueAtTime(.001,i+r)):(a.gain.linearRampToValueAtTime(t.magnitude,i+r*.5),a.gain.linearRampToValueAtTime(0,i+r)),s.start(i),s.stop(i+r),await new Promise(x=>{let p=!1,c=setTimeout(()=>{if(!p){console.warn(`Oscillator onended for chunk ${t.id} timed out. Force cleaning up.`);try{s.disconnect(),a.disconnect()}catch{}p=!0,x()}},r*1e3+150);s.onended=()=>{if(!p){clearTimeout(c);try{s.disconnect(),a.disconnect()}catch{}p=!0,x()}}}),!0}return!1}catch(e){let n=e instanceof Error?e.message:String(e);return console.error(`Failed to prepare audio for chunk ${t.id}:`,n),!1}}function S(t,e,n=!1){try{let o=re(t,e);if(o.length===0)return;o.forEach((i,r)=>{setTimeout(()=>{L(i).catch(s=>{console.error(`Error during scheduled playback for chunk ${i.id}:`,s)})},r*v.STAGGER_DELAY_MS)})}catch(o){console.error("Sonification setup failed:",o instanceof Error?o.message:String(o))}}function k(t){if(t instanceof CustomEvent&&t.type==="zusound:trace"&&t.detail?.traceData){let n=t.detail.traceData,{diff:o,duration:i}=n;o&&typeof o=="object"&&S(o,i)}}function R(){typeof window<"u"&&(window.removeEventListener("zusound:trace",k),window.addEventListener("zusound:trace",k))}function ae(){typeof window<"u"&&window.removeEventListener("zusound:trace",k)}function se(t){if(typeof window<"u"){let e=new CustomEvent("zusound:trace",{detail:{traceData:t}});window.dispatchEvent(e)}}var N=(t,e={})=>{let{enabled:n=!I(),logDiffs:o=!1,allowInProduction:i=!1,onTrace:r,diffFn:s,initSonification:a=!0,...u}=e,g=I();if(!n||g&&!i)return t;typeof window<"u"&&a&&setTimeout(()=>{try{R()}catch(c){console.error("Error initializing sonification:",c)}},0);let p={...u,diffFn:s,onTrace:c=>{if(se(c),r)try{r(c)}catch(m){console.error("Error in user-provided 'onTrace' callback:",m)}}};if(o){typeof window<"u"&&!window.__zusound_logger__&&(window.__zusound_logger__=[]);let c=p.onTrace;p.onTrace=m=>{typeof window<"u"&&window.__zusound_logger__&&window.__zusound_logger__.push({...m}),c(m)}}return B(t,p)};var D=class{constructor(e,n){l(this,"canvas");l(this,"gl",null);l(this,"program",null);l(this,"uniforms",{});l(this,"vertexBuffer",null);l(this,"vertexShaderSource",`
attribute vec2 a_position;
varying vec2 v_texCoord;
void main() {
gl_Position = vec4(a_position, 0.0, 1.0);
v_texCoord = a_position * 0.5 + 0.5; // Map position to texture coordinates
}
`);l(this,"fragmentShaderSource",`
precision mediump float;
varying vec2 v_texCoord;
uniform int u_eventCount;
uniform float u_eventProgress[${10}];
uniform float u_eventFrequency[${10}];
uniform float u_eventMagnitude[${10}];
uniform float u_eventDetune[${10}];
uniform int u_eventType[${10}]; // 0=sine, 1=square, 2=sawtooth, 3=triangle
// Function to get color based on waveform type
vec3 getTypeColor(int type) {
if (type == 0) return vec3(0.2, 0.6, 1.0); // sine - blue
if (type == 1) return vec3(1.0, 0.5, 0.2); // square - orange
if (type == 2) return vec3(0.2, 1.0, 0.5); // sawtooth - green
return vec3(1.0, 0.3, 0.8); // triangle - pink
}
// Function to simulate wave shape based on type
float getWaveShape(int type, float t) {
t = fract(t); // Use fractional part for repeating pattern
if (type == 0) return 0.5 + 0.5 * sin(t * 6.28318); // Sine wave
if (type == 1) return t < 0.5 ? 0.0 : 1.0; // Square wave
if (type == 2) return t; // Sawtooth wave
return t < 0.5 ? t * 2.0 : 2.0 - t * 2.0; // Triangle wave
}
void main() {
vec2 p = (v_texCoord * 2.0 - 1.0); // Map texture coords to -1 to 1 range
vec3 color = vec3(0.1, 0.1, 0.15); // Base background color
float alpha = 1.0; // Base alpha
// Add subtle background glow towards the center
float bgGlow = 1.0 - length(p);
color += vec3(0.05, 0.05, 0.1) * max(0.0, bgGlow);
// Loop through active events and layer their effects
for (int i = 0; i < ${10}; i++) {
if (i >= u_eventCount) break; // Stop if we've processed all active events
if (u_eventProgress[i] >= 1.0) continue; // Skip completed events
// Get event properties from uniforms
float progress = u_eventProgress[i];
float magnitude = u_eventMagnitude[i];
float frequency = u_eventFrequency[i] / 440.0; // Normalize frequency (relative to A4)
float detune = u_eventDetune[i] / 1200.0; // Convert cents to octave fraction
float scaledFreq = frequency * pow(2.0, detune); // Apply detune
int type = u_eventType[i];
// Calculate visibility based on progress (fade in/out)
float fadeIn = smoothstep(0.0, 0.1, progress);
float fadeOut = 1.0 - smoothstep(0.7, 1.0, progress);
float visibility = fadeIn * fadeOut;
// Calculate effect based on distance from center and wave shape
float dist = length(p);
float ringWidth = 0.05 * magnitude; // Ring width depends on magnitude
float ringSize = 0.3 + 0.7 * (1.0 - progress); // Ring expands outwards as progress decreases
// Create a smooth ring shape
float ring = smoothstep(ringSize - ringWidth, ringSize, dist) *
smoothstep(ringSize + ringWidth, ringSize, dist);
// Add ripples based on wave shape and frequency
float ripples = getWaveShape(type, dist * 10.0 * scaledFreq);
// Combine ring and ripples, apply visibility and magnitude
vec3 eventColor = getTypeColor(type);
float eventEffect = (ring * 0.8 + ripples * 0.2) * visibility * magnitude;
// Add event's color contribution
color += eventColor * eventEffect;
}
gl_FragColor = vec4(color, alpha);
}
`);this.canvas=document.createElement("canvas"),this.canvas.width=e,this.canvas.height=n,this.canvas.style.display="block",this.canvas.style.borderRadius="50%"}getCanvasElement(){return this.canvas}initialize(){if(this.gl)return!0;if(typeof window>"u")return!1;try{if(this.gl=this.canvas.getContext("webgl",{alpha:!0,antialias:!0}),!this.gl)return console.error("WebGL not supported or context creation failed."),!1;let e=this.compileShader(this.gl.VERTEX_SHADER,this.vertexShaderSource),n=this.compileShader(this.gl.FRAGMENT_SHADER,this.fragmentShaderSource);if(!e||!n)return!1;if(this.program=this.gl.createProgram(),!this.program)return console.error("Failed to create WebGL program."),!1;if(this.gl.attachShader(this.program,e),this.gl.attachShader(this.program,n),this.gl.linkProgram(this.program),!this.gl.getProgramParameter(this.program,this.gl.LINK_STATUS))return console.error("Could not link WebGL program:",this.gl.getProgramInfoLog(this.program)),this.gl.deleteProgram(this.program),this.program=null,!1;this.gl.useProgram(this.program);let o=[-1,-1,1,-1,-1,1,1,1];this.vertexBuffer=this.gl.createBuffer(),this.gl.bindBuffer(this.gl.ARRAY_BUFFER,this.vertexBuffer),this.gl.bufferData(this.gl.ARRAY_BUFFER,new Float32Array(o),this.gl.STATIC_DRAW);let i=this.gl.getAttribLocation(this.program,"a_position");this.gl.enableVertexAttribArray(i),this.gl.vertexAttribPointer(i,2,this.gl.FLOAT,!1,0,0),this.uniforms.u_eventCount=this.gl.getUniformLocation(this.program,"u_eventCount");for(let r=0;r<10;r++)this.uniforms[`u_eventProgress[${r}]`]=this.gl.getUniformLocation(this.program,`u_eventProgress[${r}]`),this.uniforms[`u_eventFrequency[${r}]`]=this.gl.getUniformLocation(this.program,`u_eventFrequency[${r}]`),this.uniforms[`u_eventMagnitude[${r}]`]=this.gl.getUniformLocation(this.program,`u_eventMagnitude[${r}]`),this.uniforms[`u_eventDetune[${r}]`]=this.gl.getUniformLocation(this.program,`u_eventDetune[${r}]`),this.uniforms[`u_eventType[${r}]`]=this.gl.getUniformLocation(this.program,`u_eventType[${r}]`);return!0}catch(e){return console.error("Failed to initialize WebGL shader manager:",e),this.cleanupPartialInit(),!1}}compileShader(e,n){if(!this.gl)return null;let o=this.gl.createShader(e);return o?(this.gl.shaderSource(o,n),this.gl.compileShader(o),this.gl.getShaderParameter(o,this.gl.COMPILE_STATUS)?o:(console.error(`Shader compile error (${e===this.gl.VERTEX_SHADER?"Vertex":"Fragment"}):`,this.gl.getShaderInfoLog(o)),this.gl.deleteShader(o),null)):(console.error("Failed to create shader object."),null)}render(e){if(!this.gl||!this.program)return;this.gl.clearColor(0,0,0,0),this.gl.clear(this.gl.COLOR_BUFFER_BIT),this.gl.useProgram(this.program),this.gl.bindBuffer(this.gl.ARRAY_BUFFER,this.vertexBuffer);let n=this.gl.getAttribLocation(this.program,"a_position");this.gl.enableVertexAttribArray(n),this.gl.vertexAttribPointer(n,2,this.gl.FLOAT,!1,0,0),this.updateUniforms(e),this.gl.drawArrays(this.gl.TRIANGLE_STRIP,0,4)}updateUniforms(e){if(!this.gl||!this.program)return;this.gl.uniform1i(this.uniforms.u_eventCount,e.length);let n={sine:0,square:1,sawtooth:2,triangle:3};for(let o=0;o<10;o++){let i=this.uniforms[`u_eventProgress[${o}]`],r=this.uniforms[`u_eventFrequency[${o}]`],s=this.uniforms[`u_eventMagnitude[${o}]`],a=this.uniforms[`u_eventDetune[${o}]`],u=this.uniforms[`u_eventType[${o}]`];if(o<e.length){let g=e[o],h=g.chunk;this.gl.uniform1f(i,g.getProgress()),this.gl.uniform1f(r,h.frequency),this.gl.uniform1f(s,h.magnitude),this.gl.uniform1f(a,h.detune),this.gl.uniform1i(u,n[h.type]??3)}else this.gl.uniform1f(i,1)}}cleanup(){if(this.stopRenderLoop(),this.gl){this.program&&(this.vertexBuffer&&this.gl.deleteBuffer(this.vertexBuffer),this.gl.deleteProgram(this.program));let e=this.gl.getExtension("WEBGL_lose_context");e&&e.loseContext()}this.cleanupPartialInit()}cleanupPartialInit(){this.gl=null,this.program=null,this.vertexBuffer=null,this.uniforms={}}startRenderLoop(){}stopRenderLoop(){}};var T=class T{constructor(){l(this,"shaderManager",null);l(this,"isInitialized",!1);l(this,"eventListenerAttached",!1);l(this,"isMounted",!1);l(this,"animationFrameId",null);l(this,"events",[]);l(this,"handleSonificationEvent",e=>{this.isZusoundEvent(e)&&e.detail?.chunk&&this.addEvent(e.detail.chunk)})}static getInstance(){return T.instance||(T.instance=new T,T.instance.initialize(),T.instance.attachEventListener()),T.instance}initialize(){if(this.isInitialized)return!0;if(typeof window>"u")return console.warn("Visualizer cannot initialize outside of a browser environment."),!1;try{return this.shaderManager=new D(64,64),this.isInitialized=this.shaderManager.initialize(),this.isInitialized||(console.error("Visualizer Shader Manager failed to initialize."),this.shaderManager=null),this.isInitialized}catch(e){return console.error("Error during visualizer initialization:",e),this.shaderManager=null,this.isInitialized=!1,!1}}getCanvasElement(){return!this.isInitialized&&!this.initialize()?null:this.shaderManager?.getCanvasElement()??null}notifyMounted(){if(!this.isInitialized){console.warn("Visualizer cannot be mounted before initialization.");return}this.isMounted=!0,this.startRenderLoop()}notifyUnmounted(){this.isMounted=!1,this.stopRenderLoop()}addEvent(e){if(!this.isInitialized&&!this.initialize()){console.warn("Visualizer not initialized, cannot add event.");return}let n=performance.now(),o={chunk:e,startTime:n,getProgress:()=>Math.min(1,(performance.now()-o.startTime)/1e3)};this.events.push(o),this.events.length>10&&this.events.shift(),this.isMounted&&this.startRenderLoop()}startRenderLoop(){if(this.animationFrameId!==null||!this.isMounted||!this.isInitialized)return;let e=()=>{if(!this.isMounted||!this.isInitialized||!this.shaderManager){this.animationFrameId=null;return}this.events=this.events.filter(n=>n.getProgress()<1),this.shaderManager.render(this.events),this.isMounted&&this.events.length>0?this.animationFrameId=requestAnimationFrame(e):this.animationFrameId=null};this.animationFrameId=requestAnimationFrame(e)}stopRenderLoop(){this.animationFrameId!==null&&(cancelAnimationFrame(this.animationFrameId),this.animationFrameId=null)}isZusoundEvent(e){return e instanceof CustomEvent&&e.type==="zusound"&&"detail"in e}attachEventListener(){this.eventListenerAttached||typeof window>"u"||(window.addEventListener("zusound",this.handleSonificationEvent),this.eventListenerAttached=!0)}detachEventListener(){!this.eventListenerAttached||typeof window>"u"||(window.removeEventListener("zusound",this.handleSonificationEvent),this.eventListenerAttached=!1)}cleanup(){this.stopRenderLoop(),this.detachEventListener(),this.shaderManager?.cleanup(),this.isInitialized=!1,this.isMounted=!1,this.shaderManager=null,this.events=[]}};l(T,"instance",null);var b=T;var G=null,ue=null,de=!1,d=null,_=!1;function P(){if(_||typeof document>"u")return;let t=b.getInstance(),e=t.getCanvasElement();if(!e){console.error("Visualizer canvas unavailable. Cannot show persistent UI.");return}de&&G&&G.contains(e)&&(t.notifyUnmounted(),ue?.removeChild(e)),d=document.createElement("div"),d.style.cssText=`
position: fixed;
top: 20px;
right: 20px;
background: rgba(30, 30, 40, 0.8);
border-radius: 50%; /* Keep the round shape */
z-index: 9999;
box-shadow: 0 4px 12px rgba(0, 0, 0, 0.3);
width: ${e.width}px;
height: ${e.height}px;
transition: transform 0.3s ease, box-shadow 0.3s ease, opacity 0.3s ease;
cursor: pointer;
opacity: 0.8;
transform: scale(1);
`,d.addEventListener("mouseenter",()=>{d&&(d.style.transform="scale(1.1)",d.style.boxShadow="0 6px 16px rgba(0, 0, 0, 0.4)",d.style.opacity="1")}),d.addEventListener("mouseleave",()=>{d&&(d.style.transform="scale(1)",d.style.boxShadow="0 4px 12px rgba(0, 0, 0, 0.3)",d.style.opacity="0.8")}),d.appendChild(e),document.body.appendChild(d),t.notifyMounted(),_=!0}function F(){if(!_||!d)return;let t=b.getInstance(),e=t.getCanvasElement();e&&d.contains(e)&&t.notifyUnmounted(),d.parentNode&&d.parentNode.removeChild(d),d=null,_=!1}function q(){b.getInstance()}function H(t){if(typeof window<"u"){let e=new CustomEvent("zusound",{detail:{chunk:t}});window.dispatchEvent(e)}else console.warn("Cannot visualizeSonicChunk outside of a browser environment.")}
//# sourceMappingURL=index.umd.js.map