UNPKG

adam-sdk

Version:

A JavaScript SDK for integrating A.D.A.M. 3D avatars into web applications.

2 lines (1 loc) 3.9 kB
(function(r,a){typeof exports=="object"&&typeof module<"u"?a(exports):typeof define=="function"&&define.amd?define(["exports"],a):(r=typeof globalThis<"u"?globalThis:r||self,a(r.AvatarSDK={}))})(this,function(r){"use strict";class a{iframe;targetOrigin;eventListeners=new Map;pendingCommands=new Map;isReady=!1;handshakeInterval;fastPollInterval;logLevel;constructor(e,n={}){this.iframe=e,this.targetOrigin=n.targetOrigin||new URL(e.src).origin,this.logLevel=n.logLevel||"info",window.addEventListener("message",this._handleMessage.bind(this)),this._log("info","AvatarSDK: Message listener attached")}connect(){return new Promise((e,n)=>{if(this.isReady)return e();const t=setTimeout(()=>{clearInterval(this.handshakeInterval),clearInterval(this.fastPollInterval),n(new Error("Connection timed out. The avatar did not respond."))},1e4);this.iframe.onerror=()=>{clearTimeout(t),clearInterval(this.handshakeInterval),clearInterval(this.fastPollInterval),n(new Error("The avatar iframe failed to load."))},this.on("ready",()=>{clearTimeout(t),clearInterval(this.handshakeInterval),clearInterval(this.fastPollInterval),e()}),this._postMessage({type:"CHECK_READY_STATUS"});let s=0;this.fastPollInterval=setInterval(()=>{s<8?(this._postMessage({type:"CHECK_READY_STATUS"}),s++):(clearInterval(this.fastPollInterval),this.handshakeInterval=setInterval(()=>{this.isReady||this._postMessage({type:"CHECK_READY_STATUS"})},500))},250)})}speak(e,n={}){let t;if(typeof e=="string"){const s=e,i=n||{};if(!s||!s.trim())return Promise.reject(new Error("Text must be a non-empty string"));t={...i,text:s}}else if(typeof e=="object"&&e!==null){if(t={...e},typeof t.text!="string"||!t.text.trim())return Promise.reject(new Error("payload.text must be a non-empty string"))}else return Promise.reject(new Error("Invalid arguments to speak"));return console.log("[AvatarSDK] speak",t),this._sendCommand("speak",t)}playAnimation(e,n=!1){return this._sendCommand("playAnimation",{name:e,loop:n})}setExpression(e){return this._sendCommand("setExpression",{name:e})}interrupt(){return this._sendCommand("interrupt")}on(e,n){this.eventListeners.has(e)||this.eventListeners.set(e,[]),this.eventListeners.get(e)?.push(n)}off(e,n){const t=this.eventListeners.get(e);if(t){const s=t.indexOf(n);s>-1&&t.splice(s,1)}}destroy(){window.removeEventListener("message",this._handleMessage.bind(this)),clearInterval(this.handshakeInterval),clearInterval(this.fastPollInterval),this.eventListeners.clear(),this.pendingCommands.clear(),this.isReady=!1}_sendCommand(e,n={}){if(!this.isReady)return Promise.reject(new Error("Not connected to avatar."));const t=`cmd_${Date.now()}_${Math.random().toString(36).substr(2,9)}`,s={type:"AVATAR_COMMAND",command:e,payload:n,commandId:t};return new Promise((i,o)=>{const l=setTimeout(()=>{this.pendingCommands.has(t)&&(this.pendingCommands.delete(t),o(new Error(`Command '${e}' timed out after 30s`)))},3e4);this.pendingCommands.set(t,{resolve:i,reject:o,timeout:l}),this._postMessage(s)})}_handleMessage(e){if(e.origin!==this.targetOrigin)return;const{type:n,commandId:t,event:s,payload:i}=e.data;if(n==="AVATAR_READY"){this.isReady=!0,this._emitEvent("ready",void 0);return}if(n==="AVATAR_EVENT"&&(this._emitEvent(s,i),t&&this.pendingCommands.has(t))){const{resolve:o,reject:l,timeout:d}=this.pendingCommands.get(t);clearTimeout(d),s==="command:success"?o(i):s==="command:error"&&l(new Error(i?.error||"Command failed")),this.pendingCommands.delete(t)}}_postMessage(e){this.iframe.contentWindow&&this.iframe.contentWindow.postMessage(e,this.targetOrigin)}_log(e,n){if(this.logLevel==="none"||e==="none")return;const t={error:1,warn:2,info:3};t[e]<=t[this.logLevel]&&console[e](n)}_emitEvent(e,n){const t=this.eventListeners.get(e);t&&t.forEach(s=>{try{s(n)}catch(i){console.error(`Error in event listener for ${e}:`,i)}})}}r.AvatarSDK=a,Object.defineProperty(r,Symbol.toStringTag,{value:"Module"})});