@tacktext/widget 0.1.14 → 0.1.16
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/index.js +14 -13
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +15 -14
- package/dist/index.mjs.map +1 -1
- package/package.json +1 -1
package/dist/index.mjs
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
var w=class{constructor(e,t){this.authToken=null;this.onUnauthorized=null;this.baseUrl=e,this.projectId=t}setAuthToken(e){this.authToken=e}setOnUnauthorized(e){this.onUnauthorized=e}getHeaders(){let e={"Content-Type":"application/json"};return this.authToken&&(e.Authorization=`Bearer ${this.authToken}`),e}async handleResponse(e){return e.status===401&&this.onUnauthorized?.(),e}async getComments(){let e=await fetch(`${this.baseUrl}/projects/${this.projectId}/comments?path=${encodeURIComponent(window.location.pathname)}`,{headers:this.getHeaders()});if(await this.handleResponse(e),!e.ok)throw new Error("Failed to fetch comments");return e.json()}async createComment(e){let t=await fetch(`${this.baseUrl}/comments`,{method:"POST",headers:this.getHeaders(),body:JSON.stringify({project_id:this.projectId,...e})});if(await this.handleResponse(t),!t.ok)throw new Error("Failed to create comment");return t.json()}async updateComment(e,t){let i=await fetch(`${this.baseUrl}/comments/${e}`,{method:"PATCH",headers:this.getHeaders(),body:JSON.stringify(t)});if(await this.handleResponse(i),!i.ok)throw new Error("Failed to update comment");return i.json()}async deleteComment(e){let t=await fetch(`${this.baseUrl}/comments/${e}`,{method:"DELETE",headers:this.getHeaders()});if(await this.handleResponse(t),!t.ok)throw new Error("Failed to delete comment")}async addReaction(e,t){let i=await fetch(`${this.baseUrl}/comments/${e}/reactions`,{method:"POST",headers:this.getHeaders(),body:JSON.stringify({emoji:t})});if(await this.handleResponse(i),!i.ok)throw new Error("Failed to add reaction")}async removeReaction(e,t){let i=await fetch(`${this.baseUrl}/comments/${e}/reactions`,{method:"DELETE",headers:this.getHeaders(),body:JSON.stringify({emoji:t})});if(await this.handleResponse(i),!i.ok)throw new Error("Failed to remove reaction")}async uploadScreenshot(e){let t=await fetch(`${this.baseUrl}/upload`,{method:"POST",headers:this.getHeaders(),body:JSON.stringify({image:e,project_id:this.projectId})});if(await this.handleResponse(t),!t.ok)throw new Error("Failed to upload screenshot");let{url:i}=await t.json();return i}};var
|
|
1
|
+
var w=class{constructor(e,t){this.authToken=null;this.onUnauthorized=null;this.baseUrl=e,this.projectId=t}setAuthToken(e){this.authToken=e}setOnUnauthorized(e){this.onUnauthorized=e}getHeaders(){let e={"Content-Type":"application/json"};return this.authToken&&(e.Authorization=`Bearer ${this.authToken}`),e}async handleResponse(e){return e.status===401&&this.onUnauthorized?.(),e}async getComments(){let e=await fetch(`${this.baseUrl}/projects/${this.projectId}/comments?path=${encodeURIComponent(window.location.pathname)}`,{headers:this.getHeaders()});if(await this.handleResponse(e),!e.ok)throw new Error("Failed to fetch comments");return e.json()}async createComment(e){let t=await fetch(`${this.baseUrl}/comments`,{method:"POST",headers:this.getHeaders(),body:JSON.stringify({project_id:this.projectId,...e})});if(await this.handleResponse(t),!t.ok)throw new Error("Failed to create comment");return t.json()}async updateComment(e,t){let i=await fetch(`${this.baseUrl}/comments/${e}`,{method:"PATCH",headers:this.getHeaders(),body:JSON.stringify(t)});if(await this.handleResponse(i),!i.ok)throw new Error("Failed to update comment");return i.json()}async deleteComment(e){let t=await fetch(`${this.baseUrl}/comments/${e}`,{method:"DELETE",headers:this.getHeaders()});if(await this.handleResponse(t),!t.ok)throw new Error("Failed to delete comment")}async addReaction(e,t){let i=await fetch(`${this.baseUrl}/comments/${e}/reactions`,{method:"POST",headers:this.getHeaders(),body:JSON.stringify({emoji:t})});if(await this.handleResponse(i),!i.ok)throw new Error("Failed to add reaction")}async removeReaction(e,t){let i=await fetch(`${this.baseUrl}/comments/${e}/reactions`,{method:"DELETE",headers:this.getHeaders(),body:JSON.stringify({emoji:t})});if(await this.handleResponse(i),!i.ok)throw new Error("Failed to remove reaction")}async uploadScreenshot(e){let t=await fetch(`${this.baseUrl}/upload`,{method:"POST",headers:this.getHeaders(),body:JSON.stringify({image:e,project_id:this.projectId})});if(await this.handleResponse(t),!t.ok)throw new Error("Failed to upload screenshot");let{url:i}=await t.json();return i}};var C=class{constructor(e){this.sessionToken=null;this.user=null;this.onAuthChange=null;this.apiUrl=e}async init(){let e=localStorage.getItem("tack_session");if(e)try{let t=await fetch(`${this.apiUrl}/auth/widget-session`,{headers:{Authorization:`Bearer ${e}`}});if(!t.ok){localStorage.removeItem("tack_session");return}let{user:i}=await t.json();this.sessionToken=e,this.user={id:i.user_id,name:i.user_name,email:i.user_email,avatar_url:i.user_avatar_url},this.onAuthChange?.(this.user)}catch{localStorage.removeItem("tack_session")}}signIn(){return new Promise((e,t)=>{let i=this.apiUrl.replace(/\/api$/,""),n=window.open(`${i}/auth/widget`,"tack-auth","width=500,height=600,popup=yes");if(!n){t(new Error("Popup blocked"));return}let a=new URL(this.apiUrl).origin,r=o=>{if(o.data?.type!=="tack:auth"||o.origin!==a)return;window.removeEventListener("message",r),clearInterval(s);let{token:c,user:d}=o.data;this.sessionToken=c,this.user={id:d.user_id,name:d.user_name,email:d.user_email,avatar_url:d.user_avatar_url},localStorage.setItem("tack_session",c),this.onAuthChange?.(this.user),e(this.user)};window.addEventListener("message",r);let s=setInterval(()=>{n.closed&&(clearInterval(s),window.removeEventListener("message",r),this.user||t(new Error("Auth popup closed")))},500)})}signOut(){this.sessionToken&&fetch(`${this.apiUrl}/auth/widget-session`,{method:"DELETE",headers:{Authorization:`Bearer ${this.sessionToken}`}}).catch(()=>{}),this.sessionToken=null,this.user=null,localStorage.removeItem("tack_session"),this.onAuthChange?.(null)}getUser(){return this.user}getSessionToken(){return this.sessionToken}isAuthenticated(){return this.user!==null}setOnAuthChange(e){this.onAuthChange=e}};function q(){return`
|
|
2
2
|
* {
|
|
3
3
|
box-sizing: border-box;
|
|
4
4
|
}
|
|
@@ -1632,12 +1632,16 @@ var w=class{constructor(e,t){this.authToken=null;this.onUnauthorized=null;this.b
|
|
|
1632
1632
|
display: flex;
|
|
1633
1633
|
align-items: center;
|
|
1634
1634
|
gap: 0;
|
|
1635
|
-
background: #
|
|
1636
|
-
border-radius:
|
|
1635
|
+
background: #FFFFFF;
|
|
1636
|
+
border-radius: 10px;
|
|
1637
1637
|
padding: 2px;
|
|
1638
1638
|
opacity: 0;
|
|
1639
1639
|
pointer-events: none;
|
|
1640
1640
|
transition: opacity 120ms ease;
|
|
1641
|
+
box-shadow:
|
|
1642
|
+
0px 0px 0px 0.5px rgba(0, 0, 0, 0.03),
|
|
1643
|
+
0px 1px 2px 0px rgba(0, 0, 0, 0.06),
|
|
1644
|
+
0px 4px 8px -2px rgba(0, 0, 0, 0.04);
|
|
1641
1645
|
}
|
|
1642
1646
|
|
|
1643
1647
|
.tack-card-row:hover .tack-card-action-pill,
|
|
@@ -1663,21 +1667,18 @@ var w=class{constructor(e,t){this.authToken=null;this.onUnauthorized=null;this.b
|
|
|
1663
1667
|
}
|
|
1664
1668
|
|
|
1665
1669
|
.tack-card-action-pill-btn:hover {
|
|
1666
|
-
background: #
|
|
1670
|
+
background: #F4F4F5;
|
|
1667
1671
|
color: #18181b;
|
|
1668
1672
|
}
|
|
1669
1673
|
|
|
1670
1674
|
.tack-card-action-pill-divider {
|
|
1671
|
-
|
|
1672
|
-
height: 16px;
|
|
1673
|
-
background: #D4D4D8;
|
|
1674
|
-
flex-shrink: 0;
|
|
1675
|
+
display: none;
|
|
1675
1676
|
}
|
|
1676
1677
|
|
|
1677
1678
|
/* Dropdown menu */
|
|
1678
1679
|
.tack-card-dropdown {
|
|
1679
1680
|
position: absolute;
|
|
1680
|
-
top:
|
|
1681
|
+
top: 44px;
|
|
1681
1682
|
right: 8px;
|
|
1682
1683
|
background: white;
|
|
1683
1684
|
border: 1px solid #E4E4E7;
|
|
@@ -1767,7 +1768,7 @@ var w=class{constructor(e,t){this.authToken=null;this.onUnauthorized=null;this.b
|
|
|
1767
1768
|
padding: 4px;
|
|
1768
1769
|
box-shadow: 0 2px 8px rgba(0,0,0,0.1);
|
|
1769
1770
|
position: absolute;
|
|
1770
|
-
top:
|
|
1771
|
+
top: 44px;
|
|
1771
1772
|
right: 8px;
|
|
1772
1773
|
z-index: 10;
|
|
1773
1774
|
}
|
|
@@ -2215,7 +2216,7 @@ var w=class{constructor(e,t){this.authToken=null;this.onUnauthorized=null;this.b
|
|
|
2215
2216
|
transform: translateY(0);
|
|
2216
2217
|
}
|
|
2217
2218
|
}
|
|
2218
|
-
`}var
|
|
2219
|
+
`}var E=class{constructor(e,t){this.enabled=!1;this.highlightedElement=null;this.highlight=null;this.scrim=null;this.styleElement=null;this.settleTimer=null;this.pendingTarget=null;this.enabledAt=0;this.callback=e,this.onEscape=t,this.onMouseMove=this.onMouseMove.bind(this),this.onMouseDown=this.onMouseDown.bind(this),this.onClick=this.onClick.bind(this),this.onKeyDown=this.onKeyDown.bind(this)}enable(){this.enabled||(this.enabled=!0,this.enabledAt=Date.now(),document.addEventListener("mousemove",this.onMouseMove),document.addEventListener("mousedown",this.onMouseDown,!0),document.addEventListener("click",this.onClick,!0),document.addEventListener("keydown",this.onKeyDown),this.scrim=document.createElement("div"),this.scrim.style.cssText=`
|
|
2219
2220
|
position: fixed;
|
|
2220
2221
|
inset: 0;
|
|
2221
2222
|
background: rgba(0, 0, 0, 0.03);
|
|
@@ -2432,7 +2433,7 @@ var w=class{constructor(e,t){this.authToken=null;this.onUnauthorized=null;this.b
|
|
|
2432
2433
|
<div class="tack-comment-content">${this.escapeHtml(e.content)}</div>
|
|
2433
2434
|
</div>
|
|
2434
2435
|
</div>
|
|
2435
|
-
`}getFilteredComments(){let e=this.comments.filter(t=>!t.parent_id);if(this.filters.showResolved||(e=e.filter(t=>!t.resolved)),this.filters.onlyYourThreads&&this.currentUser){let t=this.currentUser.id,i=this.currentUser.name;e=e.filter(n=>!!(n.user_id===t||n.author_name===i||n.replies?.some(a=>a.user_id===t||a.author_name===i)))}if(this.filters.onlyCurrentPage){let t=this.getCurrentPagePath();e=e.filter(i=>i.page_path===t)}if(this.searchQuery){let t=this.searchQuery;e=e.filter(i=>!!(i.author_name.toLowerCase().includes(t)||i.content.toLowerCase().includes(t)||i.replies?.some(n=>n.content.toLowerCase().includes(t)||n.author_name.toLowerCase().includes(t))))}switch(this.filters.sort){case"unread":e.sort((t,i)=>{let n=this.isRead(t.id)?1:0,a=this.isRead(i.id)?1:0;return n!==a?n-a:new Date(i.created_at).getTime()-new Date(t.created_at).getTime()});break;case"replies":e.sort((t,i)=>{let n=t.replies?.length||0,a=i.replies?.length||0;return a!==n?a-n:new Date(i.created_at).getTime()-new Date(t.created_at).getTime()});break;default:e.sort((t,i)=>new Date(i.created_at).getTime()-new Date(t.created_at).getTime());break}return e}getFilteredCommentIds(){return this.getFilteredComments().map(e=>e.id)}highlightRow(e){let t=this.panel.querySelector(`.tack-comment-row[data-id="${e}"]`);t&&t.classList.add("pin-hover")}clearRowHighlight(e){let t=this.panel.querySelector(`.tack-comment-row[data-id="${e}"]`);t&&t.classList.remove("pin-hover")}scrollToComment(e){this.highlightedId=e,this.renderComments(),this.panel.querySelector(`[data-id="${e}"]`)?.scrollIntoView({behavior:"smooth",block:"nearest"}),setTimeout(()=>{this.highlightedId=null,this.renderComments()},2e3)}formatTimeAgo(e){let t=Math.floor((Date.now()-e.getTime())/1e3);return t<60?"just now":t<3600?`${Math.floor(t/60)}m ago`:t<86400?`${Math.floor(t/3600)}h ago`:t<604800?`${Math.floor(t/86400)}d ago`:e.toLocaleDateString()}escapeHtml(e){let t=document.createElement("div");return t.textContent=e,t.innerHTML}};var $=class{resolve(e){if(!e)return{element:null,confidence:"none",method:"none"};if(e.cssSelector){let t=this.tryCssSelector(e);if(t.element)return t}if(e.xpath){let t=this.tryXPath(e);if(t.element)return t}if(e.textQuote){let t=this.tryTextQuote(e.textQuote);if(t.element)return t}if(e.textQuote){let t=this.tryFuzzySearch(e.textQuote);if(t.element)return t}return{element:null,confidence:"none",method:"none"}}calculatePinPosition(e,t){let i=e.getBoundingClientRect(),n=i.left+t.relativeX*i.width+window.scrollX,a=i.top+t.relativeY*i.height+window.scrollY;return{x:n,y:a}}tryCssSelector(e){try{let t=document.querySelector(e.cssSelector);return t?e.contentHash?this.generateContentHash(t)===e.contentHash?{element:t,confidence:"high",method:"css"}:{element:t,confidence:"medium",method:"css"}:{element:t,confidence:"high",method:"css"}:{element:null,confidence:"none",method:"css"}}catch{return{element:null,confidence:"none",method:"css"}}}tryXPath(e){try{let i=document.evaluate(e.xpath,document.body,null,XPathResult.FIRST_ORDERED_NODE_TYPE,null).singleNodeValue;return i?e.contentHash?this.generateContentHash(i)===e.contentHash?{element:i,confidence:"high",method:"xpath"}:{element:i,confidence:"medium",method:"xpath"}:{element:i,confidence:"medium",method:"xpath"}:{element:null,confidence:"none",method:"xpath"}}catch{return{element:null,confidence:"none",method:"xpath"}}}tryTextQuote(e){let t=document.createTreeWalker(document.body,NodeFilter.SHOW_ELEMENT,null),i=t.nextNode();for(;i;){let n=i,a=n.textContent?.trim();if(a&&a.includes(e.exact)&&this.verifyContext(n,e))return{element:n,confidence:"high",method:"textQuote"};i=t.nextNode()}return{element:null,confidence:"none",method:"textQuote"}}tryFuzzySearch(e){let t=document.createTreeWalker(document.body,NodeFilter.SHOW_ELEMENT,null),i=null,n=e.exact.toLowerCase(),a=t.nextNode();for(;a;){let r=a,s=r.textContent?.trim().toLowerCase();if(s&&s.length<1e3){let o=this.similarityScore(s,n);o>.7&&(!i||o>i.score)&&(i={element:r,score:o})}a=t.nextNode()}return i?{element:i.element,confidence:i.score>.9?"medium":"low",method:"fuzzy"}:{element:null,confidence:"none",method:"fuzzy"}}verifyContext(e,t){if(!t.prefix&&!t.suffix)return!0;let i=e.parentElement;if(!i)return!0;let n=i.textContent||"",a=e.textContent||"",r=n.indexOf(a);if(r===-1)return!0;if(t.prefix&&!n.slice(Math.max(0,r-50),r).trim().includes(t.prefix.slice(-20)))return!1;if(t.suffix){let s=r+a.length;if(!n.slice(s,s+50).trim().includes(t.suffix.slice(0,20)))return!1}return!0}similarityScore(e,t){if(e===t)return 1;if(e.length<2||t.length<2)return 0;let i=new Set,n=new Set;for(let r=0;r<e.length-1;r++)i.add(e.slice(r,r+2));for(let r=0;r<t.length-1;r++)n.add(t.slice(r,r+2));let a=0;return i.forEach(r=>{n.has(r)&&a++}),2*a/(i.size+n.size)}generateContentHash(e){let t=e.textContent?.trim().slice(0,500)||"",i=e.tagName.toLowerCase(),n=e.className?.toString()||"",a=`${i}:${n}:${t}`,r=5381;for(let s=0;s<a.length;s++)r=(r<<5)+r+a.charCodeAt(s);return(r>>>0).toString(16)}};function ce(l){return l.map(e=>`${e.id}:${e.resolved}:${e.content}:${e.replies?.length||0}`).join("|")}var
|
|
2436
|
+
`}getFilteredComments(){let e=this.comments.filter(t=>!t.parent_id);if(this.filters.showResolved||(e=e.filter(t=>!t.resolved)),this.filters.onlyYourThreads&&this.currentUser){let t=this.currentUser.id,i=this.currentUser.name;e=e.filter(n=>!!(n.user_id===t||n.author_name===i||n.replies?.some(a=>a.user_id===t||a.author_name===i)))}if(this.filters.onlyCurrentPage){let t=this.getCurrentPagePath();e=e.filter(i=>i.page_path===t)}if(this.searchQuery){let t=this.searchQuery;e=e.filter(i=>!!(i.author_name.toLowerCase().includes(t)||i.content.toLowerCase().includes(t)||i.replies?.some(n=>n.content.toLowerCase().includes(t)||n.author_name.toLowerCase().includes(t))))}switch(this.filters.sort){case"unread":e.sort((t,i)=>{let n=this.isRead(t.id)?1:0,a=this.isRead(i.id)?1:0;return n!==a?n-a:new Date(i.created_at).getTime()-new Date(t.created_at).getTime()});break;case"replies":e.sort((t,i)=>{let n=t.replies?.length||0,a=i.replies?.length||0;return a!==n?a-n:new Date(i.created_at).getTime()-new Date(t.created_at).getTime()});break;default:e.sort((t,i)=>new Date(i.created_at).getTime()-new Date(t.created_at).getTime());break}return e}getFilteredCommentIds(){return this.getFilteredComments().map(e=>e.id)}highlightRow(e){let t=this.panel.querySelector(`.tack-comment-row[data-id="${e}"]`);t&&t.classList.add("pin-hover")}clearRowHighlight(e){let t=this.panel.querySelector(`.tack-comment-row[data-id="${e}"]`);t&&t.classList.remove("pin-hover")}scrollToComment(e){this.highlightedId=e,this.renderComments(),this.panel.querySelector(`[data-id="${e}"]`)?.scrollIntoView({behavior:"smooth",block:"nearest"}),setTimeout(()=>{this.highlightedId=null,this.renderComments()},2e3)}formatTimeAgo(e){let t=Math.floor((Date.now()-e.getTime())/1e3);return t<60?"just now":t<3600?`${Math.floor(t/60)}m ago`:t<86400?`${Math.floor(t/3600)}h ago`:t<604800?`${Math.floor(t/86400)}d ago`:e.toLocaleDateString()}escapeHtml(e){let t=document.createElement("div");return t.textContent=e,t.innerHTML}};var $=class{resolve(e){if(!e)return{element:null,confidence:"none",method:"none"};if(e.cssSelector){let t=this.tryCssSelector(e);if(t.element)return t}if(e.xpath){let t=this.tryXPath(e);if(t.element)return t}if(e.textQuote){let t=this.tryTextQuote(e.textQuote);if(t.element)return t}if(e.textQuote){let t=this.tryFuzzySearch(e.textQuote);if(t.element)return t}return{element:null,confidence:"none",method:"none"}}calculatePinPosition(e,t){let i=e.getBoundingClientRect(),n=i.left+t.relativeX*i.width+window.scrollX,a=i.top+t.relativeY*i.height+window.scrollY;return{x:n,y:a}}tryCssSelector(e){try{let t=document.querySelector(e.cssSelector);return t?e.contentHash?this.generateContentHash(t)===e.contentHash?{element:t,confidence:"high",method:"css"}:{element:t,confidence:"medium",method:"css"}:{element:t,confidence:"high",method:"css"}:{element:null,confidence:"none",method:"css"}}catch{return{element:null,confidence:"none",method:"css"}}}tryXPath(e){try{let i=document.evaluate(e.xpath,document.body,null,XPathResult.FIRST_ORDERED_NODE_TYPE,null).singleNodeValue;return i?e.contentHash?this.generateContentHash(i)===e.contentHash?{element:i,confidence:"high",method:"xpath"}:{element:i,confidence:"medium",method:"xpath"}:{element:i,confidence:"medium",method:"xpath"}:{element:null,confidence:"none",method:"xpath"}}catch{return{element:null,confidence:"none",method:"xpath"}}}tryTextQuote(e){let t=document.createTreeWalker(document.body,NodeFilter.SHOW_ELEMENT,null),i=t.nextNode();for(;i;){let n=i,a=n.textContent?.trim();if(a&&a.includes(e.exact)&&this.verifyContext(n,e))return{element:n,confidence:"high",method:"textQuote"};i=t.nextNode()}return{element:null,confidence:"none",method:"textQuote"}}tryFuzzySearch(e){let t=document.createTreeWalker(document.body,NodeFilter.SHOW_ELEMENT,null),i=null,n=e.exact.toLowerCase(),a=t.nextNode();for(;a;){let r=a,s=r.textContent?.trim().toLowerCase();if(s&&s.length<1e3){let o=this.similarityScore(s,n);o>.7&&(!i||o>i.score)&&(i={element:r,score:o})}a=t.nextNode()}return i?{element:i.element,confidence:i.score>.9?"medium":"low",method:"fuzzy"}:{element:null,confidence:"none",method:"fuzzy"}}verifyContext(e,t){if(!t.prefix&&!t.suffix)return!0;let i=e.parentElement;if(!i)return!0;let n=i.textContent||"",a=e.textContent||"",r=n.indexOf(a);if(r===-1)return!0;if(t.prefix&&!n.slice(Math.max(0,r-50),r).trim().includes(t.prefix.slice(-20)))return!1;if(t.suffix){let s=r+a.length;if(!n.slice(s,s+50).trim().includes(t.suffix.slice(0,20)))return!1}return!0}similarityScore(e,t){if(e===t)return 1;if(e.length<2||t.length<2)return 0;let i=new Set,n=new Set;for(let r=0;r<e.length-1;r++)i.add(e.slice(r,r+2));for(let r=0;r<t.length-1;r++)n.add(t.slice(r,r+2));let a=0;return i.forEach(r=>{n.has(r)&&a++}),2*a/(i.size+n.size)}generateContentHash(e){let t=e.textContent?.trim().slice(0,500)||"",i=e.tagName.toLowerCase(),n=e.className?.toString()||"",a=`${i}:${n}:${t}`,r=5381;for(let s=0;s<a.length;s++)r=(r<<5)+r+a.charCodeAt(s);return(r>>>0).toString(16)}};function ce(l){return l.map(e=>`${e.id}:${e.resolved}:${e.content}:${e.replies?.length||0}`).join("|")}var F=class{constructor(e,t){this.highlightedId=null;this.activeId=null;this.pins=new Map;this.resizeObserver=null;this.repositionRAF=null;this.hoverTimers=new Map;this.leaveTimers=new Map;this.currentlyExpanded=null;this.lastFingerprint="";this.loadingPin=null;this.onHover=null;this.onHoverEnd=null;this.container=e,this.onClick=t,this.anchoring=new $,this.boundScheduleReposition=this.scheduleReposition.bind(this),this.pinsContainer=document.createElement("div"),this.pinsContainer.className="tack-pins-container",this.container.appendChild(this.pinsContainer),this.setupResizeObserver(),window.addEventListener("scroll",this.boundScheduleReposition,{passive:!0}),window.addEventListener("resize",this.boundScheduleReposition,{passive:!0})}setupResizeObserver(){this.resizeObserver=new ResizeObserver(()=>{this.scheduleReposition()}),this.resizeObserver.observe(document.body)}scheduleReposition(){this.repositionRAF&&cancelAnimationFrame(this.repositionRAF),this.repositionRAF=requestAnimationFrame(()=>{this.repositionAllPins()})}repositionAllPins(){this.pins.forEach((e,t)=>{e.targetElement&&!document.contains(e.targetElement)&&(e.anchorResult=this.anchoring.resolve(e.comment.anchor),e.targetElement=e.anchorResult.element),this.positionPin(e)})}getCurrentPagePath(){return window.location.pathname}render(e){let t=this.getCurrentPagePath(),i=t+"::"+ce(e);if(i===this.lastFingerprint)return;this.lastFingerprint=i,this.removeLoadingPin(),this.hoverTimers.forEach(a=>clearTimeout(a)),this.hoverTimers.clear(),this.leaveTimers.forEach(a=>clearTimeout(a)),this.leaveTimers.clear(),this.currentlyExpanded=null,this.pinsContainer.innerHTML="",this.pins.clear(),e.filter(a=>!a.parent_id&&a.page_path===t).forEach(a=>{let r=this.createPin(a);r&&(this.pins.set(a.id,r),this.pinsContainer.appendChild(r.element))})}getUniqueAuthors(e){let t=new Set,i=[],n=e.user_id||e.author_name;if(t.add(n),i.push({name:e.author_name,avatar_url:e.author_avatar_url}),e.replies)for(let a of e.replies){let r=a.user_id||a.author_name;t.has(r)||(t.add(r),i.push({name:a.author_name,avatar_url:a.author_avatar_url}))}return i}renderInsetAvatar(e,t){let i=u(e.name),n=S(e.name),a=Math.round(t*.38);return e.avatar_url?`<img src="${e.avatar_url}" alt="${i}" referrerpolicy="no-referrer" crossorigin="anonymous" class="tack-pin-avatar-img" style="width:${t}px;height:${t}px;" onerror="this.outerHTML='<div class=\\'tack-pin-avatar-fallback\\' style=\\'width:${t}px;height:${t}px;background:${n};font-size:${a}px;\\'>${i}</div>'" />`:`<div class="tack-pin-avatar-fallback" style="width:${t}px;height:${t}px;background:${n};font-size:${a}px;">${i}</div>`}renderStackedAvatar(e,t){let i=u(e.name),n=S(e.name),a=Math.round(t*.38);return e.avatar_url?`<img src="${e.avatar_url}" alt="${i}" referrerpolicy="no-referrer" crossorigin="anonymous" class="tack-pin-avatar-img" style="width:${t}px;height:${t}px;" onerror="this.outerHTML='<div class=\\'tack-pin-avatar-fallback\\' style=\\'width:${t}px;height:${t}px;background:${n};font-size:${a}px;\\'>${i}</div>'" />`:`<div class="tack-pin-avatar-fallback" style="width:${t}px;height:${t}px;background:${n};font-size:${a}px;">${i}</div>`}createPin(e){let t={element:null,confidence:"none",method:"none"},i=null;e.anchor?(t=this.anchoring.resolve(e.anchor),i=t.element):e.element_selector&&(i=document.querySelector(e.element_selector),i&&(t={element:i,confidence:"medium",method:"css"}));let n=document.createElement("div"),a=e.id===this.activeId,r=e.id===this.highlightedId,s=this.getUniqueAuthors(e),o=s.length>1;n.className=`tack-pin${e.resolved?" resolved":""}${a?" active":""}${r?" highlighted":""}${o?" multi-author":""}`,n.dataset.id=e.id,t.confidence==="low"&&n.classList.add("low-confidence");let c=s[0],d=this.formatTimeAgo(new Date(e.created_at)),p=this.escapeHtml(e.content),h=e.replies?.length||0,b;if(o){let x=s.slice(0,3),_=s.length-3,m=`<div class="tack-pin-shell" style="--pin-w:${28+(x.length+(_>0?1:0)-1)*20+6}px"><div class="tack-pin-avatars">`;x.forEach((U,j)=>{m+=`<div class="tack-pin-avatar-stacked" style="z-index:${j+1}">${this.renderStackedAvatar(U,24)}</div>`}),_>0&&(m+=`<div class="tack-pin-avatar-stacked tack-pin-avatar-overflow" style="z-index:4">+${_}</div>`),m+="</div>";let y='<div class="tack-pin-preview-avatars">';s.slice(0,4).forEach((U,j)=>{y+=`<div class="tack-pin-avatar-stacked" style="z-index:${j+1}">${this.renderStackedAvatar(U,20)}</div>`}),s.length>4&&(y+=`<div class="tack-pin-avatar-stacked tack-pin-avatar-overflow" style="z-index:5;width:24px;height:24px;font-size:8px">+${s.length-4}</div>`),y+="</div>";let ae=`<div class="tack-pin-preview">
|
|
2436
2437
|
${y}
|
|
2437
2438
|
<div class="tack-pin-preview-meta" style="margin-bottom:4px">
|
|
2438
2439
|
<span class="tack-pin-preview-name">${this.escapeHtml(c.name)}</span>
|
|
@@ -2450,7 +2451,7 @@ var w=class{constructor(e,t){this.authToken=null;this.onUnauthorized=null;this.b
|
|
|
2450
2451
|
</div>
|
|
2451
2452
|
<p class="tack-pin-preview-text">${p}</p>
|
|
2452
2453
|
${h>0?`<span class="tack-pin-preview-replies">${h} ${h===1?"reply":"replies"}</span>`:""}
|
|
2453
|
-
</div>`;b=`<div class="tack-pin-shell">${this.renderInsetAvatar(k,32)}${x}</div>`}e.resolved&&(b+='<div class="tack-pin-check"></div>'),n.innerHTML=b,n.addEventListener("click",k=>{k.stopPropagation(),this.collapsePin(e.id,n),this.onClick(e.id,n)}),this.setupHoverListeners(n,e);let Y={comment:e,element:n,targetElement:i,anchorResult:t};return this.positionPin(Y),n.style.left===""&&n.style.top===""?null:Y}positionPin(e){let{comment:t,element:i,targetElement:n}=e,a=7,r=45;if(t.anchor&&n){let s=this.anchoring.calculatePinPosition(n,t.anchor);i.style.left=`${s.x-a}px`,i.style.top=`${s.y-r}px`;return}if(n){let s=n.getBoundingClientRect();i.style.left=`${s.left+window.scrollX-a}px`,i.style.top=`${s.top+window.scrollY-r}px`;return}if(t.anchor?.viewportRelativeX!=null&&t.anchor?.viewportRelativeY!=null){let s=t.anchor.viewportRelativeX*window.innerWidth+window.scrollX,o=t.anchor.viewportRelativeY*window.innerHeight+window.scrollY;i.style.left=`${s-a}px`,i.style.top=`${o-r}px`;return}if(t.x_percent!==null&&t.y_percent!==null){let s=t.x_percent/100*document.documentElement.scrollWidth,o=t.y_percent/100*document.documentElement.scrollHeight;i.style.left=`${s-a}px`,i.style.top=`${o-r}px`;return}i.style.display="none"}formatTimeAgo(e){let t=Math.floor((Date.now()-e.getTime())/1e3);return t<60?"just now":t<3600?`${Math.floor(t/60)}m ago`:t<86400?`${Math.floor(t/3600)}h ago`:t<604800?`${Math.floor(t/86400)}d ago`:e.toLocaleDateString()}escapeHtml(e){let t=document.createElement("div");return t.textContent=e,t.innerHTML}setupHoverListeners(e,t){e.addEventListener("mouseenter",()=>{let i=this.leaveTimers.get(t.id);i&&(clearTimeout(i),this.leaveTimers.delete(t.id));let n=window.setTimeout(()=>{this.expandPin(t.id,e),this.onHover?.(t.id),this.hoverTimers.delete(t.id)},150);this.hoverTimers.set(t.id,n)}),e.addEventListener("mouseleave",()=>{let i=this.hoverTimers.get(t.id);i&&(clearTimeout(i),this.hoverTimers.delete(t.id));let n=window.setTimeout(()=>{this.collapsePin(t.id,e),this.onHoverEnd?.(t.id),this.leaveTimers.delete(t.id)},120);this.leaveTimers.set(t.id,n)})}expandPin(e,t){if(t.classList.contains("active"))return;if(this.currentlyExpanded&&this.currentlyExpanded!==e){let n=this.pins.get(this.currentlyExpanded);n&&n.element.classList.remove("expanded","expand-left")}this.currentlyExpanded=e;let i=t.getBoundingClientRect();window.innerWidth-i.left<300?t.classList.add("expand-left"):t.classList.remove("expand-left"),t.classList.add("expanded")}collapsePin(e,t){t.classList.remove("expanded","expand-left"),this.currentlyExpanded===e&&(this.currentlyExpanded=null)}setActive(e){this.activeId=e,this.pins.forEach((t,i)=>{t.element.classList.toggle("active",i===e)})}highlight(e){this.highlightedId=e,this.pins.forEach((t,i)=>{t.element.classList.toggle("highlighted",i===e)}),setTimeout(()=>{this.highlightedId=null,this.pins.forEach(t=>{t.element.classList.remove("highlighted")})},2e3)}show(){this.pinsContainer.classList.add("visible")}hide(){this.pinsContainer.classList.remove("visible")}setHoverCallbacks(e,t){this.onHover=e,this.onHoverEnd=t}setHoverLinked(e){this.pins.forEach((t,i)=>{t.element.classList.toggle("hover-linked",i===e)})}beacon(e){let t=this.pins.get(e);t&&(t.element.classList.add("beacon"),setTimeout(()=>{t.element.classList.remove("beacon")},700))}getPinElement(e){return this.pins.get(e)?.element||null}showLoadingPin(e,t){this.removeLoadingPin();let i=document.createElement("div");i.className="tack-pin tack-pin-loading";let n=u(t.name),a=S(t.name),r;t.avatar_url?r=`<img src="${t.avatar_url}" alt="${n}" referrerpolicy="no-referrer" crossorigin="anonymous" class="tack-pin-avatar-img" style="width:32px;height:32px;" />`:r=`<div class="tack-pin-avatar-fallback" style="width:32px;height:32px;background:${a};font-size:12px;">${n}</div>`,i.innerHTML=`<div class="tack-pin-shell">${r}<svg class="tack-pin-loading-ring" viewBox="0 0 36 36"><circle cx="18" cy="18" r="16" /></svg></div>`;let s=this.anchoring.resolve(e),o=7,c=45;if(s.element){let d=this.anchoring.calculatePinPosition(s.element,e);i.style.left=`${d.x-o}px`,i.style.top=`${d.y-c}px`}else if(e.relativeX!==void 0&&e.relativeY!==void 0){let d=e.relativeX*document.documentElement.scrollWidth,p=e.relativeY*document.documentElement.scrollHeight;i.style.left=`${d-o}px`,i.style.top=`${p-c}px`}this.loadingPin=i,this.pinsContainer.appendChild(i)}resolveLoadingPin(){if(!this.loadingPin)return;let e=this.loadingPin;e.classList.remove("tack-pin-loading"),e.classList.add("tack-pin-settle"),e.querySelector(".tack-pin-loading-ring")?.remove();let i=e.querySelector(".tack-pin-avatar-img, .tack-pin-avatar-fallback");i&&(i.style.opacity="1",i.style.filter="none"),setTimeout(()=>{e.classList.remove("tack-pin-settle")},350)}failLoadingPin(e){if(!this.loadingPin)return;let t=this.loadingPin;t.classList.remove("tack-pin-loading"),t.classList.add("tack-pin-failed");let i=document.createElement("div");i.className="tack-pin-failed-tooltip",i.textContent="Failed to save. Click to retry.",t.appendChild(i),t.addEventListener("click",n=>{n.stopPropagation(),this.removeLoadingPin(),e()})}removeLoadingPin(){this.loadingPin&&(this.loadingPin.remove(),this.loadingPin=null)}destroy(){this.hoverTimers.forEach(e=>clearTimeout(e)),this.leaveTimers.forEach(e=>clearTimeout(e)),this.resizeObserver&&this.resizeObserver.disconnect(),this.repositionRAF&&cancelAnimationFrame(this.repositionRAF),window.removeEventListener("scroll",this.boundScheduleReposition),window.removeEventListener("resize",this.boundScheduleReposition)}};var
|
|
2454
|
+
</div>`;b=`<div class="tack-pin-shell">${this.renderInsetAvatar(k,32)}${x}</div>`}e.resolved&&(b+='<div class="tack-pin-check"></div>'),n.innerHTML=b,n.addEventListener("click",k=>{k.stopPropagation(),this.collapsePin(e.id,n),this.onClick(e.id,n)}),this.setupHoverListeners(n,e);let Y={comment:e,element:n,targetElement:i,anchorResult:t};return this.positionPin(Y),n.style.left===""&&n.style.top===""?null:Y}positionPin(e){let{comment:t,element:i,targetElement:n}=e,a=7,r=45;if(t.anchor&&n){let s=this.anchoring.calculatePinPosition(n,t.anchor);i.style.left=`${s.x-a}px`,i.style.top=`${s.y-r}px`;return}if(n){let s=n.getBoundingClientRect();i.style.left=`${s.left+window.scrollX-a}px`,i.style.top=`${s.top+window.scrollY-r}px`;return}if(t.anchor?.viewportRelativeX!=null&&t.anchor?.viewportRelativeY!=null){let s=t.anchor.viewportRelativeX*window.innerWidth+window.scrollX,o=t.anchor.viewportRelativeY*window.innerHeight+window.scrollY;i.style.left=`${s-a}px`,i.style.top=`${o-r}px`;return}if(t.x_percent!==null&&t.y_percent!==null){let s=t.x_percent/100*document.documentElement.scrollWidth,o=t.y_percent/100*document.documentElement.scrollHeight;i.style.left=`${s-a}px`,i.style.top=`${o-r}px`;return}i.style.display="none"}formatTimeAgo(e){let t=Math.floor((Date.now()-e.getTime())/1e3);return t<60?"just now":t<3600?`${Math.floor(t/60)}m ago`:t<86400?`${Math.floor(t/3600)}h ago`:t<604800?`${Math.floor(t/86400)}d ago`:e.toLocaleDateString()}escapeHtml(e){let t=document.createElement("div");return t.textContent=e,t.innerHTML}setupHoverListeners(e,t){e.addEventListener("mouseenter",()=>{let i=this.leaveTimers.get(t.id);i&&(clearTimeout(i),this.leaveTimers.delete(t.id));let n=window.setTimeout(()=>{this.expandPin(t.id,e),this.onHover?.(t.id),this.hoverTimers.delete(t.id)},150);this.hoverTimers.set(t.id,n)}),e.addEventListener("mouseleave",()=>{let i=this.hoverTimers.get(t.id);i&&(clearTimeout(i),this.hoverTimers.delete(t.id));let n=window.setTimeout(()=>{this.collapsePin(t.id,e),this.onHoverEnd?.(t.id),this.leaveTimers.delete(t.id)},120);this.leaveTimers.set(t.id,n)})}expandPin(e,t){if(t.classList.contains("active"))return;if(this.currentlyExpanded&&this.currentlyExpanded!==e){let n=this.pins.get(this.currentlyExpanded);n&&n.element.classList.remove("expanded","expand-left")}this.currentlyExpanded=e;let i=t.getBoundingClientRect();window.innerWidth-i.left<300?t.classList.add("expand-left"):t.classList.remove("expand-left"),t.classList.add("expanded")}collapsePin(e,t){t.classList.remove("expanded","expand-left"),this.currentlyExpanded===e&&(this.currentlyExpanded=null)}setActive(e){this.activeId=e,this.pins.forEach((t,i)=>{t.element.classList.toggle("active",i===e)})}highlight(e){this.highlightedId=e,this.pins.forEach((t,i)=>{t.element.classList.toggle("highlighted",i===e)}),setTimeout(()=>{this.highlightedId=null,this.pins.forEach(t=>{t.element.classList.remove("highlighted")})},2e3)}show(){this.pinsContainer.classList.add("visible")}hide(){this.pinsContainer.classList.remove("visible")}setHoverCallbacks(e,t){this.onHover=e,this.onHoverEnd=t}setHoverLinked(e){this.pins.forEach((t,i)=>{t.element.classList.toggle("hover-linked",i===e)})}beacon(e){let t=this.pins.get(e);t&&(t.element.classList.add("beacon"),setTimeout(()=>{t.element.classList.remove("beacon")},700))}getPinElement(e){return this.pins.get(e)?.element||null}showLoadingPin(e,t){this.removeLoadingPin();let i=document.createElement("div");i.className="tack-pin tack-pin-loading";let n=u(t.name),a=S(t.name),r;t.avatar_url?r=`<img src="${t.avatar_url}" alt="${n}" referrerpolicy="no-referrer" crossorigin="anonymous" class="tack-pin-avatar-img" style="width:32px;height:32px;" />`:r=`<div class="tack-pin-avatar-fallback" style="width:32px;height:32px;background:${a};font-size:12px;">${n}</div>`,i.innerHTML=`<div class="tack-pin-shell">${r}<svg class="tack-pin-loading-ring" viewBox="0 0 36 36"><circle cx="18" cy="18" r="16" /></svg></div>`;let s=this.anchoring.resolve(e),o=7,c=45;if(s.element){let d=this.anchoring.calculatePinPosition(s.element,e);i.style.left=`${d.x-o}px`,i.style.top=`${d.y-c}px`}else if(e.relativeX!==void 0&&e.relativeY!==void 0){let d=e.relativeX*document.documentElement.scrollWidth,p=e.relativeY*document.documentElement.scrollHeight;i.style.left=`${d-o}px`,i.style.top=`${p-c}px`}this.loadingPin=i,this.pinsContainer.appendChild(i)}resolveLoadingPin(){if(!this.loadingPin)return;let e=this.loadingPin;e.classList.remove("tack-pin-loading"),e.classList.add("tack-pin-settle"),e.querySelector(".tack-pin-loading-ring")?.remove();let i=e.querySelector(".tack-pin-avatar-img, .tack-pin-avatar-fallback");i&&(i.style.opacity="1",i.style.filter="none"),setTimeout(()=>{e.classList.remove("tack-pin-settle")},350)}failLoadingPin(e){if(!this.loadingPin)return;let t=this.loadingPin;t.classList.remove("tack-pin-loading"),t.classList.add("tack-pin-failed");let i=document.createElement("div");i.className="tack-pin-failed-tooltip",i.textContent="Failed to save. Click to retry.",t.appendChild(i),t.addEventListener("click",n=>{n.stopPropagation(),this.removeLoadingPin(),e()})}removeLoadingPin(){this.loadingPin&&(this.loadingPin.remove(),this.loadingPin=null)}destroy(){this.hoverTimers.forEach(e=>clearTimeout(e)),this.leaveTimers.forEach(e=>clearTimeout(e)),this.resizeObserver&&this.resizeObserver.disconnect(),this.repositionRAF&&cancelAnimationFrame(this.repositionRAF),window.removeEventListener("scroll",this.boundScheduleReposition),window.removeEventListener("resize",this.boundScheduleReposition)}};var A=class{constructor(e,t){this.currentComment=null;this.currentUser=null;this.visible=!1;this.editing=!1;this.activeDropdownId=null;this.activePickerId=null;this.container=e,this.callbacks=t,this.card=document.createElement("div"),this.card.className="tack-card",this.card.setAttribute("role","dialog"),this.card.setAttribute("aria-label","Comment details"),this.container.appendChild(this.card),this.card.addEventListener("mousedown",i=>i.stopPropagation()),this.card.addEventListener("click",i=>i.stopPropagation()),this.boundOnMouseDown=this.onDocumentMouseDown.bind(this),this.boundOnKeyDown=this.onKeyDown.bind(this)}setUser(e){this.currentUser=e}show(e,t){if(this.visible&&this.currentComment?.id===e.id){this.hide();return}this.currentComment=e,this.visible=!0,this.editing=!1,this.activeDropdownId=null,this.activePickerId=null,this.renderCard(e),this.positionNear(t),this.card.classList.add("visible"),this.attachListeners(),document.addEventListener("mousedown",this.boundOnMouseDown,!0),document.addEventListener("keydown",this.boundOnKeyDown)}hide(){this.visible&&(this.visible=!1,this.currentComment=null,this.editing=!1,this.activeDropdownId=null,this.activePickerId=null,this.card.classList.remove("visible"),document.removeEventListener("mousedown",this.boundOnMouseDown,!0),document.removeEventListener("keydown",this.boundOnKeyDown),this.callbacks.onClose())}isVisible(){return this.visible}updateComment(e){!this.visible||this.currentComment?.id!==e.id||(this.currentComment=e,this.renderCard(e),this.attachListeners())}onDocumentMouseDown(e){this.card.contains(e.target)||e.composedPath().includes(this.card)||this.hide()}onKeyDown(e){if(e.key==="Escape"){if(this.activeDropdownId){this.activeDropdownId=null,this.renderCard(this.currentComment),this.attachListeners();return}if(this.activePickerId){this.activePickerId=null,this.renderCard(this.currentComment),this.attachListeners();return}if(this.editing){this.editing=!1,this.renderCard(this.currentComment),this.attachListeners();return}e.preventDefault(),this.hide()}}positionNear(e){let t=parseFloat(e.style.left)||0,i=parseFloat(e.style.top)||0,n=44,a=44,r=t-window.scrollX,s=i-window.scrollY,o=320,c=8,d=r+n+c;d+o>window.innerWidth-16&&(d=r-o-c),d=Math.max(16,d);let p=s,h=300;p+h>window.innerHeight-16&&(p=window.innerHeight-16-h),p=Math.max(16,p),this.card.style.left=`${d}px`,this.card.style.top=`${p}px`}isOwnComment(e){return this.currentUser?.id&&e.user_id?this.currentUser.id===e.user_id:(localStorage.getItem("tack_author_name")||"")===e.author_name}renderCard(e){let t=e.replies||[],i=localStorage.getItem("tack_author_name")||"Anonymous",n=`
|
|
2454
2455
|
<div class="tack-card-title-bar">
|
|
2455
2456
|
<span class="tack-card-title">Comment</span>
|
|
2456
2457
|
<div class="tack-card-title-actions">
|
|
@@ -2520,7 +2521,7 @@ var w=class{constructor(e,t){this.authToken=null;this.onUnauthorized=null;this.b
|
|
|
2520
2521
|
z-index: 10003;
|
|
2521
2522
|
pointer-events: none;
|
|
2522
2523
|
transition: left 150ms ease, right 150ms ease, opacity 150ms ease;
|
|
2523
|
-
`,document.body.appendChild(this.snapHint)),t==="left"?(this.snapHint.style.left="0px",this.snapHint.style.right="auto"):(this.snapHint.style.left="auto",this.snapHint.style.right="0px"),this.snapHint.style.opacity="1"}removeSnapHint(){if(this.snapHint){this.snapHint.style.opacity="0";let e=this.snapHint;this.snapHint=null,setTimeout(()=>{e.parentNode&&e.parentNode.removeChild(e)},150)}}expand(){this.expanded||(this.expanded=!0,this.el.classList.add("tack-fab--expanded"),this.badge.classList.remove("visible"))}collapse(){this.expanded&&(this.expanded=!1,this.el.classList.remove("tack-fab--expanded"),setTimeout(()=>{!this.expanded&&parseInt(this.badge.textContent||"0",10)>0&&this.badge.classList.add("visible")},200))}isExpanded(){return this.expanded}getEdge(){return this.position.edge}setPanelToggleActive(e){this.panelToggleBtn.classList.toggle("tack-fab-btn--active",e)}setBadgeCount(e){this.badge.textContent=e>99?"99+":String(e),!this.expanded&&e>0?this.badge.classList.add("visible"):this.badge.classList.remove("visible")}destroy(){this.cleanupDragListeners(),v(this.dragOverlay),this.removeSnapHint(),document.body.style.userSelect="",this.boundOnResize&&(window.removeEventListener("resize",this.boundOnResize),this.boundOnResize=null),this.el.remove()}};var O=class{constructor(e){this.container=null;this.shadowRoot=null;this.selector=null;this.form=null;this.panel=null;this.pins=null;this.card=null;this.realtime=null;this.presence=null;this.fab=null;this.state="idle";this.comments=[];this.currentVersion=null;this.currentPagePath="";this.originalPushState=null;this.originalReplaceState=null;this.pollingInterval=null;this.boundOnUrlChange=null;this.boundOnKeyDown=null;this.navigationIndex=-1;this.pendingRetryData=null;this.config={apiUrl:"https://tacktext.vercel.app/api",supabaseUrl:"https://etpavqvnpupqdxdptkhc.supabase.co",supabaseKey:"eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJzdXBhYmFzZSIsInJlZiI6ImV0cGF2cXZucHVwcWR4ZHB0a2hjIiwicm9sZSI6ImFub24iLCJpYXQiOjE3NzQ4MzU4MzgsImV4cCI6MjA5MDQxMTgzOH0.GMSIuPmMaEkNhss_laSm_NchihN_KF9VyyEh5YH4Ru0",...e},this.api=new w(this.config.apiUrl,this.config.projectId),this.auth=new E(this.config.apiUrl)}async mount(){this.container=document.createElement("div"),this.container.id="tack-widget",this.shadowRoot=this.container.attachShadow({mode:"open"});let e=document.createElement("style");e.textContent=q(),this.shadowRoot.appendChild(e),this.injectPageStyles();let t=document.createElement("div");if(t.className="tack-wrapper",this.shadowRoot.appendChild(t),this.auth.setOnAuthChange(i=>{this.api.setAuthToken(i?this.auth.getSessionToken():null),this.form?.setUser(i),this.card?.setUser(i),this.panel?.setUser(i),i?this.joinPresence(i):(this.presence?.leave(),this.presence=null)}),await this.auth.init(),this.auth.isAuthenticated()&&this.api.setAuthToken(this.auth.getSessionToken()),this.api.setOnUnauthorized(()=>{this.auth.signOut(),this.showToast("Session expired. Please sign in again.")}),this.selector=new C(this.onElementSelected.bind(this),()=>this.transitionTo("idle")),this.form=new T(t,this.onCommentSubmit.bind(this)),this.form.setUser(this.auth.getUser()),this.form.setOnHide(()=>{this.state==="active"&&setTimeout(()=>{this.state==="active"&&this.selector?.enable()},100)}),this.form.setOnSignIn(()=>this.signIn()),this.panel=new R(t,{onCommentClick:this.onCommentClick.bind(this),onResolve:this.onResolve.bind(this),onReply:this.onReply.bind(this),onClose:()=>this.transitionTo("active"),onAddComment:()=>this.transitionTo("active"),onShare:this.onShare.bind(this),onRowHover:i=>{this.pins?.setHoverLinked(i)},onRowHoverEnd:()=>{this.pins?.setHoverLinked(null)},onSideChange:()=>{this.state==="active-panel"&&(this.fab&&this.panel?.setFabOffset(this.fab.getEdge()),this.setPanelOpen(!0))}}),this.card=new F(t,{onResolve:this.onResolve.bind(this),onReply:this.onReply.bind(this),onEdit:this.onEdit.bind(this),onDelete:this.onDelete.bind(this),onReaction:this.onReaction.bind(this),onClose:this.onCardClose.bind(this)}),this.card.setUser(this.auth.getUser()),this.panel.setUser(this.auth.getUser()),this.panel.setProjectId(this.config.projectId),this.pins=new A(t,this.onPinClick.bind(this)),this.pins.setHoverCallbacks(i=>{this.panel?.highlightRow(i)},i=>{this.panel?.clearRowHighlight(i)}),this.fab=new z(t,{onToggle:()=>{this.state==="idle"&&this.transitionTo("active")},onPanelToggle:()=>{this.state==="active"?this.transitionTo("active-panel"):this.state==="active-panel"&&this.transitionTo("active")},onExit:()=>{this.transitionTo("idle")}}),document.body.appendChild(this.container),await this.loadComments(),this.handleDeepLink(),this.subscribeToRealtime(),this.setupKeyboardShortcuts(),this.setupUrlChangeDetection(),this.auth.isAuthenticated()){let i=this.auth.getUser();this.joinPresence(i)}}joinPresence(e){!this.config.supabaseUrl||!this.config.supabaseKey||(this.presence?.leave(),this.presence=new I(this.config.supabaseUrl,this.config.supabaseKey,this.config.projectId),this.presence.setOnPresenceChange(t=>{this.panel?.renderPresence(t)}),this.presence.join(e),this.presence.updatePagePath(this.getPagePath()))}async signIn(){try{await this.auth.signIn()}catch(e){console.error("[Tack] Sign in failed:",e)}}getPagePath(){return window.location.pathname}setupUrlChangeDetection(){this.currentPagePath=this.getPagePath(),this.boundOnUrlChange=this.onUrlChange.bind(this),window.addEventListener("popstate",this.boundOnUrlChange),this.originalPushState=history.pushState.bind(history),this.originalReplaceState=history.replaceState.bind(history),history.pushState=(...e)=>{this.originalPushState(...e),this.onUrlChange()},history.replaceState=(...e)=>{this.originalReplaceState(...e),this.onUrlChange()}}onUrlChange(){let e=this.getPagePath();e!==this.currentPagePath&&(this.currentPagePath=e,this.presence?.updatePagePath(e),setTimeout(()=>{this.loadComments()},100))}transitionTo(e){let t=this.state;if(e==="idle"){if(this.form?.isFormVisible()&&this.form.hasContent()){this.form.jitter();return}this.selector?.disable(),this.form?.hide(),this.pins?.hide(),t==="active-panel"&&(this.panel?.hide(),this.setPanelOpen(!1)),this.fab?.collapse(),this.container?.classList.remove("tack-active"),this.fab?.setPanelToggleActive(!1),this.updateFabBadge()}else e==="active"?(this.selector?.enable(),this.pins?.show(),t==="active-panel"&&(this.panel?.hide(),this.setPanelOpen(!1)),t==="idle"&&this.fab?.expand(),this.container?.classList.add("tack-active"),this.fab?.setPanelToggleActive(!1)):e==="active-panel"&&(this.selector?.disable(),this.pins?.show(),this.fab&&this.panel?.setFabOffset(this.fab.getEdge()),this.panel?.show(),this.setPanelOpen(!0),t==="idle"&&this.fab?.expand(),this.container?.classList.add("tack-active"),this.fab?.setPanelToggleActive(!0));this.state=e}updateFabBadge(){let e=this.comments.filter(t=>!t.resolved&&!t.parent_id).length;this.fab?.setBadgeCount(e)}onShare(){let e=new URL(window.location.href);e.searchParams.set("tack_open","true"),navigator.clipboard.writeText(e.toString()).then(()=>{this.showToast("Link copied to clipboard")}).catch(()=>{this.showToast("Failed to copy link")})}injectPageStyles(){}setPanelOpen(e){}setupKeyboardShortcuts(){this.boundOnKeyDown=this.handleKeyDown.bind(this),document.addEventListener("keydown",this.boundOnKeyDown)}handleKeyDown(e){if(e.metaKey||e.ctrlKey||e.altKey)return;let t=e.key.toLowerCase();if(t!=="c"&&t!=="n"&&t!=="p")return;let i=document.activeElement;if(i&&(i.tagName==="INPUT"||i.tagName==="TEXTAREA"||i.isContentEditable))return;let n=this.shadowRoot?.activeElement;if(!(n&&(n.tagName==="INPUT"||n.tagName==="TEXTAREA"||n.isContentEditable))&&!(this.form?.isFormVisible()||this.card?.isVisible())){if(t==="c"){e.preventDefault(),this.state==="idle"?this.transitionTo("active"):this.state==="active-panel"?this.transitionTo("active"):this.transitionTo("idle");return}this.state==="active-panel"&&(t==="n"?(e.preventDefault(),this.navigateComments("next")):t==="p"&&(e.preventDefault(),this.navigateComments("prev")))}}navigateComments(e){let t=this.panel?.getFilteredCommentIds()||[];if(t.length===0)return;e==="next"?this.navigationIndex=this.navigationIndex<t.length-1?this.navigationIndex+1:0:this.navigationIndex=this.navigationIndex>0?this.navigationIndex-1:t.length-1;let i=t[this.navigationIndex],n=this.comments.find(a=>a.id===i);n&&(this.pins?.highlight(i),this.panel?.scrollToComment(i),this.scrollToComment(n))}async loadComments(){try{let e=await this.api.getComments();this.comments=e.comments,this.currentVersion=e.version,this.navigationIndex=-1,this.pins?.render(this.comments),this.panel?.render(this.comments),this.updateFabBadge()}catch(e){console.error("[Tack] Failed to load comments:",e)}}onElementSelected(e){this.form?.isFormVisible()||(this.selector?.disable(),this.form?.show(e))}async onCommentSubmit(e){let t=!1,i=window.setTimeout(()=>{let n=this.auth.getUser();this.pins?.showLoadingPin(e.anchor,{name:n?.name||e.authorName,avatar_url:n?.avatar_url||null}),t=!0},150);try{let n={content:e.content,element_selector:e.anchor.cssSelector,x_percent:e.anchor.relativeX*100,y_percent:e.anchor.relativeY*100,anchor:e.anchor,page_path:this.getPagePath(),screenshot_data:e.screenshot};this.auth.isAuthenticated()||(n.author_name=e.authorName,n.author_email=e.authorEmail);let a=await this.api.createComment(n);clearTimeout(i),t&&this.pins?.resolveLoadingPin();let r={...a,screenshot_url:a.screenshot_url||e.screenshot||null};this.comments.push(r),this.pins?.render(this.comments),this.panel?.render(this.comments),this.showToast("Comment added"),this.pendingRetryData=null,this.updateFabBadge(),this.state==="active"&&this.selector?.enable()}catch(n){clearTimeout(i),console.error("[Tack] Failed to submit comment:",n),t?(this.pendingRetryData=e,this.pins?.failLoadingPin(()=>this.retryFailedComment())):this.showToast("Failed to add comment")}}retryFailedComment(){if(!this.pendingRetryData)return;let e=this.pendingRetryData;this.pendingRetryData=null,this.onCommentSubmit(e)}onCommentClick(e){this.scrollToComment(e),setTimeout(()=>{let t=this.pins?.getPinElement(e.id);t&&(this.card?.show(e,t),this.pins?.setActive(e.id),this.pins?.beacon(e.id))},300)}onPinClick(e,t){let i=this.comments.find(n=>n.id===e);i&&(this.card?.show(i,t),this.pins?.setActive(e),this.pins?.highlight(e),this.panel?.isOpen()&&this.panel.scrollToComment(e))}onCardClose(){this.pins?.setActive(null)}async onResolve(e,t){try{await this.api.updateComment(e,{resolved:t});let i=this.comments.find(n=>n.id===e);i&&(i.resolved=t,this.pins?.render(this.comments),this.panel?.render(this.comments),this.card?.updateComment(i),this.updateFabBadge())}catch(i){console.error("[Tack] Failed to update comment:",i)}}async onReply(e,t){try{let i={content:t,parent_id:e,page_path:this.getPagePath()};this.auth.isAuthenticated()||(i.author_name=localStorage.getItem("tack_author_name")||"Anonymous");let n=await this.api.createComment(i),a=this.comments.find(r=>r.id===e);a&&(a.replies=a.replies||[],a.replies.push(n),this.panel?.render(this.comments),this.card?.updateComment(a))}catch(i){console.error("[Tack] Failed to submit reply:",i)}}async onEdit(e,t){try{await this.api.updateComment(e,{content:t});let i=this.comments.find(n=>n.id===e);i&&(i.content=t,this.pins?.render(this.comments),this.panel?.render(this.comments),this.card?.updateComment(i))}catch(i){console.error("[Tack] Failed to edit comment:",i),this.showToast("Failed to edit comment")}}async onDelete(e){try{await this.api.deleteComment(e);let t=this.findCommentById(e);t&&t.comment!==t.parent?(t.parent.replies=t.parent.replies?.filter(i=>i.id!==e)||[],this.card?.updateComment(t.parent)):this.comments=this.comments.filter(i=>i.id!==e),this.pins?.render(this.comments),this.panel?.render(this.comments),this.updateFabBadge(),this.showToast("Comment deleted")}catch(t){console.error("[Tack] Failed to delete comment:",t),this.showToast("Failed to delete comment")}}findCommentById(e){let t=this.comments.find(i=>i.id===e);if(t)return{comment:t,parent:t};for(let i of this.comments){let n=i.replies?.find(a=>a.id===e);if(n)return{comment:n,parent:i}}return null}async onReaction(e,t,i){if(!this.auth.isAuthenticated())return;let n=this.findCommentById(e);if(!n)return;let{comment:a,parent:r}=n,s=this.auth.getUser();a.reactions=a.reactions||[],i?a.reactions.push({emoji:t,user_id:s.id,user_name:s.name}):a.reactions=a.reactions.filter(o=>!(o.emoji===t&&o.user_id===s.id)),this.card?.updateComment(r);try{i?await this.api.addReaction(e,t):await this.api.removeReaction(e,t)}catch(o){console.error("[Tack] Failed to update reaction:",o),await this.loadComments()}}scrollToComment(e){if(e.element_selector)document.querySelector(e.element_selector)?.scrollIntoView({behavior:"smooth",block:"center"});else if(e.x_percent!==null&&e.y_percent!==null){let t=e.x_percent/100*document.documentElement.scrollWidth,i=e.y_percent/100*document.documentElement.scrollHeight;window.scrollTo({left:t-window.innerWidth/2,top:i-window.innerHeight/2,behavior:"smooth"})}}handleDeepLink(){let e=new URLSearchParams(window.location.search);e.get("tack_open")==="true"&&this.transitionTo("active-panel");let i=e.get("tack_comment");if(i){let n=this.comments.find(a=>a.id===i);n&&(this.transitionTo("active-panel"),this.panel?.scrollToComment(i),this.pins?.highlight(i),this.scrollToComment(n))}}subscribeToRealtime(){if(!this.currentVersion||!this.config.supabaseUrl||!this.config.supabaseKey){this.pollingInterval=setInterval(()=>this.loadComments(),3e4);return}this.realtime=new M(this.config.supabaseUrl,this.config.supabaseKey,this.currentVersion.id,(e,t)=>{this.handleRealtimeEvent(e,t)}),this.realtime.connect()}handleRealtimeEvent(e,t){switch(e){case"INSERT":if(this.comments.some(a=>a.id===t.id)||this.comments.some(a=>a.replies?.some(r=>r.id===t.id)))return;if(t.parent_id){let a=this.comments.find(r=>r.id===t.parent_id);a&&(a.replies=a.replies||[],a.replies.push(t))}else this.comments.push(t);this.showToast(`New comment from ${t.author_name}`);break;case"UPDATE":let n=this.comments.find(a=>a.id===t.id);n&&Object.assign(n,t);break;case"DELETE":this.comments=this.comments.filter(a=>a.id!==t.id);break}this.pins?.render(this.comments),this.panel?.render(this.comments),this.updateFabBadge()}showToast(e){if(!this.shadowRoot)return;let t=document.createElement("div");t.className="tack-toast",t.textContent=e,t.style.cssText=`
|
|
2524
|
+
`,document.body.appendChild(this.snapHint)),t==="left"?(this.snapHint.style.left="0px",this.snapHint.style.right="auto"):(this.snapHint.style.left="auto",this.snapHint.style.right="0px"),this.snapHint.style.opacity="1"}removeSnapHint(){if(this.snapHint){this.snapHint.style.opacity="0";let e=this.snapHint;this.snapHint=null,setTimeout(()=>{e.parentNode&&e.parentNode.removeChild(e)},150)}}expand(){this.expanded||(this.expanded=!0,this.el.classList.add("tack-fab--expanded"),this.badge.classList.remove("visible"))}collapse(){this.expanded&&(this.expanded=!1,this.el.classList.remove("tack-fab--expanded"),setTimeout(()=>{!this.expanded&&parseInt(this.badge.textContent||"0",10)>0&&this.badge.classList.add("visible")},200))}isExpanded(){return this.expanded}getEdge(){return this.position.edge}setPanelToggleActive(e){this.panelToggleBtn.classList.toggle("tack-fab-btn--active",e)}setBadgeCount(e){this.badge.textContent=e>99?"99+":String(e),!this.expanded&&e>0?this.badge.classList.add("visible"):this.badge.classList.remove("visible")}destroy(){this.cleanupDragListeners(),v(this.dragOverlay),this.removeSnapHint(),document.body.style.userSelect="",this.boundOnResize&&(window.removeEventListener("resize",this.boundOnResize),this.boundOnResize=null),this.el.remove()}};var O=class{constructor(e){this.container=null;this.shadowRoot=null;this.selector=null;this.form=null;this.panel=null;this.pins=null;this.card=null;this.realtime=null;this.presence=null;this.fab=null;this.state="idle";this.comments=[];this.currentVersion=null;this.currentPagePath="";this.originalPushState=null;this.originalReplaceState=null;this.pollingInterval=null;this.boundOnUrlChange=null;this.boundOnKeyDown=null;this.navigationIndex=-1;this.pendingRetryData=null;this.config={apiUrl:"https://tacktext.vercel.app/api",supabaseUrl:"https://etpavqvnpupqdxdptkhc.supabase.co",supabaseKey:"eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJzdXBhYmFzZSIsInJlZiI6ImV0cGF2cXZucHVwcWR4ZHB0a2hjIiwicm9sZSI6ImFub24iLCJpYXQiOjE3NzQ4MzU4MzgsImV4cCI6MjA5MDQxMTgzOH0.GMSIuPmMaEkNhss_laSm_NchihN_KF9VyyEh5YH4Ru0",...e},this.api=new w(this.config.apiUrl,this.config.projectId),this.auth=new C(this.config.apiUrl)}async mount(){this.container=document.createElement("div"),this.container.id="tack-widget",this.shadowRoot=this.container.attachShadow({mode:"open"});let e=document.createElement("style");e.textContent=q(),this.shadowRoot.appendChild(e),this.injectPageStyles();let t=document.createElement("div");if(t.className="tack-wrapper",this.shadowRoot.appendChild(t),this.auth.setOnAuthChange(i=>{this.api.setAuthToken(i?this.auth.getSessionToken():null),this.form?.setUser(i),this.card?.setUser(i),this.panel?.setUser(i),i?this.joinPresence(i):(this.presence?.leave(),this.presence=null)}),await this.auth.init(),this.auth.isAuthenticated()&&this.api.setAuthToken(this.auth.getSessionToken()),this.api.setOnUnauthorized(()=>{this.auth.signOut(),this.showToast("Session expired. Please sign in again.")}),this.selector=new E(this.onElementSelected.bind(this),()=>this.transitionTo("idle")),this.form=new T(t,this.onCommentSubmit.bind(this)),this.form.setUser(this.auth.getUser()),this.form.setOnHide(()=>{this.state==="active"&&setTimeout(()=>{this.state==="active"&&this.selector?.enable()},100)}),this.form.setOnSignIn(()=>this.signIn()),this.panel=new R(t,{onCommentClick:this.onCommentClick.bind(this),onResolve:this.onResolve.bind(this),onReply:this.onReply.bind(this),onClose:()=>this.transitionTo("active"),onAddComment:()=>this.transitionTo("active"),onShare:this.onShare.bind(this),onRowHover:i=>{this.pins?.setHoverLinked(i)},onRowHoverEnd:()=>{this.pins?.setHoverLinked(null)},onSideChange:()=>{this.state==="active-panel"&&(this.fab&&this.panel?.setFabOffset(this.fab.getEdge()),this.setPanelOpen(!0))}}),this.card=new A(t,{onResolve:this.onResolve.bind(this),onReply:this.onReply.bind(this),onEdit:this.onEdit.bind(this),onDelete:this.onDelete.bind(this),onReaction:this.onReaction.bind(this),onClose:this.onCardClose.bind(this)}),this.card.setUser(this.auth.getUser()),this.panel.setUser(this.auth.getUser()),this.panel.setProjectId(this.config.projectId),this.pins=new F(t,this.onPinClick.bind(this)),this.pins.setHoverCallbacks(i=>{this.panel?.highlightRow(i)},i=>{this.panel?.clearRowHighlight(i)}),this.fab=new z(t,{onToggle:()=>{this.state==="idle"&&this.transitionTo("active")},onPanelToggle:()=>{this.state==="active"?this.transitionTo("active-panel"):this.state==="active-panel"&&this.transitionTo("active")},onExit:()=>{this.transitionTo("idle")}}),document.body.appendChild(this.container),await this.loadComments(),this.handleDeepLink(),this.subscribeToRealtime(),this.setupKeyboardShortcuts(),this.setupUrlChangeDetection(),this.auth.isAuthenticated()){let i=this.auth.getUser();this.joinPresence(i)}}joinPresence(e){!this.config.supabaseUrl||!this.config.supabaseKey||(this.presence?.leave(),this.presence=new I(this.config.supabaseUrl,this.config.supabaseKey,this.config.projectId),this.presence.setOnPresenceChange(t=>{this.panel?.renderPresence(t)}),this.presence.join(e),this.presence.updatePagePath(this.getPagePath()))}async signIn(){try{await this.auth.signIn()}catch(e){console.error("[Tack] Sign in failed:",e)}}getPagePath(){return window.location.pathname}setupUrlChangeDetection(){this.currentPagePath=this.getPagePath(),this.boundOnUrlChange=this.onUrlChange.bind(this),window.addEventListener("popstate",this.boundOnUrlChange),this.originalPushState=history.pushState.bind(history),this.originalReplaceState=history.replaceState.bind(history),history.pushState=(...e)=>{this.originalPushState(...e),this.onUrlChange()},history.replaceState=(...e)=>{this.originalReplaceState(...e),this.onUrlChange()}}onUrlChange(){let e=this.getPagePath();e!==this.currentPagePath&&(this.currentPagePath=e,this.presence?.updatePagePath(e),setTimeout(()=>{this.loadComments()},100))}transitionTo(e){let t=this.state;if(e==="idle"){if(this.form?.isFormVisible()&&this.form.hasContent()){this.form.jitter();return}this.selector?.disable(),this.form?.hide(),this.pins?.hide(),t==="active-panel"&&(this.panel?.hide(),this.setPanelOpen(!1)),this.fab?.collapse(),this.container?.classList.remove("tack-active"),this.fab?.setPanelToggleActive(!1),this.updateFabBadge()}else e==="active"?(this.selector?.enable(),this.pins?.show(),t==="active-panel"&&(this.panel?.hide(),this.setPanelOpen(!1)),t==="idle"&&this.fab?.expand(),this.container?.classList.add("tack-active"),this.fab?.setPanelToggleActive(!1)):e==="active-panel"&&(this.selector?.disable(),this.pins?.show(),this.fab&&this.panel?.setFabOffset(this.fab.getEdge()),this.panel?.show(),this.setPanelOpen(!0),t==="idle"&&this.fab?.expand(),this.container?.classList.add("tack-active"),this.fab?.setPanelToggleActive(!0));this.state=e}updateFabBadge(){let e=this.comments.filter(t=>!t.resolved&&!t.parent_id).length;this.fab?.setBadgeCount(e)}onShare(){let e=new URL(window.location.href);e.searchParams.set("tack_open","true"),navigator.clipboard.writeText(e.toString()).then(()=>{this.showToast("Link copied to clipboard")}).catch(()=>{this.showToast("Failed to copy link")})}injectPageStyles(){}setPanelOpen(e){}setupKeyboardShortcuts(){this.boundOnKeyDown=this.handleKeyDown.bind(this),document.addEventListener("keydown",this.boundOnKeyDown)}handleKeyDown(e){if(e.metaKey||e.ctrlKey||e.altKey)return;let t=e.key.toLowerCase();if(t!=="c"&&t!=="n"&&t!=="p")return;let i=document.activeElement;if(i&&(i.tagName==="INPUT"||i.tagName==="TEXTAREA"||i.isContentEditable))return;let n=this.shadowRoot?.activeElement;if(!(n&&(n.tagName==="INPUT"||n.tagName==="TEXTAREA"||n.isContentEditable))&&!(this.form?.isFormVisible()||this.card?.isVisible())){if(t==="c"){e.preventDefault(),this.state==="idle"?this.transitionTo("active"):this.state==="active-panel"?this.transitionTo("active"):this.transitionTo("idle");return}this.state==="active-panel"&&(t==="n"?(e.preventDefault(),this.navigateComments("next")):t==="p"&&(e.preventDefault(),this.navigateComments("prev")))}}navigateComments(e){let t=this.panel?.getFilteredCommentIds()||[];if(t.length===0)return;e==="next"?this.navigationIndex=this.navigationIndex<t.length-1?this.navigationIndex+1:0:this.navigationIndex=this.navigationIndex>0?this.navigationIndex-1:t.length-1;let i=t[this.navigationIndex],n=this.comments.find(a=>a.id===i);n&&(this.pins?.highlight(i),this.panel?.scrollToComment(i),this.scrollToComment(n))}async loadComments(){try{let e=await this.api.getComments();this.comments=e.comments,this.currentVersion=e.version,this.navigationIndex=-1,this.pins?.render(this.comments),this.panel?.render(this.comments),this.updateFabBadge()}catch(e){console.error("[Tack] Failed to load comments:",e)}}onElementSelected(e){this.form?.isFormVisible()||(this.selector?.disable(),this.form?.show(e))}async onCommentSubmit(e){let t=!1,i=window.setTimeout(()=>{let n=this.auth.getUser();this.pins?.showLoadingPin(e.anchor,{name:n?.name||e.authorName,avatar_url:n?.avatar_url||null}),t=!0},150);try{let n={content:e.content,element_selector:e.anchor.cssSelector,x_percent:e.anchor.relativeX*100,y_percent:e.anchor.relativeY*100,anchor:e.anchor,page_path:this.getPagePath(),screenshot_data:e.screenshot};this.auth.isAuthenticated()||(n.author_name=e.authorName,n.author_email=e.authorEmail);let a=await this.api.createComment(n);clearTimeout(i),t&&this.pins?.resolveLoadingPin();let r={...a,screenshot_url:a.screenshot_url||e.screenshot||null};this.comments.push(r),this.pins?.render(this.comments),this.panel?.render(this.comments),this.showToast("Comment added"),this.pendingRetryData=null,this.updateFabBadge(),this.state==="active"&&this.selector?.enable()}catch(n){clearTimeout(i),console.error("[Tack] Failed to submit comment:",n),t?(this.pendingRetryData=e,this.pins?.failLoadingPin(()=>this.retryFailedComment())):this.showToast("Failed to add comment")}}retryFailedComment(){if(!this.pendingRetryData)return;let e=this.pendingRetryData;this.pendingRetryData=null,this.onCommentSubmit(e)}onCommentClick(e){this.scrollToComment(e),setTimeout(()=>{let t=this.pins?.getPinElement(e.id);t&&(this.card?.show(e,t),this.pins?.setActive(e.id),this.pins?.beacon(e.id))},300)}onPinClick(e,t){let i=this.comments.find(n=>n.id===e);i&&(this.card?.show(i,t),this.pins?.setActive(e),this.pins?.highlight(e),this.panel?.isOpen()&&this.panel.scrollToComment(e))}onCardClose(){this.pins?.setActive(null)}async onResolve(e,t){try{await this.api.updateComment(e,{resolved:t});let i=this.comments.find(n=>n.id===e);i&&(i.resolved=t,this.pins?.render(this.comments),this.panel?.render(this.comments),this.card?.updateComment(i),this.updateFabBadge())}catch(i){console.error("[Tack] Failed to update comment:",i)}}async onReply(e,t){try{let i={content:t,parent_id:e,page_path:this.getPagePath()};this.auth.isAuthenticated()||(i.author_name=localStorage.getItem("tack_author_name")||"Anonymous");let n=await this.api.createComment(i),a=this.comments.find(r=>r.id===e);a&&(a.replies=a.replies||[],a.replies.push(n),this.panel?.render(this.comments),this.card?.updateComment(a))}catch(i){console.error("[Tack] Failed to submit reply:",i)}}async onEdit(e,t){try{await this.api.updateComment(e,{content:t});let i=this.comments.find(n=>n.id===e);i&&(i.content=t,this.pins?.render(this.comments),this.panel?.render(this.comments),this.card?.updateComment(i))}catch(i){console.error("[Tack] Failed to edit comment:",i),this.showToast("Failed to edit comment")}}async onDelete(e){try{await this.api.deleteComment(e);let t=this.findCommentById(e);t&&t.comment!==t.parent?(t.parent.replies=t.parent.replies?.filter(i=>i.id!==e)||[],this.card?.updateComment(t.parent)):this.comments=this.comments.filter(i=>i.id!==e),this.pins?.render(this.comments),this.panel?.render(this.comments),this.updateFabBadge(),this.showToast("Comment deleted")}catch(t){console.error("[Tack] Failed to delete comment:",t),this.showToast("Failed to delete comment")}}findCommentById(e){let t=this.comments.find(i=>i.id===e);if(t)return{comment:t,parent:t};for(let i of this.comments){let n=i.replies?.find(a=>a.id===e);if(n)return{comment:n,parent:i}}return null}async onReaction(e,t,i){if(!this.auth.isAuthenticated())return;let n=this.findCommentById(e);if(!n)return;let{comment:a,parent:r}=n,s=this.auth.getUser();a.reactions=a.reactions||[],i?a.reactions.push({emoji:t,user_id:s.id,user_name:s.name}):a.reactions=a.reactions.filter(o=>!(o.emoji===t&&o.user_id===s.id)),this.card?.updateComment(r);try{i?await this.api.addReaction(e,t):await this.api.removeReaction(e,t)}catch(o){console.error("[Tack] Failed to update reaction:",o),await this.loadComments()}}scrollToComment(e){if(e.element_selector)document.querySelector(e.element_selector)?.scrollIntoView({behavior:"smooth",block:"center"});else if(e.x_percent!==null&&e.y_percent!==null){let t=e.x_percent/100*document.documentElement.scrollWidth,i=e.y_percent/100*document.documentElement.scrollHeight;window.scrollTo({left:t-window.innerWidth/2,top:i-window.innerHeight/2,behavior:"smooth"})}}handleDeepLink(){let e=new URLSearchParams(window.location.search);e.get("tack_open")==="true"&&this.transitionTo("active-panel");let i=e.get("tack_comment");if(i){let n=this.comments.find(a=>a.id===i);n&&(this.transitionTo("active-panel"),this.panel?.scrollToComment(i),this.pins?.highlight(i),this.scrollToComment(n))}}subscribeToRealtime(){if(!this.currentVersion||!this.config.supabaseUrl||!this.config.supabaseKey){this.pollingInterval=setInterval(()=>this.loadComments(),3e4);return}this.realtime=new M(this.config.supabaseUrl,this.config.supabaseKey,this.currentVersion.id,(e,t)=>{this.handleRealtimeEvent(e,t)}),this.realtime.connect()}handleRealtimeEvent(e,t){switch(e){case"INSERT":if(this.comments.some(a=>a.id===t.id)||this.comments.some(a=>a.replies?.some(r=>r.id===t.id)))return;if(t.parent_id){let a=this.comments.find(r=>r.id===t.parent_id);a&&(a.replies=a.replies||[],a.replies.push(t))}else this.comments.push(t);this.showToast(`New comment from ${t.author_name}`);break;case"UPDATE":let n=this.comments.find(a=>a.id===t.id);n&&Object.assign(n,t);break;case"DELETE":this.comments=this.comments.filter(a=>a.id!==t.id);break}this.pins?.render(this.comments),this.panel?.render(this.comments),this.updateFabBadge()}showToast(e){if(!this.shadowRoot)return;let t=document.createElement("div");t.className="tack-toast",t.textContent=e,t.style.cssText=`
|
|
2524
2525
|
position: fixed;
|
|
2525
2526
|
bottom: 80px;
|
|
2526
2527
|
right: 20px;
|