@li2/analytics 0.3.1-beta.0 → 0.3.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/auto-events.global.js +1 -1
- package/dist/auto-events.js +1 -1
- package/dist/auto-events.mjs +1 -1
- package/dist/chunk-FF6VDEL5.mjs +1 -0
- package/dist/chunk-LZDMBCUK.mjs +1 -1
- package/dist/chunk-MURA7RU5.mjs +1 -1
- package/dist/click-tracker/index.global.js +1 -1
- package/dist/click-tracker/index.js +1 -1
- package/dist/click-tracker/index.mjs +1 -1
- package/dist/element-resolver-BnZ_ItHT.d.mts +22 -0
- package/dist/element-resolver-BnZ_ItHT.d.ts +22 -0
- package/dist/index.d.mts +2 -22
- package/dist/index.d.ts +2 -22
- package/dist/index.global.js +1 -1
- package/dist/index.js +1 -1
- package/dist/index.mjs +1 -1
- package/dist/outbound.global.js +1 -1
- package/dist/outbound.js +1 -1
- package/dist/outbound.mjs +1 -1
- package/dist/pageview/index.global.js +1 -1
- package/dist/pageview/index.js +1 -1
- package/dist/pageview/index.mjs +1 -1
- package/dist/toolbar/index.d.mts +25 -3
- package/dist/toolbar/index.d.ts +25 -3
- package/dist/toolbar/index.global.js +95 -2
- package/dist/toolbar/index.js +95 -2
- package/dist/toolbar/index.mjs +95 -2
- package/package.json +12 -13
- package/dist/chunk-6RUMMSEZ.mjs +0 -1
- package/dist/click-triggers.d.mts +0 -2
- package/dist/click-triggers.d.ts +0 -2
- package/dist/click-triggers.global.js +0 -1
- package/dist/click-triggers.js +0 -1
- package/dist/click-triggers.mjs +0 -1
- package/dist/index-DEfkJIjF.d.mts +0 -114
- package/dist/index-DEfkJIjF.d.ts +0 -114
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
"use strict";var li2Analytics=(()=>{var g=Object.defineProperty;var S=Object.getOwnPropertyDescriptor;var H=Object.getOwnPropertyNames;var L=Object.prototype.hasOwnProperty;var U=(a,t)=>{for(var e in t)g(a,e,{get:t[e],enumerable:!0})},R=(a,t,e,o)=>{if(t&&typeof t=="object"||typeof t=="function")for(let i of H(t))!L.call(a,i)&&i!==e&&g(a,i,{get:()=>t[i],enumerable:!(o=S(t,i))||o.enumerable});return a};var D=a=>R(g({},"__esModule",{value:!0}),a);var I={};U(I,{ToolbarManager:()=>f});async function x(a){let t=new URL(`${a.apiUrl}/api/v1/track/heatmap/clicks`);t.searchParams.set("page_path",a.pagePath),t.searchParams.set("from",a.from),t.searchParams.set("to",a.to),t.searchParams.set("target_width",String(a.targetWidth)),a.deviceType&&t.searchParams.set("device_type",a.deviceType);let e=await fetch(t.toString(),{headers:{"X-Li2-Key":a.publishableKey}});if(!e.ok)throw new Error(`Heatmap API error: ${e.status}`);return(await e.json()).data.heatmap}var b=[[0,[0,0,255,128]],[.25,[0,255,255,200]],[.5,[0,255,0,220]],[.75,[255,255,0,240]],[1,[255,0,0,255]]];function _(a){if(a<=0)return[0,0,0,0];let t=Math.min(1,Math.max(0,a));for(let e=0;e<b.length-1;e++){let[o,i]=b[e],[d,l]=b[e+1];if(t>=o&&t<=d){let s=(t-o)/(d-o);return[Math.round(i[0]+(l[0]-i[0])*s),Math.round(i[1]+(l[1]-i[1])*s),Math.round(i[2]+(l[2]-i[2])*s),Math.round(i[3]+(l[3]-i[3])*s)]}}return[255,0,0,255]}var O=30;function C(a,t,e,o,i=O){let d=a.getContext("2d");if(!d||t.length===0||e===0||o===0)return;a.width=e,a.height=o;let l=Math.max(...t.map(n=>n.count));if(l===0)return;let s=document.createElement("canvas");s.width=e,s.height=o;let r=s.getContext("2d");if(!r)return;r.fillStyle="black",r.fillRect(0,0,e,o),r.globalCompositeOperation="lighter";for(let n of t){if(n.x<-i||n.x>e+i||n.y<-i||n.y>o+i)continue;let u=n.count/l,c=r.createRadialGradient(n.x,n.y,0,n.x,n.y,i);c.addColorStop(0,`rgba(255,255,255,${u})`),c.addColorStop(.33,`rgba(255,255,255,${u*.607})`),c.addColorStop(.67,`rgba(255,255,255,${u*.135})`),c.addColorStop(1,"rgba(255,255,255,0)"),r.fillStyle=c,r.beginPath(),r.arc(n.x,n.y,i,0,Math.PI*2),r.fill()}let v=r.getImageData(0,0,e,o).data,y=d.createImageData(e,o),p=y.data;for(let n=0;n<v.length;n+=4){let u=v[n]/255;if(u>.01){let[c,w,P,T]=_(u);p[n]=c,p[n+1]=w,p[n+2]=P,p[n+3]=T}}d.putImageData(y,0,0)}var h=class{constructor(){this.grid=[];this.handleResize=()=>{this.resize(),this.doRender()};this.canvas=document.createElement("canvas"),this.canvas.style.cssText="position:absolute;top:0;left:0;pointer-events:none;z-index:99998;"}mount(){document.body.appendChild(this.canvas),this.resize(),window.addEventListener("resize",this.handleResize)}unmount(){this.canvas.remove(),window.removeEventListener("resize",this.handleResize)}render(t){this.grid=t,this.doRender()}setOpacity(t){this.canvas.style.opacity=String(t)}resize(){let t=document.documentElement.scrollWidth,e=document.documentElement.scrollHeight;this.canvas.style.width=`${t}px`,this.canvas.style.height=`${e}px`}doRender(){if(this.grid.length===0)return;let t=document.documentElement.scrollWidth,e=document.documentElement.scrollHeight;C(this.canvas,this.grid,t,e)}};var m=class{constructor(t){this.root=null;this.statsEl=null;this.statusEl=null;this.config=t}mount(){this.root=document.createElement("div"),this.root.className="__li2-toolbar";let t=document.createElement("span");t.textContent="Li2 Heatmap",this.root.appendChild(t),this.root.appendChild(this.createSeparator()),this.statsEl=document.createElement("span"),this.statsEl.className="__li2-toolbar-stat",this.statsEl.textContent="...",this.root.appendChild(this.statsEl),this.root.appendChild(this.createSeparator()),this.statusEl=document.createElement("span"),this.root.appendChild(this.statusEl);let e=document.createElement("input");e.type="range",e.min="0",e.max="100",e.value=String(Math.round(this.config.initialOpacity*100)),e.className="__li2-toolbar-slider",e.addEventListener("input",()=>{this.config.onOpacityChange(Number(e.value)/100)}),this.root.appendChild(e);let o=document.createElement("button");o.className="__li2-toolbar-close",o.textContent="\xD7",o.title="Close heatmap",o.addEventListener("click",this.config.onClose),this.root.appendChild(o),document.body.appendChild(this.root)}unmount(){this.root?.remove(),this.root=null}setStats(t,e){this.statsEl&&(this.statsEl.textContent=`${t.toLocaleString()} clicks`)}setLoading(t){this.statusEl&&(t?(this.statusEl.className="__li2-toolbar-loading",this.statusEl.textContent="Loading..."):(this.statusEl.textContent="",this.statusEl.className=""))}setError(t){this.statusEl&&(this.statusEl.className="__li2-toolbar-error",this.statusEl.textContent=t)}createSeparator(){let t=document.createElement("span");return t.style.cssText="color:#555;user-select:none;",t.textContent="|",t}};function E(){if(document.getElementById("__li2-toolbar-styles"))return;let a=document.createElement("style");a.id="__li2-toolbar-styles",a.textContent=`
|
|
1
|
+
"use strict";var li2Analytics=(()=>{var C=Object.defineProperty;var D=Object.getOwnPropertyDescriptor;var $=Object.getOwnPropertyNames;var A=Object.prototype.hasOwnProperty;var B=(i,e)=>{for(var t in e)C(i,t,{get:e[t],enumerable:!0})},U=(i,e,t,n)=>{if(e&&typeof e=="object"||typeof e=="function")for(let a of $(e))!A.call(i,a)&&a!==t&&C(i,a,{get:()=>e[a],enumerable:!(n=D(e,a))||n.enumerable});return i};var F=i=>U(C({},"__esModule",{value:!0}),i);var ee={};B(ee,{ToolbarManager:()=>y});async function k(i){let e=new URL(`${i.apiUrl}/api/v1/track/heatmap/clicks`);e.searchParams.set("page_path",i.pagePath),e.searchParams.set("from",i.from),e.searchParams.set("to",i.to),e.searchParams.set("target_width",String(i.targetWidth)),i.deviceType&&e.searchParams.set("device_type",i.deviceType);let t={"X-Li2-Key":i.publishableKey};i.sessionToken&&(t["X-Li2-Session"]=i.sessionToken);let n=await fetch(e.toString(),{headers:t});if(!n.ok)throw new Error(`Heatmap API error: ${n.status}`);return(await n.json()).data.heatmap}var w=[[0,[0,0,255,128]],[.25,[0,255,255,200]],[.5,[0,255,0,220]],[.75,[255,255,0,240]],[1,[255,0,0,255]]];function M(i){if(i<=0)return[0,0,0,0];let e=Math.min(1,Math.max(0,i));for(let t=0;t<w.length-1;t++){let[n,a]=w[t],[o,l]=w[t+1];if(e>=n&&e<=o){let s=(e-n)/(o-n);return[Math.round(a[0]+(l[0]-a[0])*s),Math.round(a[1]+(l[1]-a[1])*s),Math.round(a[2]+(l[2]-a[2])*s),Math.round(a[3]+(l[3]-a[3])*s)]}}return[255,0,0,255]}var G=30;function S(i,e,t,n,a=G){let o=i.getContext("2d");if(!o||e.length===0||t===0||n===0)return;i.width=t,i.height=n;let l=Math.max(...e.map(r=>r.count));if(l===0)return;let s=document.createElement("canvas");s.width=t,s.height=n;let c=s.getContext("2d");if(!c)return;c.fillStyle="black",c.fillRect(0,0,t,n),c.globalCompositeOperation="lighter";for(let r of e){if(r.x<-a||r.x>t+a||r.y<-a||r.y>n+a)continue;let u=r.count/l,d=c.createRadialGradient(r.x,r.y,0,r.x,r.y,a);d.addColorStop(0,`rgba(255,255,255,${u})`),d.addColorStop(.33,`rgba(255,255,255,${u*.607})`),d.addColorStop(.67,`rgba(255,255,255,${u*.135})`),d.addColorStop(1,"rgba(255,255,255,0)"),c.fillStyle=d,c.beginPath(),c.arc(r.x,r.y,a,0,Math.PI*2),c.fill()}let m=c.getImageData(0,0,t,n).data,p=o.createImageData(t,n),h=p.data;for(let r=0;r<m.length;r+=4){let u=m[r]/255;if(u>.01){let[d,R,O,z]=M(u);h[r]=d,h[r+1]=R,h[r+2]=O,h[r+3]=z}}o.putImageData(p,0,0)}var b=class{constructor(){this.grid=[];this.handleResize=()=>{this.resize(),this.doRender()};this.canvas=document.createElement("canvas"),this.canvas.style.cssText="position:absolute;top:0;left:0;pointer-events:none;z-index:99998;"}mount(){document.body.appendChild(this.canvas),this.resize(),window.addEventListener("resize",this.handleResize)}unmount(){this.canvas.remove(),window.removeEventListener("resize",this.handleResize)}render(e){this.grid=e,this.doRender()}setOpacity(e){this.canvas.style.opacity=String(e)}resize(){let e=document.documentElement.scrollWidth,t=document.documentElement.scrollHeight;this.canvas.style.width=`${e}px`,this.canvas.style.height=`${t}px`}doRender(){if(this.grid.length===0)return;let e=document.documentElement.scrollWidth,t=document.documentElement.scrollHeight;S(this.canvas,this.grid,e,t)}};var x=class{constructor(){this.highlight=null;this.tooltip=null;this.currentElement=null}mount(){this.highlight=document.createElement("div"),this.highlight.className="__li2-tagger-highlight",document.body.appendChild(this.highlight),this.tooltip=document.createElement("div"),this.tooltip.className="__li2-tagger-tooltip",document.body.appendChild(this.tooltip)}unmount(){this.highlight?.remove(),this.tooltip?.remove(),this.highlight=null,this.tooltip=null,this.currentElement=null}highlightElement(e){if(!this.highlight||!this.tooltip||e===this.currentElement)return;this.currentElement=e;let t=e.getBoundingClientRect(),n=window.getComputedStyle(e).position==="fixed",a=Math.max(t.width,20),o=Math.max(t.height,20);this.highlight.style.position=n?"fixed":"absolute",this.highlight.style.top=n?`${t.top}px`:`${t.top+window.scrollY}px`,this.highlight.style.left=n?`${t.left}px`:`${t.left+window.scrollX}px`,this.highlight.style.width=`${a}px`,this.highlight.style.height=`${o}px`,this.highlight.style.display="block";let l=e.tagName.toLowerCase(),s=(e.innerText||"").trim().slice(0,40),c=e.id?` #${e.id}`:"",g=s?` "${s}${s.length>=40?"...":""}"`:"";this.tooltip.textContent=`<${l}>${g}${c}`,this.tooltip.style.position=n?"fixed":"absolute";let m=n?t.top-28:t.top+window.scrollY-28;this.tooltip.style.top=`${Math.max(m,4)}px`,this.tooltip.style.left=n?`${t.left}px`:`${t.left+window.scrollX}px`,this.tooltip.style.display="block"}clearHighlight(){this.highlight&&(this.highlight.style.display="none"),this.tooltip&&(this.tooltip.style.display="none"),this.currentElement=null}fixSelection(e){this.highlightElement(e),this.highlight&&this.highlight.classList.add("__li2-tagger-highlight--selected")}clearSelection(){this.highlight&&this.highlight.classList.remove("__li2-tagger-highlight--selected")}updatePosition(){if(this.currentElement){let e=this.currentElement;this.currentElement=null,this.highlightElement(e)}}};var j=new Set(["a","button","input","select","textarea","form","label"]),K=new Set(["button","link","tab","menuitem"]);function T(i){let e=i;for(;e&&!(e instanceof HTMLElement);)e=e.parentElement;if(!e)return null;let n=W(e),a=X(n);return{tag:n.tagName.toLowerCase(),text:H(Y(n),256),href:V(n),className:H(n.className||"",512),id:n.id||null,selectorPath:q(n),isFixed:a}}function W(i){let e=i,t=0;for(;e&&t<5&&e.tagName!=="BODY";){let n=e.tagName.toLowerCase(),a=e.getAttribute("role");if(j.has(n)||a&&K.has(a))return e;e=e.parentElement,t++}return i}function X(i){let e=i;for(;e&&e!==document.body;){try{let n=window.getComputedStyle(e).getPropertyValue("position");if(n==="fixed"||n==="sticky")return!0}catch{break}e=e.parentElement}return!1}function q(i){let e=[],t=i,n=0;for(;t&&t!==document.body&&n<5;){let a=t.tagName.toLowerCase();t.id&&(a+=`#${t.id}`);let o=t.parentElement;if(o){let l=Array.from(o.children).filter(s=>s.tagName===t.tagName);if(l.length>1){let s=l.indexOf(t)+1;a+=`:nth-of-type(${s})`}}e.unshift(a),t=t.parentElement,n++}return e.join(" > ")}function Y(i){return i instanceof HTMLInputElement?i.value||i.placeholder||"":(i.innerText||i.textContent||"").trim()}function V(i){return i instanceof HTMLAnchorElement?i.href||null:i.getAttribute("href")||null}function H(i,e){return i.length<=e?i:i.slice(0,e)}var E=class{constructor(e,t){this.active=!1;this.overlay=e,this.callbacks=t,this.handleMouseMove=this.onMouseMove.bind(this),this.handleClick=this.onClick.bind(this),this.handleScroll=this.onScroll.bind(this)}activate(){this.active||(this.active=!0,document.addEventListener("mousemove",this.handleMouseMove,!0),document.addEventListener("click",this.handleClick,!0),window.addEventListener("scroll",this.handleScroll,!0))}deactivate(){this.active&&(this.active=!1,document.removeEventListener("mousemove",this.handleMouseMove,!0),document.removeEventListener("click",this.handleClick,!0),window.removeEventListener("scroll",this.handleScroll,!0),this.overlay.clearHighlight(),this.overlay.clearSelection())}onMouseMove(e){let t=e.target;if(!t)return;if(this.isToolbarElement(t)){this.overlay.clearHighlight();return}if(!T(t)){this.overlay.clearHighlight();return}let a=this.findMeaningfulDomElement(t);a&&this.overlay.highlightElement(a)}onClick(e){let t=e.target;if(!t||this.isToolbarElement(t))return;e.preventDefault(),e.stopPropagation();let n=T(t);if(!n)return;let a=this.findMeaningfulDomElement(t);a&&(this.overlay.fixSelection(a),this.callbacks.onElementSelected(a,n))}onScroll(){this.overlay.updatePosition()}isToolbarElement(e){let t=e;for(;t;){let n=t.className;if(typeof n=="string"&&(n.includes("__li2-toolbar")||n.includes("__li2-tagger")))return!0;t=t.parentElement}return!1}findMeaningfulDomElement(e){let t=new Set(["a","button","input","select","textarea","form","label"]),n=new Set(["button","link","tab","menuitem"]),a=e,o=0;for(;a&&o<5&&a.tagName!=="BODY";){let l=a.tagName.toLowerCase(),s=a.getAttribute("role");if(t.has(l)||s&&n.has(s))return a;a=a.parentElement,o++}return e}};var f=class extends Error{constructor(e,t){super(t),this.status=e}};function P(i){return{"X-Li2-Key":i.publishableKey,"X-Li2-Session":i.sessionToken}}async function N(i,e){let t=await fetch(`${i.apiUrl}/api/v1/track/event-rules`,{method:"POST",headers:{"Content-Type":"application/json",...P(i)},body:JSON.stringify(e)}),n=await t.json().catch(()=>({}));if(!t.ok){let a=n.error||n.message||`Error ${t.status}`;throw new f(t.status,a)}return n.data}async function I(i){let e=await fetch(`${i.apiUrl}/api/v1/track/event-rules`,{headers:P(i)});if(!e.ok)throw new f(e.status,"Failed to load existing rules");return(await e.json()).data||[]}var _=class{constructor(e){this.root=null;this.nameInput=null;this.nameError=null;this.submitBtn=null;this.statusEl=null;this.rulesListEl=null;this.criteriaCheckboxes=new Map;this.existingRules=[];this.currentInfo=null;this.state="idle";this.config=e}mount(){this.root=document.createElement("div"),this.root.className="__li2-tagger-panel",this.root.style.display="none",document.body.appendChild(this.root),this.fetchExistingRules()}unmount(){this.root?.remove(),this.root=null,this.criteriaCheckboxes.clear()}show(e){this.currentInfo=e,this.state="selected",this.buildPanelContent(e),this.root&&(this.root.style.display="block")}hide(){this.currentInfo=null,this.state="idle",this.root&&(this.root.style.display="none",this.root.innerHTML=""),this.criteriaCheckboxes.clear()}buildPanelContent(e){if(!this.root)return;this.root.innerHTML="",this.criteriaCheckboxes.clear();let t=document.createElement("div");t.className="__li2-tagger-panel-header";let n=document.createElement("span");n.textContent="Create Event Rule",t.appendChild(n);let a=document.createElement("button");a.className="__li2-tagger-panel-close",a.textContent="\xD7",a.addEventListener("click",()=>this.handleCancel()),t.appendChild(a),this.root.appendChild(t);let o=document.createElement("div");o.className="__li2-tagger-summary";let l=e.text?` "${e.text.slice(0,30)}${e.text.length>30?"...":""}"`:"";o.textContent=`Selected: <${e.tag}>${l} on ${window.location.pathname}`,this.root.appendChild(o);let s=document.createElement("div");s.className="__li2-tagger-field";let c=document.createElement("label");c.className="__li2-tagger-label",c.textContent="Event name",s.appendChild(c),this.nameInput=document.createElement("input"),this.nameInput.type="text",this.nameInput.placeholder="e.g. signup_click",this.nameInput.className="__li2-tagger-input",this.nameInput.addEventListener("input",()=>this.onNameInput()),s.appendChild(this.nameInput),this.nameError=document.createElement("div"),this.nameError.className="__li2-tagger-field-error",s.appendChild(this.nameError),this.root.appendChild(s);let g=document.createElement("div");g.className="__li2-tagger-label",g.textContent="Match criteria",this.root.appendChild(g);let m=[{key:"selector_path",label:"CSS Selector",value:e.selectorPath||null},{key:"element_text",label:"Text contains",value:e.text||null},{key:"element_id",label:"Element ID",value:e.id||null},{key:"element_href",label:"Link href",value:e.href||null},{key:"page_path",label:"Page path",value:window.location.pathname}];for(let u of m){let d=this.createCriterionRow(u);this.root.appendChild(d)}this.statusEl=document.createElement("div"),this.statusEl.className="__li2-tagger-panel-status",this.root.appendChild(this.statusEl);let p=document.createElement("div");p.className="__li2-tagger-btn-row";let h=document.createElement("button");h.className="__li2-tagger-btn __li2-tagger-btn-cancel",h.textContent="Cancel",h.addEventListener("click",()=>this.handleCancel()),p.appendChild(h),this.submitBtn=document.createElement("button"),this.submitBtn.className="__li2-tagger-btn __li2-tagger-btn-submit",this.submitBtn.textContent="Create Event Rule",this.submitBtn.addEventListener("click",()=>this.handleSubmit()),p.appendChild(this.submitBtn),this.root.appendChild(p);let r=document.createElement("div");r.className="__li2-tagger-rules-header",r.textContent="Existing rules",this.root.appendChild(r),this.rulesListEl=document.createElement("div"),this.rulesListEl.className="__li2-tagger-rules-list",this.renderRulesList(),this.root.appendChild(this.rulesListEl),setTimeout(()=>this.nameInput?.focus(),50)}createCriterionRow(e){let t=document.createElement("div");t.className="__li2-tagger-criterion";let n=document.createElement("input");n.type="checkbox",n.checked=!!e.value,n.disabled=!e.value,n.addEventListener("change",()=>this.updateSubmitState()),this.criteriaCheckboxes.set(e.key,n),t.appendChild(n);let a=document.createElement("span");a.className="__li2-tagger-criterion-label",a.textContent=e.label+":",t.appendChild(a);let o=document.createElement("span");return o.className="__li2-tagger-criterion-value",o.textContent=e.value?J(e.value,60):"(empty)",e.value||(o.style.color="#666"),t.appendChild(o),t}onNameInput(){if(!this.nameInput)return;let e=this.nameInput.value,t=e.toLowerCase().replace(/[^a-z0-9_]/g,"");t!==e&&(this.nameInput.value=t),this.validateName(),this.updateSubmitState()}validateName(){let e=this.nameInput?.value||"",t=null;return e?e.length>256?t="Max 256 characters":/^[a-z0-9_]+$/.test(e)?this.existingRules.some(n=>n.name===e)&&(t="Event name already exists"):t="Only lowercase letters, numbers, and underscores":t=null,this.nameError&&(this.nameError.textContent=t||""),t}updateSubmitState(){if(!this.submitBtn)return;let e=!!this.nameInput?.value&&!this.validateName(),t=this.getCheckedCriteria().length>0;this.submitBtn.disabled=!e||!t||this.state==="creating"}getCheckedCriteria(){let e=[];for(let[t,n]of this.criteriaCheckboxes)n.checked&&e.push(t);return e}async handleSubmit(){if(!this.nameInput||!this.currentInfo)return;let e=this.nameInput.value;if(!e||this.validateName())return;this.state="creating",this.setFormDisabled(!0),this.setStatus("Creating...","loading");let t=new Set(this.getCheckedCriteria()),n=this.currentInfo,a={name:e,selector_path:t.has("selector_path")&&n.selectorPath||void 0,element_text:t.has("element_text")&&n.text||void 0,element_id:t.has("element_id")&&n.id||void 0,element_href:t.has("element_href")&&n.href||void 0,page_path:t.has("page_path")?window.location.pathname:void 0,text_match_mode:t.has("element_text")?"contains":void 0},o={};for(let[l,s]of Object.entries(a))s!==void 0&&(o[l]=s);try{await N(this.config.apiConfig,o),this.state="success",this.setStatus(`Event rule '${e}' created!`,"success"),await this.fetchExistingRules(),setTimeout(()=>{this.hide(),this.config.onCreated(e)},2e3)}catch(l){this.state="error",this.setFormDisabled(!1),l instanceof f?this.setStatus(l.message,"error"):this.setStatus("Connection failed. Please try again.","error")}}handleCancel(){this.hide(),this.config.onCancel()}setFormDisabled(e){this.nameInput&&(this.nameInput.disabled=e),this.submitBtn&&(this.submitBtn.disabled=e,this.submitBtn.textContent=e?"Creating...":"Create Event Rule");for(let t of this.criteriaCheckboxes.values())(t.checked||!e)&&(t.disabled=e?!0:!t.checked)}setStatus(e,t){this.statusEl&&(this.statusEl.textContent=e,this.statusEl.className="__li2-tagger-panel-status",t==="loading"?this.statusEl.classList.add("__li2-tagger-status-loading"):t==="success"?this.statusEl.classList.add("__li2-tagger-status-success"):t==="error"&&this.statusEl.classList.add("__li2-tagger-status-error"))}async fetchExistingRules(){try{this.existingRules=await I(this.config.apiConfig),this.renderRulesList()}catch{}}renderRulesList(){if(this.rulesListEl){if(this.rulesListEl.innerHTML="",this.existingRules.length===0){let e=document.createElement("div");e.className="__li2-tagger-rules-empty",e.textContent="No rules yet",this.rulesListEl.appendChild(e);return}for(let e of this.existingRules){let t=document.createElement("div");t.className="__li2-tagger-rule-item",t.textContent=`\u2022 ${e.name}`,this.rulesListEl.appendChild(t)}}}};function J(i,e){return i.length>e?i.slice(0,e)+"...":i}var v=class{constructor(e){this.root=null;this.statsEl=null;this.statusEl=null;this.config=e}mount(){this.root=document.createElement("div"),this.root.className="__li2-toolbar",this.config.mode==="tagger"?this.mountTagger():this.mountHeatmap(),document.body.appendChild(this.root)}mountHeatmap(){if(!this.root)return;let e=document.createElement("span");e.textContent="Li2 Heatmap",this.root.appendChild(e),this.root.appendChild(this.createSeparator()),this.statsEl=document.createElement("span"),this.statsEl.className="__li2-toolbar-stat",this.statsEl.textContent="...",this.root.appendChild(this.statsEl),this.root.appendChild(this.createSeparator()),this.statusEl=document.createElement("span"),this.root.appendChild(this.statusEl);let t=document.createElement("input");t.type="range",t.min="0",t.max="100",t.value=String(Math.round(this.config.initialOpacity*100)),t.className="__li2-toolbar-slider",t.addEventListener("input",()=>{this.config.onOpacityChange(Number(t.value)/100)}),this.root.appendChild(t),this.appendCloseButton("Close heatmap")}mountTagger(){if(!this.root)return;let e=document.createElement("span");e.textContent="Li2 Event Tagger",this.root.appendChild(e),this.root.appendChild(this.createSeparator()),this.statusEl=document.createElement("span"),this.statusEl.className="__li2-toolbar-status",this.statusEl.textContent="Click an element to tag",this.root.appendChild(this.statusEl),this.appendCloseButton("Close tagger")}appendCloseButton(e){if(!this.root)return;let t=document.createElement("button");t.className="__li2-toolbar-close",t.textContent="\xD7",t.title=e,t.addEventListener("click",this.config.onClose),this.root.appendChild(t)}unmount(){this.root?.remove(),this.root=null}setStats(e,t){this.statsEl&&(this.statsEl.textContent=`${e.toLocaleString()} clicks`)}setLoading(e){this.statusEl&&(e?(this.statusEl.className="__li2-toolbar-loading",this.statusEl.textContent="Loading..."):(this.statusEl.textContent="",this.statusEl.className=""))}setStatus(e){this.statusEl&&(this.statusEl.className="__li2-toolbar-status",this.statusEl.textContent=e)}setError(e){this.statusEl&&(this.statusEl.className="__li2-toolbar-error",this.statusEl.textContent=e)}createSeparator(){let e=document.createElement("span");return e.style.cssText="color:#555;user-select:none;",e.textContent="|",e}};function L(){if(document.getElementById("__li2-toolbar-styles"))return;let i=document.createElement("style");i.id="__li2-toolbar-styles",i.textContent=`
|
|
2
2
|
.__li2-toolbar {
|
|
3
3
|
position: fixed; bottom: 20px; right: 20px; z-index: 99999;
|
|
4
4
|
background: #1a1a2e; color: #fff; border-radius: 12px;
|
|
@@ -17,4 +17,97 @@
|
|
|
17
17
|
.__li2-toolbar-stat { color: #a5b4fc; font-variant-numeric: tabular-nums; }
|
|
18
18
|
.__li2-toolbar-loading { color: #fbbf24; }
|
|
19
19
|
.__li2-toolbar-error { color: #f87171; }
|
|
20
|
-
|
|
20
|
+
.__li2-toolbar-status { color: #a5b4fc; }
|
|
21
|
+
.__li2-tagger-highlight {
|
|
22
|
+
display: none; pointer-events: none; z-index: 99998;
|
|
23
|
+
border: 2px dashed #6366f1; background: rgba(99,102,241,0.08);
|
|
24
|
+
border-radius: 4px; box-sizing: border-box;
|
|
25
|
+
transition: top 0.05s, left 0.05s, width 0.05s, height 0.05s;
|
|
26
|
+
}
|
|
27
|
+
.__li2-tagger-highlight--selected {
|
|
28
|
+
border-style: solid; border-color: #4f46e5;
|
|
29
|
+
background: rgba(79,70,229,0.12);
|
|
30
|
+
}
|
|
31
|
+
.__li2-tagger-tooltip {
|
|
32
|
+
display: none; pointer-events: none; z-index: 99998;
|
|
33
|
+
background: #1a1a2e; color: #e0e7ff; font-family: monospace;
|
|
34
|
+
font-size: 11px; padding: 3px 8px; border-radius: 4px;
|
|
35
|
+
white-space: nowrap; max-width: 400px; overflow: hidden;
|
|
36
|
+
text-overflow: ellipsis; box-shadow: 0 2px 8px rgba(0,0,0,0.3);
|
|
37
|
+
}
|
|
38
|
+
.__li2-tagger-panel {
|
|
39
|
+
position: fixed; bottom: 60px; right: 20px; z-index: 99999;
|
|
40
|
+
width: 380px; max-height: 520px; overflow-y: auto;
|
|
41
|
+
background: #1a1a2e; color: #e0e7ff; border-radius: 12px;
|
|
42
|
+
font-family: -apple-system, sans-serif; font-size: 13px;
|
|
43
|
+
box-shadow: 0 8px 32px rgba(0,0,0,0.4);
|
|
44
|
+
line-height: 1.4; box-sizing: border-box;
|
|
45
|
+
}
|
|
46
|
+
.__li2-tagger-panel * { box-sizing: border-box; margin: 0; padding: 0; }
|
|
47
|
+
.__li2-tagger-panel-header {
|
|
48
|
+
display: flex; justify-content: space-between; align-items: center;
|
|
49
|
+
padding: 12px 16px; border-bottom: 1px solid #2a2a4e;
|
|
50
|
+
font-weight: 600; font-size: 14px;
|
|
51
|
+
}
|
|
52
|
+
.__li2-tagger-panel-close {
|
|
53
|
+
background: none; border: none; color: #999; cursor: pointer;
|
|
54
|
+
font-size: 18px; padding: 2px 6px; border-radius: 4px;
|
|
55
|
+
}
|
|
56
|
+
.__li2-tagger-panel-close:hover { color: #fff; background: rgba(255,255,255,0.1); }
|
|
57
|
+
.__li2-tagger-summary {
|
|
58
|
+
padding: 8px 16px; color: #a5b4fc; font-size: 12px;
|
|
59
|
+
border-bottom: 1px solid #2a2a4e;
|
|
60
|
+
}
|
|
61
|
+
.__li2-tagger-field { padding: 10px 16px 4px; }
|
|
62
|
+
.__li2-tagger-label {
|
|
63
|
+
display: block; padding: 6px 16px 4px; color: #94a3b8;
|
|
64
|
+
font-size: 11px; text-transform: uppercase; letter-spacing: 0.5px;
|
|
65
|
+
}
|
|
66
|
+
.__li2-tagger-input {
|
|
67
|
+
width: 100%; padding: 8px 10px; border-radius: 6px;
|
|
68
|
+
border: 1px solid #3a3a5e; background: #0f0f23; color: #e0e7ff;
|
|
69
|
+
font-size: 13px; font-family: monospace; outline: none;
|
|
70
|
+
}
|
|
71
|
+
.__li2-tagger-input:focus { border-color: #6366f1; }
|
|
72
|
+
.__li2-tagger-input:disabled { opacity: 0.5; }
|
|
73
|
+
.__li2-tagger-field-error { color: #f87171; font-size: 11px; padding: 2px 0 0; min-height: 16px; }
|
|
74
|
+
.__li2-tagger-criterion {
|
|
75
|
+
display: flex; align-items: center; gap: 8px;
|
|
76
|
+
padding: 4px 16px; font-size: 12px;
|
|
77
|
+
}
|
|
78
|
+
.__li2-tagger-criterion input[type=checkbox] { accent-color: #6366f1; flex-shrink: 0; }
|
|
79
|
+
.__li2-tagger-criterion-label { color: #94a3b8; white-space: nowrap; }
|
|
80
|
+
.__li2-tagger-criterion-value {
|
|
81
|
+
color: #e0e7ff; overflow: hidden; text-overflow: ellipsis;
|
|
82
|
+
white-space: nowrap; font-family: monospace; font-size: 11px;
|
|
83
|
+
}
|
|
84
|
+
.__li2-tagger-panel-status {
|
|
85
|
+
padding: 4px 16px; font-size: 12px; min-height: 22px;
|
|
86
|
+
}
|
|
87
|
+
.__li2-tagger-status-loading { color: #fbbf24; }
|
|
88
|
+
.__li2-tagger-status-success { color: #4ade80; }
|
|
89
|
+
.__li2-tagger-status-error { color: #f87171; }
|
|
90
|
+
.__li2-tagger-btn-row {
|
|
91
|
+
display: flex; justify-content: flex-end; gap: 8px;
|
|
92
|
+
padding: 8px 16px 12px;
|
|
93
|
+
}
|
|
94
|
+
.__li2-tagger-btn {
|
|
95
|
+
padding: 7px 14px; border-radius: 6px; font-size: 13px;
|
|
96
|
+
cursor: pointer; border: none; font-weight: 500;
|
|
97
|
+
}
|
|
98
|
+
.__li2-tagger-btn-cancel { background: #2a2a4e; color: #e0e7ff; }
|
|
99
|
+
.__li2-tagger-btn-cancel:hover { background: #3a3a5e; }
|
|
100
|
+
.__li2-tagger-btn-submit { background: #6366f1; color: #fff; }
|
|
101
|
+
.__li2-tagger-btn-submit:hover { background: #4f46e5; }
|
|
102
|
+
.__li2-tagger-btn-submit:disabled { opacity: 0.5; cursor: not-allowed; }
|
|
103
|
+
.__li2-tagger-rules-header {
|
|
104
|
+
padding: 8px 16px 4px; color: #64748b; font-size: 11px;
|
|
105
|
+
text-transform: uppercase; letter-spacing: 0.5px;
|
|
106
|
+
border-top: 1px solid #2a2a4e; margin-top: 4px;
|
|
107
|
+
}
|
|
108
|
+
.__li2-tagger-rules-list {
|
|
109
|
+
padding: 0 16px 12px; max-height: 100px; overflow-y: auto;
|
|
110
|
+
}
|
|
111
|
+
.__li2-tagger-rules-empty { color: #64748b; font-size: 12px; padding: 4px 0; }
|
|
112
|
+
.__li2-tagger-rule-item { color: #94a3b8; font-size: 12px; padding: 2px 0; }
|
|
113
|
+
`,document.head.appendChild(i)}function Q(){let i=new Date;return i.setDate(i.getDate()-7),i.toISOString().slice(0,10)}function Z(){return new Date().toISOString().slice(0,10)}var y=class{constructor(e){this.heatmapOverlay=null;this.taggerOverlay=null;this.taggerMode=null;this.taggerPanel=null;this.ui=null;this.selectedElement=null;this.onElementSelected=null;this.apiUrl=e.apiUrl,this.publishableKey=e.publishableKey,this.mode=e.mode||"heatmap",this.sessionToken=e.sessionToken}async activate(){if(!this.sessionToken){L(),this.ui=new v({mode:this.mode,initialOpacity:.6,onOpacityChange:()=>{},onClose:()=>this.deactivate()}),this.ui.mount(),this.ui.setError("Session expired. Please reopen from the dashboard.");return}L(),this.mode==="tagger"?this.activateTagger():await this.activateHeatmap()}deactivate(){this.heatmapOverlay?.unmount(),this.heatmapOverlay=null,this.taggerMode?.deactivate(),this.taggerMode=null,this.taggerPanel?.unmount(),this.taggerPanel=null,this.taggerOverlay?.unmount(),this.taggerOverlay=null,this.ui?.unmount(),this.ui=null,this.selectedElement=null;let e=new URL(window.location.href);e.searchParams.delete("li2_heatmap"),e.searchParams.delete("li2_tagger"),e.searchParams.delete("li2_session"),e.searchParams.delete("li2_from"),e.searchParams.delete("li2_to"),e.searchParams.delete("li2_device"),history.replaceState(null,"",e.toString())}async activateHeatmap(){let e=this.parseHeatmapParams();e&&(this.heatmapOverlay=new b,this.heatmapOverlay.mount(),this.ui=new v({mode:"heatmap",initialOpacity:.6,onOpacityChange:t=>this.heatmapOverlay?.setOpacity(t),onClose:()=>this.deactivate()}),this.ui.mount(),await this.fetchAndRender(e))}parseHeatmapParams(){let e=new URL(window.location.href);return e.searchParams.has("li2_heatmap")?{from:e.searchParams.get("li2_from")??Q(),to:e.searchParams.get("li2_to")??Z(),deviceType:e.searchParams.get("li2_device")??void 0}:null}async fetchAndRender(e){this.ui?.setLoading(!0);try{let t=await k({apiUrl:this.apiUrl,publishableKey:this.publishableKey,sessionToken:this.sessionToken,pagePath:window.location.pathname,from:e.from,to:e.to,deviceType:e.deviceType,targetWidth:window.innerWidth});this.heatmapOverlay?.render(t.grid),this.ui?.setStats(t.total_clicks,t.grid.length)}catch{this.ui?.setError("Failed to load heatmap data")}finally{this.ui?.setLoading(!1)}}activateTagger(){this.taggerOverlay=new x,this.taggerOverlay.mount(),this.taggerPanel=new _({apiConfig:{apiUrl:this.apiUrl,publishableKey:this.publishableKey,sessionToken:this.sessionToken},onCancel:()=>{this.taggerOverlay?.clearHighlight(),this.taggerOverlay?.clearSelection(),this.selectedElement=null,this.ui?.setStatus("Click an element to tag")},onCreated:()=>{this.taggerOverlay?.clearHighlight(),this.taggerOverlay?.clearSelection(),this.selectedElement=null,this.ui?.setStatus("Click an element to tag")}}),this.taggerPanel.mount(),this.taggerMode=new E(this.taggerOverlay,{onElementSelected:(e,t)=>{this.selectedElement={element:e,info:t},this.ui?.setStatus("Element selected"),this.taggerPanel?.show(t),this.onElementSelected?.({element:e,info:t})}}),this.taggerMode.activate(),this.ui=new v({mode:"tagger",initialOpacity:.6,onOpacityChange:()=>{},onClose:()=>this.deactivate()}),this.ui.mount()}};if(typeof window<"u"&&window.__li2ToolbarConfig){let i=window.__li2ToolbarConfig;delete window.__li2ToolbarConfig;let e=new y(i);window.__li2Toolbar=e,e.activate()}return F(ee);})();
|
package/dist/toolbar/index.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
"use strict";var g=Object.defineProperty;var S=Object.getOwnPropertyDescriptor;var H=Object.getOwnPropertyNames;var L=Object.prototype.hasOwnProperty;var U=(a,t)=>{for(var e in t)g(a,e,{get:t[e],enumerable:!0})},R=(a,t,e,o)=>{if(t&&typeof t=="object"||typeof t=="function")for(let i of H(t))!L.call(a,i)&&i!==e&&g(a,i,{get:()=>t[i],enumerable:!(o=S(t,i))||o.enumerable});return a};var D=a=>R(g({},"__esModule",{value:!0}),a);var I={};U(I,{ToolbarManager:()=>f});module.exports=D(I);async function x(a){let t=new URL(`${a.apiUrl}/api/v1/track/heatmap/clicks`);t.searchParams.set("page_path",a.pagePath),t.searchParams.set("from",a.from),t.searchParams.set("to",a.to),t.searchParams.set("target_width",String(a.targetWidth)),a.deviceType&&t.searchParams.set("device_type",a.deviceType);let e=await fetch(t.toString(),{headers:{"X-Li2-Key":a.publishableKey}});if(!e.ok)throw new Error(`Heatmap API error: ${e.status}`);return(await e.json()).data.heatmap}var b=[[0,[0,0,255,128]],[.25,[0,255,255,200]],[.5,[0,255,0,220]],[.75,[255,255,0,240]],[1,[255,0,0,255]]];function _(a){if(a<=0)return[0,0,0,0];let t=Math.min(1,Math.max(0,a));for(let e=0;e<b.length-1;e++){let[o,i]=b[e],[d,l]=b[e+1];if(t>=o&&t<=d){let s=(t-o)/(d-o);return[Math.round(i[0]+(l[0]-i[0])*s),Math.round(i[1]+(l[1]-i[1])*s),Math.round(i[2]+(l[2]-i[2])*s),Math.round(i[3]+(l[3]-i[3])*s)]}}return[255,0,0,255]}var O=30;function C(a,t,e,o,i=O){let d=a.getContext("2d");if(!d||t.length===0||e===0||o===0)return;a.width=e,a.height=o;let l=Math.max(...t.map(n=>n.count));if(l===0)return;let s=document.createElement("canvas");s.width=e,s.height=o;let r=s.getContext("2d");if(!r)return;r.fillStyle="black",r.fillRect(0,0,e,o),r.globalCompositeOperation="lighter";for(let n of t){if(n.x<-i||n.x>e+i||n.y<-i||n.y>o+i)continue;let u=n.count/l,c=r.createRadialGradient(n.x,n.y,0,n.x,n.y,i);c.addColorStop(0,`rgba(255,255,255,${u})`),c.addColorStop(.33,`rgba(255,255,255,${u*.607})`),c.addColorStop(.67,`rgba(255,255,255,${u*.135})`),c.addColorStop(1,"rgba(255,255,255,0)"),r.fillStyle=c,r.beginPath(),r.arc(n.x,n.y,i,0,Math.PI*2),r.fill()}let v=r.getImageData(0,0,e,o).data,y=d.createImageData(e,o),p=y.data;for(let n=0;n<v.length;n+=4){let u=v[n]/255;if(u>.01){let[c,w,P,T]=_(u);p[n]=c,p[n+1]=w,p[n+2]=P,p[n+3]=T}}d.putImageData(y,0,0)}var h=class{constructor(){this.grid=[];this.handleResize=()=>{this.resize(),this.doRender()};this.canvas=document.createElement("canvas"),this.canvas.style.cssText="position:absolute;top:0;left:0;pointer-events:none;z-index:99998;"}mount(){document.body.appendChild(this.canvas),this.resize(),window.addEventListener("resize",this.handleResize)}unmount(){this.canvas.remove(),window.removeEventListener("resize",this.handleResize)}render(t){this.grid=t,this.doRender()}setOpacity(t){this.canvas.style.opacity=String(t)}resize(){let t=document.documentElement.scrollWidth,e=document.documentElement.scrollHeight;this.canvas.style.width=`${t}px`,this.canvas.style.height=`${e}px`}doRender(){if(this.grid.length===0)return;let t=document.documentElement.scrollWidth,e=document.documentElement.scrollHeight;C(this.canvas,this.grid,t,e)}};var m=class{constructor(t){this.root=null;this.statsEl=null;this.statusEl=null;this.config=t}mount(){this.root=document.createElement("div"),this.root.className="__li2-toolbar";let t=document.createElement("span");t.textContent="Li2 Heatmap",this.root.appendChild(t),this.root.appendChild(this.createSeparator()),this.statsEl=document.createElement("span"),this.statsEl.className="__li2-toolbar-stat",this.statsEl.textContent="...",this.root.appendChild(this.statsEl),this.root.appendChild(this.createSeparator()),this.statusEl=document.createElement("span"),this.root.appendChild(this.statusEl);let e=document.createElement("input");e.type="range",e.min="0",e.max="100",e.value=String(Math.round(this.config.initialOpacity*100)),e.className="__li2-toolbar-slider",e.addEventListener("input",()=>{this.config.onOpacityChange(Number(e.value)/100)}),this.root.appendChild(e);let o=document.createElement("button");o.className="__li2-toolbar-close",o.textContent="\xD7",o.title="Close heatmap",o.addEventListener("click",this.config.onClose),this.root.appendChild(o),document.body.appendChild(this.root)}unmount(){this.root?.remove(),this.root=null}setStats(t,e){this.statsEl&&(this.statsEl.textContent=`${t.toLocaleString()} clicks`)}setLoading(t){this.statusEl&&(t?(this.statusEl.className="__li2-toolbar-loading",this.statusEl.textContent="Loading..."):(this.statusEl.textContent="",this.statusEl.className=""))}setError(t){this.statusEl&&(this.statusEl.className="__li2-toolbar-error",this.statusEl.textContent=t)}createSeparator(){let t=document.createElement("span");return t.style.cssText="color:#555;user-select:none;",t.textContent="|",t}};function E(){if(document.getElementById("__li2-toolbar-styles"))return;let a=document.createElement("style");a.id="__li2-toolbar-styles",a.textContent=`
|
|
1
|
+
"use strict";var C=Object.defineProperty;var D=Object.getOwnPropertyDescriptor;var $=Object.getOwnPropertyNames;var A=Object.prototype.hasOwnProperty;var B=(i,e)=>{for(var t in e)C(i,t,{get:e[t],enumerable:!0})},U=(i,e,t,n)=>{if(e&&typeof e=="object"||typeof e=="function")for(let a of $(e))!A.call(i,a)&&a!==t&&C(i,a,{get:()=>e[a],enumerable:!(n=D(e,a))||n.enumerable});return i};var F=i=>U(C({},"__esModule",{value:!0}),i);var ee={};B(ee,{ToolbarManager:()=>y});module.exports=F(ee);async function k(i){let e=new URL(`${i.apiUrl}/api/v1/track/heatmap/clicks`);e.searchParams.set("page_path",i.pagePath),e.searchParams.set("from",i.from),e.searchParams.set("to",i.to),e.searchParams.set("target_width",String(i.targetWidth)),i.deviceType&&e.searchParams.set("device_type",i.deviceType);let t={"X-Li2-Key":i.publishableKey};i.sessionToken&&(t["X-Li2-Session"]=i.sessionToken);let n=await fetch(e.toString(),{headers:t});if(!n.ok)throw new Error(`Heatmap API error: ${n.status}`);return(await n.json()).data.heatmap}var w=[[0,[0,0,255,128]],[.25,[0,255,255,200]],[.5,[0,255,0,220]],[.75,[255,255,0,240]],[1,[255,0,0,255]]];function M(i){if(i<=0)return[0,0,0,0];let e=Math.min(1,Math.max(0,i));for(let t=0;t<w.length-1;t++){let[n,a]=w[t],[o,l]=w[t+1];if(e>=n&&e<=o){let s=(e-n)/(o-n);return[Math.round(a[0]+(l[0]-a[0])*s),Math.round(a[1]+(l[1]-a[1])*s),Math.round(a[2]+(l[2]-a[2])*s),Math.round(a[3]+(l[3]-a[3])*s)]}}return[255,0,0,255]}var G=30;function S(i,e,t,n,a=G){let o=i.getContext("2d");if(!o||e.length===0||t===0||n===0)return;i.width=t,i.height=n;let l=Math.max(...e.map(r=>r.count));if(l===0)return;let s=document.createElement("canvas");s.width=t,s.height=n;let c=s.getContext("2d");if(!c)return;c.fillStyle="black",c.fillRect(0,0,t,n),c.globalCompositeOperation="lighter";for(let r of e){if(r.x<-a||r.x>t+a||r.y<-a||r.y>n+a)continue;let u=r.count/l,d=c.createRadialGradient(r.x,r.y,0,r.x,r.y,a);d.addColorStop(0,`rgba(255,255,255,${u})`),d.addColorStop(.33,`rgba(255,255,255,${u*.607})`),d.addColorStop(.67,`rgba(255,255,255,${u*.135})`),d.addColorStop(1,"rgba(255,255,255,0)"),c.fillStyle=d,c.beginPath(),c.arc(r.x,r.y,a,0,Math.PI*2),c.fill()}let m=c.getImageData(0,0,t,n).data,p=o.createImageData(t,n),h=p.data;for(let r=0;r<m.length;r+=4){let u=m[r]/255;if(u>.01){let[d,R,O,z]=M(u);h[r]=d,h[r+1]=R,h[r+2]=O,h[r+3]=z}}o.putImageData(p,0,0)}var b=class{constructor(){this.grid=[];this.handleResize=()=>{this.resize(),this.doRender()};this.canvas=document.createElement("canvas"),this.canvas.style.cssText="position:absolute;top:0;left:0;pointer-events:none;z-index:99998;"}mount(){document.body.appendChild(this.canvas),this.resize(),window.addEventListener("resize",this.handleResize)}unmount(){this.canvas.remove(),window.removeEventListener("resize",this.handleResize)}render(e){this.grid=e,this.doRender()}setOpacity(e){this.canvas.style.opacity=String(e)}resize(){let e=document.documentElement.scrollWidth,t=document.documentElement.scrollHeight;this.canvas.style.width=`${e}px`,this.canvas.style.height=`${t}px`}doRender(){if(this.grid.length===0)return;let e=document.documentElement.scrollWidth,t=document.documentElement.scrollHeight;S(this.canvas,this.grid,e,t)}};var x=class{constructor(){this.highlight=null;this.tooltip=null;this.currentElement=null}mount(){this.highlight=document.createElement("div"),this.highlight.className="__li2-tagger-highlight",document.body.appendChild(this.highlight),this.tooltip=document.createElement("div"),this.tooltip.className="__li2-tagger-tooltip",document.body.appendChild(this.tooltip)}unmount(){this.highlight?.remove(),this.tooltip?.remove(),this.highlight=null,this.tooltip=null,this.currentElement=null}highlightElement(e){if(!this.highlight||!this.tooltip||e===this.currentElement)return;this.currentElement=e;let t=e.getBoundingClientRect(),n=window.getComputedStyle(e).position==="fixed",a=Math.max(t.width,20),o=Math.max(t.height,20);this.highlight.style.position=n?"fixed":"absolute",this.highlight.style.top=n?`${t.top}px`:`${t.top+window.scrollY}px`,this.highlight.style.left=n?`${t.left}px`:`${t.left+window.scrollX}px`,this.highlight.style.width=`${a}px`,this.highlight.style.height=`${o}px`,this.highlight.style.display="block";let l=e.tagName.toLowerCase(),s=(e.innerText||"").trim().slice(0,40),c=e.id?` #${e.id}`:"",g=s?` "${s}${s.length>=40?"...":""}"`:"";this.tooltip.textContent=`<${l}>${g}${c}`,this.tooltip.style.position=n?"fixed":"absolute";let m=n?t.top-28:t.top+window.scrollY-28;this.tooltip.style.top=`${Math.max(m,4)}px`,this.tooltip.style.left=n?`${t.left}px`:`${t.left+window.scrollX}px`,this.tooltip.style.display="block"}clearHighlight(){this.highlight&&(this.highlight.style.display="none"),this.tooltip&&(this.tooltip.style.display="none"),this.currentElement=null}fixSelection(e){this.highlightElement(e),this.highlight&&this.highlight.classList.add("__li2-tagger-highlight--selected")}clearSelection(){this.highlight&&this.highlight.classList.remove("__li2-tagger-highlight--selected")}updatePosition(){if(this.currentElement){let e=this.currentElement;this.currentElement=null,this.highlightElement(e)}}};var j=new Set(["a","button","input","select","textarea","form","label"]),K=new Set(["button","link","tab","menuitem"]);function T(i){let e=i;for(;e&&!(e instanceof HTMLElement);)e=e.parentElement;if(!e)return null;let n=W(e),a=X(n);return{tag:n.tagName.toLowerCase(),text:H(Y(n),256),href:V(n),className:H(n.className||"",512),id:n.id||null,selectorPath:q(n),isFixed:a}}function W(i){let e=i,t=0;for(;e&&t<5&&e.tagName!=="BODY";){let n=e.tagName.toLowerCase(),a=e.getAttribute("role");if(j.has(n)||a&&K.has(a))return e;e=e.parentElement,t++}return i}function X(i){let e=i;for(;e&&e!==document.body;){try{let n=window.getComputedStyle(e).getPropertyValue("position");if(n==="fixed"||n==="sticky")return!0}catch{break}e=e.parentElement}return!1}function q(i){let e=[],t=i,n=0;for(;t&&t!==document.body&&n<5;){let a=t.tagName.toLowerCase();t.id&&(a+=`#${t.id}`);let o=t.parentElement;if(o){let l=Array.from(o.children).filter(s=>s.tagName===t.tagName);if(l.length>1){let s=l.indexOf(t)+1;a+=`:nth-of-type(${s})`}}e.unshift(a),t=t.parentElement,n++}return e.join(" > ")}function Y(i){return i instanceof HTMLInputElement?i.value||i.placeholder||"":(i.innerText||i.textContent||"").trim()}function V(i){return i instanceof HTMLAnchorElement?i.href||null:i.getAttribute("href")||null}function H(i,e){return i.length<=e?i:i.slice(0,e)}var E=class{constructor(e,t){this.active=!1;this.overlay=e,this.callbacks=t,this.handleMouseMove=this.onMouseMove.bind(this),this.handleClick=this.onClick.bind(this),this.handleScroll=this.onScroll.bind(this)}activate(){this.active||(this.active=!0,document.addEventListener("mousemove",this.handleMouseMove,!0),document.addEventListener("click",this.handleClick,!0),window.addEventListener("scroll",this.handleScroll,!0))}deactivate(){this.active&&(this.active=!1,document.removeEventListener("mousemove",this.handleMouseMove,!0),document.removeEventListener("click",this.handleClick,!0),window.removeEventListener("scroll",this.handleScroll,!0),this.overlay.clearHighlight(),this.overlay.clearSelection())}onMouseMove(e){let t=e.target;if(!t)return;if(this.isToolbarElement(t)){this.overlay.clearHighlight();return}if(!T(t)){this.overlay.clearHighlight();return}let a=this.findMeaningfulDomElement(t);a&&this.overlay.highlightElement(a)}onClick(e){let t=e.target;if(!t||this.isToolbarElement(t))return;e.preventDefault(),e.stopPropagation();let n=T(t);if(!n)return;let a=this.findMeaningfulDomElement(t);a&&(this.overlay.fixSelection(a),this.callbacks.onElementSelected(a,n))}onScroll(){this.overlay.updatePosition()}isToolbarElement(e){let t=e;for(;t;){let n=t.className;if(typeof n=="string"&&(n.includes("__li2-toolbar")||n.includes("__li2-tagger")))return!0;t=t.parentElement}return!1}findMeaningfulDomElement(e){let t=new Set(["a","button","input","select","textarea","form","label"]),n=new Set(["button","link","tab","menuitem"]),a=e,o=0;for(;a&&o<5&&a.tagName!=="BODY";){let l=a.tagName.toLowerCase(),s=a.getAttribute("role");if(t.has(l)||s&&n.has(s))return a;a=a.parentElement,o++}return e}};var f=class extends Error{constructor(e,t){super(t),this.status=e}};function P(i){return{"X-Li2-Key":i.publishableKey,"X-Li2-Session":i.sessionToken}}async function N(i,e){let t=await fetch(`${i.apiUrl}/api/v1/track/event-rules`,{method:"POST",headers:{"Content-Type":"application/json",...P(i)},body:JSON.stringify(e)}),n=await t.json().catch(()=>({}));if(!t.ok){let a=n.error||n.message||`Error ${t.status}`;throw new f(t.status,a)}return n.data}async function I(i){let e=await fetch(`${i.apiUrl}/api/v1/track/event-rules`,{headers:P(i)});if(!e.ok)throw new f(e.status,"Failed to load existing rules");return(await e.json()).data||[]}var _=class{constructor(e){this.root=null;this.nameInput=null;this.nameError=null;this.submitBtn=null;this.statusEl=null;this.rulesListEl=null;this.criteriaCheckboxes=new Map;this.existingRules=[];this.currentInfo=null;this.state="idle";this.config=e}mount(){this.root=document.createElement("div"),this.root.className="__li2-tagger-panel",this.root.style.display="none",document.body.appendChild(this.root),this.fetchExistingRules()}unmount(){this.root?.remove(),this.root=null,this.criteriaCheckboxes.clear()}show(e){this.currentInfo=e,this.state="selected",this.buildPanelContent(e),this.root&&(this.root.style.display="block")}hide(){this.currentInfo=null,this.state="idle",this.root&&(this.root.style.display="none",this.root.innerHTML=""),this.criteriaCheckboxes.clear()}buildPanelContent(e){if(!this.root)return;this.root.innerHTML="",this.criteriaCheckboxes.clear();let t=document.createElement("div");t.className="__li2-tagger-panel-header";let n=document.createElement("span");n.textContent="Create Event Rule",t.appendChild(n);let a=document.createElement("button");a.className="__li2-tagger-panel-close",a.textContent="\xD7",a.addEventListener("click",()=>this.handleCancel()),t.appendChild(a),this.root.appendChild(t);let o=document.createElement("div");o.className="__li2-tagger-summary";let l=e.text?` "${e.text.slice(0,30)}${e.text.length>30?"...":""}"`:"";o.textContent=`Selected: <${e.tag}>${l} on ${window.location.pathname}`,this.root.appendChild(o);let s=document.createElement("div");s.className="__li2-tagger-field";let c=document.createElement("label");c.className="__li2-tagger-label",c.textContent="Event name",s.appendChild(c),this.nameInput=document.createElement("input"),this.nameInput.type="text",this.nameInput.placeholder="e.g. signup_click",this.nameInput.className="__li2-tagger-input",this.nameInput.addEventListener("input",()=>this.onNameInput()),s.appendChild(this.nameInput),this.nameError=document.createElement("div"),this.nameError.className="__li2-tagger-field-error",s.appendChild(this.nameError),this.root.appendChild(s);let g=document.createElement("div");g.className="__li2-tagger-label",g.textContent="Match criteria",this.root.appendChild(g);let m=[{key:"selector_path",label:"CSS Selector",value:e.selectorPath||null},{key:"element_text",label:"Text contains",value:e.text||null},{key:"element_id",label:"Element ID",value:e.id||null},{key:"element_href",label:"Link href",value:e.href||null},{key:"page_path",label:"Page path",value:window.location.pathname}];for(let u of m){let d=this.createCriterionRow(u);this.root.appendChild(d)}this.statusEl=document.createElement("div"),this.statusEl.className="__li2-tagger-panel-status",this.root.appendChild(this.statusEl);let p=document.createElement("div");p.className="__li2-tagger-btn-row";let h=document.createElement("button");h.className="__li2-tagger-btn __li2-tagger-btn-cancel",h.textContent="Cancel",h.addEventListener("click",()=>this.handleCancel()),p.appendChild(h),this.submitBtn=document.createElement("button"),this.submitBtn.className="__li2-tagger-btn __li2-tagger-btn-submit",this.submitBtn.textContent="Create Event Rule",this.submitBtn.addEventListener("click",()=>this.handleSubmit()),p.appendChild(this.submitBtn),this.root.appendChild(p);let r=document.createElement("div");r.className="__li2-tagger-rules-header",r.textContent="Existing rules",this.root.appendChild(r),this.rulesListEl=document.createElement("div"),this.rulesListEl.className="__li2-tagger-rules-list",this.renderRulesList(),this.root.appendChild(this.rulesListEl),setTimeout(()=>this.nameInput?.focus(),50)}createCriterionRow(e){let t=document.createElement("div");t.className="__li2-tagger-criterion";let n=document.createElement("input");n.type="checkbox",n.checked=!!e.value,n.disabled=!e.value,n.addEventListener("change",()=>this.updateSubmitState()),this.criteriaCheckboxes.set(e.key,n),t.appendChild(n);let a=document.createElement("span");a.className="__li2-tagger-criterion-label",a.textContent=e.label+":",t.appendChild(a);let o=document.createElement("span");return o.className="__li2-tagger-criterion-value",o.textContent=e.value?J(e.value,60):"(empty)",e.value||(o.style.color="#666"),t.appendChild(o),t}onNameInput(){if(!this.nameInput)return;let e=this.nameInput.value,t=e.toLowerCase().replace(/[^a-z0-9_]/g,"");t!==e&&(this.nameInput.value=t),this.validateName(),this.updateSubmitState()}validateName(){let e=this.nameInput?.value||"",t=null;return e?e.length>256?t="Max 256 characters":/^[a-z0-9_]+$/.test(e)?this.existingRules.some(n=>n.name===e)&&(t="Event name already exists"):t="Only lowercase letters, numbers, and underscores":t=null,this.nameError&&(this.nameError.textContent=t||""),t}updateSubmitState(){if(!this.submitBtn)return;let e=!!this.nameInput?.value&&!this.validateName(),t=this.getCheckedCriteria().length>0;this.submitBtn.disabled=!e||!t||this.state==="creating"}getCheckedCriteria(){let e=[];for(let[t,n]of this.criteriaCheckboxes)n.checked&&e.push(t);return e}async handleSubmit(){if(!this.nameInput||!this.currentInfo)return;let e=this.nameInput.value;if(!e||this.validateName())return;this.state="creating",this.setFormDisabled(!0),this.setStatus("Creating...","loading");let t=new Set(this.getCheckedCriteria()),n=this.currentInfo,a={name:e,selector_path:t.has("selector_path")&&n.selectorPath||void 0,element_text:t.has("element_text")&&n.text||void 0,element_id:t.has("element_id")&&n.id||void 0,element_href:t.has("element_href")&&n.href||void 0,page_path:t.has("page_path")?window.location.pathname:void 0,text_match_mode:t.has("element_text")?"contains":void 0},o={};for(let[l,s]of Object.entries(a))s!==void 0&&(o[l]=s);try{await N(this.config.apiConfig,o),this.state="success",this.setStatus(`Event rule '${e}' created!`,"success"),await this.fetchExistingRules(),setTimeout(()=>{this.hide(),this.config.onCreated(e)},2e3)}catch(l){this.state="error",this.setFormDisabled(!1),l instanceof f?this.setStatus(l.message,"error"):this.setStatus("Connection failed. Please try again.","error")}}handleCancel(){this.hide(),this.config.onCancel()}setFormDisabled(e){this.nameInput&&(this.nameInput.disabled=e),this.submitBtn&&(this.submitBtn.disabled=e,this.submitBtn.textContent=e?"Creating...":"Create Event Rule");for(let t of this.criteriaCheckboxes.values())(t.checked||!e)&&(t.disabled=e?!0:!t.checked)}setStatus(e,t){this.statusEl&&(this.statusEl.textContent=e,this.statusEl.className="__li2-tagger-panel-status",t==="loading"?this.statusEl.classList.add("__li2-tagger-status-loading"):t==="success"?this.statusEl.classList.add("__li2-tagger-status-success"):t==="error"&&this.statusEl.classList.add("__li2-tagger-status-error"))}async fetchExistingRules(){try{this.existingRules=await I(this.config.apiConfig),this.renderRulesList()}catch{}}renderRulesList(){if(this.rulesListEl){if(this.rulesListEl.innerHTML="",this.existingRules.length===0){let e=document.createElement("div");e.className="__li2-tagger-rules-empty",e.textContent="No rules yet",this.rulesListEl.appendChild(e);return}for(let e of this.existingRules){let t=document.createElement("div");t.className="__li2-tagger-rule-item",t.textContent=`\u2022 ${e.name}`,this.rulesListEl.appendChild(t)}}}};function J(i,e){return i.length>e?i.slice(0,e)+"...":i}var v=class{constructor(e){this.root=null;this.statsEl=null;this.statusEl=null;this.config=e}mount(){this.root=document.createElement("div"),this.root.className="__li2-toolbar",this.config.mode==="tagger"?this.mountTagger():this.mountHeatmap(),document.body.appendChild(this.root)}mountHeatmap(){if(!this.root)return;let e=document.createElement("span");e.textContent="Li2 Heatmap",this.root.appendChild(e),this.root.appendChild(this.createSeparator()),this.statsEl=document.createElement("span"),this.statsEl.className="__li2-toolbar-stat",this.statsEl.textContent="...",this.root.appendChild(this.statsEl),this.root.appendChild(this.createSeparator()),this.statusEl=document.createElement("span"),this.root.appendChild(this.statusEl);let t=document.createElement("input");t.type="range",t.min="0",t.max="100",t.value=String(Math.round(this.config.initialOpacity*100)),t.className="__li2-toolbar-slider",t.addEventListener("input",()=>{this.config.onOpacityChange(Number(t.value)/100)}),this.root.appendChild(t),this.appendCloseButton("Close heatmap")}mountTagger(){if(!this.root)return;let e=document.createElement("span");e.textContent="Li2 Event Tagger",this.root.appendChild(e),this.root.appendChild(this.createSeparator()),this.statusEl=document.createElement("span"),this.statusEl.className="__li2-toolbar-status",this.statusEl.textContent="Click an element to tag",this.root.appendChild(this.statusEl),this.appendCloseButton("Close tagger")}appendCloseButton(e){if(!this.root)return;let t=document.createElement("button");t.className="__li2-toolbar-close",t.textContent="\xD7",t.title=e,t.addEventListener("click",this.config.onClose),this.root.appendChild(t)}unmount(){this.root?.remove(),this.root=null}setStats(e,t){this.statsEl&&(this.statsEl.textContent=`${e.toLocaleString()} clicks`)}setLoading(e){this.statusEl&&(e?(this.statusEl.className="__li2-toolbar-loading",this.statusEl.textContent="Loading..."):(this.statusEl.textContent="",this.statusEl.className=""))}setStatus(e){this.statusEl&&(this.statusEl.className="__li2-toolbar-status",this.statusEl.textContent=e)}setError(e){this.statusEl&&(this.statusEl.className="__li2-toolbar-error",this.statusEl.textContent=e)}createSeparator(){let e=document.createElement("span");return e.style.cssText="color:#555;user-select:none;",e.textContent="|",e}};function L(){if(document.getElementById("__li2-toolbar-styles"))return;let i=document.createElement("style");i.id="__li2-toolbar-styles",i.textContent=`
|
|
2
2
|
.__li2-toolbar {
|
|
3
3
|
position: fixed; bottom: 20px; right: 20px; z-index: 99999;
|
|
4
4
|
background: #1a1a2e; color: #fff; border-radius: 12px;
|
|
@@ -17,4 +17,97 @@
|
|
|
17
17
|
.__li2-toolbar-stat { color: #a5b4fc; font-variant-numeric: tabular-nums; }
|
|
18
18
|
.__li2-toolbar-loading { color: #fbbf24; }
|
|
19
19
|
.__li2-toolbar-error { color: #f87171; }
|
|
20
|
-
|
|
20
|
+
.__li2-toolbar-status { color: #a5b4fc; }
|
|
21
|
+
.__li2-tagger-highlight {
|
|
22
|
+
display: none; pointer-events: none; z-index: 99998;
|
|
23
|
+
border: 2px dashed #6366f1; background: rgba(99,102,241,0.08);
|
|
24
|
+
border-radius: 4px; box-sizing: border-box;
|
|
25
|
+
transition: top 0.05s, left 0.05s, width 0.05s, height 0.05s;
|
|
26
|
+
}
|
|
27
|
+
.__li2-tagger-highlight--selected {
|
|
28
|
+
border-style: solid; border-color: #4f46e5;
|
|
29
|
+
background: rgba(79,70,229,0.12);
|
|
30
|
+
}
|
|
31
|
+
.__li2-tagger-tooltip {
|
|
32
|
+
display: none; pointer-events: none; z-index: 99998;
|
|
33
|
+
background: #1a1a2e; color: #e0e7ff; font-family: monospace;
|
|
34
|
+
font-size: 11px; padding: 3px 8px; border-radius: 4px;
|
|
35
|
+
white-space: nowrap; max-width: 400px; overflow: hidden;
|
|
36
|
+
text-overflow: ellipsis; box-shadow: 0 2px 8px rgba(0,0,0,0.3);
|
|
37
|
+
}
|
|
38
|
+
.__li2-tagger-panel {
|
|
39
|
+
position: fixed; bottom: 60px; right: 20px; z-index: 99999;
|
|
40
|
+
width: 380px; max-height: 520px; overflow-y: auto;
|
|
41
|
+
background: #1a1a2e; color: #e0e7ff; border-radius: 12px;
|
|
42
|
+
font-family: -apple-system, sans-serif; font-size: 13px;
|
|
43
|
+
box-shadow: 0 8px 32px rgba(0,0,0,0.4);
|
|
44
|
+
line-height: 1.4; box-sizing: border-box;
|
|
45
|
+
}
|
|
46
|
+
.__li2-tagger-panel * { box-sizing: border-box; margin: 0; padding: 0; }
|
|
47
|
+
.__li2-tagger-panel-header {
|
|
48
|
+
display: flex; justify-content: space-between; align-items: center;
|
|
49
|
+
padding: 12px 16px; border-bottom: 1px solid #2a2a4e;
|
|
50
|
+
font-weight: 600; font-size: 14px;
|
|
51
|
+
}
|
|
52
|
+
.__li2-tagger-panel-close {
|
|
53
|
+
background: none; border: none; color: #999; cursor: pointer;
|
|
54
|
+
font-size: 18px; padding: 2px 6px; border-radius: 4px;
|
|
55
|
+
}
|
|
56
|
+
.__li2-tagger-panel-close:hover { color: #fff; background: rgba(255,255,255,0.1); }
|
|
57
|
+
.__li2-tagger-summary {
|
|
58
|
+
padding: 8px 16px; color: #a5b4fc; font-size: 12px;
|
|
59
|
+
border-bottom: 1px solid #2a2a4e;
|
|
60
|
+
}
|
|
61
|
+
.__li2-tagger-field { padding: 10px 16px 4px; }
|
|
62
|
+
.__li2-tagger-label {
|
|
63
|
+
display: block; padding: 6px 16px 4px; color: #94a3b8;
|
|
64
|
+
font-size: 11px; text-transform: uppercase; letter-spacing: 0.5px;
|
|
65
|
+
}
|
|
66
|
+
.__li2-tagger-input {
|
|
67
|
+
width: 100%; padding: 8px 10px; border-radius: 6px;
|
|
68
|
+
border: 1px solid #3a3a5e; background: #0f0f23; color: #e0e7ff;
|
|
69
|
+
font-size: 13px; font-family: monospace; outline: none;
|
|
70
|
+
}
|
|
71
|
+
.__li2-tagger-input:focus { border-color: #6366f1; }
|
|
72
|
+
.__li2-tagger-input:disabled { opacity: 0.5; }
|
|
73
|
+
.__li2-tagger-field-error { color: #f87171; font-size: 11px; padding: 2px 0 0; min-height: 16px; }
|
|
74
|
+
.__li2-tagger-criterion {
|
|
75
|
+
display: flex; align-items: center; gap: 8px;
|
|
76
|
+
padding: 4px 16px; font-size: 12px;
|
|
77
|
+
}
|
|
78
|
+
.__li2-tagger-criterion input[type=checkbox] { accent-color: #6366f1; flex-shrink: 0; }
|
|
79
|
+
.__li2-tagger-criterion-label { color: #94a3b8; white-space: nowrap; }
|
|
80
|
+
.__li2-tagger-criterion-value {
|
|
81
|
+
color: #e0e7ff; overflow: hidden; text-overflow: ellipsis;
|
|
82
|
+
white-space: nowrap; font-family: monospace; font-size: 11px;
|
|
83
|
+
}
|
|
84
|
+
.__li2-tagger-panel-status {
|
|
85
|
+
padding: 4px 16px; font-size: 12px; min-height: 22px;
|
|
86
|
+
}
|
|
87
|
+
.__li2-tagger-status-loading { color: #fbbf24; }
|
|
88
|
+
.__li2-tagger-status-success { color: #4ade80; }
|
|
89
|
+
.__li2-tagger-status-error { color: #f87171; }
|
|
90
|
+
.__li2-tagger-btn-row {
|
|
91
|
+
display: flex; justify-content: flex-end; gap: 8px;
|
|
92
|
+
padding: 8px 16px 12px;
|
|
93
|
+
}
|
|
94
|
+
.__li2-tagger-btn {
|
|
95
|
+
padding: 7px 14px; border-radius: 6px; font-size: 13px;
|
|
96
|
+
cursor: pointer; border: none; font-weight: 500;
|
|
97
|
+
}
|
|
98
|
+
.__li2-tagger-btn-cancel { background: #2a2a4e; color: #e0e7ff; }
|
|
99
|
+
.__li2-tagger-btn-cancel:hover { background: #3a3a5e; }
|
|
100
|
+
.__li2-tagger-btn-submit { background: #6366f1; color: #fff; }
|
|
101
|
+
.__li2-tagger-btn-submit:hover { background: #4f46e5; }
|
|
102
|
+
.__li2-tagger-btn-submit:disabled { opacity: 0.5; cursor: not-allowed; }
|
|
103
|
+
.__li2-tagger-rules-header {
|
|
104
|
+
padding: 8px 16px 4px; color: #64748b; font-size: 11px;
|
|
105
|
+
text-transform: uppercase; letter-spacing: 0.5px;
|
|
106
|
+
border-top: 1px solid #2a2a4e; margin-top: 4px;
|
|
107
|
+
}
|
|
108
|
+
.__li2-tagger-rules-list {
|
|
109
|
+
padding: 0 16px 12px; max-height: 100px; overflow-y: auto;
|
|
110
|
+
}
|
|
111
|
+
.__li2-tagger-rules-empty { color: #64748b; font-size: 12px; padding: 4px 0; }
|
|
112
|
+
.__li2-tagger-rule-item { color: #94a3b8; font-size: 12px; padding: 2px 0; }
|
|
113
|
+
`,document.head.appendChild(i)}function Q(){let i=new Date;return i.setDate(i.getDate()-7),i.toISOString().slice(0,10)}function Z(){return new Date().toISOString().slice(0,10)}var y=class{constructor(e){this.heatmapOverlay=null;this.taggerOverlay=null;this.taggerMode=null;this.taggerPanel=null;this.ui=null;this.selectedElement=null;this.onElementSelected=null;this.apiUrl=e.apiUrl,this.publishableKey=e.publishableKey,this.mode=e.mode||"heatmap",this.sessionToken=e.sessionToken}async activate(){if(!this.sessionToken){L(),this.ui=new v({mode:this.mode,initialOpacity:.6,onOpacityChange:()=>{},onClose:()=>this.deactivate()}),this.ui.mount(),this.ui.setError("Session expired. Please reopen from the dashboard.");return}L(),this.mode==="tagger"?this.activateTagger():await this.activateHeatmap()}deactivate(){this.heatmapOverlay?.unmount(),this.heatmapOverlay=null,this.taggerMode?.deactivate(),this.taggerMode=null,this.taggerPanel?.unmount(),this.taggerPanel=null,this.taggerOverlay?.unmount(),this.taggerOverlay=null,this.ui?.unmount(),this.ui=null,this.selectedElement=null;let e=new URL(window.location.href);e.searchParams.delete("li2_heatmap"),e.searchParams.delete("li2_tagger"),e.searchParams.delete("li2_session"),e.searchParams.delete("li2_from"),e.searchParams.delete("li2_to"),e.searchParams.delete("li2_device"),history.replaceState(null,"",e.toString())}async activateHeatmap(){let e=this.parseHeatmapParams();e&&(this.heatmapOverlay=new b,this.heatmapOverlay.mount(),this.ui=new v({mode:"heatmap",initialOpacity:.6,onOpacityChange:t=>this.heatmapOverlay?.setOpacity(t),onClose:()=>this.deactivate()}),this.ui.mount(),await this.fetchAndRender(e))}parseHeatmapParams(){let e=new URL(window.location.href);return e.searchParams.has("li2_heatmap")?{from:e.searchParams.get("li2_from")??Q(),to:e.searchParams.get("li2_to")??Z(),deviceType:e.searchParams.get("li2_device")??void 0}:null}async fetchAndRender(e){this.ui?.setLoading(!0);try{let t=await k({apiUrl:this.apiUrl,publishableKey:this.publishableKey,sessionToken:this.sessionToken,pagePath:window.location.pathname,from:e.from,to:e.to,deviceType:e.deviceType,targetWidth:window.innerWidth});this.heatmapOverlay?.render(t.grid),this.ui?.setStats(t.total_clicks,t.grid.length)}catch{this.ui?.setError("Failed to load heatmap data")}finally{this.ui?.setLoading(!1)}}activateTagger(){this.taggerOverlay=new x,this.taggerOverlay.mount(),this.taggerPanel=new _({apiConfig:{apiUrl:this.apiUrl,publishableKey:this.publishableKey,sessionToken:this.sessionToken},onCancel:()=>{this.taggerOverlay?.clearHighlight(),this.taggerOverlay?.clearSelection(),this.selectedElement=null,this.ui?.setStatus("Click an element to tag")},onCreated:()=>{this.taggerOverlay?.clearHighlight(),this.taggerOverlay?.clearSelection(),this.selectedElement=null,this.ui?.setStatus("Click an element to tag")}}),this.taggerPanel.mount(),this.taggerMode=new E(this.taggerOverlay,{onElementSelected:(e,t)=>{this.selectedElement={element:e,info:t},this.ui?.setStatus("Element selected"),this.taggerPanel?.show(t),this.onElementSelected?.({element:e,info:t})}}),this.taggerMode.activate(),this.ui=new v({mode:"tagger",initialOpacity:.6,onOpacityChange:()=>{},onClose:()=>this.deactivate()}),this.ui.mount()}};if(typeof window<"u"&&window.__li2ToolbarConfig){let i=window.__li2ToolbarConfig;delete window.__li2ToolbarConfig;let e=new y(i);window.__li2Toolbar=e,e.activate()}0&&(module.exports={ToolbarManager});
|
package/dist/toolbar/index.mjs
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
async function y(a){let t=new URL(`${a.apiUrl}/api/v1/track/heatmap/clicks`);t.searchParams.set("page_path",a.pagePath),t.searchParams.set("from",a.from),t.searchParams.set("to",a.to),t.searchParams.set("target_width",String(a.targetWidth)),a.deviceType&&t.searchParams.set("device_type",a.deviceType);let e=await fetch(t.toString(),{headers:{"X-Li2-Key":a.publishableKey}});if(!e.ok)throw new Error(`Heatmap API error: ${e.status}`);return(await e.json()).data.heatmap}var f=[[0,[0,0,255,128]],[.25,[0,255,255,200]],[.5,[0,255,0,220]],[.75,[255,255,0,240]],[1,[255,0,0,255]]];function x(a){if(a<=0)return[0,0,0,0];let t=Math.min(1,Math.max(0,a));for(let e=0;e<f.length-1;e++){let[i,n]=f[e],[d,l]=f[e+1];if(t>=i&&t<=d){let s=(t-i)/(d-i);return[Math.round(n[0]+(l[0]-n[0])*s),Math.round(n[1]+(l[1]-n[1])*s),Math.round(n[2]+(l[2]-n[2])*s),Math.round(n[3]+(l[3]-n[3])*s)]}}return[255,0,0,255]}var T=30;function _(a,t,e,i,n=T){let d=a.getContext("2d");if(!d||t.length===0||e===0||i===0)return;a.width=e,a.height=i;let l=Math.max(...t.map(o=>o.count));if(l===0)return;let s=document.createElement("canvas");s.width=e,s.height=i;let r=s.getContext("2d");if(!r)return;r.fillStyle="black",r.fillRect(0,0,e,i),r.globalCompositeOperation="lighter";for(let o of t){if(o.x<-n||o.x>e+n||o.y<-n||o.y>i+n)continue;let u=o.count/l,c=r.createRadialGradient(o.x,o.y,0,o.x,o.y,n);c.addColorStop(0,`rgba(255,255,255,${u})`),c.addColorStop(.33,`rgba(255,255,255,${u*.607})`),c.addColorStop(.67,`rgba(255,255,255,${u*.135})`),c.addColorStop(1,"rgba(255,255,255,0)"),r.fillStyle=c,r.beginPath(),r.arc(o.x,o.y,n,0,Math.PI*2),r.fill()}let b=r.getImageData(0,0,e,i).data,v=d.createImageData(e,i),p=v.data;for(let o=0;o<b.length;o+=4){let u=b[o]/255;if(u>.01){let[c,E,w,P]=x(u);p[o]=c,p[o+1]=E,p[o+2]=w,p[o+3]=P}}d.putImageData(v,0,0)}var h=class{constructor(){this.grid=[];this.handleResize=()=>{this.resize(),this.doRender()};this.canvas=document.createElement("canvas"),this.canvas.style.cssText="position:absolute;top:0;left:0;pointer-events:none;z-index:99998;"}mount(){document.body.appendChild(this.canvas),this.resize(),window.addEventListener("resize",this.handleResize)}unmount(){this.canvas.remove(),window.removeEventListener("resize",this.handleResize)}render(t){this.grid=t,this.doRender()}setOpacity(t){this.canvas.style.opacity=String(t)}resize(){let t=document.documentElement.scrollWidth,e=document.documentElement.scrollHeight;this.canvas.style.width=`${t}px`,this.canvas.style.height=`${e}px`}doRender(){if(this.grid.length===0)return;let t=document.documentElement.scrollWidth,e=document.documentElement.scrollHeight;_(this.canvas,this.grid,t,e)}};var m=class{constructor(t){this.root=null;this.statsEl=null;this.statusEl=null;this.config=t}mount(){this.root=document.createElement("div"),this.root.className="__li2-toolbar";let t=document.createElement("span");t.textContent="Li2 Heatmap",this.root.appendChild(t),this.root.appendChild(this.createSeparator()),this.statsEl=document.createElement("span"),this.statsEl.className="__li2-toolbar-stat",this.statsEl.textContent="...",this.root.appendChild(this.statsEl),this.root.appendChild(this.createSeparator()),this.statusEl=document.createElement("span"),this.root.appendChild(this.statusEl);let e=document.createElement("input");e.type="range",e.min="0",e.max="100",e.value=String(Math.round(this.config.initialOpacity*100)),e.className="__li2-toolbar-slider",e.addEventListener("input",()=>{this.config.onOpacityChange(Number(e.value)/100)}),this.root.appendChild(e);let i=document.createElement("button");i.className="__li2-toolbar-close",i.textContent="\xD7",i.title="Close heatmap",i.addEventListener("click",this.config.onClose),this.root.appendChild(i),document.body.appendChild(this.root)}unmount(){this.root?.remove(),this.root=null}setStats(t,e){this.statsEl&&(this.statsEl.textContent=`${t.toLocaleString()} clicks`)}setLoading(t){this.statusEl&&(t?(this.statusEl.className="__li2-toolbar-loading",this.statusEl.textContent="Loading..."):(this.statusEl.textContent="",this.statusEl.className=""))}setError(t){this.statusEl&&(this.statusEl.className="__li2-toolbar-error",this.statusEl.textContent=t)}createSeparator(){let t=document.createElement("span");return t.style.cssText="color:#555;user-select:none;",t.textContent="|",t}};function C(){if(document.getElementById("__li2-toolbar-styles"))return;let a=document.createElement("style");a.id="__li2-toolbar-styles",a.textContent=`
|
|
1
|
+
import{a as y}from"../chunk-FF6VDEL5.mjs";async function k(n){let e=new URL(`${n.apiUrl}/api/v1/track/heatmap/clicks`);e.searchParams.set("page_path",n.pagePath),e.searchParams.set("from",n.from),e.searchParams.set("to",n.to),e.searchParams.set("target_width",String(n.targetWidth)),n.deviceType&&e.searchParams.set("device_type",n.deviceType);let t={"X-Li2-Key":n.publishableKey};n.sessionToken&&(t["X-Li2-Session"]=n.sessionToken);let i=await fetch(e.toString(),{headers:t});if(!i.ok)throw new Error(`Heatmap API error: ${i.status}`);return(await i.json()).data.heatmap}var C=[[0,[0,0,255,128]],[.25,[0,255,255,200]],[.5,[0,255,0,220]],[.75,[255,255,0,240]],[1,[255,0,0,255]]];function L(n){if(n<=0)return[0,0,0,0];let e=Math.min(1,Math.max(0,n));for(let t=0;t<C.length-1;t++){let[i,a]=C[t],[r,l]=C[t+1];if(e>=i&&e<=r){let o=(e-i)/(r-i);return[Math.round(a[0]+(l[0]-a[0])*o),Math.round(a[1]+(l[1]-a[1])*o),Math.round(a[2]+(l[2]-a[2])*o),Math.round(a[3]+(l[3]-a[3])*o)]}}return[255,0,0,255]}var O=30;function S(n,e,t,i,a=O){let r=n.getContext("2d");if(!r||e.length===0||t===0||i===0)return;n.width=t,n.height=i;let l=Math.max(...e.map(s=>s.count));if(l===0)return;let o=document.createElement("canvas");o.width=t,o.height=i;let c=o.getContext("2d");if(!c)return;c.fillStyle="black",c.fillRect(0,0,t,i),c.globalCompositeOperation="lighter";for(let s of e){if(s.x<-a||s.x>t+a||s.y<-a||s.y>i+a)continue;let u=s.count/l,d=c.createRadialGradient(s.x,s.y,0,s.x,s.y,a);d.addColorStop(0,`rgba(255,255,255,${u})`),d.addColorStop(.33,`rgba(255,255,255,${u*.607})`),d.addColorStop(.67,`rgba(255,255,255,${u*.135})`),d.addColorStop(1,"rgba(255,255,255,0)"),c.fillStyle=d,c.beginPath(),c.arc(s.x,s.y,a,0,Math.PI*2),c.fill()}let m=c.getImageData(0,0,t,i).data,p=r.createImageData(t,i),h=p.data;for(let s=0;s<m.length;s+=4){let u=m[s]/255;if(u>.01){let[d,R,I,N]=L(u);h[s]=d,h[s+1]=R,h[s+2]=I,h[s+3]=N}}r.putImageData(p,0,0)}var b=class{constructor(){this.grid=[];this.handleResize=()=>{this.resize(),this.doRender()};this.canvas=document.createElement("canvas"),this.canvas.style.cssText="position:absolute;top:0;left:0;pointer-events:none;z-index:99998;"}mount(){document.body.appendChild(this.canvas),this.resize(),window.addEventListener("resize",this.handleResize)}unmount(){this.canvas.remove(),window.removeEventListener("resize",this.handleResize)}render(e){this.grid=e,this.doRender()}setOpacity(e){this.canvas.style.opacity=String(e)}resize(){let e=document.documentElement.scrollWidth,t=document.documentElement.scrollHeight;this.canvas.style.width=`${e}px`,this.canvas.style.height=`${t}px`}doRender(){if(this.grid.length===0)return;let e=document.documentElement.scrollWidth,t=document.documentElement.scrollHeight;S(this.canvas,this.grid,e,t)}};var x=class{constructor(){this.highlight=null;this.tooltip=null;this.currentElement=null}mount(){this.highlight=document.createElement("div"),this.highlight.className="__li2-tagger-highlight",document.body.appendChild(this.highlight),this.tooltip=document.createElement("div"),this.tooltip.className="__li2-tagger-tooltip",document.body.appendChild(this.tooltip)}unmount(){this.highlight?.remove(),this.tooltip?.remove(),this.highlight=null,this.tooltip=null,this.currentElement=null}highlightElement(e){if(!this.highlight||!this.tooltip||e===this.currentElement)return;this.currentElement=e;let t=e.getBoundingClientRect(),i=window.getComputedStyle(e).position==="fixed",a=Math.max(t.width,20),r=Math.max(t.height,20);this.highlight.style.position=i?"fixed":"absolute",this.highlight.style.top=i?`${t.top}px`:`${t.top+window.scrollY}px`,this.highlight.style.left=i?`${t.left}px`:`${t.left+window.scrollX}px`,this.highlight.style.width=`${a}px`,this.highlight.style.height=`${r}px`,this.highlight.style.display="block";let l=e.tagName.toLowerCase(),o=(e.innerText||"").trim().slice(0,40),c=e.id?` #${e.id}`:"",g=o?` "${o}${o.length>=40?"...":""}"`:"";this.tooltip.textContent=`<${l}>${g}${c}`,this.tooltip.style.position=i?"fixed":"absolute";let m=i?t.top-28:t.top+window.scrollY-28;this.tooltip.style.top=`${Math.max(m,4)}px`,this.tooltip.style.left=i?`${t.left}px`:`${t.left+window.scrollX}px`,this.tooltip.style.display="block"}clearHighlight(){this.highlight&&(this.highlight.style.display="none"),this.tooltip&&(this.tooltip.style.display="none"),this.currentElement=null}fixSelection(e){this.highlightElement(e),this.highlight&&this.highlight.classList.add("__li2-tagger-highlight--selected")}clearSelection(){this.highlight&&this.highlight.classList.remove("__li2-tagger-highlight--selected")}updatePosition(){if(this.currentElement){let e=this.currentElement;this.currentElement=null,this.highlightElement(e)}}};var _=class{constructor(e,t){this.active=!1;this.overlay=e,this.callbacks=t,this.handleMouseMove=this.onMouseMove.bind(this),this.handleClick=this.onClick.bind(this),this.handleScroll=this.onScroll.bind(this)}activate(){this.active||(this.active=!0,document.addEventListener("mousemove",this.handleMouseMove,!0),document.addEventListener("click",this.handleClick,!0),window.addEventListener("scroll",this.handleScroll,!0))}deactivate(){this.active&&(this.active=!1,document.removeEventListener("mousemove",this.handleMouseMove,!0),document.removeEventListener("click",this.handleClick,!0),window.removeEventListener("scroll",this.handleScroll,!0),this.overlay.clearHighlight(),this.overlay.clearSelection())}onMouseMove(e){let t=e.target;if(!t)return;if(this.isToolbarElement(t)){this.overlay.clearHighlight();return}if(!y(t)){this.overlay.clearHighlight();return}let a=this.findMeaningfulDomElement(t);a&&this.overlay.highlightElement(a)}onClick(e){let t=e.target;if(!t||this.isToolbarElement(t))return;e.preventDefault(),e.stopPropagation();let i=y(t);if(!i)return;let a=this.findMeaningfulDomElement(t);a&&(this.overlay.fixSelection(a),this.callbacks.onElementSelected(a,i))}onScroll(){this.overlay.updatePosition()}isToolbarElement(e){let t=e;for(;t;){let i=t.className;if(typeof i=="string"&&(i.includes("__li2-toolbar")||i.includes("__li2-tagger")))return!0;t=t.parentElement}return!1}findMeaningfulDomElement(e){let t=new Set(["a","button","input","select","textarea","form","label"]),i=new Set(["button","link","tab","menuitem"]),a=e,r=0;for(;a&&r<5&&a.tagName!=="BODY";){let l=a.tagName.toLowerCase(),o=a.getAttribute("role");if(t.has(l)||o&&i.has(o))return a;a=a.parentElement,r++}return e}};var f=class extends Error{constructor(e,t){super(t),this.status=e}};function M(n){return{"X-Li2-Key":n.publishableKey,"X-Li2-Session":n.sessionToken}}async function P(n,e){let t=await fetch(`${n.apiUrl}/api/v1/track/event-rules`,{method:"POST",headers:{"Content-Type":"application/json",...M(n)},body:JSON.stringify(e)}),i=await t.json().catch(()=>({}));if(!t.ok){let a=i.error||i.message||`Error ${t.status}`;throw new f(t.status,a)}return i.data}async function H(n){let e=await fetch(`${n.apiUrl}/api/v1/track/event-rules`,{headers:M(n)});if(!e.ok)throw new f(e.status,"Failed to load existing rules");return(await e.json()).data||[]}var E=class{constructor(e){this.root=null;this.nameInput=null;this.nameError=null;this.submitBtn=null;this.statusEl=null;this.rulesListEl=null;this.criteriaCheckboxes=new Map;this.existingRules=[];this.currentInfo=null;this.state="idle";this.config=e}mount(){this.root=document.createElement("div"),this.root.className="__li2-tagger-panel",this.root.style.display="none",document.body.appendChild(this.root),this.fetchExistingRules()}unmount(){this.root?.remove(),this.root=null,this.criteriaCheckboxes.clear()}show(e){this.currentInfo=e,this.state="selected",this.buildPanelContent(e),this.root&&(this.root.style.display="block")}hide(){this.currentInfo=null,this.state="idle",this.root&&(this.root.style.display="none",this.root.innerHTML=""),this.criteriaCheckboxes.clear()}buildPanelContent(e){if(!this.root)return;this.root.innerHTML="",this.criteriaCheckboxes.clear();let t=document.createElement("div");t.className="__li2-tagger-panel-header";let i=document.createElement("span");i.textContent="Create Event Rule",t.appendChild(i);let a=document.createElement("button");a.className="__li2-tagger-panel-close",a.textContent="\xD7",a.addEventListener("click",()=>this.handleCancel()),t.appendChild(a),this.root.appendChild(t);let r=document.createElement("div");r.className="__li2-tagger-summary";let l=e.text?` "${e.text.slice(0,30)}${e.text.length>30?"...":""}"`:"";r.textContent=`Selected: <${e.tag}>${l} on ${window.location.pathname}`,this.root.appendChild(r);let o=document.createElement("div");o.className="__li2-tagger-field";let c=document.createElement("label");c.className="__li2-tagger-label",c.textContent="Event name",o.appendChild(c),this.nameInput=document.createElement("input"),this.nameInput.type="text",this.nameInput.placeholder="e.g. signup_click",this.nameInput.className="__li2-tagger-input",this.nameInput.addEventListener("input",()=>this.onNameInput()),o.appendChild(this.nameInput),this.nameError=document.createElement("div"),this.nameError.className="__li2-tagger-field-error",o.appendChild(this.nameError),this.root.appendChild(o);let g=document.createElement("div");g.className="__li2-tagger-label",g.textContent="Match criteria",this.root.appendChild(g);let m=[{key:"selector_path",label:"CSS Selector",value:e.selectorPath||null},{key:"element_text",label:"Text contains",value:e.text||null},{key:"element_id",label:"Element ID",value:e.id||null},{key:"element_href",label:"Link href",value:e.href||null},{key:"page_path",label:"Page path",value:window.location.pathname}];for(let u of m){let d=this.createCriterionRow(u);this.root.appendChild(d)}this.statusEl=document.createElement("div"),this.statusEl.className="__li2-tagger-panel-status",this.root.appendChild(this.statusEl);let p=document.createElement("div");p.className="__li2-tagger-btn-row";let h=document.createElement("button");h.className="__li2-tagger-btn __li2-tagger-btn-cancel",h.textContent="Cancel",h.addEventListener("click",()=>this.handleCancel()),p.appendChild(h),this.submitBtn=document.createElement("button"),this.submitBtn.className="__li2-tagger-btn __li2-tagger-btn-submit",this.submitBtn.textContent="Create Event Rule",this.submitBtn.addEventListener("click",()=>this.handleSubmit()),p.appendChild(this.submitBtn),this.root.appendChild(p);let s=document.createElement("div");s.className="__li2-tagger-rules-header",s.textContent="Existing rules",this.root.appendChild(s),this.rulesListEl=document.createElement("div"),this.rulesListEl.className="__li2-tagger-rules-list",this.renderRulesList(),this.root.appendChild(this.rulesListEl),setTimeout(()=>this.nameInput?.focus(),50)}createCriterionRow(e){let t=document.createElement("div");t.className="__li2-tagger-criterion";let i=document.createElement("input");i.type="checkbox",i.checked=!!e.value,i.disabled=!e.value,i.addEventListener("change",()=>this.updateSubmitState()),this.criteriaCheckboxes.set(e.key,i),t.appendChild(i);let a=document.createElement("span");a.className="__li2-tagger-criterion-label",a.textContent=e.label+":",t.appendChild(a);let r=document.createElement("span");return r.className="__li2-tagger-criterion-value",r.textContent=e.value?z(e.value,60):"(empty)",e.value||(r.style.color="#666"),t.appendChild(r),t}onNameInput(){if(!this.nameInput)return;let e=this.nameInput.value,t=e.toLowerCase().replace(/[^a-z0-9_]/g,"");t!==e&&(this.nameInput.value=t),this.validateName(),this.updateSubmitState()}validateName(){let e=this.nameInput?.value||"",t=null;return e?e.length>256?t="Max 256 characters":/^[a-z0-9_]+$/.test(e)?this.existingRules.some(i=>i.name===e)&&(t="Event name already exists"):t="Only lowercase letters, numbers, and underscores":t=null,this.nameError&&(this.nameError.textContent=t||""),t}updateSubmitState(){if(!this.submitBtn)return;let e=!!this.nameInput?.value&&!this.validateName(),t=this.getCheckedCriteria().length>0;this.submitBtn.disabled=!e||!t||this.state==="creating"}getCheckedCriteria(){let e=[];for(let[t,i]of this.criteriaCheckboxes)i.checked&&e.push(t);return e}async handleSubmit(){if(!this.nameInput||!this.currentInfo)return;let e=this.nameInput.value;if(!e||this.validateName())return;this.state="creating",this.setFormDisabled(!0),this.setStatus("Creating...","loading");let t=new Set(this.getCheckedCriteria()),i=this.currentInfo,a={name:e,selector_path:t.has("selector_path")&&i.selectorPath||void 0,element_text:t.has("element_text")&&i.text||void 0,element_id:t.has("element_id")&&i.id||void 0,element_href:t.has("element_href")&&i.href||void 0,page_path:t.has("page_path")?window.location.pathname:void 0,text_match_mode:t.has("element_text")?"contains":void 0},r={};for(let[l,o]of Object.entries(a))o!==void 0&&(r[l]=o);try{await P(this.config.apiConfig,r),this.state="success",this.setStatus(`Event rule '${e}' created!`,"success"),await this.fetchExistingRules(),setTimeout(()=>{this.hide(),this.config.onCreated(e)},2e3)}catch(l){this.state="error",this.setFormDisabled(!1),l instanceof f?this.setStatus(l.message,"error"):this.setStatus("Connection failed. Please try again.","error")}}handleCancel(){this.hide(),this.config.onCancel()}setFormDisabled(e){this.nameInput&&(this.nameInput.disabled=e),this.submitBtn&&(this.submitBtn.disabled=e,this.submitBtn.textContent=e?"Creating...":"Create Event Rule");for(let t of this.criteriaCheckboxes.values())(t.checked||!e)&&(t.disabled=e?!0:!t.checked)}setStatus(e,t){this.statusEl&&(this.statusEl.textContent=e,this.statusEl.className="__li2-tagger-panel-status",t==="loading"?this.statusEl.classList.add("__li2-tagger-status-loading"):t==="success"?this.statusEl.classList.add("__li2-tagger-status-success"):t==="error"&&this.statusEl.classList.add("__li2-tagger-status-error"))}async fetchExistingRules(){try{this.existingRules=await H(this.config.apiConfig),this.renderRulesList()}catch{}}renderRulesList(){if(this.rulesListEl){if(this.rulesListEl.innerHTML="",this.existingRules.length===0){let e=document.createElement("div");e.className="__li2-tagger-rules-empty",e.textContent="No rules yet",this.rulesListEl.appendChild(e);return}for(let e of this.existingRules){let t=document.createElement("div");t.className="__li2-tagger-rule-item",t.textContent=`\u2022 ${e.name}`,this.rulesListEl.appendChild(t)}}}};function z(n,e){return n.length>e?n.slice(0,e)+"...":n}var v=class{constructor(e){this.root=null;this.statsEl=null;this.statusEl=null;this.config=e}mount(){this.root=document.createElement("div"),this.root.className="__li2-toolbar",this.config.mode==="tagger"?this.mountTagger():this.mountHeatmap(),document.body.appendChild(this.root)}mountHeatmap(){if(!this.root)return;let e=document.createElement("span");e.textContent="Li2 Heatmap",this.root.appendChild(e),this.root.appendChild(this.createSeparator()),this.statsEl=document.createElement("span"),this.statsEl.className="__li2-toolbar-stat",this.statsEl.textContent="...",this.root.appendChild(this.statsEl),this.root.appendChild(this.createSeparator()),this.statusEl=document.createElement("span"),this.root.appendChild(this.statusEl);let t=document.createElement("input");t.type="range",t.min="0",t.max="100",t.value=String(Math.round(this.config.initialOpacity*100)),t.className="__li2-toolbar-slider",t.addEventListener("input",()=>{this.config.onOpacityChange(Number(t.value)/100)}),this.root.appendChild(t),this.appendCloseButton("Close heatmap")}mountTagger(){if(!this.root)return;let e=document.createElement("span");e.textContent="Li2 Event Tagger",this.root.appendChild(e),this.root.appendChild(this.createSeparator()),this.statusEl=document.createElement("span"),this.statusEl.className="__li2-toolbar-status",this.statusEl.textContent="Click an element to tag",this.root.appendChild(this.statusEl),this.appendCloseButton("Close tagger")}appendCloseButton(e){if(!this.root)return;let t=document.createElement("button");t.className="__li2-toolbar-close",t.textContent="\xD7",t.title=e,t.addEventListener("click",this.config.onClose),this.root.appendChild(t)}unmount(){this.root?.remove(),this.root=null}setStats(e,t){this.statsEl&&(this.statsEl.textContent=`${e.toLocaleString()} clicks`)}setLoading(e){this.statusEl&&(e?(this.statusEl.className="__li2-toolbar-loading",this.statusEl.textContent="Loading..."):(this.statusEl.textContent="",this.statusEl.className=""))}setStatus(e){this.statusEl&&(this.statusEl.className="__li2-toolbar-status",this.statusEl.textContent=e)}setError(e){this.statusEl&&(this.statusEl.className="__li2-toolbar-error",this.statusEl.textContent=e)}createSeparator(){let e=document.createElement("span");return e.style.cssText="color:#555;user-select:none;",e.textContent="|",e}};function w(){if(document.getElementById("__li2-toolbar-styles"))return;let n=document.createElement("style");n.id="__li2-toolbar-styles",n.textContent=`
|
|
2
2
|
.__li2-toolbar {
|
|
3
3
|
position: fixed; bottom: 20px; right: 20px; z-index: 99999;
|
|
4
4
|
background: #1a1a2e; color: #fff; border-radius: 12px;
|
|
@@ -17,4 +17,97 @@ async function y(a){let t=new URL(`${a.apiUrl}/api/v1/track/heatmap/clicks`);t.s
|
|
|
17
17
|
.__li2-toolbar-stat { color: #a5b4fc; font-variant-numeric: tabular-nums; }
|
|
18
18
|
.__li2-toolbar-loading { color: #fbbf24; }
|
|
19
19
|
.__li2-toolbar-error { color: #f87171; }
|
|
20
|
-
|
|
20
|
+
.__li2-toolbar-status { color: #a5b4fc; }
|
|
21
|
+
.__li2-tagger-highlight {
|
|
22
|
+
display: none; pointer-events: none; z-index: 99998;
|
|
23
|
+
border: 2px dashed #6366f1; background: rgba(99,102,241,0.08);
|
|
24
|
+
border-radius: 4px; box-sizing: border-box;
|
|
25
|
+
transition: top 0.05s, left 0.05s, width 0.05s, height 0.05s;
|
|
26
|
+
}
|
|
27
|
+
.__li2-tagger-highlight--selected {
|
|
28
|
+
border-style: solid; border-color: #4f46e5;
|
|
29
|
+
background: rgba(79,70,229,0.12);
|
|
30
|
+
}
|
|
31
|
+
.__li2-tagger-tooltip {
|
|
32
|
+
display: none; pointer-events: none; z-index: 99998;
|
|
33
|
+
background: #1a1a2e; color: #e0e7ff; font-family: monospace;
|
|
34
|
+
font-size: 11px; padding: 3px 8px; border-radius: 4px;
|
|
35
|
+
white-space: nowrap; max-width: 400px; overflow: hidden;
|
|
36
|
+
text-overflow: ellipsis; box-shadow: 0 2px 8px rgba(0,0,0,0.3);
|
|
37
|
+
}
|
|
38
|
+
.__li2-tagger-panel {
|
|
39
|
+
position: fixed; bottom: 60px; right: 20px; z-index: 99999;
|
|
40
|
+
width: 380px; max-height: 520px; overflow-y: auto;
|
|
41
|
+
background: #1a1a2e; color: #e0e7ff; border-radius: 12px;
|
|
42
|
+
font-family: -apple-system, sans-serif; font-size: 13px;
|
|
43
|
+
box-shadow: 0 8px 32px rgba(0,0,0,0.4);
|
|
44
|
+
line-height: 1.4; box-sizing: border-box;
|
|
45
|
+
}
|
|
46
|
+
.__li2-tagger-panel * { box-sizing: border-box; margin: 0; padding: 0; }
|
|
47
|
+
.__li2-tagger-panel-header {
|
|
48
|
+
display: flex; justify-content: space-between; align-items: center;
|
|
49
|
+
padding: 12px 16px; border-bottom: 1px solid #2a2a4e;
|
|
50
|
+
font-weight: 600; font-size: 14px;
|
|
51
|
+
}
|
|
52
|
+
.__li2-tagger-panel-close {
|
|
53
|
+
background: none; border: none; color: #999; cursor: pointer;
|
|
54
|
+
font-size: 18px; padding: 2px 6px; border-radius: 4px;
|
|
55
|
+
}
|
|
56
|
+
.__li2-tagger-panel-close:hover { color: #fff; background: rgba(255,255,255,0.1); }
|
|
57
|
+
.__li2-tagger-summary {
|
|
58
|
+
padding: 8px 16px; color: #a5b4fc; font-size: 12px;
|
|
59
|
+
border-bottom: 1px solid #2a2a4e;
|
|
60
|
+
}
|
|
61
|
+
.__li2-tagger-field { padding: 10px 16px 4px; }
|
|
62
|
+
.__li2-tagger-label {
|
|
63
|
+
display: block; padding: 6px 16px 4px; color: #94a3b8;
|
|
64
|
+
font-size: 11px; text-transform: uppercase; letter-spacing: 0.5px;
|
|
65
|
+
}
|
|
66
|
+
.__li2-tagger-input {
|
|
67
|
+
width: 100%; padding: 8px 10px; border-radius: 6px;
|
|
68
|
+
border: 1px solid #3a3a5e; background: #0f0f23; color: #e0e7ff;
|
|
69
|
+
font-size: 13px; font-family: monospace; outline: none;
|
|
70
|
+
}
|
|
71
|
+
.__li2-tagger-input:focus { border-color: #6366f1; }
|
|
72
|
+
.__li2-tagger-input:disabled { opacity: 0.5; }
|
|
73
|
+
.__li2-tagger-field-error { color: #f87171; font-size: 11px; padding: 2px 0 0; min-height: 16px; }
|
|
74
|
+
.__li2-tagger-criterion {
|
|
75
|
+
display: flex; align-items: center; gap: 8px;
|
|
76
|
+
padding: 4px 16px; font-size: 12px;
|
|
77
|
+
}
|
|
78
|
+
.__li2-tagger-criterion input[type=checkbox] { accent-color: #6366f1; flex-shrink: 0; }
|
|
79
|
+
.__li2-tagger-criterion-label { color: #94a3b8; white-space: nowrap; }
|
|
80
|
+
.__li2-tagger-criterion-value {
|
|
81
|
+
color: #e0e7ff; overflow: hidden; text-overflow: ellipsis;
|
|
82
|
+
white-space: nowrap; font-family: monospace; font-size: 11px;
|
|
83
|
+
}
|
|
84
|
+
.__li2-tagger-panel-status {
|
|
85
|
+
padding: 4px 16px; font-size: 12px; min-height: 22px;
|
|
86
|
+
}
|
|
87
|
+
.__li2-tagger-status-loading { color: #fbbf24; }
|
|
88
|
+
.__li2-tagger-status-success { color: #4ade80; }
|
|
89
|
+
.__li2-tagger-status-error { color: #f87171; }
|
|
90
|
+
.__li2-tagger-btn-row {
|
|
91
|
+
display: flex; justify-content: flex-end; gap: 8px;
|
|
92
|
+
padding: 8px 16px 12px;
|
|
93
|
+
}
|
|
94
|
+
.__li2-tagger-btn {
|
|
95
|
+
padding: 7px 14px; border-radius: 6px; font-size: 13px;
|
|
96
|
+
cursor: pointer; border: none; font-weight: 500;
|
|
97
|
+
}
|
|
98
|
+
.__li2-tagger-btn-cancel { background: #2a2a4e; color: #e0e7ff; }
|
|
99
|
+
.__li2-tagger-btn-cancel:hover { background: #3a3a5e; }
|
|
100
|
+
.__li2-tagger-btn-submit { background: #6366f1; color: #fff; }
|
|
101
|
+
.__li2-tagger-btn-submit:hover { background: #4f46e5; }
|
|
102
|
+
.__li2-tagger-btn-submit:disabled { opacity: 0.5; cursor: not-allowed; }
|
|
103
|
+
.__li2-tagger-rules-header {
|
|
104
|
+
padding: 8px 16px 4px; color: #64748b; font-size: 11px;
|
|
105
|
+
text-transform: uppercase; letter-spacing: 0.5px;
|
|
106
|
+
border-top: 1px solid #2a2a4e; margin-top: 4px;
|
|
107
|
+
}
|
|
108
|
+
.__li2-tagger-rules-list {
|
|
109
|
+
padding: 0 16px 12px; max-height: 100px; overflow-y: auto;
|
|
110
|
+
}
|
|
111
|
+
.__li2-tagger-rules-empty { color: #64748b; font-size: 12px; padding: 4px 0; }
|
|
112
|
+
.__li2-tagger-rule-item { color: #94a3b8; font-size: 12px; padding: 2px 0; }
|
|
113
|
+
`,document.head.appendChild(n)}function D(){let n=new Date;return n.setDate(n.getDate()-7),n.toISOString().slice(0,10)}function $(){return new Date().toISOString().slice(0,10)}var T=class{constructor(e){this.heatmapOverlay=null;this.taggerOverlay=null;this.taggerMode=null;this.taggerPanel=null;this.ui=null;this.selectedElement=null;this.onElementSelected=null;this.apiUrl=e.apiUrl,this.publishableKey=e.publishableKey,this.mode=e.mode||"heatmap",this.sessionToken=e.sessionToken}async activate(){if(!this.sessionToken){w(),this.ui=new v({mode:this.mode,initialOpacity:.6,onOpacityChange:()=>{},onClose:()=>this.deactivate()}),this.ui.mount(),this.ui.setError("Session expired. Please reopen from the dashboard.");return}w(),this.mode==="tagger"?this.activateTagger():await this.activateHeatmap()}deactivate(){this.heatmapOverlay?.unmount(),this.heatmapOverlay=null,this.taggerMode?.deactivate(),this.taggerMode=null,this.taggerPanel?.unmount(),this.taggerPanel=null,this.taggerOverlay?.unmount(),this.taggerOverlay=null,this.ui?.unmount(),this.ui=null,this.selectedElement=null;let e=new URL(window.location.href);e.searchParams.delete("li2_heatmap"),e.searchParams.delete("li2_tagger"),e.searchParams.delete("li2_session"),e.searchParams.delete("li2_from"),e.searchParams.delete("li2_to"),e.searchParams.delete("li2_device"),history.replaceState(null,"",e.toString())}async activateHeatmap(){let e=this.parseHeatmapParams();e&&(this.heatmapOverlay=new b,this.heatmapOverlay.mount(),this.ui=new v({mode:"heatmap",initialOpacity:.6,onOpacityChange:t=>this.heatmapOverlay?.setOpacity(t),onClose:()=>this.deactivate()}),this.ui.mount(),await this.fetchAndRender(e))}parseHeatmapParams(){let e=new URL(window.location.href);return e.searchParams.has("li2_heatmap")?{from:e.searchParams.get("li2_from")??D(),to:e.searchParams.get("li2_to")??$(),deviceType:e.searchParams.get("li2_device")??void 0}:null}async fetchAndRender(e){this.ui?.setLoading(!0);try{let t=await k({apiUrl:this.apiUrl,publishableKey:this.publishableKey,sessionToken:this.sessionToken,pagePath:window.location.pathname,from:e.from,to:e.to,deviceType:e.deviceType,targetWidth:window.innerWidth});this.heatmapOverlay?.render(t.grid),this.ui?.setStats(t.total_clicks,t.grid.length)}catch{this.ui?.setError("Failed to load heatmap data")}finally{this.ui?.setLoading(!1)}}activateTagger(){this.taggerOverlay=new x,this.taggerOverlay.mount(),this.taggerPanel=new E({apiConfig:{apiUrl:this.apiUrl,publishableKey:this.publishableKey,sessionToken:this.sessionToken},onCancel:()=>{this.taggerOverlay?.clearHighlight(),this.taggerOverlay?.clearSelection(),this.selectedElement=null,this.ui?.setStatus("Click an element to tag")},onCreated:()=>{this.taggerOverlay?.clearHighlight(),this.taggerOverlay?.clearSelection(),this.selectedElement=null,this.ui?.setStatus("Click an element to tag")}}),this.taggerPanel.mount(),this.taggerMode=new _(this.taggerOverlay,{onElementSelected:(e,t)=>{this.selectedElement={element:e,info:t},this.ui?.setStatus("Element selected"),this.taggerPanel?.show(t),this.onElementSelected?.({element:e,info:t})}}),this.taggerMode.activate(),this.ui=new v({mode:"tagger",initialOpacity:.6,onOpacityChange:()=>{},onClose:()=>this.deactivate()}),this.ui.mount()}};if(typeof window<"u"&&window.__li2ToolbarConfig){let n=window.__li2ToolbarConfig;delete window.__li2ToolbarConfig;let e=new T(n);window.__li2Toolbar=e,e.activate()}export{T as ToolbarManager};
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@li2/analytics",
|
|
3
|
-
"version": "0.3.
|
|
3
|
+
"version": "0.3.2",
|
|
4
4
|
"description": "Li2 Analytics SDK for conversion tracking",
|
|
5
5
|
"main": "dist/index.js",
|
|
6
6
|
"module": "dist/index.mjs",
|
|
@@ -30,17 +30,6 @@
|
|
|
30
30
|
"files": [
|
|
31
31
|
"dist"
|
|
32
32
|
],
|
|
33
|
-
"scripts": {
|
|
34
|
-
"build": "tsup src/index.ts src/outbound.ts src/auto-events.ts src/pageview/index.ts src/click-tracker/index.ts src/toolbar/index.ts --format cjs,esm,iife --dts --minify --global-name li2Analytics",
|
|
35
|
-
"build:obfuscate": "tsup src/index.ts src/outbound.ts src/auto-events.ts src/pageview/index.ts src/click-tracker/index.ts src/toolbar/index.ts --format cjs,esm,iife --dts --minify --global-name li2Analytics && node scripts/obfuscate.js",
|
|
36
|
-
"dev": "tsup src/index.ts src/outbound.ts src/auto-events.ts src/pageview/index.ts src/click-tracker/index.ts src/toolbar/index.ts --format cjs,esm,iife --dts --watch --global-name li2Analytics",
|
|
37
|
-
"demo": "pnpm run build && node demo/server.js",
|
|
38
|
-
"demo:serve": "node demo/server.js",
|
|
39
|
-
"test": "vitest run",
|
|
40
|
-
"test:watch": "vitest",
|
|
41
|
-
"test:coverage": "vitest run --coverage",
|
|
42
|
-
"prepublishOnly": "pnpm run build:obfuscate"
|
|
43
|
-
},
|
|
44
33
|
"keywords": [
|
|
45
34
|
"li2",
|
|
46
35
|
"analytics",
|
|
@@ -56,5 +45,15 @@
|
|
|
56
45
|
"tsup": "^8.0.0",
|
|
57
46
|
"typescript": "^5.0.0",
|
|
58
47
|
"vitest": "^4.0.18"
|
|
48
|
+
},
|
|
49
|
+
"scripts": {
|
|
50
|
+
"build": "tsup src/index.ts src/outbound.ts src/auto-events.ts src/pageview/index.ts src/click-tracker/index.ts src/toolbar/index.ts --format cjs,esm,iife --dts --minify --global-name li2Analytics",
|
|
51
|
+
"build:obfuscate": "tsup src/index.ts src/outbound.ts src/auto-events.ts src/pageview/index.ts src/click-tracker/index.ts src/toolbar/index.ts --format cjs,esm,iife --dts --minify --global-name li2Analytics && node scripts/obfuscate.js",
|
|
52
|
+
"dev": "tsup src/index.ts src/outbound.ts src/auto-events.ts src/pageview/index.ts src/click-tracker/index.ts src/toolbar/index.ts --format cjs,esm,iife --dts --watch --global-name li2Analytics",
|
|
53
|
+
"demo": "pnpm run build && node demo/server.js",
|
|
54
|
+
"demo:serve": "node demo/server.js",
|
|
55
|
+
"test": "vitest run",
|
|
56
|
+
"test:watch": "vitest",
|
|
57
|
+
"test:coverage": "vitest run --coverage"
|
|
59
58
|
}
|
|
60
|
-
}
|
|
59
|
+
}
|