@snagset/server 0.0.4 → 0.1.0

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.
Files changed (135) hide show
  1. package/README.md +4 -3
  2. package/dist/app.js +82 -9
  3. package/dist/app.js.map +1 -1
  4. package/dist/bin.js +46 -9
  5. package/dist/bin.js.map +1 -1
  6. package/dist/boot.js +67 -51
  7. package/dist/boot.js.map +1 -1
  8. package/dist/config.generated.js +5 -2
  9. package/dist/config.generated.js.map +1 -1
  10. package/dist/db/connect.js +7 -0
  11. package/dist/db/connect.js.map +1 -1
  12. package/dist/db/migrations/0005_studio_reviewers.sql +45 -0
  13. package/dist/db/migrations/0006_instance_settings.sql +69 -0
  14. package/dist/db/migrations/0007_jira_provider.no-txn.sql +13 -0
  15. package/dist/domain.js +129 -0
  16. package/dist/domain.js.map +1 -0
  17. package/dist/instance/settings.js +54 -0
  18. package/dist/instance/settings.js.map +1 -0
  19. package/dist/integrations/github.js +112 -0
  20. package/dist/integrations/github.js.map +1 -0
  21. package/dist/integrations/inbound.js +88 -0
  22. package/dist/integrations/inbound.js.map +1 -0
  23. package/dist/integrations/jira.js +129 -0
  24. package/dist/integrations/jira.js.map +1 -0
  25. package/dist/integrations/linear.js +111 -0
  26. package/dist/integrations/linear.js.map +1 -0
  27. package/dist/integrations/outbox.js +305 -0
  28. package/dist/integrations/outbox.js.map +1 -0
  29. package/dist/integrations/slack.js +135 -0
  30. package/dist/integrations/slack.js.map +1 -0
  31. package/dist/integrations/store.js +101 -0
  32. package/dist/integrations/store.js.map +1 -0
  33. package/dist/mail/index.js +21 -11
  34. package/dist/mail/index.js.map +1 -1
  35. package/dist/mail/resolve.js +80 -0
  36. package/dist/mail/resolve.js.map +1 -0
  37. package/dist/projectCache.js +3 -2
  38. package/dist/projectCache.js.map +1 -1
  39. package/dist/projects.js +8 -2
  40. package/dist/projects.js.map +1 -1
  41. package/dist/routes/account.js +59 -0
  42. package/dist/routes/account.js.map +1 -0
  43. package/dist/routes/activity.js +111 -0
  44. package/dist/routes/activity.js.map +1 -0
  45. package/dist/routes/assignees.js +139 -0
  46. package/dist/routes/assignees.js.map +1 -0
  47. package/dist/routes/attachments.js +2 -2
  48. package/dist/routes/attachments.js.map +1 -1
  49. package/dist/routes/comments.js +27 -17
  50. package/dist/routes/comments.js.map +1 -1
  51. package/dist/routes/cors.js +10 -1
  52. package/dist/routes/cors.js.map +1 -1
  53. package/dist/routes/instance.js +164 -0
  54. package/dist/routes/instance.js.map +1 -0
  55. package/dist/routes/integrations.js +610 -0
  56. package/dist/routes/integrations.js.map +1 -0
  57. package/dist/routes/jobs.js +15 -3
  58. package/dist/routes/jobs.js.map +1 -1
  59. package/dist/routes/mcpTokens.js +119 -0
  60. package/dist/routes/mcpTokens.js.map +1 -0
  61. package/dist/routes/members.js +177 -0
  62. package/dist/routes/members.js.map +1 -0
  63. package/dist/routes/owner.js +64 -7
  64. package/dist/routes/owner.js.map +1 -1
  65. package/dist/routes/sites.js +181 -8
  66. package/dist/routes/sites.js.map +1 -1
  67. package/dist/routes/threads.js +276 -9
  68. package/dist/routes/threads.js.map +1 -1
  69. package/dist/serverless.js +39 -6
  70. package/dist/serverless.js.map +1 -1
  71. package/dist/studioReviewers.js +67 -0
  72. package/dist/studioReviewers.js.map +1 -0
  73. package/dist/vendor/adapters/outbound/sanitise.js +18 -3
  74. package/dist/vendor/types/brief.js +121 -0
  75. package/package.json +1 -1
  76. package/static/dashboard/assets/CompositeItem-CoPuxIvr.js +1 -0
  77. package/static/dashboard/assets/ConfirmDialog-DkCcJwll.js +1 -0
  78. package/static/dashboard/assets/CopyButton-BNa2pLLv.js +1 -0
  79. package/static/dashboard/assets/FieldItemContext-DQXjpFtW.js +1 -0
  80. package/static/dashboard/assets/InstallTag-SOlWl7Hx.js +1 -0
  81. package/static/dashboard/assets/SaveState-CmxB4XyX.js +6 -0
  82. package/static/dashboard/assets/_app-DNkv3HBi.js +1 -0
  83. package/static/dashboard/assets/_app-xVQe811c.js +56 -0
  84. package/static/dashboard/assets/activity-DsMa5Ja6.js +1 -0
  85. package/static/dashboard/assets/arrow-left-vQV4xhAD.js +6 -0
  86. package/static/dashboard/assets/avatar-DuPL6QD_.js +1 -0
  87. package/static/dashboard/assets/badge-BWjiIc8T.js +1 -0
  88. package/static/dashboard/assets/card-BIBfCno8.js +1 -0
  89. package/static/dashboard/assets/check-Dpx6GTdT.js +6 -0
  90. package/static/dashboard/assets/chevron-right-DKIlBUGN.js +6 -0
  91. package/static/dashboard/assets/copy-DCbhEe2L.js +6 -0
  92. package/static/dashboard/assets/createBaseUIEventDetails-C_ZVkrgp.js +1 -0
  93. package/static/dashboard/assets/createLucideIcon-C_IGE4WD.js +36 -0
  94. package/static/dashboard/assets/dialog-BT2uWf4e.js +6 -0
  95. package/static/dashboard/assets/dropdown-menu-DSXzPAwB.js +11 -0
  96. package/static/dashboard/assets/image-off-DGWejLDG.js +6 -0
  97. package/static/dashboard/assets/index-BRTBtV91.css +1 -0
  98. package/static/dashboard/assets/index-D6FWZoJT.js +129 -0
  99. package/static/dashboard/assets/label-9QsSpLMA.js +1 -0
  100. package/static/dashboard/assets/labels--UUyt9uB.js +1 -0
  101. package/static/dashboard/assets/layout-grid-UPGEmEw-.js +6 -0
  102. package/static/dashboard/assets/me-0HQsBXLU.js +1 -0
  103. package/static/dashboard/assets/parts-C29uZ5zo.js +1 -0
  104. package/static/dashboard/assets/plus-BFNS5LcY.js +6 -0
  105. package/static/dashboard/assets/s._site-D6Ep2tdc.js +1 -0
  106. package/static/dashboard/assets/s._site.comments-BRVI5gpJ.js +39 -0
  107. package/static/dashboard/assets/s._site.reviewers-CiEkZnnp.js +1 -0
  108. package/static/dashboard/assets/s._site.settings-BqLGyfEd.js +1 -0
  109. package/static/dashboard/assets/setup-dUMCPWdf.js +1 -0
  110. package/static/dashboard/assets/sign-in-CdRa-bio.js +1 -0
  111. package/static/dashboard/assets/sites-CmbtFKoo.js +1 -0
  112. package/static/dashboard/assets/studio-BHuVXWZh.js +1 -0
  113. package/static/dashboard/assets/studio-BjeTOKda.js +1 -0
  114. package/static/dashboard/assets/studio.index--kuzOs7w.js +1 -0
  115. package/static/dashboard/assets/studio.integrations-Bq6HP80a.js +1 -0
  116. package/static/dashboard/assets/studio.members-8AB1KYsw.js +1 -0
  117. package/static/dashboard/assets/sun-BCiTcgnh.js +16 -0
  118. package/static/dashboard/assets/table-BXmeI_yA.js +1 -0
  119. package/static/dashboard/assets/update-duXzIzFS.js +1 -0
  120. package/static/dashboard/assets/useBaseQuery-Cp9wivVR.js +1 -0
  121. package/static/dashboard/assets/useQuery-BZXZlOqO.js +1 -0
  122. package/static/dashboard/assets/useRender-CO8aPW06.js +1 -0
  123. package/static/dashboard/assets/users-Dvw2FCKM.js +6 -0
  124. package/static/dashboard/assets/welcome-BHKjw20b.js +11 -0
  125. package/static/dashboard/assets/you-RBpAfUMU.js +1 -0
  126. package/static/dashboard/assets/zod-BpyjQIvb.js +1 -0
  127. package/static/dashboard/index.html +17 -2
  128. package/static/widget/snag.capture.js +1 -1
  129. package/static/widget/snag.dock.js +1 -1
  130. package/static/widget/snag.panels.js +1 -1
  131. package/static/widget/snag.runtime.js +2 -2
  132. package/static/widget/snag.text.js +1 -1
  133. package/vercel.json +4 -0
  134. package/static/dashboard/assets/index-CATItBzT.js +0 -1
  135. package/static/dashboard/assets/index-DsUJ96yc.css +0 -1
