@beautifi/plugin 0.1.1 β 0.1.3
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/beautifi.cjs.js +1 -1
- package/dist/beautifi.cjs.js.map +1 -1
- package/dist/beautifi.esm.js +15 -5
- package/dist/beautifi.esm.js.map +1 -1
- package/dist/beautifi.min.js +1 -1
- package/dist/beautifi.min.js.map +1 -1
- package/dist/beautifi.umd.js +1 -1
- package/dist/beautifi.umd.js.map +1 -1
- package/package.json +2 -2
package/dist/beautifi.cjs.js
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
"use strict";Object.defineProperties(exports,{__esModule:{value:!0},[Symbol.toStringTag]:{value:"Module"}});class e extends Error{constructor(t,i,s){super(t),this.code=i,this.originalError=s,this.name="LivePhotoError",Error.captureStackTrace&&Error.captureStackTrace(this,e)}}const t={endpoint:"https://us-central1-seedgpt-planter.cloudfunctions.net/beautifi-api/animate",selector:"img",intensity:"subtle",type:"auto",loop:!0,respectReducedMotion:!0,debug:!1,threshold:.1,rootMargin:"50px",timeout:1e4,maxRetries:3,mode:"auto",videoEndpoint:"https://us-central1-seedgpt-planter.cloudfunctions.net/beautifi-api"},i={enabled:!0,intensity:"subtle",type:"auto",loop:!0,delay:0};class s{constructor(e="img",t=!1){this.trackedImages=new Map,this.processedElements=new WeakSet,this.mutationObserver=null,this.onImageDetected=null,this.selector=e,this.debug=t}setOnImageDetected(e){this.onImageDetected=e}scan(){const e=document.querySelectorAll(this.selector),t=[];return e.forEach(e=>{if(this.processedElements.has(e))return;const s=function(e){const t="false"!==e.dataset.live,s=e.dataset.liveIntensity,n="subtle"===s||"medium"===s||"strong"===s?s:i.intensity,o=e.dataset.liveType;return{enabled:t,intensity:n,type:"breathing"===o||"parallax"===o||"sway"===o||"auto"===o?o:i.type,loop:"false"!==e.dataset.liveLoop,delay:parseInt(e.dataset.liveDelay||"0",10)||0}}(e);if(!s.enabled)return void this.processedElements.add(e);const n={element:e,id:`lmp-${Date.now()}-${Math.random().toString(36).substr(2,9)}`,state:"idle",config:s};this.trackedImages.set(n.id,n),this.processedElements.add(e),t.push(n),this.debug}),t}observe(){this.mutationObserver||(this.mutationObserver=new MutationObserver(e=>{let t=!1;for(const i of e){if("childList"===i.type)for(const e of i.addedNodes)if(e instanceof HTMLImageElement||e instanceof Element&&e.querySelector(this.selector)){t=!0;break}if(t)break}if(t){this.scan().forEach(e=>{this.onImageDetected&&this.onImageDetected(e)})}}),this.mutationObserver.observe(document.body,{childList:!0,subtree:!0}))}getTrackedImages(){return Array.from(this.trackedImages.values())}getTrackedImage(e){return this.trackedImages.get(e)}updateImageState(e,t){const i=this.trackedImages.get(e);i&&Object.assign(i,t)}destroy(){this.mutationObserver&&(this.mutationObserver.disconnect(),this.mutationObserver=null),this.trackedImages.clear(),this.onImageDetected=null}}class n{constructor(e,t={}){this.observer=null,this.visibilityHandler=null,this.observedElements=new Map,this.isDocumentVisible=!0,this.callback=e,this.threshold=t.threshold??.1,this.rootMargin=t.rootMargin??"50px",this.debug=t.debug??!1,this.isDocumentVisible="undefined"==typeof document||!document.hidden}init(){this.observer||(this.observer=new IntersectionObserver(e=>{e.forEach(e=>{const t=this.observedElements.get(e.target);t&&this.isDocumentVisible&&(this.debug,this.callback(t,e.isIntersecting))})},{threshold:this.threshold,rootMargin:this.rootMargin}),this.visibilityHandler=()=>{const e=this.isDocumentVisible;this.isDocumentVisible=!document.hidden,e!==this.isDocumentVisible&&(this.debug,this.observedElements.forEach(e=>{this.callback(e,this.isDocumentVisible)}))},document.addEventListener("visibilitychange",this.visibilityHandler))}observe(e){this.observer||this.init(),this.observedElements.has(e.element)||(this.observedElements.set(e.element,e),this.observer.observe(e.element))}unobserve(e){this.observer&&this.observedElements.has(e.element)&&(this.observer.unobserve(e.element),this.observedElements.delete(e.element))}isVisible(){return this.isDocumentVisible}destroy(){this.observer&&(this.observer.disconnect(),this.observer=null),this.visibilityHandler&&(document.removeEventListener("visibilitychange",this.visibilityHandler),this.visibilityHandler=null),this.observedElements.clear()}}const o={timeout:1e4,maxRetries:3,enableCache:!0,debug:!1},r="lmp_cache_";class a{constructor(e){this.config={...o,...e}}async fetch(e,t={}){const i=await this.computeHash(e);if(this.config.enableCache){const e=this.getFromCache(i);if(e)return this.config.debug,{...e,cacheStatus:"hit"}}const s={imageUrl:e,imageHash:i,type:t.type??"auto",intensity:t.intensity??"subtle",loop:t.loop??!0},n=await this.fetchWithRetry(s);return n.success&&this.config.enableCache&&this.saveToCache(i,n),{...n,cacheStatus:"miss"}}async fetchWithRetry(t,i=0){try{return await this.fetchWithTimeout(t)}catch(s){if(s instanceof e&&("NETWORK_ERROR"===s.code||"TIMEOUT_ERROR"===s.code)&&i<this.config.maxRetries){const e=1e3*Math.pow(2,i);return this.config.debug,await this.sleep(e),this.fetchWithRetry(t,i+1)}throw s}}async fetchWithTimeout(t){const i=new AbortController,s=setTimeout(()=>i.abort(),this.config.timeout);try{const n=await fetch(this.config.endpoint,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify(t),signal:i.signal});if(clearTimeout(s),!n.ok){if(429===n.status)throw new e("Rate limit exceeded","RATE_LIMIT_ERROR");throw new e(`API error: ${n.status} ${n.statusText}`,"API_ERROR")}return await n.json()}catch(n){if(clearTimeout(s),n instanceof e)throw n;if(n instanceof Error){if("AbortError"===n.name)throw new e(`Request timed out after ${this.config.timeout}ms`,"TIMEOUT_ERROR",n);throw new e(`Network error: ${n.message}`,"NETWORK_ERROR",n)}throw new e("Unknown error occurred","UNKNOWN_ERROR")}}async computeHash(e){if("undefined"!=typeof crypto&&crypto.subtle){const t=(new TextEncoder).encode(e),i=await crypto.subtle.digest("SHA-256",t);return Array.from(new Uint8Array(i)).map(e=>e.toString(16).padStart(2,"0")).join("")}let t=0;for(let i=0;i<e.length;i++){t=(t<<5)-t+e.charCodeAt(i),t&=t}return Math.abs(t).toString(16)}getFromCache(e){if("undefined"==typeof localStorage)return null;try{const t=r+e,i=localStorage.getItem(t);if(!i)return null;const s=JSON.parse(i);return Date.now()-s.timestamp>2592e6?(localStorage.removeItem(t),null):s.data}catch{return null}}saveToCache(e,t){if("undefined"!=typeof localStorage)try{const i=r+e,s={data:t,timestamp:Date.now()};localStorage.setItem(i,JSON.stringify(s))}catch{this.config.debug}}clearCache(){if("undefined"==typeof localStorage)return;const e=[];for(let t=0;t<localStorage.length;t++){const i=localStorage.key(t);i&&i.startsWith(r)&&e.push(i)}e.forEach(e=>localStorage.removeItem(e))}sleep(e){return new Promise(t=>setTimeout(t,e))}}const l={subtle:.3,medium:.6,strong:1},d={breathing:{translateX:0,translateY:0,scale:.02,rotate:0,duration:3e3},parallax:{translateX:5,translateY:3,scale:.01,rotate:0,duration:4e3},sway:{translateX:3,translateY:0,scale:0,rotate:2,duration:2500}};class c{constructor(e={}){this.animations=new Map,this.config={frameRate:e.frameRate??60,debug:e.debug??!1}}play(e,t,i={}){const{id:s,element:n}=e;this.stop(s),n.style.willChange="transform",n.style.transformOrigin="center center";const o={trackedImage:e,animationData:t,currentFrame:0,animationFrameId:null,startTime:performance.now(),isPaused:!1,intensity:i.intensity??e.config.intensity,loop:i.loop??e.config.loop,onComplete:i.onComplete};this.animations.set(s,o),this.config.debug,this.renderLoop(s)}pause(e){const t=this.animations.get(e);t&&!t.isPaused&&(t.isPaused=!0,null!==t.animationFrameId&&(cancelAnimationFrame(t.animationFrameId),t.animationFrameId=null),this.config.debug)}resume(e){const t=this.animations.get(e);t&&t.isPaused&&(t.isPaused=!1,t.startTime=performance.now()-this.getElapsedTime(t),this.renderLoop(e),this.config.debug)}stop(e){const t=this.animations.get(e);t&&(null!==t.animationFrameId&&cancelAnimationFrame(t.animationFrameId),t.trackedImage.element.style.transform="",t.trackedImage.element.style.willChange="",this.animations.delete(e),this.config.debug)}isPlaying(e){const t=this.animations.get(e);return void 0!==t&&!t.isPaused}getActiveAnimations(){return Array.from(this.animations.keys())}destroy(){for(const e of this.animations.keys())this.stop(e);this.animations.clear()}renderLoop(e){const t=this.animations.get(e);if(!t||t.isPaused)return;const i=performance.now()-t.startTime,s=t.animationData.duration||3e3,n=i%s/s;if(!t.loop&&i>=s)return this.stop(e),void(t.onComplete&&t.onComplete());this.renderFrame(t,n),t.animationFrameId=requestAnimationFrame(()=>{this.renderLoop(e)})}renderFrame(e,t){const{trackedImage:i,animationData:s,intensity:n}=e,o=l[n];let r;if(s.frames&&s.frames.length>0){const e=Math.floor(t*s.frames.length);r=s.frames[Math.min(e,s.frames.length-1)].transform}else{const e=s.detectedType||"breathing";r="auto"!==e?this.generateTransformFromType(e,t):this.generateTransformFromType("breathing",t)}const a=r.translateX*o,d=r.translateY*o,c=1+r.scale*o,h=r.rotate*o;i.element.style.transform=`translate(${a}px, ${d}px) scale(${c}) rotate(${h}deg)`}generateTransformFromType(e,t){const i=d[e]||d.breathing,s=Math.sin(t*Math.PI*2);return{translateX:i.translateX*s,translateY:i.translateY*s,scale:i.scale*s,rotate:i.rotate*s}}getElapsedTime(e){const t=e.animationData.duration||3e3;return e.currentFrame/e.animationData.frameRate*1e3%t}}const h={apiKey:"",debug:!1,pollInterval:3e3,maxPollAttempts:60,cacheTTL:2592e6},u="beautifi_video_";class m{constructor(e){this.pendingOperations=new Map,this.config={...h,...e}}async startGeneration(e){var t;const i=this.computeCacheKey(e.imageUrl),s=this.getFromCache(i);if(s)return this.log(`π¦ Video cached: ${i.slice(0,8)}...`),{success:!0,status:"completed",videoUrl:s};try{const i=this.config.endpoint.replace("/animate","/animate-auto");this.log(`π¬ Starting video generation for: ${e.imageUrl.slice(0,50)}...`);const s={"Content-Type":"application/json"};this.config.apiKey&&(s["X-API-Key"]=this.config.apiKey);const n=await fetch(i,{method:"POST",headers:s,body:JSON.stringify({imageUrl:e.imageUrl,animationPrompt:e.animationPrompt,aspectRatio:e.aspectRatio,durationSeconds:e.durationSeconds})});if(!n.ok)throw new Error(`HTTP ${n.status}: ${n.statusText}`);const o=await n.json();if(!o.success)throw new Error((null==(t=o.error)?void 0:t.message)||"Video generation failed");return this.log(`π Generation started: ${o.operationId}`),o}catch(n){return this.log(`β Start generation error: ${n}`),{success:!1,error:{code:"GENERATION_ERROR",message:n instanceof Error?n.message:"Failed to start generation"}}}}async pollUntilComplete(e,t,i){var s;const n=new AbortController;this.pendingOperations.set(e,n);try{let o=0;for(;o<this.config.maxPollAttempts;){if(n.signal.aborted)return this.log(`π Polling aborted: ${e}`),null;const r=await this.checkStatus(e);if(i&&i(r.status||"unknown",o),"completed"===r.status&&r.videoUrl){this.log(`β
Video ready: ${r.videoUrl.slice(0,50)}...`);const e=this.computeCacheKey(t);return this.saveToCache(e,r.videoUrl),r.videoUrl}if("error"===r.status||!r.success)return this.log(`β Generation failed: ${null==(s=r.error)?void 0:s.message}`),null;const a=Math.min(this.config.pollInterval*Math.pow(1.5,Math.min(o,5)),15e3);this.log(`β³ Polling (${o+1}/${this.config.maxPollAttempts}): ${r.status}`),await this.sleep(a),o++}return this.log(`β° Polling timeout: ${e}`),null}finally{this.pendingOperations.delete(e)}}async checkStatus(e){try{const t=this.config.endpoint.replace("/animate","/generate-video/status").replace(/\/$/,""),i={};this.config.apiKey&&(i["X-API-Key"]=this.config.apiKey);const s=await fetch(`${t}/${e}`,{headers:i});if(!s.ok)throw new Error(`HTTP ${s.status}: ${s.statusText}`);return await s.json()}catch(t){return{success:!1,status:"error",error:{code:"POLL_ERROR",message:t instanceof Error?t.message:"Status check failed"}}}}cancelOperation(e){const t=this.pendingOperations.get(e);t&&(t.abort(),this.pendingOperations.delete(e),this.log(`π Cancelled: ${e}`))}cancelAllOperations(){for(const[e,t]of this.pendingOperations)t.abort(),this.log(`π Cancelled: ${e}`);this.pendingOperations.clear()}getCachedVideo(e){const t=this.computeCacheKey(e);return this.getFromCache(t)}computeCacheKey(e){let t=0;for(let i=0;i<e.length;i++){t=(t<<5)-t+e.charCodeAt(i),t&=t}return Math.abs(t).toString(36)}getFromCache(e){if("undefined"==typeof localStorage)return null;try{const t=localStorage.getItem(u+e);if(!t)return null;const i=JSON.parse(t);return Date.now()-i.timestamp>this.config.cacheTTL?(localStorage.removeItem(u+e),null):i.videoUrl}catch{return null}}saveToCache(e,t){if("undefined"!=typeof localStorage)try{const i={videoUrl:t,timestamp:Date.now()};localStorage.setItem(u+e,JSON.stringify(i)),this.log(`πΎ Cached: ${e}`)}catch{}}clearCache(){if("undefined"==typeof localStorage)return;const e=[];for(let t=0;t<localStorage.length;t++){const i=localStorage.key(t);(null==i?void 0:i.startsWith(u))&&e.push(i)}e.forEach(e=>localStorage.removeItem(e)),this.log(`π§Ή Cleared ${e.length} cached videos`)}sleep(e){return new Promise(t=>setTimeout(t,e))}log(e){this.config.debug}}const p={transitionDuration:500,debug:!1,autoPlay:!0,loop:!0,muted:!0};class g{constructor(e={}){this.activeVideos=new Map,this.config={...p,...e}}async prepareVideo(e,t,i,s){if(this.activeVideos.has(e))return this.log(`β οΈ Video already prepared: ${e}`),!0;try{const n=this.createWrapper(t),o=this.createVideoElement(i);n.insertBefore(o,t);const r={imageElement:t,videoElement:o,wrapperElement:n,state:"loading",onFallback:s};return this.activeVideos.set(e,r),await this.waitForVideoReady(o,r),this.log(`β
Video prepared: ${e}`),!0}catch(n){return this.log(`β Prepare failed: ${e} - ${n}`),this.cleanup(e),null==s||s(),!1}}play(e){var t;const i=this.activeVideos.get(e);if(!i)return this.log(`β οΈ No video found: ${e}`),!1;if("error"===i.state)return this.log(`β οΈ Video in error state: ${e}`),!1;try{return this.transitionToVideo(i),i.videoElement.play().catch(e=>{var t;this.log(`β Play failed: ${e}`),i.state="error",null==(t=i.onFallback)||t.call(i)}),i.state="playing",this.log(`βΆοΈ Playing: ${e}`),!0}catch(s){return this.log(`β Play error: ${s}`),i.state="error",null==(t=i.onFallback)||t.call(i),!1}}pause(e){const t=this.activeVideos.get(e);return!(!t||"playing"!==t.state)&&(t.videoElement.pause(),t.state="paused",this.log(`βΈοΈ Paused: ${e}`),!0)}resume(e){const t=this.activeVideos.get(e);return!(!t||"paused"!==t.state)&&(t.videoElement.play().catch(()=>{t.state="error"}),t.state="playing",this.log(`βΆοΈ Resumed: ${e}`),!0)}stop(e){const t=this.activeVideos.get(e);t&&(this.transitionToImage(t),setTimeout(()=>{this.cleanup(e)},this.config.transitionDuration))}isPlaying(e){const t=this.activeVideos.get(e);return"playing"===(null==t?void 0:t.state)}isPrepared(e){return this.activeVideos.has(e)}getState(e){var t;return(null==(t=this.activeVideos.get(e))?void 0:t.state)||null}destroy(){for(const e of this.activeVideos.keys())this.cleanup(e);this.log("π§Ή Destroyed all videos")}createWrapper(e){var t;const i=e.parentElement;if(null==i?void 0:i.classList.contains("beautifi-video-wrapper"))return i;const s=document.createElement("div");return s.className="beautifi-video-wrapper",s.style.cssText=`\n position: relative;\n display: inline-block;\n width: ${e.offsetWidth}px;\n height: ${e.offsetHeight}px;\n overflow: hidden;\n `,null==(t=e.parentNode)||t.insertBefore(s,e),s.appendChild(e),e.style.cssText+=`\n position: relative;\n z-index: 2;\n transition: opacity ${this.config.transitionDuration}ms ease-in-out;\n `,s}createVideoElement(e){const t=document.createElement("video");return t.src=e,t.muted=this.config.muted,t.loop=this.config.loop,t.playsInline=!0,t.preload="auto",t.crossOrigin="anonymous",t.style.cssText=`\n position: absolute;\n top: 0;\n left: 0;\n width: 100%;\n height: 100%;\n object-fit: cover;\n z-index: 1;\n opacity: 0;\n transition: opacity ${this.config.transitionDuration}ms ease-in-out;\n `,t}waitForVideoReady(e,t){return new Promise((i,s)=>{const n=setTimeout(()=>{s(new Error("Video load timeout"))},3e4);e.addEventListener("canplaythrough",()=>{clearTimeout(n),t.state="buffering",i()},{once:!0}),e.addEventListener("error",()=>{clearTimeout(n),t.state="error",s(new Error("Video load error"))},{once:!0}),e.load()})}transitionToVideo(e){e.videoElement.style.opacity="1",e.imageElement.style.opacity="0",e.imageElement.style.animation="none"}transitionToImage(e){e.imageElement.style.opacity="1",e.videoElement.style.opacity="0",e.videoElement.pause()}cleanup(e){const t=this.activeVideos.get(e);if(t){if(t.imageElement.style.opacity="1",t.imageElement.style.animation="",t.imageElement.style.position="",t.imageElement.style.zIndex="",t.imageElement.style.transition="",t.videoElement.remove(),t.wrapperElement.classList.contains("beautifi-video-wrapper")){const e=t.wrapperElement.parentNode;e&&(e.insertBefore(t.imageElement,t.wrapperElement),t.wrapperElement.remove())}this.activeVideos.delete(e),this.log(`π§Ή Cleaned up: ${e}`)}}log(e){this.config.debug}}const f=new class{constructor(){this.initialized=!1,this.options=null,this.detector=null,this.viewportObserver=null,this.apiClient=null,this.renderer=null,this.veoClient=null,this.videoRenderer=null,this.reducedMotion=!1,this.pendingVideoGenerations=new Map}init(e){if(!e.apiKey)throw new Error("beautifi: apiKey is required");if("undefined"!=typeof window&&window.matchMedia&&(this.reducedMotion=window.matchMedia("(prefers-reduced-motion: reduce)").matches),this.options={...t,...e},this.reducedMotion&&this.options.respectReducedMotion)return this.options.debug,void(this.initialized=!0);this.detector=new s(this.options.selector,this.options.debug),this.apiClient=new a({endpoint:this.options.endpoint||"https://us-central1-seedgpt-planter.cloudfunctions.net/beautifi-api/animate",timeout:this.options.timeout,maxRetries:this.options.maxRetries,enableCache:!0,debug:this.options.debug}),this.renderer=new c({debug:this.options.debug}),"css"!==this.options.mode&&(this.veoClient=new m({endpoint:this.options.videoEndpoint||this.options.endpoint,debug:this.options.debug}),this.videoRenderer=new g({debug:this.options.debug,transitionDuration:500}),this.options.debug),this.viewportObserver=new n((e,t)=>{this.handleVisibilityChange(e,t)},{threshold:this.options.threshold,rootMargin:this.options.rootMargin,debug:this.options.debug}),this.detector.setOnImageDetected(e=>{this.viewportObserver.observe(e)}),this.viewportObserver.init();this.detector.scan().forEach(e=>{this.viewportObserver.observe(e)}),this.detector.observe(),this.initialized=!0,this.options.debug}handleVisibilityChange(e,t){this.options&&(t?"idle"===e.state?this.queueAnimation(e):"paused"===e.state&&this.resumeAnimation(e):"playing"===e.state&&this.pauseAnimation(e))}async queueAnimation(t){var i,s,n;this.detector&&this.detector.updateImageState(t.id,{state:"loading"}),null==(i=this.options)||i.debug,t.config.delay&&t.config.delay>0&&await new Promise(e=>setTimeout(e,t.config.delay));const o=t.element.dataset.beautifiMode||(null==(s=this.options)?void 0:s.mode)||"auto";try{const i=await this.apiClient.fetch(t.element.src,{type:t.config.type,intensity:t.config.intensity,loop:t.config.loop});if(!i.success)throw new e(i.error||"Animation generation failed","API_ERROR");this.detector&&this.detector.updateImageState(t.id,{state:"playing",animationData:i}),"video"!==o&&(this.renderer.play(t,i,{intensity:t.config.intensity,loop:t.config.loop,onComplete:()=>{this.detector&&this.detector.updateImageState(t.id,{state:"idle"}),this.emitEvent("animationComplete",t)}}),this.emitEvent("animationStart",t)),"css"!==o&&this.veoClient&&this.videoRenderer&&this.startVideoGeneration(t)}catch(r){const i=r instanceof e?r:new e(r instanceof Error?r.message:"Unknown error","UNKNOWN_ERROR",r instanceof Error?r:void 0);this.detector&&this.detector.updateImageState(t.id,{state:"error",error:i}),null==(n=this.options)||n.debug,this.emitEvent("animationError",t,i)}}async startVideoGeneration(e){var t,i,s,n,o;if(!this.veoClient||!this.videoRenderer)return;const r=this.veoClient.getCachedVideo(e.element.src);if(r)return null==(t=this.options)||t.debug,void this.transitionToVideo(e,r);this.emitVideoEvent("videoStart",e),null==(i=this.options)||i.debug;try{const t=await this.veoClient.startGeneration({imageUrl:e.element.src});if(!t.success||!t.operationId)throw new Error((null==(s=t.error)?void 0:s.message)||"Failed to start video generation");if("completed"===t.status&&t.videoUrl)return void this.transitionToVideo(e,t.videoUrl);this.pendingVideoGenerations.set(e.id,t.operationId);const i=await this.veoClient.pollUntilComplete(t.operationId,e.element.src,(e,t)=>{var i;null==(i=this.options)||i.debug});this.pendingVideoGenerations.delete(e.id),i?this.transitionToVideo(e,i):(null==(n=this.options)||n.debug,this.emitVideoEvent("videoError",e))}catch(a){this.pendingVideoGenerations.delete(e.id),null==(o=this.options)||o.debug,this.emitVideoEvent("videoError",e)}}async transitionToVideo(e,t){var i,s;if(!this.videoRenderer)return;null==(i=this.options)||i.debug;await this.videoRenderer.prepareVideo(e.id,e.element,t,()=>{var e;null==(e=this.options)||e.debug})&&(null==(s=this.renderer)||s.stop(e.id),this.videoRenderer.play(e.id),this.emitVideoEvent("videoReady",e,t))}pauseAnimation(e){var t;this.renderer&&this.renderer.pause(e.id),this.detector&&this.detector.updateImageState(e.id,{state:"paused"}),null==(t=this.options)||t.debug,this.emitEvent("animationPause",e)}resumeAnimation(e){var t;this.renderer&&this.renderer.resume(e.id),this.detector&&this.detector.updateImageState(e.id,{state:"playing"}),null==(t=this.options)||t.debug,this.emitEvent("animationResume",e)}emitEvent(e,t,i){if("undefined"!=typeof CustomEvent){const s={type:e,timestamp:Date.now(),element:t.element,imageId:t.id,...i&&{error:i}},n=new CustomEvent(`beautifi:${e}`,{detail:s});document.dispatchEvent(n)}}emitVideoEvent(e,t,i){if("undefined"!=typeof CustomEvent){const s={type:e,timestamp:Date.now(),element:t.element,imageId:t.id,...i&&{videoUrl:i}},n=new CustomEvent(`beautifi:${e}`,{detail:s});document.dispatchEvent(n)}}isInitialized(){return this.initialized}getOptions(){return this.options}getTrackedImages(){var e;return(null==(e=this.detector)?void 0:e.getTrackedImages())??[]}destroy(){this.veoClient&&(this.veoClient.cancelAllOperations(),this.veoClient=null),this.videoRenderer&&(this.videoRenderer.destroy(),this.videoRenderer=null),this.renderer&&(this.renderer.destroy(),this.renderer=null),this.detector&&(this.detector.destroy(),this.detector=null),this.viewportObserver&&(this.viewportObserver.destroy(),this.viewportObserver=null),this.apiClient=null,this.pendingVideoGenerations.clear(),this.initialized=!1,this.options=null}},v={init:e=>f.init(e),isInitialized:()=>f.isInitialized(),getOptions:()=>f.getOptions(),getTrackedImages:()=>f.getTrackedImages(),destroy:()=>f.destroy()},y=v;"undefined"!=typeof document&&document.addEventListener("DOMContentLoaded",()=>{const e=document.querySelector('script[data-api-key][src*="beautifi"], script[data-api-key][src*="live-my-photos"]');if(e){const t=e.dataset.apiKey,i="false"!==e.dataset.autoInit;t&&i&&v.init({apiKey:t,selector:e.dataset.selector,intensity:e.dataset.intensity,type:e.dataset.type,loop:"false"!==e.dataset.loop,debug:"true"===e.dataset.debug,mode:e.dataset.mode||"auto"})}}),"undefined"!=typeof window&&(window.beautifi=v,window.LiveMyPhotos=v),exports.AnimationRenderer=c,exports.DEFAULT_ANIMATION_CONFIG=i,exports.DEFAULT_OPTIONS=t,exports.GeminiApiClient=a,exports.ImageDetector=s,exports.LiveMyPhotos=y,exports.LivePhotoError=e,exports.VeoClient=m,exports.VideoRenderer=g,exports.ViewportObserver=n,exports.beautifi=v,exports.default=v;
|
|
1
|
+
"use strict";Object.defineProperties(exports,{__esModule:{value:!0},[Symbol.toStringTag]:{value:"Module"}});class e extends Error{constructor(t,i,s){super(t),this.code=i,this.originalError=s,this.name="LivePhotoError",Error.captureStackTrace&&Error.captureStackTrace(this,e)}}const t={endpoint:"https://api.beautifi.uk/animate",selector:"img",intensity:"subtle",type:"auto",loop:!0,respectReducedMotion:!0,debug:!1,threshold:.1,rootMargin:"50px",timeout:1e4,maxRetries:3,mode:"auto",videoEndpoint:"https://api.beautifi.uk"},i={enabled:!0,intensity:"subtle",type:"auto",loop:!0,delay:0};class s{constructor(e="img",t=!1){this.trackedImages=new Map,this.processedElements=new WeakSet,this.mutationObserver=null,this.onImageDetected=null,this.selector=e,this.debug=t}setOnImageDetected(e){this.onImageDetected=e}scan(){const e=document.querySelectorAll(this.selector),t=[];return e.forEach(e=>{if(this.processedElements.has(e))return;const s=function(e){const t="false"!==e.dataset.live,s=e.dataset.liveIntensity,o="subtle"===s||"medium"===s||"strong"===s?s:i.intensity,n=e.dataset.liveType;return{enabled:t,intensity:o,type:"breathing"===n||"parallax"===n||"sway"===n||"auto"===n?n:i.type,loop:"false"!==e.dataset.liveLoop,delay:parseInt(e.dataset.liveDelay||"0",10)||0}}(e);if(!s.enabled)return void this.processedElements.add(e);const o={element:e,id:`lmp-${Date.now()}-${Math.random().toString(36).substr(2,9)}`,state:"idle",config:s};this.trackedImages.set(o.id,o),this.processedElements.add(e),t.push(o),this.debug}),t}observe(){this.mutationObserver||(this.mutationObserver=new MutationObserver(e=>{let t=!1;for(const i of e){if("childList"===i.type)for(const e of i.addedNodes)if(e instanceof HTMLImageElement||e instanceof Element&&e.querySelector(this.selector)){t=!0;break}if(t)break}if(t){this.scan().forEach(e=>{this.onImageDetected&&this.onImageDetected(e)})}}),this.mutationObserver.observe(document.body,{childList:!0,subtree:!0}))}getTrackedImages(){return Array.from(this.trackedImages.values())}getTrackedImage(e){return this.trackedImages.get(e)}updateImageState(e,t){const i=this.trackedImages.get(e);i&&Object.assign(i,t)}destroy(){this.mutationObserver&&(this.mutationObserver.disconnect(),this.mutationObserver=null),this.trackedImages.clear(),this.onImageDetected=null}}class o{constructor(e,t={}){this.observer=null,this.visibilityHandler=null,this.observedElements=new Map,this.isDocumentVisible=!0,this.callback=e,this.threshold=t.threshold??.1,this.rootMargin=t.rootMargin??"50px",this.debug=t.debug??!1,this.isDocumentVisible="undefined"==typeof document||!document.hidden}init(){this.observer||(this.observer=new IntersectionObserver(e=>{e.forEach(e=>{const t=this.observedElements.get(e.target);t&&this.isDocumentVisible&&(this.debug,this.callback(t,e.isIntersecting))})},{threshold:this.threshold,rootMargin:this.rootMargin}),this.visibilityHandler=()=>{const e=this.isDocumentVisible;this.isDocumentVisible=!document.hidden,e!==this.isDocumentVisible&&(this.debug,this.observedElements.forEach(e=>{this.callback(e,this.isDocumentVisible)}))},document.addEventListener("visibilitychange",this.visibilityHandler))}observe(e){this.observer||this.init(),this.observedElements.has(e.element)||(this.observedElements.set(e.element,e),this.observer.observe(e.element))}unobserve(e){this.observer&&this.observedElements.has(e.element)&&(this.observer.unobserve(e.element),this.observedElements.delete(e.element))}isVisible(){return this.isDocumentVisible}destroy(){this.observer&&(this.observer.disconnect(),this.observer=null),this.visibilityHandler&&(document.removeEventListener("visibilitychange",this.visibilityHandler),this.visibilityHandler=null),this.observedElements.clear()}}const n={timeout:1e4,maxRetries:3,enableCache:!0,debug:!1},a="lmp_cache_";class r{constructor(e){this.config={...n,...e}}async fetch(e,t={}){const i=await this.computeHash(e);if(this.config.enableCache){const e=this.getFromCache(i);if(e)return this.config.debug,{...e,cacheStatus:"hit"}}const s={imageUrl:e,imageHash:i,type:t.type??"auto",intensity:t.intensity??"subtle",loop:t.loop??!0},o=await this.fetchWithRetry(s);return o.success&&this.config.enableCache&&this.saveToCache(i,o),{...o,cacheStatus:"miss"}}async fetchWithRetry(t,i=0){try{return await this.fetchWithTimeout(t)}catch(s){if(s instanceof e&&("NETWORK_ERROR"===s.code||"TIMEOUT_ERROR"===s.code)&&i<this.config.maxRetries){const e=1e3*Math.pow(2,i);return this.config.debug,await this.sleep(e),this.fetchWithRetry(t,i+1)}throw s}}async fetchWithTimeout(t){const i=new AbortController,s=setTimeout(()=>i.abort(),this.config.timeout);try{const o=await fetch(this.config.endpoint,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify(t),signal:i.signal});if(clearTimeout(s),!o.ok){if(429===o.status)throw new e("Rate limit exceeded","RATE_LIMIT_ERROR");throw new e(`API error: ${o.status} ${o.statusText}`,"API_ERROR")}return await o.json()}catch(o){if(clearTimeout(s),o instanceof e)throw o;if(o instanceof Error){if("AbortError"===o.name)throw new e(`Request timed out after ${this.config.timeout}ms`,"TIMEOUT_ERROR",o);throw new e(`Network error: ${o.message}`,"NETWORK_ERROR",o)}throw new e("Unknown error occurred","UNKNOWN_ERROR")}}async computeHash(e){if("undefined"!=typeof crypto&&crypto.subtle){const t=(new TextEncoder).encode(e),i=await crypto.subtle.digest("SHA-256",t);return Array.from(new Uint8Array(i)).map(e=>e.toString(16).padStart(2,"0")).join("")}let t=0;for(let i=0;i<e.length;i++){t=(t<<5)-t+e.charCodeAt(i),t&=t}return Math.abs(t).toString(16)}getFromCache(e){if("undefined"==typeof localStorage)return null;try{const t=a+e,i=localStorage.getItem(t);if(!i)return null;const s=JSON.parse(i);return Date.now()-s.timestamp>2592e6?(localStorage.removeItem(t),null):s.data}catch{return null}}saveToCache(e,t){if("undefined"!=typeof localStorage)try{const i=a+e,s={data:t,timestamp:Date.now()};localStorage.setItem(i,JSON.stringify(s))}catch{this.config.debug}}clearCache(){if("undefined"==typeof localStorage)return;const e=[];for(let t=0;t<localStorage.length;t++){const i=localStorage.key(t);i&&i.startsWith(a)&&e.push(i)}e.forEach(e=>localStorage.removeItem(e))}sleep(e){return new Promise(t=>setTimeout(t,e))}}const l={subtle:.3,medium:.6,strong:1},d={breathing:{translateX:0,translateY:0,scale:.02,rotate:0,duration:3e3},parallax:{translateX:5,translateY:3,scale:.01,rotate:0,duration:4e3},sway:{translateX:3,translateY:0,scale:0,rotate:2,duration:2500}};class c{constructor(e={}){this.animations=new Map,this.config={frameRate:e.frameRate??60,debug:e.debug??!1}}play(e,t,i={}){const{id:s,element:o}=e;this.stop(s),o.style.willChange="transform",o.style.transformOrigin="center center";const n={trackedImage:e,animationData:t,currentFrame:0,animationFrameId:null,startTime:performance.now(),isPaused:!1,intensity:i.intensity??e.config.intensity,loop:i.loop??e.config.loop,onComplete:i.onComplete};this.animations.set(s,n),this.config.debug,this.renderLoop(s)}pause(e){const t=this.animations.get(e);t&&!t.isPaused&&(t.isPaused=!0,null!==t.animationFrameId&&(cancelAnimationFrame(t.animationFrameId),t.animationFrameId=null),this.config.debug)}resume(e){const t=this.animations.get(e);t&&t.isPaused&&(t.isPaused=!1,t.startTime=performance.now()-this.getElapsedTime(t),this.renderLoop(e),this.config.debug)}stop(e){const t=this.animations.get(e);t&&(null!==t.animationFrameId&&cancelAnimationFrame(t.animationFrameId),t.trackedImage.element.style.transform="",t.trackedImage.element.style.willChange="",this.animations.delete(e),this.config.debug)}isPlaying(e){const t=this.animations.get(e);return void 0!==t&&!t.isPaused}getActiveAnimations(){return Array.from(this.animations.keys())}destroy(){for(const e of this.animations.keys())this.stop(e);this.animations.clear()}renderLoop(e){const t=this.animations.get(e);if(!t||t.isPaused)return;const i=performance.now()-t.startTime,s=t.animationData.duration||3e3,o=i%s/s;if(!t.loop&&i>=s)return this.stop(e),void(t.onComplete&&t.onComplete());this.renderFrame(t,o),t.animationFrameId=requestAnimationFrame(()=>{this.renderLoop(e)})}renderFrame(e,t){const{trackedImage:i,animationData:s,intensity:o}=e,n=l[o];let a;if(s.frames&&s.frames.length>0){const e=Math.floor(t*s.frames.length);a=s.frames[Math.min(e,s.frames.length-1)].transform}else{const e=s.detectedType||"breathing";a="auto"!==e?this.generateTransformFromType(e,t):this.generateTransformFromType("breathing",t)}const r=a.translateX*n,d=a.translateY*n,c=1+a.scale*n,h=a.rotate*n;i.element.style.transform=`translate(${r}px, ${d}px) scale(${c}) rotate(${h}deg)`}generateTransformFromType(e,t){const i=d[e]||d.breathing,s=Math.sin(t*Math.PI*2);return{translateX:i.translateX*s,translateY:i.translateY*s,scale:i.scale*s,rotate:i.rotate*s}}getElapsedTime(e){const t=e.animationData.duration||3e3;return e.currentFrame/e.animationData.frameRate*1e3%t}}const h={apiKey:"",debug:!1,pollInterval:3e3,maxPollAttempts:60,cacheTTL:2592e6},u="beautifi_video_";class m{constructor(e){this.pendingOperations=new Map,this.config={...h,...e}}async startGeneration(e){var t;const i=this.computeCacheKey(e.imageUrl),s=this.getFromCache(i);if(s)return this.log(`π¦ Video cached: ${i.slice(0,8)}...`),{success:!0,status:"completed",videoUrl:s};try{let i=this.config.endpoint.replace(/\/$/,"");i=i.includes("/animate")?i.replace("/animate","/animate-auto"):`${i}/animate-auto`,this.log(`π¬ Starting video generation for: ${e.imageUrl.slice(0,50)}...`);const s={"Content-Type":"application/json"};this.config.apiKey&&(s["X-API-Key"]=this.config.apiKey);const o=await fetch(i,{method:"POST",headers:s,body:JSON.stringify({imageUrl:e.imageUrl,animationPrompt:e.animationPrompt,aspectRatio:e.aspectRatio,durationSeconds:e.durationSeconds})});if(!o.ok)throw new Error(`HTTP ${o.status}: ${o.statusText}`);const n=await o.json();if(!n.success)throw new Error((null==(t=n.error)?void 0:t.message)||"Video generation failed");return this.log(`π Generation started: ${n.operationId}`),n}catch(o){return this.log(`β Start generation error: ${o}`),{success:!1,error:{code:"GENERATION_ERROR",message:o instanceof Error?o.message:"Failed to start generation"}}}}async pollUntilComplete(e,t,i){var s;const o=new AbortController;this.pendingOperations.set(e,o);try{let n=0;for(;n<this.config.maxPollAttempts;){if(o.signal.aborted)return this.log(`π Polling aborted: ${e}`),null;const a=await this.checkStatus(e);if(i&&i(a.status||"unknown",n),"completed"===a.status&&a.videoUrl){this.log(`β
Video ready: ${a.videoUrl.slice(0,50)}...`);const e=this.computeCacheKey(t);return this.saveToCache(e,a.videoUrl),a.videoUrl}if("error"===a.status||!a.success)return this.log(`β Generation failed: ${null==(s=a.error)?void 0:s.message}`),null;const r=Math.min(this.config.pollInterval*Math.pow(1.5,Math.min(n,5)),15e3);this.log(`β³ Polling (${n+1}/${this.config.maxPollAttempts}): ${a.status}`),await this.sleep(r),n++}return this.log(`β° Polling timeout: ${e}`),null}finally{this.pendingOperations.delete(e)}}async checkStatus(e){try{let t=this.config.endpoint.replace(/\/$/,"");t=t.includes("/animate")?t.replace("/animate","/generate-video/status"):`${t}/generate-video/status`;const i={};this.config.apiKey&&(i["X-API-Key"]=this.config.apiKey);const s=await fetch(`${t}/${e}`,{headers:i});if(!s.ok)throw new Error(`HTTP ${s.status}: ${s.statusText}`);return await s.json()}catch(t){return{success:!1,status:"error",error:{code:"POLL_ERROR",message:t instanceof Error?t.message:"Status check failed"}}}}cancelOperation(e){const t=this.pendingOperations.get(e);t&&(t.abort(),this.pendingOperations.delete(e),this.log(`π Cancelled: ${e}`))}cancelAllOperations(){for(const[e,t]of this.pendingOperations)t.abort(),this.log(`π Cancelled: ${e}`);this.pendingOperations.clear()}getCachedVideo(e){const t=this.computeCacheKey(e);return this.getFromCache(t)}computeCacheKey(e){let t=0;for(let i=0;i<e.length;i++){t=(t<<5)-t+e.charCodeAt(i),t&=t}return Math.abs(t).toString(36)}getFromCache(e){if("undefined"==typeof localStorage)return null;try{const t=localStorage.getItem(u+e);if(!t)return null;const i=JSON.parse(t);return Date.now()-i.timestamp>this.config.cacheTTL?(localStorage.removeItem(u+e),null):i.videoUrl}catch{return null}}saveToCache(e,t){if("undefined"!=typeof localStorage)try{const i={videoUrl:t,timestamp:Date.now()};localStorage.setItem(u+e,JSON.stringify(i)),this.log(`πΎ Cached: ${e}`)}catch{}}clearCache(){if("undefined"==typeof localStorage)return;const e=[];for(let t=0;t<localStorage.length;t++){const i=localStorage.key(t);(null==i?void 0:i.startsWith(u))&&e.push(i)}e.forEach(e=>localStorage.removeItem(e)),this.log(`π§Ή Cleared ${e.length} cached videos`)}sleep(e){return new Promise(t=>setTimeout(t,e))}log(e){this.config.debug}}const p={transitionDuration:500,debug:!1,autoPlay:!0,loop:!0,muted:!0};class g{constructor(e={}){this.activeVideos=new Map,this.config={...p,...e}}async prepareVideo(e,t,i,s){if(this.activeVideos.has(e))return this.log(`β οΈ Video already prepared: ${e}`),!0;try{const o=this.createWrapper(t),n=this.createVideoElement(i);o.insertBefore(n,t);const a={imageElement:t,videoElement:n,wrapperElement:o,state:"loading",onFallback:s};return this.activeVideos.set(e,a),await this.waitForVideoReady(n,a),this.log(`β
Video prepared: ${e}`),!0}catch(o){return this.log(`β Prepare failed: ${e} - ${o}`),this.cleanup(e),null==s||s(),!1}}play(e){var t;const i=this.activeVideos.get(e);if(!i)return this.log(`β οΈ No video found: ${e}`),!1;if("error"===i.state)return this.log(`β οΈ Video in error state: ${e}`),!1;try{return this.transitionToVideo(i),i.videoElement.play().catch(e=>{var t;this.log(`β Play failed: ${e}`),i.state="error",null==(t=i.onFallback)||t.call(i)}),i.state="playing",this.log(`βΆοΈ Playing: ${e}`),!0}catch(s){return this.log(`β Play error: ${s}`),i.state="error",null==(t=i.onFallback)||t.call(i),!1}}pause(e){const t=this.activeVideos.get(e);return!(!t||"playing"!==t.state)&&(t.videoElement.pause(),t.state="paused",this.log(`βΈοΈ Paused: ${e}`),!0)}resume(e){const t=this.activeVideos.get(e);return!(!t||"paused"!==t.state)&&(t.videoElement.play().catch(()=>{t.state="error"}),t.state="playing",this.log(`βΆοΈ Resumed: ${e}`),!0)}stop(e){const t=this.activeVideos.get(e);t&&(this.transitionToImage(t),setTimeout(()=>{this.cleanup(e)},this.config.transitionDuration))}isPlaying(e){const t=this.activeVideos.get(e);return"playing"===(null==t?void 0:t.state)}isPrepared(e){return this.activeVideos.has(e)}getState(e){var t;return(null==(t=this.activeVideos.get(e))?void 0:t.state)||null}destroy(){for(const e of this.activeVideos.keys())this.cleanup(e);this.log("π§Ή Destroyed all videos")}createWrapper(e){var t;const i=e.parentElement;if(null==i?void 0:i.classList.contains("beautifi-video-wrapper"))return i;const s=document.createElement("div");return s.className="beautifi-video-wrapper",s.style.cssText=`\n position: relative;\n display: inline-block;\n width: ${e.offsetWidth}px;\n height: ${e.offsetHeight}px;\n overflow: hidden;\n `,null==(t=e.parentNode)||t.insertBefore(s,e),s.appendChild(e),e.style.cssText+=`\n position: relative;\n z-index: 2;\n transition: opacity ${this.config.transitionDuration}ms ease-in-out;\n `,s}createVideoElement(e){const t=document.createElement("video");return t.src=e,t.muted=this.config.muted,t.loop=this.config.loop,t.playsInline=!0,t.preload="auto",t.crossOrigin="anonymous",t.style.cssText=`\n position: absolute;\n top: 0;\n left: 0;\n width: 100%;\n height: 100%;\n object-fit: cover;\n z-index: 1;\n opacity: 0;\n transition: opacity ${this.config.transitionDuration}ms ease-in-out;\n `,t}waitForVideoReady(e,t){return new Promise((i,s)=>{const o=setTimeout(()=>{s(new Error("Video load timeout"))},3e4);e.addEventListener("canplaythrough",()=>{clearTimeout(o),t.state="buffering",i()},{once:!0}),e.addEventListener("error",()=>{clearTimeout(o),t.state="error",s(new Error("Video load error"))},{once:!0}),e.load()})}transitionToVideo(e){e.videoElement.style.opacity="1",e.imageElement.style.opacity="0",e.imageElement.style.animation="none"}transitionToImage(e){e.imageElement.style.opacity="1",e.videoElement.style.opacity="0",e.videoElement.pause()}cleanup(e){const t=this.activeVideos.get(e);if(t){if(t.imageElement.style.opacity="1",t.imageElement.style.animation="",t.imageElement.style.position="",t.imageElement.style.zIndex="",t.imageElement.style.transition="",t.videoElement.remove(),t.wrapperElement.classList.contains("beautifi-video-wrapper")){const e=t.wrapperElement.parentNode;e&&(e.insertBefore(t.imageElement,t.wrapperElement),t.wrapperElement.remove())}this.activeVideos.delete(e),this.log(`π§Ή Cleaned up: ${e}`)}}log(e){this.config.debug}}const f=new class{constructor(){this.initialized=!1,this.options=null,this.detector=null,this.viewportObserver=null,this.apiClient=null,this.renderer=null,this.veoClient=null,this.videoRenderer=null,this.reducedMotion=!1,this.pendingVideoGenerations=new Map}init(e){if(!e.apiKey)throw new Error("beautifi: apiKey is required");if("undefined"!=typeof window&&window.matchMedia&&(this.reducedMotion=window.matchMedia("(prefers-reduced-motion: reduce)").matches),this.options={...t,...e},this.reducedMotion&&this.options.respectReducedMotion)return this.options.debug,void(this.initialized=!0);this.detector=new s(this.options.selector,this.options.debug),this.apiClient=new r({endpoint:this.options.endpoint||"https://api.beautifi.uk/animate",timeout:this.options.timeout,maxRetries:this.options.maxRetries,enableCache:!0,debug:this.options.debug}),this.renderer=new c({debug:this.options.debug}),"css"!==this.options.mode&&(this.veoClient=new m({endpoint:this.options.videoEndpoint||this.options.endpoint,debug:this.options.debug}),this.videoRenderer=new g({debug:this.options.debug,transitionDuration:500}),this.options.debug),this.viewportObserver=new o((e,t)=>{this.handleVisibilityChange(e,t)},{threshold:this.options.threshold,rootMargin:this.options.rootMargin,debug:this.options.debug}),this.detector.setOnImageDetected(e=>{this.viewportObserver.observe(e)}),this.viewportObserver.init();this.detector.scan().forEach(e=>{this.viewportObserver.observe(e)}),this.detector.observe(),this.initialized=!0,this.options.debug}handleVisibilityChange(e,t){this.options&&(t?"idle"===e.state?this.queueAnimation(e):"paused"===e.state&&this.resumeAnimation(e):"playing"===e.state&&this.pauseAnimation(e))}async queueAnimation(t){var i,s,o;this.detector&&this.detector.updateImageState(t.id,{state:"loading"}),null==(i=this.options)||i.debug,t.config.delay&&t.config.delay>0&&await new Promise(e=>setTimeout(e,t.config.delay));const n=t.element.dataset.beautifiMode||(null==(s=this.options)?void 0:s.mode)||"auto";try{const i=await this.apiClient.fetch(t.element.src,{type:t.config.type,intensity:t.config.intensity,loop:t.config.loop});if(!i.success)throw new e(i.error||"Animation generation failed","API_ERROR");this.detector&&this.detector.updateImageState(t.id,{state:"playing",animationData:i}),"video"!==n&&(this.renderer.play(t,i,{intensity:t.config.intensity,loop:t.config.loop,onComplete:()=>{this.detector&&this.detector.updateImageState(t.id,{state:"idle"}),this.emitEvent("animationComplete",t)}}),this.emitEvent("animationStart",t)),"css"!==n&&this.veoClient&&this.videoRenderer&&this.startVideoGeneration(t)}catch(a){const i=a instanceof e?a:new e(a instanceof Error?a.message:"Unknown error","UNKNOWN_ERROR",a instanceof Error?a:void 0);this.detector&&this.detector.updateImageState(t.id,{state:"error",error:i}),null==(o=this.options)||o.debug,this.emitEvent("animationError",t,i)}}async startVideoGeneration(e){var t,i,s,o,n;if(!this.veoClient||!this.videoRenderer)return;const a=this.veoClient.getCachedVideo(e.element.src);if(a)return null==(t=this.options)||t.debug,void this.transitionToVideo(e,a);this.emitVideoEvent("videoStart",e),null==(i=this.options)||i.debug;try{const t=await this.veoClient.startGeneration({imageUrl:e.element.src});if(!t.success||!t.operationId)throw new Error((null==(s=t.error)?void 0:s.message)||"Failed to start video generation");if("completed"===t.status&&t.videoUrl)return void this.transitionToVideo(e,t.videoUrl);this.pendingVideoGenerations.set(e.id,t.operationId);const i=await this.veoClient.pollUntilComplete(t.operationId,e.element.src,(e,t)=>{var i;null==(i=this.options)||i.debug});this.pendingVideoGenerations.delete(e.id),i?this.transitionToVideo(e,i):(null==(o=this.options)||o.debug,this.emitVideoEvent("videoError",e))}catch(r){this.pendingVideoGenerations.delete(e.id),null==(n=this.options)||n.debug,this.emitVideoEvent("videoError",e)}}async transitionToVideo(e,t){var i,s;if(!this.videoRenderer)return;null==(i=this.options)||i.debug;await this.videoRenderer.prepareVideo(e.id,e.element,t,()=>{var e;null==(e=this.options)||e.debug})&&(null==(s=this.renderer)||s.stop(e.id),this.videoRenderer.play(e.id),this.emitVideoEvent("videoReady",e,t))}pauseAnimation(e){var t;this.renderer&&this.renderer.pause(e.id),this.detector&&this.detector.updateImageState(e.id,{state:"paused"}),null==(t=this.options)||t.debug,this.emitEvent("animationPause",e)}resumeAnimation(e){var t;this.renderer&&this.renderer.resume(e.id),this.detector&&this.detector.updateImageState(e.id,{state:"playing"}),null==(t=this.options)||t.debug,this.emitEvent("animationResume",e)}emitEvent(e,t,i){if("undefined"!=typeof CustomEvent){const s={type:e,timestamp:Date.now(),element:t.element,imageId:t.id,...i&&{error:i}},o=new CustomEvent(`beautifi:${e}`,{detail:s});document.dispatchEvent(o)}}emitVideoEvent(e,t,i){if("undefined"!=typeof CustomEvent){const s={type:e,timestamp:Date.now(),element:t.element,imageId:t.id,...i&&{videoUrl:i}},o=new CustomEvent(`beautifi:${e}`,{detail:s});document.dispatchEvent(o)}}isInitialized(){return this.initialized}getOptions(){return this.options}getTrackedImages(){var e;return(null==(e=this.detector)?void 0:e.getTrackedImages())??[]}destroy(){this.veoClient&&(this.veoClient.cancelAllOperations(),this.veoClient=null),this.videoRenderer&&(this.videoRenderer.destroy(),this.videoRenderer=null),this.renderer&&(this.renderer.destroy(),this.renderer=null),this.detector&&(this.detector.destroy(),this.detector=null),this.viewportObserver&&(this.viewportObserver.destroy(),this.viewportObserver=null),this.apiClient=null,this.pendingVideoGenerations.clear(),this.initialized=!1,this.options=null}},v={init:e=>f.init(e),isInitialized:()=>f.isInitialized(),getOptions:()=>f.getOptions(),getTrackedImages:()=>f.getTrackedImages(),destroy:()=>f.destroy()},y=v;"undefined"!=typeof document&&document.addEventListener("DOMContentLoaded",()=>{const e=document.querySelector('script[data-api-key][src*="beautifi"], script[data-api-key][src*="live-my-photos"]');if(e){const t=e.dataset.apiKey,i="false"!==e.dataset.autoInit;t&&i&&v.init({apiKey:t,selector:e.dataset.selector,intensity:e.dataset.intensity,type:e.dataset.type,loop:"false"!==e.dataset.loop,debug:"true"===e.dataset.debug,mode:e.dataset.mode||"auto"})}}),"undefined"!=typeof window&&(window.beautifi=v,window.LiveMyPhotos=v),exports.AnimationRenderer=c,exports.DEFAULT_ANIMATION_CONFIG=i,exports.DEFAULT_OPTIONS=t,exports.GeminiApiClient=r,exports.ImageDetector=s,exports.LiveMyPhotos=y,exports.LivePhotoError=e,exports.VeoClient=m,exports.VideoRenderer=g,exports.ViewportObserver=o,exports.beautifi=v,exports.default=v;
|
|
2
2
|
//# sourceMappingURL=beautifi.cjs.js.map
|