UNPKG

vanta-react

Version:

React components for Vanta.js animated backgrounds with TypeScript support - CDN optimized with automatic library loading

8 lines (7 loc) 15.2 kB
"use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const r=require("react");let I=!1,N=!1,we=!1,b=null,C=null;const W={THREE:"https://cdn.jsdelivr.net/npm/three@0.134.0/build/three.min.js",P5:"https://cdn.jsdelivr.net/npm/p5@1.1.9/lib/p5.min.js",VANTA_BASE:"https://cdn.jsdelivr.net/npm/vanta@latest/dist/"},B=()=>new Promise((e,t)=>{if(I&&window.THREE){e(window.THREE);return}if(b){b.addEventListener("load",()=>{e(window.THREE)}),b.addEventListener("error",t);return}b=document.createElement("script"),b.src=W.THREE,b.onload=()=>{I=!0,window.THREE?e(window.THREE):t(new Error("Three.js failed to load properly from CDN"))},b.onerror=()=>{t(new Error("Failed to load Three.js from CDN"))},document.head.appendChild(b)}),O=()=>new Promise((e,t)=>{if(N&&window.p5){e(window.p5);return}if(C){C.addEventListener("load",()=>{e(window.p5)}),C.addEventListener("error",t);return}C=document.createElement("script"),C.src=W.P5,C.onload=()=>{N=!0,window.p5?e(window.p5):t(new Error("p5.js failed to load properly from CDN"))},C.onerror=()=>{t(new Error("Failed to load p5.js from CDN"))},document.head.appendChild(C)}),L=e=>new Promise((t,n)=>{const o=`${W.VANTA_BASE}vanta.${e}.min.js`,i=window.VANTA;if(i!=null&&i[e.toUpperCase()]){t(i[e.toUpperCase()]);return}const c=document.createElement("script");c.src=o,c.onload=()=>{const f=window.VANTA,d=f==null?void 0:f[e.toUpperCase()];d?t(d):n(new Error(`Failed to load Vanta effect: ${e}`))},c.onerror=()=>{n(new Error(`Failed to load Vanta effect from CDN: ${e}`))},document.head.appendChild(c)}),me=async(e=!1)=>{const t=[B()];e&&t.push(O());const n=await Promise.all(t),o=n[0],i=e?n[1]:void 0;return{THREE:o,...e&&{p5:i}}},ye=()=>({threeLoaded:I,p5Loaded:N,vantaLoaded:we,threeAvailable:!!window.THREE,p5Available:!!window.p5,vantaAvailable:!!window.VANTA}),ae=["birds","cells","clouds","clouds2","dots","fog","globe","halo","net","rings","ripple","topology","trunk","waves"],Ee=async()=>{const e=ae.map(t=>L(t).catch(()=>null));await Promise.all(e)},P={},A={},G=async e=>{const t=e.toLowerCase();if(P[t])return P[t];if(t in A)return A[t];const n=(async()=>{try{const o=await L(t);if(o&&typeof o=="function")return P[t]=o,o;throw new Error(`Invalid effect creator received for "${t}"`)}catch{return null}finally{delete A[t]}})();return A[t]=n,n},he=()=>["birds","cells","clouds","clouds2","dots","fog","globe","halo","net","rings","ripple","topology","trunk","waves"],ge=()=>Object.keys(P),be=()=>{Object.keys(P).forEach(e=>{delete P[e]}),Object.keys(A).forEach(e=>{delete A[e]})};let z=!1,R=null,m=null;const _=async()=>z?Promise.resolve():R||(m&&(m=null),R=(async()=>{try{const e=[B().catch(o=>{throw new Error(`Failed to load THREE.js: ${o.message}`)}),O().catch(o=>{throw new Error(`Failed to load p5.js: ${o.message}`)})],[t,n]=await Promise.all(e);if(t&&typeof window<"u")window.THREE=t;else throw new Error("Failed to load THREE.js properly from CDN");if(n&&typeof window<"u")window.p5=n;else throw new Error("Failed to load p5.js properly from CDN");if(typeof window<"u"&&window.THREE&&window.p5)z=!0;else throw new Error("Library assignment verification failed")}catch(e){throw m=e instanceof Error?e:new Error("Unknown CDN preload error"),m}})(),R),D=()=>typeof window>"u"?!1:z&&!!window.THREE&&!!window.p5,ie=()=>{if(typeof window>"u"||!window.THREE)throw new Error("THREE.js is not preloaded from CDN. Call preloadLibraries() first.");return window.THREE},se=()=>{if(typeof window>"u"||!window.p5)throw new Error("p5.js is not preloaded from CDN. Call preloadLibraries() first.");return window.p5},Ce=()=>({isPreloaded:z,isLoading:!!R&&!z,hasError:!!m,error:(m==null?void 0:m.message)||null,threeAvailable:!!(typeof window<"u"&&window.THREE),p5Available:!!(typeof window<"u"&&window.p5),loadSource:"CDN"}),ve=()=>{z=!1,R=null,m=null,typeof window<"u"&&(window.THREE=void 0,window.p5=void 0)},xe=()=>r.createElement("div",{style:{display:"flex",flexDirection:"column",alignItems:"center",justifyContent:"center",height:"100%",padding:"20px",backgroundColor:"var(--vanta-loading-bg, rgba(0, 0, 0, 0.1))",color:"var(--vanta-loading-text, #666)",fontFamily:"system-ui, -apple-system, sans-serif"}},r.createElement("div",{style:{width:"40px",height:"40px",border:"3px solid var(--vanta-loading-border, #e0e0e0)",borderTop:"3px solid var(--vanta-loading-accent, #007bff)",borderRadius:"50%",animation:"vanta-spin 1s linear infinite",marginBottom:"16px"}}),r.createElement("style",null,` @keyframes vanta-spin { 0% { transform: rotate(0deg); } 100% { transform: rotate(360deg); } } `),r.createElement("p",{style:{margin:0,fontSize:"14px",textAlign:"center"}},"🌐 Vanta 라이브러리 로딩 중...")),Te=({error:e,onRetry:t})=>r.createElement("div",{style:{display:"flex",flexDirection:"column",alignItems:"center",justifyContent:"center",height:"100%",padding:"20px",backgroundColor:"var(--vanta-error-bg, rgba(255, 0, 0, 0.05))",color:"var(--vanta-error-text, #d32f2f)",fontFamily:"system-ui, -apple-system, sans-serif",textAlign:"center"}},r.createElement("div",{style:{fontSize:"48px",marginBottom:"16px"}},"⚠️"),r.createElement("h3",{style:{margin:"0 0 12px 0",fontSize:"16px",fontWeight:"600"}},"Vanta 라이브러리 로딩 실패"),r.createElement("p",{style:{margin:"0 0 20px 0",fontSize:"14px",opacity:.8,maxWidth:"300px"}},e),r.createElement("button",{onClick:t,style:{padding:"8px 16px",backgroundColor:"var(--vanta-error-button-bg, #d32f2f)",color:"var(--vanta-error-button-text, white)",border:"none",borderRadius:"4px",fontSize:"14px",fontWeight:"500",cursor:"pointer",transition:"background-color 0.2s ease"},onMouseOver:n=>{n.currentTarget.style.backgroundColor="var(--vanta-error-button-hover, #b71c1c)"},onMouseOut:n=>{n.currentTarget.style.backgroundColor="var(--vanta-error-button-bg, #d32f2f)"}},"🔄 다시 시도")),Ve=({effect:e,options:t,className:n="",style:o,background:i=!1,autoLoad:c=!0,loadingComponent:f,errorComponent:d,retryCount:F=3,retryDelay:x=1e3,onLoadStart:M,onLoadSuccess:y,onLoadError:E})=>{const s=r.useRef(null),u=r.useRef(null),[de,J]=r.useState(!1),[K,T]=r.useState(null),[S,p]=r.useState("idle"),[Q,H]=r.useState(null),[X,Y]=r.useState(0),Z=r.useMemo(()=>t,[t]),j=r.useMemo(()=>["trunk","topology","dots"].includes(e),[e]),ee=r.useCallback(()=>()=>{if(s.current&&u.current){const a=u.current;a.style.width="100vw",a.style.height="100vh",s.current.resize&&s.current.resize()}},[]),te=r.useCallback(async()=>{if(!(X>=F)){Y(a=>a+1),H(null),p("loading");try{await new Promise(a=>setTimeout(a,x)),await _(),p("success"),y==null||y()}catch(a){const h=a instanceof Error?a.message:"Unknown library loading error";H(h),p("error"),E==null||E(h)}}},[X,F,x,y,E]);r.useEffect(()=>{if(!c){D()?p("success"):(p("error"),H("Libraries not preloaded. Please call preloadLibraries() manually or set autoLoad=true."));return}if(D()){p("success");return}let a=!0;return(async()=>{if(a){p("loading"),H(null),Y(0),M==null||M();try{await _(),a&&(p("success"),y==null||y())}catch(U){if(a){const l=U instanceof Error?U.message:"Unknown library loading error";H(l),p("error"),E==null||E(l)}}}})(),()=>{a=!1}},[c,M,y,E]),r.useEffect(()=>{if(S!=="success")return;let a=!0,h=null;return h||(h=(async()=>{if(!(!u.current||!e)){if(s.current){try{s.current.destroy()}catch(l){console.warn("[Vanta] Error destroying previous effect:",l)}s.current=null}a&&(J(!0),T(null));try{let g=0;for(;g<5&&a&&!D();)g===0&&console.warn("[Vanta] Libraries are not preloaded. Ensure preloadLibraries() is called before using Vanta components."),g++,await new Promise(V=>setTimeout(V,100*g));if(!D()&&a){T("Libraries not ready after multiple attempts. Please ensure preloadLibraries() is called.");return}let re,ne;try{re=ie(),j&&(ne=se())}catch(V){a&&T(`Library access error: ${V instanceof Error?V.message:"Unknown error"}`);return}const $=await G(e);if(!$&&a){T(`Effect "${e}" not found`);return}if(a&&u.current&&$){if(i&&u.current){const w=u.current;w.style.position="fixed",w.style.top="0",w.style.left="0",w.style.width="100vw",w.style.height="100vh",w.style.zIndex="-10",w.offsetHeight}const V={el:u.current,THREE:re,...j&&{p5:ne},mouseControls:!0,touchControls:!0,gyroControls:!1,minHeight:i?window.innerHeight:200,minWidth:i?window.innerWidth:200,scale:1,scaleMobile:1,...Z};if(s.current=$(V),!s.current&&a){T(`Failed to create effect "${e}"`);return}if(i&&s.current&&a){const w=setTimeout(()=>{if(s.current&&u.current&&a)try{s.current.resize&&s.current.resize()}catch(pe){console.warn("[Vanta] Resize error:",pe)}},100),oe=ee();window.addEventListener("resize",oe);const ue=()=>{window.removeEventListener("resize",oe),clearTimeout(w)};s.current._customCleanup=ue}}}catch(l){console.error(`Vanta.js effect "${e}" failed to initialize:`,l),a&&T(`Failed to initialize effect "${e}"`)}finally{a&&J(!1)}}})()),()=>{if(a=!1,h)h.finally(()=>{if(s.current){const l=s.current;if(l._customCleanup)try{l._customCleanup()}catch(g){console.warn("[Vanta] Cleanup error:",g)}try{s.current.destroy()}catch(g){console.warn("[Vanta] Destroy error:",g)}s.current=null}});else if(s.current){try{const l=s.current;l._customCleanup&&l._customCleanup(),s.current.destroy()}catch(l){console.warn("[Vanta] Cleanup error:",l)}s.current=null}}},[e,Z,i,ee,j,S]);const fe=i?"fixed inset-0 w-screen h-screen -z-10":"w-full h-full";return K&&console.warn(`Vanta effect load error: ${K}`),S==="loading"?f||r.createElement(xe,null):S==="error"?typeof d=="function"?d(Q||"Unknown error",te):d||r.createElement(Te,{error:Q||"Unknown error",onRetry:te}):S!=="success"?null:r.createElement("div",{ref:u,className:`${fe} ${n}`,style:{opacity:de?.7:1,transition:"opacity 0.3s ease-in-out",...i&&{top:0,left:0,width:"100vw",height:"100vh",overflow:"hidden"},...o}})};class Ae extends r.Component{constructor(t){super(t),this.retryTimeoutId=null,this.handleRetry=()=>{this.setState({hasError:!1,error:null,errorInfo:null})},this.handleRetryWithDelay=()=>{this.retryTimeoutId=window.setTimeout(()=>{this.handleRetry()},1e3)},this.state={hasError:!1,error:null,errorInfo:null}}static getDerivedStateFromError(t){return{hasError:!0,error:t}}componentDidCatch(t,n){this.setState({error:t,errorInfo:n}),console.error("Vanta Error Boundary caught an error:",t),console.error("Error Info:",n),this.props.onError&&this.props.onError(t,n),(t.message.includes("ReactDebugCurrentFrame")||t.message.includes("React"))&&console.warn("React lifecycle error detected. This might be related to library loading timing.")}componentWillUnmount(){this.retryTimeoutId&&window.clearTimeout(this.retryTimeoutId)}render(){return this.state.hasError?this.props.fallback?this.props.fallback:r.createElement("div",{style:{display:"flex",flexDirection:"column",alignItems:"center",justifyContent:"center",height:"200px",padding:"20px",backgroundColor:"#f8f9fa",border:"1px solid #e9ecef",borderRadius:"8px",textAlign:"center",fontFamily:"Arial, sans-serif",color:"#495057"}},r.createElement("div",{style:{fontSize:"48px",marginBottom:"16px",color:"#dc3545"}},"⚠️"),r.createElement("h3",{style:{margin:"0 0 12px 0",fontSize:"18px",color:"#dc3545"}},"Vanta Effect Error"),r.createElement("p",{style:{margin:"0 0 16px 0",fontSize:"14px",color:"#6c757d",maxWidth:"400px",lineHeight:"1.4"}},"Something went wrong while loading the Vanta effect. This might be due to library loading issues."),typeof window<"u"&&window.location.hostname==="localhost"&&this.state.error&&r.createElement("details",{style:{marginBottom:"16px",maxWidth:"500px"}},r.createElement("summary",{style:{fontSize:"12px",color:"#6c757d",cursor:"pointer",marginBottom:"8px"}},"Error Details (Development Only)"),r.createElement("pre",{style:{fontSize:"10px",color:"#495057",backgroundColor:"#f8f9fa",padding:"8px",borderRadius:"4px",textAlign:"left",overflow:"auto",maxHeight:"100px"}},this.state.error.message)),r.createElement("div",{style:{display:"flex",gap:"12px"}},r.createElement("button",{onClick:this.handleRetry,style:{backgroundColor:"#007bff",color:"white",border:"none",padding:"8px 16px",borderRadius:"4px",cursor:"pointer",fontSize:"14px",fontWeight:"500"}},"Try Again"),r.createElement("button",{onClick:this.handleRetryWithDelay,style:{backgroundColor:"#28a745",color:"white",border:"none",padding:"8px 16px",borderRadius:"4px",cursor:"pointer",fontSize:"14px",fontWeight:"500"}},"Retry with Delay"))):this.props.children}}const Re="https://cdn.jsdelivr.net/npm/vanta@latest/dist/",k=new Set,v=new Map,le=async e=>{if(k.has(e)){const n=window.VANTA,o=n&&n[e.toUpperCase()];if(o)return o}if(v.has(e))return v.get(e);const t=L(e);v.set(e,t);try{const n=await t;return k.add(e),v.delete(e),n}catch(n){throw v.delete(e),n}},ce=async e=>{try{const t=e.map(async o=>{const i=await le(o);return{name:o,effect:i}});return(await Promise.all(t)).reduce((o,{name:i,effect:c})=>(o[i]=c,o),{})}catch(t){throw console.error("[CDN Vanta] Failed to load multiple effects:",t),t}},Pe=async()=>{await ce(["waves","birds","net","clouds","fog"])},ze=()=>({loadedEffects:Array.from(k),loadingEffects:Array.from(v.keys()),vantaAvailable:!!window.VANTA,loadedCount:k.size,loadingCount:v.size}),Se=()=>{k.clear(),v.clear()},He=e=>{if(typeof window>"u")return!1;const t=window.VANTA;return!!(t&&t[e.toUpperCase()])},De=e=>`${Re}vanta.${e}.min.js`,ke=()=>{var e,t;try{return typeof window<"u"&&window.location.hostname==="localhost"||((t=(e=globalThis.process)==null?void 0:e.env)==null?void 0:t.VANTA_PERFORMANCE_MONITORING)==="true"}catch{return!1}},q=()=>typeof window<"u"&&"performance"in window&&"memory"in window.performance?window.performance.memory.usedJSHeapSize:0,Fe=()=>{const e=performance.now(),t=q();return{startTime:e,memoryBefore:t,effectsLoaded:0,success:!1}},Me=(e,t,n,o)=>{const i=performance.now(),c=i-e.startTime,f=q(),d=f-(e.memoryBefore||0);return{...e,endTime:i,loadTime:c,memoryAfter:f,memoryIncrease:d,effectsLoaded:t,success:n,errorMessage:o}},Le=(e,t)=>{},je=e=>{const[t,n]=r.useState(!1),[o,i]=r.useState(null),[c,f]=r.useState(!1);return r.useEffect(()=>{let d=!0;return(async()=>{if(e){n(!0),i(null),f(!1);try{const x=await G(e);d&&(x?f(!0):i(`Failed to load effect: ${e}`))}catch(x){d&&i(x instanceof Error?x.message:"Unknown error")}finally{d&&n(!1)}}})(),()=>{d=!1}},[e]),{isLoading:t,error:o,isLoaded:c}};exports.ErrorBoundary=Ae;exports.VANTA_EFFECTS=ae;exports.Vanta=Ve;exports.areLibrariesReady=D;exports.clearEffectCache=be;exports.clearVantaCache=Se;exports.finishPerformanceMonitoring=Me;exports.getAvailableEffects=he;exports.getCachedEffects=ge;exports.getCdnLibraryStatus=ye;exports.getMemoryUsage=q;exports.getPreloadStatus=Ce;exports.getPreloadedP5=se;exports.getPreloadedThree=ie;exports.getVantaEffectCdnUrl=De;exports.getVantaLoadStatus=ze;exports.isPerformanceMonitoringEnabled=ke;exports.isVantaEffectAvailable=He;exports.loadCdnLibraries=me;exports.loadCdnP5=O;exports.loadCdnThree=B;exports.loadCdnVantaEffect=L;exports.loadMultipleVantaEffects=ce;exports.loadVantaEffect=G;exports.loadVantaEffectFromCdn=le;exports.logProgress=Le;exports.preloadAllVantaEffects=Ee;exports.preloadLibraries=_;exports.preloadPopularVantaEffects=Pe;exports.resetPreloadState=ve;exports.startPerformanceMonitoring=Fe;exports.useVantaEffect=je; //# sourceMappingURL=index.js.map