@@ -1 +0,0 @@
1
- (function(){const t=document.createElement("link").relList;if(t&&t.supports&&t.supports("modulepreload"))return;for(const l of document.querySelectorAll('link[rel="modulepreload"]'))s(l);new MutationObserver(l=>{for(const i of l)if(i.type==="childList")for(const o of i.addedNodes)o.tagName==="LINK"&&o.rel==="modulepreload"&&s(o)}).observe(document,{childList:!0,subtree:!0});function r(l){const i={};return l.integrity&&(i.integrity=l.integrity),l.referrerPolicy&&(i.referrerPolicy=l.referrerPolicy),l.crossOrigin==="use-credentials"?i.credentials="include":l.crossOrigin==="anonymous"?i.credentials="omit":i.credentials="same-origin",i}function s(l){if(l.ep)return;l.ep=!0;const i=r(l);fetch(l.href,i)}})();var ee,C,xe,q,me,Ie,Ee,re,V,F,je,ce,se,oe,Q={},X=[],We=/acit|ex(?:s|g|n|p|$)|rph|grid|ows|mnc|ntw|ine[ch]|zoo|^ord|itera/i,te=Array.isArray;function L(e,t){for(var r in t)e[r]=t[r];return e}function de(e){e&&e.parentNode&&e.parentNode.removeChild(e)}function Ge(e,t,r){var s,l,i,o={};for(i in t)i=="key"?s=t[i]:i=="ref"?l=t[i]:o[i]=t[i];if(arguments.length>2&&(o.children=arguments.length>3?ee.call(arguments,2):r),typeof e=="function"&&e.defaultProps!=null)for(i in e.defaultProps)o[i]===void 0&&(o[i]=e.defaultProps[i]);return K(e,o,s,l,null)}function K(e,t,r,s,l){var i={type:e,props:t,key:r,ref:s,__k:null,__:null,__b:0,__e:null,__c:null,constructor:void 0,__v:l??++xe,__i:-1,__u:0};return l==null&&C.vnode!=null&&C.vnode(i),i}function D(e){return e.children}function J(e,t){this.props=e,this.context=t}function O(e,t){if(t==null)return e.__?O(e.__,e.__i+1):null;for(var r;t<e.__k.length;t++)if((r=e.__k[t])!=null&&r.__e!=null)return r.__e;return typeof e.type=="function"?O(e):null}function ze(e){if(e.__P&&e.__d){var t=e.__v,r=t.__e,s=[],l=[],i=L({},t);i.__v=t.__v+1,C.vnode&&C.vnode(i),ue(e.__P,i,t,e.__n,e.__P.namespaceURI,32&t.__u?[r]:null,s,r??O(t),!!(32&t.__u),l),i.__v=t.__v,i.__.__k[i.__i]=i,Ue(s,i,l),t.__e=t.__=null,i.__e!=r&&Ne(i)}}function Ne(e){if((e=e.__)!=null&&e.__c!=null)return e.__e=e.__c.base=null,e.__k.some(function(t){if(t!=null&&t.__e!=null)return e.__e=e.__c.base=t.__e}),Ne(e)}function fe(e){(!e.__d&&(e.__d=!0)&&q.push(e)&&!Z.__r++||me!=C.debounceRendering)&&((me=C.debounceRendering)||Ie)(Z)}function Z(){try{for(var e,t=1;q.length;)q.length>t&&q.sort(Ee),e=q.shift(),t=q.length,ze(e)}finally{q.length=Z.__r=0}}function Re(e,t,r,s,l,i,o,c,_,d,h){var w,a,p,g,v,k,y=s&&s.__k||X,f=t.length;for(_=Ve(r,t,y,_,f),w=0;w<f;w++)(p=r.__k[w])!=null&&(a=p.__i!=-1&&y[p.__i]||Q,p.__i=w,k=ue(e,p,a,l,i,o,c,_,d,h),g=p.__e,p.ref&&a.ref!=p.ref&&(a.ref&&_e(a.ref,null,p),h.push(p.ref,p.__c||g,p)),v==null&&g!=null&&(v=g),4&p.__u?(_=De(p,_,e),a.__e&&(a.__e=null)):typeof p.type=="function"&&k!==void 0?_=k:g&&(_=g.nextSibling),p.__u&=-7);return r.__e=v,_}function Ve(e,t,r,s,l){var i,o,c,_,d,h=r.length,w=h,a=0;for(e.__k=new Array(l),i=0;i<l;i++)(o=t[i])!=null&&typeof o!="boolean"&&typeof o!="function"?(typeof o=="string"||typeof o=="number"||typeof o=="bigint"||o.constructor==String?o=e.__k[i]=K(null,o,null,null,null):te(o)?o=e.__k[i]=K(D,{children:o},null,null,null):o.constructor===void 0&&o.__b>0?o=e.__k[i]=K(o.type,o.props,o.key,o.ref?o.ref:null,o.__v):e.__k[i]=o,_=i+a,o.__=e,o.__b=e.__b+1,c=null,(d=o.__i=Ke(o,r,_,w))!=-1&&(w--,(c=r[d])&&(c.__u|=2)),c==null||c.__v==null?(d==-1&&(l>h?a--:l<h&&a++),typeof o.type!="function"&&(o.__u|=4)):d!=_&&(d==_-1?a--:d==_+1?a++:(d>_?a--:a++,o.__u|=4))):e.__k[i]=null;if(w)for(i=0;i<h;i++)(c=r[i])!=null&&(2&c.__u)==0&&(c.__e==s&&(s=O(c)),Oe(c,c));return s}function De(e,t,r){var s,l;if(typeof e.type=="function"){for(s=e.__k,l=0;s&&l<s.length;l++)s[l]&&(s[l].__=e,t=De(s[l],t,r));return t}e.__e!=t&&(t&&e.type&&!t.parentNode&&(t=O(e)),t=r.insertBefore(e.__e,t||null));do t=t&&t.nextSibling;while(t!=null&&t.nodeType==8);return t}function Ke(e,t,r,s){var l,i,o,c=e.key,_=e.type,d=t[r],h=d!=null&&(2&d.__u)==0;if(d===null&&c==null||h&&c==d.key&&_==d.type)return r;if(s>(h?1:0)){for(l=r-1,i=r+1;l>=0||i<t.length;)if((d=t[o=l>=0?l--:i++])!=null&&(2&d.__u)==0&&c==d.key&&_==d.type)return o}return-1}function ve(e,t,r){t[0]=="-"?e.setProperty(t,r??""):e[t]=r==null?"":typeof r!="number"||We.test(t)?r:r+"px"}function G(e,t,r,s,l){var i,o;e:if(t=="style")if(typeof r=="string")e.style.cssText=r;else{if(typeof s=="string"&&(e.style.cssText=s=""),s)for(t in s)r&&t in r||ve(e.style,t,"");if(r)for(t in r)s&&r[t]==s[t]||ve(e.style,t,r[t])}else if(t[0]=="o"&&t[1]=="n")i=t!=(t=t.replace(je,"$1")),o=t.toLowerCase(),t=o in e||t=="onFocusOut"||t=="onFocusIn"?o.slice(2):t.slice(2),e.l||(e.l={}),e.l[t+i]=r,r?s?r[F]=s[F]:(r[F]=ce,e.addEventListener(t,i?oe:se,i)):e.removeEventListener(t,i?oe:se,i);else{if(l=="http://www.w3.org/2000/svg")t=t.replace(/xlink(H|:h)/,"h").replace(/sName$/,"s");else if(t!="width"&&t!="height"&&t!="href"&&t!="list"&&t!="form"&&t!="tabIndex"&&t!="download"&&t!="rowSpan"&&t!="colSpan"&&t!="role"&&t!="popover"&&t in e)try{e[t]=r??"";break e}catch{}typeof r=="function"||(r==null||r===!1&&t[4]!="-"?e.removeAttribute(t):e.setAttribute(t,t=="popover"&&r==1?"":r))}}function ge(e){return function(t){if(this.l){var r=this.l[t.type+e];if(t[V]==null)t[V]=ce++;else if(t[V]<r[F])return;return r(C.event?C.event(t):t)}}}function ue(e,t,r,s,l,i,o,c,_,d){var h,w,a,p,g,v,k,y,f,T,N,m,P,R,u,S,A=t.type;if(t.constructor!==void 0)return null;128&r.__u&&(_=!!(32&r.__u),i=[c=t.__e=r.__e]),(h=C.__b)&&h(t);e:if(typeof A=="function"){w=o.length;try{if(f=t.props,T=A.prototype&&A.prototype.render,N=(h=A.contextType)&&s[h.__c],m=h?N?N.props.value:h.__:s,r.__c?y=(a=t.__c=r.__c).__=a.__E:(T?t.__c=a=new A(f,m):(t.__c=a=new J(f,m),a.constructor=A,a.render=Ye),N&&N.sub(a),a.state||(a.state={}),a.__n=s,p=a.__d=!0,a.__h=[],a._sb=[]),T&&a.__s==null&&(a.__s=a.state),T&&A.getDerivedStateFromProps!=null&&(a.__s==a.state&&(a.__s=L({},a.__s)),L(a.__s,A.getDerivedStateFromProps(f,a.__s))),g=a.props,v=a.state,a.__v=t,p)T&&A.getDerivedStateFromProps==null&&a.componentWillMount!=null&&a.componentWillMount(),T&&a.componentDidMount!=null&&a.__h.push(a.componentDidMount);else{if(T&&A.getDerivedStateFromProps==null&&f!==g&&a.componentWillReceiveProps!=null&&a.componentWillReceiveProps(f,m),t.__v==r.__v||!a.__e&&a.shouldComponentUpdate!=null&&a.shouldComponentUpdate(f,a.__s,m)===!1){t.__v!=r.__v&&(a.props=f,a.state=a.__s,a.__d=!1),t.__e=r.__e,t.__k=r.__k,t.__k.some(function($){$&&($.__=t)}),X.push.apply(a.__h,a._sb),a._sb=[],a.__h.length&&o.push(a),c=O(r);break e}a.componentWillUpdate!=null&&a.componentWillUpdate(f,a.__s,m),T&&a.componentDidUpdate!=null&&a.__h.push(function(){a.componentDidUpdate(g,v,k)})}if(a.context=m,a.props=f,a.__P=e,a.__e=!1,P=C.__r,R=0,T)a.state=a.__s,a.__d=!1,P&&P(t),h=a.render(a.props,a.state,a.context),X.push.apply(a.__h,a._sb),a._sb=[];else do a.__d=!1,P&&P(t),h=a.render(a.props,a.state,a.context),a.state=a.__s;while(a.__d&&++R<25);a.state=a.__s,a.getChildContext!=null&&(s=L(L({},s),a.getChildContext())),T&&!p&&a.getSnapshotBeforeUpdate!=null&&(k=a.getSnapshotBeforeUpdate(g,v)),u=h!=null&&h.type===D&&h.key==null?qe(h.props.children):h,c=Re(e,te(u)?u:[u],t,r,s,l,i,o,c,_,d),a.base=t.__e,t.__u&=-161,a.__h.length&&o.push(a),y&&(a.__E=a.__=null)}catch($){if(o.length=w,t.__v=null,_||i!=null){if($.then){for(t.__u|=_?160:128;c&&c.nodeType==8&&c.nextSibling;)c=c.nextSibling;i!=null&&(i[i.indexOf(c)]=null),t.__e=c}else if(i!=null)for(S=i.length;S--;)de(i[S])}else t.__e=r.__e;t.__k==null&&(t.__k=r.__k||[]),$.then||Le(t),C.__e($,t,r)}}else i==null&&t.__v==r.__v?(t.__k=r.__k,t.__e=r.__e):c=t.__e=Je(r.__e,t,r,s,l,i,o,_,d);return(h=C.diffed)&&h(t),128&t.__u?void 0:c}function Le(e){e&&(e.__c&&(e.__c.__e=!0),e.__k&&e.__k.some(Le))}function Ue(e,t,r){for(var s=0;s<r.length;s++)_e(r[s],r[++s],r[++s]);C.__c&&C.__c(t,e),e.some(function(l){try{e=l.__h,l.__h=[],e.some(function(i){i.call(l)})}catch(i){C.__e(i,l.__v)}})}function qe(e){return typeof e!="object"||e==null||e.__b>0?e:te(e)?e.map(qe):e.constructor!==void 0?null:L({},e)}function Je(e,t,r,s,l,i,o,c,_){var d,h,w,a,p,g,v,k=r.props||Q,y=t.props,f=t.type;if(f=="svg"?l="http://www.w3.org/2000/svg":f=="math"?l="http://www.w3.org/1998/Math/MathML":l||(l="http://www.w3.org/1999/xhtml"),i!=null){for(d=0;d<i.length;d++)if((p=i[d])&&"setAttribute"in p==!!f&&(f?p.localName==f:p.nodeType==3)){e=p,i[d]=null;break}}if(e==null){if(f==null)return document.createTextNode(y);e=document.createElementNS(l,f,y.is&&y),c&&(C.__m&&C.__m(t,i),c=!1),i=null}if(f==null)k===y||c&&e.data==y||(e.data=y);else{if(i=f=="textarea"&&y.defaultValue!=null?null:i&&ee.call(e.childNodes),!c&&i!=null)for(k={},d=0;d<e.attributes.length;d++)k[(p=e.attributes[d]).name]=p.value;for(d in k)p=k[d],d=="dangerouslySetInnerHTML"?w=p:d=="children"||d in y||d=="value"&&"defaultValue"in y||d=="checked"&&"defaultChecked"in y||G(e,d,null,p,l);for(d in y)p=y[d],d=="children"?a=p:d=="dangerouslySetInnerHTML"?h=p:d=="value"?g=p:d=="checked"?v=p:c&&typeof p!="function"||k[d]===p||G(e,d,p,k[d],l);if(h)c||w&&(h.__html==w.__html||h.__html==e.innerHTML)||(e.innerHTML=h.__html),t.__k=[];else if(w&&(e.innerHTML=""),Re(t.type=="template"?e.content:e,te(a)?a:[a],t,r,s,f=="foreignObject"?"http://www.w3.org/1999/xhtml":l,i,o,i?i[0]:r.__k&&O(r,0),c,_),i!=null)for(d=i.length;d--;)de(i[d]);c&&f!="textarea"||(d="value",f=="progress"&&g==null?e.removeAttribute("value"):g!=null&&(g!==e[d]||f=="progress"&&!g||f=="option"&&g!=k[d])&&G(e,d,g,k[d],l),d="checked",v!=null&&v!=e[d]&&G(e,d,v,k[d],l))}return e}function _e(e,t,r){try{if(typeof e=="function"){var s=typeof e.__u=="function";s&&e.__u(),s&&t==null||(e.__u=e(t))}else e.current=t}catch(l){C.__e(l,r)}}function Oe(e,t,r){var s,l;if(C.unmount&&C.unmount(e),(s=e.ref)&&(s.current&&s.current!=e.__e||_e(s,null,t)),(s=e.__c)!=null){if(s.componentWillUnmount)try{s.componentWillUnmount()}catch(i){C.__e(i,t)}s.base=s.__P=s.__n=null}if(s=e.__k)for(l=0;l<s.length;l++)s[l]&&Oe(s[l],t,r||typeof e.type!="function");r||de(e.__e),e.__c=e.__=e.__e=void 0}function Ye(e,t,r){return this.constructor(e,r)}function Qe(e,t,r){var s,l,i,o;t==document&&(t=document.documentElement),C.__&&C.__(e,t),l=(s=!1)?null:t.__k,i=[],o=[],ue(t,e=t.__k=Ge(D,null,[e]),l||Q,Q,t.namespaceURI,l?null:t.firstChild?ee.call(t.childNodes):null,i,l?l.__e:t.firstChild,s,o),Ue(i,e,o),e.props.children=null}ee=X.slice,C={__e:function(e,t,r,s){for(var l,i,o;t=t.__;)if((l=t.__c)&&!l.__)try{if((i=l.constructor)&&i.getDerivedStateFromError!=null&&(l.setState(i.getDerivedStateFromError(e)),o=l.__d),l.componentDidCatch!=null&&(l.componentDidCatch(e,s||{}),o=l.__d),o)return l.__E=l}catch(c){e=c}throw e}},xe=0,J.prototype.setState=function(e,t){var r;r=this.__s!=null&&this.__s!=this.state?this.__s:this.__s=L({},this.state),typeof e=="function"&&(e=e(L({},r),this.props)),e&&L(r,e),e!=null&&this.__v&&(t&&this._sb.push(t),fe(this))},J.prototype.forceUpdate=function(e){this.__v&&(this.__e=!0,e&&this.__h.push(e),fe(this))},J.prototype.render=D,q=[],Ie=typeof Promise=="function"?Promise.prototype.then.bind(Promise.resolve()):setTimeout,Ee=function(e,t){return e.__v.__b-t.__v.__b},Z.__r=0,re=Math.random().toString(8),V="__d"+re,F="__a"+re,je=/(PointerCapture)$|Capture$/i,ce=0,se=ge(!1),oe=ge(!0);var Xe=0;function n(e,t,r,s,l,i){t||(t={});var o,c,_=t;if("ref"in _)for(c in _={},t)c=="ref"?o=t[c]:_[c]=t[c];var d={type:e,props:_,key:r,ref:o,__k:null,__:null,__b:0,__e:null,__c:null,constructor:void 0,__v:--Xe,__i:-1,__u:0,__source:l,__self:i};if(typeof e=="function"&&(o=e.defaultProps))for(c in o)_[c]===void 0&&(_[c]=o[c]);return C.vnode&&C.vnode(d),d}var B,x,ie,ye,W=0,He=[],E=C,be=E.__b,we=E.__r,ke=E.diffed,Se=E.__c,Ce=E.unmount,$e=E.__;function he(e,t){E.__h&&E.__h(x,e,W||t),W=0;var r=x.__H||(x.__H={__:[],__h:[]});return e>=r.__.length&&r.__.push({}),r.__[e]}function b(e){return W=1,Ze(Be,e)}function Ze(e,t,r){var s=he(B++,2);if(s.t=e,!s.__c&&(s.__=[Be(void 0,t),function(c){var _=s.__N?s.__N[0]:s.__[0],d=s.t(_,c);_!==d&&(s.__N=[d,s.__[1]],s.__c.setState({}))}],s.__c=x,!x.__f)){var l=function(c,_,d){if(!s.__c.__H)return!0;var h=!1,w=s.__c.props!==c;if(s.__c.__H.__.some(function(p){if(p.__N){h=!0;var g=p.__[0];p.__=p.__N,p.__N=void 0,g!==p.__[0]&&(w=!0)}}),i){var a=i.call(this,c,_,d);return h?a||w:a}return!h||w};x.__f=!0;var i=x.shouldComponentUpdate,o=x.componentWillUpdate;x.componentWillUpdate=function(c,_,d){if(this.__e){var h=i;i=void 0,l(c,_,d),i=h}o&&o.call(this,c,_,d)},x.shouldComponentUpdate=l}return s.__N||s.__}function M(e,t){var r=he(B++,3);!E.__s&&Fe(r.__H,t)&&(r.__=e,r.u=t,x.__H.__h.push(r))}function et(e){return W=5,pe(function(){return{current:e}},[])}function pe(e,t){var r=he(B++,7);return Fe(r.__H,t)&&(r.__=e(),r.__H=t,r.__h=e),r.__}function Me(e,t){return W=8,pe(function(){return e},t)}function tt(){for(var e;e=He.shift();){var t=e.__H;if(e.__P&&t)try{t.__h.some(Y),t.__h.some(le),t.__h=[]}catch(r){t.__h=[],E.__e(r,e.__v)}}}E.__b=function(e){x=null,be&&be(e)},E.__=function(e,t){e&&t.__k&&t.__k.__m&&(e.__m=t.__k.__m),$e&&$e(e,t)},E.__r=function(e){we&&we(e),B=0;var t=(x=e.__c).__H;t&&(ie===x?(t.__h=[],x.__h=[],t.__.some(function(r){r.__N&&(r.__=r.__N),r.u=r.__N=void 0})):(t.__h.some(Y),t.__h.some(le),t.__h=[],B=0)),ie=x},E.diffed=function(e){ke&&ke(e);var t=e.__c;t&&t.__H&&(t.__H.__h.length&&(He.push(t)!==1&&ye===E.requestAnimationFrame||((ye=E.requestAnimationFrame)||nt)(tt)),t.__H.__.some(function(r){r.u&&(r.__H=r.u,r.u=void 0)})),ie=x=null},E.__c=function(e,t){t.some(function(r){try{r.__h.some(Y),r.__h=r.__h.filter(function(s){return!s.__||le(s)})}catch(s){t.some(function(l){l.__h&&(l.__h=[])}),t=[],E.__e(s,r.__v)}}),Se&&Se(e,t)},E.unmount=function(e){Ce&&Ce(e);var t,r=e.__c;r&&r.__H&&(r.__H.__.some(function(s){try{Y(s)}catch(l){t=l}}),r.__H=void 0,t&&E.__e(t,r.__v))};var Te=typeof requestAnimationFrame=="function";function nt(e){var t,r=function(){clearTimeout(s),Te&&cancelAnimationFrame(t),setTimeout(e)},s=setTimeout(r,35);Te&&(t=requestAnimationFrame(r))}function Y(e){var t=x,r=e.__c;typeof r=="function"&&(e.__c=void 0,r()),x=t}function le(e){var t=x;e.__c=e.__(),x=t}function Fe(e,t){return!e||e.length!==t.length||t.some(function(r,s){return r!==e[s]})}function Be(e,t){return typeof t=="function"?t(e):t}const rt={csrf:"snag_csrf"},it=rt.csrf,st={csrf:"x-snagset-csrf"};class U extends Error{status;code;constructor(t,r){super(r.message),this.status=t,this.code=r.code}}function ot(){for(const e of document.cookie.split(";")){const t=e.indexOf("=");if(t>0&&e.slice(0,t).trim()===it)return e.slice(t+1).trim()}return""}async function j(e,t,r){const s=await fetch(t,{method:e,credentials:"same-origin",headers:{...r===void 0?{}:{"content-type":"application/json"},...e==="GET"?{}:{[st.csrf]:ot()}},...r===void 0?{}:{body:JSON.stringify(r)}});if(s.status===204)return;const l=await s.json().catch(()=>null);if(!s.ok){const i=l?.error;throw new U(s.status,i??{code:"unknown",message:`Request failed (${s.status}).`})}return l}const I={me:()=>j("GET","/api/v1/me"),claimed:()=>j("GET","/api/v1/setup").then(e=>e.claimed),setup:e=>j("POST","/api/v1/setup",e),login:(e,t)=>j("POST","/auth/login",{email:e,password:t}),logout:()=>j("POST","/auth/logout"),threads:(e,t={})=>{const r=new URLSearchParams;t.status&&r.set("status",t.status),t.route&&r.set("route",t.route),t.round&&r.set("round",String(t.round)),t.q&&r.set("q",t.q),t.since&&r.set("since",t.since);const s=r.toString();return j("GET",`/api/v1/projects/${encodeURIComponent(e)}/threads${s?`?${s}`:""}`)},createProject:(e,t)=>j("POST","/api/v1/projects",{name:e,origins:t}),setAudience:(e,t)=>j("PATCH",`/api/v1/projects/${encodeURIComponent(e)}`,{writeMode:t}),origins:e=>j("GET",`/api/v1/projects/${encodeURIComponent(e)}/origins`),addOrigin:(e,t)=>j("POST",`/api/v1/projects/${encodeURIComponent(e)}/origins`,{origin:t}),rounds:e=>j("GET",`/api/v1/projects/${encodeURIComponent(e)}/rounds`),createRound:(e,t)=>j("POST",`/api/v1/projects/${encodeURIComponent(e)}/rounds`,{name:t}),setStatus:(e,t,r)=>j("PATCH",`/api/v1/projects/${encodeURIComponent(e)}/threads/${encodeURIComponent(t)}`,{status:r}),addComment:(e,t)=>j("POST",`/api/v1/threads/${encodeURIComponent(e)}/comments`,{id:crypto.randomUUID(),body:t}),listLinks:e=>j("GET",`/api/v1/projects/${encodeURIComponent(e)}/review-links`),mintLink:(e,t)=>j("POST",`/api/v1/projects/${encodeURIComponent(e)}/review-links`,t),revokeLink:e=>j("DELETE",`/api/v1/review-links/${encodeURIComponent(e)}`)};function Ae(e){const t=new Date(e),r=Math.round((Date.now()-t.getTime())/6e4);return r<1?"just now":r<60?`${r}m ago`:r<1440?`${Math.round(r/60)}h ago`:t.toLocaleDateString(void 0,{day:"numeric",month:"short"})}function lt({context:e}){const t=e?.capture,r=e?.viewport,l=[["Viewport",r?.w?`${r.w} × ${r.h}`:null],["Browser",e?.browser??e?.ua??null],["Platform",e?.os??e?.platform??null],["Device pixel ratio",e?.dpr??null]].filter(([,c])=>c!=null&&c!==""),i=t?.category&&t.category!=="ok"&&t.category!=="full";return!l.length&&!t?null:n("section",{class:"block",children:[n("h2",{children:["Capture",n("button",{type:"button",class:"linkish",style:"float:right;font-size:12px",onClick:()=>{navigator.clipboard?.writeText(JSON.stringify(e,null,2))},children:"Copy environment"})]}),l.length>0&&n("dl",{class:"kv",children:l.map(([c,_])=>n(D,{children:[n("dt",{children:c}),n("dd",{children:String(_)})]}))}),i&&n("p",{class:"warn",style:"margin:10px 0 0",children:[n("b",{children:t.category}),t.reasons?.length?` — ${t.reasons.join("; ")}`:""]}),t?.blindSpots?.length?n("p",{class:"warn",style:"margin:6px 0 0",children:[t.blindSpots.length," blind spot",t.blindSpots.length===1?"":"s",": ",t.blindSpots.join("; ")]}):null,t?.droppedCategories?.length?n("p",{class:"warn",style:"margin:6px 0 0",children:["Dropped: ",t.droppedCategories.join(", ")]}):null]})}function at({onReply:e}){const[t,r]=b(""),[s,l]=b(!1),[i,o]=b("");return n("form",{class:"composer",onSubmit:async c=>{c.preventDefault();const _=t.trim();if(!(!_||s)){l(!0),o("");try{await e(_),r("")}catch(d){o(d instanceof U?d.message:"Could not send that reply.")}finally{l(!1)}}},children:[n("label",{class:"field",children:[n("span",{children:"Reply"}),n("textarea",{rows:3,placeholder:"Write a reply…",value:t,disabled:s,onInput:c=>r(c.target.value)})]}),i&&n("p",{class:"err",children:i}),n("button",{class:"btn btn-primary",type:"submit",disabled:s||!t.trim(),children:s?"Sending…":"Reply"})]})}function ct({thread:e,onStatus:t,onReply:r,busy:s}){const l=e.attachments?.find(c=>c.kind==="screenshot")??e.attachments?.[0],i=e.anchor?.label??"",o=e.anchor??{};return n("article",{class:"detail detail-open",children:[n("div",{class:"detail-head",children:[n("span",{class:"key",children:e.key}),n("h1",{children:i||"A comment on this page"}),n("span",{class:`status status-${e.status}`,children:ae[e.status]??e.status})]}),n("p",{style:"margin:6px 0 0;color:var(--ink-soft);font-size:13px",children:["Round ",e.roundNumber," · ",e.route||"/"," · left by ",e.createdBy.name||"someone"," ",Ae(e.createdAt)]}),l?n("figure",{class:"shot",children:[n("img",{src:l.url,alt:`Screenshot of the page when ${e.key} was left`,width:l.width,height:l.height,loading:"lazy"}),n("figcaption",{children:["captured at ",l.width??"?"," × ",l.height??"?"]})]}):n("div",{class:"no-shot",children:[n("b",{children:"No screenshot for this one."}),n("p",{style:"margin:6px 0 0",children:"Either this instance had no bucket connected when it was left, or the reviewer turned the picture off for this comment. The anchor and the page context below are unaffected."})]}),n("section",{class:"thread",children:[e.comments.length===0&&n("p",{style:"color:var(--ink-soft)",children:"This thread has no readable comments."}),e.comments.map(c=>n("div",{class:"comment",children:[n("div",{class:"comment-head",children:[n("b",{children:c.author.name||"Anonymous"}),c.author.kind==="agent"&&n("span",{class:"agent",children:"agent"}),n("span",{style:"color:var(--ink-faint)",children:Ae(c.createdAt)})]}),n("p",{children:c.body??n("i",{style:"color:var(--ink-faint)",children:"deleted"})})]},c.id))]}),n(at,{onReply:r}),n("section",{class:"block",children:[n("h2",{children:"Anchor"}),n("dl",{class:"kv",children:[n("dt",{children:"State"}),n("dd",{children:e.anchorState}),i&&n(D,{children:[n("dt",{children:"Label"}),n("dd",{children:i})]}),o.css&&n(D,{children:[n("dt",{children:"Selector"}),n("dd",{children:String(o.css)})]}),o.domid&&n(D,{children:[n("dt",{children:"DOM id"}),n("dd",{children:String(o.domid)})]}),o.page?.pathname&&n(D,{children:[n("dt",{children:"Path"}),n("dd",{children:String(o.page.pathname)})]})]})]}),n(lt,{context:e.context??{}}),n("div",{class:"actions",children:[e.status!=="resolved"?n("button",{class:"btn btn-primary",disabled:s,onClick:()=>t("resolved"),children:"Mark resolved"}):n("button",{class:"btn",disabled:s,onClick:()=>t("open"),children:"Reopen"}),e.status!=="progress"&&e.status!=="resolved"&&n("button",{class:"btn",disabled:s,onClick:()=>t("progress"),children:"In progress"}),o.page?.origin&&n("a",{class:"btn",href:`${o.page.origin}${o.page.pathname??"/"}?snag_t=${encodeURIComponent(e.key)}`,target:"_blank",rel:"noreferrer noopener",children:"Open on site ↗"})]})]})}function z(e){return e?new Date(e).toLocaleDateString(void 0,{day:"numeric",month:"short",year:"numeric"}):"—"}function dt({uid:e,rounds:t}){const[r,s]=b(null),[l,i]=b(""),[o,c]=b(null),[_,d]=b(null),[h,w]=b(""),[a,p]=b("14"),[g,v]=b(""),[k,y]=b(!1),f=()=>{s(null),I.listLinks(e).then(m=>s(m.data)).catch(m=>i(m instanceof U?m.message:"Could not load the links."))};M(()=>{c(null),i(""),f()},[e]);const T=async m=>{m.preventDefault();const P=h.trim();if(!(!P||k)){y(!0),i("");try{const R=Number(a),u=Number.isFinite(R)&&R>0?new Date(Date.now()+R*864e5).toISOString():void 0,S=await I.mintLink(e,{name:P,...u?{expiresAt:u}:{},...g?{roundId:g}:{}});c(S),w(""),p("14"),v(""),f()}catch(R){i(R instanceof U?R.message:"Could not create that link.")}finally{y(!1)}}},N=async m=>{if(confirm(`Revoke "${m.name}"? Every session minted from it is out within 10 s. This cannot be undone — minting a new link is the recovery.`)){d(m.id),i("");try{await I.revokeLink(m.id),c(P=>P?.id===m.id?null:P),f()}catch(P){i(P instanceof U?P.message:"Could not revoke that link.")}finally{d(null)}}};return n("div",{class:"links",children:[n("div",{class:"links-list",children:[n("h1",{class:"links-title",children:"Review links"}),l&&n("p",{class:"err",children:l}),r===null&&n("p",{class:"empty",children:"Loading…"}),r?.length===0&&n("div",{class:"empty",children:[n("h2",{children:"No links yet"}),n("p",{children:"Mint one on the right — once this project needs a link, it is the only way a reviewer gets in."})]}),r&&r.length>0&&n("table",{class:"link-table",children:[n("thead",{children:n("tr",{children:[n("th",{children:"Name"}),n("th",{children:"Created"}),n("th",{children:"Expires"}),n("th",{children:"Last used"}),n("th",{children:"Uses"}),n("th",{})]})}),n("tbody",{children:r.map(m=>{const P=!!m.revokedAt,R=!P&&new Date(m.expiresAt).getTime()<=Date.now(),u=m.roundId?t?.find(S=>S.id===m.roundId):null;return n("tr",{class:P||R?"link-dead":"",children:[n("td",{children:[m.name,u&&n("span",{class:"link-round",children:u.name})]}),n("td",{children:z(m.createdAt)}),n("td",{children:P?n("span",{class:"warn",children:["revoked ",z(m.revokedAt)]}):R?n("span",{class:"warn",children:"expired"}):z(m.expiresAt)}),n("td",{children:z(m.lastUsedAt)}),n("td",{children:m.useCount}),n("td",{children:!P&&n("button",{class:"btn",disabled:_===m.id,onClick:()=>void N(m),children:_===m.id?"Revoking…":"Revoke"})})]},m.id)})})]})]}),n("div",{class:"links-side",children:[o&&n("div",{class:"card minted",children:[n("h2",{children:['"',o.name,'" is ready']}),n("p",{class:"sub",children:["This is the only time the token is shown — the list on the left never carries it again. Paste it after the reviewed site's URL, e.g. ",n("code",{children:["https://yoursite.com/page",o.fragment]}),"."]}),n("div",{class:"token-box",children:[n("code",{children:o.fragment}),n("button",{class:"btn",onClick:()=>void navigator.clipboard.writeText(o.fragment).catch(()=>{}),children:"Copy"})]}),n("button",{class:"linkish",style:"margin-top:10px",onClick:()=>c(null),children:"Done"})]}),n("form",{class:"card",onSubmit:T,children:[n("h2",{children:"New link"}),n("label",{class:"field",children:[n("span",{children:"Name"}),n("input",{required:!0,placeholder:"Client review — round 2",value:h,onInput:m=>w(m.target.value)})]}),n("label",{class:"field",children:[n("span",{children:"Expires in (days, up to 90)"}),n("input",{type:"number",min:1,max:90,value:a,onInput:m=>p(m.target.value)})]}),t&&t.length>0&&n("label",{class:"field",children:[n("span",{children:"Pin to a round (optional)"}),n("select",{value:g,onChange:m=>v(m.target.value),children:[n("option",{value:"",children:"Any round"}),t.map(m=>n("option",{value:m.id,children:m.name},m.id))]})]}),n("button",{class:"btn btn-primary",type:"submit",disabled:k||!h.trim(),children:k?"Creating…":"Create link"})]})]})]})}function ut({me:e,onAdded:t,origin:r}){const[s,l]=b(""),[i,o]=b(""),[c,_]=b(!1),[d,h]=b(""),[w,a]=b(null);return n("div",{class:"sites",children:[n("section",{class:"site-add",children:[n("h2",{children:"Add a site"}),n("form",{onSubmit:async g=>{if(g.preventDefault(),!c){_(!0),h("");try{const v=await I.createProject(s.trim(),i.trim());a({uid:v.uid,name:v.name,...v.warning?{warning:v.warning}:{}}),l(""),o(""),t(v.uid)}catch(v){h(v instanceof U?v.message:"Something went wrong. Try again.")}finally{_(!1)}}},children:[n("label",{children:["Name",n("input",{value:s,placeholder:"Acme redesign",onInput:g=>l(g.target.value),required:!0})]}),n("label",{children:["Where it runs",n("input",{value:i,placeholder:"https://staging.acme.com, http://localhost:3000",onInput:g=>o(g.target.value)}),n("small",{children:["Comma-separated, with the scheme. Only these can talk to the site — a tag on any other address is ignored. ",n("code",{children:"https://*.acme.com"})," covers subdomains."]})]}),n("button",{type:"submit",disabled:c||!s.trim(),children:c?"Adding…":"Add site"}),d&&n("p",{class:"error",children:d})]})]}),w&&n(_t,{site:w,origin:r}),n("section",{class:"site-list",children:[n("h2",{children:"Your sites"}),n("ul",{children:e.projects.map(g=>n("li",{children:[n("strong",{children:g.name}),n("code",{children:g.uid}),n("span",{children:[g.threads," snag",g.threads===1?"":"s"," · ",g.unresolved," open"]})]},g.uid))})]})]})}function _t({site:e,origin:t}){const[r,s]=b([]),[l,i]=b(""),[o,c]=b(""),[_,d]=b("everyone"),[h,w]=b(""),a=v=>{const k=_;d(v),w(""),I.setAudience(e.uid,v==="everyone"?"open":"link-required").catch(()=>{d(k),w("Could not save — try again.")})},p=Me(()=>{I.origins(e.uid).then(v=>s(v.origins)).catch(()=>s([]))},[e.uid]);M(p,[p]);const g=`<script src="${t}/snag.js" data-snag-site="${e.uid}" defer><\/script>`;return n("section",{class:"site-made",children:[n("h2",{children:[e.name," is ready"]}),n("p",{children:"Paste this into the site, immediately before the closing </body> tag."}),n("div",{class:"site-audience",role:"radiogroup","aria-label":"Who sees the toolbar",children:[n("label",{children:[n("input",{type:"radio",name:"audience",checked:_==="everyone",onChange:()=>a("everyone")}),n("span",{children:[n("strong",{children:"Everyone on these addresses"})," — the toolbar just appears, and anyone can comment. For staging. Saved to the server: change it here any time, no re-paste."]})]}),n("label",{children:[n("input",{type:"radio",name:"audience",checked:_==="links",onChange:()=>a("links")}),n("span",{children:[n("strong",{children:"Only people with a review link"})," — visitors see nothing. For production, where the visitors are your client's customers."]})]}),h&&n("p",{class:"error",children:h})]}),n("pre",{children:n("code",{children:g})}),n("button",{class:"linkish",onClick:()=>{navigator.clipboard?.writeText(g)},children:"Copy"}),n("h3",{children:"Allowed origins"}),r.length?n("ul",{class:"origins",children:r.map(v=>n("li",{children:n("code",{children:v})},v))}):n("p",{class:"warn",children:e.warning??"None yet — the tag will load and every request from it will be refused. Add one below."}),n("form",{onSubmit:async v=>{v.preventDefault();const k=l.trim();if(k){c("");try{const y=await I.addOrigin(e.uid,k);s(y.origins),i("")}catch(y){c(y instanceof U?y.message:"Could not add that origin.")}}},children:[n("input",{value:l,placeholder:"https://www.acme.com",onInput:v=>i(v.target.value)}),n("button",{type:"submit",disabled:!l.trim(),children:"Allow"}),o&&n("p",{class:"error",children:o})]})]})}function ht(e,t,r=[]){const s=new Set(r),l=e.filter(i=>!s.has(i.id));for(const i of t){if(s.has(i.id))continue;const o=l.findIndex(c=>c.id===i.id);o===-1?l.push(i):l[o]=i}return l}function pt({token:e,onClaimed:t}){const[r,s]=b(""),[l,i]=b(""),[o,c]=b(""),[_,d]=b(""),[h,w]=b(!1),[a,p]=b(""),[g,v]=b(null);return g?n(mt,{site:g,onContinue:t}):n("div",{class:"setup",children:[n("h1",{children:"Set up Snagset"}),n("p",{class:"setup-lede",children:"This instance has not been claimed yet. The account you make here is the only one, until you add another."}),n("form",{onSubmit:async y=>{if(y.preventDefault(),!h){w(!0),p("");try{const f=await I.setup({token:e,orgName:r.trim()||"My studio",projectName:l.trim(),email:o.trim(),password:_});v(f.project)}catch(f){p(f instanceof U?f.message:"Something went wrong. Try again.")}finally{w(!1)}}},children:[n("label",{children:["Your email",n("input",{type:"email",value:o,autocomplete:"username",required:!0,onInput:y=>c(y.target.value)})]}),n("label",{children:["Password",n("input",{type:"password",value:_,autocomplete:"new-password",required:!0,minLength:12,onInput:y=>d(y.target.value)}),n("small",{children:"At least 12 characters. There is no reset email on a fresh install — keep it."})]}),n("label",{children:["Studio name ",n("span",{class:"setup-opt",children:"optional"}),n("input",{value:r,placeholder:"My studio",onInput:y=>s(y.target.value)})]}),n("label",{children:["First site ",n("span",{class:"setup-opt",children:"optional"}),n("input",{value:l,placeholder:"Acme redesign",onInput:y=>i(y.target.value)})]}),n("button",{type:"submit",disabled:h||!o.trim()||_.length<12,children:h?"Setting up…":"Create my account"}),a&&n("p",{class:"error",children:a})]})]})}function mt({site:e,onContinue:t}){const r=`<script src="${location.origin}/snag.js" data-snag-site="${e.uid}" defer><\/script>`;return n("div",{class:"setup",children:[n("h1",{children:[e.name," is ready"]}),n("p",{class:"setup-lede",children:"Paste this into the site you want reviewed, before the closing </body> tag."}),n("pre",{children:n("code",{children:r})}),n("div",{class:"setup-actions",children:[n("button",{type:"button",class:"linkish",onClick:()=>void navigator.clipboard?.writeText(r),children:"Copy"}),n("button",{type:"button",onClick:t,children:"Open the dashboard"})]}),n("p",{class:"setup-note",children:"The site's address has to be on its allow-list before comments can reach you — add it on the Sites screen. A tag on any other address loads and is ignored."})]})}const ft=["open","progress","review","resolved"],ae={open:"Active",progress:"In progress",review:"In review",resolved:"Resolved"};function H(){const e=new URLSearchParams(location.search);return{project:e.get("project")??"",thread:e.get("t")??"",status:e.get("status")??"",q:e.get("q")??"",round:e.get("round")??"",screen:e.get("screen")??"",claim:e.get("claim")??""}}function Pe(e){const t={...H(),...e},r=new URLSearchParams;t.project&&r.set("project",t.project),t.thread&&r.set("t",t.thread),t.status&&r.set("status",t.status),t.q&&r.set("q",t.q),t.round&&r.set("round",t.round),t.screen&&r.set("screen",t.screen);const s=`${location.pathname}${r.toString()?`?${r}`:""}`;history.pushState(null,"",s)}function vt({onIn:e}){const[t,r]=b(""),[s,l]=b(""),[i,o]=b(""),[c,_]=b(!1);return n("div",{class:"gate",children:n("form",{class:"card",onSubmit:async d=>{d.preventDefault(),_(!0),o("");try{await I.login(t,s),e()}catch(h){o(h instanceof U?h.message:"Could not reach the server.")}finally{_(!1)}},children:[n("h1",{children:"Sign in"}),n("p",{class:"sub",children:"The studio side of Snagset. Reviewers do not sign in — they open a link."}),i&&n("p",{class:"err",children:i}),n("label",{class:"field",children:[n("span",{children:"Email"}),n("input",{type:"email",autocomplete:"username",required:!0,value:t,onInput:d=>r(d.target.value)})]}),n("label",{class:"field",children:[n("span",{children:"Password"}),n("input",{type:"password",autocomplete:"current-password",required:!0,value:s,onInput:d=>l(d.target.value)})]}),n("button",{class:"btn btn-primary",disabled:c,children:c?"Signing in…":"Sign in"}),n("p",{class:"sub",style:"margin:14px 0 0",children:["Forgotten it? There is no reset email on a fresh install — set a new one from the machine that runs the server: ",n("code",{children:"snagset passwd you@example.com"})]})]})})}function gt(){const[e,t]=b(null),[r,s]=b("loading"),[l,i]=b(null),[o,c]=b(H()),[_,d]=b(null),h=et(null),[w,a]=b(!1),[p,g]=b(null),[v,k]=b(null),y=Me(async()=>{try{const u=await I.me();t(u),s("in"),!H().project&&u.projects[0]&&(Pe({project:u.projects[0].uid}),c(H()))}catch{i(await I.claimed().catch(()=>!0)),s("out")}},[]);M(()=>{y(),fetch("/api/v1/meta").then(S=>S.json()).then(g).catch(()=>{});const u=()=>c(H());return addEventListener("popstate",u),()=>removeEventListener("popstate",u)},[y]);const f=o.project;M(()=>{if(r!=="in"||!f)return;let u=!0;return k(null),I.rounds(f).then(S=>u&&k(S.data)).catch(()=>u&&k([])),()=>{u=!1}},[r,f]);const T=o.round?Number(o.round):v?.[0]?.number??null;M(()=>{if(r!=="in"||!f||T===null)return;let u=!0;return d(null),I.threads(f,{round:T,...o.status?{status:o.status}:{},...o.q?{q:o.q}:{}}).then(S=>{u&&(d(S.data),h.current=S.serverTime)}).catch(()=>u&&d([])),()=>{u=!1}},[r,f,T,o.status,o.q]),M(()=>{if(r!=="in"||!f)return;let u=0;const S=()=>{if(document.hidden||!h.current)return;const A=Date.now();A-u<3e4||(u=A,I.threads(f,{...T===null?{}:{round:T},since:h.current,...o.status?{status:o.status}:{},...o.q?{q:o.q}:{}}).then($=>{h.current=$.serverTime,!(!$.data.length&&!$.deleted?.length)&&d(ne=>ne&&ht(ne,$.data,$.deleted))}).catch(()=>{}))};return document.addEventListener("visibilitychange",S),()=>document.removeEventListener("visibilitychange",S)},[r,f,T,o.status,o.q]);const N=pe(()=>_?.find(u=>u.key===o.thread)??null,[_,o.thread]),m=u=>{Pe(u),c(H())};if(r==="loading")return n("div",{class:"empty",children:"Loading…"});if(r==="out"&&(o.claim||l===!1))return n(pt,{token:o.claim,onClaimed:()=>void y()});if(r==="out")return n(vt,{onIn:()=>void y()});const P=async u=>{if(N){a(!0);try{const S=await I.setStatus(f,N.id,u);d(A=>A?.map($=>$.id===S.id?{...$,...S}:$)??A)}finally{a(!1)}}},R=async u=>{if(!N)return;const S=await I.addComment(N.id,u);d(A=>A?.map($=>$.id===N.id?{...$,comments:[...$.comments,S],commentCount:$.commentCount+1}:$)??A)};return n("div",{class:"shell",children:[n("header",{class:"topbar",children:[n("div",{class:"brand",children:["Snagset ",n("span",{children:"studio"})]}),n("select",{value:f,onChange:u=>m({project:u.target.value,thread:""}),children:e.projects.map(u=>n("option",{value:u.uid,children:[u.name," · ",u.unresolved," open"]},u.uid))}),v&&v.length>0&&n("select",{value:String(T??""),onChange:u=>m({round:u.target.value,thread:""}),children:v.map(u=>n("option",{value:String(u.number),children:[u.name,u.closed?" (closed)":""," · ",u.unresolved," open"]},u.id))}),n("button",{class:"linkish",title:"Start a new round. The page goes clean; nothing is deleted.",onClick:async()=>{const u=(v?.[0]?.number??0)+1,S=prompt("Name for the new round",`Round ${u}`);if(S===null)return;const A=await I.createRound(f,S).catch(()=>null);if(!A)return;const $=await I.rounds(f).catch(()=>null);$&&k($.data),m({round:String(A.number),thread:""})},children:"+ Round"}),n("button",{class:"linkish","aria-pressed":o.screen==="links",onClick:()=>m({screen:o.screen==="links"?"":"links",thread:""}),children:"Links"}),n("button",{class:"linkish","aria-pressed":o.screen==="sites",onClick:()=>m({screen:o.screen==="sites"?"":"sites",thread:""}),children:"Sites"}),n("div",{class:"spacer"}),n("span",{class:"who",children:e.user.email}),n("button",{class:"linkish",onClick:async()=>{await I.logout().catch(()=>{}),s("out")},children:"Sign out"})]}),o.screen==="sites"?n(ut,{me:e,origin:location.origin,onAdded:async u=>{const S=await I.me().catch(()=>null);S&&t(S),m({project:u,thread:""})}}):o.screen==="links"?n(dt,{uid:f,rounds:v}):n(D,{children:[v&&T!==null&&n(D,{children:v.filter(u=>u.number!==T&&u.unresolved>0).map(u=>n("button",{class:"carryover",onClick:()=>m({round:String(u.number),thread:""}),children:[n("b",{children:[u.unresolved," unresolved"]})," in ",u.name," — still open, not carried over. Go there ↗"]},u.id))}),n("div",{class:"inbox",children:[n("div",{class:"list",children:[n("div",{class:"filters",children:[n("input",{type:"search",placeholder:"Search comments",value:o.q,onInput:u=>m({q:u.target.value})}),ft.map(u=>n("button",{class:"chip","aria-pressed":o.status===u,onClick:()=>m({status:o.status===u?"":u}),children:ae[u]},u))]}),n("div",{class:"rows",children:[_===null&&n("p",{class:"empty",children:"Loading…"}),_?.length===0&&n("div",{class:"empty",children:[n("h2",{children:"Nothing here"}),n("p",{children:o.q||o.status?"No comment matches that filter.":"No comments on this project yet. Paste the script tag on the site and click something."})]}),_?.map(u=>n("button",{class:"row","aria-current":u.key===o.thread,onClick:()=>m({thread:u.key}),children:[n("div",{class:"row-top",children:[n("span",{class:"key",children:u.key}),n("span",{class:`status status-${u.status}`,children:ae[u.status]})]}),n("p",{class:"row-body",children:u.comments[0]?.body??u.anchor?.label??"(no comment)"}),n("div",{class:"row-meta",children:[n("span",{children:u.route||"/"}),n("span",{children:"·"}),n("span",{children:u.createdBy.name||"someone"}),u.attachments?.length?n("span",{children:"· 📷"}):null]})]},u.id))]})]}),N?n(ct,{thread:N,onStatus:u=>void P(u),onReply:R,busy:w}):n("div",{class:"empty",children:[n("h2",{children:"Pick a comment"}),n("p",{children:"Its screenshot, the thread, the anchor and the page context all open here."})]})]})]}),n("footer",{class:"foot",children:[n("span",{children:[e.org.name," · ",p?.version??"…"]}),p?.commit&&n("span",{children:p.commit.slice(0,8)})]})]})}Qe(n(gt,{}),document.getElementById("app"));
@@ -1 +0,0 @@
1
- :root{color-scheme:light dark;--ink: #181716;--ink-soft: #585755;--ink-faint: #6b6a68;--bg: #faf8f6;--surface: #fefdfc;--line: #e4e3e0;--line-soft: #eeecea;--line-strong: #939290;--accent: #2a51b8;--on-accent: #ffffff;--accent-soft: #e9f0ff;--warn: #9a2929;--open: #006f96;--progress: #9c542b;--review: #725ba1;--resolved: #417332;--mono: ui-monospace, "SF Mono", "JetBrains Mono", Menlo, Consolas, monospace;--sans: system-ui, -apple-system, "Segoe UI", Inter, sans-serif;--radius: 6px}@media(prefers-color-scheme:dark){:root{--ink: #f0eeec;--ink-soft: #a7a6a4;--ink-faint: #8e8c8b;--bg: #100f0e;--surface: #1d1c1a;--line: #2e2c2b;--line-soft: #242321;--line-strong: #696866;--accent: #8aafff;--on-accent: #100f0e;--accent-soft: #17223b;--warn: #ed8c84;--open: #3b9dc8;--progress: #cd8058;--review: #9e87d1;--resolved: #6ca05d}}*{box-sizing:border-box}body{margin:0;font:14px/1.5 var(--sans);color:var(--ink);background:var(--bg);-webkit-font-smoothing:antialiased}button{font:inherit;color:inherit}.shell{display:flex;flex-direction:column;height:100vh;overflow:hidden}.topbar{display:flex;align-items:center;gap:16px;padding:0 16px;height:52px;flex:none;border-bottom:1px solid var(--line);background:var(--surface)}.brand{font-weight:620;letter-spacing:-.01em;margin-inline-end:4px}.brand span{color:var(--ink-faint);font-weight:400}.topbar select{font:inherit;padding:4px 8px;border:1px solid var(--line-strong);border-radius:var(--radius);background:var(--surface);color:inherit}.spacer{flex:1}.who{color:var(--ink-soft);font-size:13px}.linkish{background:none;border:0;padding:4px 6px;color:var(--ink-soft);cursor:pointer;border-radius:var(--radius)}.linkish:hover{background:var(--line-soft);color:var(--ink)}.inbox{flex:1;display:grid;grid-template-columns:minmax(300px,380px) 1fr;min-height:0;overflow:hidden}@media(max-width:900px){.inbox{grid-template-columns:1fr}.inbox>.detail:not(.detail-open){display:none}}.list{border-inline-end:1px solid var(--line);background:var(--surface);display:flex;flex-direction:column;min-height:0}.filters{display:flex;gap:6px;padding:10px 12px;border-bottom:1px solid var(--line-soft);flex-wrap:wrap;align-items:center}.filters input[type=search]{font:inherit;flex:1;min-width:120px;padding:5px 9px;border:1px solid var(--line-strong);border-radius:var(--radius);background:var(--bg);color:inherit}.chip{font:500 12px/1 var(--sans);padding:5px 9px;border:1px solid var(--line-strong);border-radius:999px;background:transparent;color:var(--ink-soft);cursor:pointer}.chip[aria-pressed=true]{background:var(--accent-soft);border-color:transparent;color:var(--ink);font-weight:600}.rows{overflow-y:auto;flex:1}.row{display:block;width:100%;text-align:start;border:0;border-bottom:1px solid var(--line-soft);background:none;padding:11px 12px;cursor:pointer}.row:hover{background:var(--line-soft)}.row[aria-current=true]{background:var(--accent-soft);border-inline-start:3px solid var(--accent);padding-inline-start:9px}.row:focus-visible{outline:2px solid var(--accent);outline-offset:-2px}.row-top{display:flex;align-items:center;gap:8px}.key{font:600 12px/1 var(--mono);color:var(--ink-faint)}.row-body{margin:4px 0 0;display:-webkit-box;-webkit-line-clamp:2;-webkit-box-orient:vertical;overflow:hidden}.row-meta{margin-top:5px;font-size:12px;color:var(--ink-faint);display:flex;gap:8px}.status{font:600 11px/1 var(--sans);text-transform:uppercase;letter-spacing:.04em;padding:3px 7px;border-radius:999px;border:1px solid currentColor}.status-open{color:var(--open)}.status-progress{color:var(--progress)}.status-review{color:var(--review)}.status-resolved{color:var(--resolved)}.detail{overflow-y:auto;min-height:0;padding:22px 26px 60px}.detail-head{display:flex;align-items:baseline;gap:10px;flex-wrap:wrap}.detail-head h1{font:600 19px/1.3 var(--sans);margin:0;letter-spacing:-.01em}.shot{margin:18px 0;border:1px solid var(--line);border-radius:var(--radius);overflow:hidden;background:var(--surface)}.shot img{display:block;width:100%;height:auto}.shot figcaption{font:12px/1.4 var(--mono);color:var(--ink-faint);padding:7px 10px;border-top:1px solid var(--line-soft)}.no-shot{margin:18px 0;padding:22px;border:1px dashed var(--line);border-radius:var(--radius);color:var(--ink-soft);background:var(--surface)}.thread{margin:22px 0;display:flex;flex-direction:column;gap:14px}.comment{border-inline-start:2px solid var(--line);padding-inline-start:12px}.comment-head{display:flex;gap:8px;align-items:baseline;font-size:13px}.comment-head b{font-weight:600}.comment p{margin:3px 0 0;white-space:pre-wrap}.agent{font:600 10px/1 var(--sans);text-transform:uppercase;letter-spacing:.05em;padding:2px 5px;border-radius:3px;background:var(--review);color:var(--surface)}.block{margin:22px 0 0;border-top:1px solid var(--line);padding-top:14px}.block h2{font:600 11px/1 var(--sans);text-transform:uppercase;letter-spacing:.06em;color:var(--ink-faint);margin:0 0 10px}.kv{display:grid;grid-template-columns:max-content 1fr;gap:4px 14px;font-size:13px}.kv dt{color:var(--ink-soft)}.kv dd{margin:0;font-family:var(--mono);font-size:12.5px;overflow-wrap:anywhere}.warn{color:var(--warn)}.actions{display:flex;gap:8px;margin:18px 0 0;flex-wrap:wrap}.btn{font:500 13px/1 var(--sans);padding:8px 12px;border:1px solid var(--line-strong);border-radius:var(--radius);background:var(--surface);cursor:pointer}.btn:hover{border-color:var(--ink-faint)}.btn-primary{background:var(--accent);border-color:transparent;color:var(--on-accent)}.btn-primary:hover{filter:brightness(1.08)}.empty{padding:48px 26px;color:var(--ink-soft);max-width:46ch}.empty h2{font:600 16px/1.4 var(--sans);color:var(--ink);margin:0 0 6px}.gate{min-height:100vh;display:grid;place-items:center;padding:24px}.card{width:100%;max-width:360px;background:var(--surface);border:1px solid var(--line);border-radius:10px;padding:26px}.card h1{font:600 18px/1.3 var(--sans);margin:0 0 4px}.card p.sub{margin:0 0 18px;color:var(--ink-soft);font-size:13px}.field{display:block;margin-bottom:12px}.field span{display:block;font-size:12.5px;color:var(--ink-soft);margin-bottom:4px}.field input,.field textarea{font:inherit;width:100%;padding:8px 10px;border:1px solid var(--line-strong);border-radius:var(--radius);background:var(--bg);color:inherit}.field textarea{resize:vertical;min-height:60px}.field input:focus-visible,.field textarea:focus-visible{outline:2px solid var(--accent);outline-offset:1px}.composer{margin:18px 0 0;max-width:480px}.composer .field{margin-bottom:8px}.composer .btn-primary{padding:8px 14px}.card .btn-primary{width:100%;padding:10px}.err{margin:0 0 14px;padding:9px 11px;border-radius:var(--radius);background:color-mix(in srgb,var(--warn) 12%,transparent);color:var(--warn);font-size:13px}.foot{flex:none;border-top:1px solid var(--line);padding:10px 16px;font:12px/1.4 var(--mono);color:var(--ink-faint);display:flex;gap:12px;flex-wrap:wrap}.carryover{display:block;width:100%;text-align:start;flex:none;border:0;border-bottom:1px solid color-mix(in srgb,var(--warn) 35%,transparent);background:color-mix(in srgb,var(--warn) 12%,transparent);color:var(--warn);font:inherit;padding:9px 16px;cursor:pointer}.carryover:hover{background:color-mix(in srgb,var(--warn) 20%,transparent)}.links{flex:1;display:grid;grid-template-columns:1fr minmax(300px,380px);gap:0;min-height:0;overflow:hidden}@media(max-width:900px){.links{grid-template-columns:1fr;overflow-y:auto}}.links-list{padding:22px 26px;overflow-y:auto;min-height:0}.links-title{font:600 19px/1.3 var(--sans);margin:0 0 16px;letter-spacing:-.01em}.links-side{border-inline-start:1px solid var(--line);background:var(--surface);padding:22px;overflow-y:auto;min-height:0;display:flex;flex-direction:column;gap:16px}.links-side .card{max-width:none;padding:20px}.links-side .card h2{font:600 15px/1.3 var(--sans);margin:0 0 4px}.links-side .card p.sub{margin:0 0 14px;color:var(--ink-soft);font-size:13px}.link-table{width:100%;border-collapse:collapse;font-size:13px}.link-table th{text-align:start;font:600 11px/1 var(--sans);text-transform:uppercase;letter-spacing:.05em;color:var(--ink-faint);padding:0 10px 8px 0;border-bottom:1px solid var(--line)}.link-table td{padding:10px 10px 10px 0;border-bottom:1px solid var(--line-soft);vertical-align:top}.link-table tr.link-dead{color:var(--ink-faint)}.link-round{display:inline-block;margin-inline-start:6px;font-size:11px;color:var(--ink-faint);border:1px solid var(--line);border-radius:999px;padding:1px 7px}.minted{border-color:var(--accent)}.token-box{display:flex;align-items:center;gap:8px;padding:9px 11px;border:1px solid var(--line);border-radius:var(--radius);background:var(--bg)}.token-box code{flex:1;font:12.5px/1.4 var(--mono);overflow-wrap:anywhere}.field select{font:inherit;width:100%;padding:8px 10px;border:1px solid var(--line-strong);border-radius:var(--radius);background:var(--bg);color:inherit}.sites{max-width:720px;margin:0 auto;padding:24px 20px 64px;display:flex;flex-direction:column;gap:28px}.sites h2{font-size:15px;margin:0 0 12px}.sites h3{font-size:13px;margin:20px 0 8px;color:var(--ink-soft)}.sites form{display:flex;flex-direction:column;gap:14px}.sites label{display:flex;flex-direction:column;gap:5px;font-size:13px;color:var(--ink-soft)}.sites input{font:inherit;padding:8px 10px;border:1px solid var(--line-strong);border-radius:var(--radius);background:var(--bg);color:inherit}.sites input:focus-visible{outline:2px solid var(--accent);outline-offset:1px}.sites small{color:var(--ink-faint);font-size:12px;line-height:1.5}.sites small code{font:11.5px/1 var(--mono)}.sites button[type=submit]{align-self:flex-start;font:inherit;padding:8px 14px;border:1px solid var(--accent);border-radius:var(--radius);background:var(--accent);color:var(--on-accent);cursor:pointer}.sites button[type=submit]:disabled{opacity:.45;cursor:default}.sites .error{color:var(--warn);font-size:13px;margin:0}.site-add,.site-made,.site-list{border:1px solid var(--line);border-radius:var(--radius);background:var(--surface);padding:18px 20px}.site-made{border-color:var(--accent)}.site-made p{font-size:13px;color:var(--ink-soft);margin:0 0 10px}.site-made pre{margin:0 0 8px;padding:11px 12px;border:1px solid var(--line);border-radius:var(--radius);background:var(--bg);overflow-x:auto}.site-made pre code{font:12.5px/1.5 var(--mono);white-space:pre}.site-made form{flex-direction:row;align-items:center;gap:8px;margin-top:10px}.site-made form input{flex:1}.site-made form button{font:inherit;padding:8px 12px;border:1px solid var(--line);border-radius:var(--radius);background:var(--bg);color:inherit;cursor:pointer}.origins{list-style:none;margin:0;padding:0;display:flex;flex-wrap:wrap;gap:6px}.origins li code{font:11.5px/1 var(--mono);padding:4px 8px;border:1px solid var(--line);border-radius:999px;background:var(--bg)}.site-list ul{list-style:none;margin:0;padding:0}.site-list li{display:flex;align-items:baseline;gap:10px;padding:9px 0;border-bottom:1px solid var(--line-soft);font-size:13px}.site-list li:last-child{border-bottom:0}.site-list li code{font:11.5px/1 var(--mono);color:var(--ink-faint)}.site-list li span{margin-left:auto;color:var(--ink-faint);font-size:12px}.setup{max-width:460px;margin:0 auto;padding:56px 24px 64px}.setup h1{font-size:20px;margin:0 0 8px}.setup-lede{color:var(--ink-soft);font-size:13px;line-height:1.6;margin:0 0 24px}.setup form{display:flex;flex-direction:column;gap:16px}.setup label{display:flex;flex-direction:column;gap:5px;font-size:13px;color:var(--ink-soft)}.setup-opt{color:var(--ink-faint);font-weight:400}.setup input{font:inherit;padding:9px 11px;border:1px solid var(--line-strong);border-radius:var(--radius);background:var(--bg);color:inherit}.setup input:focus-visible{outline:2px solid var(--accent);outline-offset:1px}.setup small{color:var(--ink-faint);font-size:12px;line-height:1.5}.setup button[type=submit],.setup-actions button:not(.linkish){font:inherit;padding:9px 14px;border:1px solid var(--accent);border-radius:var(--radius);background:var(--accent);color:var(--on-accent);cursor:pointer}.setup button[type=submit]:disabled{opacity:.45;cursor:default}.setup .error{color:var(--warn);font-size:13px;margin:0}.setup pre{margin:0 0 12px;padding:11px 12px;border:1px solid var(--line);border-radius:var(--radius);background:var(--bg);overflow-x:auto}.setup pre code{font:12.5px/1.5 var(--mono);white-space:pre}.setup-actions{display:flex;align-items:center;gap:12px}.setup-note{color:var(--ink-faint);font-size:12.5px;line-height:1.6;margin:24px 0 0}.site-audience{display:flex;flex-direction:column;gap:8px;margin:0 0 12px}.site-audience label{display:flex;gap:9px;align-items:baseline;font-size:12.5px;color:var(--ink-soft);line-height:1.5;cursor:pointer}.site-audience input{accent-color:var(--accent)}.site-audience strong{color:var(--ink);font-weight:600}