@diabolic/pointy 1.0.0

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.
@@ -0,0 +1,2 @@
1
+ !function(t,e){"object"==typeof exports&&"undefined"!=typeof module?module.exports=e():"function"==typeof define&&define.amd?define(e):(t="undefined"!=typeof globalThis?globalThis:t||self).Pointy=e()}(this,function(){"use strict";class t{static EASINGS={default:"cubic-bezier(0, 0.55, 0.45, 1)",standard:"cubic-bezier(0.4, 0, 0.2, 1)",decelerate:"cubic-bezier(0, 0, 0.2, 1)",accelerate:"cubic-bezier(0.4, 0, 1, 1)",bounce:"cubic-bezier(0.68, -0.55, 0.265, 1.55)",elastic:"cubic-bezier(0.68, -0.6, 0.32, 1.6)",smooth:"cubic-bezier(0.45, 0, 0.55, 1)",snap:"cubic-bezier(0.5, 0, 0.1, 1)","expo-out":"cubic-bezier(0.19, 1, 0.22, 1)","circ-out":"cubic-bezier(0.075, 0.82, 0.165, 1)","back-out":"cubic-bezier(0.175, 0.885, 0.32, 1.275)"};static POINTER_SVG='\n <svg xmlns="http://www.w3.org/2000/svg" width="33" height="33" fill="none" viewBox="0 0 33 33">\n <g filter="url(#pointy-shadow)">\n <path fill="#0a1551" d="m18.65 24.262 6.316-14.905c.467-1.103-.645-2.215-1.748-1.747L8.313 13.925c-1.088.461-1.083 2.004.008 2.459l5.049 2.104c.325.135.583.393.718.718l2.104 5.049c.454 1.09 1.997 1.095 2.458.007"/>\n </g>\n <defs>\n <filter id="pointy-shadow" width="32.576" height="32.575" x="0" y="0" color-interpolation-filters="sRGB" filterUnits="userSpaceOnUse">\n <feFlood flood-opacity="0" result="BackgroundImageFix"/>\n <feColorMatrix in="SourceAlpha" result="hardAlpha" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0"/>\n <feOffset/>\n <feGaussianBlur stdDeviation="3.75"/>\n <feComposite in2="hardAlpha" operator="out"/>\n <feColorMatrix values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0.25 0"/>\n <feBlend in2="BackgroundImageFix" result="effect1_dropShadow"/>\n <feBlend in="SourceGraphic" in2="effect1_dropShadow" result="shape"/>\n </filter>\n </defs>\n </svg>\n ';static DEFAULT_CLASS_PREFIX="pointy";static DEFAULT_CLASS_SUFFIXES={container:"container",pointer:"pointer",bubble:"bubble",bubbleText:"bubble-text",hidden:"hidden",visible:"visible",moving:"moving"};static generateClassNames(e=t.DEFAULT_CLASS_PREFIX,s={}){const i={...t.DEFAULT_CLASS_SUFFIXES,...s};return{container:`${e}-${i.container}`,pointer:`${e}-${i.pointer}`,bubble:`${e}-${i.bubble}`,bubbleText:`${e}-${i.bubbleText}`,hidden:`${e}-${i.hidden}`,visible:`${e}-${i.visible}`,moving:`${e}-${i.moving}`}}static DEFAULT_CSS_VAR_PREFIX="pointy";static generateStyles(t,e="pointy"){const s=t,i=e;return`\n @keyframes ${s.container}-float {\n 0%, 100% {\n transform: translateY(0px);\n }\n 50% {\n transform: translateY(-8px);\n }\n }\n\n .${s.container} {\n position: absolute;\n z-index: 9999;\n font-family: 'Circular', -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;\n --${i}-duration: 1000ms;\n --${i}-easing: cubic-bezier(0, 0.55, 0.45, 1);\n --${i}-bubble-fade: 500ms;\n transition: left var(--${i}-duration) var(--${i}-easing), top var(--${i}-duration) var(--${i}-easing), opacity 0.3s ease;\n animation: ${s.container}-float 3s ease-in-out infinite;\n }\n\n .${s.container}.${s.moving} {\n animation-play-state: paused;\n }\n\n .${s.container}.${s.hidden} {\n opacity: 0;\n pointer-events: none;\n }\n\n .${s.container}.${s.visible} {\n opacity: 1;\n }\n\n .${s.pointer} {\n width: 33px;\n height: 33px;\n transition: transform var(--${i}-duration) var(--${i}-easing);\n }\n\n .${s.bubble} {\n position: absolute;\n right: 26px;\n top: 0;\n background: #0a1551;\n color: white;\n padding: 4px 12px;\n border-radius: 14px;\n font-size: 14px;\n line-height: 20px;\n font-weight: 400;\n box-shadow: 0 4px 15px rgba(0, 0, 0, 0.25);\n white-space: nowrap;\n overflow: hidden;\n transition: width 0.5s cubic-bezier(0.4, 0, 0.2, 1), height 0.5s cubic-bezier(0.4, 0, 0.2, 1), transform var(--${i}-duration) var(--${i}-easing), opacity var(--${i}-bubble-fade) ease;\n }\n\n .${s.bubbleText} {\n display: inline-block;\n }\n `}static injectedStyleKeys=new Set;static injectStyles(e,s="pointy"){const i=JSON.stringify(e)+s;if(t.injectedStyleKeys.has(i))return;if(!t.fontInjected){const e=document.createElement("link");e.href="https://cdn.jotfor.ms/fonts/?family=Circular",e.rel="stylesheet",document.head.appendChild(e),t.fontInjected=!0}const n=document.createElement("style");n.id=`pointy-styles-${i.length}`,n.textContent=t.generateStyles(e,s),document.head.appendChild(n),t.injectedStyleKeys.add(i)}static fontInjected=!1;static getTargetElement(t){return"string"==typeof t?document.querySelector(t):t}static animateText(e,s,i=500,n=null,a=null){const o=.4*i,r=.6*i;let h=null,l=null;if(n){const e=document.createElement("div");e.style.cssText="visibility: hidden; position: absolute; padding: 4px 12px;",t.renderContent(e,s),n.appendChild(e),h=e.offsetWidth,l=e.offsetHeight,n.removeChild(e);const i=n.offsetWidth,a=n.offsetHeight;n.style.width=i+"px",n.style.height=a+"px"}e.style.transition=`clip-path ${o}ms ease-in`,e.style.clipPath="inset(0 0 0 100%)",setTimeout(()=>{t.renderContent(e,s),n&&null!==h&&(n.style.width=h+"px",n.style.height=l+"px"),e.style.transition="none",e.style.clipPath="inset(0 100% 0 0)",e.offsetHeight,e.style.transition=`clip-path ${r}ms ease-out`,e.style.clipPath="inset(0 0 0 0)",n&&setTimeout(()=>{n.style.width="",n.style.height=""},r+100),a&&a()},o)}static renderContent(t,e){if(e&&"object"==typeof e&&e.$$typeof)if("undefined"!=typeof ReactDOM&&ReactDOM.createRoot){const s=ReactDOM.createRoot(t);s.render(e),t._reactRoot=s}else"undefined"!=typeof ReactDOM&&ReactDOM.render?ReactDOM.render(e,t):(console.warn("Pointy: React element passed but ReactDOM not found"),t.innerHTML=String(e));else t.innerHTML=e}constructor(e={}){if(this.classPrefix=e.classPrefix||t.DEFAULT_CLASS_PREFIX,this.classNames=t.generateClassNames(this.classPrefix,e.classSuffixes),e.classNames&&(this.classNames={...this.classNames,...e.classNames}),this.cssVarPrefix=e.cssVarPrefix||this.classPrefix,this.pointerSvg=e.pointerSvg||t.POINTER_SVG,t.injectStyles(this.classNames,this.cssVarPrefix),this.steps=e.steps||[],this.offsetX=void 0!==e.offsetX?e.offsetX:20,this.offsetY=void 0!==e.offsetY?e.offsetY:16,this.tracking=void 0===e.tracking||e.tracking,this.trackingFps=void 0!==e.trackingFps?e.trackingFps:60,this.animationDuration=void 0!==e.animationDuration?e.animationDuration:1e3,this.introFadeDuration=void 0!==e.introFadeDuration?e.introFadeDuration:1e3,this.bubbleFadeDuration=void 0!==e.bubbleFadeDuration?e.bubbleFadeDuration:500,this.messageTransitionDuration=void 0!==e.messageTransitionDuration?e.messageTransitionDuration:500,this.easing=void 0!==e.easing?e.easing:"default",this.resetOnComplete=void 0===e.resetOnComplete||e.resetOnComplete,this.floatingAnimation=void 0===e.floatingAnimation||e.floatingAnimation,this.initialPosition=e.initialPosition||"center",this.initialPositionOffset=void 0!==e.initialPositionOffset?e.initialPositionOffset:32,this.resetPositionOnHide=void 0!==e.resetPositionOnHide&&e.resetPositionOnHide,this.autoplay=e.autoplay||null,this.autoplayEnabled=void 0!==e.autoplayEnabled&&e.autoplayEnabled,this.autoplayWaitForMessages=void 0===e.autoplayWaitForMessages||e.autoplayWaitForMessages,this.hideOnComplete=void 0===e.hideOnComplete||e.hideOnComplete,this.hideOnCompleteDelay=void 0!==e.hideOnCompleteDelay?e.hideOnCompleteDelay:null,this._autoplayTimeoutId=null,this._autoplayPaused=!1,this._messagesCompletedForStep=!1,this._hideOnCompleteTimeoutId=null,this.onStepChange=e.onStepChange,this.onComplete=e.onComplete,this._eventListeners={},this.targetElement=e.target?t.getTargetElement(e.target):null,this.currentStepIndex=0,this.currentMessageIndex=0,this.currentMessages=[],this.messageInterval=e.messageInterval||null,this._messageIntervalId=null,this.isVisible=!1,this.isPointingUp=!0,this.lastTargetY=null,this.manualDirection=null,this.moveTimeout=null,this._hasShownBefore=!1,this.steps.length>0&&(this.targetElement=t.getTargetElement(this.steps[0].target)),this.container=document.createElement("div"),this.container.className=`${this.classNames.container} ${this.classNames.hidden}`,this.container.style.setProperty(`--${this.cssVarPrefix}-duration`,`${this.animationDuration}ms`),this.container.style.setProperty(`--${this.cssVarPrefix}-easing`,this._resolveEasing(this.easing)),this.container.style.setProperty(`--${this.cssVarPrefix}-bubble-fade`,`${this.bubbleFadeDuration}ms`),this.floatingAnimation||(this.container.style.animationPlayState="paused"),this.pointer=document.createElement("div"),this.pointer.className=this.classNames.pointer,t.renderContent(this.pointer,this.pointerSvg),this.bubble=document.createElement("div"),this.bubble.className=this.classNames.bubble,this.bubbleText=document.createElement("span"),this.bubbleText.className=this.classNames.bubbleText,this.steps.length>0){const e=this.steps[0].content;this.currentMessages=Array.isArray(e)?e:[e],t.renderContent(this.bubbleText,this.currentMessages[0])}else{const s=e.content||"";this.currentMessages=Array.isArray(s)?s:[s],t.renderContent(this.bubbleText,this.currentMessages[0])}this.currentMessageIndex=0,this.bubble.appendChild(this.bubbleText),this.container.appendChild(this.pointer),this.container.appendChild(this.bubble),this.updatePosition=this.updatePosition.bind(this),this._trackPosition=this._trackPosition.bind(this),this._lastTrackTime=0,window.addEventListener("resize",this.updatePosition),window.addEventListener("scroll",this.updatePosition)}_trackPosition(){if(this.isVisible&&this.targetElement){if(this.trackingFps>0){const t=performance.now(),e=1e3/this.trackingFps;t-this._lastTrackTime>=e&&(this._lastTrackTime=t,this.updatePosition(),this._emit("track",{target:this.targetElement,timestamp:t}))}else this.updatePosition(),this._emit("track",{target:this.targetElement,timestamp:performance.now()});this._rafId=requestAnimationFrame(this._trackPosition)}else this._rafId=null}_startTracking(){this.tracking&&(this._rafId||this._trackPosition())}_stopTracking(){this._rafId&&(cancelAnimationFrame(this._rafId),this._rafId=null)}updatePosition(){if(!this.targetElement)return;const t=this.targetElement.getBoundingClientRect(),e=window.scrollX,s=window.scrollY;if(null!==this.manualDirection)this.isPointingUp="up"===this.manualDirection;else{const e=t.top+s;if(null!==this.lastTargetY){const t=50;e<this.lastTargetY-t?this.isPointingUp=!0:e>this.lastTargetY+t&&(this.isPointingUp=!1)}this.lastTargetY=e}let i,n;if(this.isPointingUp)this.pointer.style.transform="rotate(0deg)",i=t.left+e-25+this.offsetX,n=t.bottom+s-8-this.offsetY,this.bubble.style.transform="translateY(28px)";else{this.pointer.style.transform="rotate(90deg)",i=t.left+e-25+this.offsetX,n=t.top+s-25+this.offsetY;const a=this.bubble.offsetHeight||28;this.bubble.style.transform=`translateY(-${a}px)`}this.container.style.left=`${i}px`,this.container.style.top=`${n}px`}show(){if(this._emit("beforeShow",{target:this.targetElement}),this._hideOnCompleteTimeoutId&&(clearTimeout(this._hideOnCompleteTimeoutId),this._hideOnCompleteTimeoutId=null),document.body.contains(this.container)||document.body.appendChild(this.container),!this._hasShownBefore){this._hasShownBefore=!0;const t="first-step"===this.initialPosition,e=this._getInitialPosition(),s=e.x,i=e.y;if(this.container.style.transition=`opacity ${this.introFadeDuration}ms ease`,this.pointer.style.transition="none",this.bubble.style.transition="none",this.bubble.style.opacity="0",this.container.style.left=`${s}px`,this.container.style.top=`${i}px`,t&&void 0!==e.isPointingUp)if(this.isPointingUp=e.isPointingUp,this.isPointingUp)this.pointer.style.transform="rotate(0deg)",this.bubble.style.transform="translateY(28px)";else{this.pointer.style.transform="rotate(90deg)";const t=this.bubble.offsetHeight||28;this.bubble.style.transform=`translateY(-${t}px)`}else this.pointer.style.transform="rotate(0deg)",this.bubble.style.transform="translateY(0)";return this.container.style.display="flex",this.container.offsetHeight,this.container.classList.remove(this.classNames.hidden),this.container.classList.add(this.classNames.visible),this.isVisible=!0,this._emit("introAnimationStart",{duration:this.introFadeDuration,initialPosition:{x:s,y:i}}),void setTimeout(()=>{this._emit("introAnimationEnd",{initialPosition:{x:s,y:i}}),t?(this.container.style.transition="none",this.pointer.style.transition="none",this._startTracking(),this.bubble.style.transition=`opacity ${this.bubbleFadeDuration}ms ease`,this.bubble.style.opacity="1",setTimeout(()=>{this.container.style.transition="",this.pointer.style.transition="",this.bubble.style.transition=""},this.bubbleFadeDuration),this.messageInterval&&this.currentMessages.length>1&&!this._messageIntervalId&&this._startMessageCycle(),this._scheduleAutoplay(),this._emit("show",{target:this.targetElement,isIntro:!0,isFirstStep:!0})):(this.container.style.transition="",this.pointer.style.transition="",this.bubble.style.transition="none",this.updatePosition(),this._startTracking(),setTimeout(()=>{this.bubble.style.transition="",this.bubble.style.opacity="1",this.messageInterval&&this.currentMessages.length>1&&!this._messageIntervalId&&this._startMessageCycle(),this._scheduleAutoplay()},this.animationDuration),this._emit("show",{target:this.targetElement,isIntro:!0,isFirstStep:!1}))},this.introFadeDuration)}this.container.style.display="flex",this.container.offsetHeight,this.container.classList.remove(this.classNames.hidden),this.container.classList.add(this.classNames.visible),this.isVisible=!0,this.updatePosition(),this._startTracking(),this._messageCyclePausedByHide&&this.messageInterval&&this.currentMessages.length>1?(this._startMessageCycle(),this._messageCyclePausedByHide=!1):this.messageInterval&&this.currentMessages.length>1&&!this._messageIntervalId&&this._startMessageCycle(),this._wasAutoplayActiveBeforeHide&&(this._scheduleAutoplay(),this._wasAutoplayActiveBeforeHide=!1),this._emit("show",{target:this.targetElement,isIntro:!1})}hide(){this._emit("beforeHide",{target:this.targetElement}),this.container.classList.remove(this.classNames.visible),this.container.classList.add(this.classNames.hidden),this.isVisible=!1,this.resetPositionOnHide&&(this._hasShownBefore=!1),this._stopTracking(),this._messageIntervalId&&(this._stopMessageCycle(),this._messageCyclePausedByHide=!0),this._wasAutoplayActiveBeforeHide=this.autoplay&&this.autoplayEnabled&&!this._autoplayPaused,this._stopAutoplay(),this._emit("hide",{target:this.targetElement})}restart(){this._emit("beforeRestart",{}),this._hasShownBefore=!1,this.isVisible?(this.container.classList.remove(this.classNames.visible),this.container.classList.add(this.classNames.hidden),this._stopTracking(),this._stopMessageCycle(),this.isVisible=!1,setTimeout(()=>{this.goToStep(0),this.show(),this._emit("restart",{})},50)):(this.goToStep(0),this.show(),this._emit("restart",{}))}destroy(){this._emit("destroy",{}),document.body.contains(this.container)&&document.body.removeChild(this.container),window.removeEventListener("resize",this.updatePosition),window.removeEventListener("scroll",this.updatePosition),this._stopTracking(),this._hideOnCompleteTimeoutId&&(clearTimeout(this._hideOnCompleteTimeoutId),this._hideOnCompleteTimeoutId=null),this._eventListeners={}}reset(e=!0){this._emit("beforeReset",{currentStep:this.currentStepIndex}),this._stopMessageCycle(),this._hideOnCompleteTimeoutId&&(clearTimeout(this._hideOnCompleteTimeoutId),this._hideOnCompleteTimeoutId=null),this.container.classList.add(this.classNames.moving),this.moveTimeout&&clearTimeout(this.moveTimeout);const{x:s,y:i}=this._getInitialPosition();if(this.container.style.left=`${s}px`,this.container.style.top=`${i}px`,this.bubble.style.opacity="0",e&&this.steps.length>0){this.currentStepIndex=0;const e=this.steps[0];this.targetElement=t.getTargetElement(e.target),this.currentMessages=Array.isArray(e.content)?e.content:[e.content],this.currentMessageIndex=0,t.renderContent(this.bubbleText,this.currentMessages[0])}this.moveTimeout=setTimeout(()=>{this.container.classList.remove(this.classNames.moving),this._hasShownBefore=!1,this._emit("reset",{stepIndex:this.currentStepIndex})},this.animationDuration)}setResetOnComplete(t){const e=this.resetOnComplete;e!==t&&(this.resetOnComplete=t,this._emit("resetOnCompleteChange",{from:e,to:t}))}setFloatingAnimation(t){const e=this.floatingAnimation;e!==t&&(this.floatingAnimation=t,this.container.style.animationPlayState=t?"":"paused",this._emit("floatingAnimationChange",{from:e,to:t}))}isFloatingAnimationEnabled(){return this.floatingAnimation}setTracking(t){const e=this.tracking;e!==t&&(this.tracking=t,t&&this.isVisible?this._startTracking():t||this._stopTracking(),this._emit("trackingChange",{from:e,to:t}))}setTrackingFps(t){const e=this.trackingFps;e!==t&&(this.trackingFps=t,this._emit("trackingFpsChange",{from:e,to:t}))}isTrackingEnabled(){return this.tracking}updateContent(e,s=!0){"string"==typeof e&&this.bubbleText.innerHTML===e||(s?t.animateText(this.bubbleText,e,this.messageTransitionDuration,this.bubble,()=>{this.updatePosition()}):(t.renderContent(this.bubbleText,e),this.updatePosition()))}_setMessages(t,e=!1){const s=null!==this._messageIntervalId;this._stopMessageCycle(),this.currentMessages=Array.isArray(t)?t:[t],this.currentMessageIndex=0,this.updateContent(this.currentMessages[0]),e&&this.messageInterval&&this.currentMessages.length>1?this._startMessageCycle():s&&this.currentMessages.length>1&&(this._messageCyclePaused=!0),this._emit("messagesSet",{messages:this.currentMessages,total:this.currentMessages.length,cyclePaused:!0===this._messageCyclePaused})}_startMessageCycle(){this._messagesCompletedForStep=!1,this._messageIntervalId=setInterval(()=>{this.currentMessageIndex===this.currentMessages.length-1&&this.autoplay&&this.autoplayWaitForMessages?(this._stopMessageCycle(),this._messagesCompletedForStep=!0,this._emit("messageCycleComplete",{stepIndex:this.currentStepIndex,totalMessages:this.currentMessages.length}),this._scheduleAutoplayAfterMessages()):this.nextMessage(!0)},this.messageInterval),this._emit("messageCycleStart",{interval:this.messageInterval,totalMessages:this.currentMessages.length})}_stopMessageCycle(){this._messageIntervalId&&(clearInterval(this._messageIntervalId),this._messageIntervalId=null,this._emit("messageCycleStop",{currentIndex:this.currentMessageIndex}))}pauseMessageCycle(){this._messageIntervalId&&(clearInterval(this._messageIntervalId),this._messageIntervalId=null,this._messageCyclePaused=!0,this._emit("messageCyclePause",{currentIndex:this.currentMessageIndex}))}resumeMessageCycle(){return!!(this._messageCyclePaused&&this.messageInterval&&this.currentMessages.length>1)&&(this._messageCyclePaused=!1,this._startMessageCycle(),this._emit("messageCycleResume",{currentIndex:this.currentMessageIndex}),!0)}startMessageCycle(t){return!this._messageIntervalId&&(!(this.currentMessages.length<=1)&&(void 0!==t&&(this.messageInterval=t),!!this.messageInterval&&(this._messageCyclePaused=!1,this._startMessageCycle(),!0)))}stopMessageCycle(){return!!this._messageIntervalId&&(this._stopMessageCycle(),this._messageCyclePaused=!1,!0)}isMessageCycleActive(){return null!==this._messageIntervalId}isMessageCyclePaused(){return!0===this._messageCyclePaused}nextMessage(t=!1){if(this.currentMessages.length<=1)return!1;const e=this.currentMessageIndex;return this.currentMessageIndex=(this.currentMessageIndex+1)%this.currentMessages.length,this.updateContent(this.currentMessages[this.currentMessageIndex]),this._emit("messageChange",{fromIndex:e,toIndex:this.currentMessageIndex,message:this.currentMessages[this.currentMessageIndex],total:this.currentMessages.length,isAuto:t}),!0}prevMessage(){if(this.currentMessages.length<=1)return!1;const t=this.currentMessageIndex;return this.currentMessageIndex=(this.currentMessageIndex-1+this.currentMessages.length)%this.currentMessages.length,this.updateContent(this.currentMessages[this.currentMessageIndex]),this._emit("messageChange",{fromIndex:t,toIndex:this.currentMessageIndex,message:this.currentMessages[this.currentMessageIndex],total:this.currentMessages.length}),!0}goToMessage(t){if(t<0||t>=this.currentMessages.length)return;const e=this.currentMessageIndex;this.currentMessageIndex=t,this.updateContent(this.currentMessages[this.currentMessageIndex]),this._emit("messageChange",{fromIndex:e,toIndex:this.currentMessageIndex,message:this.currentMessages[this.currentMessageIndex],total:this.currentMessages.length})}getCurrentMessage(){return this.currentMessageIndex}getTotalMessages(){return this.currentMessages.length}setContent(e,s=!0){const i=null!==this._messageIntervalId;s?this._setMessages(e,!1):(this._stopMessageCycle(),this.currentMessages=Array.isArray(e)?e:[e],this.currentMessageIndex=0,t.renderContent(this.bubbleText,this.currentMessages[0]),this.updatePosition(),i&&this.currentMessages.length>1&&(this._messageCyclePaused=!0)),this._emit("contentSet",{messages:this.currentMessages,total:this.currentMessages.length,animated:s,cyclePaused:!0===this._messageCyclePaused})}setMessageInterval(t){const e=this.messageInterval;e!==t&&(this.messageInterval=t,this._stopMessageCycle(),t&&this.currentMessages.length>1&&this._startMessageCycle(),this._emit("messageIntervalChange",{from:e,to:t}))}updateTarget(e){const s=this.targetElement;this.targetElement=t.getTargetElement(e),this.updatePosition(),this._emit("targetChange",{from:s,to:this.targetElement})}setOffset(t,e){const s=this.offsetX,i=this.offsetY;s===t&&i===e||(this.offsetX=t,this.offsetY=e,this.updatePosition(),this._emit("offsetChange",{from:{x:s,y:i},to:{x:t,y:e}}))}setAnimationDuration(t){const e=this.animationDuration;e!==t&&(this.animationDuration=t,this.container.style.setProperty(`--${this.cssVarPrefix}-duration`,`${t}ms`),this._emit("animationDurationChange",{from:e,to:t}))}setIntroFadeDuration(t){const e=this.introFadeDuration;e!==t&&(this.introFadeDuration=t,this._emit("introFadeDurationChange",{from:e,to:t}))}setBubbleFadeDuration(t){const e=this.bubbleFadeDuration;e!==t&&(this.bubbleFadeDuration=t,this.container.style.setProperty(`--${this.cssVarPrefix}-bubble-fade`,`${t}ms`),this._emit("bubbleFadeDurationChange",{from:e,to:t}))}_getInitialPosition(){const e=this.initialPositionOffset,s=window.innerWidth,i=window.innerHeight;if("first-step"===this.initialPosition&&this.steps.length>0){const e=this.steps[0],s=t.getTargetElement(e.target);if(s){const t=s.getBoundingClientRect(),i=window.scrollX,n=window.scrollY,a="down"!==e.direction;let o,r;return a?(o=t.left+i-25+this.offsetX,r=t.bottom+n-8-this.offsetY):(o=t.left+i-25+this.offsetX,r=t.top+n-25+this.offsetY),{x:o,y:r,isPointingUp:a}}}if(this.initialPosition&&"string"!=typeof this.initialPosition){const t=this.initialPosition.getBoundingClientRect();return{x:t.left+t.width/2,y:t.top+t.height/2}}if("string"==typeof this.initialPosition&&(this.initialPosition.startsWith("#")||this.initialPosition.startsWith("."))){const t=document.querySelector(this.initialPosition);if(t){const e=t.getBoundingClientRect();return{x:e.left+e.width/2,y:e.top+e.height/2}}}const n={center:{x:s/2,y:i/2},"top-left":{x:e,y:e},"top-center":{x:s/2,y:e},"top-right":{x:s-e,y:e},"middle-left":{x:e,y:i/2},"middle-right":{x:s-e,y:i/2},"bottom-left":{x:e,y:i-e},"bottom-center":{x:s/2,y:i-e},"bottom-right":{x:s-e,y:i-e}};return n[this.initialPosition]||n.center}setInitialPosition(t){const e=["center","top-left","top-center","top-right","middle-left","middle-right","bottom-left","bottom-center","bottom-right","first-step"];if("string"==typeof t&&!t.startsWith("#")&&!t.startsWith(".")&&!e.includes(t))return void console.warn(`Invalid initial position: ${t}. Valid presets: ${e.join(", ")}. Or use a CSS selector or DOM element.`);const s=this.initialPosition;s!==t&&(this.initialPosition=t,this._emit("initialPositionChange",{from:s,to:t}))}animateToInitialPosition(){if(!this.isVisible)return;const{x:t,y:e}=this._getInitialPosition();this._stopTracking(),this.container.style.cssText=`\n position: fixed;\n left: ${t}px;\n top: ${e}px;\n opacity: 0;\n transition: none;\n `,this.bubble.style.opacity="0",this.bubble.style.transition="none",this.container.offsetHeight,this.container.style.transition=`opacity ${this.introFadeDuration}ms ease`,this.container.style.opacity="1",setTimeout(()=>{this.container.style.transition="",this.container.style.cssText="",this.container.style.left=`${t}px`,this.container.style.top=`${e}px`,this.container.offsetHeight,this.updatePosition(),this._startTracking(),setTimeout(()=>{this.bubble.style.transition="",this.bubble.style.opacity="1"},this.animationDuration)},this.introFadeDuration)}setInitialPositionOffset(t){const e=this.initialPositionOffset;e!==t&&(this.initialPositionOffset=t,this._emit("initialPositionOffsetChange",{from:e,to:t}))}_resolveEasing(e){return t.EASINGS[e]?t.EASINGS[e]:e}setEasing(t){const e=this.easing;e!==t&&(this.easing=t,this.container.style.setProperty(`--${this.cssVarPrefix}-easing`,this._resolveEasing(t)),this._emit("easingChange",{from:e,to:t}))}setMessageTransitionDuration(t){const e=this.messageTransitionDuration;e!==t&&(this.messageTransitionDuration=t,this._emit("messageTransitionDurationChange",{from:e,to:t}))}setPointerSvg(e){const s=this.pointerSvg;s!==e&&(this.pointerSvg=e,t.renderContent(this.pointer,e),this._emit("pointerSvgChange",{from:s,to:e}))}getPointerSvg(){return this.pointerSvg}getClassNames(){return{...this.classNames}}getClassPrefix(){return this.classPrefix}getCssVarPrefix(){return this.cssVarPrefix}static getEasingPresets(){return Object.keys(t.EASINGS)}static getInitialPositions(){return["center","top-left","top-center","top-right","middle-left","middle-right","bottom-left","bottom-center","bottom-right","first-step"]}goToStep(e){if(0===this.steps.length||e<0||e>=this.steps.length)return;this._stopAutoplay(),this._messagesCompletedForStep=!1;const s=this.currentStepIndex,i=this.targetElement;this.currentStepIndex=e;const n=this.steps[this.currentStepIndex];this._emit("beforeStepChange",{fromIndex:s,toIndex:e,step:n,fromTarget:i}),this.manualDirection=n.direction||null,this.container.classList.add(this.classNames.moving),this.moveTimeout&&clearTimeout(this.moveTimeout),this._emit("animationStart",{fromTarget:i,toTarget:t.getTargetElement(n.target),type:"step",stepIndex:e}),this.moveTimeout=setTimeout(()=>{this.container.classList.remove(this.classNames.moving),this._emit("moveComplete",{index:e,step:n,target:this.targetElement}),this._emit("animationEnd",{fromTarget:i,toTarget:this.targetElement,type:"step",stepIndex:e}),this._scheduleAutoplay()},this.animationDuration),this._emit("move",{index:e,step:n}),this._setMessages(n.content,!0),this.targetElement=t.getTargetElement(n.target),this.updatePosition(),this._emit("stepChange",{fromIndex:s,toIndex:e,step:n,target:this.targetElement}),this.onStepChange&&this.onStepChange(this.currentStepIndex,n)}_scheduleAutoplay(){if(!this.autoplay||!this.autoplayEnabled||this._autoplayPaused||!this.isVisible)return;const t=this.steps[this.currentStepIndex],e=this.currentMessages.length>1&&this.messageInterval;if(this.autoplayWaitForMessages&&e)return;const s=void 0!==t.duration?t.duration:this.autoplay;s&&s>0&&(this._autoplayTimeoutId=setTimeout(()=>{!this._autoplayPaused&&this.isVisible&&this.autoplayEnabled&&(this._emit("autoplayNext",{fromIndex:this.currentStepIndex,duration:s}),this.next())},s))}_scheduleAutoplayAfterMessages(){if(!this.autoplay||!this.autoplayEnabled||this._autoplayPaused||!this.isVisible)return;this._autoplayTimeoutId=setTimeout(()=>{!this._autoplayPaused&&this.isVisible&&this._messagesCompletedForStep&&(this._emit("autoplayNext",{fromIndex:this.currentStepIndex,afterMessages:!0}),this.next())},300)}_stopAutoplay(){this._autoplayTimeoutId&&(clearTimeout(this._autoplayTimeoutId),this._autoplayTimeoutId=null)}startAutoplay(){this.autoplay&&(this.autoplayEnabled=!0,this._autoplayPaused=!1,this._emit("autoplayStart",{}),this._scheduleAutoplay())}stopAutoplay(){this._stopAutoplay(),this.autoplayEnabled=!1,this._autoplayPaused=!1,this._emit("autoplayStop",{})}pauseAutoplay(){this._stopAutoplay(),this._autoplayPaused=!0,this._emit("autoplayPause",{})}resumeAutoplay(){this._autoplayPaused&&(this._autoplayPaused=!1,this._emit("autoplayResume",{}),this._scheduleAutoplay())}isAutoplayActive(){return this.autoplay&&this.autoplayEnabled&&!this._autoplayPaused}isAutoplayPaused(){return this._autoplayPaused}setAutoplayInterval(t){const e=this.autoplay;e!==t&&(this.autoplay=t,this._emit("autoplayChange",{from:e,to:t}),this.autoplayEnabled&&t&&this.isVisible?(this._stopAutoplay(),this._scheduleAutoplay()):t||(this._stopAutoplay(),this.autoplayEnabled=!1))}setAutoplay(t){this.setAutoplayInterval(t),t&&this.isVisible&&(this.autoplayEnabled=!0,this._autoplayPaused=!1,this.restart())}setAutoplayWaitForMessages(t){const e=this.autoplayWaitForMessages;e!==t&&(this.autoplayWaitForMessages=t,this._emit("autoplayWaitForMessagesChange",{from:e,to:t}))}setHideOnComplete(t){const e=this.hideOnComplete;e!==t&&(this.hideOnComplete=t,this._emit("hideOnCompleteChange",{from:e,to:t}))}setHideOnCompleteDelay(t){const e=this.hideOnCompleteDelay;e!==t&&(this.hideOnCompleteDelay=t,this._emit("hideOnCompleteDelayChange",{from:e,to:t}))}next(){if(0!==this.steps.length)if(this.currentStepIndex<this.steps.length-1)this._emit("next",{fromIndex:this.currentStepIndex,toIndex:this.currentStepIndex+1}),this.goToStep(this.currentStepIndex+1);else{const t=this.autoplay&&this.autoplayEnabled&&!this._autoplayPaused;if(this._emit("complete",{totalSteps:this.steps.length,source:t?"autoplay":"manual"}),t&&(this._stopAutoplay(),this.autoplayEnabled=!1,this._emit("autoplayComplete",{totalSteps:this.steps.length})),this.resetOnComplete){if(this.reset(),this.hideOnComplete){const e=null!==this.hideOnCompleteDelay?this.hideOnCompleteDelay:this.animationDuration,s=t?"autoplay":"manual";this._hideOnCompleteTimeoutId=setTimeout(()=>{this.hide(),this._emit("autoHide",{delay:e,source:s})},this.animationDuration+e)}}else if(this.hideOnComplete){const e=null!==this.hideOnCompleteDelay?this.hideOnCompleteDelay:this.animationDuration,s=t?"autoplay":"manual";this._hideOnCompleteTimeoutId=setTimeout(()=>{this.hide(),this._emit("autoHide",{delay:e,source:s})},e)}this.onComplete&&this.onComplete()}}prev(){0!==this.steps.length&&this.currentStepIndex>0&&(this._emit("prev",{fromIndex:this.currentStepIndex,toIndex:this.currentStepIndex-1}),this.goToStep(this.currentStepIndex-1))}getCurrentStep(){return this.currentStepIndex}getTotalSteps(){return this.steps.length}pointTo(e,s,i){const n=this.targetElement;this._emit("beforePointTo",{target:t.getTargetElement(e),content:s,direction:i,fromTarget:n}),this.manualDirection=i||null,this.container.classList.add(this.classNames.moving),this.moveTimeout&&clearTimeout(this.moveTimeout);const a=t.getTargetElement(e);this._emit("animationStart",{fromTarget:n,toTarget:a,type:"pointTo",content:s}),this.moveTimeout=setTimeout(()=>{this.container.classList.remove(this.classNames.moving),this._emit("pointToComplete",{target:this.targetElement,content:s}),this._emit("animationEnd",{fromTarget:n,toTarget:this.targetElement,type:"pointTo",content:s})},this.animationDuration),this.targetElement=a,void 0!==s&&this._setMessages(s,!1),this.updatePosition(),this._emit("pointTo",{target:this.targetElement,content:s,direction:i}),this.isVisible||this.show()}on(t,e){return this._eventListeners[t]||(this._eventListeners[t]=[]),this._eventListeners[t].push(e),this}off(t,e){return this._eventListeners[t]?(e?this._eventListeners[t]=this._eventListeners[t].filter(t=>t!==e):delete this._eventListeners[t],this):this}_emit(e,s){const i={...s,type:e,pointy:this};this._eventListeners[e]&&this._eventListeners[e].forEach(t=>{try{t(i)}catch(t){console.error(`Pointy: Error in ${e} event handler:`,t)}});const n=t.getEventGroup(e);n&&this._eventListeners[n]&&this._eventListeners[n].forEach(t=>{try{t(i)}catch(t){console.error(`Pointy: Error in ${n} group handler for ${e}:`,t)}}),["*","all"].forEach(t=>{this._eventListeners[t]&&this._eventListeners[t].forEach(t=>{try{t(i)}catch(t){console.error(`Pointy: Error in wildcard handler for ${e}:`,t)}})})}static getEventGroup(e){for(const[s,i]of Object.entries(t.EVENT_GROUPS))if(i.includes(e))return s;return e.endsWith("Change")?"config":null}static getEventsInGroup(e){return t.EVENT_GROUPS[e]||[]}}return t.EVENT_GROUPS={lifecycle:["beforeShow","show","beforeHide","hide","destroy","beforeRestart","restart","beforeReset","reset"],navigation:["beforeStepChange","stepChange","next","prev","complete"],animation:["animationStart","animationEnd","move","moveComplete","introAnimationStart","introAnimationEnd"],content:["contentSet","messagesSet","messageChange"],messageCycle:["messageCycleStart","messageCycleStop","messageCyclePause","messageCycleResume","messageCycleComplete"],pointing:["beforePointTo","pointTo","pointToComplete"],tracking:["track","targetChange","trackingChange","trackingFpsChange"],autoplay:["autoplayStart","autoplayStop","autoplayPause","autoplayResume","autoplayNext","autoplayComplete","autoHide","autoplayChange","autoplayWaitForMessagesChange"]},t});
2
+ //# sourceMappingURL=pointy.min.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"pointy.min.js","sources":["../src/pointy.js"],"sourcesContent":["/**\n * Pointy - A lightweight tooltip library with animated pointer\n * \n * @description A vanilla JavaScript library for creating animated tooltips with a pointing cursor.\n * Features include multi-step tours, multi-message content, autoplay, custom SVG pointers,\n * and extensive customization options.\n * \n * @example\n * const pointy = new Pointy({\n * steps: [\n * { target: '#element1', content: 'Welcome!' },\n * { target: '#element2', content: ['Message 1', 'Message 2'] }\n * ],\n * autoplay: 3000,\n * messageInterval: 2500\n * });\n * pointy.show();\n * \n * @options\n * - steps {Array<{target, content, direction?, duration?}>} - Tour steps\n * - target {string|HTMLElement} - Initial target element\n * - offsetX {number} - Horizontal offset from target (default: 20)\n * - offsetY {number} - Vertical offset from target (default: 16)\n * - trackingFps {number} - Position update FPS, 0 = unlimited (default: 60)\n * - animationDuration {number} - Move animation duration in ms (default: 1000)\n * - introFadeDuration {number} - Initial fade-in duration in ms (default: 1000)\n * - bubbleFadeDuration {number} - Bubble fade-in duration in ms (default: 500)\n * - messageTransitionDuration {number} - Message change animation in ms (default: 500)\n * - easing {string} - Easing name or CSS timing function (default: 'default')\n * - messageInterval {number|null} - Auto-cycle messages interval in ms (default: null)\n * - resetOnComplete {boolean} - Reset to initial position on complete (default: true)\n * - floatingAnimation {boolean} - Enable floating animation (default: true)\n * - initialPosition {string|HTMLElement} - Starting position preset or element (default: 'center')\n * Presets: 'center', 'top-left', 'top-center', 'top-right', 'middle-left', \n * 'middle-right', 'bottom-left', 'bottom-center', 'bottom-right'\n * - initialPositionOffset {number} - Offset from edges for position presets (default: 32)\n * - resetPositionOnHide {boolean} - Reset position when hiding (default: false)\n * - autoplay {number|null} - Auto-advance interval in ms, null = manual (default: null)\n * - autoplayWaitForMessages {boolean} - Wait for all messages before advancing (default: true)\n * - classPrefix {string} - CSS class prefix (default: 'pointy')\n * - classSuffixes {object} - Custom class suffixes\n * - classNames {object} - Full override of class names\n * - cssVarPrefix {string} - CSS variable prefix (default: classPrefix)\n * - pointerSvg {string} - Custom SVG for pointer\n * - onStepChange {function} - Callback on step change\n * - onComplete {function} - Callback on tour complete\n * \n * @events\n * Lifecycle:\n * - beforeShow: Before pointer becomes visible\n * - show: Pointer becomes visible\n * - beforeHide: Before pointer is hidden\n * - hide: Pointer is hidden\n * - destroy: Instance is destroyed\n * - beforeRestart: Before restart\n * - restart: After restart completed\n * - beforeReset: Before reset to initial position\n * - reset: After reset to initial position\n * \n * Navigation:\n * - beforeStepChange: Before step transition\n * - stepChange: After step changed\n * - next: Moving to next step\n * - prev: Moving to previous step\n * - complete: Tour completed (last step finished)\n * \n * Animation:\n * - animationStart: Movement animation started\n * - animationEnd: Movement animation completed\n * - move: Position update started\n * - moveComplete: Position update finished\n * - introAnimationStart: Initial fade-in animation started\n * - introAnimationEnd: Initial fade-in animation completed\n * \n * Content:\n * - contentSet: Content updated via setContent()\n * - messagesSet: New messages array set for step\n * - messageChange: Message changed (manual or auto)\n * \n * Message Cycle:\n * - messageCycleStart: Auto message cycling started\n * - messageCycleStop: Auto message cycling stopped\n * - messageCyclePause: Message cycling paused\n * - messageCycleResume: Message cycling resumed\n * - messageCycleComplete: All messages shown (when autoplayWaitForMessages=true)\n * \n * Point To:\n * - beforePointTo: Before pointing to custom target\n * - pointTo: Pointed to custom target\n * - pointToComplete: Animation to custom target completed\n * \n * Target Tracking:\n * - track: Target position tracked (fires at trackingFps rate when enabled)\n * - targetChange: Target element changed\n * - trackingChange: Tracking enabled/disabled\n * - trackingFpsChange: Tracking FPS changed\n * \n * Autoplay:\n * - autoplayStart: Autoplay started\n * - autoplayStop: Autoplay stopped\n * - autoplayPause: Autoplay paused\n * - autoplayResume: Autoplay resumed\n * - autoplayNext: Auto-advancing to next step\n * - autoplayComplete: Autoplay finished all steps\n * - autoHide: Auto-hide triggered after complete\n * - autoplayChange: Autoplay interval changed\n * - autoplayWaitForMessagesChange: Wait for messages setting changed\n * \n * Configuration Changes:\n * - easingChange: Easing changed\n * - animationDurationChange: Animation duration changed\n * - introFadeDurationChange: Intro fade duration changed\n * - bubbleFadeDurationChange: Bubble fade duration changed\n * - messageIntervalChange: Message interval changed\n * - messageTransitionDurationChange: Message transition duration changed\n * - offsetChange: Offset changed\n * - resetOnCompleteChange: Reset on complete setting changed\n * - hideOnCompleteChange: Hide on complete setting changed\n * - hideOnCompleteDelayChange: Hide on complete delay changed\n * - floatingAnimationChange: Floating animation setting changed\n * - initialPositionChange: Initial position changed\n * - initialPositionOffsetChange: Initial position offset changed\n * - pointerSvgChange: Pointer SVG changed\n * \n * @methods\n * Core: show(), hide(), destroy()\n * Navigation: next(), prev(), goToStep(index), reset(), restart()\n * Custom Target: pointTo(target, content?, direction?)\n * Content: setContent(content), nextMessage(), prevMessage(), goToMessage(index)\n * Message Cycle: startMessageCycle(interval?), stopMessageCycle(), pauseMessageCycle(), resumeMessageCycle()\n * Autoplay: startAutoplay(), stopAutoplay(), pauseAutoplay(), resumeAutoplay()\n * Animation: animateToInitialPosition()\n * Events: on(event, callback), off(event, callback)\n * State: getCurrentStep(), getTotalSteps(), isAutoplayActive(), isAutoplayPaused()\n * \n * Setters (all emit change events):\n * setEasing(), setAnimationDuration(), setIntroFadeDuration(), setBubbleFadeDuration(),\n * setMessageInterval(), setMessageTransitionDuration(), setOffset(), setResetOnComplete(),\n * setFloatingAnimation(), setInitialPosition(), setInitialPositionOffset(),\n * setAutoplay(), setAutoplayWaitForMessages()\n * \n * Static Helpers:\n * - Pointy.renderContent(element, content) - Render string/JSX to element\n * - Pointy.getTargetElement(target) - Get DOM element from selector/element\n * - Pointy.generateClassNames(prefix, suffixes) - Generate class name object\n */\nclass Pointy {\n // Named easing presets (only custom ones, CSS built-ins like 'ease', 'linear' work directly)\n static EASINGS = {\n // Default - smooth deceleration\n 'default': 'cubic-bezier(0, 0.55, 0.45, 1)',\n // Material Design\n 'standard': 'cubic-bezier(0.4, 0, 0.2, 1)',\n 'decelerate': 'cubic-bezier(0, 0, 0.2, 1)',\n 'accelerate': 'cubic-bezier(0.4, 0, 1, 1)',\n // Expressive\n 'bounce': 'cubic-bezier(0.68, -0.55, 0.265, 1.55)',\n 'elastic': 'cubic-bezier(0.68, -0.6, 0.32, 1.6)',\n 'smooth': 'cubic-bezier(0.45, 0, 0.55, 1)',\n 'snap': 'cubic-bezier(0.5, 0, 0.1, 1)',\n // Classic easing curves\n 'expo-out': 'cubic-bezier(0.19, 1, 0.22, 1)',\n 'circ-out': 'cubic-bezier(0.075, 0.82, 0.165, 1)',\n 'back-out': 'cubic-bezier(0.175, 0.885, 0.32, 1.275)'\n };\n\n static POINTER_SVG = `\n <svg xmlns=\"http://www.w3.org/2000/svg\" width=\"33\" height=\"33\" fill=\"none\" viewBox=\"0 0 33 33\">\n <g filter=\"url(#pointy-shadow)\">\n <path fill=\"#0a1551\" d=\"m18.65 24.262 6.316-14.905c.467-1.103-.645-2.215-1.748-1.747L8.313 13.925c-1.088.461-1.083 2.004.008 2.459l5.049 2.104c.325.135.583.393.718.718l2.104 5.049c.454 1.09 1.997 1.095 2.458.007\"/>\n </g>\n <defs>\n <filter id=\"pointy-shadow\" width=\"32.576\" height=\"32.575\" x=\"0\" y=\"0\" color-interpolation-filters=\"sRGB\" filterUnits=\"userSpaceOnUse\">\n <feFlood flood-opacity=\"0\" result=\"BackgroundImageFix\"/>\n <feColorMatrix in=\"SourceAlpha\" result=\"hardAlpha\" values=\"0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0\"/>\n <feOffset/>\n <feGaussianBlur stdDeviation=\"3.75\"/>\n <feComposite in2=\"hardAlpha\" operator=\"out\"/>\n <feColorMatrix values=\"0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0.25 0\"/>\n <feBlend in2=\"BackgroundImageFix\" result=\"effect1_dropShadow\"/>\n <feBlend in=\"SourceGraphic\" in2=\"effect1_dropShadow\" result=\"shape\"/>\n </filter>\n </defs>\n </svg>\n `;\n\n // Default CSS class prefix\n static DEFAULT_CLASS_PREFIX = 'pointy';\n\n // Default class name suffixes - will be combined with prefix\n static DEFAULT_CLASS_SUFFIXES = {\n container: 'container',\n pointer: 'pointer',\n bubble: 'bubble',\n bubbleText: 'bubble-text',\n hidden: 'hidden',\n visible: 'visible',\n moving: 'moving'\n };\n\n /**\n * Generate class names from prefix and suffixes\n * @param {string} prefix - Class prefix\n * @param {object} suffixes - Custom suffixes to override defaults\n * @returns {object} - Full class names\n */\n static generateClassNames(prefix = Pointy.DEFAULT_CLASS_PREFIX, suffixes = {}) {\n const s = { ...Pointy.DEFAULT_CLASS_SUFFIXES, ...suffixes };\n return {\n container: `${prefix}-${s.container}`,\n pointer: `${prefix}-${s.pointer}`,\n bubble: `${prefix}-${s.bubble}`,\n bubbleText: `${prefix}-${s.bubbleText}`,\n hidden: `${prefix}-${s.hidden}`,\n visible: `${prefix}-${s.visible}`,\n moving: `${prefix}-${s.moving}`\n };\n }\n\n // CSS variable prefix (defaults to class prefix)\n static DEFAULT_CSS_VAR_PREFIX = 'pointy';\n\n /**\n * Generate CSS styles with custom class names\n * @param {object} classNames - Class names object\n * @param {string} cssVarPrefix - CSS variable prefix\n * @returns {string} - CSS styles\n */\n static generateStyles(classNames, cssVarPrefix = 'pointy') {\n const cn = classNames;\n const vp = cssVarPrefix;\n \n return `\n @keyframes ${cn.container}-float {\n 0%, 100% {\n transform: translateY(0px);\n }\n 50% {\n transform: translateY(-8px);\n }\n }\n\n .${cn.container} {\n position: absolute;\n z-index: 9999;\n font-family: 'Circular', -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;\n --${vp}-duration: 1000ms;\n --${vp}-easing: cubic-bezier(0, 0.55, 0.45, 1);\n --${vp}-bubble-fade: 500ms;\n transition: left var(--${vp}-duration) var(--${vp}-easing), top var(--${vp}-duration) var(--${vp}-easing), opacity 0.3s ease;\n animation: ${cn.container}-float 3s ease-in-out infinite;\n }\n\n .${cn.container}.${cn.moving} {\n animation-play-state: paused;\n }\n\n .${cn.container}.${cn.hidden} {\n opacity: 0;\n pointer-events: none;\n }\n\n .${cn.container}.${cn.visible} {\n opacity: 1;\n }\n\n .${cn.pointer} {\n width: 33px;\n height: 33px;\n transition: transform var(--${vp}-duration) var(--${vp}-easing);\n }\n\n .${cn.bubble} {\n position: absolute;\n right: 26px;\n top: 0;\n background: #0a1551;\n color: white;\n padding: 4px 12px;\n border-radius: 14px;\n font-size: 14px;\n line-height: 20px;\n font-weight: 400;\n box-shadow: 0 4px 15px rgba(0, 0, 0, 0.25);\n white-space: nowrap;\n overflow: hidden;\n transition: width 0.5s cubic-bezier(0.4, 0, 0.2, 1), height 0.5s cubic-bezier(0.4, 0, 0.2, 1), transform var(--${vp}-duration) var(--${vp}-easing), opacity var(--${vp}-bubble-fade) ease;\n }\n\n .${cn.bubbleText} {\n display: inline-block;\n }\n `;\n }\n\n // Track which style sets have been injected (by stringified classNames)\n static injectedStyleKeys = new Set();\n\n static injectStyles(classNames, cssVarPrefix = 'pointy') {\n const styleKey = JSON.stringify(classNames) + cssVarPrefix;\n if (Pointy.injectedStyleKeys.has(styleKey)) return;\n \n // Inject Circular font (only once)\n if (!Pointy.fontInjected) {\n const fontLink = document.createElement('link');\n fontLink.href = 'https://cdn.jotfor.ms/fonts/?family=Circular';\n fontLink.rel = 'stylesheet';\n document.head.appendChild(fontLink);\n Pointy.fontInjected = true;\n }\n \n const styleElement = document.createElement('style');\n styleElement.id = `pointy-styles-${styleKey.length}`;\n styleElement.textContent = Pointy.generateStyles(classNames, cssVarPrefix);\n document.head.appendChild(styleElement);\n Pointy.injectedStyleKeys.add(styleKey);\n }\n \n static fontInjected = false;\n\n static getTargetElement(target) {\n if (typeof target === 'string') {\n return document.querySelector(target);\n }\n return target;\n }\n\n static animateText(element, newContent, duration = 500, bubble = null, onComplete = null) {\n const hideTime = duration * 0.4;\n const revealTime = duration * 0.6;\n \n // Measure new content dimensions using a hidden container\n let newWidth = null;\n let newHeight = null;\n if (bubble) {\n const measureDiv = document.createElement('div');\n measureDiv.style.cssText = 'visibility: hidden; position: absolute; padding: 4px 12px;';\n Pointy.renderContent(measureDiv, newContent);\n bubble.appendChild(measureDiv);\n // Add horizontal padding (12px left + 12px right = 24px)\n newWidth = measureDiv.offsetWidth;\n newHeight = measureDiv.offsetHeight;\n bubble.removeChild(measureDiv);\n \n // Set current dimensions explicitly to enable transition\n const currentWidth = bubble.offsetWidth;\n const currentHeight = bubble.offsetHeight;\n bubble.style.width = currentWidth + 'px';\n bubble.style.height = currentHeight + 'px';\n }\n \n // Phase 1: Hide old text (clip from left, disappears to right)\n element.style.transition = `clip-path ${hideTime}ms ease-in`;\n element.style.clipPath = 'inset(0 0 0 100%)';\n \n setTimeout(() => {\n // Change content while fully clipped\n Pointy.renderContent(element, newContent);\n \n // Animate bubble to new size\n if (bubble && newWidth !== null) {\n bubble.style.width = newWidth + 'px';\n bubble.style.height = newHeight + 'px';\n }\n \n // Prepare for reveal (start fully clipped from right)\n element.style.transition = 'none';\n element.style.clipPath = 'inset(0 100% 0 0)';\n \n // Force reflow\n element.offsetHeight;\n \n // Phase 2: Reveal new text (appears from left to right)\n element.style.transition = `clip-path ${revealTime}ms ease-out`;\n element.style.clipPath = 'inset(0 0 0 0)';\n \n // Clear dimensions after transition so it can auto-size\n if (bubble) {\n setTimeout(() => {\n bubble.style.width = '';\n bubble.style.height = '';\n }, revealTime + 100);\n }\n \n if (onComplete) onComplete();\n }, hideTime);\n }\n\n /**\n * Render content to an element - supports string (HTML) and React/JSX elements\n * @param {HTMLElement} element - Target element\n * @param {string|object} content - String (HTML) or React element\n */\n static renderContent(element, content) {\n // Check if it's a React element (has $$typeof symbol)\n if (content && typeof content === 'object' && content.$$typeof) {\n // React element - use ReactDOM if available\n if (typeof ReactDOM !== 'undefined' && ReactDOM.createRoot) {\n // React 18+\n const root = ReactDOM.createRoot(element);\n root.render(content);\n element._reactRoot = root;\n } else if (typeof ReactDOM !== 'undefined' && ReactDOM.render) {\n // React 17 and below\n ReactDOM.render(content, element);\n } else {\n console.warn('Pointy: React element passed but ReactDOM not found');\n element.innerHTML = String(content);\n }\n } else {\n // String content - render as HTML\n element.innerHTML = content;\n }\n }\n\n constructor(options = {}) {\n // CSS class prefix\n this.classPrefix = options.classPrefix || Pointy.DEFAULT_CLASS_PREFIX;\n \n // Generate class names from prefix and optional custom suffixes\n this.classNames = Pointy.generateClassNames(this.classPrefix, options.classSuffixes);\n \n // Allow full override of class names if provided\n if (options.classNames) {\n this.classNames = { ...this.classNames, ...options.classNames };\n }\n \n // CSS variable prefix for avoiding conflicts (defaults to class prefix)\n this.cssVarPrefix = options.cssVarPrefix || this.classPrefix;\n \n // Custom SVG for pointer\n this.pointerSvg = options.pointerSvg || Pointy.POINTER_SVG;\n \n Pointy.injectStyles(this.classNames, this.cssVarPrefix);\n\n this.steps = options.steps || [];\n this.offsetX = options.offsetX !== undefined ? options.offsetX : 20;\n this.offsetY = options.offsetY !== undefined ? options.offsetY : 16;\n this.tracking = options.tracking !== undefined ? options.tracking : true; // Enable/disable position tracking\n this.trackingFps = options.trackingFps !== undefined ? options.trackingFps : 60; // 0 = unlimited\n this.animationDuration = options.animationDuration !== undefined ? options.animationDuration : 1000; // ms\n this.introFadeDuration = options.introFadeDuration !== undefined ? options.introFadeDuration : 1000; // ms - pointer fade-in\n this.bubbleFadeDuration = options.bubbleFadeDuration !== undefined ? options.bubbleFadeDuration : 500; // ms - bubble fade-in\n this.messageTransitionDuration = options.messageTransitionDuration !== undefined ? options.messageTransitionDuration : 500; // ms - message change animation\n this.easing = options.easing !== undefined ? options.easing : 'default'; // easing name or custom cubic-bezier\n this.resetOnComplete = options.resetOnComplete !== undefined ? options.resetOnComplete : true; // Reset to initial position on complete\n this.floatingAnimation = options.floatingAnimation !== undefined ? options.floatingAnimation : true; // Enable floating animation\n this.initialPosition = options.initialPosition || 'center'; // 'center', 'top-left', 'top-center', 'top-right', 'middle-left', 'middle-right', 'bottom-left', 'bottom-center', 'bottom-right'\n this.initialPositionOffset = options.initialPositionOffset !== undefined ? options.initialPositionOffset : 32; // Offset from edges for non-center positions\n this.resetPositionOnHide = options.resetPositionOnHide !== undefined ? options.resetPositionOnHide : false; // Reset position when hiding\n this.autoplay = options.autoplay || null; // Auto-advance steps interval in ms, null = manual\n this.autoplayEnabled = options.autoplayEnabled !== undefined ? options.autoplayEnabled : false; // Whether autoplay is enabled\n this.autoplayWaitForMessages = options.autoplayWaitForMessages !== undefined ? options.autoplayWaitForMessages : true; // Wait for all messages before advancing\n this.hideOnComplete = options.hideOnComplete !== undefined ? options.hideOnComplete : true; // Auto-hide after tour completes\n this.hideOnCompleteDelay = options.hideOnCompleteDelay !== undefined ? options.hideOnCompleteDelay : null; // Delay before hide (null = use animationDuration)\n this._autoplayTimeoutId = null;\n this._autoplayPaused = false;\n this._messagesCompletedForStep = false; // Track if all messages have been shown\n this._hideOnCompleteTimeoutId = null; // Timer for auto-hide\n this.onStepChange = options.onStepChange;\n this.onComplete = options.onComplete;\n \n // Event listeners\n this._eventListeners = {};\n \n this.targetElement = options.target ? Pointy.getTargetElement(options.target) : null;\n this.currentStepIndex = 0;\n this.currentMessageIndex = 0;\n this.currentMessages = []; // Current step's messages array\n this.messageInterval = options.messageInterval || null; // Auto-cycle interval in ms, null = manual\n this._messageIntervalId = null;\n this.isVisible = false;\n this.isPointingUp = true; // Always start pointing up\n this.lastTargetY = null;\n this.manualDirection = null; // 'up', 'down', or null (auto)\n this.moveTimeout = null;\n this._hasShownBefore = false; // For intro animation\n\n // If steps provided, use first step\n if (this.steps.length > 0) {\n this.targetElement = Pointy.getTargetElement(this.steps[0].target);\n }\n\n // Create DOM elements - pointer is the anchor, bubble positioned relative to it\n this.container = document.createElement('div');\n this.container.className = `${this.classNames.container} ${this.classNames.hidden}`;\n this.container.style.setProperty(`--${this.cssVarPrefix}-duration`, `${this.animationDuration}ms`);\n this.container.style.setProperty(`--${this.cssVarPrefix}-easing`, this._resolveEasing(this.easing));\n this.container.style.setProperty(`--${this.cssVarPrefix}-bubble-fade`, `${this.bubbleFadeDuration}ms`);\n \n // Apply floating animation setting\n if (!this.floatingAnimation) {\n this.container.style.animationPlayState = 'paused';\n }\n\n this.pointer = document.createElement('div');\n this.pointer.className = this.classNames.pointer;\n Pointy.renderContent(this.pointer, this.pointerSvg);\n\n this.bubble = document.createElement('div');\n this.bubble.className = this.classNames.bubble;\n \n this.bubbleText = document.createElement('span');\n this.bubbleText.className = this.classNames.bubbleText;\n \n // Handle initial content (string or array) - no animation on init\n if (this.steps.length > 0) {\n const content = this.steps[0].content;\n this.currentMessages = Array.isArray(content) ? content : [content];\n Pointy.renderContent(this.bubbleText, this.currentMessages[0]);\n } else {\n const content = options.content || '';\n this.currentMessages = Array.isArray(content) ? content : [content];\n Pointy.renderContent(this.bubbleText, this.currentMessages[0]);\n }\n this.currentMessageIndex = 0;\n this.bubble.appendChild(this.bubbleText);\n\n // Assemble - pointer first, bubble positioned via CSS\n this.container.appendChild(this.pointer);\n this.container.appendChild(this.bubble);\n\n // Bind methods\n this.updatePosition = this.updatePosition.bind(this);\n this._trackPosition = this._trackPosition.bind(this);\n this._lastTrackTime = 0;\n\n // Listen for resize and scroll\n window.addEventListener('resize', this.updatePosition);\n window.addEventListener('scroll', this.updatePosition);\n }\n\n _trackPosition() {\n if (!this.isVisible || !this.targetElement) {\n this._rafId = null;\n return;\n }\n \n // FPS limiting: 0 = unlimited (monitor refresh rate)\n if (this.trackingFps > 0) {\n const now = performance.now();\n const interval = 1000 / this.trackingFps;\n if (now - this._lastTrackTime >= interval) {\n this._lastTrackTime = now;\n this.updatePosition();\n this._emit('track', { target: this.targetElement, timestamp: now });\n }\n } else {\n this.updatePosition();\n this._emit('track', { target: this.targetElement, timestamp: performance.now() });\n }\n \n this._rafId = requestAnimationFrame(this._trackPosition);\n }\n\n _startTracking() {\n if (!this.tracking) return; // Tracking disabled\n if (!this._rafId) {\n this._trackPosition();\n }\n }\n\n _stopTracking() {\n if (this._rafId) {\n cancelAnimationFrame(this._rafId);\n this._rafId = null;\n }\n }\n\n updatePosition() {\n if (!this.targetElement) return;\n\n const targetRect = this.targetElement.getBoundingClientRect();\n const scrollX = window.scrollX;\n const scrollY = window.scrollY;\n\n // Manual direction takes priority\n if (this.manualDirection !== null) {\n this.isPointingUp = this.manualDirection === 'up';\n } else {\n // Auto: Check if target is above or below previous position\n const currentTargetY = targetRect.top + scrollY;\n if (this.lastTargetY !== null) {\n const threshold = 50;\n if (currentTargetY < this.lastTargetY - threshold) {\n // Target moved UP - pointer below target, pointing up\n this.isPointingUp = true;\n } else if (currentTargetY > this.lastTargetY + threshold) {\n // Target moved DOWN - pointer above target, pointing down\n this.isPointingUp = false;\n }\n }\n this.lastTargetY = currentTargetY;\n }\n\n // Pointer tip position varies based on rotation\n // Default SVG (0deg): tip at approximately (25, 8) - points top-right\n // Rotated 90deg: tip at approximately (25, 25) - points bottom-right\n let left, top;\n\n if (this.isPointingUp) {\n // Pointer points up (default): pointer's top-right → target's bottom-left\n this.pointer.style.transform = 'rotate(0deg)';\n left = targetRect.left + scrollX - 25 + this.offsetX;\n top = targetRect.bottom + scrollY - 8 - this.offsetY;\n \n // Bubble: below pointer\n this.bubble.style.transform = 'translateY(28px)';\n } else {\n // Pointer points down (90deg): pointer's bottom-right → target's top-left\n this.pointer.style.transform = 'rotate(90deg)';\n left = targetRect.left + scrollX - 25 + this.offsetX;\n top = targetRect.top + scrollY - 25 + this.offsetY;\n \n // Bubble: above pointer\n const bubbleHeight = this.bubble.offsetHeight || 28;\n this.bubble.style.transform = `translateY(-${bubbleHeight}px)`;\n }\n\n this.container.style.left = `${left}px`;\n this.container.style.top = `${top}px`;\n }\n\n show() {\n this._emit('beforeShow', { target: this.targetElement });\n \n // Cancel any pending auto-hide\n if (this._hideOnCompleteTimeoutId) {\n clearTimeout(this._hideOnCompleteTimeoutId);\n this._hideOnCompleteTimeoutId = null;\n }\n \n if (!document.body.contains(this.container)) {\n document.body.appendChild(this.container);\n }\n \n // First time showing - start from initial position\n if (!this._hasShownBefore) {\n this._hasShownBefore = true;\n \n // Check if starting at first step (no movement needed)\n const isFirstStepStart = this.initialPosition === 'first-step';\n \n // Get initial position based on configuration\n const initialPos = this._getInitialPosition();\n const initialX = initialPos.x;\n const initialY = initialPos.y;\n \n // Disable all movement transitions, only allow opacity fade\n this.container.style.transition = `opacity ${this.introFadeDuration}ms ease`;\n this.pointer.style.transition = 'none';\n this.bubble.style.transition = 'none';\n this.bubble.style.opacity = '0'; // Hide bubble during intro\n this.container.style.left = `${initialX}px`;\n this.container.style.top = `${initialY}px`;\n \n // Set initial pointer/bubble orientation based on direction\n if (isFirstStepStart && initialPos.isPointingUp !== undefined) {\n // Use the direction from first step\n this.isPointingUp = initialPos.isPointingUp;\n if (this.isPointingUp) {\n this.pointer.style.transform = 'rotate(0deg)';\n this.bubble.style.transform = 'translateY(28px)';\n } else {\n this.pointer.style.transform = 'rotate(90deg)';\n const bubbleHeight = this.bubble.offsetHeight || 28;\n this.bubble.style.transform = `translateY(-${bubbleHeight}px)`;\n }\n } else {\n // Default: pointing up\n this.pointer.style.transform = 'rotate(0deg)';\n this.bubble.style.transform = 'translateY(0)';\n }\n \n this.container.style.display = 'flex';\n this.container.offsetHeight; // Force reflow\n this.container.classList.remove(this.classNames.hidden);\n this.container.classList.add(this.classNames.visible);\n this.isVisible = true;\n \n this._emit('introAnimationStart', { duration: this.introFadeDuration, initialPosition: { x: initialX, y: initialY } });\n \n // Re-enable full transitions after fade-in completes, then animate to target\n setTimeout(() => {\n this._emit('introAnimationEnd', { initialPosition: { x: initialX, y: initialY } });\n \n // If starting at first-step, no movement needed - just show bubble\n if (isFirstStepStart) {\n // Keep transitions disabled - we're already in the right place\n this.container.style.transition = 'none';\n this.pointer.style.transition = 'none';\n \n this._startTracking();\n \n // Show bubble immediately with fade\n this.bubble.style.transition = `opacity ${this.bubbleFadeDuration}ms ease`;\n this.bubble.style.opacity = '1';\n \n // Re-enable transitions after bubble fade completes\n setTimeout(() => {\n this.container.style.transition = '';\n this.pointer.style.transition = '';\n this.bubble.style.transition = '';\n }, this.bubbleFadeDuration);\n \n // Start message cycle if multi-message\n if (this.messageInterval && this.currentMessages.length > 1 && !this._messageIntervalId) {\n this._startMessageCycle();\n }\n \n // Schedule autoplay if enabled\n this._scheduleAutoplay();\n \n this._emit('show', { target: this.targetElement, isIntro: true, isFirstStep: true });\n } else {\n // Normal flow: animate to target\n this.container.style.transition = '';\n this.pointer.style.transition = '';\n this.bubble.style.transition = 'none'; // Keep bubble transition off during movement\n this.updatePosition();\n \n // Start tracking\n this._startTracking();\n \n // Show bubble with fade after arriving at first target\n setTimeout(() => {\n this.bubble.style.transition = '';\n this.bubble.style.opacity = '1';\n \n // Start message cycle if multi-message\n if (this.messageInterval && this.currentMessages.length > 1 && !this._messageIntervalId) {\n this._startMessageCycle();\n }\n \n // Schedule autoplay if enabled\n this._scheduleAutoplay();\n }, this.animationDuration);\n \n this._emit('show', { target: this.targetElement, isIntro: true, isFirstStep: false });\n }\n }, this.introFadeDuration); // Wait for intro fade to complete\n \n return;\n }\n \n this.container.style.display = 'flex';\n // Force reflow before adding visible class for animation\n this.container.offsetHeight;\n this.container.classList.remove(this.classNames.hidden);\n this.container.classList.add(this.classNames.visible);\n this.isVisible = true;\n this.updatePosition();\n \n // Start tracking\n this._startTracking();\n \n // Resume message cycle if it was paused by hide\n if (this._messageCyclePausedByHide && this.messageInterval && this.currentMessages.length > 1) {\n this._startMessageCycle();\n this._messageCyclePausedByHide = false;\n } else if (this.messageInterval && this.currentMessages.length > 1 && !this._messageIntervalId) {\n // Start message cycle if multi-message and not already running\n this._startMessageCycle();\n }\n \n // Resume autoplay if it was active before hide\n if (this._wasAutoplayActiveBeforeHide) {\n this._scheduleAutoplay();\n this._wasAutoplayActiveBeforeHide = false;\n }\n \n this._emit('show', { target: this.targetElement, isIntro: false });\n }\n\n hide() {\n this._emit('beforeHide', { target: this.targetElement });\n \n this.container.classList.remove(this.classNames.visible);\n this.container.classList.add(this.classNames.hidden);\n this.isVisible = false;\n \n // Only reset position state if option is enabled\n if (this.resetPositionOnHide) {\n this._hasShownBefore = false;\n }\n \n // Stop tracking\n this._stopTracking();\n \n // Pause message cycle (don't stop - can be resumed)\n if (this._messageIntervalId) {\n this._stopMessageCycle();\n this._messageCyclePausedByHide = true;\n }\n \n // Pause autoplay timer (don't change _autoplayPaused state - just clear timer)\n // This preserves the autoplay state so it can resume on show()\n this._wasAutoplayActiveBeforeHide = this.autoplay && this.autoplayEnabled && !this._autoplayPaused;\n this._stopAutoplay();\n \n this._emit('hide', { target: this.targetElement });\n }\n\n /**\n * Restart the intro animation from initial position\n * Useful for demoing initial position changes\n */\n restart() {\n this._emit('beforeRestart', {});\n this._hasShownBefore = false;\n \n if (this.isVisible) {\n this.container.classList.remove(this.classNames.visible);\n this.container.classList.add(this.classNames.hidden);\n this._stopTracking();\n this._stopMessageCycle();\n this.isVisible = false;\n \n // Small delay to allow CSS transition to complete\n setTimeout(() => {\n this.goToStep(0);\n this.show();\n this._emit('restart', {});\n }, 50);\n } else {\n this.goToStep(0);\n this.show();\n this._emit('restart', {});\n }\n }\n\n destroy() {\n this._emit('destroy', {});\n \n if (document.body.contains(this.container)) {\n document.body.removeChild(this.container);\n }\n window.removeEventListener('resize', this.updatePosition);\n window.removeEventListener('scroll', this.updatePosition);\n \n // Stop tracking\n this._stopTracking();\n \n // Clear auto-hide timer\n if (this._hideOnCompleteTimeoutId) {\n clearTimeout(this._hideOnCompleteTimeoutId);\n this._hideOnCompleteTimeoutId = null;\n }\n \n // Clear all event listeners\n this._eventListeners = {};\n }\n\n /**\n * Reset pointer to initial position and optionally go back to first step\n * @param {boolean} goToFirstStep - Whether to reset step index to 0 (default: true)\n */\n reset(goToFirstStep = true) {\n this._emit('beforeReset', { currentStep: this.currentStepIndex });\n \n // Stop message cycle\n this._stopMessageCycle();\n \n // Clear hide on complete timeout if exists\n if (this._hideOnCompleteTimeoutId) {\n clearTimeout(this._hideOnCompleteTimeoutId);\n this._hideOnCompleteTimeoutId = null;\n }\n \n // Pause floating animation during movement\n this.container.classList.add(this.classNames.moving);\n if (this.moveTimeout) clearTimeout(this.moveTimeout);\n \n // Animate to initial position\n const { x: initialX, y: initialY } = this._getInitialPosition();\n \n this.container.style.left = `${initialX}px`;\n this.container.style.top = `${initialY}px`;\n \n // Fade out bubble during reset\n this.bubble.style.opacity = '0';\n \n // Reset step index if requested\n if (goToFirstStep && this.steps.length > 0) {\n this.currentStepIndex = 0;\n const firstStep = this.steps[0];\n this.targetElement = Pointy.getTargetElement(firstStep.target);\n this.currentMessages = Array.isArray(firstStep.content) ? firstStep.content : [firstStep.content];\n this.currentMessageIndex = 0;\n Pointy.renderContent(this.bubbleText, this.currentMessages[0]);\n }\n \n // After animation completes\n this.moveTimeout = setTimeout(() => {\n this.container.classList.remove(this.classNames.moving);\n this._hasShownBefore = false; // Allow intro animation again\n this._emit('reset', { stepIndex: this.currentStepIndex });\n }, this.animationDuration);\n }\n\n /**\n * Set resetOnComplete option\n * @param {boolean} reset - Whether to reset on complete\n */\n setResetOnComplete(reset) {\n const oldValue = this.resetOnComplete;\n if (oldValue === reset) return;\n \n this.resetOnComplete = reset;\n this._emit('resetOnCompleteChange', { from: oldValue, to: reset });\n }\n\n /**\n * Set floating animation enabled/disabled\n * @param {boolean} enabled - Whether floating animation is enabled\n */\n setFloatingAnimation(enabled) {\n const oldValue = this.floatingAnimation;\n if (oldValue === enabled) return;\n \n this.floatingAnimation = enabled;\n \n if (enabled) {\n this.container.style.animationPlayState = '';\n } else {\n this.container.style.animationPlayState = 'paused';\n }\n \n this._emit('floatingAnimationChange', { from: oldValue, to: enabled });\n }\n\n /**\n * Check if floating animation is enabled\n * @returns {boolean}\n */\n isFloatingAnimationEnabled() {\n return this.floatingAnimation;\n }\n\n /**\n * Set tracking enabled/disabled\n * @param {boolean} enabled - Whether position tracking is enabled\n */\n setTracking(enabled) {\n const oldValue = this.tracking;\n if (oldValue === enabled) return;\n \n this.tracking = enabled;\n \n if (enabled && this.isVisible) {\n this._startTracking();\n } else if (!enabled) {\n this._stopTracking();\n }\n \n this._emit('trackingChange', { from: oldValue, to: enabled });\n }\n\n /**\n * Set tracking FPS\n * @param {number} fps - Frames per second (0 = unlimited)\n */\n setTrackingFps(fps) {\n const oldValue = this.trackingFps;\n if (oldValue === fps) return;\n \n this.trackingFps = fps;\n this._emit('trackingFpsChange', { from: oldValue, to: fps });\n }\n\n /**\n * Check if tracking is enabled\n * @returns {boolean}\n */\n isTrackingEnabled() {\n return this.tracking;\n }\n\n updateContent(newContent, animate = true) {\n // Skip if content is the same (only for string content)\n if (typeof newContent === 'string' && this.bubbleText.innerHTML === newContent) {\n return;\n }\n \n if (animate) {\n Pointy.animateText(this.bubbleText, newContent, this.messageTransitionDuration, this.bubble, () => {\n this.updatePosition();\n });\n } else {\n Pointy.renderContent(this.bubbleText, newContent);\n this.updatePosition();\n }\n }\n\n /**\n * Set messages for current step (internal)\n * @param {string|string[]} content - Single message or array of messages\n * @param {boolean} fromStepChange - Whether this is from a step change (internal)\n * @private\n */\n _setMessages(content, fromStepChange = false) {\n // Check if cycle was running before\n const wasRunning = this._messageIntervalId !== null;\n \n // Stop any existing auto-cycle\n this._stopMessageCycle();\n \n // Normalize to array\n this.currentMessages = Array.isArray(content) ? content : [content];\n this.currentMessageIndex = 0;\n \n // Show first message\n this.updateContent(this.currentMessages[0]);\n \n // Only auto-start cycle on step changes, not on manual setContent\n // For manual setContent, user must call resumeMessageCycle()\n if (fromStepChange && this.messageInterval && this.currentMessages.length > 1) {\n this._startMessageCycle();\n } else if (wasRunning && this.currentMessages.length > 1) {\n // Mark as paused so user can resume\n this._messageCyclePaused = true;\n }\n \n this._emit('messagesSet', { \n messages: this.currentMessages, \n total: this.currentMessages.length,\n cyclePaused: this._messageCyclePaused === true\n });\n }\n\n /**\n * Start auto-cycling through messages\n * @private\n */\n _startMessageCycle() {\n this._messagesCompletedForStep = false;\n this._messageIntervalId = setInterval(() => {\n // Check if we're at the last message and autoplay is waiting for messages\n const isLastMessage = this.currentMessageIndex === this.currentMessages.length - 1;\n \n if (isLastMessage && this.autoplay && this.autoplayWaitForMessages) {\n // Don't cycle back to first message - stop here and advance to next step\n this._stopMessageCycle();\n this._messagesCompletedForStep = true;\n this._emit('messageCycleComplete', { stepIndex: this.currentStepIndex, totalMessages: this.currentMessages.length });\n // Trigger autoplay advance after a brief pause\n this._scheduleAutoplayAfterMessages();\n } else {\n // Normal message cycling\n this.nextMessage(true); // true = isAuto\n }\n }, this.messageInterval);\n this._emit('messageCycleStart', { interval: this.messageInterval, totalMessages: this.currentMessages.length });\n }\n\n /**\n * Stop auto-cycling through messages\n * @private\n */\n _stopMessageCycle() {\n if (this._messageIntervalId) {\n clearInterval(this._messageIntervalId);\n this._messageIntervalId = null;\n this._emit('messageCycleStop', { currentIndex: this.currentMessageIndex });\n }\n }\n\n /**\n * Pause auto message cycling (can be resumed later)\n */\n pauseMessageCycle() {\n if (this._messageIntervalId) {\n clearInterval(this._messageIntervalId);\n this._messageIntervalId = null;\n this._messageCyclePaused = true;\n this._emit('messageCyclePause', { currentIndex: this.currentMessageIndex });\n }\n }\n\n /**\n * Resume paused message cycling\n * @returns {boolean} - True if resumed, false if not paused or no interval set\n */\n resumeMessageCycle() {\n if (this._messageCyclePaused && this.messageInterval && this.currentMessages.length > 1) {\n this._messageCyclePaused = false;\n this._startMessageCycle();\n this._emit('messageCycleResume', { currentIndex: this.currentMessageIndex });\n return true;\n }\n return false;\n }\n\n /**\n * Start message cycling manually (regardless of messageInterval setting)\n * @param {number} interval - Optional interval in ms, uses current messageInterval if not provided\n * @returns {boolean} - True if started, false if already running or no messages\n */\n startMessageCycle(interval) {\n if (this._messageIntervalId) return false; // Already running\n if (this.currentMessages.length <= 1) return false; // No point cycling single message\n \n if (interval !== undefined) {\n this.messageInterval = interval;\n }\n \n if (!this.messageInterval) return false;\n \n this._messageCyclePaused = false;\n this._startMessageCycle();\n return true;\n }\n\n /**\n * Stop message cycling completely\n * @returns {boolean} - True if stopped, false if not running\n */\n stopMessageCycle() {\n if (this._messageIntervalId) {\n this._stopMessageCycle();\n this._messageCyclePaused = false;\n return true;\n }\n return false;\n }\n\n /**\n * Check if message cycling is currently active\n * @returns {boolean}\n */\n isMessageCycleActive() {\n return this._messageIntervalId !== null;\n }\n\n /**\n * Check if message cycling is paused\n * @returns {boolean}\n */\n isMessageCyclePaused() {\n return this._messageCyclePaused === true;\n }\n\n /**\n * Go to next message in current step\n * @param {boolean} isAuto - Whether this is from auto-cycle (internal use)\n * @returns {boolean} - True if moved to next, false if at end\n */\n nextMessage(isAuto = false) {\n if (this.currentMessages.length <= 1) return false;\n \n const previousIndex = this.currentMessageIndex;\n this.currentMessageIndex = (this.currentMessageIndex + 1) % this.currentMessages.length;\n \n this.updateContent(this.currentMessages[this.currentMessageIndex]);\n \n this._emit('messageChange', {\n fromIndex: previousIndex,\n toIndex: this.currentMessageIndex,\n message: this.currentMessages[this.currentMessageIndex],\n total: this.currentMessages.length,\n isAuto: isAuto\n });\n \n return true;\n }\n\n /**\n * Go to previous message in current step\n * @returns {boolean} - True if moved to previous, false if at start\n */\n prevMessage() {\n if (this.currentMessages.length <= 1) return false;\n \n const previousIndex = this.currentMessageIndex;\n this.currentMessageIndex = (this.currentMessageIndex - 1 + this.currentMessages.length) % this.currentMessages.length;\n \n this.updateContent(this.currentMessages[this.currentMessageIndex]);\n \n this._emit('messageChange', {\n fromIndex: previousIndex,\n toIndex: this.currentMessageIndex,\n message: this.currentMessages[this.currentMessageIndex],\n total: this.currentMessages.length\n });\n \n return true;\n }\n\n /**\n * Go to a specific message by index\n * @param {number} index - Message index\n */\n goToMessage(index) {\n if (index < 0 || index >= this.currentMessages.length) return;\n \n const previousIndex = this.currentMessageIndex;\n this.currentMessageIndex = index;\n \n this.updateContent(this.currentMessages[this.currentMessageIndex]);\n \n this._emit('messageChange', {\n fromIndex: previousIndex,\n toIndex: this.currentMessageIndex,\n message: this.currentMessages[this.currentMessageIndex],\n total: this.currentMessages.length\n });\n }\n\n /**\n * Get current message index\n * @returns {number}\n */\n getCurrentMessage() {\n return this.currentMessageIndex;\n }\n\n /**\n * Get total messages in current step\n * @returns {number}\n */\n getTotalMessages() {\n return this.currentMessages.length;\n }\n\n /**\n * Set content programmatically (replaces current messages)\n * @param {string|string[]} content - Single message or array of messages\n * @param {boolean} animate - Whether to animate the change (default: true)\n */\n setContent(content, animate = true) {\n // Check if cycle was running before\n const wasRunning = this._messageIntervalId !== null;\n \n if (animate) {\n this._setMessages(content, false); // false = not from step change\n } else {\n // Stop any existing auto-cycle\n this._stopMessageCycle();\n \n // Normalize to array\n this.currentMessages = Array.isArray(content) ? content : [content];\n this.currentMessageIndex = 0;\n \n // Show first message without animation\n Pointy.renderContent(this.bubbleText, this.currentMessages[0]);\n this.updatePosition();\n \n // Mark as paused if cycle was running (user must call resumeMessageCycle)\n if (wasRunning && this.currentMessages.length > 1) {\n this._messageCyclePaused = true;\n }\n }\n \n this._emit('contentSet', { \n messages: this.currentMessages, \n total: this.currentMessages.length,\n animated: animate,\n cyclePaused: this._messageCyclePaused === true\n });\n }\n\n /**\n * Set message auto-cycle interval\n * @param {number|null} interval - Interval in ms, null to disable\n */\n setMessageInterval(interval) {\n const oldInterval = this.messageInterval;\n if (oldInterval === interval) return;\n \n this.messageInterval = interval;\n this._stopMessageCycle();\n \n if (interval && this.currentMessages.length > 1) {\n this._startMessageCycle();\n }\n \n this._emit('messageIntervalChange', { from: oldInterval, to: interval });\n }\n\n updateTarget(newTarget) {\n const oldTarget = this.targetElement;\n this.targetElement = Pointy.getTargetElement(newTarget);\n this.updatePosition();\n this._emit('targetChange', { from: oldTarget, to: this.targetElement });\n }\n\n setOffset(offsetX, offsetY) {\n const oldOffsetX = this.offsetX;\n const oldOffsetY = this.offsetY;\n if (oldOffsetX === offsetX && oldOffsetY === offsetY) return;\n \n this.offsetX = offsetX;\n this.offsetY = offsetY;\n this.updatePosition();\n this._emit('offsetChange', { from: { x: oldOffsetX, y: oldOffsetY }, to: { x: offsetX, y: offsetY } });\n }\n\n /**\n * Set the animation duration for transitions\n * @param {number} duration - Duration in milliseconds\n */\n setAnimationDuration(duration) {\n const oldDuration = this.animationDuration;\n if (oldDuration === duration) return;\n \n this.animationDuration = duration;\n this.container.style.setProperty(`--${this.cssVarPrefix}-duration`, `${duration}ms`);\n this._emit('animationDurationChange', { from: oldDuration, to: duration });\n }\n\n /**\n * Set the intro fade duration (pointer appearing from center)\n * @param {number} duration - Duration in milliseconds\n */\n setIntroFadeDuration(duration) {\n const oldDuration = this.introFadeDuration;\n if (oldDuration === duration) return;\n \n this.introFadeDuration = duration;\n this._emit('introFadeDurationChange', { from: oldDuration, to: duration });\n }\n\n /**\n * Set the bubble fade duration\n * @param {number} duration - Duration in milliseconds\n */\n setBubbleFadeDuration(duration) {\n const oldDuration = this.bubbleFadeDuration;\n if (oldDuration === duration) return;\n \n this.bubbleFadeDuration = duration;\n this.container.style.setProperty(`--${this.cssVarPrefix}-bubble-fade`, `${duration}ms`);\n this._emit('bubbleFadeDurationChange', { from: oldDuration, to: duration });\n }\n\n /**\n * Get the initial position coordinates based on initialPosition setting\n * @returns {{x: number, y: number, isPointingUp?: boolean}} - Position coordinates and optional direction\n */\n _getInitialPosition() {\n const offset = this.initialPositionOffset;\n const w = window.innerWidth;\n const h = window.innerHeight;\n \n // Special preset: first-step - calculate exact position like updatePosition does\n if (this.initialPosition === 'first-step' && this.steps.length > 0) {\n const firstStep = this.steps[0];\n const firstTarget = Pointy.getTargetElement(firstStep.target);\n if (firstTarget) {\n const targetRect = firstTarget.getBoundingClientRect();\n const scrollX = window.scrollX;\n const scrollY = window.scrollY;\n \n // Check step direction: 'up', 'down', or auto (default to 'up')\n const isPointingUp = firstStep.direction !== 'down';\n \n let left, top;\n if (isPointingUp) {\n // Pointing up: pointer below target\n left = targetRect.left + scrollX - 25 + this.offsetX;\n top = targetRect.bottom + scrollY - 8 - this.offsetY;\n } else {\n // Pointing down: pointer above target\n left = targetRect.left + scrollX - 25 + this.offsetX;\n top = targetRect.top + scrollY - 25 + this.offsetY;\n }\n \n return { x: left, y: top, isPointingUp };\n }\n }\n \n // If initialPosition is an element or selector, get its position\n if (this.initialPosition && typeof this.initialPosition !== 'string') {\n // It's a DOM element\n const rect = this.initialPosition.getBoundingClientRect();\n return { x: rect.left + rect.width / 2, y: rect.top + rect.height / 2 };\n }\n \n // Check if it's a selector string (starts with # or .)\n if (typeof this.initialPosition === 'string' && (this.initialPosition.startsWith('#') || this.initialPosition.startsWith('.'))) {\n const el = document.querySelector(this.initialPosition);\n if (el) {\n const rect = el.getBoundingClientRect();\n return { x: rect.left + rect.width / 2, y: rect.top + rect.height / 2 };\n }\n }\n \n // Preset positions\n const positions = {\n 'center': { x: w / 2, y: h / 2 },\n 'top-left': { x: offset, y: offset },\n 'top-center': { x: w / 2, y: offset },\n 'top-right': { x: w - offset, y: offset },\n 'middle-left': { x: offset, y: h / 2 },\n 'middle-right': { x: w - offset, y: h / 2 },\n 'bottom-left': { x: offset, y: h - offset },\n 'bottom-center': { x: w / 2, y: h - offset },\n 'bottom-right': { x: w - offset, y: h - offset }\n };\n \n return positions[this.initialPosition] || positions['center'];\n }\n\n /**\n * Set the initial position\n * @param {string|HTMLElement} position - Position preset ('center', 'top-left', 'first-step', etc.), CSS selector, or DOM element\n */\n setInitialPosition(position) {\n const validPresets = ['center', 'top-left', 'top-center', 'top-right', 'middle-left', 'middle-right', 'bottom-left', 'bottom-center', 'bottom-right', 'first-step'];\n \n // Validate if it's a string preset\n if (typeof position === 'string' && !position.startsWith('#') && !position.startsWith('.') && !validPresets.includes(position)) {\n console.warn(`Invalid initial position: ${position}. Valid presets: ${validPresets.join(', ')}. Or use a CSS selector or DOM element.`);\n return;\n }\n \n const oldPosition = this.initialPosition;\n if (oldPosition === position) return;\n \n this.initialPosition = position;\n this._emit('initialPositionChange', { from: oldPosition, to: position });\n }\n\n /**\n * Animate to initial position (useful for demoing position changes)\n * Flow: teleport hidden to new position -> fade in -> move to target\n */\n animateToInitialPosition() {\n if (!this.isVisible) return;\n \n const { x, y } = this._getInitialPosition();\n \n // Stop tracking during animation\n this._stopTracking();\n \n // Step 1: Teleport hidden to new initial position (no transition, instant)\n this.container.style.cssText = `\n position: fixed;\n left: ${x}px;\n top: ${y}px;\n opacity: 0;\n transition: none;\n `;\n this.bubble.style.opacity = '0';\n this.bubble.style.transition = 'none';\n \n // Force reflow to apply instant position change\n this.container.offsetHeight;\n \n // Step 2: Fade in at new initial position (only opacity animates)\n this.container.style.transition = `opacity ${this.introFadeDuration}ms ease`;\n this.container.style.opacity = '1';\n \n // Step 3: After fade in completes, animate movement to target\n setTimeout(() => {\n // Restore normal transitions for movement\n this.container.style.transition = '';\n this.container.style.cssText = '';\n this.container.style.left = `${x}px`;\n this.container.style.top = `${y}px`;\n \n // Force reflow\n this.container.offsetHeight;\n \n // Now animate to target\n this.updatePosition();\n this._startTracking();\n \n // Show bubble after arriving at target\n setTimeout(() => {\n this.bubble.style.transition = '';\n this.bubble.style.opacity = '1';\n }, this.animationDuration);\n }, this.introFadeDuration);\n }\n\n /**\n * Set the initial position offset from edges (for non-center positions)\n * @param {number} offset - Offset in pixels (can be negative to go off-screen)\n */\n setInitialPositionOffset(offset) {\n const oldOffset = this.initialPositionOffset;\n if (oldOffset === offset) return;\n \n this.initialPositionOffset = offset;\n this._emit('initialPositionOffsetChange', { from: oldOffset, to: offset });\n }\n\n /**\n * Resolve easing name to CSS value\n * @param {string} easing - Easing name or custom cubic-bezier\n * @returns {string} - CSS easing value\n */\n _resolveEasing(easing) {\n // If it's a named preset, return the value\n if (Pointy.EASINGS[easing]) {\n return Pointy.EASINGS[easing];\n }\n // Otherwise assume it's a custom cubic-bezier or CSS easing\n return easing;\n }\n\n /**\n * Set the animation easing\n * @param {string} easing - Easing name (e.g., 'bounce', 'elastic') or custom cubic-bezier\n */\n setEasing(easing) {\n const oldEasing = this.easing;\n if (oldEasing === easing) return;\n \n this.easing = easing;\n this.container.style.setProperty(`--${this.cssVarPrefix}-easing`, this._resolveEasing(easing));\n this._emit('easingChange', { from: oldEasing, to: easing });\n }\n\n /**\n * Set the message transition duration\n * @param {number} duration - Duration in milliseconds\n */\n setMessageTransitionDuration(duration) {\n const oldDuration = this.messageTransitionDuration;\n if (oldDuration === duration) return;\n \n this.messageTransitionDuration = duration;\n this._emit('messageTransitionDurationChange', { from: oldDuration, to: duration });\n }\n\n /**\n * Set custom pointer SVG\n * @param {string|React.ReactNode} svg - SVG markup string or React element\n */\n setPointerSvg(svg) {\n const oldSvg = this.pointerSvg;\n if (oldSvg === svg) return;\n \n this.pointerSvg = svg;\n Pointy.renderContent(this.pointer, svg);\n this._emit('pointerSvgChange', { from: oldSvg, to: svg });\n }\n\n /**\n * Get current pointer SVG\n * @returns {string|React.ReactNode} - Current SVG markup or React element\n */\n getPointerSvg() {\n return this.pointerSvg;\n }\n\n /**\n * Get the class names object\n * @returns {object} - Current class names\n */\n getClassNames() {\n return { ...this.classNames };\n }\n\n /**\n * Get the class prefix\n * @returns {string} - Current class prefix\n */\n getClassPrefix() {\n return this.classPrefix;\n }\n\n /**\n * Get the CSS variable prefix\n * @returns {string} - Current CSS variable prefix\n */\n getCssVarPrefix() {\n return this.cssVarPrefix;\n }\n\n /**\n * Get list of available easing presets\n * @returns {string[]} - Array of easing names\n */\n static getEasingPresets() {\n return Object.keys(Pointy.EASINGS);\n }\n\n /**\n * Get list of available initial position presets\n * @returns {string[]} - Array of position names\n */\n static getInitialPositions() {\n return ['center', 'top-left', 'top-center', 'top-right', 'middle-left', 'middle-right', 'bottom-left', 'bottom-center', 'bottom-right', 'first-step'];\n }\n\n goToStep(index) {\n if (this.steps.length === 0 || index < 0 || index >= this.steps.length) return;\n \n // Stop any existing autoplay timer\n this._stopAutoplay();\n \n // Reset message completion tracking for new step\n this._messagesCompletedForStep = false;\n \n const previousIndex = this.currentStepIndex;\n const previousTarget = this.targetElement;\n this.currentStepIndex = index;\n const step = this.steps[this.currentStepIndex];\n \n this._emit('beforeStepChange', { \n fromIndex: previousIndex, \n toIndex: index, \n step: step,\n fromTarget: previousTarget\n });\n \n // Set direction: step.direction can be 'up', 'down', or undefined (auto)\n this.manualDirection = step.direction || null;\n \n // Pause floating animation during movement\n this.container.classList.add(this.classNames.moving);\n if (this.moveTimeout) clearTimeout(this.moveTimeout);\n \n this._emit('animationStart', { \n fromTarget: previousTarget, \n toTarget: Pointy.getTargetElement(step.target),\n type: 'step',\n stepIndex: index\n });\n \n this.moveTimeout = setTimeout(() => {\n this.container.classList.remove(this.classNames.moving);\n this._emit('moveComplete', { index: index, step: step, target: this.targetElement });\n this._emit('animationEnd', { \n fromTarget: previousTarget, \n toTarget: this.targetElement,\n type: 'step',\n stepIndex: index\n });\n \n // Schedule next step if autoplay is enabled\n this._scheduleAutoplay();\n }, this.animationDuration);\n \n this._emit('move', { index: index, step: step });\n \n this._setMessages(step.content, true); // true = from step change, auto-start cycle\n this.targetElement = Pointy.getTargetElement(step.target);\n this.updatePosition();\n \n this._emit('stepChange', { \n fromIndex: previousIndex, \n toIndex: index, \n step: step, \n target: this.targetElement \n });\n \n if (this.onStepChange) {\n this.onStepChange(this.currentStepIndex, step);\n }\n }\n\n /**\n * Schedule the next autoplay step\n * @private\n */\n _scheduleAutoplay() {\n if (!this.autoplay || !this.autoplayEnabled || this._autoplayPaused || !this.isVisible) return;\n \n const step = this.steps[this.currentStepIndex];\n const hasMultipleMessages = this.currentMessages.length > 1 && this.messageInterval;\n \n // If waiting for messages and step has multiple messages with auto-cycle, don't schedule here\n // The _startMessageCycle will handle advancing after all messages are shown\n if (this.autoplayWaitForMessages && hasMultipleMessages) {\n return; // Wait for message cycle to complete\n }\n \n // Use step-specific duration if provided, otherwise use global autoplay\n const duration = step.duration !== undefined ? step.duration : this.autoplay;\n \n if (duration && duration > 0) {\n this._autoplayTimeoutId = setTimeout(() => {\n if (!this._autoplayPaused && this.isVisible && this.autoplayEnabled) {\n this._emit('autoplayNext', { fromIndex: this.currentStepIndex, duration });\n this.next();\n }\n }, duration);\n }\n }\n\n /**\n * Schedule autoplay advance after message cycle completes\n * @private\n */\n _scheduleAutoplayAfterMessages() {\n if (!this.autoplay || !this.autoplayEnabled || this._autoplayPaused || !this.isVisible) return;\n \n // Use a short delay before advancing (user can read the last message during messageInterval already)\n const delay = 300; // Brief pause after last message before advancing\n \n this._autoplayTimeoutId = setTimeout(() => {\n if (!this._autoplayPaused && this.isVisible && this._messagesCompletedForStep) {\n this._emit('autoplayNext', { fromIndex: this.currentStepIndex, afterMessages: true });\n this.next();\n }\n }, delay);\n }\n\n /**\n * Stop autoplay timer\n * @private\n */\n _stopAutoplay() {\n if (this._autoplayTimeoutId) {\n clearTimeout(this._autoplayTimeoutId);\n this._autoplayTimeoutId = null;\n }\n }\n\n /**\n * Start autoplay\n */\n startAutoplay() {\n if (!this.autoplay) return;\n this.autoplayEnabled = true;\n this._autoplayPaused = false;\n this._emit('autoplayStart', {});\n this._scheduleAutoplay();\n }\n\n /**\n * Stop autoplay\n */\n stopAutoplay() {\n this._stopAutoplay();\n this.autoplayEnabled = false;\n this._autoplayPaused = false;\n this._emit('autoplayStop', {});\n }\n\n /**\n * Pause autoplay (can be resumed)\n */\n pauseAutoplay() {\n this._stopAutoplay();\n this._autoplayPaused = true;\n this._emit('autoplayPause', {});\n }\n\n /**\n * Resume autoplay after pause\n */\n resumeAutoplay() {\n if (!this._autoplayPaused) return;\n this._autoplayPaused = false;\n this._emit('autoplayResume', {});\n this._scheduleAutoplay();\n }\n\n /**\n * Check if autoplay is currently active\n * @returns {boolean}\n */\n isAutoplayActive() {\n return this.autoplay && this.autoplayEnabled && !this._autoplayPaused;\n }\n\n /**\n * Check if autoplay is paused\n * @returns {boolean}\n */\n isAutoplayPaused() {\n return this._autoplayPaused;\n }\n\n /**\n * Set autoplay interval (does not start autoplay, use startAutoplay() for that)\n * @param {number|null} interval - Interval in ms, or null to disable\n */\n setAutoplayInterval(interval) {\n const oldInterval = this.autoplay;\n if (oldInterval === interval) return;\n \n this.autoplay = interval;\n this._emit('autoplayChange', { from: oldInterval, to: interval });\n \n // If autoplay is enabled and running, restart with new interval\n if (this.autoplayEnabled && interval && this.isVisible) {\n this._stopAutoplay();\n this._scheduleAutoplay();\n } else if (!interval) {\n this._stopAutoplay();\n this.autoplayEnabled = false;\n }\n }\n\n /**\n * Set autoplay interval and start autoplay (legacy method, use setAutoplayInterval + startAutoplay instead)\n * @param {number|null} interval - Interval in ms, or null to disable\n */\n setAutoplay(interval) {\n this.setAutoplayInterval(interval);\n \n // Start autoplay if interval is set\n if (interval && this.isVisible) {\n this.autoplayEnabled = true;\n this._autoplayPaused = false;\n this.restart(); // Full restart from initial position\n }\n }\n\n /**\n * Set whether autoplay should wait for all messages to complete before advancing\n * @param {boolean} wait - True to wait for messages, false to use normal duration\n */\n setAutoplayWaitForMessages(wait) {\n const oldValue = this.autoplayWaitForMessages;\n if (oldValue === wait) return;\n \n this.autoplayWaitForMessages = wait;\n this._emit('autoplayWaitForMessagesChange', { from: oldValue, to: wait });\n }\n\n /**\n * Set whether to auto-hide after tour completes\n * @param {boolean} hide - True to auto-hide, false to stay visible\n */\n setHideOnComplete(hide) {\n const oldValue = this.hideOnComplete;\n if (oldValue === hide) return;\n \n this.hideOnComplete = hide;\n this._emit('hideOnCompleteChange', { from: oldValue, to: hide });\n }\n\n /**\n * Set the delay before auto-hiding after complete\n * @param {number|null} delay - Delay in ms, or null to use animationDuration\n */\n setHideOnCompleteDelay(delay) {\n const oldValue = this.hideOnCompleteDelay;\n if (oldValue === delay) return;\n \n this.hideOnCompleteDelay = delay;\n this._emit('hideOnCompleteDelayChange', { from: oldValue, to: delay });\n }\n\n next() {\n if (this.steps.length === 0) return;\n \n if (this.currentStepIndex < this.steps.length - 1) {\n this._emit('next', { fromIndex: this.currentStepIndex, toIndex: this.currentStepIndex + 1 });\n this.goToStep(this.currentStepIndex + 1);\n } else {\n // Check if autoplay was active before emitting complete\n const wasAutoplayActive = this.autoplay && this.autoplayEnabled && !this._autoplayPaused;\n \n this._emit('complete', { totalSteps: this.steps.length, source: wasAutoplayActive ? 'autoplay' : 'manual' });\n \n // Emit autoplayComplete if autoplay was running\n if (wasAutoplayActive) {\n this._stopAutoplay();\n this.autoplayEnabled = false;\n this._emit('autoplayComplete', { totalSteps: this.steps.length });\n }\n \n // Handle post-completion behavior based on settings\n // Note: hideOnComplete is respected for both autoplay and manual navigation\n if (this.resetOnComplete) {\n this.reset();\n \n // Schedule hide after reset animation completes (only if hideOnComplete is true)\n if (this.hideOnComplete) {\n const hideDelay = this.hideOnCompleteDelay !== null ? this.hideOnCompleteDelay : this.animationDuration;\n const source = wasAutoplayActive ? 'autoplay' : 'manual';\n this._hideOnCompleteTimeoutId = setTimeout(() => {\n this.hide();\n this._emit('autoHide', { delay: hideDelay, source: source });\n }, this.animationDuration + hideDelay);\n }\n } else {\n // No reset: hide immediately after delay (only if hideOnComplete is true)\n if (this.hideOnComplete) {\n const delay = this.hideOnCompleteDelay !== null ? this.hideOnCompleteDelay : this.animationDuration;\n const source = wasAutoplayActive ? 'autoplay' : 'manual';\n this._hideOnCompleteTimeoutId = setTimeout(() => {\n this.hide();\n this._emit('autoHide', { delay: delay, source: source });\n }, delay);\n }\n }\n \n if (this.onComplete) {\n this.onComplete();\n }\n }\n }\n\n prev() {\n if (this.steps.length === 0) return;\n \n if (this.currentStepIndex > 0) {\n this._emit('prev', { fromIndex: this.currentStepIndex, toIndex: this.currentStepIndex - 1 });\n this.goToStep(this.currentStepIndex - 1);\n }\n }\n\n getCurrentStep() {\n return this.currentStepIndex;\n }\n\n getTotalSteps() {\n return this.steps.length;\n }\n\n /**\n * Temporarily point to a target without changing the current step.\n * When next() is called, it will continue from where it left off.\n * @param {string|HTMLElement} target - The target element or selector\n * @param {string} content - Optional content to show\n * @param {string} direction - Optional direction: 'up', 'down', or null for auto\n */\n pointTo(target, content, direction) {\n const previousTarget = this.targetElement;\n \n this._emit('beforePointTo', { \n target: Pointy.getTargetElement(target), \n content: content,\n direction: direction,\n fromTarget: previousTarget\n });\n \n // Set manual direction\n this.manualDirection = direction || null;\n \n // Pause floating animation during movement\n this.container.classList.add(this.classNames.moving);\n if (this.moveTimeout) clearTimeout(this.moveTimeout);\n \n const toTarget = Pointy.getTargetElement(target);\n \n this._emit('animationStart', { \n fromTarget: previousTarget, \n toTarget: toTarget,\n type: 'pointTo',\n content: content\n });\n \n this.moveTimeout = setTimeout(() => {\n this.container.classList.remove(this.classNames.moving);\n this._emit('pointToComplete', { target: this.targetElement, content: content });\n this._emit('animationEnd', { \n fromTarget: previousTarget, \n toTarget: this.targetElement,\n type: 'pointTo',\n content: content\n });\n }, this.animationDuration);\n \n this.targetElement = toTarget;\n \n if (content !== undefined) {\n this._setMessages(content, false); // false = not from step change, don't auto-start cycle\n } else {\n // No new content - keep cycling if it was running\n // (cycle state is preserved)\n }\n \n this.updatePosition();\n \n this._emit('pointTo', { target: this.targetElement, content: content, direction: direction });\n \n // Make sure it's visible\n if (!this.isVisible) {\n this.show();\n }\n }\n\n /**\n * Subscribe to an event\n * @param {string} event - Event name\n * @param {function} callback - Callback function\n * @returns {Pointy} - Returns this for chaining\n * \n * Available events:\n * \n * Lifecycle:\n * - beforeShow: Before pointy becomes visible\n * - show: After pointy becomes visible\n * - beforeHide: Before pointy hides\n * - hide: After pointy hides\n * - destroy: When pointy is destroyed\n * - beforeReset: Before reset() is called\n * - reset: After reset completes\n * - beforeRestart: Before restart() is called\n * - restart: After restart completes\n * \n * Navigation:\n * - beforeStepChange: Before changing to a new step\n * - stepChange: After step has changed\n * - next: When next() is called\n * - prev: When prev() is called\n * - complete: When tour reaches the end\n * - beforePointTo: Before pointTo() moves to target\n * - pointTo: When pointTo() is called\n * - pointToComplete: When pointTo animation completes\n * \n * Animation:\n * - move: When pointy starts moving to a target\n * - moveComplete: When pointy finishes moving (after animation)\n * - animationStart: When any movement animation starts (step or pointTo)\n * - animationEnd: When any movement animation ends (step or pointTo)\n * - track: Each time position is updated during tracking\n * \n * Content:\n * - messagesSet: When messages array is set for a step\n * - messageChange: When current message changes (next/prev message) - includes isAuto flag\n * - contentSet: When setContent() is called\n * - messageCycleStart: When auto message cycling starts\n * - messageCycleStop: When auto message cycling stops\n * - messageCyclePause: When message cycling is paused\n * - messageCycleResume: When message cycling is resumed\n * - messageCycleComplete: When all messages have been shown (autoplayWaitForMessages)\n * \n * Autoplay:\n * - autoplayStart: When autoplay starts\n * - autoplayStop: When autoplay stops\n * - autoplayPause: When autoplay is paused\n * - autoplayResume: When autoplay is resumed\n * - autoplayNext: When autoplay triggers next step\n * - autoplayComplete: When autoplay finishes all steps\n * - autoplayChange: When autoplay interval changes\n * - autoplayWaitForMessagesChange: When autoplayWaitForMessages option changes\n * \n * Configuration changes:\n * - targetChange: When target element changes\n * - offsetChange: When offset values change\n * - animationDurationChange: When animation duration changes\n * - introFadeDurationChange: When intro fade duration changes\n * - bubbleFadeDurationChange: When bubble fade duration changes\n * - easingChange: When easing changes\n * - messageIntervalChange: When message interval changes\n * - messageTransitionDurationChange: When message transition duration changes\n * - pointerSvgChange: When pointer SVG changes\n * - resetOnCompleteChange: When resetOnComplete option changes\n * - floatingAnimationChange: When floating animation is toggled\n * - initialPositionChange: When initial position preset changes\n * - initialPositionOffsetChange: When initial position offset changes\n * \n * Generic Event Groups (listen to multiple events with one handler):\n * - 'lifecycle': beforeShow, show, beforeHide, hide, destroy, beforeRestart, restart, beforeReset, reset\n * - 'navigation': beforeStepChange, stepChange, next, prev, complete\n * - 'animation': animationStart, animationEnd, move, moveComplete, introAnimationStart, introAnimationEnd\n * - 'content': contentSet, messagesSet, messageChange\n * - 'messageCycle': messageCycleStart, messageCycleStop, messageCyclePause, messageCycleResume, messageCycleComplete\n * - 'pointing': beforePointTo, pointTo, pointToComplete\n * - 'tracking': track, targetChange, trackingChange, trackingFpsChange\n * - 'autoplay': autoplayStart, autoplayStop, autoplayPause, autoplayResume, autoplayNext, autoplayComplete, autoHide, autoplayChange, autoplayWaitForMessagesChange\n * - 'config': all *Change events\n * - '*' or 'all': all events\n * \n * Example: pointy.on('lifecycle', (data) => console.log(data.type, data));\n */\n on(event, callback) {\n if (!this._eventListeners[event]) {\n this._eventListeners[event] = [];\n }\n this._eventListeners[event].push(callback);\n return this;\n }\n\n /**\n * Unsubscribe from an event\n * @param {string} event - Event name\n * @param {function} callback - Callback function to remove\n * @returns {Pointy} - Returns this for chaining\n */\n off(event, callback) {\n if (!this._eventListeners[event]) return this;\n \n if (callback) {\n this._eventListeners[event] = this._eventListeners[event].filter(cb => cb !== callback);\n } else {\n // Remove all listeners for this event\n delete this._eventListeners[event];\n }\n return this;\n }\n\n /**\n * Emit an event\n * @param {string} event - Event name\n * @param {object} data - Event data\n * @private\n */\n _emit(event, data) {\n const eventData = { ...data, type: event, pointy: this };\n \n // Emit to specific event listeners\n if (this._eventListeners[event]) {\n this._eventListeners[event].forEach(callback => {\n try {\n callback(eventData);\n } catch (e) {\n console.error(`Pointy: Error in ${event} event handler:`, e);\n }\n });\n }\n \n // Find which group this event belongs to and emit to group listeners\n const group = Pointy.getEventGroup(event);\n if (group && this._eventListeners[group]) {\n this._eventListeners[group].forEach(callback => {\n try {\n callback(eventData);\n } catch (e) {\n console.error(`Pointy: Error in ${group} group handler for ${event}:`, e);\n }\n });\n }\n \n // Emit to wildcard listeners ('*' or 'all')\n ['*', 'all'].forEach(wildcard => {\n if (this._eventListeners[wildcard]) {\n this._eventListeners[wildcard].forEach(callback => {\n try {\n callback(eventData);\n } catch (e) {\n console.error(`Pointy: Error in wildcard handler for ${event}:`, e);\n }\n });\n }\n });\n }\n\n /**\n * Get the group name for an event\n * @param {string} event - Event name\n * @returns {string|null} - Group name or null if not in a group\n */\n static getEventGroup(event) {\n for (const [group, events] of Object.entries(Pointy.EVENT_GROUPS)) {\n if (events.includes(event)) {\n return group;\n }\n }\n // Check if it's a config change event\n if (event.endsWith('Change')) {\n return 'config';\n }\n return null;\n }\n\n /**\n * Get all events in a group\n * @param {string} group - Group name\n * @returns {string[]} - Array of event names\n */\n static getEventsInGroup(group) {\n return Pointy.EVENT_GROUPS[group] || [];\n }\n}\n\n/**\n * Event groups for generic listeners\n */\nPointy.EVENT_GROUPS = {\n lifecycle: ['beforeShow', 'show', 'beforeHide', 'hide', 'destroy', 'beforeRestart', 'restart', 'beforeReset', 'reset'],\n navigation: ['beforeStepChange', 'stepChange', 'next', 'prev', 'complete'],\n animation: ['animationStart', 'animationEnd', 'move', 'moveComplete', 'introAnimationStart', 'introAnimationEnd'],\n content: ['contentSet', 'messagesSet', 'messageChange'],\n messageCycle: ['messageCycleStart', 'messageCycleStop', 'messageCyclePause', 'messageCycleResume', 'messageCycleComplete'],\n pointing: ['beforePointTo', 'pointTo', 'pointToComplete'],\n tracking: ['track', 'targetChange', 'trackingChange', 'trackingFpsChange'],\n autoplay: ['autoplayStart', 'autoplayStop', 'autoplayPause', 'autoplayResume', 'autoplayNext', 'autoplayComplete', 'autoHide', 'autoplayChange', 'autoplayWaitForMessagesChange'],\n // 'config' is handled dynamically for all *Change events\n};\n\n// Export for different module systems\nexport default Pointy;\n"],"names":["Pointy","static","default","standard","decelerate","accelerate","bounce","elastic","smooth","snap","container","pointer","bubble","bubbleText","hidden","visible","moving","generateClassNames","prefix","DEFAULT_CLASS_PREFIX","suffixes","s","DEFAULT_CLASS_SUFFIXES","generateStyles","classNames","cssVarPrefix","cn","vp","Set","injectStyles","styleKey","JSON","stringify","injectedStyleKeys","has","fontInjected","fontLink","document","createElement","href","rel","head","appendChild","styleElement","id","length","textContent","add","getTargetElement","target","querySelector","animateText","element","newContent","duration","onComplete","hideTime","revealTime","newWidth","newHeight","measureDiv","style","cssText","renderContent","offsetWidth","offsetHeight","removeChild","currentWidth","currentHeight","width","height","transition","clipPath","setTimeout","content","$$typeof","ReactDOM","createRoot","root","render","_reactRoot","console","warn","innerHTML","String","constructor","options","this","classPrefix","classSuffixes","pointerSvg","POINTER_SVG","steps","offsetX","undefined","offsetY","tracking","trackingFps","animationDuration","introFadeDuration","bubbleFadeDuration","messageTransitionDuration","easing","resetOnComplete","floatingAnimation","initialPosition","initialPositionOffset","resetPositionOnHide","autoplay","autoplayEnabled","autoplayWaitForMessages","hideOnComplete","hideOnCompleteDelay","_autoplayTimeoutId","_autoplayPaused","_messagesCompletedForStep","_hideOnCompleteTimeoutId","onStepChange","_eventListeners","targetElement","currentStepIndex","currentMessageIndex","currentMessages","messageInterval","_messageIntervalId","isVisible","isPointingUp","lastTargetY","manualDirection","moveTimeout","_hasShownBefore","className","setProperty","_resolveEasing","animationPlayState","Array","isArray","updatePosition","bind","_trackPosition","_lastTrackTime","window","addEventListener","now","performance","interval","_emit","timestamp","_rafId","requestAnimationFrame","_startTracking","_stopTracking","cancelAnimationFrame","targetRect","getBoundingClientRect","scrollX","scrollY","currentTargetY","top","threshold","left","transform","bottom","bubbleHeight","show","clearTimeout","body","contains","isFirstStepStart","initialPos","_getInitialPosition","initialX","x","initialY","y","opacity","display","classList","remove","_startMessageCycle","_scheduleAutoplay","isIntro","isFirstStep","_messageCyclePausedByHide","_wasAutoplayActiveBeforeHide","hide","_stopMessageCycle","_stopAutoplay","restart","goToStep","destroy","removeEventListener","reset","goToFirstStep","currentStep","firstStep","stepIndex","setResetOnComplete","oldValue","from","to","setFloatingAnimation","enabled","isFloatingAnimationEnabled","setTracking","setTrackingFps","fps","isTrackingEnabled","updateContent","animate","_setMessages","fromStepChange","wasRunning","_messageCyclePaused","messages","total","cyclePaused","setInterval","totalMessages","_scheduleAutoplayAfterMessages","nextMessage","clearInterval","currentIndex","pauseMessageCycle","resumeMessageCycle","startMessageCycle","stopMessageCycle","isMessageCycleActive","isMessageCyclePaused","isAuto","previousIndex","fromIndex","toIndex","message","prevMessage","goToMessage","index","getCurrentMessage","getTotalMessages","setContent","animated","setMessageInterval","oldInterval","updateTarget","newTarget","oldTarget","setOffset","oldOffsetX","oldOffsetY","setAnimationDuration","oldDuration","setIntroFadeDuration","setBubbleFadeDuration","offset","w","innerWidth","h","innerHeight","firstTarget","direction","rect","startsWith","el","positions","center","setInitialPosition","position","validPresets","includes","join","oldPosition","animateToInitialPosition","setInitialPositionOffset","oldOffset","EASINGS","setEasing","oldEasing","setMessageTransitionDuration","setPointerSvg","svg","oldSvg","getPointerSvg","getClassNames","getClassPrefix","getCssVarPrefix","getEasingPresets","Object","keys","getInitialPositions","previousTarget","step","fromTarget","toTarget","type","hasMultipleMessages","next","afterMessages","startAutoplay","stopAutoplay","pauseAutoplay","resumeAutoplay","isAutoplayActive","isAutoplayPaused","setAutoplayInterval","setAutoplay","setAutoplayWaitForMessages","wait","setHideOnComplete","setHideOnCompleteDelay","delay","wasAutoplayActive","totalSteps","source","hideDelay","prev","getCurrentStep","getTotalSteps","pointTo","on","event","callback","push","off","filter","cb","data","eventData","pointy","forEach","e","error","group","getEventGroup","wildcard","events","entries","EVENT_GROUPS","endsWith","getEventsInGroup","lifecycle","navigation","animation","messageCycle","pointing"],"mappings":"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"}
package/package.json ADDED
@@ -0,0 +1,67 @@
1
+ {
2
+ "name": "@diabolic/pointy",
3
+ "version": "1.0.0",
4
+ "type": "module",
5
+ "description": "A lightweight, dependency-free JavaScript library for creating animated tooltips with a pointing cursor. Perfect for product tours, onboarding flows, and feature highlights.",
6
+ "main": "dist/pointy.js",
7
+ "module": "dist/pointy.esm.js",
8
+ "types": "dist/pointy.d.ts",
9
+ "files": [
10
+ "dist",
11
+ "src",
12
+ "README.md",
13
+ "LICENSE"
14
+ ],
15
+ "exports": {
16
+ ".": {
17
+ "import": "./dist/pointy.esm.js",
18
+ "require": "./dist/pointy.js",
19
+ "types": "./dist/pointy.d.ts"
20
+ }
21
+ },
22
+ "scripts": {
23
+ "build": "rollup -c",
24
+ "watch": "rollup -c -w",
25
+ "serve": "live-server docs --port=8080 --no-browser",
26
+ "dev": "concurrently \"npm run watch\" \"npm run serve\"",
27
+ "prepublishOnly": "npm run build",
28
+ "test": "echo \"No tests specified\" && exit 0"
29
+ },
30
+ "repository": {
31
+ "type": "git",
32
+ "url": "git+https://github.com/bugrakaan/pointy.git"
33
+ },
34
+ "keywords": [
35
+ "tooltip",
36
+ "tour",
37
+ "onboarding",
38
+ "product-tour",
39
+ "walkthrough",
40
+ "guided-tour",
41
+ "pointer",
42
+ "cursor",
43
+ "animation",
44
+ "vanilla-js",
45
+ "no-dependencies",
46
+ "lightweight",
47
+ "tutorial",
48
+ "help",
49
+ "guide",
50
+ "feature-highlight",
51
+ "user-onboarding"
52
+ ],
53
+ "author": "Diabolic",
54
+ "license": "MIT",
55
+ "bugs": {
56
+ "url": "https://github.com/bugrakaan/pointy/issues"
57
+ },
58
+ "homepage": "https://bugrakaan.github.io/pointy/",
59
+ "devDependencies": {
60
+ "@rollup/plugin-node-resolve": "^15.2.3",
61
+ "@rollup/plugin-terser": "^0.4.4",
62
+ "concurrently": "^9.2.1",
63
+ "live-server": "^1.2.0",
64
+ "rollup": "^4.9.0",
65
+ "rollup-plugin-copy": "^3.5.0"
66
+ }
67
+ }