review-lens-react 1.0.1 → 1.0.3
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.
|
@@ -1,3 +1,3 @@
|
|
|
1
|
-
(function(L,
|
|
2
|
-
`);return
|
|
3
|
-
`)}function vt(e){return e.actorEmail?`Sent by Review Lens on behalf of ${e.actorEmail}.`:"Sent by Review Lens on behalf of the signed-in Google user."}function Ce(e){return e.kind==="created"?"New review feedback":e.kind==="assigned"?`Review assignment changed to ${e.item.assigneeEmail??"unassigned"}`:e.kind==="status"?`Review status changed to ${Ee(e.item.status)}`:e.kind==="fixed"?"Review marked fixed":e.kind==="resolved"?"Review resolved":e.kind==="reply"?"New review reply":"Review updated"}function yt(e){try{const t=new URL(e.originalUrl);return t.searchParams.set("reviewLensFeedback",e.id),t.toString()}catch{return e.originalUrl}}function Ee(e){return e.replace(/_/g," ")}const St=["data-review-id","data-testid","data-test-id","aria-label","name"];function W(e){const t=e.getBoundingClientRect(),n=kt(e);return{selector:n.selector,selectorStrategy:n.strategy,fingerprint:Et(e,t),cssSnapshot:Nt(e,t),rect:t}}function kt(e){for(const t of St){const n=e.getAttribute(t);if(n)return{selector:`[${t}="${Ne(n)}"]`,strategy:"stable-attribute"}}return e.id?{selector:`#${Ne(e.id)}`,strategy:"stable-attribute"}:{selector:Ct(e),strategy:"css-path"}}function Ct(e){const t=[];let n=e;for(;n&&n.nodeType===Node.ELEMENT_NODE&&n!==document.body;){const s=n.parentElement,a=n.tagName.toLowerCase();if(!s){t.unshift(a);break}const d=n.tagName,h=Array.from(s.children).filter(f=>f.tagName===d),w=h.indexOf(n)+1;t.unshift(h.length>1?`${a}:nth-of-type(${w})`:a),n=s}return t.join(" > ")}function Et(e,t){var n;return{tagName:e.tagName.toLowerCase(),id:e.id||void 0,className:e.getAttribute("class")||void 0,textSnippet:((n=e.textContent)==null?void 0:n.trim().slice(0,80))||void 0,ariaLabel:e.getAttribute("aria-label")||void 0,width:Math.round(t.width),height:Math.round(t.height)}}function Nt(e,t){const n=window.getComputedStyle(e);return{margin:oe(n.marginTop,n.marginRight,n.marginBottom,n.marginLeft),marginTop:n.marginTop,marginRight:n.marginRight,marginBottom:n.marginBottom,marginLeft:n.marginLeft,padding:oe(n.paddingTop,n.paddingRight,n.paddingBottom,n.paddingLeft),paddingTop:n.paddingTop,paddingRight:n.paddingRight,paddingBottom:n.paddingBottom,paddingLeft:n.paddingLeft,border:oe(n.borderTopWidth,n.borderRightWidth,n.borderBottomWidth,n.borderLeftWidth),borderTopWidth:n.borderTopWidth,borderRightWidth:n.borderRightWidth,borderBottomWidth:n.borderBottomWidth,borderLeftWidth:n.borderLeftWidth,fontFamily:n.fontFamily,fontSize:n.fontSize,lineHeight:n.lineHeight,color:n.color,backgroundColor:n.backgroundColor,borderRadius:n.borderRadius,width:Math.round(t.width),height:Math.round(t.height)}}function oe(e,t,n,s){return e===t&&t===n&&n===s?e:`${e} ${t} ${n} ${s}`}function Ne(e){return typeof CSS<"u"&&typeof CSS.escape=="function"?CSS.escape(e):e.replace(/["\\]/g,"\\$&")}function xe({className:e,title:t="Review Lens logo"}){return r.jsxs("svg",{className:e,role:"img","aria-label":t,viewBox:"0 0 40 40",fill:"none",xmlns:"http://www.w3.org/2000/svg",children:[r.jsx("rect",{x:"4",y:"6",width:"28",height:"28",rx:"8",fill:"#171717"}),r.jsx("path",{d:"M13 15.5C14.5 13.4 17.1 12 20 12C23.9 12 27.3 14.5 28.7 18C27.3 21.5 23.9 24 20 24C17.1 24 14.5 22.6 13 20.5",stroke:"#FFFFFF",strokeWidth:"2.2",strokeLinecap:"round",strokeLinejoin:"round"}),r.jsx("circle",{cx:"20",cy:"18",r:"3.4",fill:"#F97316"}),r.jsx("path",{d:"M28.5 26.5L34.5 32.5",stroke:"#2563EB",strokeWidth:"4",strokeLinecap:"round"}),r.jsx("circle",{cx:"31.8",cy:"29.8",r:"2.1",fill:"#FACC15",stroke:"#171717",strokeWidth:"1.4"})]})}const xt=[{label:"Desktop",value:"desktop"},{label:"Tablet",value:"tablet"},{label:"Mobile",value:"mobile"}],Le=["open","in_progress","needs_clarification","fixed","wontfix","resolved"],Fe=["low","medium","high"],Ae=["bug","visual","copy","accessibility","responsive"],R={open:"Open",in_progress:"In progress",needs_clarification:"Needs clarification",fixed:"Fixed",wontfix:"Won't fix",resolved:"Resolved"},H={low:"Low",medium:"Medium",high:"High"},O={bug:"Bug",visual:"Visual",copy:"Copy",accessibility:"Accessibility",responsive:"Responsive"};function Lt({open:e,onOpenChange:t,placement:n="top-right",showResolved:s=!1,syncSelectionToUrl:a=!1,responsivePresets:d=xt}){var Qe;const{adapter:h,config:w,currentUser:f,feedback:b,normalizedPath:g,permissions:m,createFeedback:p,updateFeedback:S,listMessages:E,createMessage:N,uploadAttachment:o}=Se(),[A,v]=c.useState(),[y,C]=c.useState(),[F,j]=c.useState(""),[q,Vt]=c.useState("medium"),[Be,Yt]=c.useState("visual"),[Pe,_e]=c.useState(""),[je,Xt]=c.useState(((Qe=d[0])==null?void 0:Qe.value)??"desktop"),[k,G]=c.useState(),[T,P]=c.useState("review"),[Qt,Ue]=c.useState(!1),[V,We]=c.useState("all"),[Y,De]=c.useState("all"),[X,ze]=c.useState("all"),[Q,He]=c.useState("all"),[Z,Oe]=c.useState("all"),[Zt,Rt]=c.useState(!1),[en,Ke]=c.useState({}),[le,de]=c.useState(""),te=c.useRef(null),Je=c.useRef(e),ce=c.useRef(a?new URL(window.location.href).searchParams.get("reviewLensFeedback"):null),$=!!f,B=m.includes("create"),qe=m.includes("reply"),Ge=m.includes("update"),tn=m.includes("assign"),U=A??y,nn=!!y,rn=!!(w.captureScreenshot&&(w.uploadAttachment||h.uploadAttachment)),sn=c.useMemo(()=>{const i=b.map(u=>u.assigneeEmail).filter(u=>!!u);return f!=null&&f.email&&i.push(f.email),Array.from(new Set(i)).sort((u,l)=>u.localeCompare(l))},[f==null?void 0:f.email,b]),M=c.useMemo(()=>b.filter(i=>s||i.status!=="resolved").filter(i=>V==="all"||i.status===V).filter(i=>Y==="all"||i.severity===Y).filter(i=>X==="all"||i.category===X).filter(i=>Q==="all"||i.assigneeEmail===Q).filter(i=>Z==="all"||i.viewportPreset===Z),[Q,X,b,Y,s,V,Z]),an=[V,Y,X,Q,Z].filter(i=>i!=="all").length;c.useEffect(()=>{if(e){Je.current=!0;return}if(v(void 0),C(void 0),j(""),de(""),P("review"),a&&Je.current){const i=new URL(window.location.href);i.searchParams.has("reviewLensFeedback")&&(i.searchParams.delete("reviewLensFeedback"),window.history.replaceState({},"",i))}},[e,a]),c.useEffect(()=>{$||(v(void 0),C(void 0))},[$]),c.useEffect(()=>{!y||T!=="review"||window.requestAnimationFrame(()=>{var i,u,l;(u=(i=te.current)==null?void 0:i.scrollIntoView)==null||u.call(i,{block:"nearest"}),(l=te.current)==null||l.focus()})},[y,T]),c.useEffect(()=>{if(!k)return;let i=!0;return E(k.id).then(u=>{i&&Ke(l=>({...l,[k.id]:u}))}),()=>{i=!1}},[E,k]),c.useEffect(()=>{if(!a||!ce.current||b.length===0)return;const i=b.find(u=>u.id===ce.current);i&&(ce.current=null,t==null||t(!0),z(i,{syncUrl:!1}))},[b,a]),c.useEffect(()=>{if(!e||!a||k||b.length===0)return;const i=new URL(window.location.href).searchParams.get("reviewLensFeedback"),u=b.find(l=>l.id===i);u&&z(u,{syncUrl:!1})},[b,e,k,a]),c.useEffect(()=>{if(!e)return;function i(l){var x;if(l.key==="Shift"&&Ue(!0),l.key==="Escape"){l.preventDefault(),t==null||t(!1);return}Kt(l.target)||((l.key==="n"||l.key==="ArrowDown")&&(l.preventDefault(),Ve(1)),(l.key==="p"||l.key==="ArrowUp")&&(l.preventDefault(),Ve(-1)),l.key==="c"&&(l.preventDefault(),P("review"),(x=te.current)==null||x.focus()),l.key==="f"&&k&&Ge&&(l.preventDefault(),Xe(k)))}function u(l){l.key==="Shift"&&Ue(!1)}return window.addEventListener("keydown",i),window.addEventListener("keyup",u),()=>{window.removeEventListener("keydown",i),window.removeEventListener("keyup",u)}});const he=c.useCallback(i=>{const u=i.target instanceof Element?i.target:null;if(u)return u.closest("[data-review-lens-ui]")?null:u;const l=document.elementFromPoint(i.clientX,i.clientY);return!l||l.closest("[data-review-lens-ui]")?null:l},[]);if(c.useEffect(()=>{if(!e||!$)return;function i(l){const x=he(l);v(x?W(x):void 0)}function u(l){const x=he(l);x&&(l.preventDefault(),l.stopPropagation(),C(W(x)),P("review"))}return window.addEventListener("mousemove",i,!0),window.addEventListener("click",u,!0),()=>{window.removeEventListener("mousemove",i,!0),window.removeEventListener("click",u,!0)}},[$,he,e]),!e)return null;function z(i,u={syncUrl:!0}){var x;if(G(i),C(void 0),P("feedback"),a&&u.syncUrl!==!1){const ne=new URL(window.location.href);ne.searchParams.set("reviewLensFeedback",i.id),window.history.replaceState({},"",ne)}const l=D(i.selector);if(!l){v(void 0);return}(x=l.scrollIntoView)==null||x.call(l,{behavior:"smooth",block:"center",inline:"center"}),window.requestAnimationFrame(()=>{v(W(l))})}function Ve(i){if(M.length===0)return;const u=k?M.findIndex(x=>x.id===k.id):-1,l=u<0?i>0?0:M.length-1:(u+i+M.length)%M.length;z(M[l])}async function Ye(){if(!y||!F.trim()||!f||!B)return;let i=await p({projectKey:w.projectKey,contentId:w.contentId,normalizedPath:g,originalUrl:w.currentUrl??window.location.href,selector:y.selector,selectorStrategy:y.selectorStrategy,elementFingerprint:y.fingerprint,createdCssSnapshot:y.cssSnapshot,comment:F.trim(),status:"open",severity:q,category:Be,assigneeEmail:Pe.trim()||void 0,viewportWidth:window.innerWidth,viewportHeight:window.innerHeight,viewportPreset:je,screenshotUrl:void 0,screenshotThumbnailUrl:void 0,authorEmail:f.email});if(w.captureScreenshot)try{const u=await w.captureScreenshot(y),l=await o(i.id,{type:"screenshot",data:u,createdBy:f.email});i=await S(i.id,{attachments:[l],screenshotUrl:l.url,screenshotThumbnailUrl:l.thumbnailUrl})}catch{}if(j(""),_e(""),C(void 0),v(void 0),P("feedback"),G(i),a){const u=new URL(window.location.href);u.searchParams.set("reviewLensFeedback",i.id),window.history.replaceState({},"",u)}}async function on(i,u){const l=new Date().toISOString(),x=u==="resolved"?{status:u,resolvedAt:l,resolvedBy:f==null?void 0:f.email}:{status:u},ne=await S(i.id,x);G(ne)}async function Xe(i){const u=D(i.selector);if(!u||!f)return;const l=W(u),x=await S(i.id,{status:"fixed",fixedCssSnapshot:l.cssSnapshot,fixedAt:new Date().toISOString(),fixedBy:f.email});G(x)}async function ln(i){if(!le.trim()||!f||!qe)return;const u=await N({feedbackId:i.id,body:le.trim(),authorEmail:f.email});Ke(l=>({...l,[i.id]:[...l[i.id]??[],u]})),de("")}return r.jsxs("div",{className:"review-lens-root","data-review-lens-ui":!0,children:[$&&U?r.jsx($t,{target:U,locked:!!y}):null,$&&y&&A&&Qt?r.jsx(Bt,{from:y,to:A}):null,$?r.jsxs(r.Fragment,{children:[r.jsx(Pt,{feedback:M,selectedFeedback:k,onSelect:z}),r.jsx(jt,{feedback:M,selectedFeedback:k,onSelect:z})]}):null,r.jsxs("aside",{className:`review-lens-panel review-lens-panel--${n}`,"data-review-lens-ui":!0,children:[r.jsxs("header",{className:"review-lens-panel__header",children:[r.jsxs("div",{className:"review-lens-brand",children:[r.jsx(xe,{className:"review-lens-brand__mark"}),r.jsxs("div",{children:[r.jsx("p",{className:"review-lens-kicker",children:"Review Lens"}),r.jsx("h2",{children:T==="summary"?"Summary":T==="feedback"?"Feedback":y?"Element locked":"Inspecting"})]})]}),r.jsx("button",{type:"button",onClick:()=>t==null?void 0:t(!1),children:"Close"})]}),r.jsxs("div",{className:"review-lens-panel__body",children:[r.jsxs("div",{className:"review-lens-mode-switch",role:"tablist","aria-label":"Review Lens mode",children:[r.jsx("button",{type:"button",role:"tab","aria-selected":T==="review",onClick:()=>P("review"),children:"Review"}),r.jsxs("button",{type:"button",role:"tab","aria-selected":T==="feedback",onClick:()=>P("feedback"),children:["Feedback ",r.jsx("span",{children:M.length})]}),r.jsx("button",{type:"button",role:"tab","aria-selected":T==="summary",onClick:()=>P("summary"),children:"Summary"})]}),T==="review"?r.jsxs("div",{className:"review-lens-review-pane",role:"tabpanel",children:[r.jsxs("div",{className:"review-lens-inspection",children:[$?null:r.jsx("p",{children:"Authenticate with Google to inspect this page."}),$&&U?r.jsxs(r.Fragment,{children:[r.jsx(Ut,{target:U}),r.jsx(Ie,{title:"Accessibility",items:Wt(U)}),r.jsx(Ie,{title:"Design tokens",items:Dt(U.cssSnapshot,w.designTokens)})]}):null,$&&!U?r.jsx("p",{children:"Move over the app to inspect."}):null]}),nn?r.jsx("div",{className:"review-lens-composer-panel",children:r.jsxs("form",{className:"review-lens-feedback-form",onSubmit:i=>{i.preventDefault(),Ye()},children:[r.jsx("label",{htmlFor:"review-lens-comment",children:"New feedback"}),r.jsx("textarea",{ref:te,id:"review-lens-comment",value:F,disabled:!B,onChange:i=>j(i.target.value),onKeyDown:i=>{i.key==="Enter"&&i.metaKey&&(i.preventDefault(),Ye())},placeholder:B?"Describe the UX issue...":"You do not have permission to comment."}),r.jsxs("div",{className:"review-lens-form-grid",children:[r.jsxs("label",{children:["Severity",r.jsx("select",{value:q,onChange:i=>Vt(i.target.value),disabled:!B,children:Fe.map(i=>r.jsx("option",{value:i,children:H[i]},i))})]}),r.jsxs("label",{children:["Type",r.jsx("select",{value:Be,onChange:i=>Yt(i.target.value),disabled:!B,children:Ae.map(i=>r.jsx("option",{value:i,children:O[i]},i))})]}),r.jsxs("label",{children:["Assignee",r.jsx("input",{value:Pe,onChange:i=>_e(i.target.value),disabled:!B,placeholder:"optional@email.com"})]}),r.jsxs("label",{children:["Viewport",r.jsx("select",{value:je,onChange:i=>Xt(i.target.value),disabled:!B,children:d.map(i=>r.jsx("option",{value:i.value,children:i.label},i.value))})]})]}),B?r.jsxs("p",{className:"review-lens-feedback-form__hint",children:["Press ",r.jsx("kbd",{children:"Command"})," + ",r.jsx("kbd",{children:"Enter"})," to submit.",rn?" Screenshot capture runs after save.":""]}):null,r.jsx("div",{className:"review-lens-actions",children:r.jsx("button",{type:"submit",disabled:!F.trim()||!B,children:"Save feedback"})})]})}):null]}):null,T==="feedback"?r.jsxs("div",{className:"review-lens-comments",children:[r.jsx(Ft,{open:Zt,activeCount:an,statusFilter:V,severityFilter:Y,categoryFilter:X,assigneeFilter:Q,viewportFilter:Z,assignees:sn,responsivePresets:d,onStatusChange:We,onSeverityChange:De,onCategoryChange:ze,onAssigneeChange:He,onViewportChange:Oe,onToggle:()=>Rt(i=>!i),onClear:()=>{We("all"),De("all"),ze("all"),He("all"),Oe("all")}}),r.jsxs("div",{className:"review-lens-list-panel",children:[r.jsxs("div",{className:"review-lens-comments__header",children:[r.jsx("h3",{children:"All feedback"}),r.jsx("span",{children:M.length})]}),r.jsxs("div",{className:"review-lens-comments__list",children:[M.length===0?r.jsx("p",{children:"No feedback for this view."}):null,M.map(i=>r.jsx(At,{item:i,selected:(k==null?void 0:k.id)===i.id,onSelect:z},i.id))]})]}),k?r.jsxs("div",{className:"review-lens-selected-panel",children:[r.jsx("div",{className:"review-lens-selected-panel__label",children:"Selected feedback"}),r.jsx(It,{item:k,messages:en[k.id]??[],messageDraft:le,canReply:qe,canUpdate:Ge,canAssign:tn,syncSelectionToUrl:a,onMessageDraftChange:de,onSubmitMessage:()=>void ln(k),onStatusChange:i=>void on(k,i),onAssigneeChange:i=>void S(k.id,{assigneeEmail:i.trim()||void 0}).then(G),onMarkFixed:()=>void Xe(k)},k.id)]}):r.jsxs("div",{className:"review-lens-selected-panel review-lens-selected-panel--empty",children:[r.jsx("div",{className:"review-lens-selected-panel__label",children:"Selected feedback"}),r.jsx("p",{children:"Select a feedback item above to review status, assignment, drift, and replies."})]})]}):null,T==="summary"?r.jsx(Tt,{feedback:b}):null]})]})]})}function Ft({open:e,activeCount:t,statusFilter:n,severityFilter:s,categoryFilter:a,assigneeFilter:d,viewportFilter:h,assignees:w,responsivePresets:f,onStatusChange:b,onSeverityChange:g,onCategoryChange:m,onAssigneeChange:p,onViewportChange:S,onToggle:E,onClear:N}){return r.jsxs("div",{className:"review-lens-filter-shell",children:[r.jsxs("div",{className:"review-lens-filter-bar",children:[r.jsxs("button",{type:"button","aria-expanded":e,onClick:E,children:["Filters",t>0?r.jsx("span",{children:t}):null]}),t>0?r.jsx("button",{type:"button",onClick:N,children:"Clear"}):null]}),e?r.jsxs("div",{className:"review-lens-filters",children:[r.jsxs("label",{children:["Status",r.jsxs("select",{"aria-label":"Filter status",value:n,onChange:o=>b(o.target.value),children:[r.jsx("option",{value:"all",children:"All statuses"}),Le.map(o=>r.jsx("option",{value:o,children:R[o]},o))]})]}),r.jsxs("label",{children:["Priority",r.jsxs("select",{"aria-label":"Filter severity",value:s,onChange:o=>g(o.target.value),children:[r.jsx("option",{value:"all",children:"All priorities"}),Fe.map(o=>r.jsx("option",{value:o,children:H[o]},o))]})]}),r.jsxs("label",{children:["Type",r.jsxs("select",{"aria-label":"Filter type",value:a,onChange:o=>m(o.target.value),children:[r.jsx("option",{value:"all",children:"All types"}),Ae.map(o=>r.jsx("option",{value:o,children:O[o]},o))]})]}),r.jsxs("label",{children:["Assignee",r.jsxs("select",{"aria-label":"Filter assignee",value:d,onChange:o=>p(o.target.value),children:[r.jsx("option",{value:"all",children:"All assignees"}),w.map(o=>r.jsx("option",{value:o,children:o},o))]})]}),r.jsxs("label",{children:["Viewport",r.jsxs("select",{"aria-label":"Filter viewport",value:h,onChange:o=>S(o.target.value),children:[r.jsx("option",{value:"all",children:"All viewports"}),f.map(o=>r.jsx("option",{value:o.value,children:o.label},o.value))]})]})]}):null]})}function At({item:e,selected:t,onSelect:n}){const s=Me(e);return r.jsxs("article",{tabIndex:0,className:["review-lens-comment",`review-lens-comment--${e.severity}`,t?"review-lens-comment--selected":""].filter(Boolean).join(" "),onClick:()=>n(e),onKeyDown:a=>{(a.key==="Enter"||a.key===" ")&&(a.preventDefault(),n(e))},children:[r.jsxs("div",{className:"review-lens-comment__header",children:[r.jsx("span",{children:R[e.status]}),r.jsx("strong",{children:H[e.severity]})]}),r.jsxs("div",{className:"review-lens-comment__content",children:[r.jsx("p",{children:e.comment}),r.jsxs("span",{children:[e.authorEmail,e.assigneeEmail?` -> ${e.assigneeEmail}`:""]})]}),r.jsxs("div",{className:"review-lens-tags",children:[r.jsx("span",{children:O[e.category]}),r.jsx("span",{children:e.viewportPreset}),r.jsx("span",{children:s.label})]})]})}function It({item:e,messages:t,messageDraft:n,canReply:s,canUpdate:a,canAssign:d,syncSelectionToUrl:h,onMessageDraftChange:w,onSubmitMessage:f,onStatusChange:b,onAssigneeChange:g,onMarkFixed:m}){const[p,S]=c.useState(!1),E=Me(e);function N(){const o=new URL(window.location.href);o.searchParams.set("reviewLensFeedback",e.id),Mt(o.toString()).then(A=>{A&&(S(!0),setTimeout(()=>S(!1),2e3))})}return r.jsxs("section",{className:"review-lens-detail","aria-label":"Selected feedback detail",children:[r.jsxs("div",{className:"review-lens-detail__header",children:[r.jsxs("h3",{children:[O[e.category]," feedback"]}),r.jsxs("div",{className:"review-lens-detail__header-actions",children:[h?r.jsx("button",{type:"button",className:"review-lens-copy-link",onClick:N,"aria-label":"Copy link to this feedback",children:p?"Copied!":"Copy link"}):null,r.jsx("strong",{children:H[e.severity]})]})]}),r.jsx("blockquote",{children:e.comment}),r.jsxs("dl",{className:"review-lens-detail-meta",children:[r.jsxs("div",{children:[r.jsx("dt",{children:"Target"}),r.jsx("dd",{children:E.label})]}),r.jsxs("div",{children:[r.jsx("dt",{children:"Viewport"}),r.jsx("dd",{children:e.viewportPreset})]}),e.screenshotUrl?r.jsxs("div",{children:[r.jsx("dt",{children:"Evidence"}),r.jsx("dd",{children:r.jsx("a",{href:e.screenshotUrl,target:"_blank",rel:"noreferrer",children:"Screenshot"})})]}):null]}),r.jsxs("div",{className:"review-lens-form-grid",children:[r.jsxs("label",{children:["Status",r.jsx("select",{value:e.status,disabled:!a,onChange:o=>b(o.target.value),children:Le.map(o=>r.jsx("option",{value:o,children:R[o]},o))})]}),r.jsxs("label",{children:["Assignee",r.jsx("input",{defaultValue:e.assigneeEmail??"",disabled:!d,onBlur:o=>g(o.target.value),placeholder:"optional@email.com"})]})]}),r.jsxs("div",{className:"review-lens-status-actions",children:[r.jsx("button",{type:"button",className:"review-lens-button-secondary",disabled:!a,onClick:m,children:"Mark fixed"}),r.jsx("button",{type:"button",className:"review-lens-button-primary",disabled:!a,onClick:()=>b("resolved"),children:"Resolve"})]}),r.jsxs("div",{className:"review-lens-thread",children:[r.jsxs("div",{className:"review-lens-thread__header",children:[r.jsx("h3",{children:"Thread"}),r.jsx("span",{children:t.length})]}),t.length===0?r.jsx("p",{children:"No replies yet."}):null,t.map(o=>r.jsxs("div",{className:"review-lens-thread__message",children:[r.jsx("p",{children:o.body}),r.jsx("span",{children:o.authorEmail})]},o.id)),r.jsx("textarea",{"aria-label":"Reply",value:n,disabled:!s,onChange:o=>w(o.target.value),placeholder:s?"Reply...":"You do not have permission to reply."}),r.jsx("div",{className:"review-lens-actions",children:r.jsx("button",{type:"button",disabled:!n.trim()||!s,onClick:f,children:"Reply"})})]})]})}async function Mt(e){var n;if((n=navigator.clipboard)!=null&&n.writeText)return await navigator.clipboard.writeText(e),!0;const t=document.createElement("textarea");t.value=e,t.setAttribute("readonly",""),t.style.position="fixed",t.style.opacity="0",document.body.append(t),t.select();try{return document.execCommand("copy")}finally{t.remove()}}function Tt({feedback:e}){return r.jsxs("div",{className:"review-lens-summary",role:"tabpanel",children:[r.jsx(K,{title:"Status",values:J(e,t=>R[t.status])}),r.jsx(K,{title:"Severity",values:J(e,t=>H[t.severity])}),r.jsx(K,{title:"Type",values:J(e,t=>O[t.category])}),r.jsx(K,{title:"Assignee",values:J(e,t=>t.assigneeEmail??"Unassigned")}),r.jsx(K,{title:"Viewport",values:J(e,t=>t.viewportPreset)})]})}function K({title:e,values:t}){return r.jsxs("section",{children:[r.jsx("h3",{children:e}),r.jsx("dl",{children:t.map(([n,s])=>r.jsxs("div",{children:[r.jsx("dt",{children:n}),r.jsx("dd",{children:s})]},n))})]})}function $t({target:e,locked:t}){const n=Gt(e),s=Ht(e.fingerprint);return r.jsxs("div",{className:t?"review-lens-highlight review-lens-highlight--locked":"review-lens-highlight",style:{top:n.margin.top,left:n.margin.left,width:n.margin.width,height:n.margin.height},children:[r.jsx("div",{className:"review-lens-highlight__border",style:{top:n.border.top-n.margin.top,left:n.border.left-n.margin.left,width:n.border.width,height:n.border.height}}),r.jsx("div",{className:"review-lens-highlight__padding",style:{top:n.padding.top-n.margin.top,left:n.padding.left-n.margin.left,width:n.padding.width,height:n.padding.height}}),r.jsx("div",{className:"review-lens-highlight__content",style:{top:n.content.top-n.margin.top,left:n.content.left-n.margin.left,width:n.content.width,height:n.content.height}}),r.jsxs("div",{className:"review-lens-highlight__label",children:[r.jsx("strong",{children:s}),r.jsxs("span",{children:[Math.round(e.rect.width)," x ",Math.round(e.rect.height)]})]})]})}function Bt({from:e,to:t}){const n=Ot(e.rect,t.rect);return n.length===0?null:r.jsx(r.Fragment,{children:n.map(s=>r.jsx("div",{className:`review-lens-distance review-lens-distance--${s.axis}`,style:{top:s.top,left:s.left,width:s.width,height:s.height},children:r.jsx("span",{children:s.label})},s.key))})}function Pt({feedback:e,selectedFeedback:t,onSelect:n}){return r.jsx(r.Fragment,{children:e.map(s=>r.jsx(_t,{feedback:s,selected:(t==null?void 0:t.id)===s.id,onSelect:n},s.id))})}function _t({feedback:e,selected:t,onSelect:n}){const s=c.useRef(null);return c.useLayoutEffect(()=>{let a=0;const d=()=>{a=0;const w=s.current,f=D(e.selector),b=f==null?void 0:f.getBoundingClientRect();!w||!b||(w.style.top=`${b.top}px`,w.style.left=`${b.right}px`,w.hidden=b.bottom<0||b.top>window.innerHeight)},h=()=>{a||(a=window.requestAnimationFrame(d))};return d(),window.addEventListener("scroll",h,!0),window.addEventListener("resize",h),()=>{a&&window.cancelAnimationFrame(a),window.removeEventListener("scroll",h,!0),window.removeEventListener("resize",h)}},[e.selector]),r.jsx("button",{ref:s,type:"button",className:t?"review-lens-marker review-lens-marker--selected":"review-lens-marker",onClick:()=>n(e),"aria-label":`Open feedback from ${e.authorEmail}`})}function jt({feedback:e,selectedFeedback:t,onSelect:n}){const s=e.map(a=>{const d=D(a.selector),h=d==null?void 0:d.getBoundingClientRect(),w=Math.max(document.documentElement.scrollHeight,document.body.scrollHeight,window.innerHeight);return!h||w<=0?null:{item:a,top:Math.min(100,Math.max(0,(h.top+window.scrollY)/w*100))}}).filter(a=>a!==null);return s.length===0?null:r.jsx("div",{className:"review-lens-minimap","data-review-lens-ui":!0,"aria-label":"Feedback map",children:s.map(a=>r.jsx("button",{type:"button",className:(t==null?void 0:t.id)===a.item.id?"review-lens-minimap__point review-lens-minimap__point--selected":"review-lens-minimap__point",style:{top:`${a.top}%`},onClick:()=>n(a.item),"aria-label":`Jump to feedback from ${a.item.authorEmail}`},a.item.id))})}function Ut({target:e}){const t=[["Selector",e.selector],["Size",`${e.cssSnapshot.width} x ${e.cssSnapshot.height}`],["Margin",e.cssSnapshot.margin],["Padding",e.cssSnapshot.padding],["Border",e.cssSnapshot.border],["Radius",e.cssSnapshot.borderRadius],["Font",`${e.cssSnapshot.fontSize} / ${e.cssSnapshot.lineHeight}`],["Family",e.cssSnapshot.fontFamily],["Color",e.cssSnapshot.color],["Background",e.cssSnapshot.backgroundColor]];return r.jsx("dl",{className:"review-lens-metrics",children:t.map(([n,s])=>r.jsxs("div",{children:[r.jsx("dt",{children:n}),r.jsx("dd",{children:s})]},n))})}function Ie({title:e,items:t}){return r.jsxs("section",{className:"review-lens-insights",children:[r.jsx("h3",{children:e}),t.length===0?r.jsx("p",{children:"No issues detected."}):null,t.length>0?r.jsx("ul",{children:t.map(n=>r.jsx("li",{children:n},n))}):null]})}function D(e){try{return document.querySelector(e)}catch{return null}}function Me(e){const t=D(e.selector);if(!t)return{label:"Target missing",level:"warning"};const n=W(t);return n.fingerprint.tagName!==e.elementFingerprint.tagName?{label:"Element changed",level:"warning"}:Math.abs(n.fingerprint.width-e.elementFingerprint.width)>2||Math.abs(n.fingerprint.height-e.elementFingerprint.height)>2?{label:"Size changed",level:"warning"}:n.cssSnapshot.fontSize!==e.createdCssSnapshot.fontSize||n.cssSnapshot.color!==e.createdCssSnapshot.color||n.cssSnapshot.padding!==e.createdCssSnapshot.padding?{label:"Style changed",level:"warning"}:{label:"Target unchanged",level:"ok"}}function Wt(e){var f;const t=D(e.selector);if(!t)return["Selected element is no longer available."];const n=[],s=t.tagName.toLowerCase(),a=t.getAttribute("role"),d=["button","a","input","select","textarea"].includes(s)||a==="button"||a==="link",h=t.getAttribute("aria-label")||t.getAttribute("title")||((f=t.textContent)==null?void 0:f.trim());d&&!h&&n.push("Interactive element has no accessible name."),d&&(e.rect.width<44||e.rect.height<44)&&n.push("Tap target is smaller than 44 x 44."),s==="img"&&!t.getAttribute("alt")&&n.push("Image is missing alt text.");const w=/^h[1-6]$/.test(s)?Number(s.slice(1)):0;return w>1&&!document.querySelector(`h${w-1}`)&&n.push("Heading may skip the previous level."),Jt(e.cssSnapshot.color,e.cssSnapshot.backgroundColor)&&n.push("Text contrast may be low."),n}function Dt(e,t={}){const n=[];return _("Padding",e.padding,t.spacing,n,{allowComposite:!0}),_("Margin",e.margin,t.spacing,n,{allowComposite:!0}),_("Font size",e.fontSize,t.fontSize,n),_("Line height",e.lineHeight,t.lineHeight,n),_("Text color",e.color,t.color,n),_("Background",e.backgroundColor,t.color,n),_("Radius",e.borderRadius,t.radius,n,{allowComposite:!0}),n}function _(e,t,n,s,a={}){!n||n.length===0||!t||zt(t,n,a)||s.push(`${e} ${t} is outside configured tokens.`)}function zt(e,t,n={}){if(t.includes(e))return!0;if(!n.allowComposite)return!1;const s=e.trim().split(/\s+/);return s.length>1&&s.every(a=>t.includes(a))}function Ht(e){const t=e.id?`#${e.id}`:"",n=e.className?`.${e.className.split(/\s+/).filter(Boolean).slice(0,2).join(".")}`:"",s=e.ariaLabel?`[aria-label="${e.ariaLabel}"]`:"";return`${e.tagName}${t}${n}${s}`||e.tagName}function Ot(e,t){const n=[],s=(Math.max(e.left,t.left)+Math.min(e.right,t.right))/2,a=(Math.max(e.top,t.top)+Math.min(e.bottom,t.bottom))/2;if(e.right<=t.left||t.right<=e.left){const d=e.right<=t.left?e.right:t.right,h=e.right<=t.left?t.left:e.left;n.push({key:"horizontal",axis:"horizontal",top:Te(a,0,window.innerHeight),left:d,width:Math.max(h-d,1),height:1,label:`${Math.round(h-d)}px`})}if(e.bottom<=t.top||t.bottom<=e.top){const d=e.bottom<=t.top?e.bottom:t.bottom,h=e.bottom<=t.top?t.top:e.top;n.push({key:"vertical",axis:"vertical",top:d,left:Te(s,0,window.innerWidth),width:1,height:Math.max(h-d,1),label:`${Math.round(h-d)}px`})}return n}function Te(e,t,n){return Math.min(Math.max(e,t),n)}function J(e,t){const n=new Map;for(const s of e){const a=t(s);n.set(a,(n.get(a)??0)+1)}return Array.from(n.entries()).sort((s,a)=>a[1]-s[1]||s[0].localeCompare(a[0]))}function Kt(e){return e instanceof HTMLInputElement||e instanceof HTMLTextAreaElement||e instanceof HTMLSelectElement||e instanceof HTMLElement&&e.isContentEditable}function Jt(e,t){const n=$e(e),s=$e(t);return!n||!s||s.alpha===0?!1:qt(n,s)<4.5}function $e(e){const t=e.match(/rgba?\(([^)]+)\)/);if(!t)return null;const[n,s,a,d="1"]=t[1].split(",").map(h=>h.trim());return{red:Number(n),green:Number(s),blue:Number(a),alpha:Number(d)}}function qt(e,t){const n=Math.max(ee(e),ee(t)),s=Math.min(ee(e),ee(t));return(n+.05)/(s+.05)}function ee(e){const t=[e.red,e.green,e.blue].map(n=>{const s=n/255;return s<=.03928?s/12.92:((s+.055)/1.055)**2.4});return t[0]*.2126+t[1]*.7152+t[2]*.0722}function Gt(e){const t={top:I(e.cssSnapshot.marginTop),right:I(e.cssSnapshot.marginRight),bottom:I(e.cssSnapshot.marginBottom),left:I(e.cssSnapshot.marginLeft)},n={top:I(e.cssSnapshot.borderTopWidth),right:I(e.cssSnapshot.borderRightWidth),bottom:I(e.cssSnapshot.borderBottomWidth),left:I(e.cssSnapshot.borderLeftWidth)},s={top:I(e.cssSnapshot.paddingTop),right:I(e.cssSnapshot.paddingRight),bottom:I(e.cssSnapshot.paddingBottom),left:I(e.cssSnapshot.paddingLeft)},a={top:e.rect.top,left:e.rect.left,width:Math.max(e.rect.width,0),height:Math.max(e.rect.height,0)},d={top:a.top-t.top,left:a.left-t.left,width:a.width+t.left+t.right,height:a.height+t.top+t.bottom},h={top:a.top+n.top,left:a.left+n.left,width:Math.max(a.width-n.left-n.right,0),height:Math.max(a.height-n.top-n.bottom,0)},w={top:h.top+s.top,left:h.left+s.left,width:Math.max(h.width-s.left-s.right,0),height:Math.max(h.height-s.top-s.bottom,0)};return{margin:d,border:a,padding:h,content:w}}function I(e){const t=Number.parseFloat(e);return Number.isFinite(t)?t:0}L.ReviewLensLogo=xe,L.ReviewLensOverlay=Lt,L.ReviewLensProvider=ft,L.buildElementTarget=W,L.createGoogleSheetsAdapter=pe,L.normalizeReviewUrl=ve,L.useReviewLens=Se,Object.defineProperty(L,Symbol.toStringTag,{value:"Module"})}));
|
|
1
|
+
(function(L,n){typeof exports=="object"&&typeof module<"u"?n(exports,require("react/jsx-runtime"),require("react")):typeof define=="function"&&define.amd?define(["exports","react/jsx-runtime","react"],n):(L=typeof globalThis<"u"?globalThis:L||self,n(L.ReviewLensReact={},L.jsxRuntime,L.React))})(this,(function(L,n,h){"use strict";const ue=["https://www.googleapis.com/auth/spreadsheets","https://www.googleapis.com/auth/userinfo.email"],et="https://www.googleapis.com/auth/gmail.send",pe="https://www.googleapis.com/oauth2/v3/userinfo",tt="https://gmail.googleapis.com/gmail/v1/users/me/messages/send",rt="review-lens-google-token";function fe(e){const t=e.feedbackSheetName??"Feedback",r=e.messagesSheetName??"Messages",s=e.usersSheetName??"Users",a=e.enableEmailNotifications?[...ue,et].join(" "):ue.join(" "),l=pt(e.googleClientId,a);let u,m;async function g(){const f=ft(l);if(f)return f.accessToken;u??(u=ut(e.googleClientId,a).then(c=>(gt(l,c),c)));const v=await u;return Date.now()>=v.expiresAt?(u=void 0,g()):v.accessToken}async function b(f,v,c){const S=await g(),o=await fetch(`https://sheets.googleapis.com/v4/spreadsheets/${f}${v}`,{...c,headers:{Authorization:`Bearer ${S}`,"Content-Type":"application/json",...c==null?void 0:c.headers}});if(o.status===401){ye(l),u=void 0;const C=await g(),w=await fetch(`https://sheets.googleapis.com/v4/spreadsheets/${f}${v}`,{...c,headers:{Authorization:`Bearer ${C}`,"Content-Type":"application/json",...c==null?void 0:c.headers}});if(!w.ok)throw new Error(`Google Sheets request failed with ${w.status}`);return w.json()}if(!o.ok)throw new Error(`Google Sheets request failed with ${o.status}`);return o.json()}async function A(f,v){return(await b(f,`/values/${encodeURIComponent(v)}`)).values??[]}return{async getCurrentUser(){if(m||(m=await x()),!m)throw new Error("Google account did not return an email address");return{email:m}},async getPermissions(f){const[{email:v},c]=await Promise.all([this.getCurrentUser(),A(e.usersSpreadsheetId,s)]),S=ne(c),o=v.toLowerCase(),C=S.find(w=>{var y;return((y=w.email)==null?void 0:y.toLowerCase())===o&&w.active!=="false"&&(!w.projectKey||w.projectKey===f)});return at((C==null?void 0:C.role)??"designer")},async listFeedback(f){return ne(await A(e.contentSpreadsheetId,t)).map(ve).filter(c=>c!==null).filter(c=>c.projectKey===f.projectKey&&c.contentId===f.contentId&&c.normalizedPath===f.normalizedPath).sort((c,S)=>S.createdAt.localeCompare(c.createdAt))},async createFeedback(f){const v=new Date().toISOString(),c={...f,id:crypto.randomUUID(),attachments:[],createdAt:v,updatedAt:v};return await b(e.contentSpreadsheetId,`/values/${encodeURIComponent(t)}:append?valueInputOption=RAW`,{method:"POST",body:JSON.stringify({values:[we(c)]})}),c},async updateFeedback(f,v){const c=await A(e.contentSpreadsheetId,t),S=c[0]??ge,o=S.indexOf("id");if(o===-1)throw new Error(`Sheet ${t} is missing an id column`);const C=c.findIndex((B,U)=>U>0&&B[o]===f);if(C<1)throw new Error(`Feedback ${f} was not found`);const w=new Date().toISOString(),y=ve(me(S,c[C]));if(!y)throw new Error(`Feedback ${f} could not be parsed before updating`);const E={...y,...v,updatedAt:w},F=we(E);return await b(e.contentSpreadsheetId,`/values/${encodeURIComponent(t)}!A${C+1}:${ht(ge.length)}${C+1}?valueInputOption=RAW`,{method:"PUT",body:JSON.stringify({values:[F]})}),E},async listMessages(f){return ne(await A(e.contentSpreadsheetId,r)).map(it).filter(c=>c!==null).filter(c=>c.feedbackId===f).sort((c,S)=>c.createdAt.localeCompare(S.createdAt))},async createMessage(f){const v={...f,id:crypto.randomUUID(),createdAt:new Date().toISOString()};return await b(e.contentSpreadsheetId,`/values/${encodeURIComponent(r)}:append?valueInputOption=RAW`,{method:"POST",body:JSON.stringify({values:[st(v)]})}),v},async sendEmail(f){if(!e.enableEmailNotifications||f.to.length===0)return;const v=await g(),c=await this.getCurrentUser(),S=await fetch(tt,{method:"POST",headers:{Authorization:`Bearer ${v}`,"Content-Type":"application/json"},body:JSON.stringify({raw:mt({from:c.email,to:f.to,subject:f.subject,text:f.text})})});if(!S.ok)throw new Error(`Gmail send request failed with ${S.status}`)}};async function x(){const f=await fetch(pe,{headers:{Authorization:`Bearer ${await g()}`}});if(f.status===401){ye(l),u=void 0;const c=await fetch(pe,{headers:{Authorization:`Bearer ${await g()}`}});if(!c.ok)throw new Error(`Google userinfo request failed with ${c.status}`);return(await c.json()).email}if(!f.ok)throw new Error(`Google userinfo request failed with ${f.status}`);return(await f.json()).email}}const ge=["id","projectKey","contentId","normalizedPath","originalUrl","selector","selectorStrategy","elementFingerprintJson","createdCssSnapshotJson","comment","status","severity","category","assigneeEmail","viewportWidth","viewportHeight","viewportPreset","screenshotUrl","screenshotThumbnailUrl","attachmentJson","authorEmail","createdAt","updatedAt","fixedCssSnapshotJson","fixedAt","fixedBy","resolvedAt","resolvedBy"],nt=["id","feedbackId","body","authorEmail","createdAt"];function we(e){return[e.id,e.projectKey,e.contentId,e.normalizedPath,e.originalUrl,e.selector,e.selectorStrategy,JSON.stringify(e.elementFingerprint),JSON.stringify(e.createdCssSnapshot),e.comment,e.status,e.severity,e.category,e.assigneeEmail??"",String(e.viewportWidth),String(e.viewportHeight),e.viewportPreset,e.screenshotUrl??"",e.screenshotThumbnailUrl??"",JSON.stringify(e.attachments),e.authorEmail,e.createdAt,e.updatedAt,e.fixedCssSnapshot?JSON.stringify(e.fixedCssSnapshot):"",e.fixedAt??"",e.fixedBy??"",e.resolvedAt??"",e.resolvedBy??""]}function st(e){return nt.map(t=>e[t])}function ne(e){const[t,...r]=e;return t?r.map(s=>me(t,s)):[]}function me(e,t){return Object.fromEntries(e.map((r,s)=>[r,t[s]??""]))}function ve(e){return e.id?{id:e.id,projectKey:e.projectKey,contentId:e.contentId,normalizedPath:e.normalizedPath,originalUrl:e.originalUrl,selector:e.selector,selectorStrategy:e.selectorStrategy==="stable-attribute"?"stable-attribute":"css-path",elementFingerprint:se(e.elementFingerprintJson,{tagName:"",width:0,height:0}),createdCssSnapshot:be(e.createdCssSnapshotJson),fixedCssSnapshot:e.fixedCssSnapshotJson?be(e.fixedCssSnapshotJson):void 0,comment:e.comment,status:ot(e.status),severity:lt(e.severity),category:dt(e.category),assigneeEmail:e.assigneeEmail||void 0,viewportWidth:Number(e.viewportWidth)||0,viewportHeight:Number(e.viewportHeight)||0,viewportPreset:ct(e.viewportPreset),screenshotUrl:e.screenshotUrl||void 0,screenshotThumbnailUrl:e.screenshotThumbnailUrl||void 0,attachments:se(e.attachmentJson,[]),authorEmail:e.authorEmail,createdAt:e.createdAt,updatedAt:e.updatedAt,fixedAt:e.fixedAt||void 0,fixedBy:e.fixedBy||void 0,resolvedAt:e.resolvedAt||void 0,resolvedBy:e.resolvedBy||void 0}:null}function it(e){return!e.id||!e.feedbackId?null:{id:e.id,feedbackId:e.feedbackId,body:e.body,authorEmail:e.authorEmail,createdAt:e.createdAt}}function se(e,t){try{return e?JSON.parse(e):t}catch{return t}}function be(e){const t=se(e,{});return{margin:t.margin??"",marginTop:t.marginTop??"",marginRight:t.marginRight??"",marginBottom:t.marginBottom??"",marginLeft:t.marginLeft??"",padding:t.padding??"",paddingTop:t.paddingTop??"",paddingRight:t.paddingRight??"",paddingBottom:t.paddingBottom??"",paddingLeft:t.paddingLeft??"",border:t.border??"",borderTopWidth:t.borderTopWidth??"",borderRightWidth:t.borderRightWidth??"",borderBottomWidth:t.borderBottomWidth??"",borderLeftWidth:t.borderLeftWidth??"",fontFamily:t.fontFamily??"",fontSize:t.fontSize??"",lineHeight:t.lineHeight??"",color:t.color??"",backgroundColor:t.backgroundColor??"",borderRadius:t.borderRadius??"",width:t.width??0,height:t.height??0}}function at(e){return e==="admin"?["create","read","reply","update","assign"]:e==="developer"?["read","reply","update","assign"]:["create","read","reply"]}function ot(e){return e==="in_progress"||e==="needs_clarification"||e==="fixed"||e==="wontfix"||e==="resolved"?e:"open"}function lt(e){return e==="low"||e==="high"?e:"medium"}function dt(e){return e==="visual"||e==="copy"||e==="accessibility"||e==="responsive"?e:"bug"}function ct(e){return e==="mobile"||e==="tablet"||e==="desktop"?e:"custom"}function ht(e){let t=e,r="";for(;t>0;){const s=(t-1)%26;r=String.fromCharCode(65+s)+r,t=Math.floor((t-s)/26)}return r}async function ut(e,t){return await wt(),new Promise((r,s)=>{var l;const a=(l=window.google)==null?void 0:l.accounts.oauth2.initTokenClient({client_id:e,scope:t,callback:u=>{if(u.error||!u.access_token){s(new Error(u.error??"Google OAuth did not return an access token"));return}const m=u.expires_in??3600;r({accessToken:u.access_token,expiresAt:Date.now()+m*1e3})}});a==null||a.requestAccessToken({prompt:""})})}function pt(e,t){return`${rt}:${e}:${t}`}function ft(e){try{const t=window.localStorage.getItem(e);if(!t)return;const r=JSON.parse(t);if(typeof r.accessToken!="string"||typeof r.expiresAt!="number"||Date.now()>=r.expiresAt-6e4){window.localStorage.removeItem(e);return}return r}catch{return}}function gt(e,t){try{window.localStorage.setItem(e,JSON.stringify(t))}catch{}}function ye(e){try{window.localStorage.removeItem(e)}catch{}}function wt(){var e;return(e=window.google)!=null&&e.accounts.oauth2?Promise.resolve():new Promise((t,r)=>{const s=document.querySelector('script[src="https://accounts.google.com/gsi/client"]');if(s){s.addEventListener("load",()=>t(),{once:!0}),s.addEventListener("error",()=>r(new Error("Google Identity failed to load")),{once:!0});return}const a=document.createElement("script");a.src="https://accounts.google.com/gsi/client",a.async=!0,a.defer=!0,a.onload=()=>t(),a.onerror=()=>r(new Error("Google Identity failed to load")),document.head.append(a)})}function mt(e){const t=[`From: ${e.from}`,`To: ${e.to.join(", ")}`,`Subject: ${e.subject}`,"Content-Type: text/plain; charset=UTF-8","",e.text].join(`\r
|
|
2
|
+
`);return vt(t)}function vt(e){const t=new TextEncoder().encode(e);let r="";return t.forEach(s=>{r+=String.fromCharCode(s)}),btoa(r).replace(/\+/g,"-").replace(/\//g,"_").replace(/=+$/g,"")}function Se(e){return new URL(e,window.location.href).pathname.replace(/\/+$/,"")||"/"}const ke=h.createContext(null);function bt({config:e,children:t}){const r=h.useMemo(()=>e.adapter?e.adapter:fe({googleClientId:ie(e.googleClientId,"googleClientId"),contentSpreadsheetId:ie(e.contentSpreadsheetId,"contentSpreadsheetId"),usersSpreadsheetId:ie(e.usersSpreadsheetId,"usersSpreadsheetId"),feedbackSheetName:e.sheetName??"Feedback",enableEmailNotifications:Ce(e)}),[e.adapter,e.contentSpreadsheetId,e.emailNotifications,e.googleClientId,e.sheetName,e.usersSpreadsheetId]),s=e.currentUrl??window.location.href,a=(e.normalizeUrl??Se)(s),[l,u]=h.useState(),[m,g]=h.useState([]),[b,A]=h.useState([]),x=h.useCallback(async()=>{const w=await r.listFeedback({projectKey:e.projectKey,contentId:e.contentId,normalizedPath:a});A(w)},[r,e.contentId,e.projectKey,a]);h.useEffect(()=>{let w=!0;async function y(){const[E,F]=await Promise.all([r.getCurrentUser(),r.getPermissions(e.projectKey)]);w&&(u(E),g(F),await x())}return y(),()=>{w=!1}},[r,e.projectKey,x]);const f=h.useCallback(async w=>{const y=await r.createFeedback(w);return A(E=>[y,...E]),ae(e,r,{actorEmail:(l==null?void 0:l.email)??w.authorEmail,item:y,kind:"created"}),y},[r,e,l==null?void 0:l.email]),v=h.useCallback(async(w,y)=>{const E=b.find(B=>B.id===w),F=await r.updateFeedback(w,y);return A(B=>B.map(U=>U.id===w?F:U)),ae(e,r,{actorEmail:l==null?void 0:l.email,item:F,kind:yt(y),previousItem:E}),F},[r,e,l==null?void 0:l.email,b]),c=h.useCallback(w=>r.listMessages(w),[r]),S=h.useCallback(async w=>{const y=await r.createMessage(w),E=b.find(F=>F.id===w.feedbackId);return E&&ae(e,r,{actorEmail:w.authorEmail,item:E,kind:"reply",replyBody:w.body}),y},[r,e,b]),o=h.useCallback(async(w,y)=>{const E=e.uploadAttachment??r.uploadAttachment;if(!E)throw new Error("Review Lens attachment upload is not configured");return E(w,y)},[r,e]),C=h.useMemo(()=>({config:e,adapter:r,currentUser:l,permissions:m,feedback:b,normalizedPath:a,refreshFeedback:x,createFeedback:f,updateFeedback:v,listMessages:c,createMessage:S,uploadAttachment:o}),[r,e,f,l,b,a,m,x,v,c,S,o]);return n.jsx(ke.Provider,{value:C,children:t})}function Ee(){const e=h.useContext(ke);if(!e)throw new Error("useReviewLens must be used inside ReviewLensProvider");return e}function ie(e,t){if(!e)throw new Error(`review-lens-react requires config.${t} when no adapter is provided`);return e}function Ce(e){return typeof e.emailNotifications=="object"?e.emailNotifications.enabled!==!1:!!e.emailNotifications}function yt(e){return e.status==="resolved"?"resolved":e.status==="fixed"||e.fixedAt||e.fixedBy?"fixed":e.status?"status":"assigneeEmail"in e?"assigned":"updated"}async function ae(e,t,r){if(!Ce(e)||!t.sendEmail)return;const s=St(r);if(s.length!==0)try{await t.sendEmail({to:s,subject:kt(e,r),text:Et(r)})}catch(a){console.warn("Review Lens email notification failed",a)}}function St(e){var r;const t=new Set;return t.add(e.item.authorEmail),(r=e.previousItem)!=null&&r.assigneeEmail&&t.add(e.previousItem.assigneeEmail),e.item.assigneeEmail&&t.add(e.item.assigneeEmail),[...t].filter(s=>{var a;return s?s.toLowerCase()!==((a=e.actorEmail)==null?void 0:a.toLowerCase()):!1})}function kt(e,t){return`${(typeof e.emailNotifications=="object"?e.emailNotifications:{}).subjectPrefix??"Review Lens"}: ${Ne(t)}`}function Et(e){const t=["[Review Lens]",Ne(e),Ct(e),"",`Review: ${e.item.comment}`,`Status: ${xe(e.item.status)}`,`Author: ${e.item.authorEmail}`,`Assignee: ${e.item.assigneeEmail??"Unassigned"}`,`Link: ${Nt(e.item)}`];return e.replyBody&&t.splice(2,0,`Reply: ${e.replyBody}`,""),t.join(`
|
|
3
|
+
`)}function Ct(e){return e.actorEmail?`Sent by Review Lens on behalf of ${e.actorEmail}.`:"Sent by Review Lens on behalf of the signed-in Google user."}function Ne(e){return e.kind==="created"?"New review feedback":e.kind==="assigned"?`Review assignment changed to ${e.item.assigneeEmail??"unassigned"}`:e.kind==="status"?`Review status changed to ${xe(e.item.status)}`:e.kind==="fixed"?"Review marked fixed":e.kind==="resolved"?"Review resolved":e.kind==="reply"?"New review reply":"Review updated"}function Nt(e){try{const t=new URL(e.originalUrl);return t.searchParams.set("reviewLensFeedback",e.id),t.toString()}catch{return e.originalUrl}}function xe(e){return e.replace(/_/g," ")}const xt=["data-review-id","data-testid","data-test-id","aria-label","name"];function W(e){const t=e.getBoundingClientRect(),r=Lt(e);return{selector:r.selector,selectorStrategy:r.strategy,fingerprint:Ft(e,t),cssSnapshot:It(e,t),rect:t}}function Lt(e){for(const t of xt){const r=e.getAttribute(t);if(r)return{selector:`[${t}="${Le(r)}"]`,strategy:"stable-attribute"}}return e.id?{selector:`#${Le(e.id)}`,strategy:"stable-attribute"}:{selector:At(e),strategy:"css-path"}}function At(e){const t=[];let r=e;for(;r&&r.nodeType===Node.ELEMENT_NODE&&r!==document.body;){const s=r.parentElement,a=r.tagName.toLowerCase();if(!s){t.unshift(a);break}const l=r.tagName,u=Array.from(s.children).filter(g=>g.tagName===l),m=u.indexOf(r)+1;t.unshift(u.length>1?`${a}:nth-of-type(${m})`:a),r=s}return t.join(" > ")}function Ft(e,t){var r;return{tagName:e.tagName.toLowerCase(),id:e.id||void 0,className:e.getAttribute("class")||void 0,textSnippet:((r=e.textContent)==null?void 0:r.trim().slice(0,80))||void 0,ariaLabel:e.getAttribute("aria-label")||void 0,width:Math.round(t.width),height:Math.round(t.height)}}function It(e,t){const r=window.getComputedStyle(e);return{margin:oe(r.marginTop,r.marginRight,r.marginBottom,r.marginLeft),marginTop:r.marginTop,marginRight:r.marginRight,marginBottom:r.marginBottom,marginLeft:r.marginLeft,padding:oe(r.paddingTop,r.paddingRight,r.paddingBottom,r.paddingLeft),paddingTop:r.paddingTop,paddingRight:r.paddingRight,paddingBottom:r.paddingBottom,paddingLeft:r.paddingLeft,border:oe(r.borderTopWidth,r.borderRightWidth,r.borderBottomWidth,r.borderLeftWidth),borderTopWidth:r.borderTopWidth,borderRightWidth:r.borderRightWidth,borderBottomWidth:r.borderBottomWidth,borderLeftWidth:r.borderLeftWidth,fontFamily:r.fontFamily,fontSize:r.fontSize,lineHeight:r.lineHeight,color:r.color,backgroundColor:r.backgroundColor,borderRadius:r.borderRadius,width:Math.round(t.width),height:Math.round(t.height)}}function oe(e,t,r,s){return e===t&&t===r&&r===s?e:`${e} ${t} ${r} ${s}`}function Le(e){return typeof CSS<"u"&&typeof CSS.escape=="function"?CSS.escape(e):e.replace(/["\\]/g,"\\$&")}function Ae({className:e,title:t="Review Lens logo"}){return n.jsxs("svg",{className:e,role:"img","aria-label":t,viewBox:"0 0 40 40",fill:"none",xmlns:"http://www.w3.org/2000/svg",children:[n.jsx("rect",{x:"5",y:"5",width:"30",height:"30",rx:"9",fill:"#111827"}),n.jsx("path",{d:"M11.5 20C14.2 15.7 17.4 13.6 20 13.6C22.6 13.6 25.8 15.7 28.5 20C25.8 24.3 22.6 26.4 20 26.4C17.4 26.4 14.2 24.3 11.5 20Z",stroke:"#F8FAFC",strokeWidth:"2.4",strokeLinecap:"round",strokeLinejoin:"round"}),n.jsx("path",{d:"M24.7 24.7L31.5 31.5",stroke:"#22D3EE",strokeWidth:"3.6",strokeLinecap:"round"}),n.jsx("circle",{cx:"20",cy:"20",r:"4.6",fill:"#F8FAFC"}),n.jsx("circle",{cx:"20",cy:"20",r:"2.2",fill:"#2563EB"}),n.jsx("path",{d:"M14.2 11.6L17 11.6M11.6 14.2L11.6 17M28.4 14.2L28.4 17",stroke:"#A7F3D0",strokeWidth:"2",strokeLinecap:"round"})]})}const Tt=[{label:"Desktop",value:"desktop"},{label:"Tablet",value:"tablet"},{label:"Mobile",value:"mobile"}],Fe=["open","in_progress","needs_clarification","fixed","wontfix","resolved"],Ie=["low","medium","high"],Te=["bug","visual","copy","accessibility","responsive"],R={open:"Open",in_progress:"In progress",needs_clarification:"Needs clarification",fixed:"Fixed",wontfix:"Won't fix",resolved:"Resolved"},O={low:"Low",medium:"Medium",high:"High"},K={bug:"Bug",visual:"Visual",copy:"Copy",accessibility:"Accessibility",responsive:"Responsive"};function Mt({open:e,onOpenChange:t,placement:r="top-right",showResolved:s=!1,syncSelectionToUrl:a=!1,responsivePresets:l=Tt}){var Re;const{adapter:u,config:m,currentUser:g,feedback:b,normalizedPath:A,permissions:x,createFeedback:f,updateFeedback:v,listMessages:c,createMessage:S,uploadAttachment:o}=Ee(),[C,w]=h.useState(),[y,E]=h.useState(),[F,B]=h.useState(""),[U,Rt]=h.useState("medium"),[_e,er]=h.useState("visual"),[je,Ue]=h.useState(""),[De,tr]=h.useState(((Re=l[0])==null?void 0:Re.value)??"desktop"),[k,q]=h.useState(),[M,_]=h.useState("review"),[rr,We]=h.useState(!1),[V,ze]=h.useState("all"),[Y,He]=h.useState("all"),[X,Oe]=h.useState("all"),[Q,Ke]=h.useState("all"),[Z,Je]=h.useState("all"),[nr,sr]=h.useState(!1),[ir,Ge]=h.useState({}),[le,de]=h.useState(""),te=h.useRef(null),qe=h.useRef(e),ce=h.useRef(a?new URL(window.location.href).searchParams.get("reviewLensFeedback"):null),$=!!g,P=x.includes("create"),Ve=x.includes("reply"),Ye=x.includes("update"),ar=x.includes("assign"),D=C??y,or=!!y,lr=!!(m.captureScreenshot&&(m.uploadAttachment||u.uploadAttachment)),dr=h.useMemo(()=>{const i=b.map(p=>p.assigneeEmail).filter(p=>!!p);return g!=null&&g.email&&i.push(g.email),Array.from(new Set(i)).sort((p,d)=>p.localeCompare(d))},[g==null?void 0:g.email,b]),T=h.useMemo(()=>b.filter(i=>s||i.status!=="resolved").filter(i=>V==="all"||i.status===V).filter(i=>Y==="all"||i.severity===Y).filter(i=>X==="all"||i.category===X).filter(i=>Q==="all"||i.assigneeEmail===Q).filter(i=>Z==="all"||i.viewportPreset===Z),[Q,X,b,Y,s,V,Z]),cr=[V,Y,X,Q,Z].filter(i=>i!=="all").length;h.useEffect(()=>{if(e){qe.current=!0;return}if(w(void 0),E(void 0),B(""),de(""),_("review"),a&&qe.current){const i=new URL(window.location.href);i.searchParams.has("reviewLensFeedback")&&(i.searchParams.delete("reviewLensFeedback"),window.history.replaceState({},"",i))}},[e,a]),h.useEffect(()=>{$||(w(void 0),E(void 0))},[$]),h.useEffect(()=>{!y||M!=="review"||window.requestAnimationFrame(()=>{var i,p,d;(p=(i=te.current)==null?void 0:i.scrollIntoView)==null||p.call(i,{block:"nearest"}),(d=te.current)==null||d.focus()})},[y,M]),h.useEffect(()=>{if(!k)return;let i=!0;return c(k.id).then(p=>{i&&Ge(d=>({...d,[k.id]:p}))}),()=>{i=!1}},[c,k]),h.useEffect(()=>{if(!a||!ce.current||b.length===0)return;const i=b.find(p=>p.id===ce.current);i&&(ce.current=null,t==null||t(!0),H(i,{syncUrl:!1}))},[b,a]),h.useEffect(()=>{if(!e||!a||k||b.length===0)return;const i=new URL(window.location.href).searchParams.get("reviewLensFeedback"),p=b.find(d=>d.id===i);p&&H(p,{syncUrl:!1})},[b,e,k,a]),h.useEffect(()=>{if(!e)return;function i(d){var N;if(d.key==="Shift"&&We(!0),d.key==="Escape"){d.preventDefault(),t==null||t(!1);return}Yt(d.target)||((d.key==="n"||d.key==="ArrowDown")&&(d.preventDefault(),Xe(1)),(d.key==="p"||d.key==="ArrowUp")&&(d.preventDefault(),Xe(-1)),d.key==="c"&&(d.preventDefault(),_("review"),(N=te.current)==null||N.focus()),d.key==="f"&&k&&Ye&&(d.preventDefault(),Ze(k)))}function p(d){d.key==="Shift"&&We(!1)}return window.addEventListener("keydown",i),window.addEventListener("keyup",p),()=>{window.removeEventListener("keydown",i),window.removeEventListener("keyup",p)}});const he=h.useCallback(i=>{const p=i.target instanceof Element?i.target:null;if(p)return p.closest("[data-review-lens-ui]")?null:p;const d=document.elementFromPoint(i.clientX,i.clientY);return!d||d.closest("[data-review-lens-ui]")?null:d},[]);if(h.useEffect(()=>{if(!e||!$)return;function i(d){const N=he(d);w(N?W(N):void 0)}function p(d){const N=he(d);N&&(d.preventDefault(),d.stopPropagation(),E(W(N)),_("review"))}return window.addEventListener("mousemove",i,!0),window.addEventListener("click",p,!0),()=>{window.removeEventListener("mousemove",i,!0),window.removeEventListener("click",p,!0)}},[$,he,e]),!e)return null;function H(i,p={syncUrl:!0}){var N;if(q(i),E(void 0),_("feedback"),a&&p.syncUrl!==!1){const re=new URL(window.location.href);re.searchParams.set("reviewLensFeedback",i.id),window.history.replaceState({},"",re)}const d=z(i.selector);if(!d){w(void 0);return}(N=d.scrollIntoView)==null||N.call(d,{behavior:"smooth",block:"center",inline:"center"}),window.requestAnimationFrame(()=>{w(W(d))})}function Xe(i){if(T.length===0)return;const p=k?T.findIndex(N=>N.id===k.id):-1,d=p<0?i>0?0:T.length-1:(p+i+T.length)%T.length;H(T[d])}async function Qe(){if(!y||!F.trim()||!g||!P)return;let i=await f({projectKey:m.projectKey,contentId:m.contentId,normalizedPath:A,originalUrl:m.currentUrl??window.location.href,selector:y.selector,selectorStrategy:y.selectorStrategy,elementFingerprint:y.fingerprint,createdCssSnapshot:y.cssSnapshot,comment:F.trim(),status:"open",severity:U,category:_e,assigneeEmail:je.trim()||void 0,viewportWidth:window.innerWidth,viewportHeight:window.innerHeight,viewportPreset:De,screenshotUrl:void 0,screenshotThumbnailUrl:void 0,authorEmail:g.email});if(m.captureScreenshot)try{const p=await m.captureScreenshot(y),d=await o(i.id,{type:"screenshot",data:p,createdBy:g.email});i=await v(i.id,{attachments:[d],screenshotUrl:d.url,screenshotThumbnailUrl:d.thumbnailUrl})}catch{}if(B(""),Ue(""),E(void 0),w(void 0),_("feedback"),q(i),a){const p=new URL(window.location.href);p.searchParams.set("reviewLensFeedback",i.id),window.history.replaceState({},"",p)}}async function hr(i,p){const d=new Date().toISOString(),N=p==="resolved"?{status:p,resolvedAt:d,resolvedBy:g==null?void 0:g.email}:{status:p},re=await v(i.id,N);q(re)}async function Ze(i){const p=z(i.selector);if(!p||!g)return;const d=W(p),N=await v(i.id,{status:"fixed",fixedCssSnapshot:d.cssSnapshot,fixedAt:new Date().toISOString(),fixedBy:g.email});q(N)}async function ur(i){if(!le.trim()||!g||!Ve)return;const p=await S({feedbackId:i.id,body:le.trim(),authorEmail:g.email});Ge(d=>({...d,[i.id]:[...d[i.id]??[],p]})),de("")}return n.jsxs("div",{className:"review-lens-root","data-review-lens-ui":!0,children:[$&&D?n.jsx(Ut,{target:D,locked:!!y}):null,$&&y&&C&&rr?n.jsx(Dt,{from:y,to:C}):null,$?n.jsxs(n.Fragment,{children:[n.jsx(Wt,{feedback:T,selectedFeedback:k,onSelect:H}),n.jsx(Ht,{feedback:T,selectedFeedback:k,onSelect:H})]}):null,n.jsxs("aside",{className:`review-lens-panel review-lens-panel--${r}`,"data-review-lens-ui":!0,children:[n.jsxs("header",{className:"review-lens-panel__header",children:[n.jsxs("div",{className:"review-lens-brand",children:[n.jsx(Ae,{className:"review-lens-brand__mark"}),n.jsxs("div",{children:[n.jsx("p",{className:"review-lens-kicker",children:"Review Lens"}),n.jsx("h2",{children:M==="summary"?"Summary":M==="feedback"?"Feedback":y?"Element locked":"Inspecting"})]})]}),n.jsx("button",{type:"button",onClick:()=>t==null?void 0:t(!1),children:"Close"})]}),n.jsxs("div",{className:"review-lens-panel__body",children:[n.jsxs("div",{className:"review-lens-mode-switch",role:"tablist","aria-label":"Review Lens mode",children:[n.jsx("button",{type:"button",role:"tab","aria-selected":M==="review",onClick:()=>_("review"),children:"Review"}),n.jsxs("button",{type:"button",role:"tab","aria-selected":M==="feedback",onClick:()=>_("feedback"),children:["Feedback ",n.jsx("span",{children:T.length})]}),n.jsx("button",{type:"button",role:"tab","aria-selected":M==="summary",onClick:()=>_("summary"),children:"Summary"})]}),M==="review"?n.jsxs("div",{className:"review-lens-review-pane",role:"tabpanel",children:[n.jsxs("div",{className:"review-lens-inspection",children:[$?null:n.jsx("p",{children:"Authenticate with Google to inspect this page."}),$&&D?n.jsxs(n.Fragment,{children:[n.jsx(Ot,{target:D}),n.jsx(Me,{title:"Accessibility",items:Kt(D)}),n.jsx(Me,{title:"Design tokens",items:Jt(D.cssSnapshot,m.designTokens)})]}):null,$&&!D?n.jsx("p",{children:"Move over the app to inspect."}):null]}),or?n.jsx("div",{className:"review-lens-composer-panel",children:n.jsxs("form",{className:"review-lens-feedback-form",onSubmit:i=>{i.preventDefault(),Qe()},children:[n.jsx("label",{htmlFor:"review-lens-comment",children:"New feedback"}),n.jsx("textarea",{ref:te,id:"review-lens-comment",value:F,disabled:!P,onChange:i=>B(i.target.value),onKeyDown:i=>{i.key==="Enter"&&i.metaKey&&(i.preventDefault(),Qe())},placeholder:P?"Describe the UX issue...":"You do not have permission to comment."}),n.jsxs("div",{className:"review-lens-form-grid",children:[n.jsxs("label",{children:["Severity",n.jsx("select",{value:U,onChange:i=>Rt(i.target.value),disabled:!P,children:Ie.map(i=>n.jsx("option",{value:i,children:O[i]},i))})]}),n.jsxs("label",{children:["Type",n.jsx("select",{value:_e,onChange:i=>er(i.target.value),disabled:!P,children:Te.map(i=>n.jsx("option",{value:i,children:K[i]},i))})]}),n.jsxs("label",{children:["Assignee",n.jsx("input",{value:je,onChange:i=>Ue(i.target.value),disabled:!P,placeholder:"optional@email.com"})]}),n.jsxs("label",{children:["Viewport",n.jsx("select",{value:De,onChange:i=>tr(i.target.value),disabled:!P,children:l.map(i=>n.jsx("option",{value:i.value,children:i.label},i.value))})]})]}),P?n.jsxs("p",{className:"review-lens-feedback-form__hint",children:["Press ",n.jsx("kbd",{children:"Command"})," + ",n.jsx("kbd",{children:"Enter"})," to submit.",lr?" Screenshot capture runs after save.":""]}):null,n.jsx("div",{className:"review-lens-actions",children:n.jsx("button",{type:"submit",disabled:!F.trim()||!P,children:"Save feedback"})})]})}):null]}):null,M==="feedback"?n.jsxs("div",{className:"review-lens-comments",children:[n.jsx($t,{open:nr,activeCount:cr,statusFilter:V,severityFilter:Y,categoryFilter:X,assigneeFilter:Q,viewportFilter:Z,assignees:dr,responsivePresets:l,onStatusChange:ze,onSeverityChange:He,onCategoryChange:Oe,onAssigneeChange:Ke,onViewportChange:Je,onToggle:()=>sr(i=>!i),onClear:()=>{ze("all"),He("all"),Oe("all"),Ke("all"),Je("all")}}),n.jsxs("div",{className:"review-lens-list-panel",children:[n.jsxs("div",{className:"review-lens-comments__header",children:[n.jsx("h3",{children:"All feedback"}),n.jsx("span",{children:T.length})]}),n.jsxs("div",{className:"review-lens-comments__list",children:[T.length===0?n.jsx("p",{children:"No feedback for this view."}):null,T.map(i=>n.jsx(Bt,{item:i,selected:(k==null?void 0:k.id)===i.id,onSelect:H},i.id))]})]}),k?n.jsxs("div",{className:"review-lens-selected-panel",children:[n.jsx("div",{className:"review-lens-selected-panel__label",children:"Selected feedback"}),n.jsx(Pt,{item:k,messages:ir[k.id]??[],messageDraft:le,canReply:Ve,canUpdate:Ye,canAssign:ar,syncSelectionToUrl:a,onMessageDraftChange:de,onSubmitMessage:()=>void ur(k),onStatusChange:i=>void hr(k,i),onAssigneeChange:i=>void v(k.id,{assigneeEmail:i.trim()||void 0}).then(q),onMarkFixed:()=>void Ze(k)},k.id)]}):n.jsxs("div",{className:"review-lens-selected-panel review-lens-selected-panel--empty",children:[n.jsx("div",{className:"review-lens-selected-panel__label",children:"Selected feedback"}),n.jsx("p",{children:"Select a feedback item above to review status, assignment, drift, and replies."})]})]}):null,M==="summary"?n.jsx(jt,{feedback:b}):null]})]})]})}function $t({open:e,activeCount:t,statusFilter:r,severityFilter:s,categoryFilter:a,assigneeFilter:l,viewportFilter:u,assignees:m,responsivePresets:g,onStatusChange:b,onSeverityChange:A,onCategoryChange:x,onAssigneeChange:f,onViewportChange:v,onToggle:c,onClear:S}){return n.jsxs("div",{className:"review-lens-filter-shell",children:[n.jsxs("div",{className:"review-lens-filter-bar",children:[n.jsxs("button",{type:"button","aria-expanded":e,onClick:c,children:["Filters",t>0?n.jsx("span",{children:t}):null]}),t>0?n.jsx("button",{type:"button",onClick:S,children:"Clear"}):null]}),e?n.jsxs("div",{className:"review-lens-filters",children:[n.jsxs("label",{children:["Status",n.jsxs("select",{"aria-label":"Filter status",value:r,onChange:o=>b(o.target.value),children:[n.jsx("option",{value:"all",children:"All statuses"}),Fe.map(o=>n.jsx("option",{value:o,children:R[o]},o))]})]}),n.jsxs("label",{children:["Priority",n.jsxs("select",{"aria-label":"Filter severity",value:s,onChange:o=>A(o.target.value),children:[n.jsx("option",{value:"all",children:"All priorities"}),Ie.map(o=>n.jsx("option",{value:o,children:O[o]},o))]})]}),n.jsxs("label",{children:["Type",n.jsxs("select",{"aria-label":"Filter type",value:a,onChange:o=>x(o.target.value),children:[n.jsx("option",{value:"all",children:"All types"}),Te.map(o=>n.jsx("option",{value:o,children:K[o]},o))]})]}),n.jsxs("label",{children:["Assignee",n.jsxs("select",{"aria-label":"Filter assignee",value:l,onChange:o=>f(o.target.value),children:[n.jsx("option",{value:"all",children:"All assignees"}),m.map(o=>n.jsx("option",{value:o,children:o},o))]})]}),n.jsxs("label",{children:["Viewport",n.jsxs("select",{"aria-label":"Filter viewport",value:u,onChange:o=>v(o.target.value),children:[n.jsx("option",{value:"all",children:"All viewports"}),g.map(o=>n.jsx("option",{value:o.value,children:o.label},o.value))]})]})]}):null]})}function Bt({item:e,selected:t,onSelect:r}){const s=$e(e);return n.jsxs("article",{tabIndex:0,className:["review-lens-comment",`review-lens-comment--${e.severity}`,t?"review-lens-comment--selected":""].filter(Boolean).join(" "),onClick:()=>r(e),onKeyDown:a=>{(a.key==="Enter"||a.key===" ")&&(a.preventDefault(),r(e))},children:[n.jsxs("div",{className:"review-lens-comment__header",children:[n.jsx("span",{children:R[e.status]}),n.jsx("strong",{children:O[e.severity]})]}),n.jsxs("div",{className:"review-lens-comment__content",children:[n.jsx("p",{children:e.comment}),n.jsxs("span",{children:[e.authorEmail,e.assigneeEmail?` -> ${e.assigneeEmail}`:""]})]}),n.jsxs("div",{className:"review-lens-tags",children:[n.jsx("span",{children:K[e.category]}),n.jsx("span",{children:e.viewportPreset}),n.jsx("span",{children:s.label})]})]})}function Pt({item:e,messages:t,messageDraft:r,canReply:s,canUpdate:a,canAssign:l,syncSelectionToUrl:u,onMessageDraftChange:m,onSubmitMessage:g,onStatusChange:b,onAssigneeChange:A,onMarkFixed:x}){const[f,v]=h.useState(!1),c=$e(e);function S(){const o=new URL(window.location.href);o.searchParams.set("reviewLensFeedback",e.id),_t(o.toString()).then(C=>{C&&(v(!0),setTimeout(()=>v(!1),2e3))})}return n.jsxs("section",{className:"review-lens-detail","aria-label":"Selected feedback detail",children:[n.jsxs("div",{className:"review-lens-detail__header",children:[n.jsxs("h3",{children:[K[e.category]," feedback"]}),n.jsxs("div",{className:"review-lens-detail__header-actions",children:[u?n.jsx("button",{type:"button",className:"review-lens-copy-link",onClick:S,"aria-label":"Copy link to this feedback",children:f?"Copied!":"Copy link"}):null,n.jsx("strong",{children:O[e.severity]})]})]}),n.jsx("blockquote",{children:e.comment}),n.jsxs("dl",{className:"review-lens-detail-meta",children:[n.jsxs("div",{children:[n.jsx("dt",{children:"Target"}),n.jsx("dd",{children:c.label})]}),n.jsxs("div",{children:[n.jsx("dt",{children:"Viewport"}),n.jsx("dd",{children:e.viewportPreset})]}),e.screenshotUrl?n.jsxs("div",{children:[n.jsx("dt",{children:"Evidence"}),n.jsx("dd",{children:n.jsx("a",{href:e.screenshotUrl,target:"_blank",rel:"noreferrer",children:"Screenshot"})})]}):null]}),n.jsxs("div",{className:"review-lens-form-grid",children:[n.jsxs("label",{children:["Status",n.jsx("select",{value:e.status,disabled:!a,onChange:o=>b(o.target.value),children:Fe.map(o=>n.jsx("option",{value:o,children:R[o]},o))})]}),n.jsxs("label",{children:["Assignee",n.jsx("input",{defaultValue:e.assigneeEmail??"",disabled:!l,onBlur:o=>A(o.target.value),placeholder:"optional@email.com"})]})]}),n.jsxs("div",{className:"review-lens-status-actions",children:[n.jsx("button",{type:"button",className:"review-lens-button-secondary",disabled:!a,onClick:x,children:"Mark fixed"}),n.jsx("button",{type:"button",className:"review-lens-button-primary",disabled:!a,onClick:()=>b("resolved"),children:"Resolve"})]}),n.jsxs("div",{className:"review-lens-thread",children:[n.jsxs("div",{className:"review-lens-thread__header",children:[n.jsx("h3",{children:"Thread"}),n.jsx("span",{children:t.length})]}),t.length===0?n.jsx("p",{children:"No replies yet."}):null,t.map(o=>n.jsxs("div",{className:"review-lens-thread__message",children:[n.jsx("p",{children:o.body}),n.jsx("span",{children:o.authorEmail})]},o.id)),n.jsx("textarea",{"aria-label":"Reply",value:r,disabled:!s,onChange:o=>m(o.target.value),placeholder:s?"Reply...":"You do not have permission to reply."}),n.jsx("div",{className:"review-lens-actions",children:n.jsx("button",{type:"button",disabled:!r.trim()||!s,onClick:g,children:"Reply"})})]})]})}async function _t(e){var r;if((r=navigator.clipboard)!=null&&r.writeText)return await navigator.clipboard.writeText(e),!0;const t=document.createElement("textarea");t.value=e,t.setAttribute("readonly",""),t.style.position="fixed",t.style.opacity="0",document.body.append(t),t.select();try{return document.execCommand("copy")}finally{t.remove()}}function jt({feedback:e}){return n.jsxs("div",{className:"review-lens-summary",role:"tabpanel",children:[n.jsx(J,{title:"Status",values:G(e,t=>R[t.status])}),n.jsx(J,{title:"Severity",values:G(e,t=>O[t.severity])}),n.jsx(J,{title:"Type",values:G(e,t=>K[t.category])}),n.jsx(J,{title:"Assignee",values:G(e,t=>t.assigneeEmail??"Unassigned")}),n.jsx(J,{title:"Viewport",values:G(e,t=>t.viewportPreset)})]})}function J({title:e,values:t}){return n.jsxs("section",{children:[n.jsx("h3",{children:e}),n.jsx("dl",{children:t.map(([r,s])=>n.jsxs("div",{children:[n.jsx("dt",{children:r}),n.jsx("dd",{children:s})]},r))})]})}function Ut({target:e,locked:t}){const r=Zt(e),s=qt(e.fingerprint);return n.jsxs("div",{className:t?"review-lens-highlight review-lens-highlight--locked":"review-lens-highlight",style:{top:r.margin.top,left:r.margin.left,width:r.margin.width,height:r.margin.height},children:[n.jsx("div",{className:"review-lens-highlight__border",style:{top:r.border.top-r.margin.top,left:r.border.left-r.margin.left,width:r.border.width,height:r.border.height}}),n.jsx("div",{className:"review-lens-highlight__padding",style:{top:r.padding.top-r.margin.top,left:r.padding.left-r.margin.left,width:r.padding.width,height:r.padding.height}}),n.jsx("div",{className:"review-lens-highlight__content",style:{top:r.content.top-r.margin.top,left:r.content.left-r.margin.left,width:r.content.width,height:r.content.height}}),n.jsxs("div",{className:"review-lens-highlight__label",children:[n.jsx("strong",{children:s}),n.jsxs("span",{children:[Math.round(e.rect.width)," x ",Math.round(e.rect.height)]})]})]})}function Dt({from:e,to:t}){const r=Vt(e.rect,t.rect);return r.length===0?null:n.jsx(n.Fragment,{children:r.map(s=>n.jsx("div",{className:`review-lens-distance review-lens-distance--${s.axis}`,style:{top:s.top,left:s.left,width:s.width,height:s.height},children:n.jsx("span",{children:s.label})},s.key))})}function Wt({feedback:e,selectedFeedback:t,onSelect:r}){return n.jsx(n.Fragment,{children:e.map(s=>n.jsx(zt,{feedback:s,selected:(t==null?void 0:t.id)===s.id,onSelect:r},s.id))})}function zt({feedback:e,selected:t,onSelect:r}){const s=h.useRef(null);return h.useLayoutEffect(()=>{let a=0;const l=()=>{a=0;const m=s.current,g=z(e.selector),b=g==null?void 0:g.getBoundingClientRect();!m||!b||(m.style.top=`${b.top}px`,m.style.left=`${b.right}px`,m.hidden=b.bottom<0||b.top>window.innerHeight)},u=()=>{a||(a=window.requestAnimationFrame(l))};return l(),window.addEventListener("scroll",u,!0),window.addEventListener("resize",u),()=>{a&&window.cancelAnimationFrame(a),window.removeEventListener("scroll",u,!0),window.removeEventListener("resize",u)}},[e.selector]),n.jsx("button",{ref:s,type:"button",className:t?"review-lens-marker review-lens-marker--selected":"review-lens-marker",onClick:()=>r(e),"aria-label":`Open feedback from ${e.authorEmail}`})}function Ht({feedback:e,selectedFeedback:t,onSelect:r}){const s=e.map(a=>{const l=z(a.selector),u=l==null?void 0:l.getBoundingClientRect(),m=Math.max(document.documentElement.scrollHeight,document.body.scrollHeight,window.innerHeight);return!u||m<=0?null:{item:a,top:Math.min(100,Math.max(0,(u.top+window.scrollY)/m*100))}}).filter(a=>a!==null);return s.length===0?null:n.jsx("div",{className:"review-lens-minimap","data-review-lens-ui":!0,"aria-label":"Feedback map",children:s.map(a=>n.jsx("button",{type:"button",className:(t==null?void 0:t.id)===a.item.id?"review-lens-minimap__point review-lens-minimap__point--selected":"review-lens-minimap__point",style:{top:`${a.top}%`},onClick:()=>r(a.item),"aria-label":`Jump to feedback from ${a.item.authorEmail}`},a.item.id))})}function Ot({target:e}){const t=[["Selector",e.selector],["Size",`${e.cssSnapshot.width} x ${e.cssSnapshot.height}`],["Margin",e.cssSnapshot.margin],["Padding",e.cssSnapshot.padding],["Border",e.cssSnapshot.border],["Radius",e.cssSnapshot.borderRadius],["Font",`${e.cssSnapshot.fontSize} / ${e.cssSnapshot.lineHeight}`],["Family",e.cssSnapshot.fontFamily],["Color",e.cssSnapshot.color],["Background",e.cssSnapshot.backgroundColor]];return n.jsx("dl",{className:"review-lens-metrics",children:t.map(([r,s])=>n.jsxs("div",{children:[n.jsx("dt",{children:r}),n.jsx("dd",{children:s})]},r))})}function Me({title:e,items:t}){return n.jsxs("section",{className:"review-lens-insights",children:[n.jsx("h3",{children:e}),t.length===0?n.jsx("p",{children:"No issues detected."}):null,t.length>0?n.jsx("ul",{children:t.map(r=>n.jsx("li",{children:r},r))}):null]})}function z(e){try{return document.querySelector(e)}catch{return null}}function $e(e){const t=z(e.selector);if(!t)return{label:"Target missing",level:"warning"};const r=W(t);return r.fingerprint.tagName!==e.elementFingerprint.tagName?{label:"Element changed",level:"warning"}:Math.abs(r.fingerprint.width-e.elementFingerprint.width)>2||Math.abs(r.fingerprint.height-e.elementFingerprint.height)>2?{label:"Size changed",level:"warning"}:r.cssSnapshot.fontSize!==e.createdCssSnapshot.fontSize||r.cssSnapshot.color!==e.createdCssSnapshot.color||r.cssSnapshot.padding!==e.createdCssSnapshot.padding?{label:"Style changed",level:"warning"}:{label:"Target unchanged",level:"ok"}}function Kt(e){var g;const t=z(e.selector);if(!t)return["Selected element is no longer available."];const r=[],s=t.tagName.toLowerCase(),a=t.getAttribute("role"),l=["button","a","input","select","textarea"].includes(s)||a==="button"||a==="link",u=t.getAttribute("aria-label")||t.getAttribute("title")||((g=t.textContent)==null?void 0:g.trim());l&&!u&&r.push("Interactive element has no accessible name."),l&&(e.rect.width<44||e.rect.height<44)&&r.push("Tap target is smaller than 44 x 44."),s==="img"&&!t.getAttribute("alt")&&r.push("Image is missing alt text.");const m=/^h[1-6]$/.test(s)?Number(s.slice(1)):0;return m>1&&!document.querySelector(`h${m-1}`)&&r.push("Heading may skip the previous level."),Xt(e.cssSnapshot.color,e.cssSnapshot.backgroundColor)&&r.push("Text contrast may be low."),r}function Jt(e,t={}){const r=[];return j("Padding",e.padding,t.spacing,r,{allowComposite:!0}),j("Margin",e.margin,t.spacing,r,{allowComposite:!0}),j("Font size",e.fontSize,t.fontSize,r),j("Line height",e.lineHeight,t.lineHeight,r),j("Text color",e.color,t.color,r),j("Background",e.backgroundColor,t.color,r),j("Radius",e.borderRadius,t.radius,r,{allowComposite:!0}),r}function j(e,t,r,s,a={}){!r||r.length===0||!t||Gt(t,r,a)||s.push(`${e} ${t} is outside configured tokens.`)}function Gt(e,t,r={}){if(t.includes(e))return!0;if(!r.allowComposite)return!1;const s=e.trim().split(/\s+/);return s.length>1&&s.every(a=>t.includes(a))}function qt(e){const t=e.id?`#${e.id}`:"",r=e.className?`.${e.className.split(/\s+/).filter(Boolean).slice(0,2).join(".")}`:"",s=e.ariaLabel?`[aria-label="${e.ariaLabel}"]`:"";return`${e.tagName}${t}${r}${s}`||e.tagName}function Vt(e,t){const r=[],s=(Math.max(e.left,t.left)+Math.min(e.right,t.right))/2,a=(Math.max(e.top,t.top)+Math.min(e.bottom,t.bottom))/2;if(e.right<=t.left||t.right<=e.left){const l=e.right<=t.left?e.right:t.right,u=e.right<=t.left?t.left:e.left;r.push({key:"horizontal",axis:"horizontal",top:Be(a,0,window.innerHeight),left:l,width:Math.max(u-l,1),height:1,label:`${Math.round(u-l)}px`})}if(e.bottom<=t.top||t.bottom<=e.top){const l=e.bottom<=t.top?e.bottom:t.bottom,u=e.bottom<=t.top?t.top:e.top;r.push({key:"vertical",axis:"vertical",top:l,left:Be(s,0,window.innerWidth),width:1,height:Math.max(u-l,1),label:`${Math.round(u-l)}px`})}return r}function Be(e,t,r){return Math.min(Math.max(e,t),r)}function G(e,t){const r=new Map;for(const s of e){const a=t(s);r.set(a,(r.get(a)??0)+1)}return Array.from(r.entries()).sort((s,a)=>a[1]-s[1]||s[0].localeCompare(a[0]))}function Yt(e){return e instanceof HTMLInputElement||e instanceof HTMLTextAreaElement||e instanceof HTMLSelectElement||e instanceof HTMLElement&&e.isContentEditable}function Xt(e,t){const r=Pe(e),s=Pe(t);return!r||!s||s.alpha===0?!1:Qt(r,s)<4.5}function Pe(e){const t=e.match(/rgba?\(([^)]+)\)/);if(!t)return null;const[r,s,a,l="1"]=t[1].split(",").map(u=>u.trim());return{red:Number(r),green:Number(s),blue:Number(a),alpha:Number(l)}}function Qt(e,t){const r=Math.max(ee(e),ee(t)),s=Math.min(ee(e),ee(t));return(r+.05)/(s+.05)}function ee(e){const t=[e.red,e.green,e.blue].map(r=>{const s=r/255;return s<=.03928?s/12.92:((s+.055)/1.055)**2.4});return t[0]*.2126+t[1]*.7152+t[2]*.0722}function Zt(e){const t={top:I(e.cssSnapshot.marginTop),right:I(e.cssSnapshot.marginRight),bottom:I(e.cssSnapshot.marginBottom),left:I(e.cssSnapshot.marginLeft)},r={top:I(e.cssSnapshot.borderTopWidth),right:I(e.cssSnapshot.borderRightWidth),bottom:I(e.cssSnapshot.borderBottomWidth),left:I(e.cssSnapshot.borderLeftWidth)},s={top:I(e.cssSnapshot.paddingTop),right:I(e.cssSnapshot.paddingRight),bottom:I(e.cssSnapshot.paddingBottom),left:I(e.cssSnapshot.paddingLeft)},a={top:e.rect.top,left:e.rect.left,width:Math.max(e.rect.width,0),height:Math.max(e.rect.height,0)},l={top:a.top-t.top,left:a.left-t.left,width:a.width+t.left+t.right,height:a.height+t.top+t.bottom},u={top:a.top+r.top,left:a.left+r.left,width:Math.max(a.width-r.left-r.right,0),height:Math.max(a.height-r.top-r.bottom,0)},m={top:u.top+s.top,left:u.left+s.left,width:Math.max(u.width-s.left-s.right,0),height:Math.max(u.height-s.top-s.bottom,0)};return{margin:l,border:a,padding:u,content:m}}function I(e){const t=Number.parseFloat(e);return Number.isFinite(t)?t:0}L.ReviewLensLogo=Ae,L.ReviewLensOverlay=Mt,L.ReviewLensProvider=bt,L.buildElementTarget=W,L.createGoogleSheetsAdapter=fe,L.normalizeReviewUrl=Se,L.useReviewLens=Ee,Object.defineProperty(L,Symbol.toStringTag,{value:"Module"})}));
|