commerce-kit 0.36.3 → 0.36.5

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/browser.js CHANGED
@@ -1,3 +1,3 @@
1
- import{useEffect as C,useRef as M,useState as v}from"react";import{createRoot as _}from"react-dom/client";import{jsx as b,jsxs as w}from"react/jsx-runtime";var k="yns-feedback-toolbar-root",B=()=>{if(typeof window>"u")return null;let e=(process.env.NEXT_PUBLIC_YNS_API_BASE??"").trim();if(e)return e.replace(/\/$/,"");let n=window.location.hostname,t=window.location.protocol;return n.endsWith(".yns.store")?`${t}//yns.store`:n.endsWith(".yns.cx")?`${t}//yns.cx`:window.location.origin},F=e=>{if(e.id)return`#${CSS.escape(e.id)}`;let n=[],t=e;for(;t&&t.nodeType===Node.ELEMENT_NODE&&n.length<6;){let o=t.tagName.toLowerCase(),i=t.getAttribute("class");if(i){let c=i.split(/\s+/).filter(Boolean).slice(0,2).map(l=>`.${CSS.escape(l)}`).join("");o+=c}let r=t.parentElement,d=t.tagName;if(r){let c=Array.from(r.children).filter(l=>l.tagName===d);if(c.length>1){let l=c.indexOf(t)+1;o+=`:nth-of-type(${l})`}}n.unshift(o),t=r}return n.join(" > ")},z=["id","class","data-testid","aria-label","role","name","href","src"],L=e=>{let n=[];for(let t of z){let o=e.getAttribute(t);if(!o)continue;let i=o.length>80?`${o.slice(0,80)}\u2026`:o;n.push(` ${t}="${i.replace(/"/g,"&quot;")}"`)}return n.join("")},P=e=>{let n=(e.textContent??"").replace(/\s+/g," ").trim();return n?n.length>100?`${n.slice(0,100)}\u2026`:n:""},j=e=>{let n=[],t=e;for(;t&&t!==document.documentElement&&n.length<5;){let l=t.parentElement;if(!l)break;n.unshift(l),t=l}let o=[],i=0;for(let l of n){let f=" ".repeat(i);o.push(`${f}<${l.tagName.toLowerCase()}${L(l)}>`),i++}let r=" ".repeat(i),d=e.tagName.toLowerCase(),c=P(e);if(o.push(`${r}<${d}${L(e)}>${c?`${c}</${d}>`:""} \u2190 TARGET`),!c){let l=" ".repeat(i+1),f=Array.from(e.children).slice(0,6);for(let u of f){let h=P(u);o.push(`${l}<${u.tagName.toLowerCase()}${L(u)}>${h?`${h}</${u.tagName.toLowerCase()}>`:""}`)}e.children.length>6&&o.push(`${l}\u2026 (${e.children.length-6} more children)`),o.push(`${r}</${d}>`)}for(let l=n.length-1;l>=0;l--){let f=" ".repeat(l),u=n[l];u&&o.push(`${f}</${u.tagName.toLowerCase()}>`)}return o.join(`
2
- `)},X=e=>{let n=e;for(;n;){if(n instanceof HTMLElement&&n.dataset.ynsFeedbackUi==="true")return!0;n=n.parentElement}return!1};function D(){let[e,n]=v(null),[t,o]=v(!0),[i,r]=v(!1),[d,c]=v(null),[l,f]=v(null),u=M(null);C(()=>{if(u.current=B(),!u.current){o(!1);return}let s=new AbortController;return fetch(`${u.current}/api/feedback-comments?host=${encodeURIComponent(window.location.host)}`,{credentials:"include",signal:s.signal}).then(async a=>{if(!a.ok){n(null);return}let y=await a.json();n(y)}).catch(()=>{n(null)}).finally(()=>o(!1)),()=>s.abort()},[]),C(()=>{if(i)return document.body.style.cursor="crosshair",()=>{document.body.style.cursor=""}},[i]),C(()=>{if(!i)return;let s=a=>{let y=a.target;if(!(y instanceof Element)||X(y))return;a.preventDefault(),a.stopPropagation();let S=y.getBoundingClientRect();c({cssSelector:F(y),pagePath:window.location.pathname,surroundingHtml:j(y),rect:{top:S.top+window.scrollY,left:S.left+window.scrollX,width:S.width,height:S.height},clickX:a.clientX+window.scrollX,clickY:a.clientY+window.scrollY}),r(!1)};return document.addEventListener("click",s,{capture:!0}),()=>document.removeEventListener("click",s,{capture:!0})},[i]);let h=async()=>{if(!u.current)return;let s=await fetch(`${u.current}/api/feedback-comments?host=${encodeURIComponent(window.location.host)}`,{credentials:"include"});if(!s.ok)return;let a=await s.json();n(a)},E=async s=>{!u.current||!e||!d||!(await fetch(`${u.current}/api/feedback-comments`,{method:"POST",credentials:"include",headers:{"Content-Type":"application/json"},body:JSON.stringify({feedbackSessionId:e.feedbackSessionId,content:s,pagePath:d.pagePath,cssSelector:d.cssSelector,surroundingHtml:d.surroundingHtml})})).ok||(c(null),await h())},g=async(s,a)=>{!u.current||!(await fetch(`${u.current}/api/feedback-comments/${s}`,{method:"PATCH",credentials:"include",headers:{"Content-Type":"application/json"},body:JSON.stringify({content:a})})).ok||(f(null),await h())},m=async s=>{!u.current||!(await fetch(`${u.current}/api/feedback-comments/${s}`,{method:"DELETE",credentials:"include"})).ok||await h()};if(t||!e||!e.canComment)return null;let p=e.comments.filter(s=>s.pagePath===window.location.pathname&&s.status!=="done");return w("div",{"data-yns-feedback-ui":"true",children:[p.map((s,a)=>b(U,{pin:s,number:a+1,editing:l===s.id,onStartEdit:()=>f(s.id),onCancelEdit:()=>f(null),onSave:y=>g(s.id,y),onRemove:()=>m(s.id)},s.id)),d&&b(Y,{pending:d,onCancel:()=>c(null),onSave:s=>E(s)}),w("div",{style:V,children:[b("button",{type:"button",onClick:()=>r(s=>!s),style:i?H:T,children:i?"Cancel":"Add comment"}),b("span",{style:W,children:i?"Click any element to comment":`${p.length} on this page`})]})]})}function U({pin:e,number:n,editing:t,onStartEdit:o,onCancelEdit:i,onSave:r,onRemove:d}){let c=O(e.cssSelector);return c?w("div",{style:{position:"absolute",top:c.top,left:c.left,zIndex:2147483600,pointerEvents:"auto"},children:[b("button",{type:"button",onClick:o,style:q,title:e.content,children:n}),t&&b(N,{initial:e.content,onCancel:i,onSave:r,onRemove:d})]}):null}function Y({pending:e,onCancel:n,onSave:t}){return b("div",{style:{position:"absolute",top:e.clickY+10,left:e.clickX+10,zIndex:2147483647},children:b(N,{initial:"",onCancel:n,onSave:t})})}function N({initial:e,onCancel:n,onSave:t,onRemove:o}){let[i,r]=v(e),[d,c]=v(!1);return w("form",{onSubmit:async f=>{f.preventDefault();let u=i.trim();if(u){c(!0);try{await t(u)}finally{c(!1)}}},style:K,children:[b("textarea",{value:i,onChange:f=>r(f.target.value),placeholder:"Leave a comment\u2026",style:G,rows:3}),w("div",{style:J,children:[o&&b("button",{type:"button",onClick:()=>o(),style:ee,disabled:d,children:"Delete"}),b("div",{style:{flex:1}}),b("button",{type:"button",onClick:n,style:Z,disabled:d,children:"Cancel"}),b("button",{type:"submit",style:Q,disabled:d||!i.trim(),children:d?"Saving\u2026":"Save"})]})]})}function O(e){let[n,t]=v(null);return C(()=>{let o=()=>{let r=null;try{r=document.querySelector(e)}catch{r=null}if(!r){t(null);return}let d=r.getBoundingClientRect();t({top:d.top+window.scrollY-12,left:d.left+window.scrollX-12})};o();let i=new ResizeObserver(o);try{let r=document.querySelector(e);r&&i.observe(r)}catch{}return window.addEventListener("scroll",o,!0),window.addEventListener("resize",o),()=>{i.disconnect(),window.removeEventListener("scroll",o,!0),window.removeEventListener("resize",o)}},[e]),n}var V={position:"fixed",bottom:16,left:"50%",transform:"translateX(-50%)",zIndex:2147483646,display:"flex",alignItems:"center",gap:12,padding:"8px 12px",background:"rgba(17, 17, 17, 0.92)",color:"white",borderRadius:999,boxShadow:"0 8px 24px rgba(0,0,0,0.25)",fontFamily:'-apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Helvetica, Arial, sans-serif, "Apple Color Emoji", "Segoe UI Emoji"',fontSize:14,pointerEvents:"auto"},T={border:"none",background:"white",color:"#111",padding:"6px 12px",borderRadius:999,cursor:"pointer",fontWeight:600,fontSize:13},H={...T,background:"#ef4444",color:"white"},W={opacity:.8,fontSize:12},q={width:24,height:24,borderRadius:999,background:"#10b981",color:"white",border:"2px solid white",cursor:"pointer",fontSize:12,fontWeight:700,boxShadow:"0 2px 6px rgba(0,0,0,0.3)",display:"inline-flex",alignItems:"center",justifyContent:"center",padding:0},K={background:"white",border:"1px solid #e5e7eb",borderRadius:8,padding:12,width:280,boxShadow:"0 12px 32px rgba(0,0,0,0.18)",fontFamily:'-apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Helvetica, Arial, sans-serif, "Apple Color Emoji", "Segoe UI Emoji"',display:"flex",flexDirection:"column",gap:8,color:"#111"},G={width:"100%",border:"1px solid #d1d5db",borderRadius:6,padding:8,fontSize:14,resize:"vertical",fontFamily:"inherit",color:"#111",background:"white",boxSizing:"border-box"},J={display:"flex",alignItems:"center",gap:6},$={border:"1px solid transparent",borderRadius:6,padding:"6px 10px",fontSize:13,cursor:"pointer",fontWeight:500},Q={...$,background:"#111",color:"white"},Z={...$,background:"transparent",color:"#374151",borderColor:"#d1d5db"},ee={...$,background:"transparent",color:"#b91c1c",borderColor:"#fecaca"};function I(){if(console.log("[YNS Feedback Toolbar] mountFeedbackToolbar() called",{isWindow:typeof window<"u",vercelEnv:process.env.NEXT_PUBLIC_VERCEL_ENV,alreadyMounted:typeof document<"u"&&!!document.getElementById(k)}),typeof window>"u")return null;if(process.env.NEXT_PUBLIC_VERCEL_ENV!=="preview")return console.log("[YNS Feedback Toolbar] gate failed \u2014 NEXT_PUBLIC_VERCEL_ENV is",process.env.NEXT_PUBLIC_VERCEL_ENV),null;if(document.getElementById(k))return null;let e=document.createElement("div");e.id=k,e.dataset.ynsFeedbackUi="true",document.body.appendChild(e);let n=_(e);return n.render(b(D,{})),{unmount:()=>{n.unmount(),e.remove()}}}typeof window<"u"&&console.log("[YNS Feedback Toolbar] module evaluated",{vercelEnv:process.env.NEXT_PUBLIC_VERCEL_ENV,readyState:document.readyState,willAutoMount:process.env.NEXT_PUBLIC_VERCEL_ENV==="preview"});typeof window<"u"&&process.env.NEXT_PUBLIC_VERCEL_ENV==="preview"&&(document.readyState==="loading"?document.addEventListener("DOMContentLoaded",()=>{I()}):I());function A(){typeof window>"u"||(console.log("[YNS Sandbox Inspectors] module evaluated"),oe(),ie())}A();var te=new Set(["HEAD","SCRIPT","STYLE","NOSCRIPT","HTML"]);function ne(e){if(e.id)return`${e.tagName.toLowerCase()}#${CSS.escape(e.id)}`;let n=[],t=e;for(;t&&t!==document.body&&t!==document.documentElement;){let o=t.tagName.toLowerCase();if(t.id){n.unshift(`${o}#${CSS.escape(t.id)}`);break}let i=Array.from(t.classList).filter(c=>!c.startsWith("data-yns-"));i.length>0&&(o+=`.${i.map(c=>CSS.escape(c)).join(".")}`);let r=t.parentElement,d=t.tagName;if(r&&Array.from(r.children).filter(l=>l.tagName===d&&(i.length===0||i.every(f=>l.classList.contains(f)))).length>1){let l=Array.from(r.children).indexOf(t)+1;o+=`:nth-child(${l})`}n.unshift(o),t=t.parentElement}return n.join(" > ")}function R(e,n){let t=e.getBoundingClientRect(),o=window.getComputedStyle(e),i=(e.textContent??"").trim();return{tag:e.tagName.toLowerCase(),id:e.id||void 0,classes:Array.from(e.classList).filter(r=>!r.startsWith("data-yns-")),textContent:i.length>n?`${i.slice(0,n)}\u2026`:i,cssSelector:ne(e),boundingRect:{top:t.top,left:t.left,width:t.width,height:t.height},computedStyles:{color:o.color,backgroundColor:o.backgroundColor,fontSize:o.fontSize,fontFamily:o.fontFamily,padding:o.padding,margin:o.margin}}}function x(e,n){if(!e||!e.tagName||te.has(e.tagName))return!0;for(let t of n)if(e.hasAttribute?.(t))return!0;return!1}function oe(){let e=!1,n=null,t=null,o=document.createElement("div");o.setAttribute("data-yns-design-overlay","hover"),o.style.cssText=["position: fixed","pointer-events: none","z-index: 2147483646","border: 2px solid #3b82f6","background: rgba(59, 130, 246, 0.08)","border-radius: 3px","display: none","transition: top 0.05s, left 0.05s, width 0.05s, height 0.05s"].join(";");let i=document.createElement("div");i.setAttribute("data-yns-design-overlay","label"),i.style.cssText=["position: fixed","pointer-events: none","z-index: 2147483647","background: #3b82f6","color: #fff","font-size: 11px","font-family: ui-monospace, monospace","padding: 2px 6px","border-radius: 3px","white-space: nowrap","display: none"].join(";"),document.documentElement.appendChild(o),document.documentElement.appendChild(i);let r=document.createElement("style");r.setAttribute("data-yns-design-overlay","style"),r.textContent="[data-yns-selected] { outline: 2px solid #3b82f6 !important; outline-offset: 1px; }",document.head.appendChild(r);function d(g){let m=g.getBoundingClientRect();o.style.top=`${m.top}px`,o.style.left=`${m.left}px`,o.style.width=`${m.width}px`,o.style.height=`${m.height}px`,o.style.display="block";let p=Array.from(g.classList).filter(a=>!a.startsWith("data-yns-")),s=g.tagName.toLowerCase()+(p.length?`.${p[0]}`:"");i.textContent=s,i.style.left=`${m.left}px`,i.style.top=`${Math.max(0,m.top-22)}px`,i.style.display="block"}let c=g=>{let m=document.elementFromPoint(g.clientX,g.clientY);if(x(m,["data-yns-design-overlay"])){o.style.display="none",i.style.display="none",n=null;return}n=m,requestAnimationFrame(()=>{n===m&&e&&m&&d(m)})},l=()=>{o.style.display="none",i.style.display="none",n=null},f=g=>{if(!e||!n)return;g.preventDefault(),g.stopPropagation(),g.stopImmediatePropagation();let m=n;if(x(m,["data-yns-design-overlay"]))return;let p=R(m,120),s=p.cssSelector;t&&t.el.removeAttribute("data-yns-selected"),t&&t.cssSelector===s?(t=null,window.parent.postMessage({type:"element-deselected",data:p},"*")):(t={el:m,cssSelector:s},m.setAttribute("data-yns-selected",""),window.parent.postMessage({type:"element-selected",data:p},"*"))},u=g=>{g.key==="Escape"&&e&&(E(),window.parent.postMessage({type:"design-mode-cleared"},"*"))};function h(){e=!0,document.addEventListener("mousemove",c,!0),document.addEventListener("mouseleave",l),document.addEventListener("click",f,!0),document.addEventListener("keydown",u,!0)}function E(){e=!1,document.removeEventListener("mousemove",c,!0),document.removeEventListener("mouseleave",l),document.removeEventListener("click",f,!0),document.removeEventListener("keydown",u,!0),o.style.display="none",i.style.display="none",n=null,t&&(t.el.removeAttribute("data-yns-selected"),t=null)}window.addEventListener("message",g=>{let m=g.data;!m||typeof m!="object"||(m.type==="design-mode-toggle"&&(m.enabled?h():(E(),window.parent.postMessage({type:"design-mode-cleared"},"*"))),m.type==="design-mode-deselect"&&t&&(t.el.removeAttribute("data-yns-selected"),t=null))})}function ie(){let e=!1,n=null,t=[],o=document.createElement("div");o.setAttribute("data-yns-comment-overlay","hover"),o.style.cssText=["position: fixed","pointer-events: none","z-index: 2147483644","border: 2px dashed #10b981","background: rgba(16, 185, 129, 0.06)","border-radius: 3px","display: none","transition: top 0.05s, left 0.05s, width 0.05s, height 0.05s"].join(";");let i=document.createElement("div");i.setAttribute("data-yns-comment-overlay","cursor-label"),i.textContent="Click to comment",i.style.cssText=["position: fixed","pointer-events: none","z-index: 2147483645","background: #059669","color: #fff","font-size: 11px","font-family: ui-sans-serif, system-ui, sans-serif","padding: 3px 8px","border-radius: 4px","white-space: nowrap","display: none","box-shadow: 0 2px 6px rgba(0,0,0,0.15)"].join(";");let r=document.createElement("div");r.setAttribute("data-yns-comment-overlay","pins"),r.style.cssText="position: fixed; top: 0; left: 0; width: 100%; height: 100%; pointer-events: none; z-index: 2147483643;",document.documentElement.appendChild(o),document.documentElement.appendChild(i),document.documentElement.appendChild(r);function d(){r.innerHTML="";for(let p of t){let s=null;try{s=document.querySelector(p.selector)}catch{s=null}if(!s)continue;let a=s.getBoundingClientRect(),y=document.createElement("div");y.style.cssText=["position: fixed",`top: ${a.top-12}px`,`left: ${a.left+a.width/2-12}px`,"width: 24px","height: 24px","border-radius: 50%","background: #059669","color: #fff","display: flex","align-items: center","justify-content: center","font-size: 12px","font-weight: 600","font-family: ui-sans-serif, system-ui, sans-serif","box-shadow: 0 2px 8px rgba(0,0,0,0.2)","pointer-events: none"].join(";"),y.textContent=String(p.number),r.appendChild(y)}}let c=p=>{let s=document.elementFromPoint(p.clientX,p.clientY);if(x(s,["data-yns-comment-overlay","data-yns-design-overlay"])){o.style.display="none",i.style.display="none",n=null;return}n=s,requestAnimationFrame(()=>{if(n===s&&e&&s){let a=s.getBoundingClientRect();o.style.top=`${a.top}px`,o.style.left=`${a.left}px`,o.style.width=`${a.width}px`,o.style.height=`${a.height}px`,o.style.display="block",i.style.left=`${p.clientX+14}px`,i.style.top=`${p.clientY+14}px`,i.style.display="block"}})},l=()=>{o.style.display="none",i.style.display="none",n=null},f=p=>{if(!e||!n)return;p.preventDefault(),p.stopPropagation(),p.stopImmediatePropagation();let s=n;if(x(s,["data-yns-comment-overlay","data-yns-design-overlay"]))return;let a=R(s,200),y=s.getBoundingClientRect();window.parent.postMessage({type:"comment-click",data:{element:a,clickPosition:{x:p.clientX,y:p.clientY},elementRect:{top:y.top,left:y.left,width:y.width,height:y.height},pagePath:window.location.pathname}},"*")},u=p=>{p.key==="Escape"&&e&&(E(),window.parent.postMessage({type:"comment-mode-cleared"},"*"))};function h(){e=!0,document.body.style.cursor="crosshair",document.addEventListener("mousemove",c,!0),document.addEventListener("mouseleave",l),document.addEventListener("click",f,!0),document.addEventListener("keydown",u,!0)}function E(){e=!1,document.body.style.cursor="",document.removeEventListener("mousemove",c,!0),document.removeEventListener("mouseleave",l),document.removeEventListener("click",f,!0),document.removeEventListener("keydown",u,!0),o.style.display="none",i.style.display="none",n=null}let g=!1,m=()=>{g||(g=!0,requestAnimationFrame(()=>{g=!1,d()}))};window.addEventListener("scroll",m,{passive:!0}),window.addEventListener("resize",m,{passive:!0}),window.addEventListener("message",p=>{let s=p.data;!s||typeof s!="object"||(s.type==="comment-mode-toggle"&&(s.enabled?h():E()),s.type==="comment-pins-update"&&(t=s.pins??[],d()),s.type==="comment-pin-remove"&&(t=t.filter(a=>a.id!==s.pinId),d()))})}export{I as mountFeedbackToolbar,A as startSandboxInspectors};
1
+ import{useEffect as $,useRef as X,useState as C}from"react";import{createRoot as q}from"react-dom/client";import{Fragment as Ce,jsx as f,jsxs as x}from"react/jsx-runtime";var A="yns-feedback-toolbar-root",G=()=>{if(typeof window>"u")return null;let e=(process.env.NEXT_PUBLIC_YNS_API_BASE??"").trim();if(e)return e.replace(/\/$/,"");let t=window.location.hostname,n=window.location.protocol;return t.endsWith(".yns.store")?`${n}//yns.store`:t.endsWith(".yns.cx")?`${n}//yns.cx`:window.location.origin},K=e=>{if(e.id)return`#${CSS.escape(e.id)}`;let t=[],n=e;for(;n&&n.nodeType===Node.ELEMENT_NODE&&t.length<6;){let o=n.tagName.toLowerCase(),i=n.getAttribute("class");if(i){let s=i.split(/\s+/).filter(Boolean).slice(0,2).map(a=>`.${CSS.escape(a)}`).join("");o+=s}let d=n.parentElement,l=n.tagName;if(d){let s=Array.from(d.children).filter(a=>a.tagName===l);if(s.length>1){let a=s.indexOf(n)+1;o+=`:nth-of-type(${a})`}}t.unshift(o),n=d}return t.join(" > ")},J=["id","class","data-testid","aria-label","role","name","href","src"],N=e=>{let t=[];for(let n of J){let o=e.getAttribute(n);if(!o)continue;let i=o.length>80?`${o.slice(0,80)}\u2026`:o;t.push(` ${n}="${i.replace(/"/g,"&quot;")}"`)}return t.join("")},F=e=>{let t=(e.textContent??"").replace(/\s+/g," ").trim();return t?t.length>100?`${t.slice(0,100)}\u2026`:t:""},Q=e=>{let t=[],n=e;for(;n&&n!==document.documentElement&&t.length<5;){let a=n.parentElement;if(!a)break;t.unshift(a),n=a}let o=[],i=0;for(let a of t){let b=" ".repeat(i);o.push(`${b}<${a.tagName.toLowerCase()}${N(a)}>`),i++}let d=" ".repeat(i),l=e.tagName.toLowerCase(),s=F(e);if(o.push(`${d}<${l}${N(e)}>${s?`${s}</${l}>`:""} \u2190 TARGET`),!s){let a=" ".repeat(i+1),b=Array.from(e.children).slice(0,6);for(let g of b){let v=F(g);o.push(`${a}<${g.tagName.toLowerCase()}${N(g)}>${v?`${v}</${g.tagName.toLowerCase()}>`:""}`)}e.children.length>6&&o.push(`${a}\u2026 (${e.children.length-6} more children)`),o.push(`${d}</${l}>`)}for(let a=t.length-1;a>=0;a--){let b=" ".repeat(a),g=t[a];g&&o.push(`${b}</${g.tagName.toLowerCase()}>`)}return o.join(`
2
+ `)},B=e=>{let t=e;for(;t;){if(t instanceof HTMLElement&&t.dataset.ynsFeedbackUi==="true")return!0;t=t.parentElement}return!1},Z=new Set(["HTML","HEAD","SCRIPT","STYLE","NOSCRIPT"]);function ee(){let[e,t]=C(null),[n,o]=C(!0),[i,d]=C(!1),[l,s]=C(null),[a,b]=C(null),[g,v]=C(!1),[k,y]=C(!1),c=X(null);$(()=>{if(c.current=G(),!c.current){o(!1);return}let r=new AbortController;return fetch(`${c.current}/api/feedback-comments?host=${encodeURIComponent(window.location.host)}`,{credentials:"include",signal:r.signal}).then(async u=>{if(!u.ok){t(null);return}let S=await u.json();t(S)}).catch(()=>{t(null)}).finally(()=>o(!1)),()=>r.abort()},[]),$(()=>{if(i)return document.body.style.cursor="crosshair",()=>{document.body.style.cursor=""}},[i]),$(()=>{if(!i)return;let r=document.createElement("div");r.dataset.ynsFeedbackUi="true",r.style.cssText=["position: fixed","pointer-events: none","z-index: 2147483644","border: 2px dashed #10b981","background: rgba(16, 185, 129, 0.08)","border-radius: 3px","display: none","transition: top 0.05s, left 0.05s, width 0.05s, height 0.05s"].join(";");let u=document.createElement("div");u.dataset.ynsFeedbackUi="true",u.textContent="Click to comment",u.style.cssText=["position: fixed","pointer-events: none","z-index: 2147483645","background: #059669","color: #fff","font-size: 11px","font-family: ui-sans-serif, system-ui, sans-serif","padding: 3px 8px","border-radius: 4px","white-space: nowrap","display: none","box-shadow: 0 2px 6px rgba(0,0,0,0.15)"].join(";"),document.documentElement.appendChild(r),document.documentElement.appendChild(u);let S=null,w=P=>{let L=document.elementFromPoint(P.clientX,P.clientY);if(!L||Z.has(L.tagName)||B(L)){r.style.display="none",u.style.display="none",S=null;return}S=L,requestAnimationFrame(()=>{if(S!==L)return;let I=L.getBoundingClientRect();r.style.top=`${I.top}px`,r.style.left=`${I.left}px`,r.style.width=`${I.width}px`,r.style.height=`${I.height}px`,r.style.display="block",u.style.left=`${P.clientX+14}px`,u.style.top=`${P.clientY+14}px`,u.style.display="block"})},R=()=>{r.style.display="none",u.style.display="none",S=null};return document.addEventListener("mousemove",w,!0),document.addEventListener("mouseleave",R),()=>{document.removeEventListener("mousemove",w,!0),document.removeEventListener("mouseleave",R),r.remove(),u.remove()}},[i]),$(()=>{if(!i)return;let r=u=>{let S=u.target;if(!(S instanceof Element)||B(S))return;u.preventDefault(),u.stopPropagation();let w=S.getBoundingClientRect(),R=w.width>0?(u.clientX-w.left)/w.width:.5,P=w.height>0?(u.clientY-w.top)/w.height:.5;s({cssSelector:K(S),pagePath:window.location.pathname,surroundingHtml:Q(S),rect:{top:w.top+window.scrollY,left:w.left+window.scrollX,width:w.width,height:w.height},clickX:u.clientX+window.scrollX,clickY:u.clientY+window.scrollY,offsetXRatio:Math.min(1,Math.max(0,R)),offsetYRatio:Math.min(1,Math.max(0,P))}),d(!1)};return document.addEventListener("click",r,{capture:!0}),()=>document.removeEventListener("click",r,{capture:!0})},[i]);let m=async()=>{if(!c.current)return;let r=await fetch(`${c.current}/api/feedback-comments?host=${encodeURIComponent(window.location.host)}`,{credentials:"include"});if(!r.ok)return;let u=await r.json();t(u)},p=async r=>{!c.current||!e||!l||!(await fetch(`${c.current}/api/feedback-comments`,{method:"POST",credentials:"include",headers:{"Content-Type":"application/json"},body:JSON.stringify({feedbackSessionId:e.feedbackSessionId,content:r,pagePath:l.pagePath,cssSelector:l.cssSelector,surroundingHtml:l.surroundingHtml,offsetXRatio:l.offsetXRatio,offsetYRatio:l.offsetYRatio})})).ok||(s(null),d(!0),await m())},h=async(r,u)=>{!c.current||!(await fetch(`${c.current}/api/feedback-comments/${r}`,{method:"PATCH",credentials:"include",headers:{"Content-Type":"application/json"},body:JSON.stringify({content:u})})).ok||(b(null),await m())},E=async r=>{!c.current||!(await fetch(`${c.current}/api/feedback-comments/${r}`,{method:"DELETE",credentials:"include"})).ok||await m()},V=async()=>{if(!(!c.current||!e)&&window.confirm("Finalize this feedback session? You won't be able to add more comments.")){y(!0);try{if(!(await fetch(`${c.current}/api/feedback-sessions/${e.feedbackSessionId}/finalize`,{method:"POST",credentials:"include"})).ok)return;t(u=>u&&{...u,canComment:!1})}finally{y(!1)}}},W=r=>{if(r.pagePath!==window.location.pathname){window.location.assign(r.pagePath);return}let u=null;try{u=document.querySelector(r.cssSelector)}catch{u=null}u&&(u.scrollIntoView({behavior:"smooth",block:"center"}),b(r.id))};if(n||!e||!e.canComment)return null;let M=e.comments.filter(r=>r.pagePath===window.location.pathname&&r.status!=="done");return x("div",{"data-yns-feedback-ui":"true",children:[M.map((r,u)=>f(te,{pin:r,number:u+1,editing:a===r.id,onStartEdit:()=>b(r.id),onCancelEdit:()=>b(null),onSave:S=>h(r.id,S),onRemove:()=>E(r.id)},r.id)),l&&f(ne,{pending:l,onCancel:()=>{s(null),d(!0)},onSave:r=>p(r)}),g&&f(oe,{comments:e.comments,currentPath:window.location.pathname,onClose:()=>v(!1),onSelect:W}),x("div",{style:se,children:[f("button",{type:"button",onClick:()=>d(r=>!r),style:i?re:j,children:i?"Cancel":"Add comment"}),f("button",{type:"button",onClick:()=>v(r=>!r),style:le,children:g?"Hide list":`List (${e.comments.length})`}),f("button",{type:"button",onClick:V,disabled:k,style:ae,children:k?"Finalizing\u2026":"Finalize"}),f("span",{style:de,children:i?"Click any element to comment":`${M.length} on this page`})]})]})}function te({pin:e,number:t,editing:n,onStartEdit:o,onCancelEdit:i,onSave:d,onRemove:l}){let s=ie(e.cssSelector,e.offsetXRatio,e.offsetYRatio);return s?x("div",{style:{position:"absolute",top:s.top,left:s.left,zIndex:2147483600,pointerEvents:"auto"},children:[f("button",{type:"button",onClick:o,style:D,title:e.content,children:t}),n&&f(Y,{initial:e.content,onCancel:i,onSave:d,onRemove:l})]}):null}function ne({pending:e,onCancel:t,onSave:n}){return x(Ce,{children:[f("div",{style:{position:"absolute",top:e.rect.top+e.rect.height*e.offsetYRatio-12,left:e.rect.left+e.rect.width*e.offsetXRatio-12,zIndex:2147483600,pointerEvents:"none"},children:f("div",{style:D,children:"\u2022"})}),f("div",{style:{position:"absolute",top:e.clickY+10,left:e.clickX+10,zIndex:2147483647},children:f(Y,{initial:"",onCancel:t,onSave:n})})]})}function oe({comments:e,currentPath:t,onClose:n,onSelect:o}){let i=new Map;for(let l of e){let s=i.get(l.pagePath)??[];s.push(l),i.set(l.pagePath,s)}let d=Array.from(i.keys()).sort((l,s)=>l===t?-1:s===t?1:l.localeCompare(s));return x("div",{style:ge,children:[x("div",{style:ye,children:[x("strong",{style:{fontSize:14},children:["Comments (",e.length,")"]}),f("button",{type:"button",onClick:n,style:U,children:"Close"})]}),f("div",{style:be,children:e.length===0?f("div",{style:he,children:"No comments yet. Click \u201CAdd comment\u201D to leave one."}):d.map(l=>x("div",{style:{marginBottom:12},children:[f("div",{style:ve,children:l===t?`${l} \xB7 current`:l}),(i.get(l)??[]).map((s,a)=>x("button",{type:"button",onClick:()=>o(s),style:Se,disabled:s.status==="done"&&!1,children:[f("span",{style:we,children:a+1}),f("span",{style:xe,children:s.content.length>140?`${s.content.slice(0,140)}\u2026`:s.content}),s.status==="done"&&f("span",{style:Ee,children:"done"})]},s.id))]},l))})]})}function Y({initial:e,onCancel:t,onSave:n,onRemove:o}){let[i,d]=C(e),[l,s]=C(!1),a=X(null);return $(()=>{let g=a.current;if(!g)return;g.focus();let v=g.value.length;g.setSelectionRange(v,v)},[]),x("form",{onSubmit:async g=>{g.preventDefault();let v=i.trim();if(v){s(!0);try{await n(v)}finally{s(!1)}}},style:ce,children:[f("textarea",{ref:a,value:i,onChange:g=>d(g.target.value),placeholder:"Leave a comment\u2026",style:ue,rows:3}),x("div",{style:pe,children:[o&&f("button",{type:"button",onClick:()=>o(),style:fe,disabled:l,children:"Delete"}),f("div",{style:{flex:1}}),f("button",{type:"button",onClick:t,style:U,disabled:l,children:"Cancel"}),f("button",{type:"submit",style:me,disabled:l||!i.trim(),children:l?"Saving\u2026":"Save"})]})]})}function ie(e,t,n){let[o,i]=C(null);return $(()=>{let d=()=>{let s=null;try{s=document.querySelector(e)}catch{s=null}if(!s){i(null);return}let a=s.getBoundingClientRect();i({top:a.top+window.scrollY+a.height*n-12,left:a.left+window.scrollX+a.width*t-12})};d();let l=new ResizeObserver(d);try{let s=document.querySelector(e);s&&l.observe(s)}catch{}return window.addEventListener("scroll",d,!0),window.addEventListener("resize",d),()=>{l.disconnect(),window.removeEventListener("scroll",d,!0),window.removeEventListener("resize",d)}},[e,t,n]),o}var se={position:"fixed",bottom:16,left:"50%",transform:"translateX(-50%)",zIndex:2147483646,display:"flex",alignItems:"center",gap:8,padding:"8px 12px",background:"rgba(17, 17, 17, 0.92)",color:"white",borderRadius:999,boxShadow:"0 8px 24px rgba(0,0,0,0.25)",fontFamily:'-apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Helvetica, Arial, sans-serif, "Apple Color Emoji", "Segoe UI Emoji"',fontSize:14,pointerEvents:"auto"},j={border:"none",background:"white",color:"#111",padding:"6px 12px",borderRadius:999,cursor:"pointer",fontWeight:600,fontSize:13},re={...j,background:"#ef4444",color:"white"},le={border:"1px solid rgba(255,255,255,0.4)",background:"transparent",color:"white",padding:"6px 12px",borderRadius:999,cursor:"pointer",fontWeight:500,fontSize:13},ae={border:"none",background:"#10b981",color:"white",padding:"6px 12px",borderRadius:999,cursor:"pointer",fontWeight:600,fontSize:13},de={opacity:.8,fontSize:12},D={width:24,height:24,borderRadius:999,background:"#10b981",color:"white",border:"2px solid white",cursor:"pointer",fontSize:12,fontWeight:700,boxShadow:"0 2px 6px rgba(0,0,0,0.3)",display:"inline-flex",alignItems:"center",justifyContent:"center",padding:0},ce={background:"white",border:"1px solid #e5e7eb",borderRadius:8,padding:12,width:280,boxShadow:"0 12px 32px rgba(0,0,0,0.18)",fontFamily:'-apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Helvetica, Arial, sans-serif, "Apple Color Emoji", "Segoe UI Emoji"',display:"flex",flexDirection:"column",gap:8,color:"#111"},ue={width:"100%",border:"1px solid #d1d5db",borderRadius:6,padding:8,fontSize:14,resize:"vertical",fontFamily:"inherit",color:"#111",background:"white",boxSizing:"border-box"},pe={display:"flex",alignItems:"center",gap:6},z={border:"1px solid transparent",borderRadius:6,padding:"6px 10px",fontSize:13,cursor:"pointer",fontWeight:500},me={...z,background:"#111",color:"white"},U={...z,background:"transparent",color:"#374151",borderColor:"#d1d5db"},fe={...z,background:"transparent",color:"#b91c1c",borderColor:"#fecaca"},ge={position:"fixed",top:0,right:0,bottom:0,width:360,maxWidth:"92vw",background:"white",borderLeft:"1px solid #e5e7eb",boxShadow:"-12px 0 32px rgba(0,0,0,0.12)",zIndex:2147483646,display:"flex",flexDirection:"column",fontFamily:'-apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Helvetica, Arial, sans-serif, "Apple Color Emoji", "Segoe UI Emoji"',color:"#111"},ye={display:"flex",alignItems:"center",justifyContent:"space-between",padding:"12px 16px",borderBottom:"1px solid #e5e7eb"},be={flex:1,overflow:"auto",padding:"12px 12px 24px"},he={color:"#6b7280",fontSize:13,padding:"24px 8px",textAlign:"center"},ve={fontSize:11,textTransform:"uppercase",letterSpacing:.5,color:"#6b7280",padding:"4px 4px 6px",wordBreak:"break-all"},Se={display:"flex",alignItems:"flex-start",gap:8,width:"100%",textAlign:"left",background:"white",border:"1px solid #e5e7eb",borderRadius:6,padding:"8px 10px",cursor:"pointer",fontSize:13,marginBottom:6,color:"#111"},we={flexShrink:0,width:22,height:22,borderRadius:999,background:"#10b981",color:"white",fontWeight:700,fontSize:11,display:"inline-flex",alignItems:"center",justifyContent:"center"},xe={flex:1,whiteSpace:"pre-wrap",wordBreak:"break-word"},Ee={flexShrink:0,background:"#d1fae5",color:"#065f46",fontSize:11,fontWeight:600,padding:"2px 6px",borderRadius:4,alignSelf:"center"};function _(){if(console.log("[YNS Feedback Toolbar] mountFeedbackToolbar() called",{isWindow:typeof window<"u",vercelEnv:process.env.NEXT_PUBLIC_VERCEL_ENV,alreadyMounted:typeof document<"u"&&!!document.getElementById(A)}),typeof window>"u")return null;if(process.env.NEXT_PUBLIC_VERCEL_ENV!=="preview")return console.log("[YNS Feedback Toolbar] gate failed \u2014 NEXT_PUBLIC_VERCEL_ENV is",process.env.NEXT_PUBLIC_VERCEL_ENV),null;if(document.getElementById(A))return null;let e=document.createElement("div");e.id=A,e.dataset.ynsFeedbackUi="true",document.body.appendChild(e);let t=q(e);return t.render(f(ee,{})),{unmount:()=>{t.unmount(),e.remove()}}}typeof window<"u"&&console.log("[YNS Feedback Toolbar] module evaluated",{vercelEnv:process.env.NEXT_PUBLIC_VERCEL_ENV,readyState:document.readyState,willAutoMount:process.env.NEXT_PUBLIC_VERCEL_ENV==="preview"});typeof window<"u"&&process.env.NEXT_PUBLIC_VERCEL_ENV==="preview"&&(document.readyState==="loading"?document.addEventListener("DOMContentLoaded",()=>{_()}):_());function O(){typeof window>"u"||(console.log("[YNS Sandbox Inspectors] module evaluated"),Le(),$e())}O();var ke=new Set(["HEAD","SCRIPT","STYLE","NOSCRIPT","HTML"]);function Pe(e){if(e.id)return`${e.tagName.toLowerCase()}#${CSS.escape(e.id)}`;let t=[],n=e;for(;n&&n!==document.body&&n!==document.documentElement;){let o=n.tagName.toLowerCase();if(n.id){t.unshift(`${o}#${CSS.escape(n.id)}`);break}let i=Array.from(n.classList).filter(s=>!s.startsWith("data-yns-"));i.length>0&&(o+=`.${i.map(s=>CSS.escape(s)).join(".")}`);let d=n.parentElement,l=n.tagName;if(d&&Array.from(d.children).filter(a=>a.tagName===l&&(i.length===0||i.every(b=>a.classList.contains(b)))).length>1){let a=Array.from(d.children).indexOf(n)+1;o+=`:nth-child(${a})`}t.unshift(o),n=n.parentElement}return t.join(" > ")}function H(e,t){let n=e.getBoundingClientRect(),o=window.getComputedStyle(e),i=(e.textContent??"").trim();return{tag:e.tagName.toLowerCase(),id:e.id||void 0,classes:Array.from(e.classList).filter(d=>!d.startsWith("data-yns-")),textContent:i.length>t?`${i.slice(0,t)}\u2026`:i,cssSelector:Pe(e),boundingRect:{top:n.top,left:n.left,width:n.width,height:n.height},computedStyles:{color:o.color,backgroundColor:o.backgroundColor,fontSize:o.fontSize,fontFamily:o.fontFamily,padding:o.padding,margin:o.margin}}}function T(e,t){if(!e||!e.tagName||ke.has(e.tagName))return!0;for(let n of t)if(e.hasAttribute?.(n))return!0;return!1}function Le(){let e=!1,t=null,n=null,o=document.createElement("div");o.setAttribute("data-yns-design-overlay","hover"),o.style.cssText=["position: fixed","pointer-events: none","z-index: 2147483646","border: 2px solid #3b82f6","background: rgba(59, 130, 246, 0.08)","border-radius: 3px","display: none","transition: top 0.05s, left 0.05s, width 0.05s, height 0.05s"].join(";");let i=document.createElement("div");i.setAttribute("data-yns-design-overlay","label"),i.style.cssText=["position: fixed","pointer-events: none","z-index: 2147483647","background: #3b82f6","color: #fff","font-size: 11px","font-family: ui-monospace, monospace","padding: 2px 6px","border-radius: 3px","white-space: nowrap","display: none"].join(";"),document.documentElement.appendChild(o),document.documentElement.appendChild(i);let d=document.createElement("style");d.setAttribute("data-yns-design-overlay","style"),d.textContent="[data-yns-selected] { outline: 2px solid #3b82f6 !important; outline-offset: 1px; }",document.head.appendChild(d);function l(y){let c=y.getBoundingClientRect();o.style.top=`${c.top}px`,o.style.left=`${c.left}px`,o.style.width=`${c.width}px`,o.style.height=`${c.height}px`,o.style.display="block";let m=Array.from(y.classList).filter(h=>!h.startsWith("data-yns-")),p=y.tagName.toLowerCase()+(m.length?`.${m[0]}`:"");i.textContent=p,i.style.left=`${c.left}px`,i.style.top=`${Math.max(0,c.top-22)}px`,i.style.display="block"}let s=y=>{let c=document.elementFromPoint(y.clientX,y.clientY);if(T(c,["data-yns-design-overlay"])){o.style.display="none",i.style.display="none",t=null;return}t=c,requestAnimationFrame(()=>{t===c&&e&&c&&l(c)})},a=()=>{o.style.display="none",i.style.display="none",t=null},b=y=>{if(!e||!t)return;y.preventDefault(),y.stopPropagation(),y.stopImmediatePropagation();let c=t;if(T(c,["data-yns-design-overlay"]))return;let m=H(c,120),p=m.cssSelector;n&&n.el.removeAttribute("data-yns-selected"),n&&n.cssSelector===p?(n=null,window.parent.postMessage({type:"element-deselected",data:m},"*")):(n={el:c,cssSelector:p},c.setAttribute("data-yns-selected",""),window.parent.postMessage({type:"element-selected",data:m},"*"))},g=y=>{y.key==="Escape"&&e&&(k(),window.parent.postMessage({type:"design-mode-cleared"},"*"))};function v(){e=!0,document.addEventListener("mousemove",s,!0),document.addEventListener("mouseleave",a),document.addEventListener("click",b,!0),document.addEventListener("keydown",g,!0)}function k(){e=!1,document.removeEventListener("mousemove",s,!0),document.removeEventListener("mouseleave",a),document.removeEventListener("click",b,!0),document.removeEventListener("keydown",g,!0),o.style.display="none",i.style.display="none",t=null,n&&(n.el.removeAttribute("data-yns-selected"),n=null)}window.addEventListener("message",y=>{let c=y.data;!c||typeof c!="object"||(c.type==="design-mode-toggle"&&(c.enabled?v():(k(),window.parent.postMessage({type:"design-mode-cleared"},"*"))),c.type==="design-mode-deselect"&&n&&(n.el.removeAttribute("data-yns-selected"),n=null))})}function $e(){let e=!1,t=null,n=[],o=document.createElement("div");o.setAttribute("data-yns-comment-overlay","hover"),o.style.cssText=["position: fixed","pointer-events: none","z-index: 2147483644","border: 2px dashed #10b981","background: rgba(16, 185, 129, 0.06)","border-radius: 3px","display: none","transition: top 0.05s, left 0.05s, width 0.05s, height 0.05s"].join(";");let i=document.createElement("div");i.setAttribute("data-yns-comment-overlay","cursor-label"),i.textContent="Click to comment",i.style.cssText=["position: fixed","pointer-events: none","z-index: 2147483645","background: #059669","color: #fff","font-size: 11px","font-family: ui-sans-serif, system-ui, sans-serif","padding: 3px 8px","border-radius: 4px","white-space: nowrap","display: none","box-shadow: 0 2px 6px rgba(0,0,0,0.15)"].join(";");let d=document.createElement("div");d.setAttribute("data-yns-comment-overlay","pins"),d.style.cssText="position: fixed; top: 0; left: 0; width: 100%; height: 100%; pointer-events: none; z-index: 2147483643;",document.documentElement.appendChild(o),document.documentElement.appendChild(i),document.documentElement.appendChild(d);function l(){d.innerHTML="";for(let m of n){let p=null;try{p=document.querySelector(m.selector)}catch{p=null}if(!p)continue;let h=p.getBoundingClientRect(),E=document.createElement("div");E.style.cssText=["position: fixed",`top: ${h.top-12}px`,`left: ${h.left+h.width/2-12}px`,"width: 24px","height: 24px","border-radius: 50%","background: #059669","color: #fff","display: flex","align-items: center","justify-content: center","font-size: 12px","font-weight: 600","font-family: ui-sans-serif, system-ui, sans-serif","box-shadow: 0 2px 8px rgba(0,0,0,0.2)","pointer-events: none"].join(";"),E.textContent=String(m.number),d.appendChild(E)}}let s=m=>{let p=document.elementFromPoint(m.clientX,m.clientY);if(T(p,["data-yns-comment-overlay","data-yns-design-overlay"])){o.style.display="none",i.style.display="none",t=null;return}t=p,requestAnimationFrame(()=>{if(t===p&&e&&p){let h=p.getBoundingClientRect();o.style.top=`${h.top}px`,o.style.left=`${h.left}px`,o.style.width=`${h.width}px`,o.style.height=`${h.height}px`,o.style.display="block",i.style.left=`${m.clientX+14}px`,i.style.top=`${m.clientY+14}px`,i.style.display="block"}})},a=()=>{o.style.display="none",i.style.display="none",t=null},b=m=>{if(!e||!t)return;m.preventDefault(),m.stopPropagation(),m.stopImmediatePropagation();let p=t;if(T(p,["data-yns-comment-overlay","data-yns-design-overlay"]))return;let h=H(p,200),E=p.getBoundingClientRect();window.parent.postMessage({type:"comment-click",data:{element:h,clickPosition:{x:m.clientX,y:m.clientY},elementRect:{top:E.top,left:E.left,width:E.width,height:E.height},pagePath:window.location.pathname}},"*")},g=m=>{m.key==="Escape"&&e&&(k(),window.parent.postMessage({type:"comment-mode-cleared"},"*"))};function v(){e=!0,document.body.style.cursor="crosshair",document.addEventListener("mousemove",s,!0),document.addEventListener("mouseleave",a),document.addEventListener("click",b,!0),document.addEventListener("keydown",g,!0)}function k(){e=!1,document.body.style.cursor="",document.removeEventListener("mousemove",s,!0),document.removeEventListener("mouseleave",a),document.removeEventListener("click",b,!0),document.removeEventListener("keydown",g,!0),o.style.display="none",i.style.display="none",t=null}let y=!1,c=()=>{y||(y=!0,requestAnimationFrame(()=>{y=!1,l()}))};window.addEventListener("scroll",c,{passive:!0}),window.addEventListener("resize",c,{passive:!0}),window.addEventListener("message",m=>{let p=m.data;!p||typeof p!="object"||(p.type==="comment-mode-toggle"&&(p.enabled?v():k()),p.type==="comment-pins-update"&&(n=p.pins??[],l()),p.type==="comment-pin-remove"&&(n=n.filter(h=>h.id!==p.pinId),l()))})}export{_ as mountFeedbackToolbar,O as startSandboxInspectors};
3
3
  //# sourceMappingURL=browser.js.map
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/feedback-toolbar.tsx","../src/sandbox-inspectors.ts"],"sourcesContent":["/**\n * Feedback session toolbar — side-effect entry.\n *\n * Importing `commerce-kit/feedback-toolbar` (or `commerce-kit/browser` for the\n * combined entry) mounts a floating toolbar onto the page that lets reviewers\n * leave click-anchored comments. Comments persist via YNS API endpoints,\n * authenticated with the `better-auth` session cookie sent through\n * `credentials: \"include\"`.\n *\n * Gated on `process.env.NEXT_PUBLIC_VERCEL_ENV === \"preview\"` — only Vercel\n * preview deploys get the toolbar. Sandbox dev (env undefined) and production\n * (env === \"production\") skip it.\n */\n\nimport { type CSSProperties, type FormEvent, useEffect, useRef, useState } from \"react\";\nimport { createRoot } from \"react-dom/client\";\n\nconst MOUNT_NODE_ID = \"yns-feedback-toolbar-root\";\n\ninterface FeedbackComment {\n\tid: string;\n\tpagePath: string;\n\tcssSelector: string;\n\tcontent: string;\n\tstatus: \"todo\" | \"done\";\n}\n\ninterface ActiveSession {\n\tfeedbackSessionId: string;\n\tcomments: FeedbackComment[];\n\tcanComment: boolean;\n}\n\ninterface PendingPin {\n\tcssSelector: string;\n\tpagePath: string;\n\tsurroundingHtml: string;\n\trect: { top: number; left: number; width: number; height: number };\n\tclickX: number;\n\tclickY: number;\n}\n\nconst buildApiBase = (): string | null => {\n\tif (typeof window === \"undefined\") return null;\n\tconst override = (process.env.NEXT_PUBLIC_YNS_API_BASE ?? \"\").trim();\n\tif (override) return override.replace(/\\/$/, \"\");\n\n\t// Toolbar runs on a per-store preview deploy (mystore-preview.yns.{store|cx})\n\t// served by the merchant's Vercel project — that host has no YNS API. Aim\n\t// at the apex `yns.store` / `yns.cx`, which yns-app serves and where the\n\t// API lives. Cookies scoped to `.yns.store` / `.yns.cx` travel along.\n\tconst host = window.location.hostname;\n\tconst protocol = window.location.protocol;\n\tif (host.endsWith(\".yns.store\")) return `${protocol}//yns.store`;\n\tif (host.endsWith(\".yns.cx\")) return `${protocol}//yns.cx`;\n\treturn window.location.origin;\n};\n\nconst computeCssSelector = (el: Element): string => {\n\tif (el.id) return `#${CSS.escape(el.id)}`;\n\tconst path: string[] = [];\n\tlet node: Element | null = el;\n\twhile (node && node.nodeType === Node.ELEMENT_NODE && path.length < 6) {\n\t\tlet part = node.tagName.toLowerCase();\n\t\tconst className = node.getAttribute(\"class\");\n\t\tif (className) {\n\t\t\tconst classes = className\n\t\t\t\t.split(/\\s+/)\n\t\t\t\t.filter(Boolean)\n\t\t\t\t.slice(0, 2)\n\t\t\t\t.map((c) => `.${CSS.escape(c)}`)\n\t\t\t\t.join(\"\");\n\t\t\tpart += classes;\n\t\t}\n\t\tconst parent: Element | null = node.parentElement;\n\t\tconst tag = node.tagName;\n\t\tif (parent) {\n\t\t\tconst siblings: Element[] = Array.from(parent.children).filter((c) => c.tagName === tag);\n\t\t\tif (siblings.length > 1) {\n\t\t\t\tconst idx = siblings.indexOf(node) + 1;\n\t\t\t\tpart += `:nth-of-type(${idx})`;\n\t\t\t}\n\t\t}\n\t\tpath.unshift(part);\n\t\tnode = parent;\n\t}\n\treturn path.join(\" > \");\n};\n\nconst ATTRS_OF_INTEREST = [\"id\", \"class\", \"data-testid\", \"aria-label\", \"role\", \"name\", \"href\", \"src\"];\n\nconst formatAttrs = (el: Element): string => {\n\tconst parts: string[] = [];\n\tfor (const attr of ATTRS_OF_INTEREST) {\n\t\tconst v = el.getAttribute(attr);\n\t\tif (!v) continue;\n\t\tconst trimmed = v.length > 80 ? `${v.slice(0, 80)}…` : v;\n\t\tparts.push(` ${attr}=\"${trimmed.replace(/\"/g, \"&quot;\")}\"`);\n\t}\n\treturn parts.join(\"\");\n};\n\nconst formatTextContent = (el: Element): string => {\n\tconst text = (el.textContent ?? \"\").replace(/\\s+/g, \" \").trim();\n\tif (!text) return \"\";\n\treturn text.length > 100 ? `${text.slice(0, 100)}…` : text;\n};\n\n/**\n * Build a compact HTML-like outline of the clicked element + its ancestors and a\n * sample of nearby children. Marks the target with `← TARGET` so the AI agent\n * can locate it later. Output stays small (< 2KB typical).\n */\nconst buildSurroundingHtml = (target: Element): string => {\n\tconst ancestors: Element[] = [];\n\tlet cur: Element | null = target;\n\twhile (cur && cur !== document.documentElement && ancestors.length < 5) {\n\t\tconst parent: Element | null = cur.parentElement;\n\t\tif (!parent) break;\n\t\tancestors.unshift(parent);\n\t\tcur = parent;\n\t}\n\n\tconst lines: string[] = [];\n\tlet depth = 0;\n\tfor (const ancestor of ancestors) {\n\t\tconst indent = \" \".repeat(depth);\n\t\tlines.push(`${indent}<${ancestor.tagName.toLowerCase()}${formatAttrs(ancestor)}>`);\n\t\tdepth++;\n\t}\n\n\tconst targetIndent = \" \".repeat(depth);\n\tconst targetTag = target.tagName.toLowerCase();\n\tconst targetText = formatTextContent(target);\n\tlines.push(\n\t\t`${targetIndent}<${targetTag}${formatAttrs(target)}>${\n\t\t\ttargetText ? `${targetText}</${targetTag}>` : \"\"\n\t\t} ← TARGET`,\n\t);\n\n\tif (!targetText) {\n\t\tconst childIndent = \" \".repeat(depth + 1);\n\t\tconst children = Array.from(target.children).slice(0, 6);\n\t\tfor (const child of children) {\n\t\t\tconst childText = formatTextContent(child);\n\t\t\tlines.push(\n\t\t\t\t`${childIndent}<${child.tagName.toLowerCase()}${formatAttrs(child)}>${\n\t\t\t\t\tchildText ? `${childText}</${child.tagName.toLowerCase()}>` : \"\"\n\t\t\t\t}`,\n\t\t\t);\n\t\t}\n\t\tif (target.children.length > 6) {\n\t\t\tlines.push(`${childIndent}… (${target.children.length - 6} more children)`);\n\t\t}\n\t\tlines.push(`${targetIndent}</${targetTag}>`);\n\t}\n\n\tfor (let i = ancestors.length - 1; i >= 0; i--) {\n\t\tconst indent = \" \".repeat(i);\n\t\tconst ancestor = ancestors[i];\n\t\tif (!ancestor) continue;\n\t\tlines.push(`${indent}</${ancestor.tagName.toLowerCase()}>`);\n\t}\n\n\treturn lines.join(\"\\n\");\n};\n\nconst isInsideToolbar = (el: Element | null): boolean => {\n\tlet node = el;\n\twhile (node) {\n\t\tif (node instanceof HTMLElement && node.dataset.ynsFeedbackUi === \"true\") return true;\n\t\tnode = node.parentElement;\n\t}\n\treturn false;\n};\n\nfunction FeedbackToolbar() {\n\tconst [session, setSession] = useState<ActiveSession | null>(null);\n\tconst [loading, setLoading] = useState(true);\n\tconst [pinMode, setPinMode] = useState(false);\n\tconst [pending, setPending] = useState<PendingPin | null>(null);\n\tconst [editingId, setEditingId] = useState<string | null>(null);\n\tconst apiBase = useRef<string | null>(null);\n\n\tuseEffect(() => {\n\t\tapiBase.current = buildApiBase();\n\t\tif (!apiBase.current) {\n\t\t\tsetLoading(false);\n\t\t\treturn;\n\t\t}\n\n\t\tconst controller = new AbortController();\n\t\tfetch(`${apiBase.current}/api/feedback-comments?host=${encodeURIComponent(window.location.host)}`, {\n\t\t\tcredentials: \"include\",\n\t\t\tsignal: controller.signal,\n\t\t})\n\t\t\t.then(async (res) => {\n\t\t\t\tif (!res.ok) {\n\t\t\t\t\tsetSession(null);\n\t\t\t\t\treturn;\n\t\t\t\t}\n\t\t\t\tconst data = (await res.json()) as ActiveSession;\n\t\t\t\tsetSession(data);\n\t\t\t})\n\t\t\t.catch(() => {\n\t\t\t\tsetSession(null);\n\t\t\t})\n\t\t\t.finally(() => setLoading(false));\n\n\t\treturn () => controller.abort();\n\t}, []);\n\n\tuseEffect(() => {\n\t\tif (!pinMode) return;\n\t\tdocument.body.style.cursor = \"crosshair\";\n\t\treturn () => {\n\t\t\tdocument.body.style.cursor = \"\";\n\t\t};\n\t}, [pinMode]);\n\n\tuseEffect(() => {\n\t\tif (!pinMode) return;\n\t\tconst handleClick = (event: MouseEvent) => {\n\t\t\tconst target = event.target;\n\t\t\tif (!(target instanceof Element)) return;\n\t\t\tif (isInsideToolbar(target)) return;\n\n\t\t\tevent.preventDefault();\n\t\t\tevent.stopPropagation();\n\n\t\t\tconst rect = target.getBoundingClientRect();\n\t\t\tsetPending({\n\t\t\t\tcssSelector: computeCssSelector(target),\n\t\t\t\tpagePath: window.location.pathname,\n\t\t\t\tsurroundingHtml: buildSurroundingHtml(target),\n\t\t\t\trect: {\n\t\t\t\t\ttop: rect.top + window.scrollY,\n\t\t\t\t\tleft: rect.left + window.scrollX,\n\t\t\t\t\twidth: rect.width,\n\t\t\t\t\theight: rect.height,\n\t\t\t\t},\n\t\t\t\tclickX: event.clientX + window.scrollX,\n\t\t\t\tclickY: event.clientY + window.scrollY,\n\t\t\t});\n\t\t\tsetPinMode(false);\n\t\t};\n\t\tdocument.addEventListener(\"click\", handleClick, { capture: true });\n\t\treturn () => document.removeEventListener(\"click\", handleClick, { capture: true });\n\t}, [pinMode]);\n\n\tconst refreshComments = async () => {\n\t\tif (!apiBase.current) return;\n\t\tconst res = await fetch(\n\t\t\t`${apiBase.current}/api/feedback-comments?host=${encodeURIComponent(window.location.host)}`,\n\t\t\t{ credentials: \"include\" },\n\t\t);\n\t\tif (!res.ok) return;\n\t\tconst data = (await res.json()) as ActiveSession;\n\t\tsetSession(data);\n\t};\n\n\tconst submitNewComment = async (content: string) => {\n\t\tif (!apiBase.current || !session || !pending) return;\n\t\tconst res = await fetch(`${apiBase.current}/api/feedback-comments`, {\n\t\t\tmethod: \"POST\",\n\t\t\tcredentials: \"include\",\n\t\t\theaders: { \"Content-Type\": \"application/json\" },\n\t\t\tbody: JSON.stringify({\n\t\t\t\tfeedbackSessionId: session.feedbackSessionId,\n\t\t\t\tcontent,\n\t\t\t\tpagePath: pending.pagePath,\n\t\t\t\tcssSelector: pending.cssSelector,\n\t\t\t\tsurroundingHtml: pending.surroundingHtml,\n\t\t\t}),\n\t\t});\n\t\tif (!res.ok) return;\n\t\tsetPending(null);\n\t\tawait refreshComments();\n\t};\n\n\tconst updateComment = async (id: string, content: string) => {\n\t\tif (!apiBase.current) return;\n\t\tconst res = await fetch(`${apiBase.current}/api/feedback-comments/${id}`, {\n\t\t\tmethod: \"PATCH\",\n\t\t\tcredentials: \"include\",\n\t\t\theaders: { \"Content-Type\": \"application/json\" },\n\t\t\tbody: JSON.stringify({ content }),\n\t\t});\n\t\tif (!res.ok) return;\n\t\tsetEditingId(null);\n\t\tawait refreshComments();\n\t};\n\n\tconst removeComment = async (id: string) => {\n\t\tif (!apiBase.current) return;\n\t\tconst res = await fetch(`${apiBase.current}/api/feedback-comments/${id}`, {\n\t\t\tmethod: \"DELETE\",\n\t\t\tcredentials: \"include\",\n\t\t});\n\t\tif (!res.ok) return;\n\t\tawait refreshComments();\n\t};\n\n\tif (loading || !session || !session.canComment) return null;\n\n\tconst visiblePins = session.comments.filter(\n\t\t(c) => c.pagePath === window.location.pathname && c.status !== \"done\",\n\t);\n\n\treturn (\n\t\t<div data-yns-feedback-ui=\"true\">\n\t\t\t{visiblePins.map((pin, idx) => (\n\t\t\t\t<PinOverlay\n\t\t\t\t\tkey={pin.id}\n\t\t\t\t\tpin={pin}\n\t\t\t\t\tnumber={idx + 1}\n\t\t\t\t\tediting={editingId === pin.id}\n\t\t\t\t\tonStartEdit={() => setEditingId(pin.id)}\n\t\t\t\t\tonCancelEdit={() => setEditingId(null)}\n\t\t\t\t\tonSave={(content) => updateComment(pin.id, content)}\n\t\t\t\t\tonRemove={() => removeComment(pin.id)}\n\t\t\t\t/>\n\t\t\t))}\n\n\t\t\t{pending && (\n\t\t\t\t<PendingCommentPopover\n\t\t\t\t\tpending={pending}\n\t\t\t\t\tonCancel={() => setPending(null)}\n\t\t\t\t\tonSave={(content) => submitNewComment(content)}\n\t\t\t\t/>\n\t\t\t)}\n\n\t\t\t<div style={toolbarStyle}>\n\t\t\t\t<button\n\t\t\t\t\ttype=\"button\"\n\t\t\t\t\tonClick={() => setPinMode((v) => !v)}\n\t\t\t\t\tstyle={pinMode ? toolbarButtonActiveStyle : toolbarButtonStyle}\n\t\t\t\t>\n\t\t\t\t\t{pinMode ? \"Cancel\" : \"Add comment\"}\n\t\t\t\t</button>\n\t\t\t\t<span style={toolbarHintStyle}>\n\t\t\t\t\t{pinMode ? \"Click any element to comment\" : `${visiblePins.length} on this page`}\n\t\t\t\t</span>\n\t\t\t</div>\n\t\t</div>\n\t);\n}\n\nfunction PinOverlay({\n\tpin,\n\tnumber,\n\tediting,\n\tonStartEdit,\n\tonCancelEdit,\n\tonSave,\n\tonRemove,\n}: {\n\tpin: FeedbackComment;\n\tnumber: number;\n\tediting: boolean;\n\tonStartEdit: () => void;\n\tonCancelEdit: () => void;\n\tonSave: (content: string) => Promise<void>;\n\tonRemove: () => Promise<void>;\n}) {\n\tconst target = useTargetRect(pin.cssSelector);\n\tif (!target) return null;\n\n\treturn (\n\t\t<div\n\t\t\tstyle={{\n\t\t\t\tposition: \"absolute\",\n\t\t\t\ttop: target.top,\n\t\t\t\tleft: target.left,\n\t\t\t\tzIndex: 2147483600,\n\t\t\t\tpointerEvents: \"auto\",\n\t\t\t}}\n\t\t>\n\t\t\t<button type=\"button\" onClick={onStartEdit} style={pinDotStyle} title={pin.content}>\n\t\t\t\t{number}\n\t\t\t</button>\n\t\t\t{editing && (\n\t\t\t\t<EditPopover initial={pin.content} onCancel={onCancelEdit} onSave={onSave} onRemove={onRemove} />\n\t\t\t)}\n\t\t</div>\n\t);\n}\n\nfunction PendingCommentPopover({\n\tpending,\n\tonCancel,\n\tonSave,\n}: {\n\tpending: PendingPin;\n\tonCancel: () => void;\n\tonSave: (content: string) => Promise<void>;\n}) {\n\treturn (\n\t\t<div\n\t\t\tstyle={{\n\t\t\t\tposition: \"absolute\",\n\t\t\t\ttop: pending.clickY + 10,\n\t\t\t\tleft: pending.clickX + 10,\n\t\t\t\tzIndex: 2147483647,\n\t\t\t}}\n\t\t>\n\t\t\t<EditPopover initial=\"\" onCancel={onCancel} onSave={onSave} />\n\t\t</div>\n\t);\n}\n\nfunction EditPopover({\n\tinitial,\n\tonCancel,\n\tonSave,\n\tonRemove,\n}: {\n\tinitial: string;\n\tonCancel: () => void;\n\tonSave: (content: string) => Promise<void>;\n\tonRemove?: () => Promise<void>;\n}) {\n\tconst [value, setValue] = useState(initial);\n\tconst [saving, setSaving] = useState(false);\n\n\tconst handleSubmit = async (e: FormEvent) => {\n\t\te.preventDefault();\n\t\tconst content = value.trim();\n\t\tif (!content) return;\n\t\tsetSaving(true);\n\t\ttry {\n\t\t\tawait onSave(content);\n\t\t} finally {\n\t\t\tsetSaving(false);\n\t\t}\n\t};\n\n\treturn (\n\t\t<form onSubmit={handleSubmit} style={popoverStyle}>\n\t\t\t<textarea\n\t\t\t\tvalue={value}\n\t\t\t\tonChange={(e) => setValue(e.target.value)}\n\t\t\t\tplaceholder=\"Leave a comment…\"\n\t\t\t\tstyle={textareaStyle}\n\t\t\t\trows={3}\n\t\t\t/>\n\t\t\t<div style={popoverActionsStyle}>\n\t\t\t\t{onRemove && (\n\t\t\t\t\t<button type=\"button\" onClick={() => onRemove()} style={dangerButtonStyle} disabled={saving}>\n\t\t\t\t\t\tDelete\n\t\t\t\t\t</button>\n\t\t\t\t)}\n\t\t\t\t<div style={{ flex: 1 }} />\n\t\t\t\t<button type=\"button\" onClick={onCancel} style={ghostButtonStyle} disabled={saving}>\n\t\t\t\t\tCancel\n\t\t\t\t</button>\n\t\t\t\t<button type=\"submit\" style={primaryButtonStyle} disabled={saving || !value.trim()}>\n\t\t\t\t\t{saving ? \"Saving…\" : \"Save\"}\n\t\t\t\t</button>\n\t\t\t</div>\n\t\t</form>\n\t);\n}\n\nfunction useTargetRect(selector: string) {\n\tconst [rect, setRect] = useState<{ top: number; left: number } | null>(null);\n\n\tuseEffect(() => {\n\t\tconst update = () => {\n\t\t\tlet el: Element | null = null;\n\t\t\ttry {\n\t\t\t\tel = document.querySelector(selector);\n\t\t\t} catch {\n\t\t\t\tel = null;\n\t\t\t}\n\t\t\tif (!el) {\n\t\t\t\tsetRect(null);\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tconst r = el.getBoundingClientRect();\n\t\t\tsetRect({ top: r.top + window.scrollY - 12, left: r.left + window.scrollX - 12 });\n\t\t};\n\n\t\tupdate();\n\t\tconst ro = new ResizeObserver(update);\n\t\ttry {\n\t\t\tconst el = document.querySelector(selector);\n\t\t\tif (el) ro.observe(el);\n\t\t} catch {\n\t\t\t// swallow invalid selector\n\t\t}\n\t\twindow.addEventListener(\"scroll\", update, true);\n\t\twindow.addEventListener(\"resize\", update);\n\t\treturn () => {\n\t\t\tro.disconnect();\n\t\t\twindow.removeEventListener(\"scroll\", update, true);\n\t\t\twindow.removeEventListener(\"resize\", update);\n\t\t};\n\t}, [selector]);\n\n\treturn rect;\n}\n\n// Inline styles — toolbar is injected into arbitrary stores, so we avoid relying\n// on any CSS framework being present.\nconst toolbarStyle: CSSProperties = {\n\tposition: \"fixed\",\n\tbottom: 16,\n\tleft: \"50%\",\n\ttransform: \"translateX(-50%)\",\n\tzIndex: 2147483646,\n\tdisplay: \"flex\",\n\talignItems: \"center\",\n\tgap: 12,\n\tpadding: \"8px 12px\",\n\tbackground: \"rgba(17, 17, 17, 0.92)\",\n\tcolor: \"white\",\n\tborderRadius: 999,\n\tboxShadow: \"0 8px 24px rgba(0,0,0,0.25)\",\n\tfontFamily:\n\t\t'-apple-system, BlinkMacSystemFont, \"Segoe UI\", Roboto, Helvetica, Arial, sans-serif, \"Apple Color Emoji\", \"Segoe UI Emoji\"',\n\tfontSize: 14,\n\tpointerEvents: \"auto\",\n};\n\nconst toolbarButtonStyle: CSSProperties = {\n\tborder: \"none\",\n\tbackground: \"white\",\n\tcolor: \"#111\",\n\tpadding: \"6px 12px\",\n\tborderRadius: 999,\n\tcursor: \"pointer\",\n\tfontWeight: 600,\n\tfontSize: 13,\n};\n\nconst toolbarButtonActiveStyle: CSSProperties = {\n\t...toolbarButtonStyle,\n\tbackground: \"#ef4444\",\n\tcolor: \"white\",\n};\n\nconst toolbarHintStyle: CSSProperties = {\n\topacity: 0.8,\n\tfontSize: 12,\n};\n\nconst pinDotStyle: CSSProperties = {\n\twidth: 24,\n\theight: 24,\n\tborderRadius: 999,\n\tbackground: \"#10b981\",\n\tcolor: \"white\",\n\tborder: \"2px solid white\",\n\tcursor: \"pointer\",\n\tfontSize: 12,\n\tfontWeight: 700,\n\tboxShadow: \"0 2px 6px rgba(0,0,0,0.3)\",\n\tdisplay: \"inline-flex\",\n\talignItems: \"center\",\n\tjustifyContent: \"center\",\n\tpadding: 0,\n};\n\nconst popoverStyle: CSSProperties = {\n\tbackground: \"white\",\n\tborder: \"1px solid #e5e7eb\",\n\tborderRadius: 8,\n\tpadding: 12,\n\twidth: 280,\n\tboxShadow: \"0 12px 32px rgba(0,0,0,0.18)\",\n\tfontFamily:\n\t\t'-apple-system, BlinkMacSystemFont, \"Segoe UI\", Roboto, Helvetica, Arial, sans-serif, \"Apple Color Emoji\", \"Segoe UI Emoji\"',\n\tdisplay: \"flex\",\n\tflexDirection: \"column\",\n\tgap: 8,\n\tcolor: \"#111\",\n};\n\nconst textareaStyle: CSSProperties = {\n\twidth: \"100%\",\n\tborder: \"1px solid #d1d5db\",\n\tborderRadius: 6,\n\tpadding: 8,\n\tfontSize: 14,\n\tresize: \"vertical\",\n\tfontFamily: \"inherit\",\n\tcolor: \"#111\",\n\tbackground: \"white\",\n\tboxSizing: \"border-box\",\n};\n\nconst popoverActionsStyle: CSSProperties = {\n\tdisplay: \"flex\",\n\talignItems: \"center\",\n\tgap: 6,\n};\n\nconst baseButton: CSSProperties = {\n\tborder: \"1px solid transparent\",\n\tborderRadius: 6,\n\tpadding: \"6px 10px\",\n\tfontSize: 13,\n\tcursor: \"pointer\",\n\tfontWeight: 500,\n};\n\nconst primaryButtonStyle: CSSProperties = {\n\t...baseButton,\n\tbackground: \"#111\",\n\tcolor: \"white\",\n};\n\nconst ghostButtonStyle: CSSProperties = {\n\t...baseButton,\n\tbackground: \"transparent\",\n\tcolor: \"#374151\",\n\tborderColor: \"#d1d5db\",\n};\n\nconst dangerButtonStyle: CSSProperties = {\n\t...baseButton,\n\tbackground: \"transparent\",\n\tcolor: \"#b91c1c\",\n\tborderColor: \"#fecaca\",\n};\n\nexport function mountFeedbackToolbar(): { unmount: () => void } | null {\n\tconsole.log(\"[YNS Feedback Toolbar] mountFeedbackToolbar() called\", {\n\t\tisWindow: typeof window !== \"undefined\",\n\t\tvercelEnv: process.env.NEXT_PUBLIC_VERCEL_ENV,\n\t\talreadyMounted: typeof document !== \"undefined\" && Boolean(document.getElementById(MOUNT_NODE_ID)),\n\t});\n\tif (typeof window === \"undefined\") return null;\n\tif (process.env.NEXT_PUBLIC_VERCEL_ENV !== \"preview\") {\n\t\tconsole.log(\n\t\t\t\"[YNS Feedback Toolbar] gate failed — NEXT_PUBLIC_VERCEL_ENV is\",\n\t\t\tprocess.env.NEXT_PUBLIC_VERCEL_ENV,\n\t\t);\n\t\treturn null;\n\t}\n\tif (document.getElementById(MOUNT_NODE_ID)) return null;\n\n\tconst container = document.createElement(\"div\");\n\tcontainer.id = MOUNT_NODE_ID;\n\tcontainer.dataset.ynsFeedbackUi = \"true\";\n\tdocument.body.appendChild(container);\n\n\tconst root = createRoot(container);\n\troot.render(<FeedbackToolbar />);\n\n\treturn {\n\t\tunmount: () => {\n\t\t\troot.unmount();\n\t\t\tcontainer.remove();\n\t\t},\n\t};\n}\n\n// Auto-mount on import. Wait for DOM ready.\nif (typeof window !== \"undefined\") {\n\tconsole.log(\"[YNS Feedback Toolbar] module evaluated\", {\n\t\tvercelEnv: process.env.NEXT_PUBLIC_VERCEL_ENV,\n\t\treadyState: document.readyState,\n\t\twillAutoMount: process.env.NEXT_PUBLIC_VERCEL_ENV === \"preview\",\n\t});\n}\nif (typeof window !== \"undefined\" && process.env.NEXT_PUBLIC_VERCEL_ENV === \"preview\") {\n\tif (document.readyState === \"loading\") {\n\t\tdocument.addEventListener(\"DOMContentLoaded\", () => {\n\t\t\tmountFeedbackToolbar();\n\t\t});\n\t} else {\n\t\tmountFeedbackToolbar();\n\t}\n}\n","/**\n * Sandbox Inspectors — side-effect entry.\n *\n * Auto-mounts the design-mode + comment-mode inspectors inside per-store\n * storefronts running under the AI Builder sandbox dev server. Communicates\n * with the parent /design iframe via postMessage.\n *\n * Always-on: inspectors are passive postMessage listeners and don't affect the\n * page until the AI Builder iframe sends a `*-mode-toggle` message. Gating on\n * NODE_ENV is wrong (always \"production\" on Vercel) and any build-time gate\n * gets folded out by the commerce-kit bundle, leaving an empty file.\n */\n\n/**\n * Exported so `browser.tsx` can `export { startSandboxInspectors }` — the\n * named binding anchors this module against esbuild tree-shaking when\n * commerce-kit is bundled. Without it, an `export * from \"./sandbox-inspectors\"`\n * re-exports an empty binding set and esbuild DCEs the whole file.\n */\nexport function startSandboxInspectors(): void {\n\tif (typeof window === \"undefined\") return;\n\tconsole.log(\"[YNS Sandbox Inspectors] module evaluated\");\n\tinitDesignModeInspector();\n\tinitCommentModeInspector();\n}\n\n// Auto-start on import.\nstartSandboxInspectors();\n\ninterface ElementInfo {\n\ttag: string;\n\tid: string | undefined;\n\tclasses: string[];\n\ttextContent: string;\n\tcssSelector: string;\n\tboundingRect: { top: number; left: number; width: number; height: number };\n\tcomputedStyles: Partial<{\n\t\tcolor: string;\n\t\tbackgroundColor: string;\n\t\tfontSize: string;\n\t\tfontFamily: string;\n\t\tpadding: string;\n\t\tmargin: string;\n\t}>;\n}\n\nconst IGNORED_TAGS = new Set([\"HEAD\", \"SCRIPT\", \"STYLE\", \"NOSCRIPT\", \"HTML\"]);\n\nfunction generateCssSelector(el: Element): string {\n\tif (el.id) return `${el.tagName.toLowerCase()}#${CSS.escape(el.id)}`;\n\n\tconst parts: string[] = [];\n\tlet current: Element | null = el;\n\twhile (current && current !== document.body && current !== document.documentElement) {\n\t\tlet selector = current.tagName.toLowerCase();\n\n\t\tif (current.id) {\n\t\t\tparts.unshift(`${selector}#${CSS.escape(current.id)}`);\n\t\t\tbreak;\n\t\t}\n\n\t\tconst classes = Array.from(current.classList).filter((c) => !c.startsWith(\"data-yns-\"));\n\t\tif (classes.length > 0) {\n\t\t\tselector += `.${classes.map((c) => CSS.escape(c)).join(\".\")}`;\n\t\t}\n\n\t\tconst parent: Element | null = current.parentElement;\n\t\tconst tag = current.tagName;\n\t\tif (parent) {\n\t\t\tconst siblings = Array.from(parent.children).filter(\n\t\t\t\t(s) => s.tagName === tag && (classes.length === 0 || classes.every((c) => s.classList.contains(c))),\n\t\t\t);\n\t\t\tif (siblings.length > 1) {\n\t\t\t\tconst index = Array.from(parent.children).indexOf(current) + 1;\n\t\t\t\tselector += `:nth-child(${index})`;\n\t\t\t}\n\t\t}\n\n\t\tparts.unshift(selector);\n\t\tcurrent = current.parentElement;\n\t}\n\treturn parts.join(\" > \");\n}\n\nfunction buildElementInfo(el: Element, textLimit: number): ElementInfo {\n\tconst rect = el.getBoundingClientRect();\n\tconst computed = window.getComputedStyle(el);\n\tconst text = (el.textContent ?? \"\").trim();\n\treturn {\n\t\ttag: el.tagName.toLowerCase(),\n\t\tid: el.id || undefined,\n\t\tclasses: Array.from(el.classList).filter((c) => !c.startsWith(\"data-yns-\")),\n\t\ttextContent: text.length > textLimit ? `${text.slice(0, textLimit)}…` : text,\n\t\tcssSelector: generateCssSelector(el),\n\t\tboundingRect: { top: rect.top, left: rect.left, width: rect.width, height: rect.height },\n\t\tcomputedStyles: {\n\t\t\tcolor: computed.color,\n\t\t\tbackgroundColor: computed.backgroundColor,\n\t\t\tfontSize: computed.fontSize,\n\t\t\tfontFamily: computed.fontFamily,\n\t\t\tpadding: computed.padding,\n\t\t\tmargin: computed.margin,\n\t\t},\n\t};\n}\n\nfunction shouldIgnore(el: Element | null, overlayAttrs: string[]): el is null {\n\tif (!el || !el.tagName) return true;\n\tif (IGNORED_TAGS.has(el.tagName)) return true;\n\tfor (const attr of overlayAttrs) {\n\t\tif (el.hasAttribute?.(attr)) return true;\n\t}\n\treturn false;\n}\n\nfunction initDesignModeInspector() {\n\tlet enabled = false;\n\tlet hoveredElement: Element | null = null;\n\tlet selectedElement: { el: Element; cssSelector: string } | null = null;\n\n\tconst overlay = document.createElement(\"div\");\n\toverlay.setAttribute(\"data-yns-design-overlay\", \"hover\");\n\toverlay.style.cssText = [\n\t\t\"position: fixed\",\n\t\t\"pointer-events: none\",\n\t\t\"z-index: 2147483646\",\n\t\t\"border: 2px solid #3b82f6\",\n\t\t\"background: rgba(59, 130, 246, 0.08)\",\n\t\t\"border-radius: 3px\",\n\t\t\"display: none\",\n\t\t\"transition: top 0.05s, left 0.05s, width 0.05s, height 0.05s\",\n\t].join(\";\");\n\n\tconst label = document.createElement(\"div\");\n\tlabel.setAttribute(\"data-yns-design-overlay\", \"label\");\n\tlabel.style.cssText = [\n\t\t\"position: fixed\",\n\t\t\"pointer-events: none\",\n\t\t\"z-index: 2147483647\",\n\t\t\"background: #3b82f6\",\n\t\t\"color: #fff\",\n\t\t\"font-size: 11px\",\n\t\t\"font-family: ui-monospace, monospace\",\n\t\t\"padding: 2px 6px\",\n\t\t\"border-radius: 3px\",\n\t\t\"white-space: nowrap\",\n\t\t\"display: none\",\n\t].join(\";\");\n\n\tdocument.documentElement.appendChild(overlay);\n\tdocument.documentElement.appendChild(label);\n\n\tconst style = document.createElement(\"style\");\n\tstyle.setAttribute(\"data-yns-design-overlay\", \"style\");\n\tstyle.textContent = \"[data-yns-selected] { outline: 2px solid #3b82f6 !important; outline-offset: 1px; }\";\n\tdocument.head.appendChild(style);\n\n\tfunction positionOverlay(el: Element) {\n\t\tconst rect = el.getBoundingClientRect();\n\t\toverlay.style.top = `${rect.top}px`;\n\t\toverlay.style.left = `${rect.left}px`;\n\t\toverlay.style.width = `${rect.width}px`;\n\t\toverlay.style.height = `${rect.height}px`;\n\t\toverlay.style.display = \"block\";\n\n\t\tconst classes = Array.from(el.classList).filter((c) => !c.startsWith(\"data-yns-\"));\n\t\tconst labelText = el.tagName.toLowerCase() + (classes.length ? `.${classes[0]}` : \"\");\n\t\tlabel.textContent = labelText;\n\t\tlabel.style.left = `${rect.left}px`;\n\t\tlabel.style.top = `${Math.max(0, rect.top - 22)}px`;\n\t\tlabel.style.display = \"block\";\n\t}\n\n\tconst handleMouseMove = (e: MouseEvent) => {\n\t\tconst el = document.elementFromPoint(e.clientX, e.clientY);\n\t\tif (shouldIgnore(el, [\"data-yns-design-overlay\"])) {\n\t\t\toverlay.style.display = \"none\";\n\t\t\tlabel.style.display = \"none\";\n\t\t\thoveredElement = null;\n\t\t\treturn;\n\t\t}\n\t\thoveredElement = el;\n\t\trequestAnimationFrame(() => {\n\t\t\tif (hoveredElement === el && enabled && el) {\n\t\t\t\tpositionOverlay(el);\n\t\t\t}\n\t\t});\n\t};\n\n\tconst handleMouseLeave = () => {\n\t\toverlay.style.display = \"none\";\n\t\tlabel.style.display = \"none\";\n\t\thoveredElement = null;\n\t};\n\n\tconst handleClick = (e: MouseEvent) => {\n\t\tif (!enabled || !hoveredElement) return;\n\t\te.preventDefault();\n\t\te.stopPropagation();\n\t\te.stopImmediatePropagation();\n\n\t\tconst el = hoveredElement;\n\t\tif (shouldIgnore(el, [\"data-yns-design-overlay\"])) return;\n\n\t\tconst info = buildElementInfo(el, 120);\n\t\tconst selector = info.cssSelector;\n\n\t\tif (selectedElement) {\n\t\t\tselectedElement.el.removeAttribute(\"data-yns-selected\");\n\t\t}\n\n\t\tif (selectedElement && selectedElement.cssSelector === selector) {\n\t\t\tselectedElement = null;\n\t\t\twindow.parent.postMessage({ type: \"element-deselected\", data: info }, \"*\");\n\t\t} else {\n\t\t\tselectedElement = { el, cssSelector: selector };\n\t\t\tel.setAttribute(\"data-yns-selected\", \"\");\n\t\t\twindow.parent.postMessage({ type: \"element-selected\", data: info }, \"*\");\n\t\t}\n\t};\n\n\tconst handleKeyDown = (e: KeyboardEvent) => {\n\t\tif (e.key === \"Escape\" && enabled) {\n\t\t\tdisableDesignMode();\n\t\t\twindow.parent.postMessage({ type: \"design-mode-cleared\" }, \"*\");\n\t\t}\n\t};\n\n\tfunction enableDesignMode() {\n\t\tenabled = true;\n\t\tdocument.addEventListener(\"mousemove\", handleMouseMove, true);\n\t\tdocument.addEventListener(\"mouseleave\", handleMouseLeave);\n\t\tdocument.addEventListener(\"click\", handleClick, true);\n\t\tdocument.addEventListener(\"keydown\", handleKeyDown, true);\n\t}\n\n\tfunction disableDesignMode() {\n\t\tenabled = false;\n\t\tdocument.removeEventListener(\"mousemove\", handleMouseMove, true);\n\t\tdocument.removeEventListener(\"mouseleave\", handleMouseLeave);\n\t\tdocument.removeEventListener(\"click\", handleClick, true);\n\t\tdocument.removeEventListener(\"keydown\", handleKeyDown, true);\n\n\t\toverlay.style.display = \"none\";\n\t\tlabel.style.display = \"none\";\n\t\thoveredElement = null;\n\n\t\tif (selectedElement) {\n\t\t\tselectedElement.el.removeAttribute(\"data-yns-selected\");\n\t\t\tselectedElement = null;\n\t\t}\n\t}\n\n\twindow.addEventListener(\"message\", (event) => {\n\t\tconst msg = event.data;\n\t\tif (!msg || typeof msg !== \"object\") return;\n\n\t\tif (msg.type === \"design-mode-toggle\") {\n\t\t\tif (msg.enabled) {\n\t\t\t\tenableDesignMode();\n\t\t\t} else {\n\t\t\t\tdisableDesignMode();\n\t\t\t\twindow.parent.postMessage({ type: \"design-mode-cleared\" }, \"*\");\n\t\t\t}\n\t\t}\n\n\t\tif (msg.type === \"design-mode-deselect\") {\n\t\t\tif (selectedElement) {\n\t\t\t\tselectedElement.el.removeAttribute(\"data-yns-selected\");\n\t\t\t\tselectedElement = null;\n\t\t\t}\n\t\t}\n\t});\n}\n\nfunction initCommentModeInspector() {\n\tlet enabled = false;\n\tlet hoveredElement: Element | null = null;\n\tlet pins: Array<{ id: string; selector: string; number: number }> = [];\n\n\tconst overlay = document.createElement(\"div\");\n\toverlay.setAttribute(\"data-yns-comment-overlay\", \"hover\");\n\toverlay.style.cssText = [\n\t\t\"position: fixed\",\n\t\t\"pointer-events: none\",\n\t\t\"z-index: 2147483644\",\n\t\t\"border: 2px dashed #10b981\",\n\t\t\"background: rgba(16, 185, 129, 0.06)\",\n\t\t\"border-radius: 3px\",\n\t\t\"display: none\",\n\t\t\"transition: top 0.05s, left 0.05s, width 0.05s, height 0.05s\",\n\t].join(\";\");\n\n\tconst cursorLabel = document.createElement(\"div\");\n\tcursorLabel.setAttribute(\"data-yns-comment-overlay\", \"cursor-label\");\n\tcursorLabel.textContent = \"Click to comment\";\n\tcursorLabel.style.cssText = [\n\t\t\"position: fixed\",\n\t\t\"pointer-events: none\",\n\t\t\"z-index: 2147483645\",\n\t\t\"background: #059669\",\n\t\t\"color: #fff\",\n\t\t\"font-size: 11px\",\n\t\t\"font-family: ui-sans-serif, system-ui, sans-serif\",\n\t\t\"padding: 3px 8px\",\n\t\t\"border-radius: 4px\",\n\t\t\"white-space: nowrap\",\n\t\t\"display: none\",\n\t\t\"box-shadow: 0 2px 6px rgba(0,0,0,0.15)\",\n\t].join(\";\");\n\n\tconst pinContainer = document.createElement(\"div\");\n\tpinContainer.setAttribute(\"data-yns-comment-overlay\", \"pins\");\n\tpinContainer.style.cssText =\n\t\t\"position: fixed; top: 0; left: 0; width: 100%; height: 100%; pointer-events: none; z-index: 2147483643;\";\n\n\tdocument.documentElement.appendChild(overlay);\n\tdocument.documentElement.appendChild(cursorLabel);\n\tdocument.documentElement.appendChild(pinContainer);\n\n\tfunction renderPins() {\n\t\tpinContainer.innerHTML = \"\";\n\t\tfor (const pin of pins) {\n\t\t\tlet el: Element | null = null;\n\t\t\ttry {\n\t\t\t\tel = document.querySelector(pin.selector);\n\t\t\t} catch {\n\t\t\t\tel = null;\n\t\t\t}\n\t\t\tif (!el) continue;\n\n\t\t\tconst r = el.getBoundingClientRect();\n\t\t\tconst pinEl = document.createElement(\"div\");\n\t\t\tpinEl.style.cssText = [\n\t\t\t\t\"position: fixed\",\n\t\t\t\t`top: ${r.top - 12}px`,\n\t\t\t\t`left: ${r.left + r.width / 2 - 12}px`,\n\t\t\t\t\"width: 24px\",\n\t\t\t\t\"height: 24px\",\n\t\t\t\t\"border-radius: 50%\",\n\t\t\t\t\"background: #059669\",\n\t\t\t\t\"color: #fff\",\n\t\t\t\t\"display: flex\",\n\t\t\t\t\"align-items: center\",\n\t\t\t\t\"justify-content: center\",\n\t\t\t\t\"font-size: 12px\",\n\t\t\t\t\"font-weight: 600\",\n\t\t\t\t\"font-family: ui-sans-serif, system-ui, sans-serif\",\n\t\t\t\t\"box-shadow: 0 2px 8px rgba(0,0,0,0.2)\",\n\t\t\t\t\"pointer-events: none\",\n\t\t\t].join(\";\");\n\t\t\tpinEl.textContent = String(pin.number);\n\t\t\tpinContainer.appendChild(pinEl);\n\t\t}\n\t}\n\n\tconst handleMouseMove = (e: MouseEvent) => {\n\t\tconst el = document.elementFromPoint(e.clientX, e.clientY);\n\t\tif (shouldIgnore(el, [\"data-yns-comment-overlay\", \"data-yns-design-overlay\"])) {\n\t\t\toverlay.style.display = \"none\";\n\t\t\tcursorLabel.style.display = \"none\";\n\t\t\thoveredElement = null;\n\t\t\treturn;\n\t\t}\n\t\thoveredElement = el;\n\t\trequestAnimationFrame(() => {\n\t\t\tif (hoveredElement === el && enabled && el) {\n\t\t\t\tconst rect = el.getBoundingClientRect();\n\t\t\t\toverlay.style.top = `${rect.top}px`;\n\t\t\t\toverlay.style.left = `${rect.left}px`;\n\t\t\t\toverlay.style.width = `${rect.width}px`;\n\t\t\t\toverlay.style.height = `${rect.height}px`;\n\t\t\t\toverlay.style.display = \"block\";\n\n\t\t\t\tcursorLabel.style.left = `${e.clientX + 14}px`;\n\t\t\t\tcursorLabel.style.top = `${e.clientY + 14}px`;\n\t\t\t\tcursorLabel.style.display = \"block\";\n\t\t\t}\n\t\t});\n\t};\n\n\tconst handleMouseLeave = () => {\n\t\toverlay.style.display = \"none\";\n\t\tcursorLabel.style.display = \"none\";\n\t\thoveredElement = null;\n\t};\n\n\tconst handleClick = (e: MouseEvent) => {\n\t\tif (!enabled || !hoveredElement) return;\n\t\te.preventDefault();\n\t\te.stopPropagation();\n\t\te.stopImmediatePropagation();\n\n\t\tconst el = hoveredElement;\n\t\tif (shouldIgnore(el, [\"data-yns-comment-overlay\", \"data-yns-design-overlay\"])) return;\n\n\t\tconst info = buildElementInfo(el, 200);\n\t\tconst rect = el.getBoundingClientRect();\n\n\t\twindow.parent.postMessage(\n\t\t\t{\n\t\t\t\ttype: \"comment-click\",\n\t\t\t\tdata: {\n\t\t\t\t\telement: info,\n\t\t\t\t\tclickPosition: { x: e.clientX, y: e.clientY },\n\t\t\t\t\telementRect: { top: rect.top, left: rect.left, width: rect.width, height: rect.height },\n\t\t\t\t\tpagePath: window.location.pathname,\n\t\t\t\t},\n\t\t\t},\n\t\t\t\"*\",\n\t\t);\n\t};\n\n\tconst handleKeyDown = (e: KeyboardEvent) => {\n\t\tif (e.key === \"Escape\" && enabled) {\n\t\t\tdisableCommentMode();\n\t\t\twindow.parent.postMessage({ type: \"comment-mode-cleared\" }, \"*\");\n\t\t}\n\t};\n\n\tfunction enableCommentMode() {\n\t\tenabled = true;\n\t\tdocument.body.style.cursor = \"crosshair\";\n\t\tdocument.addEventListener(\"mousemove\", handleMouseMove, true);\n\t\tdocument.addEventListener(\"mouseleave\", handleMouseLeave);\n\t\tdocument.addEventListener(\"click\", handleClick, true);\n\t\tdocument.addEventListener(\"keydown\", handleKeyDown, true);\n\t}\n\n\tfunction disableCommentMode() {\n\t\tenabled = false;\n\t\tdocument.body.style.cursor = \"\";\n\t\tdocument.removeEventListener(\"mousemove\", handleMouseMove, true);\n\t\tdocument.removeEventListener(\"mouseleave\", handleMouseLeave);\n\t\tdocument.removeEventListener(\"click\", handleClick, true);\n\t\tdocument.removeEventListener(\"keydown\", handleKeyDown, true);\n\n\t\toverlay.style.display = \"none\";\n\t\tcursorLabel.style.display = \"none\";\n\t\thoveredElement = null;\n\t}\n\n\tlet rafPending = false;\n\tconst scheduleRender = () => {\n\t\tif (rafPending) return;\n\t\trafPending = true;\n\t\trequestAnimationFrame(() => {\n\t\t\trafPending = false;\n\t\t\trenderPins();\n\t\t});\n\t};\n\twindow.addEventListener(\"scroll\", scheduleRender, { passive: true });\n\twindow.addEventListener(\"resize\", scheduleRender, { passive: true });\n\n\twindow.addEventListener(\"message\", (event) => {\n\t\tconst msg = event.data;\n\t\tif (!msg || typeof msg !== \"object\") return;\n\n\t\tif (msg.type === \"comment-mode-toggle\") {\n\t\t\tif (msg.enabled) enableCommentMode();\n\t\t\telse disableCommentMode();\n\t\t}\n\n\t\tif (msg.type === \"comment-pins-update\") {\n\t\t\tpins = msg.pins ?? [];\n\t\t\trenderPins();\n\t\t}\n\n\t\tif (msg.type === \"comment-pin-remove\") {\n\t\t\tpins = pins.filter((p) => p.id !== msg.pinId);\n\t\t\trenderPins();\n\t\t}\n\t});\n}\n"],"mappings":"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","names":["useEffect","useRef","useState","createRoot","jsx","jsxs","MOUNT_NODE_ID","buildApiBase","override","host","protocol","computeCssSelector","el","path","node","part","className","classes","c","parent","tag","siblings","idx","ATTRS_OF_INTEREST","formatAttrs","parts","attr","v","trimmed","formatTextContent","text","buildSurroundingHtml","target","ancestors","cur","lines","depth","ancestor","indent","targetIndent","targetTag","targetText","childIndent","children","child","childText","i","isInsideToolbar","FeedbackToolbar","session","setSession","loading","setLoading","pinMode","setPinMode","pending","setPending","editingId","setEditingId","apiBase","controller","res","data","handleClick","event","rect","refreshComments","submitNewComment","content","updateComment","id","removeComment","visiblePins","pin","PinOverlay","PendingCommentPopover","toolbarStyle","toolbarButtonActiveStyle","toolbarButtonStyle","toolbarHintStyle","number","editing","onStartEdit","onCancelEdit","onSave","onRemove","useTargetRect","pinDotStyle","EditPopover","onCancel","initial","value","setValue","saving","setSaving","e","popoverStyle","textareaStyle","popoverActionsStyle","dangerButtonStyle","ghostButtonStyle","primaryButtonStyle","selector","setRect","update","r","ro","baseButton","mountFeedbackToolbar","container","root","startSandboxInspectors","initDesignModeInspector","initCommentModeInspector","IGNORED_TAGS","generateCssSelector","el","parts","current","selector","classes","parent","tag","s","c","index","buildElementInfo","textLimit","rect","computed","text","shouldIgnore","overlayAttrs","attr","enabled","hoveredElement","selectedElement","overlay","label","style","positionOverlay","labelText","handleMouseMove","e","handleMouseLeave","handleClick","info","handleKeyDown","disableDesignMode","enableDesignMode","event","msg","pins","cursorLabel","pinContainer","renderPins","pin","r","pinEl","disableCommentMode","enableCommentMode","rafPending","scheduleRender","p"]}
1
+ {"version":3,"sources":["../src/feedback-toolbar.tsx","../src/sandbox-inspectors.ts"],"sourcesContent":["/**\n * Feedback session toolbar — side-effect entry.\n *\n * Importing `commerce-kit/feedback-toolbar` (or `commerce-kit/browser` for the\n * combined entry) mounts a floating toolbar onto the page that lets reviewers\n * leave click-anchored comments. Comments persist via YNS API endpoints,\n * authenticated with the `better-auth` session cookie sent through\n * `credentials: \"include\"`.\n *\n * Gated on `process.env.NEXT_PUBLIC_VERCEL_ENV === \"preview\"` — only Vercel\n * preview deploys get the toolbar. Sandbox dev (env undefined) and production\n * (env === \"production\") skip it.\n */\n\nimport { type CSSProperties, type FormEvent, useEffect, useRef, useState } from \"react\";\nimport { createRoot } from \"react-dom/client\";\n\nconst MOUNT_NODE_ID = \"yns-feedback-toolbar-root\";\n\ninterface FeedbackComment {\n\tid: string;\n\tpagePath: string;\n\tcssSelector: string;\n\tcontent: string;\n\tstatus: \"todo\" | \"done\";\n\toffsetXRatio: number;\n\toffsetYRatio: number;\n}\n\ninterface ActiveSession {\n\tfeedbackSessionId: string;\n\tcomments: FeedbackComment[];\n\tcanComment: boolean;\n}\n\ninterface PendingPin {\n\tcssSelector: string;\n\tpagePath: string;\n\tsurroundingHtml: string;\n\trect: { top: number; left: number; width: number; height: number };\n\tclickX: number;\n\tclickY: number;\n\toffsetXRatio: number;\n\toffsetYRatio: number;\n}\n\nconst buildApiBase = (): string | null => {\n\tif (typeof window === \"undefined\") return null;\n\tconst override = (process.env.NEXT_PUBLIC_YNS_API_BASE ?? \"\").trim();\n\tif (override) return override.replace(/\\/$/, \"\");\n\n\t// Toolbar runs on a per-store preview deploy (mystore-preview.yns.{store|cx})\n\t// served by the merchant's Vercel project — that host has no YNS API. Aim\n\t// at the apex `yns.store` / `yns.cx`, which yns-app serves and where the\n\t// API lives. Cookies scoped to `.yns.store` / `.yns.cx` travel along.\n\tconst host = window.location.hostname;\n\tconst protocol = window.location.protocol;\n\tif (host.endsWith(\".yns.store\")) return `${protocol}//yns.store`;\n\tif (host.endsWith(\".yns.cx\")) return `${protocol}//yns.cx`;\n\treturn window.location.origin;\n};\n\nconst computeCssSelector = (el: Element): string => {\n\tif (el.id) return `#${CSS.escape(el.id)}`;\n\tconst path: string[] = [];\n\tlet node: Element | null = el;\n\twhile (node && node.nodeType === Node.ELEMENT_NODE && path.length < 6) {\n\t\tlet part = node.tagName.toLowerCase();\n\t\tconst className = node.getAttribute(\"class\");\n\t\tif (className) {\n\t\t\tconst classes = className\n\t\t\t\t.split(/\\s+/)\n\t\t\t\t.filter(Boolean)\n\t\t\t\t.slice(0, 2)\n\t\t\t\t.map((c) => `.${CSS.escape(c)}`)\n\t\t\t\t.join(\"\");\n\t\t\tpart += classes;\n\t\t}\n\t\tconst parent: Element | null = node.parentElement;\n\t\tconst tag = node.tagName;\n\t\tif (parent) {\n\t\t\tconst siblings: Element[] = Array.from(parent.children).filter((c) => c.tagName === tag);\n\t\t\tif (siblings.length > 1) {\n\t\t\t\tconst idx = siblings.indexOf(node) + 1;\n\t\t\t\tpart += `:nth-of-type(${idx})`;\n\t\t\t}\n\t\t}\n\t\tpath.unshift(part);\n\t\tnode = parent;\n\t}\n\treturn path.join(\" > \");\n};\n\nconst ATTRS_OF_INTEREST = [\"id\", \"class\", \"data-testid\", \"aria-label\", \"role\", \"name\", \"href\", \"src\"];\n\nconst formatAttrs = (el: Element): string => {\n\tconst parts: string[] = [];\n\tfor (const attr of ATTRS_OF_INTEREST) {\n\t\tconst v = el.getAttribute(attr);\n\t\tif (!v) continue;\n\t\tconst trimmed = v.length > 80 ? `${v.slice(0, 80)}…` : v;\n\t\tparts.push(` ${attr}=\"${trimmed.replace(/\"/g, \"&quot;\")}\"`);\n\t}\n\treturn parts.join(\"\");\n};\n\nconst formatTextContent = (el: Element): string => {\n\tconst text = (el.textContent ?? \"\").replace(/\\s+/g, \" \").trim();\n\tif (!text) return \"\";\n\treturn text.length > 100 ? `${text.slice(0, 100)}…` : text;\n};\n\nconst buildSurroundingHtml = (target: Element): string => {\n\tconst ancestors: Element[] = [];\n\tlet cur: Element | null = target;\n\twhile (cur && cur !== document.documentElement && ancestors.length < 5) {\n\t\tconst parent: Element | null = cur.parentElement;\n\t\tif (!parent) break;\n\t\tancestors.unshift(parent);\n\t\tcur = parent;\n\t}\n\n\tconst lines: string[] = [];\n\tlet depth = 0;\n\tfor (const ancestor of ancestors) {\n\t\tconst indent = \" \".repeat(depth);\n\t\tlines.push(`${indent}<${ancestor.tagName.toLowerCase()}${formatAttrs(ancestor)}>`);\n\t\tdepth++;\n\t}\n\n\tconst targetIndent = \" \".repeat(depth);\n\tconst targetTag = target.tagName.toLowerCase();\n\tconst targetText = formatTextContent(target);\n\tlines.push(\n\t\t`${targetIndent}<${targetTag}${formatAttrs(target)}>${\n\t\t\ttargetText ? `${targetText}</${targetTag}>` : \"\"\n\t\t} ← TARGET`,\n\t);\n\n\tif (!targetText) {\n\t\tconst childIndent = \" \".repeat(depth + 1);\n\t\tconst children = Array.from(target.children).slice(0, 6);\n\t\tfor (const child of children) {\n\t\t\tconst childText = formatTextContent(child);\n\t\t\tlines.push(\n\t\t\t\t`${childIndent}<${child.tagName.toLowerCase()}${formatAttrs(child)}>${\n\t\t\t\t\tchildText ? `${childText}</${child.tagName.toLowerCase()}>` : \"\"\n\t\t\t\t}`,\n\t\t\t);\n\t\t}\n\t\tif (target.children.length > 6) {\n\t\t\tlines.push(`${childIndent}… (${target.children.length - 6} more children)`);\n\t\t}\n\t\tlines.push(`${targetIndent}</${targetTag}>`);\n\t}\n\n\tfor (let i = ancestors.length - 1; i >= 0; i--) {\n\t\tconst indent = \" \".repeat(i);\n\t\tconst ancestor = ancestors[i];\n\t\tif (!ancestor) continue;\n\t\tlines.push(`${indent}</${ancestor.tagName.toLowerCase()}>`);\n\t}\n\n\treturn lines.join(\"\\n\");\n};\n\nconst isInsideToolbar = (el: Element | null): boolean => {\n\tlet node = el;\n\twhile (node) {\n\t\tif (node instanceof HTMLElement && node.dataset.ynsFeedbackUi === \"true\") return true;\n\t\tnode = node.parentElement;\n\t}\n\treturn false;\n};\n\nconst IGNORED_TAGS = new Set([\"HTML\", \"HEAD\", \"SCRIPT\", \"STYLE\", \"NOSCRIPT\"]);\n\nfunction FeedbackToolbar() {\n\tconst [session, setSession] = useState<ActiveSession | null>(null);\n\tconst [loading, setLoading] = useState(true);\n\tconst [pinMode, setPinMode] = useState(false);\n\tconst [pending, setPending] = useState<PendingPin | null>(null);\n\tconst [editingId, setEditingId] = useState<string | null>(null);\n\tconst [sidebarOpen, setSidebarOpen] = useState(false);\n\tconst [finalizing, setFinalizing] = useState(false);\n\tconst apiBase = useRef<string | null>(null);\n\n\tuseEffect(() => {\n\t\tapiBase.current = buildApiBase();\n\t\tif (!apiBase.current) {\n\t\t\tsetLoading(false);\n\t\t\treturn;\n\t\t}\n\n\t\tconst controller = new AbortController();\n\t\tfetch(`${apiBase.current}/api/feedback-comments?host=${encodeURIComponent(window.location.host)}`, {\n\t\t\tcredentials: \"include\",\n\t\t\tsignal: controller.signal,\n\t\t})\n\t\t\t.then(async (res) => {\n\t\t\t\tif (!res.ok) {\n\t\t\t\t\tsetSession(null);\n\t\t\t\t\treturn;\n\t\t\t\t}\n\t\t\t\tconst data = (await res.json()) as ActiveSession;\n\t\t\t\tsetSession(data);\n\t\t\t})\n\t\t\t.catch(() => {\n\t\t\t\tsetSession(null);\n\t\t\t})\n\t\t\t.finally(() => setLoading(false));\n\n\t\treturn () => controller.abort();\n\t}, []);\n\n\tuseEffect(() => {\n\t\tif (!pinMode) return;\n\t\tdocument.body.style.cursor = \"crosshair\";\n\t\treturn () => {\n\t\t\tdocument.body.style.cursor = \"\";\n\t\t};\n\t}, [pinMode]);\n\n\tuseEffect(() => {\n\t\tif (!pinMode) return;\n\n\t\tconst overlay = document.createElement(\"div\");\n\t\toverlay.dataset.ynsFeedbackUi = \"true\";\n\t\toverlay.style.cssText = [\n\t\t\t\"position: fixed\",\n\t\t\t\"pointer-events: none\",\n\t\t\t\"z-index: 2147483644\",\n\t\t\t\"border: 2px dashed #10b981\",\n\t\t\t\"background: rgba(16, 185, 129, 0.08)\",\n\t\t\t\"border-radius: 3px\",\n\t\t\t\"display: none\",\n\t\t\t\"transition: top 0.05s, left 0.05s, width 0.05s, height 0.05s\",\n\t\t].join(\";\");\n\n\t\tconst label = document.createElement(\"div\");\n\t\tlabel.dataset.ynsFeedbackUi = \"true\";\n\t\tlabel.textContent = \"Click to comment\";\n\t\tlabel.style.cssText = [\n\t\t\t\"position: fixed\",\n\t\t\t\"pointer-events: none\",\n\t\t\t\"z-index: 2147483645\",\n\t\t\t\"background: #059669\",\n\t\t\t\"color: #fff\",\n\t\t\t\"font-size: 11px\",\n\t\t\t\"font-family: ui-sans-serif, system-ui, sans-serif\",\n\t\t\t\"padding: 3px 8px\",\n\t\t\t\"border-radius: 4px\",\n\t\t\t\"white-space: nowrap\",\n\t\t\t\"display: none\",\n\t\t\t\"box-shadow: 0 2px 6px rgba(0,0,0,0.15)\",\n\t\t].join(\";\");\n\n\t\tdocument.documentElement.appendChild(overlay);\n\t\tdocument.documentElement.appendChild(label);\n\n\t\tlet hovered: Element | null = null;\n\t\tconst handleMove = (e: MouseEvent) => {\n\t\t\tconst el = document.elementFromPoint(e.clientX, e.clientY);\n\t\t\tif (!el || IGNORED_TAGS.has(el.tagName) || isInsideToolbar(el)) {\n\t\t\t\toverlay.style.display = \"none\";\n\t\t\t\tlabel.style.display = \"none\";\n\t\t\t\thovered = null;\n\t\t\t\treturn;\n\t\t\t}\n\t\t\thovered = el;\n\t\t\trequestAnimationFrame(() => {\n\t\t\t\tif (hovered !== el) return;\n\t\t\t\tconst rect = el.getBoundingClientRect();\n\t\t\t\toverlay.style.top = `${rect.top}px`;\n\t\t\t\toverlay.style.left = `${rect.left}px`;\n\t\t\t\toverlay.style.width = `${rect.width}px`;\n\t\t\t\toverlay.style.height = `${rect.height}px`;\n\t\t\t\toverlay.style.display = \"block\";\n\t\t\t\tlabel.style.left = `${e.clientX + 14}px`;\n\t\t\t\tlabel.style.top = `${e.clientY + 14}px`;\n\t\t\t\tlabel.style.display = \"block\";\n\t\t\t});\n\t\t};\n\n\t\tconst handleLeave = () => {\n\t\t\toverlay.style.display = \"none\";\n\t\t\tlabel.style.display = \"none\";\n\t\t\thovered = null;\n\t\t};\n\n\t\tdocument.addEventListener(\"mousemove\", handleMove, true);\n\t\tdocument.addEventListener(\"mouseleave\", handleLeave);\n\n\t\treturn () => {\n\t\t\tdocument.removeEventListener(\"mousemove\", handleMove, true);\n\t\t\tdocument.removeEventListener(\"mouseleave\", handleLeave);\n\t\t\toverlay.remove();\n\t\t\tlabel.remove();\n\t\t};\n\t}, [pinMode]);\n\n\tuseEffect(() => {\n\t\tif (!pinMode) return;\n\t\tconst handleClick = (event: MouseEvent) => {\n\t\t\tconst target = event.target;\n\t\t\tif (!(target instanceof Element)) return;\n\t\t\tif (isInsideToolbar(target)) return;\n\n\t\t\tevent.preventDefault();\n\t\t\tevent.stopPropagation();\n\n\t\t\tconst rect = target.getBoundingClientRect();\n\t\t\tconst offsetXRatio = rect.width > 0 ? (event.clientX - rect.left) / rect.width : 0.5;\n\t\t\tconst offsetYRatio = rect.height > 0 ? (event.clientY - rect.top) / rect.height : 0.5;\n\t\t\tsetPending({\n\t\t\t\tcssSelector: computeCssSelector(target),\n\t\t\t\tpagePath: window.location.pathname,\n\t\t\t\tsurroundingHtml: buildSurroundingHtml(target),\n\t\t\t\trect: {\n\t\t\t\t\ttop: rect.top + window.scrollY,\n\t\t\t\t\tleft: rect.left + window.scrollX,\n\t\t\t\t\twidth: rect.width,\n\t\t\t\t\theight: rect.height,\n\t\t\t\t},\n\t\t\t\tclickX: event.clientX + window.scrollX,\n\t\t\t\tclickY: event.clientY + window.scrollY,\n\t\t\t\toffsetXRatio: Math.min(1, Math.max(0, offsetXRatio)),\n\t\t\t\toffsetYRatio: Math.min(1, Math.max(0, offsetYRatio)),\n\t\t\t});\n\t\t\tsetPinMode(false);\n\t\t};\n\t\tdocument.addEventListener(\"click\", handleClick, { capture: true });\n\t\treturn () => document.removeEventListener(\"click\", handleClick, { capture: true });\n\t}, [pinMode]);\n\n\tconst refreshComments = async () => {\n\t\tif (!apiBase.current) return;\n\t\tconst res = await fetch(\n\t\t\t`${apiBase.current}/api/feedback-comments?host=${encodeURIComponent(window.location.host)}`,\n\t\t\t{ credentials: \"include\" },\n\t\t);\n\t\tif (!res.ok) return;\n\t\tconst data = (await res.json()) as ActiveSession;\n\t\tsetSession(data);\n\t};\n\n\tconst submitNewComment = async (content: string) => {\n\t\tif (!apiBase.current || !session || !pending) return;\n\t\tconst res = await fetch(`${apiBase.current}/api/feedback-comments`, {\n\t\t\tmethod: \"POST\",\n\t\t\tcredentials: \"include\",\n\t\t\theaders: { \"Content-Type\": \"application/json\" },\n\t\t\tbody: JSON.stringify({\n\t\t\t\tfeedbackSessionId: session.feedbackSessionId,\n\t\t\t\tcontent,\n\t\t\t\tpagePath: pending.pagePath,\n\t\t\t\tcssSelector: pending.cssSelector,\n\t\t\t\tsurroundingHtml: pending.surroundingHtml,\n\t\t\t\toffsetXRatio: pending.offsetXRatio,\n\t\t\t\toffsetYRatio: pending.offsetYRatio,\n\t\t\t}),\n\t\t});\n\t\tif (!res.ok) return;\n\t\tsetPending(null);\n\t\tsetPinMode(true);\n\t\tawait refreshComments();\n\t};\n\n\tconst updateComment = async (id: string, content: string) => {\n\t\tif (!apiBase.current) return;\n\t\tconst res = await fetch(`${apiBase.current}/api/feedback-comments/${id}`, {\n\t\t\tmethod: \"PATCH\",\n\t\t\tcredentials: \"include\",\n\t\t\theaders: { \"Content-Type\": \"application/json\" },\n\t\t\tbody: JSON.stringify({ content }),\n\t\t});\n\t\tif (!res.ok) return;\n\t\tsetEditingId(null);\n\t\tawait refreshComments();\n\t};\n\n\tconst removeComment = async (id: string) => {\n\t\tif (!apiBase.current) return;\n\t\tconst res = await fetch(`${apiBase.current}/api/feedback-comments/${id}`, {\n\t\t\tmethod: \"DELETE\",\n\t\t\tcredentials: \"include\",\n\t\t});\n\t\tif (!res.ok) return;\n\t\tawait refreshComments();\n\t};\n\n\tconst finalizeSession = async () => {\n\t\tif (!apiBase.current || !session) return;\n\t\tif (!window.confirm(\"Finalize this feedback session? You won't be able to add more comments.\")) return;\n\t\tsetFinalizing(true);\n\t\ttry {\n\t\t\tconst res = await fetch(\n\t\t\t\t`${apiBase.current}/api/feedback-sessions/${session.feedbackSessionId}/finalize`,\n\t\t\t\t{ method: \"POST\", credentials: \"include\" },\n\t\t\t);\n\t\t\tif (!res.ok) return;\n\t\t\tsetSession((prev) => (prev ? { ...prev, canComment: false } : prev));\n\t\t} finally {\n\t\t\tsetFinalizing(false);\n\t\t}\n\t};\n\n\tconst scrollToComment = (comment: FeedbackComment) => {\n\t\tif (comment.pagePath !== window.location.pathname) {\n\t\t\twindow.location.assign(comment.pagePath);\n\t\t\treturn;\n\t\t}\n\t\tlet el: Element | null = null;\n\t\ttry {\n\t\t\tel = document.querySelector(comment.cssSelector);\n\t\t} catch {\n\t\t\tel = null;\n\t\t}\n\t\tif (!el) return;\n\t\tel.scrollIntoView({ behavior: \"smooth\", block: \"center\" });\n\t\tsetEditingId(comment.id);\n\t};\n\n\tif (loading || !session || !session.canComment) return null;\n\n\tconst visiblePins = session.comments.filter(\n\t\t(c) => c.pagePath === window.location.pathname && c.status !== \"done\",\n\t);\n\n\treturn (\n\t\t<div data-yns-feedback-ui=\"true\">\n\t\t\t{visiblePins.map((pin, idx) => (\n\t\t\t\t<PinOverlay\n\t\t\t\t\tkey={pin.id}\n\t\t\t\t\tpin={pin}\n\t\t\t\t\tnumber={idx + 1}\n\t\t\t\t\tediting={editingId === pin.id}\n\t\t\t\t\tonStartEdit={() => setEditingId(pin.id)}\n\t\t\t\t\tonCancelEdit={() => setEditingId(null)}\n\t\t\t\t\tonSave={(content) => updateComment(pin.id, content)}\n\t\t\t\t\tonRemove={() => removeComment(pin.id)}\n\t\t\t\t/>\n\t\t\t))}\n\n\t\t\t{pending && (\n\t\t\t\t<PendingCommentPopover\n\t\t\t\t\tpending={pending}\n\t\t\t\t\tonCancel={() => {\n\t\t\t\t\t\tsetPending(null);\n\t\t\t\t\t\tsetPinMode(true);\n\t\t\t\t\t}}\n\t\t\t\t\tonSave={(content) => submitNewComment(content)}\n\t\t\t\t/>\n\t\t\t)}\n\n\t\t\t{sidebarOpen && (\n\t\t\t\t<CommentsSidebar\n\t\t\t\t\tcomments={session.comments}\n\t\t\t\t\tcurrentPath={window.location.pathname}\n\t\t\t\t\tonClose={() => setSidebarOpen(false)}\n\t\t\t\t\tonSelect={scrollToComment}\n\t\t\t\t/>\n\t\t\t)}\n\n\t\t\t<div style={toolbarStyle}>\n\t\t\t\t<button\n\t\t\t\t\ttype=\"button\"\n\t\t\t\t\tonClick={() => setPinMode((v) => !v)}\n\t\t\t\t\tstyle={pinMode ? toolbarButtonActiveStyle : toolbarButtonStyle}\n\t\t\t\t>\n\t\t\t\t\t{pinMode ? \"Cancel\" : \"Add comment\"}\n\t\t\t\t</button>\n\t\t\t\t<button type=\"button\" onClick={() => setSidebarOpen((v) => !v)} style={toolbarButtonGhostStyle}>\n\t\t\t\t\t{sidebarOpen ? \"Hide list\" : `List (${session.comments.length})`}\n\t\t\t\t</button>\n\t\t\t\t<button\n\t\t\t\t\ttype=\"button\"\n\t\t\t\t\tonClick={finalizeSession}\n\t\t\t\t\tdisabled={finalizing}\n\t\t\t\t\tstyle={toolbarButtonFinalizeStyle}\n\t\t\t\t>\n\t\t\t\t\t{finalizing ? \"Finalizing…\" : \"Finalize\"}\n\t\t\t\t</button>\n\t\t\t\t<span style={toolbarHintStyle}>\n\t\t\t\t\t{pinMode ? \"Click any element to comment\" : `${visiblePins.length} on this page`}\n\t\t\t\t</span>\n\t\t\t</div>\n\t\t</div>\n\t);\n}\n\nfunction PinOverlay({\n\tpin,\n\tnumber,\n\tediting,\n\tonStartEdit,\n\tonCancelEdit,\n\tonSave,\n\tonRemove,\n}: {\n\tpin: FeedbackComment;\n\tnumber: number;\n\tediting: boolean;\n\tonStartEdit: () => void;\n\tonCancelEdit: () => void;\n\tonSave: (content: string) => Promise<void>;\n\tonRemove: () => Promise<void>;\n}) {\n\tconst target = useTargetPosition(pin.cssSelector, pin.offsetXRatio, pin.offsetYRatio);\n\tif (!target) return null;\n\n\treturn (\n\t\t<div\n\t\t\tstyle={{\n\t\t\t\tposition: \"absolute\",\n\t\t\t\ttop: target.top,\n\t\t\t\tleft: target.left,\n\t\t\t\tzIndex: 2147483600,\n\t\t\t\tpointerEvents: \"auto\",\n\t\t\t}}\n\t\t>\n\t\t\t<button type=\"button\" onClick={onStartEdit} style={pinDotStyle} title={pin.content}>\n\t\t\t\t{number}\n\t\t\t</button>\n\t\t\t{editing && (\n\t\t\t\t<EditPopover initial={pin.content} onCancel={onCancelEdit} onSave={onSave} onRemove={onRemove} />\n\t\t\t)}\n\t\t</div>\n\t);\n}\n\nfunction PendingCommentPopover({\n\tpending,\n\tonCancel,\n\tonSave,\n}: {\n\tpending: PendingPin;\n\tonCancel: () => void;\n\tonSave: (content: string) => Promise<void>;\n}) {\n\treturn (\n\t\t<>\n\t\t\t<div\n\t\t\t\tstyle={{\n\t\t\t\t\tposition: \"absolute\",\n\t\t\t\t\ttop: pending.rect.top + pending.rect.height * pending.offsetYRatio - 12,\n\t\t\t\t\tleft: pending.rect.left + pending.rect.width * pending.offsetXRatio - 12,\n\t\t\t\t\tzIndex: 2147483600,\n\t\t\t\t\tpointerEvents: \"none\",\n\t\t\t\t}}\n\t\t\t>\n\t\t\t\t<div style={pinDotStyle}>•</div>\n\t\t\t</div>\n\t\t\t<div\n\t\t\t\tstyle={{\n\t\t\t\t\tposition: \"absolute\",\n\t\t\t\t\ttop: pending.clickY + 10,\n\t\t\t\t\tleft: pending.clickX + 10,\n\t\t\t\t\tzIndex: 2147483647,\n\t\t\t\t}}\n\t\t\t>\n\t\t\t\t<EditPopover initial=\"\" onCancel={onCancel} onSave={onSave} />\n\t\t\t</div>\n\t\t</>\n\t);\n}\n\nfunction CommentsSidebar({\n\tcomments,\n\tcurrentPath,\n\tonClose,\n\tonSelect,\n}: {\n\tcomments: FeedbackComment[];\n\tcurrentPath: string;\n\tonClose: () => void;\n\tonSelect: (comment: FeedbackComment) => void;\n}) {\n\tconst groups = new Map<string, FeedbackComment[]>();\n\tfor (const c of comments) {\n\t\tconst list = groups.get(c.pagePath) ?? [];\n\t\tlist.push(c);\n\t\tgroups.set(c.pagePath, list);\n\t}\n\tconst paths = Array.from(groups.keys()).sort((a, b) => {\n\t\tif (a === currentPath) return -1;\n\t\tif (b === currentPath) return 1;\n\t\treturn a.localeCompare(b);\n\t});\n\n\treturn (\n\t\t<div style={sidebarStyle}>\n\t\t\t<div style={sidebarHeaderStyle}>\n\t\t\t\t<strong style={{ fontSize: 14 }}>Comments ({comments.length})</strong>\n\t\t\t\t<button type=\"button\" onClick={onClose} style={ghostButtonStyle}>\n\t\t\t\t\tClose\n\t\t\t\t</button>\n\t\t\t</div>\n\t\t\t<div style={sidebarScrollStyle}>\n\t\t\t\t{comments.length === 0 ? (\n\t\t\t\t\t<div style={sidebarEmptyStyle}>No comments yet. Click “Add comment” to leave one.</div>\n\t\t\t\t) : (\n\t\t\t\t\tpaths.map((path) => (\n\t\t\t\t\t\t<div key={path} style={{ marginBottom: 12 }}>\n\t\t\t\t\t\t\t<div style={sidebarPathStyle}>{path === currentPath ? `${path} · current` : path}</div>\n\t\t\t\t\t\t\t{(groups.get(path) ?? []).map((c, idx) => (\n\t\t\t\t\t\t\t\t<button\n\t\t\t\t\t\t\t\t\tkey={c.id}\n\t\t\t\t\t\t\t\t\ttype=\"button\"\n\t\t\t\t\t\t\t\t\tonClick={() => onSelect(c)}\n\t\t\t\t\t\t\t\t\tstyle={sidebarItemStyle}\n\t\t\t\t\t\t\t\t\tdisabled={c.status === \"done\" && false}\n\t\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t\t<span style={sidebarItemIndexStyle}>{idx + 1}</span>\n\t\t\t\t\t\t\t\t\t<span style={sidebarItemTextStyle}>\n\t\t\t\t\t\t\t\t\t\t{c.content.length > 140 ? `${c.content.slice(0, 140)}…` : c.content}\n\t\t\t\t\t\t\t\t\t</span>\n\t\t\t\t\t\t\t\t\t{c.status === \"done\" && <span style={sidebarItemDoneStyle}>done</span>}\n\t\t\t\t\t\t\t\t</button>\n\t\t\t\t\t\t\t))}\n\t\t\t\t\t\t</div>\n\t\t\t\t\t))\n\t\t\t\t)}\n\t\t\t</div>\n\t\t</div>\n\t);\n}\n\nfunction EditPopover({\n\tinitial,\n\tonCancel,\n\tonSave,\n\tonRemove,\n}: {\n\tinitial: string;\n\tonCancel: () => void;\n\tonSave: (content: string) => Promise<void>;\n\tonRemove?: () => Promise<void>;\n}) {\n\tconst [value, setValue] = useState(initial);\n\tconst [saving, setSaving] = useState(false);\n\tconst textareaRef = useRef<HTMLTextAreaElement | null>(null);\n\n\tuseEffect(() => {\n\t\tconst el = textareaRef.current;\n\t\tif (!el) return;\n\t\tel.focus();\n\t\tconst len = el.value.length;\n\t\tel.setSelectionRange(len, len);\n\t}, []);\n\n\tconst handleSubmit = async (e: FormEvent) => {\n\t\te.preventDefault();\n\t\tconst content = value.trim();\n\t\tif (!content) return;\n\t\tsetSaving(true);\n\t\ttry {\n\t\t\tawait onSave(content);\n\t\t} finally {\n\t\t\tsetSaving(false);\n\t\t}\n\t};\n\n\treturn (\n\t\t<form onSubmit={handleSubmit} style={popoverStyle}>\n\t\t\t<textarea\n\t\t\t\tref={textareaRef}\n\t\t\t\tvalue={value}\n\t\t\t\tonChange={(e) => setValue(e.target.value)}\n\t\t\t\tplaceholder=\"Leave a comment…\"\n\t\t\t\tstyle={textareaStyle}\n\t\t\t\trows={3}\n\t\t\t/>\n\t\t\t<div style={popoverActionsStyle}>\n\t\t\t\t{onRemove && (\n\t\t\t\t\t<button type=\"button\" onClick={() => onRemove()} style={dangerButtonStyle} disabled={saving}>\n\t\t\t\t\t\tDelete\n\t\t\t\t\t</button>\n\t\t\t\t)}\n\t\t\t\t<div style={{ flex: 1 }} />\n\t\t\t\t<button type=\"button\" onClick={onCancel} style={ghostButtonStyle} disabled={saving}>\n\t\t\t\t\tCancel\n\t\t\t\t</button>\n\t\t\t\t<button type=\"submit\" style={primaryButtonStyle} disabled={saving || !value.trim()}>\n\t\t\t\t\t{saving ? \"Saving…\" : \"Save\"}\n\t\t\t\t</button>\n\t\t\t</div>\n\t\t</form>\n\t);\n}\n\nfunction useTargetPosition(selector: string, offsetXRatio: number, offsetYRatio: number) {\n\tconst [pos, setPos] = useState<{ top: number; left: number } | null>(null);\n\n\tuseEffect(() => {\n\t\tconst update = () => {\n\t\t\tlet el: Element | null = null;\n\t\t\ttry {\n\t\t\t\tel = document.querySelector(selector);\n\t\t\t} catch {\n\t\t\t\tel = null;\n\t\t\t}\n\t\t\tif (!el) {\n\t\t\t\tsetPos(null);\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tconst r = el.getBoundingClientRect();\n\t\t\tsetPos({\n\t\t\t\ttop: r.top + window.scrollY + r.height * offsetYRatio - 12,\n\t\t\t\tleft: r.left + window.scrollX + r.width * offsetXRatio - 12,\n\t\t\t});\n\t\t};\n\n\t\tupdate();\n\t\tconst ro = new ResizeObserver(update);\n\t\ttry {\n\t\t\tconst el = document.querySelector(selector);\n\t\t\tif (el) ro.observe(el);\n\t\t} catch {\n\t\t\t// swallow invalid selector\n\t\t}\n\t\twindow.addEventListener(\"scroll\", update, true);\n\t\twindow.addEventListener(\"resize\", update);\n\t\treturn () => {\n\t\t\tro.disconnect();\n\t\t\twindow.removeEventListener(\"scroll\", update, true);\n\t\t\twindow.removeEventListener(\"resize\", update);\n\t\t};\n\t}, [selector, offsetXRatio, offsetYRatio]);\n\n\treturn pos;\n}\n\n// Inline styles — toolbar is injected into arbitrary stores, so we avoid relying\n// on any CSS framework being present.\nconst toolbarStyle: CSSProperties = {\n\tposition: \"fixed\",\n\tbottom: 16,\n\tleft: \"50%\",\n\ttransform: \"translateX(-50%)\",\n\tzIndex: 2147483646,\n\tdisplay: \"flex\",\n\talignItems: \"center\",\n\tgap: 8,\n\tpadding: \"8px 12px\",\n\tbackground: \"rgba(17, 17, 17, 0.92)\",\n\tcolor: \"white\",\n\tborderRadius: 999,\n\tboxShadow: \"0 8px 24px rgba(0,0,0,0.25)\",\n\tfontFamily:\n\t\t'-apple-system, BlinkMacSystemFont, \"Segoe UI\", Roboto, Helvetica, Arial, sans-serif, \"Apple Color Emoji\", \"Segoe UI Emoji\"',\n\tfontSize: 14,\n\tpointerEvents: \"auto\",\n};\n\nconst toolbarButtonStyle: CSSProperties = {\n\tborder: \"none\",\n\tbackground: \"white\",\n\tcolor: \"#111\",\n\tpadding: \"6px 12px\",\n\tborderRadius: 999,\n\tcursor: \"pointer\",\n\tfontWeight: 600,\n\tfontSize: 13,\n};\n\nconst toolbarButtonActiveStyle: CSSProperties = {\n\t...toolbarButtonStyle,\n\tbackground: \"#ef4444\",\n\tcolor: \"white\",\n};\n\nconst toolbarButtonGhostStyle: CSSProperties = {\n\tborder: \"1px solid rgba(255,255,255,0.4)\",\n\tbackground: \"transparent\",\n\tcolor: \"white\",\n\tpadding: \"6px 12px\",\n\tborderRadius: 999,\n\tcursor: \"pointer\",\n\tfontWeight: 500,\n\tfontSize: 13,\n};\n\nconst toolbarButtonFinalizeStyle: CSSProperties = {\n\tborder: \"none\",\n\tbackground: \"#10b981\",\n\tcolor: \"white\",\n\tpadding: \"6px 12px\",\n\tborderRadius: 999,\n\tcursor: \"pointer\",\n\tfontWeight: 600,\n\tfontSize: 13,\n};\n\nconst toolbarHintStyle: CSSProperties = {\n\topacity: 0.8,\n\tfontSize: 12,\n};\n\nconst pinDotStyle: CSSProperties = {\n\twidth: 24,\n\theight: 24,\n\tborderRadius: 999,\n\tbackground: \"#10b981\",\n\tcolor: \"white\",\n\tborder: \"2px solid white\",\n\tcursor: \"pointer\",\n\tfontSize: 12,\n\tfontWeight: 700,\n\tboxShadow: \"0 2px 6px rgba(0,0,0,0.3)\",\n\tdisplay: \"inline-flex\",\n\talignItems: \"center\",\n\tjustifyContent: \"center\",\n\tpadding: 0,\n};\n\nconst popoverStyle: CSSProperties = {\n\tbackground: \"white\",\n\tborder: \"1px solid #e5e7eb\",\n\tborderRadius: 8,\n\tpadding: 12,\n\twidth: 280,\n\tboxShadow: \"0 12px 32px rgba(0,0,0,0.18)\",\n\tfontFamily:\n\t\t'-apple-system, BlinkMacSystemFont, \"Segoe UI\", Roboto, Helvetica, Arial, sans-serif, \"Apple Color Emoji\", \"Segoe UI Emoji\"',\n\tdisplay: \"flex\",\n\tflexDirection: \"column\",\n\tgap: 8,\n\tcolor: \"#111\",\n};\n\nconst textareaStyle: CSSProperties = {\n\twidth: \"100%\",\n\tborder: \"1px solid #d1d5db\",\n\tborderRadius: 6,\n\tpadding: 8,\n\tfontSize: 14,\n\tresize: \"vertical\",\n\tfontFamily: \"inherit\",\n\tcolor: \"#111\",\n\tbackground: \"white\",\n\tboxSizing: \"border-box\",\n};\n\nconst popoverActionsStyle: CSSProperties = {\n\tdisplay: \"flex\",\n\talignItems: \"center\",\n\tgap: 6,\n};\n\nconst baseButton: CSSProperties = {\n\tborder: \"1px solid transparent\",\n\tborderRadius: 6,\n\tpadding: \"6px 10px\",\n\tfontSize: 13,\n\tcursor: \"pointer\",\n\tfontWeight: 500,\n};\n\nconst primaryButtonStyle: CSSProperties = {\n\t...baseButton,\n\tbackground: \"#111\",\n\tcolor: \"white\",\n};\n\nconst ghostButtonStyle: CSSProperties = {\n\t...baseButton,\n\tbackground: \"transparent\",\n\tcolor: \"#374151\",\n\tborderColor: \"#d1d5db\",\n};\n\nconst dangerButtonStyle: CSSProperties = {\n\t...baseButton,\n\tbackground: \"transparent\",\n\tcolor: \"#b91c1c\",\n\tborderColor: \"#fecaca\",\n};\n\nconst sidebarStyle: CSSProperties = {\n\tposition: \"fixed\",\n\ttop: 0,\n\tright: 0,\n\tbottom: 0,\n\twidth: 360,\n\tmaxWidth: \"92vw\",\n\tbackground: \"white\",\n\tborderLeft: \"1px solid #e5e7eb\",\n\tboxShadow: \"-12px 0 32px rgba(0,0,0,0.12)\",\n\tzIndex: 2147483646,\n\tdisplay: \"flex\",\n\tflexDirection: \"column\",\n\tfontFamily:\n\t\t'-apple-system, BlinkMacSystemFont, \"Segoe UI\", Roboto, Helvetica, Arial, sans-serif, \"Apple Color Emoji\", \"Segoe UI Emoji\"',\n\tcolor: \"#111\",\n};\n\nconst sidebarHeaderStyle: CSSProperties = {\n\tdisplay: \"flex\",\n\talignItems: \"center\",\n\tjustifyContent: \"space-between\",\n\tpadding: \"12px 16px\",\n\tborderBottom: \"1px solid #e5e7eb\",\n};\n\nconst sidebarScrollStyle: CSSProperties = {\n\tflex: 1,\n\toverflow: \"auto\",\n\tpadding: \"12px 12px 24px\",\n};\n\nconst sidebarEmptyStyle: CSSProperties = {\n\tcolor: \"#6b7280\",\n\tfontSize: 13,\n\tpadding: \"24px 8px\",\n\ttextAlign: \"center\",\n};\n\nconst sidebarPathStyle: CSSProperties = {\n\tfontSize: 11,\n\ttextTransform: \"uppercase\",\n\tletterSpacing: 0.5,\n\tcolor: \"#6b7280\",\n\tpadding: \"4px 4px 6px\",\n\twordBreak: \"break-all\",\n};\n\nconst sidebarItemStyle: CSSProperties = {\n\tdisplay: \"flex\",\n\talignItems: \"flex-start\",\n\tgap: 8,\n\twidth: \"100%\",\n\ttextAlign: \"left\",\n\tbackground: \"white\",\n\tborder: \"1px solid #e5e7eb\",\n\tborderRadius: 6,\n\tpadding: \"8px 10px\",\n\tcursor: \"pointer\",\n\tfontSize: 13,\n\tmarginBottom: 6,\n\tcolor: \"#111\",\n};\n\nconst sidebarItemIndexStyle: CSSProperties = {\n\tflexShrink: 0,\n\twidth: 22,\n\theight: 22,\n\tborderRadius: 999,\n\tbackground: \"#10b981\",\n\tcolor: \"white\",\n\tfontWeight: 700,\n\tfontSize: 11,\n\tdisplay: \"inline-flex\",\n\talignItems: \"center\",\n\tjustifyContent: \"center\",\n};\n\nconst sidebarItemTextStyle: CSSProperties = {\n\tflex: 1,\n\twhiteSpace: \"pre-wrap\",\n\twordBreak: \"break-word\",\n};\n\nconst sidebarItemDoneStyle: CSSProperties = {\n\tflexShrink: 0,\n\tbackground: \"#d1fae5\",\n\tcolor: \"#065f46\",\n\tfontSize: 11,\n\tfontWeight: 600,\n\tpadding: \"2px 6px\",\n\tborderRadius: 4,\n\talignSelf: \"center\",\n};\n\nexport function mountFeedbackToolbar(): { unmount: () => void } | null {\n\tconsole.log(\"[YNS Feedback Toolbar] mountFeedbackToolbar() called\", {\n\t\tisWindow: typeof window !== \"undefined\",\n\t\tvercelEnv: process.env.NEXT_PUBLIC_VERCEL_ENV,\n\t\talreadyMounted: typeof document !== \"undefined\" && Boolean(document.getElementById(MOUNT_NODE_ID)),\n\t});\n\tif (typeof window === \"undefined\") return null;\n\tif (process.env.NEXT_PUBLIC_VERCEL_ENV !== \"preview\") {\n\t\tconsole.log(\n\t\t\t\"[YNS Feedback Toolbar] gate failed — NEXT_PUBLIC_VERCEL_ENV is\",\n\t\t\tprocess.env.NEXT_PUBLIC_VERCEL_ENV,\n\t\t);\n\t\treturn null;\n\t}\n\tif (document.getElementById(MOUNT_NODE_ID)) return null;\n\n\tconst container = document.createElement(\"div\");\n\tcontainer.id = MOUNT_NODE_ID;\n\tcontainer.dataset.ynsFeedbackUi = \"true\";\n\tdocument.body.appendChild(container);\n\n\tconst root = createRoot(container);\n\troot.render(<FeedbackToolbar />);\n\n\treturn {\n\t\tunmount: () => {\n\t\t\troot.unmount();\n\t\t\tcontainer.remove();\n\t\t},\n\t};\n}\n\n// Auto-mount on import. Wait for DOM ready.\nif (typeof window !== \"undefined\") {\n\tconsole.log(\"[YNS Feedback Toolbar] module evaluated\", {\n\t\tvercelEnv: process.env.NEXT_PUBLIC_VERCEL_ENV,\n\t\treadyState: document.readyState,\n\t\twillAutoMount: process.env.NEXT_PUBLIC_VERCEL_ENV === \"preview\",\n\t});\n}\nif (typeof window !== \"undefined\" && process.env.NEXT_PUBLIC_VERCEL_ENV === \"preview\") {\n\tif (document.readyState === \"loading\") {\n\t\tdocument.addEventListener(\"DOMContentLoaded\", () => {\n\t\t\tmountFeedbackToolbar();\n\t\t});\n\t} else {\n\t\tmountFeedbackToolbar();\n\t}\n}\n","/**\n * Sandbox Inspectors — side-effect entry.\n *\n * Auto-mounts the design-mode + comment-mode inspectors inside per-store\n * storefronts running under the AI Builder sandbox dev server. Communicates\n * with the parent /design iframe via postMessage.\n *\n * Always-on: inspectors are passive postMessage listeners and don't affect the\n * page until the AI Builder iframe sends a `*-mode-toggle` message. Gating on\n * NODE_ENV is wrong (always \"production\" on Vercel) and any build-time gate\n * gets folded out by the commerce-kit bundle, leaving an empty file.\n */\n\n/**\n * Exported so `browser.tsx` can `export { startSandboxInspectors }` — the\n * named binding anchors this module against esbuild tree-shaking when\n * commerce-kit is bundled. Without it, an `export * from \"./sandbox-inspectors\"`\n * re-exports an empty binding set and esbuild DCEs the whole file.\n */\nexport function startSandboxInspectors(): void {\n\tif (typeof window === \"undefined\") return;\n\tconsole.log(\"[YNS Sandbox Inspectors] module evaluated\");\n\tinitDesignModeInspector();\n\tinitCommentModeInspector();\n}\n\n// Auto-start on import.\nstartSandboxInspectors();\n\ninterface ElementInfo {\n\ttag: string;\n\tid: string | undefined;\n\tclasses: string[];\n\ttextContent: string;\n\tcssSelector: string;\n\tboundingRect: { top: number; left: number; width: number; height: number };\n\tcomputedStyles: Partial<{\n\t\tcolor: string;\n\t\tbackgroundColor: string;\n\t\tfontSize: string;\n\t\tfontFamily: string;\n\t\tpadding: string;\n\t\tmargin: string;\n\t}>;\n}\n\nconst IGNORED_TAGS = new Set([\"HEAD\", \"SCRIPT\", \"STYLE\", \"NOSCRIPT\", \"HTML\"]);\n\nfunction generateCssSelector(el: Element): string {\n\tif (el.id) return `${el.tagName.toLowerCase()}#${CSS.escape(el.id)}`;\n\n\tconst parts: string[] = [];\n\tlet current: Element | null = el;\n\twhile (current && current !== document.body && current !== document.documentElement) {\n\t\tlet selector = current.tagName.toLowerCase();\n\n\t\tif (current.id) {\n\t\t\tparts.unshift(`${selector}#${CSS.escape(current.id)}`);\n\t\t\tbreak;\n\t\t}\n\n\t\tconst classes = Array.from(current.classList).filter((c) => !c.startsWith(\"data-yns-\"));\n\t\tif (classes.length > 0) {\n\t\t\tselector += `.${classes.map((c) => CSS.escape(c)).join(\".\")}`;\n\t\t}\n\n\t\tconst parent: Element | null = current.parentElement;\n\t\tconst tag = current.tagName;\n\t\tif (parent) {\n\t\t\tconst siblings = Array.from(parent.children).filter(\n\t\t\t\t(s) => s.tagName === tag && (classes.length === 0 || classes.every((c) => s.classList.contains(c))),\n\t\t\t);\n\t\t\tif (siblings.length > 1) {\n\t\t\t\tconst index = Array.from(parent.children).indexOf(current) + 1;\n\t\t\t\tselector += `:nth-child(${index})`;\n\t\t\t}\n\t\t}\n\n\t\tparts.unshift(selector);\n\t\tcurrent = current.parentElement;\n\t}\n\treturn parts.join(\" > \");\n}\n\nfunction buildElementInfo(el: Element, textLimit: number): ElementInfo {\n\tconst rect = el.getBoundingClientRect();\n\tconst computed = window.getComputedStyle(el);\n\tconst text = (el.textContent ?? \"\").trim();\n\treturn {\n\t\ttag: el.tagName.toLowerCase(),\n\t\tid: el.id || undefined,\n\t\tclasses: Array.from(el.classList).filter((c) => !c.startsWith(\"data-yns-\")),\n\t\ttextContent: text.length > textLimit ? `${text.slice(0, textLimit)}…` : text,\n\t\tcssSelector: generateCssSelector(el),\n\t\tboundingRect: { top: rect.top, left: rect.left, width: rect.width, height: rect.height },\n\t\tcomputedStyles: {\n\t\t\tcolor: computed.color,\n\t\t\tbackgroundColor: computed.backgroundColor,\n\t\t\tfontSize: computed.fontSize,\n\t\t\tfontFamily: computed.fontFamily,\n\t\t\tpadding: computed.padding,\n\t\t\tmargin: computed.margin,\n\t\t},\n\t};\n}\n\nfunction shouldIgnore(el: Element | null, overlayAttrs: string[]): el is null {\n\tif (!el || !el.tagName) return true;\n\tif (IGNORED_TAGS.has(el.tagName)) return true;\n\tfor (const attr of overlayAttrs) {\n\t\tif (el.hasAttribute?.(attr)) return true;\n\t}\n\treturn false;\n}\n\nfunction initDesignModeInspector() {\n\tlet enabled = false;\n\tlet hoveredElement: Element | null = null;\n\tlet selectedElement: { el: Element; cssSelector: string } | null = null;\n\n\tconst overlay = document.createElement(\"div\");\n\toverlay.setAttribute(\"data-yns-design-overlay\", \"hover\");\n\toverlay.style.cssText = [\n\t\t\"position: fixed\",\n\t\t\"pointer-events: none\",\n\t\t\"z-index: 2147483646\",\n\t\t\"border: 2px solid #3b82f6\",\n\t\t\"background: rgba(59, 130, 246, 0.08)\",\n\t\t\"border-radius: 3px\",\n\t\t\"display: none\",\n\t\t\"transition: top 0.05s, left 0.05s, width 0.05s, height 0.05s\",\n\t].join(\";\");\n\n\tconst label = document.createElement(\"div\");\n\tlabel.setAttribute(\"data-yns-design-overlay\", \"label\");\n\tlabel.style.cssText = [\n\t\t\"position: fixed\",\n\t\t\"pointer-events: none\",\n\t\t\"z-index: 2147483647\",\n\t\t\"background: #3b82f6\",\n\t\t\"color: #fff\",\n\t\t\"font-size: 11px\",\n\t\t\"font-family: ui-monospace, monospace\",\n\t\t\"padding: 2px 6px\",\n\t\t\"border-radius: 3px\",\n\t\t\"white-space: nowrap\",\n\t\t\"display: none\",\n\t].join(\";\");\n\n\tdocument.documentElement.appendChild(overlay);\n\tdocument.documentElement.appendChild(label);\n\n\tconst style = document.createElement(\"style\");\n\tstyle.setAttribute(\"data-yns-design-overlay\", \"style\");\n\tstyle.textContent = \"[data-yns-selected] { outline: 2px solid #3b82f6 !important; outline-offset: 1px; }\";\n\tdocument.head.appendChild(style);\n\n\tfunction positionOverlay(el: Element) {\n\t\tconst rect = el.getBoundingClientRect();\n\t\toverlay.style.top = `${rect.top}px`;\n\t\toverlay.style.left = `${rect.left}px`;\n\t\toverlay.style.width = `${rect.width}px`;\n\t\toverlay.style.height = `${rect.height}px`;\n\t\toverlay.style.display = \"block\";\n\n\t\tconst classes = Array.from(el.classList).filter((c) => !c.startsWith(\"data-yns-\"));\n\t\tconst labelText = el.tagName.toLowerCase() + (classes.length ? `.${classes[0]}` : \"\");\n\t\tlabel.textContent = labelText;\n\t\tlabel.style.left = `${rect.left}px`;\n\t\tlabel.style.top = `${Math.max(0, rect.top - 22)}px`;\n\t\tlabel.style.display = \"block\";\n\t}\n\n\tconst handleMouseMove = (e: MouseEvent) => {\n\t\tconst el = document.elementFromPoint(e.clientX, e.clientY);\n\t\tif (shouldIgnore(el, [\"data-yns-design-overlay\"])) {\n\t\t\toverlay.style.display = \"none\";\n\t\t\tlabel.style.display = \"none\";\n\t\t\thoveredElement = null;\n\t\t\treturn;\n\t\t}\n\t\thoveredElement = el;\n\t\trequestAnimationFrame(() => {\n\t\t\tif (hoveredElement === el && enabled && el) {\n\t\t\t\tpositionOverlay(el);\n\t\t\t}\n\t\t});\n\t};\n\n\tconst handleMouseLeave = () => {\n\t\toverlay.style.display = \"none\";\n\t\tlabel.style.display = \"none\";\n\t\thoveredElement = null;\n\t};\n\n\tconst handleClick = (e: MouseEvent) => {\n\t\tif (!enabled || !hoveredElement) return;\n\t\te.preventDefault();\n\t\te.stopPropagation();\n\t\te.stopImmediatePropagation();\n\n\t\tconst el = hoveredElement;\n\t\tif (shouldIgnore(el, [\"data-yns-design-overlay\"])) return;\n\n\t\tconst info = buildElementInfo(el, 120);\n\t\tconst selector = info.cssSelector;\n\n\t\tif (selectedElement) {\n\t\t\tselectedElement.el.removeAttribute(\"data-yns-selected\");\n\t\t}\n\n\t\tif (selectedElement && selectedElement.cssSelector === selector) {\n\t\t\tselectedElement = null;\n\t\t\twindow.parent.postMessage({ type: \"element-deselected\", data: info }, \"*\");\n\t\t} else {\n\t\t\tselectedElement = { el, cssSelector: selector };\n\t\t\tel.setAttribute(\"data-yns-selected\", \"\");\n\t\t\twindow.parent.postMessage({ type: \"element-selected\", data: info }, \"*\");\n\t\t}\n\t};\n\n\tconst handleKeyDown = (e: KeyboardEvent) => {\n\t\tif (e.key === \"Escape\" && enabled) {\n\t\t\tdisableDesignMode();\n\t\t\twindow.parent.postMessage({ type: \"design-mode-cleared\" }, \"*\");\n\t\t}\n\t};\n\n\tfunction enableDesignMode() {\n\t\tenabled = true;\n\t\tdocument.addEventListener(\"mousemove\", handleMouseMove, true);\n\t\tdocument.addEventListener(\"mouseleave\", handleMouseLeave);\n\t\tdocument.addEventListener(\"click\", handleClick, true);\n\t\tdocument.addEventListener(\"keydown\", handleKeyDown, true);\n\t}\n\n\tfunction disableDesignMode() {\n\t\tenabled = false;\n\t\tdocument.removeEventListener(\"mousemove\", handleMouseMove, true);\n\t\tdocument.removeEventListener(\"mouseleave\", handleMouseLeave);\n\t\tdocument.removeEventListener(\"click\", handleClick, true);\n\t\tdocument.removeEventListener(\"keydown\", handleKeyDown, true);\n\n\t\toverlay.style.display = \"none\";\n\t\tlabel.style.display = \"none\";\n\t\thoveredElement = null;\n\n\t\tif (selectedElement) {\n\t\t\tselectedElement.el.removeAttribute(\"data-yns-selected\");\n\t\t\tselectedElement = null;\n\t\t}\n\t}\n\n\twindow.addEventListener(\"message\", (event) => {\n\t\tconst msg = event.data;\n\t\tif (!msg || typeof msg !== \"object\") return;\n\n\t\tif (msg.type === \"design-mode-toggle\") {\n\t\t\tif (msg.enabled) {\n\t\t\t\tenableDesignMode();\n\t\t\t} else {\n\t\t\t\tdisableDesignMode();\n\t\t\t\twindow.parent.postMessage({ type: \"design-mode-cleared\" }, \"*\");\n\t\t\t}\n\t\t}\n\n\t\tif (msg.type === \"design-mode-deselect\") {\n\t\t\tif (selectedElement) {\n\t\t\t\tselectedElement.el.removeAttribute(\"data-yns-selected\");\n\t\t\t\tselectedElement = null;\n\t\t\t}\n\t\t}\n\t});\n}\n\nfunction initCommentModeInspector() {\n\tlet enabled = false;\n\tlet hoveredElement: Element | null = null;\n\tlet pins: Array<{ id: string; selector: string; number: number }> = [];\n\n\tconst overlay = document.createElement(\"div\");\n\toverlay.setAttribute(\"data-yns-comment-overlay\", \"hover\");\n\toverlay.style.cssText = [\n\t\t\"position: fixed\",\n\t\t\"pointer-events: none\",\n\t\t\"z-index: 2147483644\",\n\t\t\"border: 2px dashed #10b981\",\n\t\t\"background: rgba(16, 185, 129, 0.06)\",\n\t\t\"border-radius: 3px\",\n\t\t\"display: none\",\n\t\t\"transition: top 0.05s, left 0.05s, width 0.05s, height 0.05s\",\n\t].join(\";\");\n\n\tconst cursorLabel = document.createElement(\"div\");\n\tcursorLabel.setAttribute(\"data-yns-comment-overlay\", \"cursor-label\");\n\tcursorLabel.textContent = \"Click to comment\";\n\tcursorLabel.style.cssText = [\n\t\t\"position: fixed\",\n\t\t\"pointer-events: none\",\n\t\t\"z-index: 2147483645\",\n\t\t\"background: #059669\",\n\t\t\"color: #fff\",\n\t\t\"font-size: 11px\",\n\t\t\"font-family: ui-sans-serif, system-ui, sans-serif\",\n\t\t\"padding: 3px 8px\",\n\t\t\"border-radius: 4px\",\n\t\t\"white-space: nowrap\",\n\t\t\"display: none\",\n\t\t\"box-shadow: 0 2px 6px rgba(0,0,0,0.15)\",\n\t].join(\";\");\n\n\tconst pinContainer = document.createElement(\"div\");\n\tpinContainer.setAttribute(\"data-yns-comment-overlay\", \"pins\");\n\tpinContainer.style.cssText =\n\t\t\"position: fixed; top: 0; left: 0; width: 100%; height: 100%; pointer-events: none; z-index: 2147483643;\";\n\n\tdocument.documentElement.appendChild(overlay);\n\tdocument.documentElement.appendChild(cursorLabel);\n\tdocument.documentElement.appendChild(pinContainer);\n\n\tfunction renderPins() {\n\t\tpinContainer.innerHTML = \"\";\n\t\tfor (const pin of pins) {\n\t\t\tlet el: Element | null = null;\n\t\t\ttry {\n\t\t\t\tel = document.querySelector(pin.selector);\n\t\t\t} catch {\n\t\t\t\tel = null;\n\t\t\t}\n\t\t\tif (!el) continue;\n\n\t\t\tconst r = el.getBoundingClientRect();\n\t\t\tconst pinEl = document.createElement(\"div\");\n\t\t\tpinEl.style.cssText = [\n\t\t\t\t\"position: fixed\",\n\t\t\t\t`top: ${r.top - 12}px`,\n\t\t\t\t`left: ${r.left + r.width / 2 - 12}px`,\n\t\t\t\t\"width: 24px\",\n\t\t\t\t\"height: 24px\",\n\t\t\t\t\"border-radius: 50%\",\n\t\t\t\t\"background: #059669\",\n\t\t\t\t\"color: #fff\",\n\t\t\t\t\"display: flex\",\n\t\t\t\t\"align-items: center\",\n\t\t\t\t\"justify-content: center\",\n\t\t\t\t\"font-size: 12px\",\n\t\t\t\t\"font-weight: 600\",\n\t\t\t\t\"font-family: ui-sans-serif, system-ui, sans-serif\",\n\t\t\t\t\"box-shadow: 0 2px 8px rgba(0,0,0,0.2)\",\n\t\t\t\t\"pointer-events: none\",\n\t\t\t].join(\";\");\n\t\t\tpinEl.textContent = String(pin.number);\n\t\t\tpinContainer.appendChild(pinEl);\n\t\t}\n\t}\n\n\tconst handleMouseMove = (e: MouseEvent) => {\n\t\tconst el = document.elementFromPoint(e.clientX, e.clientY);\n\t\tif (shouldIgnore(el, [\"data-yns-comment-overlay\", \"data-yns-design-overlay\"])) {\n\t\t\toverlay.style.display = \"none\";\n\t\t\tcursorLabel.style.display = \"none\";\n\t\t\thoveredElement = null;\n\t\t\treturn;\n\t\t}\n\t\thoveredElement = el;\n\t\trequestAnimationFrame(() => {\n\t\t\tif (hoveredElement === el && enabled && el) {\n\t\t\t\tconst rect = el.getBoundingClientRect();\n\t\t\t\toverlay.style.top = `${rect.top}px`;\n\t\t\t\toverlay.style.left = `${rect.left}px`;\n\t\t\t\toverlay.style.width = `${rect.width}px`;\n\t\t\t\toverlay.style.height = `${rect.height}px`;\n\t\t\t\toverlay.style.display = \"block\";\n\n\t\t\t\tcursorLabel.style.left = `${e.clientX + 14}px`;\n\t\t\t\tcursorLabel.style.top = `${e.clientY + 14}px`;\n\t\t\t\tcursorLabel.style.display = \"block\";\n\t\t\t}\n\t\t});\n\t};\n\n\tconst handleMouseLeave = () => {\n\t\toverlay.style.display = \"none\";\n\t\tcursorLabel.style.display = \"none\";\n\t\thoveredElement = null;\n\t};\n\n\tconst handleClick = (e: MouseEvent) => {\n\t\tif (!enabled || !hoveredElement) return;\n\t\te.preventDefault();\n\t\te.stopPropagation();\n\t\te.stopImmediatePropagation();\n\n\t\tconst el = hoveredElement;\n\t\tif (shouldIgnore(el, [\"data-yns-comment-overlay\", \"data-yns-design-overlay\"])) return;\n\n\t\tconst info = buildElementInfo(el, 200);\n\t\tconst rect = el.getBoundingClientRect();\n\n\t\twindow.parent.postMessage(\n\t\t\t{\n\t\t\t\ttype: \"comment-click\",\n\t\t\t\tdata: {\n\t\t\t\t\telement: info,\n\t\t\t\t\tclickPosition: { x: e.clientX, y: e.clientY },\n\t\t\t\t\telementRect: { top: rect.top, left: rect.left, width: rect.width, height: rect.height },\n\t\t\t\t\tpagePath: window.location.pathname,\n\t\t\t\t},\n\t\t\t},\n\t\t\t\"*\",\n\t\t);\n\t};\n\n\tconst handleKeyDown = (e: KeyboardEvent) => {\n\t\tif (e.key === \"Escape\" && enabled) {\n\t\t\tdisableCommentMode();\n\t\t\twindow.parent.postMessage({ type: \"comment-mode-cleared\" }, \"*\");\n\t\t}\n\t};\n\n\tfunction enableCommentMode() {\n\t\tenabled = true;\n\t\tdocument.body.style.cursor = \"crosshair\";\n\t\tdocument.addEventListener(\"mousemove\", handleMouseMove, true);\n\t\tdocument.addEventListener(\"mouseleave\", handleMouseLeave);\n\t\tdocument.addEventListener(\"click\", handleClick, true);\n\t\tdocument.addEventListener(\"keydown\", handleKeyDown, true);\n\t}\n\n\tfunction disableCommentMode() {\n\t\tenabled = false;\n\t\tdocument.body.style.cursor = \"\";\n\t\tdocument.removeEventListener(\"mousemove\", handleMouseMove, true);\n\t\tdocument.removeEventListener(\"mouseleave\", handleMouseLeave);\n\t\tdocument.removeEventListener(\"click\", handleClick, true);\n\t\tdocument.removeEventListener(\"keydown\", handleKeyDown, true);\n\n\t\toverlay.style.display = \"none\";\n\t\tcursorLabel.style.display = \"none\";\n\t\thoveredElement = null;\n\t}\n\n\tlet rafPending = false;\n\tconst scheduleRender = () => {\n\t\tif (rafPending) return;\n\t\trafPending = true;\n\t\trequestAnimationFrame(() => {\n\t\t\trafPending = false;\n\t\t\trenderPins();\n\t\t});\n\t};\n\twindow.addEventListener(\"scroll\", scheduleRender, { passive: true });\n\twindow.addEventListener(\"resize\", scheduleRender, { passive: true });\n\n\twindow.addEventListener(\"message\", (event) => {\n\t\tconst msg = event.data;\n\t\tif (!msg || typeof msg !== \"object\") return;\n\n\t\tif (msg.type === \"comment-mode-toggle\") {\n\t\t\tif (msg.enabled) enableCommentMode();\n\t\t\telse disableCommentMode();\n\t\t}\n\n\t\tif (msg.type === \"comment-pins-update\") {\n\t\t\tpins = msg.pins ?? [];\n\t\t\trenderPins();\n\t\t}\n\n\t\tif (msg.type === \"comment-pin-remove\") {\n\t\t\tpins = pins.filter((p) => p.id !== msg.pinId);\n\t\t\trenderPins();\n\t\t}\n\t});\n}\n"],"mappings":"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","names":["useEffect","useRef","useState","createRoot","Fragment","jsx","jsxs","MOUNT_NODE_ID","buildApiBase","override","host","protocol","computeCssSelector","el","path","node","part","className","classes","c","parent","tag","siblings","idx","ATTRS_OF_INTEREST","formatAttrs","parts","attr","v","trimmed","formatTextContent","text","buildSurroundingHtml","target","ancestors","cur","lines","depth","ancestor","indent","targetIndent","targetTag","targetText","childIndent","children","child","childText","i","isInsideToolbar","IGNORED_TAGS","FeedbackToolbar","session","setSession","loading","setLoading","pinMode","setPinMode","pending","setPending","editingId","setEditingId","sidebarOpen","setSidebarOpen","finalizing","setFinalizing","apiBase","controller","res","data","overlay","label","hovered","handleMove","e","rect","handleLeave","handleClick","event","offsetXRatio","offsetYRatio","refreshComments","submitNewComment","content","updateComment","id","removeComment","finalizeSession","prev","scrollToComment","comment","visiblePins","pin","PinOverlay","PendingCommentPopover","CommentsSidebar","toolbarStyle","toolbarButtonActiveStyle","toolbarButtonStyle","toolbarButtonGhostStyle","toolbarButtonFinalizeStyle","toolbarHintStyle","number","editing","onStartEdit","onCancelEdit","onSave","onRemove","useTargetPosition","pinDotStyle","EditPopover","onCancel","comments","currentPath","onClose","onSelect","groups","list","paths","a","b","sidebarStyle","sidebarHeaderStyle","ghostButtonStyle","sidebarScrollStyle","sidebarEmptyStyle","sidebarPathStyle","sidebarItemStyle","sidebarItemIndexStyle","sidebarItemTextStyle","sidebarItemDoneStyle","initial","value","setValue","saving","setSaving","textareaRef","len","popoverStyle","textareaStyle","popoverActionsStyle","dangerButtonStyle","primaryButtonStyle","selector","pos","setPos","update","r","ro","baseButton","mountFeedbackToolbar","container","root","startSandboxInspectors","initDesignModeInspector","initCommentModeInspector","IGNORED_TAGS","generateCssSelector","el","parts","current","selector","classes","c","parent","tag","s","index","buildElementInfo","textLimit","rect","computed","text","shouldIgnore","overlayAttrs","attr","enabled","hoveredElement","selectedElement","overlay","label","style","positionOverlay","labelText","handleMouseMove","e","handleMouseLeave","handleClick","info","handleKeyDown","disableDesignMode","enableDesignMode","event","msg","pins","cursorLabel","pinContainer","renderPins","pin","r","pinEl","disableCommentMode","enableCommentMode","rafPending","scheduleRender","p"]}
@@ -1,3 +1,3 @@
1
- import{useEffect as y,useRef as I,useState as g}from"react";import{createRoot as R}from"react-dom/client";import{jsx as m,jsxs as S}from"react/jsx-runtime";var w="yns-feedback-toolbar-root",_=()=>{if(typeof window>"u")return null;let e=(process.env.NEXT_PUBLIC_YNS_API_BASE??"").trim();if(e)return e.replace(/\/$/,"");let t=window.location.hostname,o=window.location.protocol;return t.endsWith(".yns.store")?`${o}//yns.store`:t.endsWith(".yns.cx")?`${o}//yns.cx`:window.location.origin},B=e=>{if(e.id)return`#${CSS.escape(e.id)}`;let t=[],o=e;for(;o&&o.nodeType===Node.ELEMENT_NODE&&t.length<6;){let n=o.tagName.toLowerCase(),i=o.getAttribute("class");if(i){let d=i.split(/\s+/).filter(Boolean).slice(0,2).map(s=>`.${CSS.escape(s)}`).join("");n+=d}let c=o.parentElement,l=o.tagName;if(c){let d=Array.from(c.children).filter(s=>s.tagName===l);if(d.length>1){let s=d.indexOf(o)+1;n+=`:nth-of-type(${s})`}}t.unshift(n),o=c}return t.join(" > ")},A=["id","class","data-testid","aria-label","role","name","href","src"],v=e=>{let t=[];for(let o of A){let n=e.getAttribute(o);if(!n)continue;let i=n.length>80?`${n.slice(0,80)}\u2026`:n;t.push(` ${o}="${i.replace(/"/g,"&quot;")}"`)}return t.join("")},k=e=>{let t=(e.textContent??"").replace(/\s+/g," ").trim();return t?t.length>100?`${t.slice(0,100)}\u2026`:t:""},F=e=>{let t=[],o=e;for(;o&&o!==document.documentElement&&t.length<5;){let s=o.parentElement;if(!s)break;t.unshift(s),o=s}let n=[],i=0;for(let s of t){let p=" ".repeat(i);n.push(`${p}<${s.tagName.toLowerCase()}${v(s)}>`),i++}let c=" ".repeat(i),l=e.tagName.toLowerCase(),d=k(e);if(n.push(`${c}<${l}${v(e)}>${d?`${d}</${l}>`:""} \u2190 TARGET`),!d){let s=" ".repeat(i+1),p=Array.from(e.children).slice(0,6);for(let a of p){let b=k(a);n.push(`${s}<${a.tagName.toLowerCase()}${v(a)}>${b?`${b}</${a.tagName.toLowerCase()}>`:""}`)}e.children.length>6&&n.push(`${s}\u2026 (${e.children.length-6} more children)`),n.push(`${c}</${l}>`)}for(let s=t.length-1;s>=0;s--){let p=" ".repeat(s),a=t[s];a&&n.push(`${p}</${a.tagName.toLowerCase()}>`)}return n.join(`
2
- `)},U=e=>{let t=e;for(;t;){if(t instanceof HTMLElement&&t.dataset.ynsFeedbackUi==="true")return!0;t=t.parentElement}return!1};function X(){let[e,t]=g(null),[o,n]=g(!0),[i,c]=g(!1),[l,d]=g(null),[s,p]=g(null),a=I(null);y(()=>{if(a.current=_(),!a.current){n(!1);return}let r=new AbortController;return fetch(`${a.current}/api/feedback-comments?host=${encodeURIComponent(window.location.host)}`,{credentials:"include",signal:r.signal}).then(async u=>{if(!u.ok){t(null);return}let f=await u.json();t(f)}).catch(()=>{t(null)}).finally(()=>n(!1)),()=>r.abort()},[]),y(()=>{if(i)return document.body.style.cursor="crosshair",()=>{document.body.style.cursor=""}},[i]),y(()=>{if(!i)return;let r=u=>{let f=u.target;if(!(f instanceof Element)||U(f))return;u.preventDefault(),u.stopPropagation();let h=f.getBoundingClientRect();d({cssSelector:B(f),pagePath:window.location.pathname,surroundingHtml:F(f),rect:{top:h.top+window.scrollY,left:h.left+window.scrollX,width:h.width,height:h.height},clickX:u.clientX+window.scrollX,clickY:u.clientY+window.scrollY}),c(!1)};return document.addEventListener("click",r,{capture:!0}),()=>document.removeEventListener("click",r,{capture:!0})},[i]);let b=async()=>{if(!a.current)return;let r=await fetch(`${a.current}/api/feedback-comments?host=${encodeURIComponent(window.location.host)}`,{credentials:"include"});if(!r.ok)return;let u=await r.json();t(u)},N=async r=>{!a.current||!e||!l||!(await fetch(`${a.current}/api/feedback-comments`,{method:"POST",credentials:"include",headers:{"Content-Type":"application/json"},body:JSON.stringify({feedbackSessionId:e.feedbackSessionId,content:r,pagePath:l.pagePath,cssSelector:l.cssSelector,surroundingHtml:l.surroundingHtml})})).ok||(d(null),await b())},T=async(r,u)=>{!a.current||!(await fetch(`${a.current}/api/feedback-comments/${r}`,{method:"PATCH",credentials:"include",headers:{"Content-Type":"application/json"},body:JSON.stringify({content:u})})).ok||(p(null),await b())},L=async r=>{!a.current||!(await fetch(`${a.current}/api/feedback-comments/${r}`,{method:"DELETE",credentials:"include"})).ok||await b()};if(o||!e||!e.canComment)return null;let C=e.comments.filter(r=>r.pagePath===window.location.pathname&&r.status!=="done");return S("div",{"data-yns-feedback-ui":"true",children:[C.map((r,u)=>m(V,{pin:r,number:u+1,editing:s===r.id,onStartEdit:()=>p(r.id),onCancelEdit:()=>p(null),onSave:f=>T(r.id,f),onRemove:()=>L(r.id)},r.id)),l&&m(z,{pending:l,onCancel:()=>d(null),onSave:r=>N(r)}),S("div",{style:M,children:[m("button",{type:"button",onClick:()=>c(r=>!r),style:i?O:$,children:i?"Cancel":"Add comment"}),m("span",{style:Y,children:i?"Click any element to comment":`${C.length} on this page`})]})]})}function V({pin:e,number:t,editing:o,onStartEdit:n,onCancelEdit:i,onSave:c,onRemove:l}){let d=j(e.cssSelector);return d?S("div",{style:{position:"absolute",top:d.top,left:d.left,zIndex:2147483600,pointerEvents:"auto"},children:[m("button",{type:"button",onClick:n,style:D,title:e.content,children:t}),o&&m(x,{initial:e.content,onCancel:i,onSave:c,onRemove:l})]}):null}function z({pending:e,onCancel:t,onSave:o}){return m("div",{style:{position:"absolute",top:e.clickY+10,left:e.clickX+10,zIndex:2147483647},children:m(x,{initial:"",onCancel:t,onSave:o})})}function x({initial:e,onCancel:t,onSave:o,onRemove:n}){let[i,c]=g(e),[l,d]=g(!1);return S("form",{onSubmit:async p=>{p.preventDefault();let a=i.trim();if(a){d(!0);try{await o(a)}finally{d(!1)}}},style:H,children:[m("textarea",{value:i,onChange:p=>c(p.target.value),placeholder:"Leave a comment\u2026",style:W,rows:3}),S("div",{style:q,children:[n&&m("button",{type:"button",onClick:()=>n(),style:K,disabled:l,children:"Delete"}),m("div",{style:{flex:1}}),m("button",{type:"button",onClick:t,style:G,disabled:l,children:"Cancel"}),m("button",{type:"submit",style:J,disabled:l||!i.trim(),children:l?"Saving\u2026":"Save"})]})]})}function j(e){let[t,o]=g(null);return y(()=>{let n=()=>{let c=null;try{c=document.querySelector(e)}catch{c=null}if(!c){o(null);return}let l=c.getBoundingClientRect();o({top:l.top+window.scrollY-12,left:l.left+window.scrollX-12})};n();let i=new ResizeObserver(n);try{let c=document.querySelector(e);c&&i.observe(c)}catch{}return window.addEventListener("scroll",n,!0),window.addEventListener("resize",n),()=>{i.disconnect(),window.removeEventListener("scroll",n,!0),window.removeEventListener("resize",n)}},[e]),t}var M={position:"fixed",bottom:16,left:"50%",transform:"translateX(-50%)",zIndex:2147483646,display:"flex",alignItems:"center",gap:12,padding:"8px 12px",background:"rgba(17, 17, 17, 0.92)",color:"white",borderRadius:999,boxShadow:"0 8px 24px rgba(0,0,0,0.25)",fontFamily:'-apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Helvetica, Arial, sans-serif, "Apple Color Emoji", "Segoe UI Emoji"',fontSize:14,pointerEvents:"auto"},$={border:"none",background:"white",color:"#111",padding:"6px 12px",borderRadius:999,cursor:"pointer",fontWeight:600,fontSize:13},O={...$,background:"#ef4444",color:"white"},Y={opacity:.8,fontSize:12},D={width:24,height:24,borderRadius:999,background:"#10b981",color:"white",border:"2px solid white",cursor:"pointer",fontSize:12,fontWeight:700,boxShadow:"0 2px 6px rgba(0,0,0,0.3)",display:"inline-flex",alignItems:"center",justifyContent:"center",padding:0},H={background:"white",border:"1px solid #e5e7eb",borderRadius:8,padding:12,width:280,boxShadow:"0 12px 32px rgba(0,0,0,0.18)",fontFamily:'-apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Helvetica, Arial, sans-serif, "Apple Color Emoji", "Segoe UI Emoji"',display:"flex",flexDirection:"column",gap:8,color:"#111"},W={width:"100%",border:"1px solid #d1d5db",borderRadius:6,padding:8,fontSize:14,resize:"vertical",fontFamily:"inherit",color:"#111",background:"white",boxSizing:"border-box"},q={display:"flex",alignItems:"center",gap:6},E={border:"1px solid transparent",borderRadius:6,padding:"6px 10px",fontSize:13,cursor:"pointer",fontWeight:500},J={...E,background:"#111",color:"white"},G={...E,background:"transparent",color:"#374151",borderColor:"#d1d5db"},K={...E,background:"transparent",color:"#b91c1c",borderColor:"#fecaca"};function P(){if(console.log("[YNS Feedback Toolbar] mountFeedbackToolbar() called",{isWindow:typeof window<"u",vercelEnv:process.env.NEXT_PUBLIC_VERCEL_ENV,alreadyMounted:typeof document<"u"&&!!document.getElementById(w)}),typeof window>"u")return null;if(process.env.NEXT_PUBLIC_VERCEL_ENV!=="preview")return console.log("[YNS Feedback Toolbar] gate failed \u2014 NEXT_PUBLIC_VERCEL_ENV is",process.env.NEXT_PUBLIC_VERCEL_ENV),null;if(document.getElementById(w))return null;let e=document.createElement("div");e.id=w,e.dataset.ynsFeedbackUi="true",document.body.appendChild(e);let t=R(e);return t.render(m(X,{})),{unmount:()=>{t.unmount(),e.remove()}}}typeof window<"u"&&console.log("[YNS Feedback Toolbar] module evaluated",{vercelEnv:process.env.NEXT_PUBLIC_VERCEL_ENV,readyState:document.readyState,willAutoMount:process.env.NEXT_PUBLIC_VERCEL_ENV==="preview"});typeof window<"u"&&process.env.NEXT_PUBLIC_VERCEL_ENV==="preview"&&(document.readyState==="loading"?document.addEventListener("DOMContentLoaded",()=>{P()}):P());export{P as mountFeedbackToolbar};
1
+ import{useEffect as C,useRef as B,useState as S}from"react";import{createRoot as V}from"react-dom/client";import{Fragment as we,jsx as d,jsxs as y}from"react/jsx-runtime";var P="yns-feedback-toolbar-root",D=()=>{if(typeof window>"u")return null;let e=(process.env.NEXT_PUBLIC_YNS_API_BASE??"").trim();if(e)return e.replace(/\/$/,"");let t=window.location.hostname,l=window.location.protocol;return t.endsWith(".yns.store")?`${l}//yns.store`:t.endsWith(".yns.cx")?`${l}//yns.cx`:window.location.origin},W=e=>{if(e.id)return`#${CSS.escape(e.id)}`;let t=[],l=e;for(;l&&l.nodeType===Node.ELEMENT_NODE&&t.length<6;){let c=l.tagName.toLowerCase(),s=l.getAttribute("class");if(s){let o=s.split(/\s+/).filter(Boolean).slice(0,2).map(a=>`.${CSS.escape(a)}`).join("");c+=o}let u=l.parentElement,r=l.tagName;if(u){let o=Array.from(u.children).filter(a=>a.tagName===r);if(o.length>1){let a=o.indexOf(l)+1;c+=`:nth-of-type(${a})`}}t.unshift(c),l=u}return t.join(" > ")},q=["id","class","data-testid","aria-label","role","name","href","src"],R=e=>{let t=[];for(let l of q){let c=e.getAttribute(l);if(!c)continue;let s=c.length>80?`${c.slice(0,80)}\u2026`:c;t.push(` ${l}="${s.replace(/"/g,"&quot;")}"`)}return t.join("")},N=e=>{let t=(e.textContent??"").replace(/\s+/g," ").trim();return t?t.length>100?`${t.slice(0,100)}\u2026`:t:""},G=e=>{let t=[],l=e;for(;l&&l!==document.documentElement&&t.length<5;){let a=l.parentElement;if(!a)break;t.unshift(a),l=a}let c=[],s=0;for(let a of t){let g=" ".repeat(s);c.push(`${g}<${a.tagName.toLowerCase()}${R(a)}>`),s++}let u=" ".repeat(s),r=e.tagName.toLowerCase(),o=N(e);if(c.push(`${u}<${r}${R(e)}>${o?`${o}</${r}>`:""} \u2190 TARGET`),!o){let a=" ".repeat(s+1),g=Array.from(e.children).slice(0,6);for(let p of g){let h=N(p);c.push(`${a}<${p.tagName.toLowerCase()}${R(p)}>${h?`${h}</${p.tagName.toLowerCase()}>`:""}`)}e.children.length>6&&c.push(`${a}\u2026 (${e.children.length-6} more children)`),c.push(`${u}</${r}>`)}for(let a=t.length-1;a>=0;a--){let g=" ".repeat(a),p=t[a];p&&c.push(`${g}</${p.tagName.toLowerCase()}>`)}return c.join(`
2
+ `)},z=e=>{let t=e;for(;t;){if(t instanceof HTMLElement&&t.dataset.ynsFeedbackUi==="true")return!0;t=t.parentElement}return!1},J=new Set(["HTML","HEAD","SCRIPT","STYLE","NOSCRIPT"]);function K(){let[e,t]=S(null),[l,c]=S(!0),[s,u]=S(!1),[r,o]=S(null),[a,g]=S(null),[p,h]=S(!1),[I,T]=S(!1),f=B(null);C(()=>{if(f.current=D(),!f.current){c(!1);return}let n=new AbortController;return fetch(`${f.current}/api/feedback-comments?host=${encodeURIComponent(window.location.host)}`,{credentials:"include",signal:n.signal}).then(async i=>{if(!i.ok){t(null);return}let m=await i.json();t(m)}).catch(()=>{t(null)}).finally(()=>c(!1)),()=>n.abort()},[]),C(()=>{if(s)return document.body.style.cursor="crosshair",()=>{document.body.style.cursor=""}},[s]),C(()=>{if(!s)return;let n=document.createElement("div");n.dataset.ynsFeedbackUi="true",n.style.cssText=["position: fixed","pointer-events: none","z-index: 2147483644","border: 2px dashed #10b981","background: rgba(16, 185, 129, 0.08)","border-radius: 3px","display: none","transition: top 0.05s, left 0.05s, width 0.05s, height 0.05s"].join(";");let i=document.createElement("div");i.dataset.ynsFeedbackUi="true",i.textContent="Click to comment",i.style.cssText=["position: fixed","pointer-events: none","z-index: 2147483645","background: #059669","color: #fff","font-size: 11px","font-family: ui-sans-serif, system-ui, sans-serif","padding: 3px 8px","border-radius: 4px","white-space: nowrap","display: none","box-shadow: 0 2px 6px rgba(0,0,0,0.15)"].join(";"),document.documentElement.appendChild(n),document.documentElement.appendChild(i);let m=null,b=v=>{let w=document.elementFromPoint(v.clientX,v.clientY);if(!w||J.has(w.tagName)||z(w)){n.style.display="none",i.style.display="none",m=null;return}m=w,requestAnimationFrame(()=>{if(m!==w)return;let E=w.getBoundingClientRect();n.style.top=`${E.top}px`,n.style.left=`${E.left}px`,n.style.width=`${E.width}px`,n.style.height=`${E.height}px`,n.style.display="block",i.style.left=`${v.clientX+14}px`,i.style.top=`${v.clientY+14}px`,i.style.display="block"})},x=()=>{n.style.display="none",i.style.display="none",m=null};return document.addEventListener("mousemove",b,!0),document.addEventListener("mouseleave",x),()=>{document.removeEventListener("mousemove",b,!0),document.removeEventListener("mouseleave",x),n.remove(),i.remove()}},[s]),C(()=>{if(!s)return;let n=i=>{let m=i.target;if(!(m instanceof Element)||z(m))return;i.preventDefault(),i.stopPropagation();let b=m.getBoundingClientRect(),x=b.width>0?(i.clientX-b.left)/b.width:.5,v=b.height>0?(i.clientY-b.top)/b.height:.5;o({cssSelector:W(m),pagePath:window.location.pathname,surroundingHtml:G(m),rect:{top:b.top+window.scrollY,left:b.left+window.scrollX,width:b.width,height:b.height},clickX:i.clientX+window.scrollX,clickY:i.clientY+window.scrollY,offsetXRatio:Math.min(1,Math.max(0,x)),offsetYRatio:Math.min(1,Math.max(0,v))}),u(!1)};return document.addEventListener("click",n,{capture:!0}),()=>document.removeEventListener("click",n,{capture:!0})},[s]);let k=async()=>{if(!f.current)return;let n=await fetch(`${f.current}/api/feedback-comments?host=${encodeURIComponent(window.location.host)}`,{credentials:"include"});if(!n.ok)return;let i=await n.json();t(i)},M=async n=>{!f.current||!e||!r||!(await fetch(`${f.current}/api/feedback-comments`,{method:"POST",credentials:"include",headers:{"Content-Type":"application/json"},body:JSON.stringify({feedbackSessionId:e.feedbackSessionId,content:n,pagePath:r.pagePath,cssSelector:r.cssSelector,surroundingHtml:r.surroundingHtml,offsetXRatio:r.offsetXRatio,offsetYRatio:r.offsetYRatio})})).ok||(o(null),u(!0),await k())},U=async(n,i)=>{!f.current||!(await fetch(`${f.current}/api/feedback-comments/${n}`,{method:"PATCH",credentials:"include",headers:{"Content-Type":"application/json"},body:JSON.stringify({content:i})})).ok||(g(null),await k())},j=async n=>{!f.current||!(await fetch(`${f.current}/api/feedback-comments/${n}`,{method:"DELETE",credentials:"include"})).ok||await k()},H=async()=>{if(!(!f.current||!e)&&window.confirm("Finalize this feedback session? You won't be able to add more comments.")){T(!0);try{if(!(await fetch(`${f.current}/api/feedback-sessions/${e.feedbackSessionId}/finalize`,{method:"POST",credentials:"include"})).ok)return;t(i=>i&&{...i,canComment:!1})}finally{T(!1)}}},O=n=>{if(n.pagePath!==window.location.pathname){window.location.assign(n.pagePath);return}let i=null;try{i=document.querySelector(n.cssSelector)}catch{i=null}i&&(i.scrollIntoView({behavior:"smooth",block:"center"}),g(n.id))};if(l||!e||!e.canComment)return null;let L=e.comments.filter(n=>n.pagePath===window.location.pathname&&n.status!=="done");return y("div",{"data-yns-feedback-ui":"true",children:[L.map((n,i)=>d(Q,{pin:n,number:i+1,editing:a===n.id,onStartEdit:()=>g(n.id),onCancelEdit:()=>g(null),onSave:m=>U(n.id,m),onRemove:()=>j(n.id)},n.id)),r&&d(Z,{pending:r,onCancel:()=>{o(null),u(!0)},onSave:n=>M(n)}),p&&d(ee,{comments:e.comments,currentPath:window.location.pathname,onClose:()=>h(!1),onSelect:O}),y("div",{style:ne,children:[d("button",{type:"button",onClick:()=>u(n=>!n),style:s?oe:_,children:s?"Cancel":"Add comment"}),d("button",{type:"button",onClick:()=>h(n=>!n),style:ie,children:p?"Hide list":`List (${e.comments.length})`}),d("button",{type:"button",onClick:H,disabled:I,style:re,children:I?"Finalizing\u2026":"Finalize"}),d("span",{style:se,children:s?"Click any element to comment":`${L.length} on this page`})]})]})}function Q({pin:e,number:t,editing:l,onStartEdit:c,onCancelEdit:s,onSave:u,onRemove:r}){let o=te(e.cssSelector,e.offsetXRatio,e.offsetYRatio);return o?y("div",{style:{position:"absolute",top:o.top,left:o.left,zIndex:2147483600,pointerEvents:"auto"},children:[d("button",{type:"button",onClick:c,style:X,title:e.content,children:t}),l&&d(F,{initial:e.content,onCancel:s,onSave:u,onRemove:r})]}):null}function Z({pending:e,onCancel:t,onSave:l}){return y(we,{children:[d("div",{style:{position:"absolute",top:e.rect.top+e.rect.height*e.offsetYRatio-12,left:e.rect.left+e.rect.width*e.offsetXRatio-12,zIndex:2147483600,pointerEvents:"none"},children:d("div",{style:X,children:"\u2022"})}),d("div",{style:{position:"absolute",top:e.clickY+10,left:e.clickX+10,zIndex:2147483647},children:d(F,{initial:"",onCancel:t,onSave:l})})]})}function ee({comments:e,currentPath:t,onClose:l,onSelect:c}){let s=new Map;for(let r of e){let o=s.get(r.pagePath)??[];o.push(r),s.set(r.pagePath,o)}let u=Array.from(s.keys()).sort((r,o)=>r===t?-1:o===t?1:r.localeCompare(o));return y("div",{style:pe,children:[y("div",{style:me,children:[y("strong",{style:{fontSize:14},children:["Comments (",e.length,")"]}),d("button",{type:"button",onClick:l,style:Y,children:"Close"})]}),d("div",{style:fe,children:e.length===0?d("div",{style:be,children:"No comments yet. Click \u201CAdd comment\u201D to leave one."}):u.map(r=>y("div",{style:{marginBottom:12},children:[d("div",{style:ge,children:r===t?`${r} \xB7 current`:r}),(s.get(r)??[]).map((o,a)=>y("button",{type:"button",onClick:()=>c(o),style:he,disabled:o.status==="done"&&!1,children:[d("span",{style:ye,children:a+1}),d("span",{style:Se,children:o.content.length>140?`${o.content.slice(0,140)}\u2026`:o.content}),o.status==="done"&&d("span",{style:ve,children:"done"})]},o.id))]},r))})]})}function F({initial:e,onCancel:t,onSave:l,onRemove:c}){let[s,u]=S(e),[r,o]=S(!1),a=B(null);return C(()=>{let p=a.current;if(!p)return;p.focus();let h=p.value.length;p.setSelectionRange(h,h)},[]),y("form",{onSubmit:async p=>{p.preventDefault();let h=s.trim();if(h){o(!0);try{await l(h)}finally{o(!1)}}},style:le,children:[d("textarea",{ref:a,value:s,onChange:p=>u(p.target.value),placeholder:"Leave a comment\u2026",style:ae,rows:3}),y("div",{style:ce,children:[c&&d("button",{type:"button",onClick:()=>c(),style:ue,disabled:r,children:"Delete"}),d("div",{style:{flex:1}}),d("button",{type:"button",onClick:t,style:Y,disabled:r,children:"Cancel"}),d("button",{type:"submit",style:de,disabled:r||!s.trim(),children:r?"Saving\u2026":"Save"})]})]})}function te(e,t,l){let[c,s]=S(null);return C(()=>{let u=()=>{let o=null;try{o=document.querySelector(e)}catch{o=null}if(!o){s(null);return}let a=o.getBoundingClientRect();s({top:a.top+window.scrollY+a.height*l-12,left:a.left+window.scrollX+a.width*t-12})};u();let r=new ResizeObserver(u);try{let o=document.querySelector(e);o&&r.observe(o)}catch{}return window.addEventListener("scroll",u,!0),window.addEventListener("resize",u),()=>{r.disconnect(),window.removeEventListener("scroll",u,!0),window.removeEventListener("resize",u)}},[e,t,l]),c}var ne={position:"fixed",bottom:16,left:"50%",transform:"translateX(-50%)",zIndex:2147483646,display:"flex",alignItems:"center",gap:8,padding:"8px 12px",background:"rgba(17, 17, 17, 0.92)",color:"white",borderRadius:999,boxShadow:"0 8px 24px rgba(0,0,0,0.25)",fontFamily:'-apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Helvetica, Arial, sans-serif, "Apple Color Emoji", "Segoe UI Emoji"',fontSize:14,pointerEvents:"auto"},_={border:"none",background:"white",color:"#111",padding:"6px 12px",borderRadius:999,cursor:"pointer",fontWeight:600,fontSize:13},oe={..._,background:"#ef4444",color:"white"},ie={border:"1px solid rgba(255,255,255,0.4)",background:"transparent",color:"white",padding:"6px 12px",borderRadius:999,cursor:"pointer",fontWeight:500,fontSize:13},re={border:"none",background:"#10b981",color:"white",padding:"6px 12px",borderRadius:999,cursor:"pointer",fontWeight:600,fontSize:13},se={opacity:.8,fontSize:12},X={width:24,height:24,borderRadius:999,background:"#10b981",color:"white",border:"2px solid white",cursor:"pointer",fontSize:12,fontWeight:700,boxShadow:"0 2px 6px rgba(0,0,0,0.3)",display:"inline-flex",alignItems:"center",justifyContent:"center",padding:0},le={background:"white",border:"1px solid #e5e7eb",borderRadius:8,padding:12,width:280,boxShadow:"0 12px 32px rgba(0,0,0,0.18)",fontFamily:'-apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Helvetica, Arial, sans-serif, "Apple Color Emoji", "Segoe UI Emoji"',display:"flex",flexDirection:"column",gap:8,color:"#111"},ae={width:"100%",border:"1px solid #d1d5db",borderRadius:6,padding:8,fontSize:14,resize:"vertical",fontFamily:"inherit",color:"#111",background:"white",boxSizing:"border-box"},ce={display:"flex",alignItems:"center",gap:6},$={border:"1px solid transparent",borderRadius:6,padding:"6px 10px",fontSize:13,cursor:"pointer",fontWeight:500},de={...$,background:"#111",color:"white"},Y={...$,background:"transparent",color:"#374151",borderColor:"#d1d5db"},ue={...$,background:"transparent",color:"#b91c1c",borderColor:"#fecaca"},pe={position:"fixed",top:0,right:0,bottom:0,width:360,maxWidth:"92vw",background:"white",borderLeft:"1px solid #e5e7eb",boxShadow:"-12px 0 32px rgba(0,0,0,0.12)",zIndex:2147483646,display:"flex",flexDirection:"column",fontFamily:'-apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Helvetica, Arial, sans-serif, "Apple Color Emoji", "Segoe UI Emoji"',color:"#111"},me={display:"flex",alignItems:"center",justifyContent:"space-between",padding:"12px 16px",borderBottom:"1px solid #e5e7eb"},fe={flex:1,overflow:"auto",padding:"12px 12px 24px"},be={color:"#6b7280",fontSize:13,padding:"24px 8px",textAlign:"center"},ge={fontSize:11,textTransform:"uppercase",letterSpacing:.5,color:"#6b7280",padding:"4px 4px 6px",wordBreak:"break-all"},he={display:"flex",alignItems:"flex-start",gap:8,width:"100%",textAlign:"left",background:"white",border:"1px solid #e5e7eb",borderRadius:6,padding:"8px 10px",cursor:"pointer",fontSize:13,marginBottom:6,color:"#111"},ye={flexShrink:0,width:22,height:22,borderRadius:999,background:"#10b981",color:"white",fontWeight:700,fontSize:11,display:"inline-flex",alignItems:"center",justifyContent:"center"},Se={flex:1,whiteSpace:"pre-wrap",wordBreak:"break-word"},ve={flexShrink:0,background:"#d1fae5",color:"#065f46",fontSize:11,fontWeight:600,padding:"2px 6px",borderRadius:4,alignSelf:"center"};function A(){if(console.log("[YNS Feedback Toolbar] mountFeedbackToolbar() called",{isWindow:typeof window<"u",vercelEnv:process.env.NEXT_PUBLIC_VERCEL_ENV,alreadyMounted:typeof document<"u"&&!!document.getElementById(P)}),typeof window>"u")return null;if(process.env.NEXT_PUBLIC_VERCEL_ENV!=="preview")return console.log("[YNS Feedback Toolbar] gate failed \u2014 NEXT_PUBLIC_VERCEL_ENV is",process.env.NEXT_PUBLIC_VERCEL_ENV),null;if(document.getElementById(P))return null;let e=document.createElement("div");e.id=P,e.dataset.ynsFeedbackUi="true",document.body.appendChild(e);let t=V(e);return t.render(d(K,{})),{unmount:()=>{t.unmount(),e.remove()}}}typeof window<"u"&&console.log("[YNS Feedback Toolbar] module evaluated",{vercelEnv:process.env.NEXT_PUBLIC_VERCEL_ENV,readyState:document.readyState,willAutoMount:process.env.NEXT_PUBLIC_VERCEL_ENV==="preview"});typeof window<"u"&&process.env.NEXT_PUBLIC_VERCEL_ENV==="preview"&&(document.readyState==="loading"?document.addEventListener("DOMContentLoaded",()=>{A()}):A());export{A as mountFeedbackToolbar};
3
3
  //# sourceMappingURL=feedback-toolbar.js.map
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/feedback-toolbar.tsx"],"sourcesContent":["/**\n * Feedback session toolbar — side-effect entry.\n *\n * Importing `commerce-kit/feedback-toolbar` (or `commerce-kit/browser` for the\n * combined entry) mounts a floating toolbar onto the page that lets reviewers\n * leave click-anchored comments. Comments persist via YNS API endpoints,\n * authenticated with the `better-auth` session cookie sent through\n * `credentials: \"include\"`.\n *\n * Gated on `process.env.NEXT_PUBLIC_VERCEL_ENV === \"preview\"` — only Vercel\n * preview deploys get the toolbar. Sandbox dev (env undefined) and production\n * (env === \"production\") skip it.\n */\n\nimport { type CSSProperties, type FormEvent, useEffect, useRef, useState } from \"react\";\nimport { createRoot } from \"react-dom/client\";\n\nconst MOUNT_NODE_ID = \"yns-feedback-toolbar-root\";\n\ninterface FeedbackComment {\n\tid: string;\n\tpagePath: string;\n\tcssSelector: string;\n\tcontent: string;\n\tstatus: \"todo\" | \"done\";\n}\n\ninterface ActiveSession {\n\tfeedbackSessionId: string;\n\tcomments: FeedbackComment[];\n\tcanComment: boolean;\n}\n\ninterface PendingPin {\n\tcssSelector: string;\n\tpagePath: string;\n\tsurroundingHtml: string;\n\trect: { top: number; left: number; width: number; height: number };\n\tclickX: number;\n\tclickY: number;\n}\n\nconst buildApiBase = (): string | null => {\n\tif (typeof window === \"undefined\") return null;\n\tconst override = (process.env.NEXT_PUBLIC_YNS_API_BASE ?? \"\").trim();\n\tif (override) return override.replace(/\\/$/, \"\");\n\n\t// Toolbar runs on a per-store preview deploy (mystore-preview.yns.{store|cx})\n\t// served by the merchant's Vercel project — that host has no YNS API. Aim\n\t// at the apex `yns.store` / `yns.cx`, which yns-app serves and where the\n\t// API lives. Cookies scoped to `.yns.store` / `.yns.cx` travel along.\n\tconst host = window.location.hostname;\n\tconst protocol = window.location.protocol;\n\tif (host.endsWith(\".yns.store\")) return `${protocol}//yns.store`;\n\tif (host.endsWith(\".yns.cx\")) return `${protocol}//yns.cx`;\n\treturn window.location.origin;\n};\n\nconst computeCssSelector = (el: Element): string => {\n\tif (el.id) return `#${CSS.escape(el.id)}`;\n\tconst path: string[] = [];\n\tlet node: Element | null = el;\n\twhile (node && node.nodeType === Node.ELEMENT_NODE && path.length < 6) {\n\t\tlet part = node.tagName.toLowerCase();\n\t\tconst className = node.getAttribute(\"class\");\n\t\tif (className) {\n\t\t\tconst classes = className\n\t\t\t\t.split(/\\s+/)\n\t\t\t\t.filter(Boolean)\n\t\t\t\t.slice(0, 2)\n\t\t\t\t.map((c) => `.${CSS.escape(c)}`)\n\t\t\t\t.join(\"\");\n\t\t\tpart += classes;\n\t\t}\n\t\tconst parent: Element | null = node.parentElement;\n\t\tconst tag = node.tagName;\n\t\tif (parent) {\n\t\t\tconst siblings: Element[] = Array.from(parent.children).filter((c) => c.tagName === tag);\n\t\t\tif (siblings.length > 1) {\n\t\t\t\tconst idx = siblings.indexOf(node) + 1;\n\t\t\t\tpart += `:nth-of-type(${idx})`;\n\t\t\t}\n\t\t}\n\t\tpath.unshift(part);\n\t\tnode = parent;\n\t}\n\treturn path.join(\" > \");\n};\n\nconst ATTRS_OF_INTEREST = [\"id\", \"class\", \"data-testid\", \"aria-label\", \"role\", \"name\", \"href\", \"src\"];\n\nconst formatAttrs = (el: Element): string => {\n\tconst parts: string[] = [];\n\tfor (const attr of ATTRS_OF_INTEREST) {\n\t\tconst v = el.getAttribute(attr);\n\t\tif (!v) continue;\n\t\tconst trimmed = v.length > 80 ? `${v.slice(0, 80)}…` : v;\n\t\tparts.push(` ${attr}=\"${trimmed.replace(/\"/g, \"&quot;\")}\"`);\n\t}\n\treturn parts.join(\"\");\n};\n\nconst formatTextContent = (el: Element): string => {\n\tconst text = (el.textContent ?? \"\").replace(/\\s+/g, \" \").trim();\n\tif (!text) return \"\";\n\treturn text.length > 100 ? `${text.slice(0, 100)}…` : text;\n};\n\n/**\n * Build a compact HTML-like outline of the clicked element + its ancestors and a\n * sample of nearby children. Marks the target with `← TARGET` so the AI agent\n * can locate it later. Output stays small (< 2KB typical).\n */\nconst buildSurroundingHtml = (target: Element): string => {\n\tconst ancestors: Element[] = [];\n\tlet cur: Element | null = target;\n\twhile (cur && cur !== document.documentElement && ancestors.length < 5) {\n\t\tconst parent: Element | null = cur.parentElement;\n\t\tif (!parent) break;\n\t\tancestors.unshift(parent);\n\t\tcur = parent;\n\t}\n\n\tconst lines: string[] = [];\n\tlet depth = 0;\n\tfor (const ancestor of ancestors) {\n\t\tconst indent = \" \".repeat(depth);\n\t\tlines.push(`${indent}<${ancestor.tagName.toLowerCase()}${formatAttrs(ancestor)}>`);\n\t\tdepth++;\n\t}\n\n\tconst targetIndent = \" \".repeat(depth);\n\tconst targetTag = target.tagName.toLowerCase();\n\tconst targetText = formatTextContent(target);\n\tlines.push(\n\t\t`${targetIndent}<${targetTag}${formatAttrs(target)}>${\n\t\t\ttargetText ? `${targetText}</${targetTag}>` : \"\"\n\t\t} ← TARGET`,\n\t);\n\n\tif (!targetText) {\n\t\tconst childIndent = \" \".repeat(depth + 1);\n\t\tconst children = Array.from(target.children).slice(0, 6);\n\t\tfor (const child of children) {\n\t\t\tconst childText = formatTextContent(child);\n\t\t\tlines.push(\n\t\t\t\t`${childIndent}<${child.tagName.toLowerCase()}${formatAttrs(child)}>${\n\t\t\t\t\tchildText ? `${childText}</${child.tagName.toLowerCase()}>` : \"\"\n\t\t\t\t}`,\n\t\t\t);\n\t\t}\n\t\tif (target.children.length > 6) {\n\t\t\tlines.push(`${childIndent}… (${target.children.length - 6} more children)`);\n\t\t}\n\t\tlines.push(`${targetIndent}</${targetTag}>`);\n\t}\n\n\tfor (let i = ancestors.length - 1; i >= 0; i--) {\n\t\tconst indent = \" \".repeat(i);\n\t\tconst ancestor = ancestors[i];\n\t\tif (!ancestor) continue;\n\t\tlines.push(`${indent}</${ancestor.tagName.toLowerCase()}>`);\n\t}\n\n\treturn lines.join(\"\\n\");\n};\n\nconst isInsideToolbar = (el: Element | null): boolean => {\n\tlet node = el;\n\twhile (node) {\n\t\tif (node instanceof HTMLElement && node.dataset.ynsFeedbackUi === \"true\") return true;\n\t\tnode = node.parentElement;\n\t}\n\treturn false;\n};\n\nfunction FeedbackToolbar() {\n\tconst [session, setSession] = useState<ActiveSession | null>(null);\n\tconst [loading, setLoading] = useState(true);\n\tconst [pinMode, setPinMode] = useState(false);\n\tconst [pending, setPending] = useState<PendingPin | null>(null);\n\tconst [editingId, setEditingId] = useState<string | null>(null);\n\tconst apiBase = useRef<string | null>(null);\n\n\tuseEffect(() => {\n\t\tapiBase.current = buildApiBase();\n\t\tif (!apiBase.current) {\n\t\t\tsetLoading(false);\n\t\t\treturn;\n\t\t}\n\n\t\tconst controller = new AbortController();\n\t\tfetch(`${apiBase.current}/api/feedback-comments?host=${encodeURIComponent(window.location.host)}`, {\n\t\t\tcredentials: \"include\",\n\t\t\tsignal: controller.signal,\n\t\t})\n\t\t\t.then(async (res) => {\n\t\t\t\tif (!res.ok) {\n\t\t\t\t\tsetSession(null);\n\t\t\t\t\treturn;\n\t\t\t\t}\n\t\t\t\tconst data = (await res.json()) as ActiveSession;\n\t\t\t\tsetSession(data);\n\t\t\t})\n\t\t\t.catch(() => {\n\t\t\t\tsetSession(null);\n\t\t\t})\n\t\t\t.finally(() => setLoading(false));\n\n\t\treturn () => controller.abort();\n\t}, []);\n\n\tuseEffect(() => {\n\t\tif (!pinMode) return;\n\t\tdocument.body.style.cursor = \"crosshair\";\n\t\treturn () => {\n\t\t\tdocument.body.style.cursor = \"\";\n\t\t};\n\t}, [pinMode]);\n\n\tuseEffect(() => {\n\t\tif (!pinMode) return;\n\t\tconst handleClick = (event: MouseEvent) => {\n\t\t\tconst target = event.target;\n\t\t\tif (!(target instanceof Element)) return;\n\t\t\tif (isInsideToolbar(target)) return;\n\n\t\t\tevent.preventDefault();\n\t\t\tevent.stopPropagation();\n\n\t\t\tconst rect = target.getBoundingClientRect();\n\t\t\tsetPending({\n\t\t\t\tcssSelector: computeCssSelector(target),\n\t\t\t\tpagePath: window.location.pathname,\n\t\t\t\tsurroundingHtml: buildSurroundingHtml(target),\n\t\t\t\trect: {\n\t\t\t\t\ttop: rect.top + window.scrollY,\n\t\t\t\t\tleft: rect.left + window.scrollX,\n\t\t\t\t\twidth: rect.width,\n\t\t\t\t\theight: rect.height,\n\t\t\t\t},\n\t\t\t\tclickX: event.clientX + window.scrollX,\n\t\t\t\tclickY: event.clientY + window.scrollY,\n\t\t\t});\n\t\t\tsetPinMode(false);\n\t\t};\n\t\tdocument.addEventListener(\"click\", handleClick, { capture: true });\n\t\treturn () => document.removeEventListener(\"click\", handleClick, { capture: true });\n\t}, [pinMode]);\n\n\tconst refreshComments = async () => {\n\t\tif (!apiBase.current) return;\n\t\tconst res = await fetch(\n\t\t\t`${apiBase.current}/api/feedback-comments?host=${encodeURIComponent(window.location.host)}`,\n\t\t\t{ credentials: \"include\" },\n\t\t);\n\t\tif (!res.ok) return;\n\t\tconst data = (await res.json()) as ActiveSession;\n\t\tsetSession(data);\n\t};\n\n\tconst submitNewComment = async (content: string) => {\n\t\tif (!apiBase.current || !session || !pending) return;\n\t\tconst res = await fetch(`${apiBase.current}/api/feedback-comments`, {\n\t\t\tmethod: \"POST\",\n\t\t\tcredentials: \"include\",\n\t\t\theaders: { \"Content-Type\": \"application/json\" },\n\t\t\tbody: JSON.stringify({\n\t\t\t\tfeedbackSessionId: session.feedbackSessionId,\n\t\t\t\tcontent,\n\t\t\t\tpagePath: pending.pagePath,\n\t\t\t\tcssSelector: pending.cssSelector,\n\t\t\t\tsurroundingHtml: pending.surroundingHtml,\n\t\t\t}),\n\t\t});\n\t\tif (!res.ok) return;\n\t\tsetPending(null);\n\t\tawait refreshComments();\n\t};\n\n\tconst updateComment = async (id: string, content: string) => {\n\t\tif (!apiBase.current) return;\n\t\tconst res = await fetch(`${apiBase.current}/api/feedback-comments/${id}`, {\n\t\t\tmethod: \"PATCH\",\n\t\t\tcredentials: \"include\",\n\t\t\theaders: { \"Content-Type\": \"application/json\" },\n\t\t\tbody: JSON.stringify({ content }),\n\t\t});\n\t\tif (!res.ok) return;\n\t\tsetEditingId(null);\n\t\tawait refreshComments();\n\t};\n\n\tconst removeComment = async (id: string) => {\n\t\tif (!apiBase.current) return;\n\t\tconst res = await fetch(`${apiBase.current}/api/feedback-comments/${id}`, {\n\t\t\tmethod: \"DELETE\",\n\t\t\tcredentials: \"include\",\n\t\t});\n\t\tif (!res.ok) return;\n\t\tawait refreshComments();\n\t};\n\n\tif (loading || !session || !session.canComment) return null;\n\n\tconst visiblePins = session.comments.filter(\n\t\t(c) => c.pagePath === window.location.pathname && c.status !== \"done\",\n\t);\n\n\treturn (\n\t\t<div data-yns-feedback-ui=\"true\">\n\t\t\t{visiblePins.map((pin, idx) => (\n\t\t\t\t<PinOverlay\n\t\t\t\t\tkey={pin.id}\n\t\t\t\t\tpin={pin}\n\t\t\t\t\tnumber={idx + 1}\n\t\t\t\t\tediting={editingId === pin.id}\n\t\t\t\t\tonStartEdit={() => setEditingId(pin.id)}\n\t\t\t\t\tonCancelEdit={() => setEditingId(null)}\n\t\t\t\t\tonSave={(content) => updateComment(pin.id, content)}\n\t\t\t\t\tonRemove={() => removeComment(pin.id)}\n\t\t\t\t/>\n\t\t\t))}\n\n\t\t\t{pending && (\n\t\t\t\t<PendingCommentPopover\n\t\t\t\t\tpending={pending}\n\t\t\t\t\tonCancel={() => setPending(null)}\n\t\t\t\t\tonSave={(content) => submitNewComment(content)}\n\t\t\t\t/>\n\t\t\t)}\n\n\t\t\t<div style={toolbarStyle}>\n\t\t\t\t<button\n\t\t\t\t\ttype=\"button\"\n\t\t\t\t\tonClick={() => setPinMode((v) => !v)}\n\t\t\t\t\tstyle={pinMode ? toolbarButtonActiveStyle : toolbarButtonStyle}\n\t\t\t\t>\n\t\t\t\t\t{pinMode ? \"Cancel\" : \"Add comment\"}\n\t\t\t\t</button>\n\t\t\t\t<span style={toolbarHintStyle}>\n\t\t\t\t\t{pinMode ? \"Click any element to comment\" : `${visiblePins.length} on this page`}\n\t\t\t\t</span>\n\t\t\t</div>\n\t\t</div>\n\t);\n}\n\nfunction PinOverlay({\n\tpin,\n\tnumber,\n\tediting,\n\tonStartEdit,\n\tonCancelEdit,\n\tonSave,\n\tonRemove,\n}: {\n\tpin: FeedbackComment;\n\tnumber: number;\n\tediting: boolean;\n\tonStartEdit: () => void;\n\tonCancelEdit: () => void;\n\tonSave: (content: string) => Promise<void>;\n\tonRemove: () => Promise<void>;\n}) {\n\tconst target = useTargetRect(pin.cssSelector);\n\tif (!target) return null;\n\n\treturn (\n\t\t<div\n\t\t\tstyle={{\n\t\t\t\tposition: \"absolute\",\n\t\t\t\ttop: target.top,\n\t\t\t\tleft: target.left,\n\t\t\t\tzIndex: 2147483600,\n\t\t\t\tpointerEvents: \"auto\",\n\t\t\t}}\n\t\t>\n\t\t\t<button type=\"button\" onClick={onStartEdit} style={pinDotStyle} title={pin.content}>\n\t\t\t\t{number}\n\t\t\t</button>\n\t\t\t{editing && (\n\t\t\t\t<EditPopover initial={pin.content} onCancel={onCancelEdit} onSave={onSave} onRemove={onRemove} />\n\t\t\t)}\n\t\t</div>\n\t);\n}\n\nfunction PendingCommentPopover({\n\tpending,\n\tonCancel,\n\tonSave,\n}: {\n\tpending: PendingPin;\n\tonCancel: () => void;\n\tonSave: (content: string) => Promise<void>;\n}) {\n\treturn (\n\t\t<div\n\t\t\tstyle={{\n\t\t\t\tposition: \"absolute\",\n\t\t\t\ttop: pending.clickY + 10,\n\t\t\t\tleft: pending.clickX + 10,\n\t\t\t\tzIndex: 2147483647,\n\t\t\t}}\n\t\t>\n\t\t\t<EditPopover initial=\"\" onCancel={onCancel} onSave={onSave} />\n\t\t</div>\n\t);\n}\n\nfunction EditPopover({\n\tinitial,\n\tonCancel,\n\tonSave,\n\tonRemove,\n}: {\n\tinitial: string;\n\tonCancel: () => void;\n\tonSave: (content: string) => Promise<void>;\n\tonRemove?: () => Promise<void>;\n}) {\n\tconst [value, setValue] = useState(initial);\n\tconst [saving, setSaving] = useState(false);\n\n\tconst handleSubmit = async (e: FormEvent) => {\n\t\te.preventDefault();\n\t\tconst content = value.trim();\n\t\tif (!content) return;\n\t\tsetSaving(true);\n\t\ttry {\n\t\t\tawait onSave(content);\n\t\t} finally {\n\t\t\tsetSaving(false);\n\t\t}\n\t};\n\n\treturn (\n\t\t<form onSubmit={handleSubmit} style={popoverStyle}>\n\t\t\t<textarea\n\t\t\t\tvalue={value}\n\t\t\t\tonChange={(e) => setValue(e.target.value)}\n\t\t\t\tplaceholder=\"Leave a comment…\"\n\t\t\t\tstyle={textareaStyle}\n\t\t\t\trows={3}\n\t\t\t/>\n\t\t\t<div style={popoverActionsStyle}>\n\t\t\t\t{onRemove && (\n\t\t\t\t\t<button type=\"button\" onClick={() => onRemove()} style={dangerButtonStyle} disabled={saving}>\n\t\t\t\t\t\tDelete\n\t\t\t\t\t</button>\n\t\t\t\t)}\n\t\t\t\t<div style={{ flex: 1 }} />\n\t\t\t\t<button type=\"button\" onClick={onCancel} style={ghostButtonStyle} disabled={saving}>\n\t\t\t\t\tCancel\n\t\t\t\t</button>\n\t\t\t\t<button type=\"submit\" style={primaryButtonStyle} disabled={saving || !value.trim()}>\n\t\t\t\t\t{saving ? \"Saving…\" : \"Save\"}\n\t\t\t\t</button>\n\t\t\t</div>\n\t\t</form>\n\t);\n}\n\nfunction useTargetRect(selector: string) {\n\tconst [rect, setRect] = useState<{ top: number; left: number } | null>(null);\n\n\tuseEffect(() => {\n\t\tconst update = () => {\n\t\t\tlet el: Element | null = null;\n\t\t\ttry {\n\t\t\t\tel = document.querySelector(selector);\n\t\t\t} catch {\n\t\t\t\tel = null;\n\t\t\t}\n\t\t\tif (!el) {\n\t\t\t\tsetRect(null);\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tconst r = el.getBoundingClientRect();\n\t\t\tsetRect({ top: r.top + window.scrollY - 12, left: r.left + window.scrollX - 12 });\n\t\t};\n\n\t\tupdate();\n\t\tconst ro = new ResizeObserver(update);\n\t\ttry {\n\t\t\tconst el = document.querySelector(selector);\n\t\t\tif (el) ro.observe(el);\n\t\t} catch {\n\t\t\t// swallow invalid selector\n\t\t}\n\t\twindow.addEventListener(\"scroll\", update, true);\n\t\twindow.addEventListener(\"resize\", update);\n\t\treturn () => {\n\t\t\tro.disconnect();\n\t\t\twindow.removeEventListener(\"scroll\", update, true);\n\t\t\twindow.removeEventListener(\"resize\", update);\n\t\t};\n\t}, [selector]);\n\n\treturn rect;\n}\n\n// Inline styles — toolbar is injected into arbitrary stores, so we avoid relying\n// on any CSS framework being present.\nconst toolbarStyle: CSSProperties = {\n\tposition: \"fixed\",\n\tbottom: 16,\n\tleft: \"50%\",\n\ttransform: \"translateX(-50%)\",\n\tzIndex: 2147483646,\n\tdisplay: \"flex\",\n\talignItems: \"center\",\n\tgap: 12,\n\tpadding: \"8px 12px\",\n\tbackground: \"rgba(17, 17, 17, 0.92)\",\n\tcolor: \"white\",\n\tborderRadius: 999,\n\tboxShadow: \"0 8px 24px rgba(0,0,0,0.25)\",\n\tfontFamily:\n\t\t'-apple-system, BlinkMacSystemFont, \"Segoe UI\", Roboto, Helvetica, Arial, sans-serif, \"Apple Color Emoji\", \"Segoe UI Emoji\"',\n\tfontSize: 14,\n\tpointerEvents: \"auto\",\n};\n\nconst toolbarButtonStyle: CSSProperties = {\n\tborder: \"none\",\n\tbackground: \"white\",\n\tcolor: \"#111\",\n\tpadding: \"6px 12px\",\n\tborderRadius: 999,\n\tcursor: \"pointer\",\n\tfontWeight: 600,\n\tfontSize: 13,\n};\n\nconst toolbarButtonActiveStyle: CSSProperties = {\n\t...toolbarButtonStyle,\n\tbackground: \"#ef4444\",\n\tcolor: \"white\",\n};\n\nconst toolbarHintStyle: CSSProperties = {\n\topacity: 0.8,\n\tfontSize: 12,\n};\n\nconst pinDotStyle: CSSProperties = {\n\twidth: 24,\n\theight: 24,\n\tborderRadius: 999,\n\tbackground: \"#10b981\",\n\tcolor: \"white\",\n\tborder: \"2px solid white\",\n\tcursor: \"pointer\",\n\tfontSize: 12,\n\tfontWeight: 700,\n\tboxShadow: \"0 2px 6px rgba(0,0,0,0.3)\",\n\tdisplay: \"inline-flex\",\n\talignItems: \"center\",\n\tjustifyContent: \"center\",\n\tpadding: 0,\n};\n\nconst popoverStyle: CSSProperties = {\n\tbackground: \"white\",\n\tborder: \"1px solid #e5e7eb\",\n\tborderRadius: 8,\n\tpadding: 12,\n\twidth: 280,\n\tboxShadow: \"0 12px 32px rgba(0,0,0,0.18)\",\n\tfontFamily:\n\t\t'-apple-system, BlinkMacSystemFont, \"Segoe UI\", Roboto, Helvetica, Arial, sans-serif, \"Apple Color Emoji\", \"Segoe UI Emoji\"',\n\tdisplay: \"flex\",\n\tflexDirection: \"column\",\n\tgap: 8,\n\tcolor: \"#111\",\n};\n\nconst textareaStyle: CSSProperties = {\n\twidth: \"100%\",\n\tborder: \"1px solid #d1d5db\",\n\tborderRadius: 6,\n\tpadding: 8,\n\tfontSize: 14,\n\tresize: \"vertical\",\n\tfontFamily: \"inherit\",\n\tcolor: \"#111\",\n\tbackground: \"white\",\n\tboxSizing: \"border-box\",\n};\n\nconst popoverActionsStyle: CSSProperties = {\n\tdisplay: \"flex\",\n\talignItems: \"center\",\n\tgap: 6,\n};\n\nconst baseButton: CSSProperties = {\n\tborder: \"1px solid transparent\",\n\tborderRadius: 6,\n\tpadding: \"6px 10px\",\n\tfontSize: 13,\n\tcursor: \"pointer\",\n\tfontWeight: 500,\n};\n\nconst primaryButtonStyle: CSSProperties = {\n\t...baseButton,\n\tbackground: \"#111\",\n\tcolor: \"white\",\n};\n\nconst ghostButtonStyle: CSSProperties = {\n\t...baseButton,\n\tbackground: \"transparent\",\n\tcolor: \"#374151\",\n\tborderColor: \"#d1d5db\",\n};\n\nconst dangerButtonStyle: CSSProperties = {\n\t...baseButton,\n\tbackground: \"transparent\",\n\tcolor: \"#b91c1c\",\n\tborderColor: \"#fecaca\",\n};\n\nexport function mountFeedbackToolbar(): { unmount: () => void } | null {\n\tconsole.log(\"[YNS Feedback Toolbar] mountFeedbackToolbar() called\", {\n\t\tisWindow: typeof window !== \"undefined\",\n\t\tvercelEnv: process.env.NEXT_PUBLIC_VERCEL_ENV,\n\t\talreadyMounted: typeof document !== \"undefined\" && Boolean(document.getElementById(MOUNT_NODE_ID)),\n\t});\n\tif (typeof window === \"undefined\") return null;\n\tif (process.env.NEXT_PUBLIC_VERCEL_ENV !== \"preview\") {\n\t\tconsole.log(\n\t\t\t\"[YNS Feedback Toolbar] gate failed — NEXT_PUBLIC_VERCEL_ENV is\",\n\t\t\tprocess.env.NEXT_PUBLIC_VERCEL_ENV,\n\t\t);\n\t\treturn null;\n\t}\n\tif (document.getElementById(MOUNT_NODE_ID)) return null;\n\n\tconst container = document.createElement(\"div\");\n\tcontainer.id = MOUNT_NODE_ID;\n\tcontainer.dataset.ynsFeedbackUi = \"true\";\n\tdocument.body.appendChild(container);\n\n\tconst root = createRoot(container);\n\troot.render(<FeedbackToolbar />);\n\n\treturn {\n\t\tunmount: () => {\n\t\t\troot.unmount();\n\t\t\tcontainer.remove();\n\t\t},\n\t};\n}\n\n// Auto-mount on import. Wait for DOM ready.\nif (typeof window !== \"undefined\") {\n\tconsole.log(\"[YNS Feedback Toolbar] module evaluated\", {\n\t\tvercelEnv: process.env.NEXT_PUBLIC_VERCEL_ENV,\n\t\treadyState: document.readyState,\n\t\twillAutoMount: process.env.NEXT_PUBLIC_VERCEL_ENV === \"preview\",\n\t});\n}\nif (typeof window !== \"undefined\" && process.env.NEXT_PUBLIC_VERCEL_ENV === \"preview\") {\n\tif (document.readyState === \"loading\") {\n\t\tdocument.addEventListener(\"DOMContentLoaded\", () => {\n\t\t\tmountFeedbackToolbar();\n\t\t});\n\t} else {\n\t\tmountFeedbackToolbar();\n\t}\n}\n"],"mappings":"AAcA,OAA6C,aAAAA,EAAW,UAAAC,EAAQ,YAAAC,MAAgB,QAChF,OAAS,cAAAC,MAAkB,mBAySvB,cAAAC,EAoBD,QAAAC,MApBC,oBAvSJ,IAAMC,EAAgB,4BAyBhBC,EAAe,IAAqB,CACzC,GAAI,OAAO,OAAW,IAAa,OAAO,KAC1C,IAAMC,GAAY,QAAQ,IAAI,0BAA4B,IAAI,KAAK,EACnE,GAAIA,EAAU,OAAOA,EAAS,QAAQ,MAAO,EAAE,EAM/C,IAAMC,EAAO,OAAO,SAAS,SACvBC,EAAW,OAAO,SAAS,SACjC,OAAID,EAAK,SAAS,YAAY,EAAU,GAAGC,CAAQ,cAC/CD,EAAK,SAAS,SAAS,EAAU,GAAGC,CAAQ,WACzC,OAAO,SAAS,MACxB,EAEMC,EAAsBC,GAAwB,CACnD,GAAIA,EAAG,GAAI,MAAO,IAAI,IAAI,OAAOA,EAAG,EAAE,CAAC,GACvC,IAAMC,EAAiB,CAAC,EACpBC,EAAuBF,EAC3B,KAAOE,GAAQA,EAAK,WAAa,KAAK,cAAgBD,EAAK,OAAS,GAAG,CACtE,IAAIE,EAAOD,EAAK,QAAQ,YAAY,EAC9BE,EAAYF,EAAK,aAAa,OAAO,EAC3C,GAAIE,EAAW,CACd,IAAMC,EAAUD,EACd,MAAM,KAAK,EACX,OAAO,OAAO,EACd,MAAM,EAAG,CAAC,EACV,IAAKE,GAAM,IAAI,IAAI,OAAOA,CAAC,CAAC,EAAE,EAC9B,KAAK,EAAE,EACTH,GAAQE,CACT,CACA,IAAME,EAAyBL,EAAK,cAC9BM,EAAMN,EAAK,QACjB,GAAIK,EAAQ,CACX,IAAME,EAAsB,MAAM,KAAKF,EAAO,QAAQ,EAAE,OAAQD,GAAMA,EAAE,UAAYE,CAAG,EACvF,GAAIC,EAAS,OAAS,EAAG,CACxB,IAAMC,EAAMD,EAAS,QAAQP,CAAI,EAAI,EACrCC,GAAQ,gBAAgBO,CAAG,GAC5B,CACD,CACAT,EAAK,QAAQE,CAAI,EACjBD,EAAOK,CACR,CACA,OAAON,EAAK,KAAK,KAAK,CACvB,EAEMU,EAAoB,CAAC,KAAM,QAAS,cAAe,aAAc,OAAQ,OAAQ,OAAQ,KAAK,EAE9FC,EAAeZ,GAAwB,CAC5C,IAAMa,EAAkB,CAAC,EACzB,QAAWC,KAAQH,EAAmB,CACrC,IAAMI,EAAIf,EAAG,aAAac,CAAI,EAC9B,GAAI,CAACC,EAAG,SACR,IAAMC,EAAUD,EAAE,OAAS,GAAK,GAAGA,EAAE,MAAM,EAAG,EAAE,CAAC,SAAMA,EACvDF,EAAM,KAAK,IAAIC,CAAI,KAAKE,EAAQ,QAAQ,KAAM,QAAQ,CAAC,GAAG,CAC3D,CACA,OAAOH,EAAM,KAAK,EAAE,CACrB,EAEMI,EAAqBjB,GAAwB,CAClD,IAAMkB,GAAQlB,EAAG,aAAe,IAAI,QAAQ,OAAQ,GAAG,EAAE,KAAK,EAC9D,OAAKkB,EACEA,EAAK,OAAS,IAAM,GAAGA,EAAK,MAAM,EAAG,GAAG,CAAC,SAAMA,EADpC,EAEnB,EAOMC,EAAwBC,GAA4B,CACzD,IAAMC,EAAuB,CAAC,EAC1BC,EAAsBF,EAC1B,KAAOE,GAAOA,IAAQ,SAAS,iBAAmBD,EAAU,OAAS,GAAG,CACvE,IAAMd,EAAyBe,EAAI,cACnC,GAAI,CAACf,EAAQ,MACbc,EAAU,QAAQd,CAAM,EACxBe,EAAMf,CACP,CAEA,IAAMgB,EAAkB,CAAC,EACrBC,EAAQ,EACZ,QAAWC,KAAYJ,EAAW,CACjC,IAAMK,EAAS,KAAK,OAAOF,CAAK,EAChCD,EAAM,KAAK,GAAGG,CAAM,IAAID,EAAS,QAAQ,YAAY,CAAC,GAAGb,EAAYa,CAAQ,CAAC,GAAG,EACjFD,GACD,CAEA,IAAMG,EAAe,KAAK,OAAOH,CAAK,EAChCI,EAAYR,EAAO,QAAQ,YAAY,EACvCS,EAAaZ,EAAkBG,CAAM,EAO3C,GANAG,EAAM,KACL,GAAGI,CAAY,IAAIC,CAAS,GAAGhB,EAAYQ,CAAM,CAAC,IACjDS,EAAa,GAAGA,CAAU,KAAKD,CAAS,IAAM,EAC/C,iBACD,EAEI,CAACC,EAAY,CAChB,IAAMC,EAAc,KAAK,OAAON,EAAQ,CAAC,EACnCO,EAAW,MAAM,KAAKX,EAAO,QAAQ,EAAE,MAAM,EAAG,CAAC,EACvD,QAAWY,KAASD,EAAU,CAC7B,IAAME,EAAYhB,EAAkBe,CAAK,EACzCT,EAAM,KACL,GAAGO,CAAW,IAAIE,EAAM,QAAQ,YAAY,CAAC,GAAGpB,EAAYoB,CAAK,CAAC,IACjEC,EAAY,GAAGA,CAAS,KAAKD,EAAM,QAAQ,YAAY,CAAC,IAAM,EAC/D,EACD,CACD,CACIZ,EAAO,SAAS,OAAS,GAC5BG,EAAM,KAAK,GAAGO,CAAW,WAAMV,EAAO,SAAS,OAAS,CAAC,iBAAiB,EAE3EG,EAAM,KAAK,GAAGI,CAAY,KAAKC,CAAS,GAAG,CAC5C,CAEA,QAASM,EAAIb,EAAU,OAAS,EAAGa,GAAK,EAAGA,IAAK,CAC/C,IAAMR,EAAS,KAAK,OAAOQ,CAAC,EACtBT,EAAWJ,EAAUa,CAAC,EACvBT,GACLF,EAAM,KAAK,GAAGG,CAAM,KAAKD,EAAS,QAAQ,YAAY,CAAC,GAAG,CAC3D,CAEA,OAAOF,EAAM,KAAK;AAAA,CAAI,CACvB,EAEMY,EAAmBnC,GAAgC,CACxD,IAAIE,EAAOF,EACX,KAAOE,GAAM,CACZ,GAAIA,aAAgB,aAAeA,EAAK,QAAQ,gBAAkB,OAAQ,MAAO,GACjFA,EAAOA,EAAK,aACb,CACA,MAAO,EACR,EAEA,SAASkC,GAAkB,CAC1B,GAAM,CAACC,EAASC,CAAU,EAAIhD,EAA+B,IAAI,EAC3D,CAACiD,EAASC,CAAU,EAAIlD,EAAS,EAAI,EACrC,CAACmD,EAASC,CAAU,EAAIpD,EAAS,EAAK,EACtC,CAACqD,EAASC,CAAU,EAAItD,EAA4B,IAAI,EACxD,CAACuD,EAAWC,CAAY,EAAIxD,EAAwB,IAAI,EACxDyD,EAAU1D,EAAsB,IAAI,EAE1CD,EAAU,IAAM,CAEf,GADA2D,EAAQ,QAAUpD,EAAa,EAC3B,CAACoD,EAAQ,QAAS,CACrBP,EAAW,EAAK,EAChB,MACD,CAEA,IAAMQ,EAAa,IAAI,gBACvB,aAAM,GAAGD,EAAQ,OAAO,+BAA+B,mBAAmB,OAAO,SAAS,IAAI,CAAC,GAAI,CAClG,YAAa,UACb,OAAQC,EAAW,MACpB,CAAC,EACC,KAAK,MAAOC,GAAQ,CACpB,GAAI,CAACA,EAAI,GAAI,CACZX,EAAW,IAAI,EACf,MACD,CACA,IAAMY,EAAQ,MAAMD,EAAI,KAAK,EAC7BX,EAAWY,CAAI,CAChB,CAAC,EACA,MAAM,IAAM,CACZZ,EAAW,IAAI,CAChB,CAAC,EACA,QAAQ,IAAME,EAAW,EAAK,CAAC,EAE1B,IAAMQ,EAAW,MAAM,CAC/B,EAAG,CAAC,CAAC,EAEL5D,EAAU,IAAM,CACf,GAAKqD,EACL,gBAAS,KAAK,MAAM,OAAS,YACtB,IAAM,CACZ,SAAS,KAAK,MAAM,OAAS,EAC9B,CACD,EAAG,CAACA,CAAO,CAAC,EAEZrD,EAAU,IAAM,CACf,GAAI,CAACqD,EAAS,OACd,IAAMU,EAAeC,GAAsB,CAC1C,IAAMhC,EAASgC,EAAM,OAErB,GADI,EAAEhC,aAAkB,UACpBe,EAAgBf,CAAM,EAAG,OAE7BgC,EAAM,eAAe,EACrBA,EAAM,gBAAgB,EAEtB,IAAMC,EAAOjC,EAAO,sBAAsB,EAC1CwB,EAAW,CACV,YAAa7C,EAAmBqB,CAAM,EACtC,SAAU,OAAO,SAAS,SAC1B,gBAAiBD,EAAqBC,CAAM,EAC5C,KAAM,CACL,IAAKiC,EAAK,IAAM,OAAO,QACvB,KAAMA,EAAK,KAAO,OAAO,QACzB,MAAOA,EAAK,MACZ,OAAQA,EAAK,MACd,EACA,OAAQD,EAAM,QAAU,OAAO,QAC/B,OAAQA,EAAM,QAAU,OAAO,OAChC,CAAC,EACDV,EAAW,EAAK,CACjB,EACA,gBAAS,iBAAiB,QAASS,EAAa,CAAE,QAAS,EAAK,CAAC,EAC1D,IAAM,SAAS,oBAAoB,QAASA,EAAa,CAAE,QAAS,EAAK,CAAC,CAClF,EAAG,CAACV,CAAO,CAAC,EAEZ,IAAMa,EAAkB,SAAY,CACnC,GAAI,CAACP,EAAQ,QAAS,OACtB,IAAME,EAAM,MAAM,MACjB,GAAGF,EAAQ,OAAO,+BAA+B,mBAAmB,OAAO,SAAS,IAAI,CAAC,GACzF,CAAE,YAAa,SAAU,CAC1B,EACA,GAAI,CAACE,EAAI,GAAI,OACb,IAAMC,EAAQ,MAAMD,EAAI,KAAK,EAC7BX,EAAWY,CAAI,CAChB,EAEMK,EAAmB,MAAOC,GAAoB,CAC/C,CAACT,EAAQ,SAAW,CAACV,GAAW,CAACM,GAajC,EAZQ,MAAM,MAAM,GAAGI,EAAQ,OAAO,yBAA0B,CACnE,OAAQ,OACR,YAAa,UACb,QAAS,CAAE,eAAgB,kBAAmB,EAC9C,KAAM,KAAK,UAAU,CACpB,kBAAmBV,EAAQ,kBAC3B,QAAAmB,EACA,SAAUb,EAAQ,SAClB,YAAaA,EAAQ,YACrB,gBAAiBA,EAAQ,eAC1B,CAAC,CACF,CAAC,GACQ,KACTC,EAAW,IAAI,EACf,MAAMU,EAAgB,EACvB,EAEMG,EAAgB,MAAOC,EAAYF,IAAoB,CACxD,CAACT,EAAQ,SAOT,EANQ,MAAM,MAAM,GAAGA,EAAQ,OAAO,0BAA0BW,CAAE,GAAI,CACzE,OAAQ,QACR,YAAa,UACb,QAAS,CAAE,eAAgB,kBAAmB,EAC9C,KAAM,KAAK,UAAU,CAAE,QAAAF,CAAQ,CAAC,CACjC,CAAC,GACQ,KACTV,EAAa,IAAI,EACjB,MAAMQ,EAAgB,EACvB,EAEMK,EAAgB,MAAOD,GAAe,CACvC,CAACX,EAAQ,SAKT,EAJQ,MAAM,MAAM,GAAGA,EAAQ,OAAO,0BAA0BW,CAAE,GAAI,CACzE,OAAQ,SACR,YAAa,SACd,CAAC,GACQ,IACT,MAAMJ,EAAgB,CACvB,EAEA,GAAIf,GAAW,CAACF,GAAW,CAACA,EAAQ,WAAY,OAAO,KAEvD,IAAMuB,EAAcvB,EAAQ,SAAS,OACnC/B,GAAMA,EAAE,WAAa,OAAO,SAAS,UAAYA,EAAE,SAAW,MAChE,EAEA,OACCb,EAAC,OAAI,uBAAqB,OACxB,UAAAmE,EAAY,IAAI,CAACC,EAAKnD,IACtBlB,EAACsE,EAAA,CAEA,IAAKD,EACL,OAAQnD,EAAM,EACd,QAASmC,IAAcgB,EAAI,GAC3B,YAAa,IAAMf,EAAae,EAAI,EAAE,EACtC,aAAc,IAAMf,EAAa,IAAI,EACrC,OAASU,GAAYC,EAAcI,EAAI,GAAIL,CAAO,EAClD,SAAU,IAAMG,EAAcE,EAAI,EAAE,GAP/BA,EAAI,EAQV,CACA,EAEAlB,GACAnD,EAACuE,EAAA,CACA,QAASpB,EACT,SAAU,IAAMC,EAAW,IAAI,EAC/B,OAASY,GAAYD,EAAiBC,CAAO,EAC9C,EAGD/D,EAAC,OAAI,MAAOuE,EACX,UAAAxE,EAAC,UACA,KAAK,SACL,QAAS,IAAMkD,EAAY3B,GAAM,CAACA,CAAC,EACnC,MAAO0B,EAAUwB,EAA2BC,EAE3C,SAAAzB,EAAU,SAAW,cACvB,EACAjD,EAAC,QAAK,MAAO2E,EACX,SAAA1B,EAAU,+BAAiC,GAAGmB,EAAY,MAAM,gBAClE,GACD,GACD,CAEF,CAEA,SAASE,EAAW,CACnB,IAAAD,EACA,OAAAO,EACA,QAAAC,EACA,YAAAC,EACA,aAAAC,EACA,OAAAC,EACA,SAAAC,CACD,EAQG,CACF,IAAMrD,EAASsD,EAAcb,EAAI,WAAW,EAC5C,OAAKzC,EAGJ3B,EAAC,OACA,MAAO,CACN,SAAU,WACV,IAAK2B,EAAO,IACZ,KAAMA,EAAO,KACb,OAAQ,WACR,cAAe,MAChB,EAEA,UAAA5B,EAAC,UAAO,KAAK,SAAS,QAAS8E,EAAa,MAAOK,EAAa,MAAOd,EAAI,QACzE,SAAAO,EACF,EACCC,GACA7E,EAACoF,EAAA,CAAY,QAASf,EAAI,QAAS,SAAUU,EAAc,OAAQC,EAAQ,SAAUC,EAAU,GAEjG,EAlBmB,IAoBrB,CAEA,SAASV,EAAsB,CAC9B,QAAApB,EACA,SAAAkC,EACA,OAAAL,CACD,EAIG,CACF,OACChF,EAAC,OACA,MAAO,CACN,SAAU,WACV,IAAKmD,EAAQ,OAAS,GACtB,KAAMA,EAAQ,OAAS,GACvB,OAAQ,UACT,EAEA,SAAAnD,EAACoF,EAAA,CAAY,QAAQ,GAAG,SAAUC,EAAU,OAAQL,EAAQ,EAC7D,CAEF,CAEA,SAASI,EAAY,CACpB,QAAAE,EACA,SAAAD,EACA,OAAAL,EACA,SAAAC,CACD,EAKG,CACF,GAAM,CAACM,EAAOC,CAAQ,EAAI1F,EAASwF,CAAO,EACpC,CAACG,EAAQC,CAAS,EAAI5F,EAAS,EAAK,EAc1C,OACCG,EAAC,QAAK,SAbc,MAAO0F,GAAiB,CAC5CA,EAAE,eAAe,EACjB,IAAM3B,EAAUuB,EAAM,KAAK,EAC3B,GAAKvB,EACL,CAAA0B,EAAU,EAAI,EACd,GAAI,CACH,MAAMV,EAAOhB,CAAO,CACrB,QAAE,CACD0B,EAAU,EAAK,CAChB,EACD,EAG+B,MAAOE,EACpC,UAAA5F,EAAC,YACA,MAAOuF,EACP,SAAWI,GAAMH,EAASG,EAAE,OAAO,KAAK,EACxC,YAAY,wBACZ,MAAOE,EACP,KAAM,EACP,EACA5F,EAAC,OAAI,MAAO6F,EACV,UAAAb,GACAjF,EAAC,UAAO,KAAK,SAAS,QAAS,IAAMiF,EAAS,EAAG,MAAOc,EAAmB,SAAUN,EAAQ,kBAE7F,EAEDzF,EAAC,OAAI,MAAO,CAAE,KAAM,CAAE,EAAG,EACzBA,EAAC,UAAO,KAAK,SAAS,QAASqF,EAAU,MAAOW,EAAkB,SAAUP,EAAQ,kBAEpF,EACAzF,EAAC,UAAO,KAAK,SAAS,MAAOiG,EAAoB,SAAUR,GAAU,CAACF,EAAM,KAAK,EAC/E,SAAAE,EAAS,eAAY,OACvB,GACD,GACD,CAEF,CAEA,SAASP,EAAcgB,EAAkB,CACxC,GAAM,CAACrC,EAAMsC,CAAO,EAAIrG,EAA+C,IAAI,EAE3E,OAAAF,EAAU,IAAM,CACf,IAAMwG,EAAS,IAAM,CACpB,IAAI5F,EAAqB,KACzB,GAAI,CACHA,EAAK,SAAS,cAAc0F,CAAQ,CACrC,MAAQ,CACP1F,EAAK,IACN,CACA,GAAI,CAACA,EAAI,CACR2F,EAAQ,IAAI,EACZ,MACD,CACA,IAAME,EAAI7F,EAAG,sBAAsB,EACnC2F,EAAQ,CAAE,IAAKE,EAAE,IAAM,OAAO,QAAU,GAAI,KAAMA,EAAE,KAAO,OAAO,QAAU,EAAG,CAAC,CACjF,EAEAD,EAAO,EACP,IAAME,EAAK,IAAI,eAAeF,CAAM,EACpC,GAAI,CACH,IAAM5F,EAAK,SAAS,cAAc0F,CAAQ,EACtC1F,GAAI8F,EAAG,QAAQ9F,CAAE,CACtB,MAAQ,CAER,CACA,cAAO,iBAAiB,SAAU4F,EAAQ,EAAI,EAC9C,OAAO,iBAAiB,SAAUA,CAAM,EACjC,IAAM,CACZE,EAAG,WAAW,EACd,OAAO,oBAAoB,SAAUF,EAAQ,EAAI,EACjD,OAAO,oBAAoB,SAAUA,CAAM,CAC5C,CACD,EAAG,CAACF,CAAQ,CAAC,EAENrC,CACR,CAIA,IAAMW,EAA8B,CACnC,SAAU,QACV,OAAQ,GACR,KAAM,MACN,UAAW,mBACX,OAAQ,WACR,QAAS,OACT,WAAY,SACZ,IAAK,GACL,QAAS,WACT,WAAY,yBACZ,MAAO,QACP,aAAc,IACd,UAAW,8BACX,WACC,6HACD,SAAU,GACV,cAAe,MAChB,EAEME,EAAoC,CACzC,OAAQ,OACR,WAAY,QACZ,MAAO,OACP,QAAS,WACT,aAAc,IACd,OAAQ,UACR,WAAY,IACZ,SAAU,EACX,EAEMD,EAA0C,CAC/C,GAAGC,EACH,WAAY,UACZ,MAAO,OACR,EAEMC,EAAkC,CACvC,QAAS,GACT,SAAU,EACX,EAEMQ,EAA6B,CAClC,MAAO,GACP,OAAQ,GACR,aAAc,IACd,WAAY,UACZ,MAAO,QACP,OAAQ,kBACR,OAAQ,UACR,SAAU,GACV,WAAY,IACZ,UAAW,4BACX,QAAS,cACT,WAAY,SACZ,eAAgB,SAChB,QAAS,CACV,EAEMS,EAA8B,CACnC,WAAY,QACZ,OAAQ,oBACR,aAAc,EACd,QAAS,GACT,MAAO,IACP,UAAW,+BACX,WACC,6HACD,QAAS,OACT,cAAe,SACf,IAAK,EACL,MAAO,MACR,EAEMC,EAA+B,CACpC,MAAO,OACP,OAAQ,oBACR,aAAc,EACd,QAAS,EACT,SAAU,GACV,OAAQ,WACR,WAAY,UACZ,MAAO,OACP,WAAY,QACZ,UAAW,YACZ,EAEMC,EAAqC,CAC1C,QAAS,OACT,WAAY,SACZ,IAAK,CACN,EAEMS,EAA4B,CACjC,OAAQ,wBACR,aAAc,EACd,QAAS,WACT,SAAU,GACV,OAAQ,UACR,WAAY,GACb,EAEMN,EAAoC,CACzC,GAAGM,EACH,WAAY,OACZ,MAAO,OACR,EAEMP,EAAkC,CACvC,GAAGO,EACH,WAAY,cACZ,MAAO,UACP,YAAa,SACd,EAEMR,EAAmC,CACxC,GAAGQ,EACH,WAAY,cACZ,MAAO,UACP,YAAa,SACd,EAEO,SAASC,GAAuD,CAMtE,GALA,QAAQ,IAAI,uDAAwD,CACnE,SAAU,OAAO,OAAW,IAC5B,UAAW,QAAQ,IAAI,uBACvB,eAAgB,OAAO,SAAa,KAAe,EAAQ,SAAS,eAAetG,CAAa,CACjG,CAAC,EACG,OAAO,OAAW,IAAa,OAAO,KAC1C,GAAI,QAAQ,IAAI,yBAA2B,UAC1C,eAAQ,IACP,sEACA,QAAQ,IAAI,sBACb,EACO,KAER,GAAI,SAAS,eAAeA,CAAa,EAAG,OAAO,KAEnD,IAAMuG,EAAY,SAAS,cAAc,KAAK,EAC9CA,EAAU,GAAKvG,EACfuG,EAAU,QAAQ,cAAgB,OAClC,SAAS,KAAK,YAAYA,CAAS,EAEnC,IAAMC,EAAO3G,EAAW0G,CAAS,EACjC,OAAAC,EAAK,OAAO1G,EAAC4C,EAAA,EAAgB,CAAE,EAExB,CACN,QAAS,IAAM,CACd8D,EAAK,QAAQ,EACbD,EAAU,OAAO,CAClB,CACD,CACD,CAGI,OAAO,OAAW,KACrB,QAAQ,IAAI,0CAA2C,CACtD,UAAW,QAAQ,IAAI,uBACvB,WAAY,SAAS,WACrB,cAAe,QAAQ,IAAI,yBAA2B,SACvD,CAAC,EAEE,OAAO,OAAW,KAAe,QAAQ,IAAI,yBAA2B,YACvE,SAAS,aAAe,UAC3B,SAAS,iBAAiB,mBAAoB,IAAM,CACnDD,EAAqB,CACtB,CAAC,EAEDA,EAAqB","names":["useEffect","useRef","useState","createRoot","jsx","jsxs","MOUNT_NODE_ID","buildApiBase","override","host","protocol","computeCssSelector","el","path","node","part","className","classes","c","parent","tag","siblings","idx","ATTRS_OF_INTEREST","formatAttrs","parts","attr","v","trimmed","formatTextContent","text","buildSurroundingHtml","target","ancestors","cur","lines","depth","ancestor","indent","targetIndent","targetTag","targetText","childIndent","children","child","childText","i","isInsideToolbar","FeedbackToolbar","session","setSession","loading","setLoading","pinMode","setPinMode","pending","setPending","editingId","setEditingId","apiBase","controller","res","data","handleClick","event","rect","refreshComments","submitNewComment","content","updateComment","id","removeComment","visiblePins","pin","PinOverlay","PendingCommentPopover","toolbarStyle","toolbarButtonActiveStyle","toolbarButtonStyle","toolbarHintStyle","number","editing","onStartEdit","onCancelEdit","onSave","onRemove","useTargetRect","pinDotStyle","EditPopover","onCancel","initial","value","setValue","saving","setSaving","e","popoverStyle","textareaStyle","popoverActionsStyle","dangerButtonStyle","ghostButtonStyle","primaryButtonStyle","selector","setRect","update","r","ro","baseButton","mountFeedbackToolbar","container","root"]}
1
+ {"version":3,"sources":["../src/feedback-toolbar.tsx"],"sourcesContent":["/**\n * Feedback session toolbar — side-effect entry.\n *\n * Importing `commerce-kit/feedback-toolbar` (or `commerce-kit/browser` for the\n * combined entry) mounts a floating toolbar onto the page that lets reviewers\n * leave click-anchored comments. Comments persist via YNS API endpoints,\n * authenticated with the `better-auth` session cookie sent through\n * `credentials: \"include\"`.\n *\n * Gated on `process.env.NEXT_PUBLIC_VERCEL_ENV === \"preview\"` — only Vercel\n * preview deploys get the toolbar. Sandbox dev (env undefined) and production\n * (env === \"production\") skip it.\n */\n\nimport { type CSSProperties, type FormEvent, useEffect, useRef, useState } from \"react\";\nimport { createRoot } from \"react-dom/client\";\n\nconst MOUNT_NODE_ID = \"yns-feedback-toolbar-root\";\n\ninterface FeedbackComment {\n\tid: string;\n\tpagePath: string;\n\tcssSelector: string;\n\tcontent: string;\n\tstatus: \"todo\" | \"done\";\n\toffsetXRatio: number;\n\toffsetYRatio: number;\n}\n\ninterface ActiveSession {\n\tfeedbackSessionId: string;\n\tcomments: FeedbackComment[];\n\tcanComment: boolean;\n}\n\ninterface PendingPin {\n\tcssSelector: string;\n\tpagePath: string;\n\tsurroundingHtml: string;\n\trect: { top: number; left: number; width: number; height: number };\n\tclickX: number;\n\tclickY: number;\n\toffsetXRatio: number;\n\toffsetYRatio: number;\n}\n\nconst buildApiBase = (): string | null => {\n\tif (typeof window === \"undefined\") return null;\n\tconst override = (process.env.NEXT_PUBLIC_YNS_API_BASE ?? \"\").trim();\n\tif (override) return override.replace(/\\/$/, \"\");\n\n\t// Toolbar runs on a per-store preview deploy (mystore-preview.yns.{store|cx})\n\t// served by the merchant's Vercel project — that host has no YNS API. Aim\n\t// at the apex `yns.store` / `yns.cx`, which yns-app serves and where the\n\t// API lives. Cookies scoped to `.yns.store` / `.yns.cx` travel along.\n\tconst host = window.location.hostname;\n\tconst protocol = window.location.protocol;\n\tif (host.endsWith(\".yns.store\")) return `${protocol}//yns.store`;\n\tif (host.endsWith(\".yns.cx\")) return `${protocol}//yns.cx`;\n\treturn window.location.origin;\n};\n\nconst computeCssSelector = (el: Element): string => {\n\tif (el.id) return `#${CSS.escape(el.id)}`;\n\tconst path: string[] = [];\n\tlet node: Element | null = el;\n\twhile (node && node.nodeType === Node.ELEMENT_NODE && path.length < 6) {\n\t\tlet part = node.tagName.toLowerCase();\n\t\tconst className = node.getAttribute(\"class\");\n\t\tif (className) {\n\t\t\tconst classes = className\n\t\t\t\t.split(/\\s+/)\n\t\t\t\t.filter(Boolean)\n\t\t\t\t.slice(0, 2)\n\t\t\t\t.map((c) => `.${CSS.escape(c)}`)\n\t\t\t\t.join(\"\");\n\t\t\tpart += classes;\n\t\t}\n\t\tconst parent: Element | null = node.parentElement;\n\t\tconst tag = node.tagName;\n\t\tif (parent) {\n\t\t\tconst siblings: Element[] = Array.from(parent.children).filter((c) => c.tagName === tag);\n\t\t\tif (siblings.length > 1) {\n\t\t\t\tconst idx = siblings.indexOf(node) + 1;\n\t\t\t\tpart += `:nth-of-type(${idx})`;\n\t\t\t}\n\t\t}\n\t\tpath.unshift(part);\n\t\tnode = parent;\n\t}\n\treturn path.join(\" > \");\n};\n\nconst ATTRS_OF_INTEREST = [\"id\", \"class\", \"data-testid\", \"aria-label\", \"role\", \"name\", \"href\", \"src\"];\n\nconst formatAttrs = (el: Element): string => {\n\tconst parts: string[] = [];\n\tfor (const attr of ATTRS_OF_INTEREST) {\n\t\tconst v = el.getAttribute(attr);\n\t\tif (!v) continue;\n\t\tconst trimmed = v.length > 80 ? `${v.slice(0, 80)}…` : v;\n\t\tparts.push(` ${attr}=\"${trimmed.replace(/\"/g, \"&quot;\")}\"`);\n\t}\n\treturn parts.join(\"\");\n};\n\nconst formatTextContent = (el: Element): string => {\n\tconst text = (el.textContent ?? \"\").replace(/\\s+/g, \" \").trim();\n\tif (!text) return \"\";\n\treturn text.length > 100 ? `${text.slice(0, 100)}…` : text;\n};\n\nconst buildSurroundingHtml = (target: Element): string => {\n\tconst ancestors: Element[] = [];\n\tlet cur: Element | null = target;\n\twhile (cur && cur !== document.documentElement && ancestors.length < 5) {\n\t\tconst parent: Element | null = cur.parentElement;\n\t\tif (!parent) break;\n\t\tancestors.unshift(parent);\n\t\tcur = parent;\n\t}\n\n\tconst lines: string[] = [];\n\tlet depth = 0;\n\tfor (const ancestor of ancestors) {\n\t\tconst indent = \" \".repeat(depth);\n\t\tlines.push(`${indent}<${ancestor.tagName.toLowerCase()}${formatAttrs(ancestor)}>`);\n\t\tdepth++;\n\t}\n\n\tconst targetIndent = \" \".repeat(depth);\n\tconst targetTag = target.tagName.toLowerCase();\n\tconst targetText = formatTextContent(target);\n\tlines.push(\n\t\t`${targetIndent}<${targetTag}${formatAttrs(target)}>${\n\t\t\ttargetText ? `${targetText}</${targetTag}>` : \"\"\n\t\t} ← TARGET`,\n\t);\n\n\tif (!targetText) {\n\t\tconst childIndent = \" \".repeat(depth + 1);\n\t\tconst children = Array.from(target.children).slice(0, 6);\n\t\tfor (const child of children) {\n\t\t\tconst childText = formatTextContent(child);\n\t\t\tlines.push(\n\t\t\t\t`${childIndent}<${child.tagName.toLowerCase()}${formatAttrs(child)}>${\n\t\t\t\t\tchildText ? `${childText}</${child.tagName.toLowerCase()}>` : \"\"\n\t\t\t\t}`,\n\t\t\t);\n\t\t}\n\t\tif (target.children.length > 6) {\n\t\t\tlines.push(`${childIndent}… (${target.children.length - 6} more children)`);\n\t\t}\n\t\tlines.push(`${targetIndent}</${targetTag}>`);\n\t}\n\n\tfor (let i = ancestors.length - 1; i >= 0; i--) {\n\t\tconst indent = \" \".repeat(i);\n\t\tconst ancestor = ancestors[i];\n\t\tif (!ancestor) continue;\n\t\tlines.push(`${indent}</${ancestor.tagName.toLowerCase()}>`);\n\t}\n\n\treturn lines.join(\"\\n\");\n};\n\nconst isInsideToolbar = (el: Element | null): boolean => {\n\tlet node = el;\n\twhile (node) {\n\t\tif (node instanceof HTMLElement && node.dataset.ynsFeedbackUi === \"true\") return true;\n\t\tnode = node.parentElement;\n\t}\n\treturn false;\n};\n\nconst IGNORED_TAGS = new Set([\"HTML\", \"HEAD\", \"SCRIPT\", \"STYLE\", \"NOSCRIPT\"]);\n\nfunction FeedbackToolbar() {\n\tconst [session, setSession] = useState<ActiveSession | null>(null);\n\tconst [loading, setLoading] = useState(true);\n\tconst [pinMode, setPinMode] = useState(false);\n\tconst [pending, setPending] = useState<PendingPin | null>(null);\n\tconst [editingId, setEditingId] = useState<string | null>(null);\n\tconst [sidebarOpen, setSidebarOpen] = useState(false);\n\tconst [finalizing, setFinalizing] = useState(false);\n\tconst apiBase = useRef<string | null>(null);\n\n\tuseEffect(() => {\n\t\tapiBase.current = buildApiBase();\n\t\tif (!apiBase.current) {\n\t\t\tsetLoading(false);\n\t\t\treturn;\n\t\t}\n\n\t\tconst controller = new AbortController();\n\t\tfetch(`${apiBase.current}/api/feedback-comments?host=${encodeURIComponent(window.location.host)}`, {\n\t\t\tcredentials: \"include\",\n\t\t\tsignal: controller.signal,\n\t\t})\n\t\t\t.then(async (res) => {\n\t\t\t\tif (!res.ok) {\n\t\t\t\t\tsetSession(null);\n\t\t\t\t\treturn;\n\t\t\t\t}\n\t\t\t\tconst data = (await res.json()) as ActiveSession;\n\t\t\t\tsetSession(data);\n\t\t\t})\n\t\t\t.catch(() => {\n\t\t\t\tsetSession(null);\n\t\t\t})\n\t\t\t.finally(() => setLoading(false));\n\n\t\treturn () => controller.abort();\n\t}, []);\n\n\tuseEffect(() => {\n\t\tif (!pinMode) return;\n\t\tdocument.body.style.cursor = \"crosshair\";\n\t\treturn () => {\n\t\t\tdocument.body.style.cursor = \"\";\n\t\t};\n\t}, [pinMode]);\n\n\tuseEffect(() => {\n\t\tif (!pinMode) return;\n\n\t\tconst overlay = document.createElement(\"div\");\n\t\toverlay.dataset.ynsFeedbackUi = \"true\";\n\t\toverlay.style.cssText = [\n\t\t\t\"position: fixed\",\n\t\t\t\"pointer-events: none\",\n\t\t\t\"z-index: 2147483644\",\n\t\t\t\"border: 2px dashed #10b981\",\n\t\t\t\"background: rgba(16, 185, 129, 0.08)\",\n\t\t\t\"border-radius: 3px\",\n\t\t\t\"display: none\",\n\t\t\t\"transition: top 0.05s, left 0.05s, width 0.05s, height 0.05s\",\n\t\t].join(\";\");\n\n\t\tconst label = document.createElement(\"div\");\n\t\tlabel.dataset.ynsFeedbackUi = \"true\";\n\t\tlabel.textContent = \"Click to comment\";\n\t\tlabel.style.cssText = [\n\t\t\t\"position: fixed\",\n\t\t\t\"pointer-events: none\",\n\t\t\t\"z-index: 2147483645\",\n\t\t\t\"background: #059669\",\n\t\t\t\"color: #fff\",\n\t\t\t\"font-size: 11px\",\n\t\t\t\"font-family: ui-sans-serif, system-ui, sans-serif\",\n\t\t\t\"padding: 3px 8px\",\n\t\t\t\"border-radius: 4px\",\n\t\t\t\"white-space: nowrap\",\n\t\t\t\"display: none\",\n\t\t\t\"box-shadow: 0 2px 6px rgba(0,0,0,0.15)\",\n\t\t].join(\";\");\n\n\t\tdocument.documentElement.appendChild(overlay);\n\t\tdocument.documentElement.appendChild(label);\n\n\t\tlet hovered: Element | null = null;\n\t\tconst handleMove = (e: MouseEvent) => {\n\t\t\tconst el = document.elementFromPoint(e.clientX, e.clientY);\n\t\t\tif (!el || IGNORED_TAGS.has(el.tagName) || isInsideToolbar(el)) {\n\t\t\t\toverlay.style.display = \"none\";\n\t\t\t\tlabel.style.display = \"none\";\n\t\t\t\thovered = null;\n\t\t\t\treturn;\n\t\t\t}\n\t\t\thovered = el;\n\t\t\trequestAnimationFrame(() => {\n\t\t\t\tif (hovered !== el) return;\n\t\t\t\tconst rect = el.getBoundingClientRect();\n\t\t\t\toverlay.style.top = `${rect.top}px`;\n\t\t\t\toverlay.style.left = `${rect.left}px`;\n\t\t\t\toverlay.style.width = `${rect.width}px`;\n\t\t\t\toverlay.style.height = `${rect.height}px`;\n\t\t\t\toverlay.style.display = \"block\";\n\t\t\t\tlabel.style.left = `${e.clientX + 14}px`;\n\t\t\t\tlabel.style.top = `${e.clientY + 14}px`;\n\t\t\t\tlabel.style.display = \"block\";\n\t\t\t});\n\t\t};\n\n\t\tconst handleLeave = () => {\n\t\t\toverlay.style.display = \"none\";\n\t\t\tlabel.style.display = \"none\";\n\t\t\thovered = null;\n\t\t};\n\n\t\tdocument.addEventListener(\"mousemove\", handleMove, true);\n\t\tdocument.addEventListener(\"mouseleave\", handleLeave);\n\n\t\treturn () => {\n\t\t\tdocument.removeEventListener(\"mousemove\", handleMove, true);\n\t\t\tdocument.removeEventListener(\"mouseleave\", handleLeave);\n\t\t\toverlay.remove();\n\t\t\tlabel.remove();\n\t\t};\n\t}, [pinMode]);\n\n\tuseEffect(() => {\n\t\tif (!pinMode) return;\n\t\tconst handleClick = (event: MouseEvent) => {\n\t\t\tconst target = event.target;\n\t\t\tif (!(target instanceof Element)) return;\n\t\t\tif (isInsideToolbar(target)) return;\n\n\t\t\tevent.preventDefault();\n\t\t\tevent.stopPropagation();\n\n\t\t\tconst rect = target.getBoundingClientRect();\n\t\t\tconst offsetXRatio = rect.width > 0 ? (event.clientX - rect.left) / rect.width : 0.5;\n\t\t\tconst offsetYRatio = rect.height > 0 ? (event.clientY - rect.top) / rect.height : 0.5;\n\t\t\tsetPending({\n\t\t\t\tcssSelector: computeCssSelector(target),\n\t\t\t\tpagePath: window.location.pathname,\n\t\t\t\tsurroundingHtml: buildSurroundingHtml(target),\n\t\t\t\trect: {\n\t\t\t\t\ttop: rect.top + window.scrollY,\n\t\t\t\t\tleft: rect.left + window.scrollX,\n\t\t\t\t\twidth: rect.width,\n\t\t\t\t\theight: rect.height,\n\t\t\t\t},\n\t\t\t\tclickX: event.clientX + window.scrollX,\n\t\t\t\tclickY: event.clientY + window.scrollY,\n\t\t\t\toffsetXRatio: Math.min(1, Math.max(0, offsetXRatio)),\n\t\t\t\toffsetYRatio: Math.min(1, Math.max(0, offsetYRatio)),\n\t\t\t});\n\t\t\tsetPinMode(false);\n\t\t};\n\t\tdocument.addEventListener(\"click\", handleClick, { capture: true });\n\t\treturn () => document.removeEventListener(\"click\", handleClick, { capture: true });\n\t}, [pinMode]);\n\n\tconst refreshComments = async () => {\n\t\tif (!apiBase.current) return;\n\t\tconst res = await fetch(\n\t\t\t`${apiBase.current}/api/feedback-comments?host=${encodeURIComponent(window.location.host)}`,\n\t\t\t{ credentials: \"include\" },\n\t\t);\n\t\tif (!res.ok) return;\n\t\tconst data = (await res.json()) as ActiveSession;\n\t\tsetSession(data);\n\t};\n\n\tconst submitNewComment = async (content: string) => {\n\t\tif (!apiBase.current || !session || !pending) return;\n\t\tconst res = await fetch(`${apiBase.current}/api/feedback-comments`, {\n\t\t\tmethod: \"POST\",\n\t\t\tcredentials: \"include\",\n\t\t\theaders: { \"Content-Type\": \"application/json\" },\n\t\t\tbody: JSON.stringify({\n\t\t\t\tfeedbackSessionId: session.feedbackSessionId,\n\t\t\t\tcontent,\n\t\t\t\tpagePath: pending.pagePath,\n\t\t\t\tcssSelector: pending.cssSelector,\n\t\t\t\tsurroundingHtml: pending.surroundingHtml,\n\t\t\t\toffsetXRatio: pending.offsetXRatio,\n\t\t\t\toffsetYRatio: pending.offsetYRatio,\n\t\t\t}),\n\t\t});\n\t\tif (!res.ok) return;\n\t\tsetPending(null);\n\t\tsetPinMode(true);\n\t\tawait refreshComments();\n\t};\n\n\tconst updateComment = async (id: string, content: string) => {\n\t\tif (!apiBase.current) return;\n\t\tconst res = await fetch(`${apiBase.current}/api/feedback-comments/${id}`, {\n\t\t\tmethod: \"PATCH\",\n\t\t\tcredentials: \"include\",\n\t\t\theaders: { \"Content-Type\": \"application/json\" },\n\t\t\tbody: JSON.stringify({ content }),\n\t\t});\n\t\tif (!res.ok) return;\n\t\tsetEditingId(null);\n\t\tawait refreshComments();\n\t};\n\n\tconst removeComment = async (id: string) => {\n\t\tif (!apiBase.current) return;\n\t\tconst res = await fetch(`${apiBase.current}/api/feedback-comments/${id}`, {\n\t\t\tmethod: \"DELETE\",\n\t\t\tcredentials: \"include\",\n\t\t});\n\t\tif (!res.ok) return;\n\t\tawait refreshComments();\n\t};\n\n\tconst finalizeSession = async () => {\n\t\tif (!apiBase.current || !session) return;\n\t\tif (!window.confirm(\"Finalize this feedback session? You won't be able to add more comments.\")) return;\n\t\tsetFinalizing(true);\n\t\ttry {\n\t\t\tconst res = await fetch(\n\t\t\t\t`${apiBase.current}/api/feedback-sessions/${session.feedbackSessionId}/finalize`,\n\t\t\t\t{ method: \"POST\", credentials: \"include\" },\n\t\t\t);\n\t\t\tif (!res.ok) return;\n\t\t\tsetSession((prev) => (prev ? { ...prev, canComment: false } : prev));\n\t\t} finally {\n\t\t\tsetFinalizing(false);\n\t\t}\n\t};\n\n\tconst scrollToComment = (comment: FeedbackComment) => {\n\t\tif (comment.pagePath !== window.location.pathname) {\n\t\t\twindow.location.assign(comment.pagePath);\n\t\t\treturn;\n\t\t}\n\t\tlet el: Element | null = null;\n\t\ttry {\n\t\t\tel = document.querySelector(comment.cssSelector);\n\t\t} catch {\n\t\t\tel = null;\n\t\t}\n\t\tif (!el) return;\n\t\tel.scrollIntoView({ behavior: \"smooth\", block: \"center\" });\n\t\tsetEditingId(comment.id);\n\t};\n\n\tif (loading || !session || !session.canComment) return null;\n\n\tconst visiblePins = session.comments.filter(\n\t\t(c) => c.pagePath === window.location.pathname && c.status !== \"done\",\n\t);\n\n\treturn (\n\t\t<div data-yns-feedback-ui=\"true\">\n\t\t\t{visiblePins.map((pin, idx) => (\n\t\t\t\t<PinOverlay\n\t\t\t\t\tkey={pin.id}\n\t\t\t\t\tpin={pin}\n\t\t\t\t\tnumber={idx + 1}\n\t\t\t\t\tediting={editingId === pin.id}\n\t\t\t\t\tonStartEdit={() => setEditingId(pin.id)}\n\t\t\t\t\tonCancelEdit={() => setEditingId(null)}\n\t\t\t\t\tonSave={(content) => updateComment(pin.id, content)}\n\t\t\t\t\tonRemove={() => removeComment(pin.id)}\n\t\t\t\t/>\n\t\t\t))}\n\n\t\t\t{pending && (\n\t\t\t\t<PendingCommentPopover\n\t\t\t\t\tpending={pending}\n\t\t\t\t\tonCancel={() => {\n\t\t\t\t\t\tsetPending(null);\n\t\t\t\t\t\tsetPinMode(true);\n\t\t\t\t\t}}\n\t\t\t\t\tonSave={(content) => submitNewComment(content)}\n\t\t\t\t/>\n\t\t\t)}\n\n\t\t\t{sidebarOpen && (\n\t\t\t\t<CommentsSidebar\n\t\t\t\t\tcomments={session.comments}\n\t\t\t\t\tcurrentPath={window.location.pathname}\n\t\t\t\t\tonClose={() => setSidebarOpen(false)}\n\t\t\t\t\tonSelect={scrollToComment}\n\t\t\t\t/>\n\t\t\t)}\n\n\t\t\t<div style={toolbarStyle}>\n\t\t\t\t<button\n\t\t\t\t\ttype=\"button\"\n\t\t\t\t\tonClick={() => setPinMode((v) => !v)}\n\t\t\t\t\tstyle={pinMode ? toolbarButtonActiveStyle : toolbarButtonStyle}\n\t\t\t\t>\n\t\t\t\t\t{pinMode ? \"Cancel\" : \"Add comment\"}\n\t\t\t\t</button>\n\t\t\t\t<button type=\"button\" onClick={() => setSidebarOpen((v) => !v)} style={toolbarButtonGhostStyle}>\n\t\t\t\t\t{sidebarOpen ? \"Hide list\" : `List (${session.comments.length})`}\n\t\t\t\t</button>\n\t\t\t\t<button\n\t\t\t\t\ttype=\"button\"\n\t\t\t\t\tonClick={finalizeSession}\n\t\t\t\t\tdisabled={finalizing}\n\t\t\t\t\tstyle={toolbarButtonFinalizeStyle}\n\t\t\t\t>\n\t\t\t\t\t{finalizing ? \"Finalizing…\" : \"Finalize\"}\n\t\t\t\t</button>\n\t\t\t\t<span style={toolbarHintStyle}>\n\t\t\t\t\t{pinMode ? \"Click any element to comment\" : `${visiblePins.length} on this page`}\n\t\t\t\t</span>\n\t\t\t</div>\n\t\t</div>\n\t);\n}\n\nfunction PinOverlay({\n\tpin,\n\tnumber,\n\tediting,\n\tonStartEdit,\n\tonCancelEdit,\n\tonSave,\n\tonRemove,\n}: {\n\tpin: FeedbackComment;\n\tnumber: number;\n\tediting: boolean;\n\tonStartEdit: () => void;\n\tonCancelEdit: () => void;\n\tonSave: (content: string) => Promise<void>;\n\tonRemove: () => Promise<void>;\n}) {\n\tconst target = useTargetPosition(pin.cssSelector, pin.offsetXRatio, pin.offsetYRatio);\n\tif (!target) return null;\n\n\treturn (\n\t\t<div\n\t\t\tstyle={{\n\t\t\t\tposition: \"absolute\",\n\t\t\t\ttop: target.top,\n\t\t\t\tleft: target.left,\n\t\t\t\tzIndex: 2147483600,\n\t\t\t\tpointerEvents: \"auto\",\n\t\t\t}}\n\t\t>\n\t\t\t<button type=\"button\" onClick={onStartEdit} style={pinDotStyle} title={pin.content}>\n\t\t\t\t{number}\n\t\t\t</button>\n\t\t\t{editing && (\n\t\t\t\t<EditPopover initial={pin.content} onCancel={onCancelEdit} onSave={onSave} onRemove={onRemove} />\n\t\t\t)}\n\t\t</div>\n\t);\n}\n\nfunction PendingCommentPopover({\n\tpending,\n\tonCancel,\n\tonSave,\n}: {\n\tpending: PendingPin;\n\tonCancel: () => void;\n\tonSave: (content: string) => Promise<void>;\n}) {\n\treturn (\n\t\t<>\n\t\t\t<div\n\t\t\t\tstyle={{\n\t\t\t\t\tposition: \"absolute\",\n\t\t\t\t\ttop: pending.rect.top + pending.rect.height * pending.offsetYRatio - 12,\n\t\t\t\t\tleft: pending.rect.left + pending.rect.width * pending.offsetXRatio - 12,\n\t\t\t\t\tzIndex: 2147483600,\n\t\t\t\t\tpointerEvents: \"none\",\n\t\t\t\t}}\n\t\t\t>\n\t\t\t\t<div style={pinDotStyle}>•</div>\n\t\t\t</div>\n\t\t\t<div\n\t\t\t\tstyle={{\n\t\t\t\t\tposition: \"absolute\",\n\t\t\t\t\ttop: pending.clickY + 10,\n\t\t\t\t\tleft: pending.clickX + 10,\n\t\t\t\t\tzIndex: 2147483647,\n\t\t\t\t}}\n\t\t\t>\n\t\t\t\t<EditPopover initial=\"\" onCancel={onCancel} onSave={onSave} />\n\t\t\t</div>\n\t\t</>\n\t);\n}\n\nfunction CommentsSidebar({\n\tcomments,\n\tcurrentPath,\n\tonClose,\n\tonSelect,\n}: {\n\tcomments: FeedbackComment[];\n\tcurrentPath: string;\n\tonClose: () => void;\n\tonSelect: (comment: FeedbackComment) => void;\n}) {\n\tconst groups = new Map<string, FeedbackComment[]>();\n\tfor (const c of comments) {\n\t\tconst list = groups.get(c.pagePath) ?? [];\n\t\tlist.push(c);\n\t\tgroups.set(c.pagePath, list);\n\t}\n\tconst paths = Array.from(groups.keys()).sort((a, b) => {\n\t\tif (a === currentPath) return -1;\n\t\tif (b === currentPath) return 1;\n\t\treturn a.localeCompare(b);\n\t});\n\n\treturn (\n\t\t<div style={sidebarStyle}>\n\t\t\t<div style={sidebarHeaderStyle}>\n\t\t\t\t<strong style={{ fontSize: 14 }}>Comments ({comments.length})</strong>\n\t\t\t\t<button type=\"button\" onClick={onClose} style={ghostButtonStyle}>\n\t\t\t\t\tClose\n\t\t\t\t</button>\n\t\t\t</div>\n\t\t\t<div style={sidebarScrollStyle}>\n\t\t\t\t{comments.length === 0 ? (\n\t\t\t\t\t<div style={sidebarEmptyStyle}>No comments yet. Click “Add comment” to leave one.</div>\n\t\t\t\t) : (\n\t\t\t\t\tpaths.map((path) => (\n\t\t\t\t\t\t<div key={path} style={{ marginBottom: 12 }}>\n\t\t\t\t\t\t\t<div style={sidebarPathStyle}>{path === currentPath ? `${path} · current` : path}</div>\n\t\t\t\t\t\t\t{(groups.get(path) ?? []).map((c, idx) => (\n\t\t\t\t\t\t\t\t<button\n\t\t\t\t\t\t\t\t\tkey={c.id}\n\t\t\t\t\t\t\t\t\ttype=\"button\"\n\t\t\t\t\t\t\t\t\tonClick={() => onSelect(c)}\n\t\t\t\t\t\t\t\t\tstyle={sidebarItemStyle}\n\t\t\t\t\t\t\t\t\tdisabled={c.status === \"done\" && false}\n\t\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t\t<span style={sidebarItemIndexStyle}>{idx + 1}</span>\n\t\t\t\t\t\t\t\t\t<span style={sidebarItemTextStyle}>\n\t\t\t\t\t\t\t\t\t\t{c.content.length > 140 ? `${c.content.slice(0, 140)}…` : c.content}\n\t\t\t\t\t\t\t\t\t</span>\n\t\t\t\t\t\t\t\t\t{c.status === \"done\" && <span style={sidebarItemDoneStyle}>done</span>}\n\t\t\t\t\t\t\t\t</button>\n\t\t\t\t\t\t\t))}\n\t\t\t\t\t\t</div>\n\t\t\t\t\t))\n\t\t\t\t)}\n\t\t\t</div>\n\t\t</div>\n\t);\n}\n\nfunction EditPopover({\n\tinitial,\n\tonCancel,\n\tonSave,\n\tonRemove,\n}: {\n\tinitial: string;\n\tonCancel: () => void;\n\tonSave: (content: string) => Promise<void>;\n\tonRemove?: () => Promise<void>;\n}) {\n\tconst [value, setValue] = useState(initial);\n\tconst [saving, setSaving] = useState(false);\n\tconst textareaRef = useRef<HTMLTextAreaElement | null>(null);\n\n\tuseEffect(() => {\n\t\tconst el = textareaRef.current;\n\t\tif (!el) return;\n\t\tel.focus();\n\t\tconst len = el.value.length;\n\t\tel.setSelectionRange(len, len);\n\t}, []);\n\n\tconst handleSubmit = async (e: FormEvent) => {\n\t\te.preventDefault();\n\t\tconst content = value.trim();\n\t\tif (!content) return;\n\t\tsetSaving(true);\n\t\ttry {\n\t\t\tawait onSave(content);\n\t\t} finally {\n\t\t\tsetSaving(false);\n\t\t}\n\t};\n\n\treturn (\n\t\t<form onSubmit={handleSubmit} style={popoverStyle}>\n\t\t\t<textarea\n\t\t\t\tref={textareaRef}\n\t\t\t\tvalue={value}\n\t\t\t\tonChange={(e) => setValue(e.target.value)}\n\t\t\t\tplaceholder=\"Leave a comment…\"\n\t\t\t\tstyle={textareaStyle}\n\t\t\t\trows={3}\n\t\t\t/>\n\t\t\t<div style={popoverActionsStyle}>\n\t\t\t\t{onRemove && (\n\t\t\t\t\t<button type=\"button\" onClick={() => onRemove()} style={dangerButtonStyle} disabled={saving}>\n\t\t\t\t\t\tDelete\n\t\t\t\t\t</button>\n\t\t\t\t)}\n\t\t\t\t<div style={{ flex: 1 }} />\n\t\t\t\t<button type=\"button\" onClick={onCancel} style={ghostButtonStyle} disabled={saving}>\n\t\t\t\t\tCancel\n\t\t\t\t</button>\n\t\t\t\t<button type=\"submit\" style={primaryButtonStyle} disabled={saving || !value.trim()}>\n\t\t\t\t\t{saving ? \"Saving…\" : \"Save\"}\n\t\t\t\t</button>\n\t\t\t</div>\n\t\t</form>\n\t);\n}\n\nfunction useTargetPosition(selector: string, offsetXRatio: number, offsetYRatio: number) {\n\tconst [pos, setPos] = useState<{ top: number; left: number } | null>(null);\n\n\tuseEffect(() => {\n\t\tconst update = () => {\n\t\t\tlet el: Element | null = null;\n\t\t\ttry {\n\t\t\t\tel = document.querySelector(selector);\n\t\t\t} catch {\n\t\t\t\tel = null;\n\t\t\t}\n\t\t\tif (!el) {\n\t\t\t\tsetPos(null);\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tconst r = el.getBoundingClientRect();\n\t\t\tsetPos({\n\t\t\t\ttop: r.top + window.scrollY + r.height * offsetYRatio - 12,\n\t\t\t\tleft: r.left + window.scrollX + r.width * offsetXRatio - 12,\n\t\t\t});\n\t\t};\n\n\t\tupdate();\n\t\tconst ro = new ResizeObserver(update);\n\t\ttry {\n\t\t\tconst el = document.querySelector(selector);\n\t\t\tif (el) ro.observe(el);\n\t\t} catch {\n\t\t\t// swallow invalid selector\n\t\t}\n\t\twindow.addEventListener(\"scroll\", update, true);\n\t\twindow.addEventListener(\"resize\", update);\n\t\treturn () => {\n\t\t\tro.disconnect();\n\t\t\twindow.removeEventListener(\"scroll\", update, true);\n\t\t\twindow.removeEventListener(\"resize\", update);\n\t\t};\n\t}, [selector, offsetXRatio, offsetYRatio]);\n\n\treturn pos;\n}\n\n// Inline styles — toolbar is injected into arbitrary stores, so we avoid relying\n// on any CSS framework being present.\nconst toolbarStyle: CSSProperties = {\n\tposition: \"fixed\",\n\tbottom: 16,\n\tleft: \"50%\",\n\ttransform: \"translateX(-50%)\",\n\tzIndex: 2147483646,\n\tdisplay: \"flex\",\n\talignItems: \"center\",\n\tgap: 8,\n\tpadding: \"8px 12px\",\n\tbackground: \"rgba(17, 17, 17, 0.92)\",\n\tcolor: \"white\",\n\tborderRadius: 999,\n\tboxShadow: \"0 8px 24px rgba(0,0,0,0.25)\",\n\tfontFamily:\n\t\t'-apple-system, BlinkMacSystemFont, \"Segoe UI\", Roboto, Helvetica, Arial, sans-serif, \"Apple Color Emoji\", \"Segoe UI Emoji\"',\n\tfontSize: 14,\n\tpointerEvents: \"auto\",\n};\n\nconst toolbarButtonStyle: CSSProperties = {\n\tborder: \"none\",\n\tbackground: \"white\",\n\tcolor: \"#111\",\n\tpadding: \"6px 12px\",\n\tborderRadius: 999,\n\tcursor: \"pointer\",\n\tfontWeight: 600,\n\tfontSize: 13,\n};\n\nconst toolbarButtonActiveStyle: CSSProperties = {\n\t...toolbarButtonStyle,\n\tbackground: \"#ef4444\",\n\tcolor: \"white\",\n};\n\nconst toolbarButtonGhostStyle: CSSProperties = {\n\tborder: \"1px solid rgba(255,255,255,0.4)\",\n\tbackground: \"transparent\",\n\tcolor: \"white\",\n\tpadding: \"6px 12px\",\n\tborderRadius: 999,\n\tcursor: \"pointer\",\n\tfontWeight: 500,\n\tfontSize: 13,\n};\n\nconst toolbarButtonFinalizeStyle: CSSProperties = {\n\tborder: \"none\",\n\tbackground: \"#10b981\",\n\tcolor: \"white\",\n\tpadding: \"6px 12px\",\n\tborderRadius: 999,\n\tcursor: \"pointer\",\n\tfontWeight: 600,\n\tfontSize: 13,\n};\n\nconst toolbarHintStyle: CSSProperties = {\n\topacity: 0.8,\n\tfontSize: 12,\n};\n\nconst pinDotStyle: CSSProperties = {\n\twidth: 24,\n\theight: 24,\n\tborderRadius: 999,\n\tbackground: \"#10b981\",\n\tcolor: \"white\",\n\tborder: \"2px solid white\",\n\tcursor: \"pointer\",\n\tfontSize: 12,\n\tfontWeight: 700,\n\tboxShadow: \"0 2px 6px rgba(0,0,0,0.3)\",\n\tdisplay: \"inline-flex\",\n\talignItems: \"center\",\n\tjustifyContent: \"center\",\n\tpadding: 0,\n};\n\nconst popoverStyle: CSSProperties = {\n\tbackground: \"white\",\n\tborder: \"1px solid #e5e7eb\",\n\tborderRadius: 8,\n\tpadding: 12,\n\twidth: 280,\n\tboxShadow: \"0 12px 32px rgba(0,0,0,0.18)\",\n\tfontFamily:\n\t\t'-apple-system, BlinkMacSystemFont, \"Segoe UI\", Roboto, Helvetica, Arial, sans-serif, \"Apple Color Emoji\", \"Segoe UI Emoji\"',\n\tdisplay: \"flex\",\n\tflexDirection: \"column\",\n\tgap: 8,\n\tcolor: \"#111\",\n};\n\nconst textareaStyle: CSSProperties = {\n\twidth: \"100%\",\n\tborder: \"1px solid #d1d5db\",\n\tborderRadius: 6,\n\tpadding: 8,\n\tfontSize: 14,\n\tresize: \"vertical\",\n\tfontFamily: \"inherit\",\n\tcolor: \"#111\",\n\tbackground: \"white\",\n\tboxSizing: \"border-box\",\n};\n\nconst popoverActionsStyle: CSSProperties = {\n\tdisplay: \"flex\",\n\talignItems: \"center\",\n\tgap: 6,\n};\n\nconst baseButton: CSSProperties = {\n\tborder: \"1px solid transparent\",\n\tborderRadius: 6,\n\tpadding: \"6px 10px\",\n\tfontSize: 13,\n\tcursor: \"pointer\",\n\tfontWeight: 500,\n};\n\nconst primaryButtonStyle: CSSProperties = {\n\t...baseButton,\n\tbackground: \"#111\",\n\tcolor: \"white\",\n};\n\nconst ghostButtonStyle: CSSProperties = {\n\t...baseButton,\n\tbackground: \"transparent\",\n\tcolor: \"#374151\",\n\tborderColor: \"#d1d5db\",\n};\n\nconst dangerButtonStyle: CSSProperties = {\n\t...baseButton,\n\tbackground: \"transparent\",\n\tcolor: \"#b91c1c\",\n\tborderColor: \"#fecaca\",\n};\n\nconst sidebarStyle: CSSProperties = {\n\tposition: \"fixed\",\n\ttop: 0,\n\tright: 0,\n\tbottom: 0,\n\twidth: 360,\n\tmaxWidth: \"92vw\",\n\tbackground: \"white\",\n\tborderLeft: \"1px solid #e5e7eb\",\n\tboxShadow: \"-12px 0 32px rgba(0,0,0,0.12)\",\n\tzIndex: 2147483646,\n\tdisplay: \"flex\",\n\tflexDirection: \"column\",\n\tfontFamily:\n\t\t'-apple-system, BlinkMacSystemFont, \"Segoe UI\", Roboto, Helvetica, Arial, sans-serif, \"Apple Color Emoji\", \"Segoe UI Emoji\"',\n\tcolor: \"#111\",\n};\n\nconst sidebarHeaderStyle: CSSProperties = {\n\tdisplay: \"flex\",\n\talignItems: \"center\",\n\tjustifyContent: \"space-between\",\n\tpadding: \"12px 16px\",\n\tborderBottom: \"1px solid #e5e7eb\",\n};\n\nconst sidebarScrollStyle: CSSProperties = {\n\tflex: 1,\n\toverflow: \"auto\",\n\tpadding: \"12px 12px 24px\",\n};\n\nconst sidebarEmptyStyle: CSSProperties = {\n\tcolor: \"#6b7280\",\n\tfontSize: 13,\n\tpadding: \"24px 8px\",\n\ttextAlign: \"center\",\n};\n\nconst sidebarPathStyle: CSSProperties = {\n\tfontSize: 11,\n\ttextTransform: \"uppercase\",\n\tletterSpacing: 0.5,\n\tcolor: \"#6b7280\",\n\tpadding: \"4px 4px 6px\",\n\twordBreak: \"break-all\",\n};\n\nconst sidebarItemStyle: CSSProperties = {\n\tdisplay: \"flex\",\n\talignItems: \"flex-start\",\n\tgap: 8,\n\twidth: \"100%\",\n\ttextAlign: \"left\",\n\tbackground: \"white\",\n\tborder: \"1px solid #e5e7eb\",\n\tborderRadius: 6,\n\tpadding: \"8px 10px\",\n\tcursor: \"pointer\",\n\tfontSize: 13,\n\tmarginBottom: 6,\n\tcolor: \"#111\",\n};\n\nconst sidebarItemIndexStyle: CSSProperties = {\n\tflexShrink: 0,\n\twidth: 22,\n\theight: 22,\n\tborderRadius: 999,\n\tbackground: \"#10b981\",\n\tcolor: \"white\",\n\tfontWeight: 700,\n\tfontSize: 11,\n\tdisplay: \"inline-flex\",\n\talignItems: \"center\",\n\tjustifyContent: \"center\",\n};\n\nconst sidebarItemTextStyle: CSSProperties = {\n\tflex: 1,\n\twhiteSpace: \"pre-wrap\",\n\twordBreak: \"break-word\",\n};\n\nconst sidebarItemDoneStyle: CSSProperties = {\n\tflexShrink: 0,\n\tbackground: \"#d1fae5\",\n\tcolor: \"#065f46\",\n\tfontSize: 11,\n\tfontWeight: 600,\n\tpadding: \"2px 6px\",\n\tborderRadius: 4,\n\talignSelf: \"center\",\n};\n\nexport function mountFeedbackToolbar(): { unmount: () => void } | null {\n\tconsole.log(\"[YNS Feedback Toolbar] mountFeedbackToolbar() called\", {\n\t\tisWindow: typeof window !== \"undefined\",\n\t\tvercelEnv: process.env.NEXT_PUBLIC_VERCEL_ENV,\n\t\talreadyMounted: typeof document !== \"undefined\" && Boolean(document.getElementById(MOUNT_NODE_ID)),\n\t});\n\tif (typeof window === \"undefined\") return null;\n\tif (process.env.NEXT_PUBLIC_VERCEL_ENV !== \"preview\") {\n\t\tconsole.log(\n\t\t\t\"[YNS Feedback Toolbar] gate failed — NEXT_PUBLIC_VERCEL_ENV is\",\n\t\t\tprocess.env.NEXT_PUBLIC_VERCEL_ENV,\n\t\t);\n\t\treturn null;\n\t}\n\tif (document.getElementById(MOUNT_NODE_ID)) return null;\n\n\tconst container = document.createElement(\"div\");\n\tcontainer.id = MOUNT_NODE_ID;\n\tcontainer.dataset.ynsFeedbackUi = \"true\";\n\tdocument.body.appendChild(container);\n\n\tconst root = createRoot(container);\n\troot.render(<FeedbackToolbar />);\n\n\treturn {\n\t\tunmount: () => {\n\t\t\troot.unmount();\n\t\t\tcontainer.remove();\n\t\t},\n\t};\n}\n\n// Auto-mount on import. Wait for DOM ready.\nif (typeof window !== \"undefined\") {\n\tconsole.log(\"[YNS Feedback Toolbar] module evaluated\", {\n\t\tvercelEnv: process.env.NEXT_PUBLIC_VERCEL_ENV,\n\t\treadyState: document.readyState,\n\t\twillAutoMount: process.env.NEXT_PUBLIC_VERCEL_ENV === \"preview\",\n\t});\n}\nif (typeof window !== \"undefined\" && process.env.NEXT_PUBLIC_VERCEL_ENV === \"preview\") {\n\tif (document.readyState === \"loading\") {\n\t\tdocument.addEventListener(\"DOMContentLoaded\", () => {\n\t\t\tmountFeedbackToolbar();\n\t\t});\n\t} else {\n\t\tmountFeedbackToolbar();\n\t}\n}\n"],"mappings":"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","names":["useEffect","useRef","useState","createRoot","Fragment","jsx","jsxs","MOUNT_NODE_ID","buildApiBase","override","host","protocol","computeCssSelector","el","path","node","part","className","classes","c","parent","tag","siblings","idx","ATTRS_OF_INTEREST","formatAttrs","parts","attr","v","trimmed","formatTextContent","text","buildSurroundingHtml","target","ancestors","cur","lines","depth","ancestor","indent","targetIndent","targetTag","targetText","childIndent","children","child","childText","i","isInsideToolbar","IGNORED_TAGS","FeedbackToolbar","session","setSession","loading","setLoading","pinMode","setPinMode","pending","setPending","editingId","setEditingId","sidebarOpen","setSidebarOpen","finalizing","setFinalizing","apiBase","controller","res","data","overlay","label","hovered","handleMove","e","rect","handleLeave","handleClick","event","offsetXRatio","offsetYRatio","refreshComments","submitNewComment","content","updateComment","id","removeComment","finalizeSession","prev","scrollToComment","comment","visiblePins","pin","PinOverlay","PendingCommentPopover","CommentsSidebar","toolbarStyle","toolbarButtonActiveStyle","toolbarButtonStyle","toolbarButtonGhostStyle","toolbarButtonFinalizeStyle","toolbarHintStyle","number","editing","onStartEdit","onCancelEdit","onSave","onRemove","useTargetPosition","pinDotStyle","EditPopover","onCancel","comments","currentPath","onClose","onSelect","groups","list","paths","a","b","sidebarStyle","sidebarHeaderStyle","ghostButtonStyle","sidebarScrollStyle","sidebarEmptyStyle","sidebarPathStyle","sidebarItemStyle","sidebarItemIndexStyle","sidebarItemTextStyle","sidebarItemDoneStyle","initial","value","setValue","saving","setSaving","textareaRef","len","popoverStyle","textareaStyle","popoverActionsStyle","dangerButtonStyle","primaryButtonStyle","selector","pos","setPos","update","r","ro","baseButton","mountFeedbackToolbar","container","root"]}
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "$schema": "https://json.schemastore.org/package",
3
3
  "name": "commerce-kit",
4
- "version": "0.36.3",
4
+ "version": "0.36.5",
5
5
  "type": "module",
6
6
  "license": "AGPL-3.0-only",
7
7
  "keywords": [