-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathclicksense.js
More file actions
2 lines (2 loc) · 10.2 KB
/
Copy pathclicksense.js
File metadata and controls
2 lines (2 loc) · 10.2 KB
1
2
var ClickSenseLib=(()=>{var w=Object.defineProperty;var F=Object.getOwnPropertyDescriptor;var O=Object.getOwnPropertyNames;var H=Object.prototype.hasOwnProperty;var P=(_,e)=>{for(var s in e)w(_,s,{get:e[s],enumerable:!0})},V=(_,e,s,a)=>{if(e&&typeof e=="object"||typeof e=="function")for(let t of O(e))!H.call(_,t)&&t!==s&&w(_,t,{get:()=>e[t],enumerable:!(a=F(e,t))||a.enumerable});return _};var j=_=>V(w({},"__esModule",{value:!0}),_);var z={};P(z,{ClickSense:()=>C,createBufferedAdapter:()=>U,createPostHogAdapter:()=>Y});var R={minDuration:10,maxDuration:3e3,maxDragDistance:10,captureText:!0,textMaxLength:80,autoLabel:!0,pathDepth:3,buttons:[0],scope:null,enableApproachDynamics:!1,onCapture:null},S=60,k=4,q=500,K=300,W=1,C=class{constructor(e={}){if(this._config={...R,...e},!this._config.onCapture)throw new Error("ClickSense: onCapture callback is required");this._pending=null,this._root=null,this._onMouseDown=this._handleMouseDown.bind(this),this._onMouseUp=this._handleMouseUp.bind(this),this._onTouchStart=this._handleTouchStart.bind(this),this._onTouchEnd=this._handleTouchEnd.bind(this),this._config.enableApproachDynamics&&(this._onMouseMove=this._handleMouseMove.bind(this),this._velocityBuf=new Float64Array(S*k),this._bufHead=0,this._bufCount=0,this._lastMoveX=NaN,this._lastMoveY=NaN,this._lastMoveTime=NaN,this._lastSignificantMoveTime=NaN),this._attach()}destroy(){this._root&&(this._root.removeEventListener("mousedown",this._onMouseDown,!0),this._root.removeEventListener("mouseup",this._onMouseUp,!0),this._root.removeEventListener("touchstart",this._onTouchStart,!0),this._root.removeEventListener("touchend",this._onTouchEnd,!0),this._onMouseMove&&this._root.removeEventListener("mousemove",this._onMouseMove),this._root=null),this._pending=null,this._velocityBuf=null}_attach(){let e=this._config.scope;this._root=e?document.querySelector(e):document,this._root||(console.warn(`ClickSense: scope "${e}" not found, falling back to document`),this._root=document),this._root.addEventListener("mousedown",this._onMouseDown,!0),this._root.addEventListener("mouseup",this._onMouseUp,!0),this._root.addEventListener("touchstart",this._onTouchStart,{capture:!0,passive:!0}),this._root.addEventListener("touchend",this._onTouchEnd,{capture:!0,passive:!0}),this._onMouseMove&&this._root.addEventListener("mousemove",this._onMouseMove,{passive:!0})}_handleMouseMove(e){let s=typeof e.getCoalescedEvents=="function"?e.getCoalescedEvents():null;if(s&&s.length>0)for(let a=0;a<s.length;a++)this._recordVelocitySample(s[a].clientX,s[a].clientY,s[a].timeStamp);else this._recordVelocitySample(e.clientX,e.clientY,e.timeStamp)}_recordVelocitySample(e,s,a){if(!isFinite(this._lastMoveTime)){this._lastMoveX=e,this._lastMoveY=s,this._lastMoveTime=a,this._lastSignificantMoveTime=a;return}let t=a-this._lastMoveTime;if(t<=0)return;let o=e-this._lastMoveX,i=s-this._lastMoveY,r=Math.sqrt(o*o+i*i),c=r/t;r>W&&(this._lastSignificantMoveTime=a);let h=this._bufHead*k;this._velocityBuf[h]=c,this._velocityBuf[h+1]=a,this._velocityBuf[h+2]=e,this._velocityBuf[h+3]=s,this._bufHead=(this._bufHead+1)%S,this._bufCount<S&&this._bufCount++,this._lastMoveX=e,this._lastMoveY=s,this._lastMoveTime=a}_harvestApproach(e){if(!this._velocityBuf)return null;let s=isFinite(this._lastSignificantMoveTime)?Math.round(e-this._lastSignificantMoveTime):0;if(this._bufCount<2)return{approach_pause_ms:s};let a=e-q,t=e-K,o=[],i=[];for(let n=0;n<this._bufCount;n++){let l=(this._bufHead-1-n+S)%S*k,f=this._velocityBuf[l],p=this._velocityBuf[l+1],y=this._velocityBuf[l+2],d=this._velocityBuf[l+3];if(p<a)break;o.push({velocity:f,timestamp:p,x:y,y:d}),p>=t&&i.push({velocity:f,timestamp:p})}if(o.length<2)return{approach_pause_ms:s};let r=0;for(let n=0;n<o.length;n++)r+=o[n].velocity;let c=r/o.length,h=o[0].velocity,m=0;if(i.length>=2){let n=i.length,u=0,l=0,f=0,p=0,y=i[n-1].timestamp;for(let v=0;v<n;v++){let x=i[v].timestamp-y,b=i[v].velocity;u+=x,l+=b,f+=x*b,p+=x*x}let d=n*p-u*u;isFinite(d)&&Math.abs(d)>1e-10&&(m=(n*f-u*l)/d)}let M=0;if(o.length>=3){let n=0;for(let u=o.length-2;u>=1;u--){let l=o[u-1].velocity-o[u].velocity;n!==0&&l!==0&&Math.sign(l)!==Math.sign(n)&&M++,l!==0&&(n=l)}}let g=0;for(let n=o.length-1;n>=1;n--){let u=o[n-1].timestamp-o[n].timestamp;if(u>0){let l=(o[n-1].velocity+o[n].velocity)/2;g+=l*u}}let B=1,A=0,D="straight";if(o.length>=3){let n=o[o.length-1],u=o[0],l=u.x-n.x,f=u.y-n.y,p=Math.sqrt(l*l+f*f);if(g>0&&p>0&&(B=Math.min(1,p/g)),p>1){let y=f,d=-l,v=l*n.y-f*n.x,x=Math.sqrt(y*y+d*d),b=0,I=0,L=0;for(let E=0;E<o.length;E++){let T=(y*o[E].x+d*o[E].y+v)/x,X=Math.abs(T);X>b&&(b=X);let N=T>.5?1:T<-.5?-1:0;N!==0&&L!==0&&N!==L&&I++,N!==0&&(L=N)}A=b,I>0?D="reversal":b/p>=.1&&(D="curved")}}return{approach_velocity_mean:Math.round(c*1e3)/1e3,approach_velocity_final:Math.round(h*1e3)/1e3,approach_deceleration:Math.round(m*1e6)/1e6,approach_corrections:M,approach_distance:Math.round(g),approach_pause_ms:s,approach_linearity:Math.round(B*1e3)/1e3,approach_max_deviation:Math.round(A),approach_trajectory_type:D}}_handleMouseDown(e){this._config.buttons.includes(e.button)&&(this._pending={time:performance.now(),x:e.clientX,y:e.clientY,target:e.target,input_type:"mouse",approach:this._velocityBuf?this._harvestApproach(e.timeStamp):null})}_handleMouseUp(e){this._pending&&this._config.buttons.includes(e.button)&&this._measure(e.clientX,e.clientY,e.target)}_handleTouchStart(e){if(!e.touches.length)return;let s=e.touches[0];this._pending={time:performance.now(),x:s.clientX,y:s.clientY,target:e.target,input_type:"touch"}}_handleTouchEnd(e){if(!this._pending)return;let s=e.changedTouches?.[0],a=s?s.clientX:this._pending.x,t=s?s.clientY:this._pending.y;this._measure(a,t,e.target)}_measure(e,s,a){let t=this._pending;this._pending=null;let o=performance.now()-t.time;if(o<this._config.minDuration||o>this._config.maxDuration)return;let i=e-t.x,r=s-t.y,c=Math.sqrt(i*i+r*r);if(c>this._config.maxDragDistance)return;let h={duration_ms:Math.round(o),timestamp:Date.now(),x:Math.round(t.x),y:Math.round(t.y),drag_distance:Math.round(c),input_type:t.input_type,target:this._extractTarget(t.target)};t.approach&&(h.approach=t.approach);try{this._config.onCapture(h)}catch(m){console.warn("ClickSense: onCapture threw",m)}}_extractTarget(e){let a=e.closest('a, button, [role="button"], input, select, label, [data-clicksense]')||e,t={tag:a.tagName?.toLowerCase()||"unknown"};a.id&&(t.id=a.id);let o=a.getAttribute("data-clicksense");o&&(t.label=o);let i=a.className;if(typeof i=="string"&&i.length>0&&(t.classes=i.substring(0,100)),a.tagName==="A"&&a.href&&(t.href=a.href),this._config.captureText){let r=(a.innerText||a.textContent||"").trim();r.length>0&&(t.text=r.substring(0,this._config.textMaxLength))}if(this._config.autoLabel){let r=a.getAttribute("aria-label");r&&(t.aria_label=r.substring(0,this._config.textMaxLength));let c=a.getAttribute("title");c&&(t.title=c.substring(0,this._config.textMaxLength)),a.name&&(t.name=String(a.name).substring(0,80)),a.placeholder&&(t.placeholder=String(a.placeholder).substring(0,80)),(a.tagName==="BUTTON"&&a.value||a.tagName==="INPUT"&&/^(submit|button|reset)$/i.test(a.type)&&a.value)&&(t.value=String(a.value).substring(0,80));let h={},m=a.attributes;for(let M=0;M<m.length;M++){let g=m[M];g.name.startsWith("data-")&&g.name!=="data-clicksense"&&(h[g.name.slice(5)]=String(g.value).substring(0,80))}Object.keys(h).length>0&&(t.data=h),t.name_computed=t.label||t.aria_label||t.id||t.value||t.text||t.title||t.placeholder||t.tag,t.path=this._computePath(a,this._config.pathDepth)}return t}_computePath(e,s){if(!e||!e.tagName)return"";let a=[],t=e,o=0,i=Math.max(0,s|0);for(;t&&t.tagName&&t.tagName!=="BODY"&&t.tagName!=="HTML"&&o<=i;)a.unshift(this._selectorFor(t)),t=t.parentElement,o++;return a.join(" > ")}_selectorFor(e){let s=e.tagName.toLowerCase();if(e.id)return s+"#"+e.id;let t=(e.className&&typeof e.className=="string"?e.className.trim().split(/\s+/):[]).filter(i=>i&&/^[a-zA-Z_][\w-]*$/.test(i)).slice(0,2);t.length>0&&(s+="."+t.join("."));let o=e.parentElement;if(o){let i=1,r=!1;for(let c=0;c<o.children.length;c++){let h=o.children[c];if(h===e)break;h.tagName===e.tagName&&(i++,r=!0)}if(!r)for(let c=0;c<o.children.length;c++){let h=o.children[c];if(h!==e&&h.tagName===e.tagName){r=!0;break}}r&&(s+=":nth-of-type("+i+")")}return s}};var Z="0.2.0",$="2026-05-30";function Y(_,e="click_confidence",s){return function(t){let o=_||window.posthog;if(!o||typeof o.capture!="function"){console.warn("ClickSense PostHog adapter: posthog not available");return}let i={duration_ms:t.duration_ms,click_x:t.x,click_y:t.y,drag_distance:t.drag_distance,input_type:t.input_type,target_tag:t.target.tag};if(t.target.id&&(i.target_id=t.target.id),t.target.label&&(i.target_label=t.target.label),t.target.classes&&(i.target_classes=t.target.classes),t.target.href&&(i.target_href=t.target.href),t.target.text&&(i.target_text=t.target.text),t.target.aria_label&&(i.target_aria_label=t.target.aria_label),t.target.title&&(i.target_title=t.target.title),t.target.name&&(i.target_name_attr=t.target.name),t.target.value&&(i.target_value=t.target.value),t.target.placeholder&&(i.target_placeholder=t.target.placeholder),t.target.name_computed&&(i.target_name=t.target.name_computed),t.target.path&&(i.target_path=t.target.path),t.target.data)for(let r in t.target.data){let c=r.replace(/[^a-zA-Z0-9_-]/g,"_");i["target_data_"+c]=t.target.data[r]}t.approach&&(i.approach_velocity_mean=t.approach.approach_velocity_mean,i.approach_velocity_final=t.approach.approach_velocity_final,i.approach_deceleration=t.approach.approach_deceleration,i.approach_corrections=t.approach.approach_corrections,i.approach_distance=t.approach.approach_distance,i.approach_pause_ms=t.approach.approach_pause_ms,i.approach_linearity=t.approach.approach_linearity,i.approach_max_deviation=t.approach.approach_max_deviation,i.approach_trajectory_type=t.approach.approach_trajectory_type),i.clicksense_version=Z,i.clicksense_build=$,s&&Object.assign(i,s),o.capture(e,i)}}function U({onFlush:_,flushInterval:e=3e4,maxBuffer:s=200}){let a=[],t=null;function o(){if(a.length===0)return;let i=a;a=[];try{_(i)}catch(r){console.warn("ClickSense buffered adapter: onFlush threw",r)}}return e>0&&(t=setInterval(o,e)),typeof window<"u"&&window.addEventListener("visibilitychange",()=>{document.visibilityState==="hidden"&&o()}),function(r){a.push(r),a.length>=s&&o()}}return j(z);})();
//# sourceMappingURL=clicksense.js.map