@01.works/visual-review 0.8.2 → 0.8.4

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.
@@ -0,0 +1,141 @@
1
+ function e(e,r,i,a){let o=e.shadowRoot??e.attachShadow({mode:`open`}),s=o.ownerDocument;e.dataset.vrTheme=t(s);let c=s.createElement(`style`);i&&(c.nonce=i),c.textContent=n;let l=s.createElement(`strong`);l.id=`visual-review-bootstrap-error-title`,l.textContent=`Visual Review를 시작할 수 없습니다`;let u=s.createElement(`span`);u.id=`visual-review-bootstrap-error-description`,u.textContent=r;let d=s.createElement(`span`);d.className=`bootstrap-error-mark`,d.setAttribute(`aria-hidden`,`true`);let f=s.createElement(`span`);f.className=`bootstrap-error-copy`,f.append(l,u);let p=s.createElement(`span`);p.className=`bootstrap-error-content`,p.append(d,f);let m=s.createElement(`button`);m.type=`button`,m.className=`bootstrap-error-retry`,m.textContent=`다시 시도`,a&&m.addEventListener(`click`,()=>{m.disabled=!0,m.textContent=`다시 시도 중…`,g.setAttribute(`aria-busy`,`true`),a()},{once:!0});let h=s.createElement(`button`);h.type=`button`,h.className=`bootstrap-error-dismiss`,h.setAttribute(`aria-label`,`Visual Review 알림 닫기`),h.textContent=`×`,h.addEventListener(`click`,()=>e.remove(),{once:!0});let g=s.createElement(`div`);g.className=`bootstrap-error`,g.setAttribute(`role`,`alert`),g.setAttribute(`aria-labelledby`,l.id),g.setAttribute(`aria-describedby`,u.id),g.append(p),a&&g.append(m),g.append(h),o.replaceChildren(c,g)}function t(e){let t=e.defaultView;if(!t)return`light`;for(let n of[e.body,e.documentElement]){if(!n)continue;let e=t.getComputedStyle(n).backgroundColor.match(/[\d.]+/g)?.map(Number);if(!e||e.length<3)continue;let[r=0,i=0,a=0,o=1]=e;if(!(o<.5))return(r*.2126+i*.7152+a*.0722)/255<.45?`light`:`dark`}return t.matchMedia?.(`(prefers-color-scheme: dark)`).matches??!1?`light`:`dark`}const n=`
2
+ :host {
3
+ all: initial;
4
+ position: fixed;
5
+ right: max(16px, env(safe-area-inset-right));
6
+ bottom: max(16px, env(safe-area-inset-bottom));
7
+ z-index: 2147483646;
8
+ display: block;
9
+ width: min(320px, calc(100vw - 32px));
10
+ }
11
+ .bootstrap-error {
12
+ all: initial;
13
+ --vr-panel: #ffffff;
14
+ --vr-text: #171717;
15
+ --vr-muted: #737373;
16
+ --vr-surface-hover: rgba(0, 0, 0, .05);
17
+ --vr-error: #b42318;
18
+ --vr-error-surface: rgba(180, 35, 24, .12);
19
+ --vr-shadow: 0 2px 12px rgba(0, 0, 0, .1);
20
+ box-sizing: border-box;
21
+ position: relative;
22
+ display: block;
23
+ width: 100%;
24
+ padding: 12px 40px 12px 12px;
25
+ border: 0;
26
+ border-radius: 14px;
27
+ corner-shape: superellipse(1.25);
28
+ color: var(--vr-text);
29
+ background: var(--vr-panel);
30
+ box-shadow: var(--vr-shadow);
31
+ color-scheme: light;
32
+ font: 500 13px/16px Geist, ui-sans-serif, system-ui, sans-serif;
33
+ font-synthesis: none;
34
+ overflow-wrap: anywhere;
35
+ animation: vr-bootstrap-error-enter 180ms cubic-bezier(.32,.72,0,1) both;
36
+ }
37
+ :host([data-vr-theme="dark"]) .bootstrap-error {
38
+ --vr-panel: #161616;
39
+ --vr-text: #ffffff;
40
+ --vr-muted: #a7a7a7;
41
+ --vr-surface-hover: rgba(255, 255, 255, .1);
42
+ --vr-error: #ff8a80;
43
+ --vr-error-surface: rgba(255, 138, 128, .14);
44
+ --vr-shadow: 0 2px 8px rgba(0, 0, 0, .18);
45
+ color-scheme: dark;
46
+ }
47
+ .bootstrap-error-content {
48
+ all: unset;
49
+ display: grid;
50
+ grid-template-columns: 10px minmax(0, 1fr);
51
+ align-items: start;
52
+ gap: 8px;
53
+ }
54
+ .bootstrap-error-mark {
55
+ all: unset;
56
+ display: block;
57
+ width: 6px;
58
+ height: 6px;
59
+ margin-top: 5px;
60
+ border-radius: 50%;
61
+ background: var(--vr-error);
62
+ box-shadow: 0 0 0 3px var(--vr-error-surface);
63
+ }
64
+ .bootstrap-error-copy {
65
+ all: unset;
66
+ display: block;
67
+ min-width: 0;
68
+ }
69
+ .bootstrap-error strong {
70
+ display: block;
71
+ margin: 0 0 2px;
72
+ color: var(--vr-text);
73
+ font: 600 12px/16px Geist, ui-sans-serif, system-ui, sans-serif;
74
+ }
75
+ .bootstrap-error-copy > span {
76
+ display: block;
77
+ color: var(--vr-muted);
78
+ font: 500 11px/16px Geist, ui-sans-serif, system-ui, sans-serif;
79
+ }
80
+ .bootstrap-error button {
81
+ all: unset;
82
+ box-sizing: border-box;
83
+ cursor: pointer;
84
+ -webkit-tap-highlight-color: transparent;
85
+ }
86
+ .bootstrap-error .bootstrap-error-retry {
87
+ display: inline-flex;
88
+ align-items: center;
89
+ justify-content: center;
90
+ min-height: 28px;
91
+ margin: 8px 0 0 18px;
92
+ padding: 0 8px;
93
+ border-radius: 7px;
94
+ color: var(--vr-text);
95
+ background: var(--vr-surface-hover);
96
+ font: 600 11px/14px Geist, ui-sans-serif, system-ui, sans-serif;
97
+ transition: background 150ms ease-out, transform 300ms cubic-bezier(.34,1.56,.64,1);
98
+ }
99
+ .bootstrap-error .bootstrap-error-dismiss {
100
+ position: absolute;
101
+ top: 4px;
102
+ right: 4px;
103
+ display: grid;
104
+ place-items: center;
105
+ width: 32px;
106
+ height: 32px;
107
+ border-radius: 8px;
108
+ color: var(--vr-muted);
109
+ font: 400 18px/1 Geist, ui-sans-serif, system-ui, sans-serif;
110
+ transition: color 150ms ease-out, background 150ms ease-out, transform 300ms cubic-bezier(.34,1.56,.64,1);
111
+ }
112
+ .bootstrap-error button:focus-visible {
113
+ outline: 2px solid var(--vr-error);
114
+ outline-offset: 2px;
115
+ }
116
+ .bootstrap-error button:active { transform: scale(.96); transition-duration: 60ms; }
117
+ .bootstrap-error button:disabled { opacity: .5; cursor: wait; }
118
+ @media (hover: hover) and (pointer: fine) {
119
+ .bootstrap-error .bootstrap-error-retry:hover,
120
+ .bootstrap-error .bootstrap-error-dismiss:hover { background: var(--vr-surface-hover); }
121
+ .bootstrap-error .bootstrap-error-dismiss:hover { color: var(--vr-text); }
122
+ }
123
+ @media (pointer: coarse) {
124
+ .bootstrap-error .bootstrap-error-retry { min-height: 36px; padding-inline: 12px; }
125
+ .bootstrap-error .bootstrap-error-dismiss { width: 40px; height: 40px; }
126
+ }
127
+ @media (max-width: 480px) {
128
+ :host {
129
+ right: max(8px, env(safe-area-inset-right));
130
+ bottom: max(8px, env(safe-area-inset-bottom));
131
+ width: min(320px, calc(100vw - 16px));
132
+ }
133
+ }
134
+ @media (prefers-reduced-motion: reduce) {
135
+ .bootstrap-error, .bootstrap-error * { animation: none !important; transition: none !important; }
136
+ }
137
+ @keyframes vr-bootstrap-error-enter {
138
+ from { opacity: 0; transform: translateY(4px) scale(.985); }
139
+ to { opacity: 1; transform: translateY(0) scale(1); }
140
+ }
141
+ `;export{e as renderBootstrapError};
@@ -1,4 +1,4 @@
1
- import{r as e}from"./install-DvwZzCFL.js";import{t}from"./embedded-source-e0DrdxU8.js";import{i as n,init as r}from"@instantdb/core";const i=n.schema({entities:{$files:n.entity({path:n.string().unique().indexed(),url:n.string()}),$users:n.entity({email:n.string().unique().indexed()}),projects:n.entity({name:n.string(),slug:n.string().unique().indexed(),allowedOrigin:n.string().optional(),originDisconnectedAt:n.number().optional(),createdAt:n.number().indexed(),updatedAt:n.number()}),reviewPages:n.entity({projectId:n.string().indexed(),autoRegistrationSlot:n.string().unique().indexed().optional(),name:n.string(),pathname:n.string(),stagingOrigin:n.string(),createdAt:n.number().indexed(),updatedAt:n.number()}),reviewPageBuilds:n.entity({projectId:n.string().indexed(),pageId:n.string().unique().indexed(),buildId:n.string(),gitCommit:n.string().optional(),generatedAt:n.number().optional(),mode:n.string(),updatedAt:n.number().indexed()}),reviewers:n.entity({authUserId:n.string().indexed(),projectId:n.string().indexed(),email:n.string().indexed(),displayName:n.string(),role:n.string(),createdAt:n.number()}),reviewerIdentityClaims:n.entity({reviewerId:n.string().unique().indexed(),projectId:n.string().indexed(),authUserId:n.string().indexed(),email:n.string(),displayName:n.string(),role:n.string(),createdAt:n.number()}),invitations:n.entity({projectId:n.string().indexed(),reviewerId:n.string().indexed().optional(),email:n.string().indexed(),status:n.string().indexed(),claimRevision:n.number(),claimedByAuthUserId:n.string().indexed().optional(),expiresAt:n.number().indexed(),createdAt:n.number(),acceptedAt:n.number().optional(),revokedAt:n.number().optional()}),comments:n.entity({pageId:n.string().indexed(),authorId:n.string().indexed(),authorAuthUserId:n.string().indexed(),authorName:n.string(),body:n.string(),bodyContentMarker:n.string().optional(),anchorSelector:n.string().optional(),anchorOffsetX:n.number().optional(),anchorOffsetY:n.number().optional(),anchorViewportX:n.number().optional(),anchorViewportY:n.number().optional(),targetKind:n.string().optional(),targetPageX:n.number().optional(),targetPageY:n.number().optional(),targetWidth:n.number().optional(),targetHeight:n.number().optional(),targetViewportX:n.number().optional(),targetViewportY:n.number().optional(),targetViewportWidth:n.number().optional(),targetViewportHeight:n.number().optional(),targetPageOrigin:n.string().optional(),targetPagePathname:n.string().optional(),targetPageSearch:n.string().optional(),targetPageHash:n.string().optional(),targetPageTitle:n.string().optional(),targetCapturedAt:n.number().optional(),status:n.string().indexed(),workflowRevision:n.number(),createdAt:n.number().indexed(),updatedAt:n.number().indexed(),resolvedAt:n.number().optional(),resolvedById:n.string().optional()}),commentWorkflowClaims:n.entity({claimKey:n.string().unique().indexed(),commentId:n.string().indexed(),expectedWorkflowRevision:n.number(),createdAt:n.number().indexed()}),commentTargetElements:n.entity({commentId:n.string().indexed(),slotKey:n.string().unique().indexed().optional(),ordinal:n.number(),selector:n.string(),tagName:n.string(),textPreview:n.string(),pageX:n.number(),pageY:n.number(),width:n.number(),height:n.number(),viewportX:n.number(),viewportY:n.number(),viewportWidth:n.number(),viewportHeight:n.number(),authorAuthUserId:n.string().indexed()}),commentScopeEntries:n.entity({commentId:n.string().indexed(),slotKey:n.string().unique().indexed().optional(),ordinal:n.number(),key:n.string(),valueType:n.string(),stringValue:n.string().optional(),numberValue:n.number().optional(),booleanValue:n.boolean().optional(),authorAuthUserId:n.string().indexed()}),commentSourceContexts:n.entity({commentId:n.string().unique().indexed(),pageId:n.string().indexed(),authorAuthUserId:n.string().indexed(),contextJson:n.string(),createdAt:n.number().indexed()}),replies:n.entity({pageId:n.string().indexed(),commentId:n.string().indexed(),authorId:n.string().indexed(),authorAuthUserId:n.string().indexed(),authorName:n.string(),body:n.string(),bodyContentMarker:n.string().optional(),createdAt:n.number().indexed(),updatedAt:n.number().indexed()}),reviewMessages:n.entity({pageId:n.string().indexed(),pathname:n.string().indexed(),authorId:n.string().indexed(),authorAuthUserId:n.string().indexed(),authorName:n.string(),body:n.string(),bodyContentMarker:n.string(),createdAt:n.number().indexed(),updatedAt:n.number().indexed()})},links:{projectOwners:{forward:{on:`projects`,has:`many`,label:`owners`},reverse:{on:`$users`,has:`many`,label:`ownedProjects`}},projectPages:{forward:{on:`projects`,has:`many`,label:`pages`},reverse:{on:`reviewPages`,has:`one`,label:`project`}},pageCurrentBuild:{forward:{on:`reviewPageBuilds`,has:`one`,label:`page`,required:!0,onDelete:`cascade`},reverse:{on:`reviewPages`,has:`one`,label:`currentBuild`}},projectReviewers:{forward:{on:`projects`,has:`many`,label:`reviewers`},reverse:{on:`reviewers`,has:`one`,label:`project`}},reviewerUser:{forward:{on:`reviewers`,has:`one`,label:`$user`},reverse:{on:`$users`,has:`many`,label:`reviewerMemberships`}},projectInvitations:{forward:{on:`projects`,has:`many`,label:`invitations`},reverse:{on:`invitations`,has:`one`,label:`project`}},invitationReviewer:{forward:{on:`invitations`,has:`one`,label:`reviewer`},reverse:{on:`reviewers`,has:`many`,label:`acceptedInvitations`}},invitationActiveUser:{forward:{on:`invitations`,has:`one`,label:`activeUser`},reverse:{on:`$users`,has:`one`,label:`activeReviewInvitation`}},pageComments:{forward:{on:`reviewPages`,has:`many`,label:`comments`},reverse:{on:`comments`,has:`one`,label:`page`}},pageReviewMessages:{forward:{on:`reviewPages`,has:`many`,label:`reviewMessages`},reverse:{on:`reviewMessages`,has:`one`,label:`page`}},commentReplies:{forward:{on:`comments`,has:`many`,label:`replies`},reverse:{on:`replies`,has:`one`,label:`comment`}},commentTargetElements:{forward:{on:`commentTargetElements`,has:`one`,label:`comment`,required:!0,onDelete:`cascade`},reverse:{on:`comments`,has:`many`,label:`targetElements`}},commentScopeEntries:{forward:{on:`commentScopeEntries`,has:`one`,label:`comment`,required:!0,onDelete:`cascade`},reverse:{on:`comments`,has:`many`,label:`scopeEntries`}},commentSourceContext:{forward:{on:`commentSourceContexts`,has:`one`,label:`comment`,required:!0,onDelete:`cascade`},reverse:{on:`comments`,has:`one`,label:`sourceContext`}},pageSourceContexts:{forward:{on:`commentSourceContexts`,has:`one`,label:`page`,required:!0},reverse:{on:`reviewPages`,has:`many`,label:`sourceContexts`}},sourceContextAuthor:{forward:{on:`commentSourceContexts`,has:`one`,label:`author`,required:!0},reverse:{on:`reviewers`,has:`many`,label:`sourceContexts`}},commentAuthor:{forward:{on:`comments`,has:`one`,label:`author`},reverse:{on:`reviewers`,has:`many`,label:`comments`}},replyAuthor:{forward:{on:`replies`,has:`one`,label:`author`},reverse:{on:`reviewers`,has:`many`,label:`replies`}},reviewMessageAuthor:{forward:{on:`reviewMessages`,has:`one`,label:`author`},reverse:{on:`reviewers`,has:`many`,label:`reviewMessages`}}},rooms:{visualReview:{presence:n.entity({reviewerId:n.string(),displayName:n.string(),color:n.string(),active:n.boolean(),cursorX:n.number().optional(),cursorY:n.number().optional(),viewportWidth:n.number().optional(),viewportHeight:n.number().optional()})}}}),a=new Uint8Array([107,167,184,17,157,173,17,209,128,180,0,192,79,212,48,200]);function o(e,t,n){return u(e,n),`${e}:${t}:${n}`}async function s(e,t,n){return l(o(e,t,n))}async function c(e){if(!e.trim())throw Error(`Comment ID is required for source context`);return l(`${e}:source-context`)}async function l(e){let t=globalThis.crypto?.subtle;if(!t)throw Error(`Web Crypto is required to persist review capture context`);let n=new TextEncoder().encode(`01works.visual-review/v1/${e}`),r=new Uint8Array(a.length+n.length);r.set(a),r.set(n,a.length);let i=new Uint8Array(await t.digest(`SHA-1`,r)).slice(0,16);i[6]=i[6]&15|80,i[8]=i[8]&63|128;let o=[...i].map(e=>e.toString(16).padStart(2,`0`)).join(``);return`${o.slice(0,8)}-${o.slice(8,12)}-${o.slice(12,16)}-${o.slice(16,20)}-${o.slice(20)}`}function u(e,t){if(!e.trim())throw Error(`Comment ID is required for capture context`);if(!Number.isSafeInteger(t)||t<0)throw Error(`Capture child ordinal must be a non-negative integer`)}const d=131072,f=32768,p=4096,m=1e3;var h=class extends Error{constructor(e,t){super(e,t),this.name=`InstantCaptureIntegrityError`}};function g(e){let t=se(e,`comment target`,!0),n={kind:t.kind,anchor:pe(t.anchor),region:ge(t.region),elements:t.elements.map(e=>({selector:e.selector,tagName:e.tagName,textPreview:e.textPreview,rect:ge(e.rect),source:null,componentStack:[]})),pageUrl:t.pageUrl,pageTitle:t.pageTitle,capturedAt:t.capturedAt},r={elements:t.elements.map(e=>({selector:e.selector,source:e.source?_e(e.source):null,componentStack:e.componentStack.map(_e)})),...t.sourceProvenance?{sourceProvenance:ve(t.sourceProvenance)}:{}};E(n,d,`Public target`);let i=Te(r,65536,`Source context`);return{publicTarget:n,commentFields:te(n),targetElements:n.elements.map(ne),sourceContextJson:i}}function ee(e,t,n){let r=x(e,n),i={selector:S(r.anchorSelector,`${n} anchor selector`,p),offsetX:T(r.anchorOffsetX,`${n} anchor offsetX`),offsetY:T(r.anchorOffsetY,`${n} anchor offsetY`),viewportX:T(r.anchorViewportX,`${n} anchor viewportX`),viewportY:T(r.anchorViewportY,`${n} anchor viewportY`)},a=ie({kind:r.targetKind,anchor:i,region:{pageX:r.targetPageX,pageY:r.targetPageY,width:r.targetWidth,height:r.targetHeight,viewportX:r.targetViewportX,viewportY:r.targetViewportY,viewportWidth:r.targetViewportWidth,viewportHeight:r.targetViewportHeight},elements:[],pageUrl:he({origin:C(r.targetPageOrigin,`${n} page origin`,1024),pathname:C(r.targetPagePathname,`${n} page pathname`,4096),search:S(r.targetPageSearch,`${n} page search`,1024),hash:S(r.targetPageHash,`${n} page hash`,1024)}),pageTitle:r.targetPageTitle,capturedAt:r.targetCapturedAt},n),o=re(t,`${n} elements`),s=a;for(let e of o)try{s=ie({...a,elements:[...s.elements,e]},n)}catch{}return s}function _(e){let t=oe(e);return t?Object.entries(t).map(([e,t],n)=>typeof t==`string`?{ordinal:n,key:e,valueType:`string`,stringValue:t}:typeof t==`number`?{ordinal:n,key:e,valueType:`number`,numberValue:t}:typeof t==`boolean`?{ordinal:n,key:e,valueType:`boolean`,booleanValue:t}:{ordinal:n,key:e,valueType:`null`}):[]}function v(e){if(!Array.isArray(e)||e.length===0)return;let t=[...e].map(e=>{try{let t=x(e,`Comment scope entry`);return{row:t,ordinal:xe(t.ordinal,`Comment scope entry ordinal`,0,19),id:typeof t.id==`string`?t.id:``}}catch{return null}}).filter(e=>e!==null).sort((e,t)=>e.ordinal-t.ordinal||e.id.localeCompare(t.id)),n={},r=new Set;for(let{row:e,ordinal:i}of t)if(!r.has(i)){r.add(i);try{let t=C(e.key,`Comment scope key`,256);if(Object.hasOwn(n,t))continue;switch(e.valueType){case`string`:n[t]=S(e.stringValue,`Comment scope ${t}`,m);break;case`number`:n[t]=w(e.numberValue,`Comment scope ${t}`);break;case`boolean`:if(typeof e.booleanValue!=`boolean`)throw D(`Comment scope ${t} is invalid`);n[t]=e.booleanValue;break;case`null`:n[t]=null;break;default:throw D(`Comment scope ${t} is invalid`)}}catch{}}if(Object.keys(n).length!==0)try{return E(n,f,`Comment scope`),n}catch{return}}function te(e){let t=new URL(e.pageUrl);return{anchorSelector:e.anchor.selector,anchorOffsetX:e.anchor.offsetX,anchorOffsetY:e.anchor.offsetY,anchorViewportX:e.anchor.viewportX,anchorViewportY:e.anchor.viewportY,targetKind:e.kind,targetPageX:e.region.pageX,targetPageY:e.region.pageY,targetWidth:e.region.width,targetHeight:e.region.height,targetViewportX:e.region.viewportX,targetViewportY:e.region.viewportY,targetViewportWidth:e.region.viewportWidth,targetViewportHeight:e.region.viewportHeight,targetPageOrigin:t.origin,targetPagePathname:me(t.pathname),targetPageSearch:t.search.slice(1),targetPageHash:t.hash.slice(1),targetPageTitle:e.pageTitle,targetCapturedAt:e.capturedAt}}function ne(e,t){return{ordinal:t,selector:e.selector,tagName:e.tagName,textPreview:e.textPreview,pageX:e.rect.pageX,pageY:e.rect.pageY,width:e.rect.width,height:e.rect.height,viewportX:e.rect.viewportX,viewportY:e.rect.viewportY,viewportWidth:e.rect.viewportWidth,viewportHeight:e.rect.viewportHeight}}function re(e,t){if(!Array.isArray(e)||e.length===0)return[];let n=[...e].map(e=>{try{let n=x(e,t);return{row:n,ordinal:xe(n.ordinal,`${t} ordinal`,0,7),id:typeof n.id==`string`?n.id:``}}catch{return null}}).filter(e=>e!==null).sort((e,t)=>e.ordinal-t.ordinal||e.id.localeCompare(t.id)),r=[],i=new Set;for(let{row:e,ordinal:a}of n)if(!i.has(a)){i.add(a);try{r.push(ce({selector:e.selector,tagName:e.tagName,textPreview:e.textPreview,rect:{pageX:e.pageX,pageY:e.pageY,width:e.width,height:e.height,viewportX:e.viewportX,viewportY:e.viewportY,viewportWidth:e.viewportWidth,viewportHeight:e.viewportHeight},source:null,componentStack:[]},`${t}[${a}]`,!1))}catch{}}return r}function ie(e,t){return se(e,t,!1)}function y(e,t=`Comment body`){return C(e,t,2e4)}function ae(e,t=`Comment body`){let n=y(e,t);for(let e of n)if(e.trim())return e;throw D(`${t} is empty`)}function oe(e){if(e==null)return;let t=x(e,`Comment scope`);if(Object.keys(t).length>20)throw D(`Comment scope has too many fields`);let n={};for(let[e,r]of Object.entries(t)){if(!e.trim()||e.length>256)throw D(`Comment scope has an invalid key`);if(typeof r==`string`){if(r.length>m)throw D(`Comment scope ${e} is too long`);n[e]=r}else if(typeof r==`number`)n[e]=w(r,`Comment scope ${e}`);else if(typeof r==`boolean`||r===null)n[e]=r;else throw D(`Comment scope ${e} is invalid`)}return E(n,f,`Comment scope`),n}function se(e,t,n){let r=b(e,t,[`kind`,`anchor`,`region`,`elements`,`pageUrl`,`pageTitle`,`capturedAt`,`sourceProvenance`],[`sourceProvenance`]),i=r.kind;if(i!==`element`&&i!==`region`&&i!==`viewport`)throw D(`${t} kind is invalid`);let a=ye(r.elements,`${t} elements`);if(a.length>8)throw D(`${t} contains too many elements`);if(!n&&r.sourceProvenance!=null)throw D(`${t} exposes source provenance`);let o=C(r.pageUrl,`${t} pageUrl`,8192);we(o,`${t} pageUrl`);let s={kind:i,anchor:le(r.anchor,`${t} anchor`),region:ue(r.region,`${t} region`),elements:a.map((e,r)=>ce(e,`${t} elements[${r}]`,n)),pageUrl:o,pageTitle:S(r.pageTitle,`${t} pageTitle`,m),capturedAt:Se(r.capturedAt,`${t} capturedAt`),...n&&r.sourceProvenance!=null?{sourceProvenance:fe(r.sourceProvenance,`${t} provenance`)}:{}};return E(s,n?196608:d,t),s}function ce(e,t,n){let r=b(e,t,[`selector`,`tagName`,`textPreview`,`rect`,`source`,`componentStack`]),i=ye(r.componentStack,`${t} componentStack`);if(i.length>32)throw D(`${t} componentStack is too large`);if(!n&&(r.source!=null||i.length>0))throw D(`${t} exposes source metadata`);return{selector:C(r.selector,`${t} selector`,p),tagName:C(r.tagName,`${t} tagName`,128),textPreview:S(r.textPreview,`${t} textPreview`,m),rect:ue(r.rect,`${t} rect`),source:n&&r.source!=null?de(r.source,`${t} source`):null,componentStack:n?i.map((e,n)=>de(e,`${t} stack[${n}]`)):[]}}function le(e,t){let n=b(e,t,[`selector`,`offsetX`,`offsetY`,`viewportX`,`viewportY`]);return{selector:S(n.selector,`${t} selector`,p),offsetX:T(n.offsetX,`${t} offsetX`),offsetY:T(n.offsetY,`${t} offsetY`),viewportX:T(n.viewportX,`${t} viewportX`),viewportY:T(n.viewportY,`${t} viewportY`)}}function ue(e,t){let n=b(e,t,[`pageX`,`pageY`,`width`,`height`,`viewportX`,`viewportY`,`viewportWidth`,`viewportHeight`]),r={pageX:w(n.pageX,`${t} pageX`),pageY:w(n.pageY,`${t} pageY`),width:w(n.width,`${t} width`),height:w(n.height,`${t} height`),viewportX:w(n.viewportX,`${t} viewportX`),viewportY:w(n.viewportY,`${t} viewportY`),viewportWidth:w(n.viewportWidth,`${t} viewportWidth`),viewportHeight:w(n.viewportHeight,`${t} viewportHeight`)};if(r.width<0||r.height<0||r.viewportWidth<0||r.viewportHeight<0)throw D(`${t} has a negative dimension`);return r}function de(e,n){let r=b(e,n,[`filePath`,`lineNumber`,`columnNumber`,`componentName`,`origin`,`generated`],[`generated`]),i=r.origin;if(i!==`app`&&i!==`shared-ui`&&i!==`dependency`&&i!==`generated`&&i!==`unknown`)throw D(`${n} origin is invalid`);let a=C(r.filePath,`${n} filePath`,p);return{filePath:a,lineNumber:Ce(r.lineNumber,`${n} lineNumber`),columnNumber:Ce(r.columnNumber,`${n} columnNumber`),componentName:r.componentName==null?null:C(r.componentName,`${n} componentName`,512),origin:t(a)}}function fe(e,t){let n=b(e,t,[`provider`,`build`,`resolvedAt`]),r=n.provider;if(r!==`react-grab`&&r!==`embedded`&&r!==`custom`)throw D(`${t} provider is invalid`);let i=b(n.build,`${t} build`,[`buildId`,`gitCommit`,`generatedAt`,`mode`],[`generatedAt`]),a=i.mode;if(a!==`development`&&a!==`preview`&&a!==`production`)throw D(`${t} build mode is invalid`);return{provider:r,build:{buildId:C(i.buildId,`${t} buildId`,512),gitCommit:i.gitCommit==null?null:C(i.gitCommit,`${t} gitCommit`,256),...i.generatedAt==null?{}:{generatedAt:Se(i.generatedAt,`${t} generatedAt`)},mode:a},resolvedAt:Se(n.resolvedAt,`${t} resolvedAt`)}}function pe(e){return{...e}}function me(e){return e.replace(/\/+$/,``)||`/`}function he(e){return`${e.origin}${e.pathname}${e.search?`?${e.search}`:``}${e.hash?`#${e.hash}`:``}`}function ge(e){return{...e}}function _e(e){return{...e}}function ve(e){return{...e,build:{...e.build}}}function b(e,t,n,r=[]){let i=x(e,t);if(Object.keys(i).some(e=>!n.includes(e)))throw D(`${t} contains unknown fields`);for(let e of n)if(!r.includes(e)&&!Object.hasOwn(i,e))throw D(`${t} is missing ${e}`);return i}function x(e,t){if(!e||typeof e!=`object`||Array.isArray(e))throw D(`${t} is missing or invalid`);return e}function ye(e,t){if(!Array.isArray(e))throw D(`${t} is missing or invalid`);return e}function S(e,t,n){if(typeof e!=`string`||be(e,n)>n)throw D(`${t} is invalid or too long`);return e}function be(e,t){let n=0;for(let r of e)if(n+=1,n>t)return n;return n}function C(e,t,n){let r=S(e,t,n);if(!r.trim())throw D(`${t} is empty`);return r}function w(e,t){if(typeof e!=`number`||!Number.isFinite(e))throw D(`${t} is invalid`);return e}function xe(e,t,n,r){if(typeof e!=`number`||!Number.isSafeInteger(e)||e<n||e>r)throw D(`${t} is invalid`);return e}function T(e,t){let n=w(e,t);if(n<0||n>1)throw D(`${t} is outside 0..1`);return n}function Se(e,t){if(typeof e!=`number`||!Number.isSafeInteger(e)||e<0||e>0xe677d21fdbff)throw D(`${t} is invalid`);return e}function Ce(e,t){if(e===null)return null;if(typeof e!=`number`||!Number.isSafeInteger(e)||e<0)throw D(`${t} is invalid`);return e}function we(e,t){let n;try{n=new URL(e)}catch(e){throw D(`${t} is invalid`,e)}if(n.protocol!==`http:`&&n.protocol!==`https:`)throw D(`${t} must use HTTP or HTTPS`)}function E(e,t,n){Te(e,t,n)}function Te(e,t,n){let r;try{r=JSON.stringify(e)}catch(e){throw D(`${n} cannot be serialized`,e)}if(r.length>t)throw D(`${n} is too large`);return r}function D(e,t){return new h(e,{cause:t instanceof Error?t:void 0})}function Ee(e){if(!e.trim())throw Error(`InstantDB app ID is required`);return r({appId:e,schema:i,devtool:!1})}var De=class{db;session;#e;attachScreenshot;constructor(e,t,n={}){this.db=e,this.session=t,this.#e=n.commentTransport,this.#e&&(this.attachScreenshot=(e,t,n)=>this.#e.uploadScreenshot({pageId:e,commentId:t,screenshot:n}))}async getSnapshot(e){let{data:t}=await this.db.queryOnce(Oe(e,this.session.authUserId));return Ae(e,t.comments,t.replies)}async getProjectSnapshot(e){this.#t(e);let{data:t}=await this.db.queryOnce(ke(e,this.session.authUserId));return je(e,t.comments,t.replies)}subscribe(e,t,n){return this.db.subscribeQuery(Oe(e,this.session.authUserId),r=>{if(r.error){n?.(Re(r.error));return}if(r.data)try{t(Ae(e,r.data.comments,r.data.replies))}catch{n?.({type:`error`,code:`data-integrity`,recovery:`retry`,clearSnapshot:!0})}})}subscribeProject(e,t,n){return this.#t(e),this.db.subscribeQuery(ke(e,this.session.authUserId),r=>{if(r.error){n?.(Re(r.error));return}if(r.data)try{t(je(e,r.data.comments,r.data.replies))}catch{n?.({type:`error`,code:`data-integrity`,recovery:`retry`,clearSnapshot:!0})}})}async mutate(e,t){switch(t.type){case`comment.upsert`:{if(t.comment.pageId!==e)throw Error(`Comment page mismatch`);let n=t.comment;if(n.authorId!==this.session.reviewerId)throw Error(`Comment author mismatch`);let r=y(n.body).trim(),i=ae(r),a=M(n.createdAt,`Comment createdAt`),l=M(n.updatedAt,`Comment updatedAt`);if(l<a)throw new h(`Comment updatedAt precedes createdAt`);if(n.createdAt!==n.updatedAt)throw new h(`Comment edits must go through the review service`);if(n.status!==`open`||n.resolvedAt!==void 0||n.resolvedById!==void 0)throw new h(`New comments must start open`);let u=g(n.target);if(!Ie(n.anchor,u.publicTarget.anchor))throw new h(`Comment anchor does not match its target`);if(this.#e){await this.#e.createComment({pageId:e,commentId:n.id,body:r,target:n.target,...n.scope===void 0?{}:{scope:n.scope}});return}let d=_(n.scope),f=await Promise.all(u.targetElements.map(async e=>({element:e,id:await s(n.id,`element`,e.ordinal),slotKey:o(n.id,`element`,e.ordinal)}))),p=await Promise.all(d.map(async e=>({entry:e,id:await s(n.id,`scope`,e.ordinal),slotKey:o(n.id,`scope`,e.ordinal)}))),m=await c(n.id);await this.db.transact([this.db.tx.comments[n.id].update({pageId:e,authorId:this.session.reviewerId,authorAuthUserId:this.session.authUserId,authorName:this.session.displayName,body:r,bodyContentMarker:i,...u.commentFields,status:n.status,workflowRevision:0,createdAt:a,updatedAt:l}).link({page:e,author:this.session.reviewerId}),...f.map(({element:e,id:t,slotKey:r})=>this.db.tx.commentTargetElements[t].update({commentId:n.id,slotKey:r,authorAuthUserId:this.session.authUserId,...e}).link({comment:n.id})),...p.map(({entry:e,id:t,slotKey:r})=>this.db.tx.commentScopeEntries[t].update({commentId:n.id,slotKey:r,authorAuthUserId:this.session.authUserId,...e}).link({comment:n.id})),this.db.tx.commentSourceContexts[m].update({commentId:n.id,pageId:e,authorAuthUserId:this.session.authUserId,contextJson:u.sourceContextJson,createdAt:a}).link({comment:n.id,page:e,author:this.session.reviewerId})]);return}case`comment.delete`:throw new h(`Comment deletion must go through the review service`);case`reply.upsert`:{let n=t.reply;if(n.authorId!==this.session.reviewerId)throw Error(`Reply author mismatch`);let r=y(n.body,`Reply body`).trim(),i=ae(r,`Reply body`),a=M(n.createdAt,`Reply createdAt`),o=M(n.updatedAt,`Reply updatedAt`);if(o<a)throw new h(`Reply updatedAt precedes createdAt`);if(n.createdAt!==n.updatedAt)throw new h(`Reply edits must go through the review service`);if(this.#e){await this.#e.createReply({commentId:n.commentId,replyId:n.id,body:r});return}await this.db.transact(this.db.tx.replies[n.id].update({pageId:e,commentId:n.commentId,authorId:this.session.reviewerId,authorAuthUserId:this.session.authUserId,authorName:this.session.displayName,body:r,bodyContentMarker:i,createdAt:a,updatedAt:o}).link({comment:n.commentId,author:this.session.reviewerId}));return}case`reply.delete`:throw new h(`Reply deletion must go through the review service`)}}#t(e){if(!e.trim()||e!==this.session.projectId)throw Error(`Project does not belong to the reviewer session`)}};function Oe(e,t){return{comments:{$:{where:{pageId:e},order:{createdAt:`asc`}},targetElements:{},scopeEntries:{}},replies:{$:{where:{pageId:e},order:{createdAt:`asc`}}},$users:{$:{where:{id:t}},activeReviewInvitation:{project:{}}}}}function ke(e,t){return{comments:{$:{where:{"page.project.id":e},order:{createdAt:`asc`}},page:{project:{}},targetElements:{},scopeEntries:{}},replies:{$:{where:{"comment.page.project.id":e},order:{createdAt:`asc`}},comment:{page:{project:{}}}},$users:{$:{where:{id:t}},activeReviewInvitation:{project:{}}}}}function Ae(e,t,n){let r=t.map(t=>Ne(t,e));O(r,`comment`);let i=new Set(r.map(({id:e})=>e)),a=n.map(t=>Pe(t,e));O(a,`reply`);for(let e of a)if(!i.has(e.commentId))throw new h(`Reply ${e.id} references a comment outside the page snapshot`);return{pageId:e,comments:r,replies:a}}function je(e,t,n){let r=new Map,i=t.map(t=>{let n=A(t.pageId,`comment pageId`);Me(t.page,n,e,`comment ${String(t.id)}`);let i=k(t.page,`comment ${String(t.id)} page`),a=Ne(t,n),o=`/`;try{o=new URL(a.target.pageUrl).pathname||`/`}catch{}return r.set(n,{id:n,name:typeof i.name==`string`&&i.name.trim()?i.name.trim():a.target.pageTitle.trim()||o,pathname:typeof i.pathname==`string`&&i.pathname.trim()?i.pathname.trim():o}),a});O(i,`comment`);let a=new Map(i.map(e=>[e.id,e])),o=n.map(t=>{let n=A(t.pageId,`reply pageId`),r=k(t.comment,`reply ${String(t.id)} comment`),i=A(t.commentId,`reply ${String(t.id)} commentId`);if(A(r.id,`reply ${String(t.id)} comment relation id`)!==i)throw new h(`Reply ${String(t.id)} has an inconsistent comment relation`);Me(r.page,n,e,`reply ${String(t.id)}`);let o=Pe(t,n),s=a.get(o.commentId);if(!s||s.pageId!==n)throw new h(`Reply ${o.id} references a comment outside the project snapshot`);return o});return O(o,`reply`),{projectId:e,pages:[...r.values()].sort((e,t)=>e.pathname.localeCompare(t.pathname)||e.id.localeCompare(t.id)),comments:i,replies:o}}function Me(e,t,n,r){let i=k(e,`${r} page`);if(A(i.id,`${r} page id`)!==t)throw new h(`${r} escaped its page relation`);if(A(k(i.project,`${r} project`).id,`${r} project id`)!==n)throw new h(`${r} escaped its project scope`)}function Ne(e,t){let n=k(e,`comment`),r=A(n.id,`comment id`);if(A(n.pageId,`comment ${r} pageId`)!==t)throw new h(`Comment ${r} escaped its page scope`);A(n.authorAuthUserId,`comment ${r} authorAuthUserId`);let i=!(Object.hasOwn(n,`anchor`)&&Object.hasOwn(n,`target`)),a=i?ee(n,n.targetElements,`comment ${r} target`):ie(n.target,`comment ${r} target`),o=i?{...a.anchor}:Fe(n.anchor,`comment ${r} anchor`);if(!Ie(o,a.anchor))throw new h(`Comment ${r} has inconsistent anchors`);let s=n.status;if(s!==`open`&&s!==`resolved`)throw new h(`Comment ${r} has an invalid status`);let c=M(n.createdAt,`comment ${r} createdAt`),l=M(n.updatedAt,`comment ${r} updatedAt`);if(l<c)throw new h(`Comment ${r} updatedAt precedes createdAt`);let u=He(n.resolvedAt,`comment ${r} resolvedAt`),d=Ue(n.resolvedById,`comment ${r} resolvedById`);if(s===`open`&&(u!==void 0||d!==void 0))throw new h(`Open comment ${r} contains resolution metadata`);if(s===`resolved`&&(u===void 0||d===void 0||u!==l))throw new h(`Resolved comment ${r} has invalid workflow metadata`);return{id:r,pageId:t,authorId:A(n.authorId,`comment ${r} authorId`),authorName:A(n.authorName,`comment ${r} authorName`),body:y(n.body,`comment ${r} body`),anchor:o,target:a,...i?Le(v(n.scopeEntries)):n.scope==null?{}:{scope:oe(n.scope)},status:s,workflowRevision:Ve(n.workflowRevision,`comment ${r} workflowRevision`),createdAt:c,updatedAt:l,...u===void 0?{}:{resolvedAt:u},...d===void 0?{}:{resolvedById:d}}}function Pe(e,t){let n=k(e,`reply`),r=A(n.id,`reply id`);if(A(n.pageId,`reply ${r} pageId`)!==t)throw new h(`Reply ${r} escaped its page scope`);A(n.authorAuthUserId,`reply ${r} authorAuthUserId`);let i=M(n.createdAt,`reply ${r} createdAt`),a=M(n.updatedAt,`reply ${r} updatedAt`);if(a<i)throw new h(`Reply ${r} updatedAt precedes createdAt`);return{id:r,commentId:A(n.commentId,`reply ${r} commentId`),authorId:A(n.authorId,`reply ${r} authorId`),authorName:A(n.authorName,`reply ${r} authorName`),body:y(n.body,`reply ${r} body`),createdAt:i,updatedAt:a}}function Fe(e,t){let n=k(e,t);if(Object.keys(n).length!==5||!Object.hasOwn(n,`selector`)||!Object.hasOwn(n,`offsetX`)||!Object.hasOwn(n,`offsetY`)||!Object.hasOwn(n,`viewportX`)||!Object.hasOwn(n,`viewportY`))throw new h(`${t} has invalid fields`);return{selector:Be(n.selector,`${t} selector`),offsetX:j(n.offsetX,`${t} offsetX`),offsetY:j(n.offsetY,`${t} offsetY`),viewportX:j(n.viewportX,`${t} viewportX`),viewportY:j(n.viewportY,`${t} viewportY`)}}function Ie(e,t){return e.selector===t.selector&&e.offsetX===t.offsetX&&e.offsetY===t.offsetY&&e.viewportX===t.viewportX&&e.viewportY===t.viewportY}function Le(e){return e===void 0?{}:{scope:e}}function O(e,t){let n=new Set;for(let r of e){if(n.has(r.id))throw new h(`Duplicate ${t} ${r.id}`);n.add(r.id)}}function Re(e){let t=ze(e).toLowerCase();return t.includes(`expired`)||t.includes(`token`)?{type:`access-lost`,code:`session-expired`,recovery:`reauthenticate`,clearSnapshot:!0}:t.includes(`permission`)||t.includes(`forbidden`)||t.includes(`unauthorized`)?{type:`access-lost`,code:`permission-denied`,recovery:`reauthenticate`,clearSnapshot:!0}:{type:`error`,code:`transport`,recovery:`retry`,clearSnapshot:!0}}function ze(e){return e instanceof Error?e.message:e&&typeof e==`object`&&`message`in e?String(e.message):``}function k(e,t){if(!e||typeof e!=`object`||Array.isArray(e))throw new h(`${t} is missing or invalid`);return e}function Be(e,t){if(typeof e!=`string`)throw new h(`${t} is invalid`);return e}function A(e,t){let n=Be(e,t);if(!n.trim())throw new h(`${t} is empty`);return n}function j(e,t){if(typeof e!=`number`||!Number.isFinite(e)||e<0||e>1)throw new h(`${t} is invalid`);return e}function M(e,t){if(!Number.isSafeInteger(e)||e<0||e>0xe677d21fdbff)throw new h(`${t} is invalid`);return e}function Ve(e,t){if(!Number.isSafeInteger(e)||e<0)throw new h(`${t} is invalid`);return e}function He(e,t){return e==null?void 0:M(e,t)}function Ue(e,t){return e==null?void 0:A(e,t)}Object.freeze({field:`createdAt`,direction:`desc`,tieBreaker:`id`,tieDirection:`desc`}),Object.freeze({comments:200,replies:1e3,sourceContexts:200});var We=class{db;session;roomCredential;#e=new Map;constructor(e,t,n){this.db=e,this.session=t,this.roomCredential=n}subscribe(e,t,n,r){let i=[],a=[],o=!1,s=[],c=()=>{o||n({pageId:e,peers:structuredClone(i),messages:structuredClone(a)})};if(t.cursors){let n=$e(e,t.roomId),a,l,u=this.roomCredential?.id===t.roomId?this.roomCredential:void 0,d=u??{id:t.roomId,expiresAt:2**53-1,refresh:async()=>void 0},f=t=>{let o=this.db.joinRoom(`visualReview`,t),s=o.subscribePresence({},e=>{if(e.error){r?.(F(e.error));return}i=Object.values(e.peers).map(e=>Ke(e)).filter(e=>e!==null).sort((e,t)=>e.displayName.localeCompare(t.displayName)||e.peerId.localeCompare(t.peerId)),c()}),l=a;a=()=>{s(),o.leaveRoom()},this.#e.set(n,{pageId:e,roomId:t,publishPresence:e=>o.publishPresence(e)}),l?.()},p=()=>{if(!u||o)return;let e=Math.max(1e3,d.expiresAt-Date.now()+250);l=setTimeout(()=>{m()},e)},m=async()=>{try{let e=await d.refresh();if(o||!e)return;d={...e,refresh:d.refresh},u&&(u.id=e.id,u.expiresAt=e.expiresAt),f(e.id),p()}catch(e){if(o)return;r?.(F(e)),o||(l=setTimeout(()=>{m()},5e3))}};f(d.id),p(),s.push(()=>{l&&clearTimeout(l),this.#e.delete(n),a?.()})}return t.chat&&s.push(this.db.subscribeQuery(Ge(e,this.session.authUserId),t=>{if(t.error){r?.(F(t.error));return}if(t.data)try{a=t.data.reviewMessages.map(t=>qe(t,e)).sort(et),c()}catch{r?.({type:`error`,code:`data-integrity`,recovery:`retry`,clearSnapshot:!0})}})),queueMicrotask(c),()=>{if(!o){o=!0;for(let e of s.reverse())try{e()}catch{}}}}publishPresence(e,t,n){let r=this.#e.get($e(e,t));r&&r.publishPresence({reviewerId:this.session.reviewerId,displayName:this.session.displayName,color:n.color,active:n.active,...n.cursorX===void 0?{}:{cursorX:n.cursorX},...n.cursorY===void 0?{}:{cursorY:n.cursorY},...n.viewportWidth===void 0?{}:{viewportWidth:n.viewportWidth},...n.viewportHeight===void 0?{}:{viewportHeight:n.viewportHeight}})}async sendMessage(e,t){if(t.pageId!==e)throw Error(`Review message page mismatch`);if(t.authorId!==this.session.reviewerId)throw Error(`Review message author mismatch`);let n=Je(t.body),r=Ye(t.pathname),i=P(t.createdAt,`Review message createdAt`),a=P(t.updatedAt,`Review message updatedAt`);if(i!==a)throw Error(`New review messages must be immutable`);await this.db.transact(this.db.tx.reviewMessages[t.id].update({pageId:e,pathname:r,authorId:this.session.reviewerId,authorAuthUserId:this.session.authUserId,authorName:this.session.displayName,body:n,bodyContentMarker:ae(n,`Review message body`),createdAt:i,updatedAt:a}).link({page:e,author:this.session.reviewerId}))}};function Ge(e,t){return{reviewMessages:{$:{where:{pageId:e},order:{createdAt:`asc`}}},$users:{$:{where:{id:t}},activeReviewInvitation:{project:{}}}}}function Ke(e){let t=Xe(e.reviewerId,128),n=Xe(e.displayName,512),r=typeof e.color==`string`&&/^#[0-9a-f]{6}$/iu.test(e.color)?e.color:null;if(!t||!n||!r||typeof e.active!=`boolean`)return null;let i=Ze(e.cursorX),a=Ze(e.cursorY),o=Qe(e.viewportWidth),s=Qe(e.viewportHeight);return{peerId:e.peerId,reviewerId:t,displayName:n,color:r,active:e.active,...i===void 0?{}:{cursorX:i},...a===void 0?{}:{cursorY:a},...o===void 0?{}:{viewportWidth:o},...s===void 0?{}:{viewportHeight:s}}}function qe(e,t){let n=N(e.id,`Review message id`,128);if(N(e.pageId,`Review message pageId`,128)!==t)throw Error(`Review message page mismatch`);return{id:n,pageId:t,pathname:Ye(e.pathname),authorId:N(e.authorId,`Review message authorId`,128),authorName:N(e.authorName,`Review message authorName`,512),body:Je(e.body),createdAt:P(e.createdAt,`Review message createdAt`),updatedAt:P(e.updatedAt,`Review message updatedAt`)}}function Je(e){return N(e,`Review message body`,4e3)}function Ye(e){let t=N(e,`Review message pathname`,2e3);if(!t.startsWith(`/`))throw Error(`Review message pathname is invalid`);return t}function N(e,t,n){if(typeof e!=`string`)throw Error(`${t} is invalid`);let r=e.trim();if(!r||r.length>n)throw Error(`${t} is invalid`);return r}function Xe(e,t){if(typeof e!=`string`)return null;let n=e.trim();return n&&n.length<=t?n:null}function Ze(e){return typeof e==`number`&&Number.isFinite(e)?e:void 0}function Qe(e){let t=Ze(e);return t!==void 0&&t>0?t:void 0}function P(e,t){if(!Number.isSafeInteger(e)||e<0)throw Error(`${t} is invalid`);return e}function $e(e,t){return JSON.stringify([e,t])}function et(e,t){return e.createdAt-t.createdAt||e.id.localeCompare(t.id)}function F(e){let t=e&&typeof e==`object`&&`code`in e?String(e.code):``;if(/^INVITATION_(?:EXPIRED|NOT_FOUND|REQUIRED|REVOKED)$/u.test(t))return{type:`access-lost`,code:t===`INVITATION_EXPIRED`?`session-expired`:`membership-revoked`,recovery:`reauthenticate`,clearSnapshot:!0};let n=String(e instanceof Error||e&&typeof e==`object`&&`message`in e?e.message:e).toLowerCase();return n.includes(`expired`)||n.includes(`token`)?{type:`access-lost`,code:`session-expired`,recovery:`reauthenticate`,clearSnapshot:!0}:n.includes(`permission`)||n.includes(`forbidden`)||n.includes(`unauthorized`)?{type:`access-lost`,code:`permission-denied`,recovery:`reauthenticate`,clearSnapshot:!0}:{type:`error`,code:`transport`,recovery:`retry`,clearSnapshot:!0}}Object.freeze({field:`createdAt`,direction:`desc`,tieBreaker:`id`,tieDirection:`desc`});const I={$default:`false`},L={$default:`false`},R=`$user.activeReviewInvitation.project.id`;function z(e){return[`auth.id != null`,`size(auth.ref('$user.activeReviewInvitation.id')) == 1`,`size(auth.ref('${R}')) == 1`,`size(auth.ref('$user.activeReviewInvitation.status')) == 1`,`size(auth.ref('$user.activeReviewInvitation.expiresAt')) == 1`,`size(auth.ref('$user.activeReviewInvitation.revokedAt')) == 0`,`size(auth.ref('$user.activeReviewInvitation.project.originDisconnectedAt')) == 0`,`auth.ref('$user.activeReviewInvitation.status')[0] == 'accepted'`,`request.time < timestamp(auth.ref('$user.activeReviewInvitation.expiresAt')[0])`,e].join(` && `)}function B(...e){return e.map(e=>`(${e})`).join(` && `)}function V(...e){return e.map(e=>`(${e})`).join(` || `)}function H(e,t){return`!has(${e}.${t}) || ${e}.${t} == null`}const tt=`actions.data == 'create' && actions.linkedData == 'update'`,nt=e=>`${e}.matches('[^ \\t\\n\\r\\f\\u000b\\u00a0\\u1680\\u2000-\\u200a\\u2028\\u2029\\u202f\\u205f\\u3000\\ufeff]')`,rt=e=>B(`${e} >= 0`,`${e} <= 253402300799999`,`${e} % 1 == 0`),it=e=>B(rt(e),`(request.time - timestamp(${e})).getSeconds() <= 86400`,`(request.time - timestamp(${e})).getSeconds() >= -300`);function U(e){let t=`data.ref('${e}project.allowedOrigin')`,n=`data.ref('${e}stagingOrigin')`;return V(`size(${t}) == 0`,B(`size(${n}) == 1`,`${n}[0] in ${t}`))}const at=z(`auth.ref('${R}')[0] in data.ref('project.id')`);V(`size(data.ref('project.allowedOrigin')) == 0`,B(`has(data.stagingOrigin) && data.stagingOrigin != null`,`data.stagingOrigin in data.ref('project.allowedOrigin')`)),B(`actions.data == 'update' && actions.linkedData == 'create'`,V(`auth.id != null && auth.id in data.ref('project.owners.id')`,at));const ot=z(`auth.ref('${R}')[0] in data.ref('page.project.id')`);U(`page.`),B(tt,V(`auth.id != null && auth.id in data.ref('page.project.owners.id')`,ot),`auth.id != null && auth.id == data.authorAuthUserId && auth.id in data.ref('author.$user.id')`,`data.pageId in data.ref('page.id')`,`data.authorId in data.ref('author.id') && data.authorAuthUserId in data.ref('author.$user.id') && data.authorName in data.ref('author.displayName')`,`data.pageId in data.ref('author.project.pages.id')`),B(tt,`data.pageId == linkedData.id`,`auth.id != null && auth.id == data.authorAuthUserId`,`data.authorId in auth.ref('$user.reviewerMemberships.id')`,`data.authorId in linkedData.ref('project.reviewers.id')`,V(`auth.id != null && auth.id in linkedData.ref('project.owners.id')`,z(`auth.ref('${R}')[0] in linkedData.ref('project.id')`))),V(`auth.id != null && auth.id in data.ref('comment.page.project.owners.id')`,B(z(`auth.ref('${R}')[0] in data.ref('comment.page.project.id')`),U(`comment.page.`))),z(`auth.ref('${R}')[0] in data.ref('comment.page.project.id')`),U(`comment.page.`),z(`auth.ref('${R}')[0] in data.ref('page.project.id')`),U(`page.`);const st=B(`data.reviewerId != null`,`data.projectId in data.ref('project.id')`,`data.reviewerId in data.ref('reviewer.id')`,`data.projectId in data.ref('reviewer.project.id')`,`auth.id in data.ref('reviewer.$user.id')`,`auth.email in data.ref('reviewer.email')`);B(`auth.id != null`,`data.revokedAt == null`,`data.status in ['pending', 'accepted']`,`data.status == 'pending' || data.claimedByAuthUserId == auth.id`,`request.time < timestamp(data.expiresAt)`,`request.modifiedFields.all(field, field in ['status', 'claimedByAuthUserId', 'acceptedAt', 'claimRevision', 'activeUser'])`,`'status' in request.modifiedFields`,`'claimedByAuthUserId' in request.modifiedFields`,`'acceptedAt' in request.modifiedFields`,`'claimRevision' in request.modifiedFields`,`'activeUser' in request.modifiedFields`,`newData.status == 'accepted'`,`newData.claimedByAuthUserId == auth.id`,`newData.claimRevision == data.claimRevision + 1`,`math.abs((request.time - timestamp(newData.acceptedAt)).getMinutes()) <= 1`,st),B(`actions.data == 'update'`,`actions.linkedData == 'update'`,`auth.id != null`,`auth.email != null`,`linkedData.id == auth.id`,`linkedData.email == auth.email`,`data.email == auth.email`,`data.revokedAt == null`,`data.status in ['pending', 'accepted']`,`data.status == 'pending' || data.claimedByAuthUserId == auth.id`,`request.time < timestamp(data.expiresAt)`,`newData.status == 'accepted'`,`newData.claimedByAuthUserId == auth.id`,`newData.claimRevision == data.claimRevision + 1`,`math.abs((request.time - timestamp(newData.acceptedAt)).getMinutes()) <= 1`,st),B(`actions.data == 'update'`,`actions.linkedData == 'update'`,`auth.id != null`,`auth.email != null`,`data.id == auth.id`,`data.email == auth.email`,`linkedData.email == auth.email`,`linkedData.revokedAt == null`,`linkedData.status == 'accepted'`,`linkedData.claimedByAuthUserId == auth.id`,`request.time < timestamp(linkedData.expiresAt)`,`math.abs((request.time - timestamp(linkedData.acceptedAt)).getMinutes()) <= 1`,`linkedData.projectId in linkedData.ref('project.id')`,`linkedData.reviewerId in linkedData.ref('reviewer.id')`,`linkedData.projectId in linkedData.ref('reviewer.project.id')`,`auth.id in linkedData.ref('reviewer.$user.id')`,`auth.email in linkedData.ref('reviewer.email')`),B(`auth.id != null`,`auth.email != null`,`linkedData.id == auth.id`,`linkedData.email == auth.email`,`data.email == auth.email`,`data.claimedByAuthUserId == auth.id`,`auth.id in data.ref('activeUser.id')`),B(`auth.id != null`,`auth.email != null`,`data.id == auth.id`,`data.email == auth.email`,`linkedData.email == auth.email`,`linkedData.claimedByAuthUserId == auth.id`,`auth.id in linkedData.ref('activeUser.id')`),{...I},{...I},{...L},{...L},z(`data.id == auth.ref('${R}')[0]`),{...I},B(`isOwner`,V(B(H(`data`,`allowedOrigin`),H(`newData`,`allowedOrigin`)),`newData.allowedOrigin == data.allowedOrigin`),V(B(H(`data`,`originDisconnectedAt`),H(`newData`,`originDisconnectedAt`)),`newData.originDisconnectedAt == data.originDisconnectedAt`)),{...L},{...I},B(`isOwner`,V(B(H(`data`,`autoRegistrationSlot`),H(`newData`,`autoRegistrationSlot`)),`newData.autoRegistrationSlot == data.autoRegistrationSlot`)),{...L},{...I},{...L},z(`auth.ref('${R}')[0] in data.ref('project.id')`),{...I},{...L},{...I},{...I},{...L},{...L},{...I},{...L},{...I},{...I},{...I},{...I},{...I},B(`data.createdAt == data.updatedAt`,it(`data.createdAt`),`size(data.body) > 0`,`size(data.body) <= 4000`,`size(data.bodyContentMarker) == 1`,nt(`data.bodyContentMarker`),`data.body.startsWith(data.bodyContentMarker)`,`size(data.authorName) > 0`,`size(data.authorName) <= 512`,nt(`data.authorName`),`size(data.pathname) > 0`,`size(data.pathname) <= 2000`,`request.modifiedFields.all(field, field in ['pageId', 'pathname', 'authorId', 'authorAuthUserId', 'authorName', 'body', 'bodyContentMarker', 'createdAt', 'updatedAt', 'page', 'author'])`),{...I},{...L};var W=class extends Error{code;constructor(e,t){super(t),this.code=e,this.name=`ReviewerCommentSaveError`}};function ct(e,t){let n=e.replace(/\/+$/,``),r=async(e,r)=>{let i=await t();if(!i)throw new W(`AUTH_REQUIRED`,`로그인 세션이 만료되었습니다. 새로고침 후 다시 시도해 주세요.`);let a;try{a=await fetch(`${n}${e}`,{method:`POST`,headers:{authorization:`Bearer ${i}`,"content-type":`application/json`},body:JSON.stringify(r)})}catch{throw new W(`NETWORK`,`리뷰 서버에 연결하지 못했습니다. 연결을 확인하고 다시 시도해 주세요.`)}if(!a.ok)throw new W(...await ut(a))};return{createComment:e=>r(`/v1/comments`,e),createReply:e=>r(`/v1/replies`,e),uploadScreenshot:async({pageId:e,commentId:r,screenshot:i})=>{let a=await t();if(!a)throw new W(`AUTH_REQUIRED`,`로그인 세션이 만료되어 위치 캡처를 저장하지 못했습니다.`);let o;try{o=await fetch(`${n}/v1/comments/${encodeURIComponent(r)}/screenshot`,{method:`PUT`,headers:{authorization:`Bearer ${a}`,"content-type":i.contentType,"x-review-page-id":e,"x-review-image-width":String(i.width),"x-review-image-height":String(i.height)},body:lt(i.bytes)})}catch{throw new W(`NETWORK`,`리뷰 서버에 연결하지 못해 위치 캡처를 저장하지 못했습니다.`)}if(!o.ok)throw new W(...await ut(o))}}}function lt(e){let t=new Uint8Array(e.byteLength);return t.set(e),t.buffer}async function ut(e){let t=e.status>=500?`리뷰 서버가 코멘트를 저장하지 못했습니다. 잠시 후 다시 시도해 주세요.`:`코멘트를 저장하지 못했습니다.`;try{let n=await e.json();if(!n||typeof n!=`object`)return[`UNKNOWN`,t];let r=n;return[typeof r.error==`string`?r.error:`UNKNOWN`,typeof r.message==`string`&&r.message.trim()?r.message:t]}catch{return[`UNKNOWN`,t]}}var G=class extends Error{code;constructor(e,t){super(t),this.code=e,this.name=`ReviewBootstrapError`}};const K=new Map;function dt(e,t={}){let n=e.trim();if(!n)throw Error(`InstantDB app ID is required`);return{async resolve(e){let r=(t.databaseFactory??Ee)(n),i=await mt(n,r,e.authHost,e.signal,e.styleNonce,t.reviewerToken);for(;;)try{await ft(t.acceptInvitation,{refreshToken:i.refresh_token,invitationId:e.invitationId,suggestedDisplayName:Dt(i.email),authHost:e.authHost,signal:e.signal,styleNonce:e.styleNonce});break}catch(a){if(!Ot(a,`INVITATION_EMAIL_MISMATCH`))throw a;await bt(e.authHost,e.signal,e.styleNonce),i=await ht(n,r,i,e.authHost,e.signal,e.styleNonce,t.reviewerToken)}let{data:a}=await r.queryOnce({reviewers:{$:{where:{authUserId:i.id}}},reviewPages:{$:{where:{stagingOrigin:e.location.origin}}},invitations:{}}),o=pt(a.invitations,a.reviewers,a.reviewPages,{invitationId:e.invitationId,authUserId:i.id,email:i.email??``,location:e.location,now:Date.now()});if(!o.ok)throw new G(o.code,Mt(o.code));let s={authUserId:i.id,reviewerId:o.reviewer.id,projectId:o.reviewer.projectId,invitationId:e.invitationId,email:o.reviewer.email||i.email||``,displayName:o.reviewer.displayName||i.email||`Reviewer`,role:o.reviewer.role===`agency`?`agency`:`reviewer`},c=o.page.id,l=e.collaboration?.scopeId,u=e.collaboration?.cursors===!0&&t.resolveCollaborationRoom?await t.resolveCollaborationRoom({refreshToken:i.refresh_token,invitationId:e.invitationId,pageId:o.page.id,scopeId:e.collaboration.scopeId,signal:e.signal}):void 0,d=u&&t.resolveCollaborationRoom?{...u,refresh:async()=>{let n=await r.getAuth();if(!(!n?.refresh_token||l===void 0))return t.resolveCollaborationRoom?.({refreshToken:n.refresh_token,invitationId:e.invitationId,pageId:c,scopeId:l,signal:new AbortController().signal})}}:void 0,f=0;return{pageId:o.page.id,resolvePage:async n=>{let i=++f,a=()=>i!==f||n.signal.aborted,o=(e,t,n)=>({pageId:e,...n&&d?{collaborationRoomId:n.id}:{},commit:()=>{a()||(c=e,t!==void 0&&(l=t),!(!n||!d)&&(d.id=n.id,d.expiresAt=n.expiresAt))}});if(n.location.origin!==e.location.origin)throw new G(`PAGE_NOT_FOUND`,Mt(`PAGE_NOT_FOUND`));let{data:u}=await r.queryOnce({reviewPages:{$:{where:{stagingOrigin:n.location.origin}}}});if(a())throw kt();let p=Z(n.location.pathname),m=u.reviewPages.find(e=>e.projectId===s.projectId&&e.stagingOrigin===n.location.origin&&Z(e.pathname)===p);if(!m)throw new G(`PAGE_NOT_FOUND`,Mt(`PAGE_NOT_FOUND`));if(n.collaboration?.cursors!==!0||d===void 0||t.resolveCollaborationRoom===void 0||!n.collaboration)return o(m.id,n.collaboration?.scopeId);let h=await r.getAuth();if(a())throw kt();if(!h?.refresh_token)throw Error(`리뷰 세션이 만료되어 실시간 협업 연결을 갱신할 수 없습니다.`);let g=await t.resolveCollaborationRoom({refreshToken:h.refresh_token,invitationId:e.invitationId,pageId:m.id,scopeId:n.collaboration.scopeId,signal:n.signal});if(a())throw kt();return o(m.id,n.collaboration.scopeId,g)},session:s,repository:new De(r,s,{...t.serviceUrl===void 0?{}:{commentTransport:ct(t.serviceUrl,async()=>(await r.getAuth())?.refresh_token??null)}}),...e.collaboration?.cursors===!0||e.collaboration?.chat===!0?{collaborationRepository:new We(r,s,d)}:{},...e.collaboration?.cursors===!0&&d?{collaborationRoomId:d.id}:{},allowedStagingHosts:[e.location.hostname]}}}}async function ft(e,t){if(!e)return;let n={refreshToken:t.refreshToken,invitationId:t.invitationId,signal:t.signal};try{await e(n);return}catch(e){if(!Ot(e,`DISPLAY_NAME_REQUIRED`))throw e}let r=await yt(t.authHost,t.signal,t.suggestedDisplayName,t.styleNonce);await e({...n,displayName:r})}function pt(e,t,n,r){let i=e.find(({id:e})=>e===r.invitationId);if(!i||jt(i.email)!==jt(r.email))return{ok:!1,code:`INVITATION_REQUIRED`};if(i.status===`revoked`)return{ok:!1,code:`INVITATION_REVOKED`};if(i.status===`expired`||i.expiresAt<=r.now)return{ok:!1,code:`INVITATION_EXPIRED`};if(i.status!==`accepted`)return{ok:!1,code:`INVITATION_NOT_ACCEPTED`};let a=t.find(e=>e.authUserId===r.authUserId&&e.projectId===i.projectId);if(!a)return{ok:!1,code:`MEMBERSHIP_REQUIRED`};let o=Z(r.location.pathname),s=n.find(e=>e.projectId===i.projectId&&e.stagingOrigin===r.location.origin&&Z(e.pathname)===o);return s?{ok:!0,invitation:i,reviewer:a,page:s}:{ok:!1,code:`PAGE_NOT_FOUND`}}async function mt(e,t,n,r,i,a){let o=await q(r,()=>t.getAuth());if(o)return o;let s=await gt(e,r);try{return await q(r,()=>t.getAuth())||(a?await q(r,async()=>{await t.auth.signInWithToken(a);let e=await t.getAuth();if(!e)throw Error(`Reviewer session did not establish`);return e}):await vt(t,n,r,i))}finally{s()}}async function ht(e,t,n,r,i,a,o){J(i);let s=await gt(e,i);try{let e=await q(i,()=>t.getAuth());return e&&e.id!==n.id?e:(e&&await q(i,async()=>{await t.auth.signOut()}),J(i),o?await q(i,async()=>{await t.auth.signInWithToken(o);let e=await t.getAuth();if(!e)throw Error(`Reviewer session did not establish`);return e}):await vt(t,r,i,a))}finally{s()}}async function gt(e,t){J(t);let n=K.get(e);return n||(n={held:!1,waiters:[]},K.set(e,n)),n.held?new Promise((e,r)=>{let i,a=()=>{let e=n.waiters.indexOf(i);e<0||(n.waiters.splice(e,1),t.removeEventListener(`abort`,a),r(X()))};i={signal:t,resolve:e,reject:r,abort:a},n.waiters.push(i),t.addEventListener(`abort`,a,{once:!0}),t.aborted&&a()}):(n.held=!0,_t(e,n))}function _t(e,t){let n=!1;return()=>{if(!n){for(n=!0;t.waiters.length>0;){let n=t.waiters.shift();if(n.signal.removeEventListener(`abort`,n.abort),n.signal.aborted){n.reject(X());continue}n.resolve(_t(e,t));return}t.held=!1,K.get(e)===t&&K.delete(e)}}}async function q(e,t){J(e);let n=await t();return J(e),n}function J(e){if(e.aborted)throw X()}function vt(e,t,n,r){try{J(n)}catch(e){return Promise.reject(e)}let i=St(t);i.replaceChildren(Ct(i,r),wt(i));let a=i.querySelector(`form`),o=i.querySelector(`h2`),s=i.querySelector(`.description`),c=a.elements.namedItem(`email`),l=a.elements.namedItem(`code`),u=i.querySelector(`.code`),d=i.querySelector(`button`),f=i.querySelector(`.error`),p=!1;return new Promise((t,r)=>{let m=!1,h=!1,g=!1,ee=()=>{n.removeEventListener(`abort`,v),i.removeEventListener(`keydown`,te),a.removeEventListener(`submit`,ne)},_=e=>{m||(m=!0,ee(),e())},v=()=>{m||(g=!0,ee(),h||_(()=>r(X())))},te=e=>{let t=e;t.key===`Escape`?(t.preventDefault(),v()):t.key===`Tab`&&At(i,t)},ne=async i=>{if(i.preventDefault(),!(m||h)){h=!0,f.textContent=``,d.disabled=!0,a.setAttribute(`aria-busy`,`true`);try{if(J(n),!p){let t=c.value.trim();await q(n,async()=>{await e.auth.sendMagicCode({email:t})}),p=!0,c.readOnly=!0,u.hidden=!1,l.required=!0,o.textContent=`인증 코드`,s.textContent=`${t}로 보낸 코드를 입력하세요.`,d.textContent=`확인`,l.focus();return}await q(n,async()=>{await e.auth.signInWithMagicCode({email:c.value.trim(),code:l.value.trim()})});let r=await q(n,()=>e.getAuth());if(!r)throw Error(`인증 세션을 확인할 수 없습니다.`);_(()=>t(r))}catch(e){if(m||n.aborted||Ot(e,`AUTH_CANCELLED`))return;f.textContent=xt(e)}finally{h=!1,!m&&(g||n.aborted)?_(()=>r(X())):m||(d.disabled=!1,a.removeAttribute(`aria-busy`))}}};n.addEventListener(`abort`,v,{once:!0}),i.addEventListener(`keydown`,te),a.addEventListener(`submit`,ne)})}function yt(e,t,n=``,r){if(t.aborted)return Promise.reject(X());let i=St(e);i.replaceChildren(Ct(i,r),Tt(i));let a=i.querySelector(`form`),o=a.elements.namedItem(`displayName`),s=i.querySelector(`button`),c=i.querySelector(`.error`);return o.value=n.trim().slice(0,120),o.focus(),o.select(),new Promise((e,n)=>{let r=!1,l=e=>{r||(r=!0,t.removeEventListener(`abort`,u),i.removeEventListener(`keydown`,p),a.removeEventListener(`submit`,f),e())},u=()=>l(()=>n(X())),d=()=>{let t=o.value.trim();if(!t){c.textContent=`이름을 입력해 주세요.`,o.focus();return}if(t.length>120){c.textContent=`이름은 120자 이하여야 합니다.`,o.focus();return}c.textContent=``,s.disabled=!0,a.setAttribute(`aria-busy`,`true`),l(()=>e(t))},f=e=>{e.preventDefault(),d()},p=e=>{let t=e;if(t.key===`Escape`){t.preventDefault(),u();return}if(t.key===`Tab`){At(i,t);return}t.key===`Enter`&&!t.isComposing&&t.target===o&&(t.preventDefault(),d())};t.addEventListener(`abort`,u,{once:!0}),i.addEventListener(`keydown`,p),a.addEventListener(`submit`,f)})}function bt(e,t,n){if(t.aborted)return Promise.reject(X());let r=St(e);r.replaceChildren(Ct(r,n),Et(r));let i=r.querySelector(`form`),a=r.querySelector(`button`);return a.focus(),new Promise((e,n)=>{let o=!1,s=e=>{o||(o=!0,t.removeEventListener(`abort`,c),r.removeEventListener(`keydown`,u),i.removeEventListener(`submit`,l),e())},c=()=>s(()=>n(X())),l=t=>{t.preventDefault(),a.disabled=!0,i.setAttribute(`aria-busy`,`true`),s(e)},u=e=>{let t=e;t.key===`Escape`?(t.preventDefault(),c()):t.key===`Tab`&&At(r,t)};t.addEventListener(`abort`,c,{once:!0}),r.addEventListener(`keydown`,u),i.addEventListener(`submit`,l)})}function xt(e){if(e&&typeof e==`object`&&`body`in e){let t=e.body;if(t?.message)return t.message}return e instanceof Error?e.message:`로그인에 실패했습니다. 다시 시도해 주세요.`}function St(e){return e.shadowRoot??e.attachShadow({mode:`open`})}function Ct(e,t){let n=e.ownerDocument.createElement(`style`);return t&&(n.nonce=t),n.textContent=Nt,n}function wt(e){let t=e.ownerDocument,n=t.createElement(`form`);n.setAttribute(`role`,`dialog`),n.setAttribute(`aria-modal`,`true`),n.setAttribute(`aria-labelledby`,`visual-review-login-title`),n.setAttribute(`aria-describedby`,`visual-review-login-description`);let r=Y(t,`p`,`01.works`,`eyebrow`),i=Y(t,`h2`,`Visual Review`);i.id=`visual-review-login-title`;let a=Y(t,`p`,`초대받은 이메일로 계속하세요.`,`description`);a.id=`visual-review-login-description`;let o=t.createElement(`label`);o.append(`이메일`);let s=t.createElement(`input`);s.name=`email`,s.type=`email`,s.autocomplete=`email`,s.required=!0,o.append(s);let c=t.createElement(`label`);c.className=`code`,c.hidden=!0,c.append(`인증 코드`);let l=t.createElement(`input`);l.name=`code`,l.inputMode=`numeric`,l.autocomplete=`one-time-code`,c.append(l);let u=Y(t,`p`,``,`error`);u.setAttribute(`role`,`alert`);let d=Y(t,`button`,`코드 받기`);return d.type=`submit`,n.append(r,i,a,o,c,u,d),n}function Tt(e){let t=e.ownerDocument,n=t.createElement(`form`);n.setAttribute(`role`,`dialog`),n.setAttribute(`aria-modal`,`true`),n.setAttribute(`aria-labelledby`,`visual-review-name-title`),n.setAttribute(`aria-describedby`,`visual-review-name-description`);let r=Y(t,`p`,`01.works`,`eyebrow`),i=Y(t,`h2`,`표시 이름`);i.id=`visual-review-name-title`;let a=Y(t,`p`,`피드백에 이 이름이 표시됩니다.`,`description`);a.id=`visual-review-name-description`;let o=Y(t,`label`,`이름`);o.htmlFor=`visual-review-display-name`;let s=t.createElement(`input`);s.id=`visual-review-display-name`,s.name=`displayName`,s.autocomplete=`name`,s.maxLength=120,s.required=!0;let c=Y(t,`p`,``,`error`);c.setAttribute(`role`,`alert`);let l=Y(t,`button`,`리뷰 시작`);return l.type=`submit`,n.append(r,i,a,o,s,c,l),n}function Et(e){let t=e.ownerDocument,n=t.createElement(`form`);n.setAttribute(`role`,`dialog`),n.setAttribute(`aria-modal`,`true`),n.setAttribute(`aria-labelledby`,`visual-review-account-title`),n.setAttribute(`aria-describedby`,`visual-review-account-description`);let r=Y(t,`p`,`01.works`,`eyebrow`),i=Y(t,`h2`,`계정 확인`);i.id=`visual-review-account-title`;let a=Y(t,`p`,`이 초대는 현재 로그인한 계정과 일치하지 않습니다.`,`description`);a.id=`visual-review-account-description`;let o=Y(t,`button`,`다른 계정으로 계속`);return o.type=`submit`,n.append(r,i,a,o),n}function Y(e,t,n,r){let i=e.createElement(t);return i.textContent=n,r&&(i.className=r),i}function Dt(e){return e?.split(`@`)[0]?.trim().slice(0,120)??``}function Ot(e,t){return!!(e&&typeof e==`object`&&`code`in e&&e.code===t)}function kt(){return new DOMException(`Aborted`,`AbortError`)}function X(){return new G(`AUTH_CANCELLED`,`리뷰 로그인이 취소되었습니다.`)}function At(e,t){let n=Array.from(e.querySelectorAll(`input:not([disabled]),button:not([disabled])`)).filter(e=>!e.closest(`[hidden]`));if(n.length===0)return;let r=n[0],i=n.at(-1);t.shiftKey&&e.activeElement===r?(t.preventDefault(),i.focus()):!t.shiftKey&&e.activeElement===i&&(t.preventDefault(),r.focus())}function Z(e){return e.replace(/\/+$/,``)||`/`}function jt(e){return e.trim().toLowerCase()}function Mt(e){switch(e){case`INVITATION_REQUIRED`:return`현재 계정과 일치하는 리뷰 초대를 찾을 수 없습니다.`;case`INVITATION_NOT_ACCEPTED`:return`아직 수락되지 않은 리뷰 초대입니다.`;case`INVITATION_REVOKED`:return`취소된 리뷰 초대입니다. 계속 검토하려면 담당자에게 다시 요청하세요.`;case`INVITATION_EXPIRED`:return`만료된 리뷰 초대입니다. 담당자에게 새 링크를 요청하세요.`;case`MEMBERSHIP_REQUIRED`:return`이 프로젝트의 reviewer membership이 없습니다.`;case`PAGE_NOT_FOUND`:return`이 페이지는 아직 리뷰 대상이 아닙니다. 담당자에게 문의하세요.`}}const Nt=`
1
+ import{r as e}from"./install-B5CNlFQl.js";import{t}from"./embedded-source-e0DrdxU8.js";import{i as n,init as r}from"@instantdb/core";const i=n.schema({entities:{$files:n.entity({path:n.string().unique().indexed(),url:n.string()}),$users:n.entity({email:n.string().unique().indexed()}),projects:n.entity({name:n.string(),slug:n.string().unique().indexed(),allowedOrigin:n.string().optional(),originDisconnectedAt:n.number().optional(),createdAt:n.number().indexed(),updatedAt:n.number()}),reviewPages:n.entity({projectId:n.string().indexed(),autoRegistrationSlot:n.string().unique().indexed().optional(),name:n.string(),pathname:n.string(),stagingOrigin:n.string(),createdAt:n.number().indexed(),updatedAt:n.number()}),reviewPageBuilds:n.entity({projectId:n.string().indexed(),pageId:n.string().unique().indexed(),buildId:n.string(),gitCommit:n.string().optional(),generatedAt:n.number().optional(),mode:n.string(),updatedAt:n.number().indexed()}),reviewers:n.entity({authUserId:n.string().indexed(),projectId:n.string().indexed(),email:n.string().indexed(),displayName:n.string(),role:n.string(),createdAt:n.number()}),reviewerIdentityClaims:n.entity({reviewerId:n.string().unique().indexed(),projectId:n.string().indexed(),authUserId:n.string().indexed(),email:n.string(),displayName:n.string(),role:n.string(),createdAt:n.number()}),invitations:n.entity({projectId:n.string().indexed(),reviewerId:n.string().indexed().optional(),email:n.string().indexed(),status:n.string().indexed(),claimRevision:n.number(),claimedByAuthUserId:n.string().indexed().optional(),expiresAt:n.number().indexed(),createdAt:n.number(),acceptedAt:n.number().optional(),revokedAt:n.number().optional()}),comments:n.entity({pageId:n.string().indexed(),authorId:n.string().indexed(),authorAuthUserId:n.string().indexed(),authorName:n.string(),body:n.string(),bodyContentMarker:n.string().optional(),anchorSelector:n.string().optional(),anchorOffsetX:n.number().optional(),anchorOffsetY:n.number().optional(),anchorViewportX:n.number().optional(),anchorViewportY:n.number().optional(),targetKind:n.string().optional(),targetPageX:n.number().optional(),targetPageY:n.number().optional(),targetWidth:n.number().optional(),targetHeight:n.number().optional(),targetViewportX:n.number().optional(),targetViewportY:n.number().optional(),targetViewportWidth:n.number().optional(),targetViewportHeight:n.number().optional(),targetPageOrigin:n.string().optional(),targetPagePathname:n.string().optional(),targetPageSearch:n.string().optional(),targetPageHash:n.string().optional(),targetPageTitle:n.string().optional(),targetCapturedAt:n.number().optional(),status:n.string().indexed(),workflowRevision:n.number(),createdAt:n.number().indexed(),updatedAt:n.number().indexed(),resolvedAt:n.number().optional(),resolvedById:n.string().optional()}),commentWorkflowClaims:n.entity({claimKey:n.string().unique().indexed(),commentId:n.string().indexed(),expectedWorkflowRevision:n.number(),createdAt:n.number().indexed()}),commentTargetElements:n.entity({commentId:n.string().indexed(),slotKey:n.string().unique().indexed().optional(),ordinal:n.number(),selector:n.string(),tagName:n.string(),textPreview:n.string(),pageX:n.number(),pageY:n.number(),width:n.number(),height:n.number(),viewportX:n.number(),viewportY:n.number(),viewportWidth:n.number(),viewportHeight:n.number(),authorAuthUserId:n.string().indexed()}),commentScopeEntries:n.entity({commentId:n.string().indexed(),slotKey:n.string().unique().indexed().optional(),ordinal:n.number(),key:n.string(),valueType:n.string(),stringValue:n.string().optional(),numberValue:n.number().optional(),booleanValue:n.boolean().optional(),authorAuthUserId:n.string().indexed()}),commentSourceContexts:n.entity({commentId:n.string().unique().indexed(),pageId:n.string().indexed(),authorAuthUserId:n.string().indexed(),contextJson:n.string(),createdAt:n.number().indexed()}),replies:n.entity({pageId:n.string().indexed(),commentId:n.string().indexed(),authorId:n.string().indexed(),authorAuthUserId:n.string().indexed(),authorName:n.string(),body:n.string(),bodyContentMarker:n.string().optional(),createdAt:n.number().indexed(),updatedAt:n.number().indexed()}),reviewMessages:n.entity({pageId:n.string().indexed(),pathname:n.string().indexed(),authorId:n.string().indexed(),authorAuthUserId:n.string().indexed(),authorName:n.string(),body:n.string(),bodyContentMarker:n.string(),createdAt:n.number().indexed(),updatedAt:n.number().indexed()})},links:{projectOwners:{forward:{on:`projects`,has:`many`,label:`owners`},reverse:{on:`$users`,has:`many`,label:`ownedProjects`}},projectPages:{forward:{on:`projects`,has:`many`,label:`pages`},reverse:{on:`reviewPages`,has:`one`,label:`project`}},pageCurrentBuild:{forward:{on:`reviewPageBuilds`,has:`one`,label:`page`,required:!0,onDelete:`cascade`},reverse:{on:`reviewPages`,has:`one`,label:`currentBuild`}},projectReviewers:{forward:{on:`projects`,has:`many`,label:`reviewers`},reverse:{on:`reviewers`,has:`one`,label:`project`}},reviewerUser:{forward:{on:`reviewers`,has:`one`,label:`$user`},reverse:{on:`$users`,has:`many`,label:`reviewerMemberships`}},projectInvitations:{forward:{on:`projects`,has:`many`,label:`invitations`},reverse:{on:`invitations`,has:`one`,label:`project`}},invitationReviewer:{forward:{on:`invitations`,has:`one`,label:`reviewer`},reverse:{on:`reviewers`,has:`many`,label:`acceptedInvitations`}},invitationActiveUser:{forward:{on:`invitations`,has:`one`,label:`activeUser`},reverse:{on:`$users`,has:`one`,label:`activeReviewInvitation`}},pageComments:{forward:{on:`reviewPages`,has:`many`,label:`comments`},reverse:{on:`comments`,has:`one`,label:`page`}},pageReviewMessages:{forward:{on:`reviewPages`,has:`many`,label:`reviewMessages`},reverse:{on:`reviewMessages`,has:`one`,label:`page`}},commentReplies:{forward:{on:`comments`,has:`many`,label:`replies`},reverse:{on:`replies`,has:`one`,label:`comment`}},commentTargetElements:{forward:{on:`commentTargetElements`,has:`one`,label:`comment`,required:!0,onDelete:`cascade`},reverse:{on:`comments`,has:`many`,label:`targetElements`}},commentScopeEntries:{forward:{on:`commentScopeEntries`,has:`one`,label:`comment`,required:!0,onDelete:`cascade`},reverse:{on:`comments`,has:`many`,label:`scopeEntries`}},commentSourceContext:{forward:{on:`commentSourceContexts`,has:`one`,label:`comment`,required:!0,onDelete:`cascade`},reverse:{on:`comments`,has:`one`,label:`sourceContext`}},pageSourceContexts:{forward:{on:`commentSourceContexts`,has:`one`,label:`page`,required:!0},reverse:{on:`reviewPages`,has:`many`,label:`sourceContexts`}},sourceContextAuthor:{forward:{on:`commentSourceContexts`,has:`one`,label:`author`,required:!0},reverse:{on:`reviewers`,has:`many`,label:`sourceContexts`}},commentAuthor:{forward:{on:`comments`,has:`one`,label:`author`},reverse:{on:`reviewers`,has:`many`,label:`comments`}},replyAuthor:{forward:{on:`replies`,has:`one`,label:`author`},reverse:{on:`reviewers`,has:`many`,label:`replies`}},reviewMessageAuthor:{forward:{on:`reviewMessages`,has:`one`,label:`author`},reverse:{on:`reviewers`,has:`many`,label:`reviewMessages`}}},rooms:{visualReview:{presence:n.entity({reviewerId:n.string(),displayName:n.string(),color:n.string(),active:n.boolean(),pathname:n.string().optional(),cursorX:n.number().optional(),cursorY:n.number().optional(),viewportWidth:n.number().optional(),viewportHeight:n.number().optional(),cursorChat:n.string().optional()})}}}),a=new Uint8Array([107,167,184,17,157,173,17,209,128,180,0,192,79,212,48,200]);function o(e,t,n){return u(e,n),`${e}:${t}:${n}`}async function s(e,t,n){return l(o(e,t,n))}async function c(e){if(!e.trim())throw Error(`Comment ID is required for source context`);return l(`${e}:source-context`)}async function l(e){let t=globalThis.crypto?.subtle;if(!t)throw Error(`Web Crypto is required to persist review capture context`);let n=new TextEncoder().encode(`01works.visual-review/v1/${e}`),r=new Uint8Array(a.length+n.length);r.set(a),r.set(n,a.length);let i=new Uint8Array(await t.digest(`SHA-1`,r)).slice(0,16);i[6]=i[6]&15|80,i[8]=i[8]&63|128;let o=[...i].map(e=>e.toString(16).padStart(2,`0`)).join(``);return`${o.slice(0,8)}-${o.slice(8,12)}-${o.slice(12,16)}-${o.slice(16,20)}-${o.slice(20)}`}function u(e,t){if(!e.trim())throw Error(`Comment ID is required for capture context`);if(!Number.isSafeInteger(t)||t<0)throw Error(`Capture child ordinal must be a non-negative integer`)}const d=131072,f=32768,p=4096,m=1e3;var h=class extends Error{constructor(e,t){super(e,t),this.name=`InstantCaptureIntegrityError`}};function g(e){let t=se(e,`comment target`,!0),n={kind:t.kind,anchor:pe(t.anchor),region:ge(t.region),elements:t.elements.map(e=>({selector:e.selector,tagName:e.tagName,textPreview:e.textPreview,rect:ge(e.rect),source:null,componentStack:[]})),pageUrl:t.pageUrl,pageTitle:t.pageTitle,capturedAt:t.capturedAt},r={elements:t.elements.map(e=>({selector:e.selector,source:e.source?_e(e.source):null,componentStack:e.componentStack.map(_e)})),...t.sourceProvenance?{sourceProvenance:ve(t.sourceProvenance)}:{}};E(n,d,`Public target`);let i=Te(r,65536,`Source context`);return{publicTarget:n,commentFields:te(n),targetElements:n.elements.map(ne),sourceContextJson:i}}function ee(e,t,n){let r=x(e,n),i={selector:S(r.anchorSelector,`${n} anchor selector`,p),offsetX:T(r.anchorOffsetX,`${n} anchor offsetX`),offsetY:T(r.anchorOffsetY,`${n} anchor offsetY`),viewportX:T(r.anchorViewportX,`${n} anchor viewportX`),viewportY:T(r.anchorViewportY,`${n} anchor viewportY`)},a=ie({kind:r.targetKind,anchor:i,region:{pageX:r.targetPageX,pageY:r.targetPageY,width:r.targetWidth,height:r.targetHeight,viewportX:r.targetViewportX,viewportY:r.targetViewportY,viewportWidth:r.targetViewportWidth,viewportHeight:r.targetViewportHeight},elements:[],pageUrl:he({origin:C(r.targetPageOrigin,`${n} page origin`,1024),pathname:C(r.targetPagePathname,`${n} page pathname`,4096),search:S(r.targetPageSearch,`${n} page search`,1024),hash:S(r.targetPageHash,`${n} page hash`,1024)}),pageTitle:r.targetPageTitle,capturedAt:r.targetCapturedAt},n),o=re(t,`${n} elements`),s=a;for(let e of o)try{s=ie({...a,elements:[...s.elements,e]},n)}catch{}return s}function _(e){let t=oe(e);return t?Object.entries(t).map(([e,t],n)=>typeof t==`string`?{ordinal:n,key:e,valueType:`string`,stringValue:t}:typeof t==`number`?{ordinal:n,key:e,valueType:`number`,numberValue:t}:typeof t==`boolean`?{ordinal:n,key:e,valueType:`boolean`,booleanValue:t}:{ordinal:n,key:e,valueType:`null`}):[]}function v(e){if(!Array.isArray(e)||e.length===0)return;let t=[...e].map(e=>{try{let t=x(e,`Comment scope entry`);return{row:t,ordinal:xe(t.ordinal,`Comment scope entry ordinal`,0,19),id:typeof t.id==`string`?t.id:``}}catch{return null}}).filter(e=>e!==null).sort((e,t)=>e.ordinal-t.ordinal||e.id.localeCompare(t.id)),n={},r=new Set;for(let{row:e,ordinal:i}of t)if(!r.has(i)){r.add(i);try{let t=C(e.key,`Comment scope key`,256);if(Object.hasOwn(n,t))continue;switch(e.valueType){case`string`:n[t]=S(e.stringValue,`Comment scope ${t}`,m);break;case`number`:n[t]=w(e.numberValue,`Comment scope ${t}`);break;case`boolean`:if(typeof e.booleanValue!=`boolean`)throw D(`Comment scope ${t} is invalid`);n[t]=e.booleanValue;break;case`null`:n[t]=null;break;default:throw D(`Comment scope ${t} is invalid`)}}catch{}}if(Object.keys(n).length!==0)try{return E(n,f,`Comment scope`),n}catch{return}}function te(e){let t=new URL(e.pageUrl);return{anchorSelector:e.anchor.selector,anchorOffsetX:e.anchor.offsetX,anchorOffsetY:e.anchor.offsetY,anchorViewportX:e.anchor.viewportX,anchorViewportY:e.anchor.viewportY,targetKind:e.kind,targetPageX:e.region.pageX,targetPageY:e.region.pageY,targetWidth:e.region.width,targetHeight:e.region.height,targetViewportX:e.region.viewportX,targetViewportY:e.region.viewportY,targetViewportWidth:e.region.viewportWidth,targetViewportHeight:e.region.viewportHeight,targetPageOrigin:t.origin,targetPagePathname:me(t.pathname),targetPageSearch:t.search.slice(1),targetPageHash:t.hash.slice(1),targetPageTitle:e.pageTitle,targetCapturedAt:e.capturedAt}}function ne(e,t){return{ordinal:t,selector:e.selector,tagName:e.tagName,textPreview:e.textPreview,pageX:e.rect.pageX,pageY:e.rect.pageY,width:e.rect.width,height:e.rect.height,viewportX:e.rect.viewportX,viewportY:e.rect.viewportY,viewportWidth:e.rect.viewportWidth,viewportHeight:e.rect.viewportHeight}}function re(e,t){if(!Array.isArray(e)||e.length===0)return[];let n=[...e].map(e=>{try{let n=x(e,t);return{row:n,ordinal:xe(n.ordinal,`${t} ordinal`,0,7),id:typeof n.id==`string`?n.id:``}}catch{return null}}).filter(e=>e!==null).sort((e,t)=>e.ordinal-t.ordinal||e.id.localeCompare(t.id)),r=[],i=new Set;for(let{row:e,ordinal:a}of n)if(!i.has(a)){i.add(a);try{r.push(ce({selector:e.selector,tagName:e.tagName,textPreview:e.textPreview,rect:{pageX:e.pageX,pageY:e.pageY,width:e.width,height:e.height,viewportX:e.viewportX,viewportY:e.viewportY,viewportWidth:e.viewportWidth,viewportHeight:e.viewportHeight},source:null,componentStack:[]},`${t}[${a}]`,!1))}catch{}}return r}function ie(e,t){return se(e,t,!1)}function y(e,t=`Comment body`){return C(e,t,2e4)}function ae(e,t=`Comment body`){let n=y(e,t);for(let e of n)if(e.trim())return e;throw D(`${t} is empty`)}function oe(e){if(e==null)return;let t=x(e,`Comment scope`);if(Object.keys(t).length>20)throw D(`Comment scope has too many fields`);let n={};for(let[e,r]of Object.entries(t)){if(!e.trim()||e.length>256)throw D(`Comment scope has an invalid key`);if(typeof r==`string`){if(r.length>m)throw D(`Comment scope ${e} is too long`);n[e]=r}else if(typeof r==`number`)n[e]=w(r,`Comment scope ${e}`);else if(typeof r==`boolean`||r===null)n[e]=r;else throw D(`Comment scope ${e} is invalid`)}return E(n,f,`Comment scope`),n}function se(e,t,n){let r=b(e,t,[`kind`,`anchor`,`region`,`elements`,`pageUrl`,`pageTitle`,`capturedAt`,`sourceProvenance`],[`sourceProvenance`]),i=r.kind;if(i!==`element`&&i!==`region`&&i!==`viewport`)throw D(`${t} kind is invalid`);let a=ye(r.elements,`${t} elements`);if(a.length>8)throw D(`${t} contains too many elements`);if(!n&&r.sourceProvenance!=null)throw D(`${t} exposes source provenance`);let o=C(r.pageUrl,`${t} pageUrl`,8192);we(o,`${t} pageUrl`);let s={kind:i,anchor:le(r.anchor,`${t} anchor`),region:ue(r.region,`${t} region`),elements:a.map((e,r)=>ce(e,`${t} elements[${r}]`,n)),pageUrl:o,pageTitle:S(r.pageTitle,`${t} pageTitle`,m),capturedAt:Se(r.capturedAt,`${t} capturedAt`),...n&&r.sourceProvenance!=null?{sourceProvenance:fe(r.sourceProvenance,`${t} provenance`)}:{}};return E(s,n?196608:d,t),s}function ce(e,t,n){let r=b(e,t,[`selector`,`tagName`,`textPreview`,`rect`,`source`,`componentStack`]),i=ye(r.componentStack,`${t} componentStack`);if(i.length>32)throw D(`${t} componentStack is too large`);if(!n&&(r.source!=null||i.length>0))throw D(`${t} exposes source metadata`);return{selector:C(r.selector,`${t} selector`,p),tagName:C(r.tagName,`${t} tagName`,128),textPreview:S(r.textPreview,`${t} textPreview`,m),rect:ue(r.rect,`${t} rect`),source:n&&r.source!=null?de(r.source,`${t} source`):null,componentStack:n?i.map((e,n)=>de(e,`${t} stack[${n}]`)):[]}}function le(e,t){let n=b(e,t,[`selector`,`offsetX`,`offsetY`,`viewportX`,`viewportY`]);return{selector:S(n.selector,`${t} selector`,p),offsetX:T(n.offsetX,`${t} offsetX`),offsetY:T(n.offsetY,`${t} offsetY`),viewportX:T(n.viewportX,`${t} viewportX`),viewportY:T(n.viewportY,`${t} viewportY`)}}function ue(e,t){let n=b(e,t,[`pageX`,`pageY`,`width`,`height`,`viewportX`,`viewportY`,`viewportWidth`,`viewportHeight`]),r={pageX:w(n.pageX,`${t} pageX`),pageY:w(n.pageY,`${t} pageY`),width:w(n.width,`${t} width`),height:w(n.height,`${t} height`),viewportX:w(n.viewportX,`${t} viewportX`),viewportY:w(n.viewportY,`${t} viewportY`),viewportWidth:w(n.viewportWidth,`${t} viewportWidth`),viewportHeight:w(n.viewportHeight,`${t} viewportHeight`)};if(r.width<0||r.height<0||r.viewportWidth<0||r.viewportHeight<0)throw D(`${t} has a negative dimension`);return r}function de(e,n){let r=b(e,n,[`filePath`,`lineNumber`,`columnNumber`,`componentName`,`origin`,`generated`],[`generated`]),i=r.origin;if(i!==`app`&&i!==`shared-ui`&&i!==`dependency`&&i!==`generated`&&i!==`unknown`)throw D(`${n} origin is invalid`);let a=C(r.filePath,`${n} filePath`,p);return{filePath:a,lineNumber:Ce(r.lineNumber,`${n} lineNumber`),columnNumber:Ce(r.columnNumber,`${n} columnNumber`),componentName:r.componentName==null?null:C(r.componentName,`${n} componentName`,512),origin:t(a)}}function fe(e,t){let n=b(e,t,[`provider`,`build`,`resolvedAt`]),r=n.provider;if(r!==`react-grab`&&r!==`embedded`&&r!==`custom`)throw D(`${t} provider is invalid`);let i=b(n.build,`${t} build`,[`buildId`,`gitCommit`,`generatedAt`,`mode`],[`generatedAt`]),a=i.mode;if(a!==`development`&&a!==`preview`&&a!==`production`)throw D(`${t} build mode is invalid`);return{provider:r,build:{buildId:C(i.buildId,`${t} buildId`,512),gitCommit:i.gitCommit==null?null:C(i.gitCommit,`${t} gitCommit`,256),...i.generatedAt==null?{}:{generatedAt:Se(i.generatedAt,`${t} generatedAt`)},mode:a},resolvedAt:Se(n.resolvedAt,`${t} resolvedAt`)}}function pe(e){return{...e}}function me(e){return e.replace(/\/+$/,``)||`/`}function he(e){return`${e.origin}${e.pathname}${e.search?`?${e.search}`:``}${e.hash?`#${e.hash}`:``}`}function ge(e){return{...e}}function _e(e){return{...e}}function ve(e){return{...e,build:{...e.build}}}function b(e,t,n,r=[]){let i=x(e,t);if(Object.keys(i).some(e=>!n.includes(e)))throw D(`${t} contains unknown fields`);for(let e of n)if(!r.includes(e)&&!Object.hasOwn(i,e))throw D(`${t} is missing ${e}`);return i}function x(e,t){if(!e||typeof e!=`object`||Array.isArray(e))throw D(`${t} is missing or invalid`);return e}function ye(e,t){if(!Array.isArray(e))throw D(`${t} is missing or invalid`);return e}function S(e,t,n){if(typeof e!=`string`||be(e,n)>n)throw D(`${t} is invalid or too long`);return e}function be(e,t){let n=0;for(let r of e)if(n+=1,n>t)return n;return n}function C(e,t,n){let r=S(e,t,n);if(!r.trim())throw D(`${t} is empty`);return r}function w(e,t){if(typeof e!=`number`||!Number.isFinite(e))throw D(`${t} is invalid`);return e}function xe(e,t,n,r){if(typeof e!=`number`||!Number.isSafeInteger(e)||e<n||e>r)throw D(`${t} is invalid`);return e}function T(e,t){let n=w(e,t);if(n<0||n>1)throw D(`${t} is outside 0..1`);return n}function Se(e,t){if(typeof e!=`number`||!Number.isSafeInteger(e)||e<0||e>0xe677d21fdbff)throw D(`${t} is invalid`);return e}function Ce(e,t){if(e===null)return null;if(typeof e!=`number`||!Number.isSafeInteger(e)||e<0)throw D(`${t} is invalid`);return e}function we(e,t){let n;try{n=new URL(e)}catch(e){throw D(`${t} is invalid`,e)}if(n.protocol!==`http:`&&n.protocol!==`https:`)throw D(`${t} must use HTTP or HTTPS`)}function E(e,t,n){Te(e,t,n)}function Te(e,t,n){let r;try{r=JSON.stringify(e)}catch(e){throw D(`${n} cannot be serialized`,e)}if(r.length>t)throw D(`${n} is too large`);return r}function D(e,t){return new h(e,{cause:t instanceof Error?t:void 0})}function Ee(e){if(!e.trim())throw Error(`InstantDB app ID is required`);return r({appId:e,schema:i,devtool:!1})}var De=class{db;session;#e;attachScreenshot;constructor(e,t,n={}){this.db=e,this.session=t,this.#e=n.commentTransport,this.#e&&(this.attachScreenshot=(e,t,n)=>this.#e.uploadScreenshot({pageId:e,commentId:t,screenshot:n}))}async getSnapshot(e){let{data:t}=await this.db.queryOnce(Oe(e,this.session.authUserId));return Ae(e,t.comments,t.replies)}async getProjectSnapshot(e){this.#t(e);let{data:t}=await this.db.queryOnce(ke(e,this.session.authUserId));return je(e,t.comments,t.replies)}subscribe(e,t,n){return this.db.subscribeQuery(Oe(e,this.session.authUserId),r=>{if(r.error){n?.(Re(r.error));return}if(r.data)try{t(Ae(e,r.data.comments,r.data.replies))}catch{n?.({type:`error`,code:`data-integrity`,recovery:`retry`,clearSnapshot:!0})}})}subscribeProject(e,t,n){return this.#t(e),this.db.subscribeQuery(ke(e,this.session.authUserId),r=>{if(r.error){n?.(Re(r.error));return}if(r.data)try{t(je(e,r.data.comments,r.data.replies))}catch{n?.({type:`error`,code:`data-integrity`,recovery:`retry`,clearSnapshot:!0})}})}async mutate(e,t){switch(t.type){case`comment.upsert`:{if(t.comment.pageId!==e)throw Error(`Comment page mismatch`);let n=t.comment;if(n.authorId!==this.session.reviewerId)throw Error(`Comment author mismatch`);let r=y(n.body).trim(),i=ae(r),a=M(n.createdAt,`Comment createdAt`),l=M(n.updatedAt,`Comment updatedAt`);if(l<a)throw new h(`Comment updatedAt precedes createdAt`);if(n.createdAt!==n.updatedAt)throw new h(`Comment edits must go through the review service`);if(n.status!==`open`||n.resolvedAt!==void 0||n.resolvedById!==void 0)throw new h(`New comments must start open`);let u=g(n.target);if(!Ie(n.anchor,u.publicTarget.anchor))throw new h(`Comment anchor does not match its target`);if(this.#e){await this.#e.createComment({pageId:e,commentId:n.id,body:r,target:n.target,...n.scope===void 0?{}:{scope:n.scope}});return}let d=_(n.scope),f=await Promise.all(u.targetElements.map(async e=>({element:e,id:await s(n.id,`element`,e.ordinal),slotKey:o(n.id,`element`,e.ordinal)}))),p=await Promise.all(d.map(async e=>({entry:e,id:await s(n.id,`scope`,e.ordinal),slotKey:o(n.id,`scope`,e.ordinal)}))),m=await c(n.id);await this.db.transact([this.db.tx.comments[n.id].update({pageId:e,authorId:this.session.reviewerId,authorAuthUserId:this.session.authUserId,authorName:this.session.displayName,body:r,bodyContentMarker:i,...u.commentFields,status:n.status,workflowRevision:0,createdAt:a,updatedAt:l}).link({page:e,author:this.session.reviewerId}),...f.map(({element:e,id:t,slotKey:r})=>this.db.tx.commentTargetElements[t].update({commentId:n.id,slotKey:r,authorAuthUserId:this.session.authUserId,...e}).link({comment:n.id})),...p.map(({entry:e,id:t,slotKey:r})=>this.db.tx.commentScopeEntries[t].update({commentId:n.id,slotKey:r,authorAuthUserId:this.session.authUserId,...e}).link({comment:n.id})),this.db.tx.commentSourceContexts[m].update({commentId:n.id,pageId:e,authorAuthUserId:this.session.authUserId,contextJson:u.sourceContextJson,createdAt:a}).link({comment:n.id,page:e,author:this.session.reviewerId})]);return}case`comment.delete`:throw new h(`Comment deletion must go through the review service`);case`reply.upsert`:{let n=t.reply;if(n.authorId!==this.session.reviewerId)throw Error(`Reply author mismatch`);let r=y(n.body,`Reply body`).trim(),i=ae(r,`Reply body`),a=M(n.createdAt,`Reply createdAt`),o=M(n.updatedAt,`Reply updatedAt`);if(o<a)throw new h(`Reply updatedAt precedes createdAt`);if(n.createdAt!==n.updatedAt)throw new h(`Reply edits must go through the review service`);if(this.#e){await this.#e.createReply({commentId:n.commentId,replyId:n.id,body:r});return}await this.db.transact(this.db.tx.replies[n.id].update({pageId:e,commentId:n.commentId,authorId:this.session.reviewerId,authorAuthUserId:this.session.authUserId,authorName:this.session.displayName,body:r,bodyContentMarker:i,createdAt:a,updatedAt:o}).link({comment:n.commentId,author:this.session.reviewerId}));return}case`reply.delete`:throw new h(`Reply deletion must go through the review service`)}}#t(e){if(!e.trim()||e!==this.session.projectId)throw Error(`Project does not belong to the reviewer session`)}};function Oe(e,t){return{comments:{$:{where:{pageId:e},order:{createdAt:`asc`}},targetElements:{},scopeEntries:{}},replies:{$:{where:{pageId:e},order:{createdAt:`asc`}}},$users:{$:{where:{id:t}},activeReviewInvitation:{project:{}}}}}function ke(e,t){return{comments:{$:{where:{"page.project.id":e},order:{createdAt:`asc`}},page:{project:{}},targetElements:{},scopeEntries:{}},replies:{$:{where:{"comment.page.project.id":e},order:{createdAt:`asc`}},comment:{page:{project:{}}}},$users:{$:{where:{id:t}},activeReviewInvitation:{project:{}}}}}function Ae(e,t,n){let r=t.map(t=>Ne(t,e));O(r,`comment`);let i=new Set(r.map(({id:e})=>e)),a=n.map(t=>Pe(t,e));O(a,`reply`);for(let e of a)if(!i.has(e.commentId))throw new h(`Reply ${e.id} references a comment outside the page snapshot`);return{pageId:e,comments:r,replies:a}}function je(e,t,n){let r=new Map,i=t.map(t=>{let n=A(t.pageId,`comment pageId`);Me(t.page,n,e,`comment ${String(t.id)}`);let i=k(t.page,`comment ${String(t.id)} page`),a=Ne(t,n),o=`/`;try{o=new URL(a.target.pageUrl).pathname||`/`}catch{}return r.set(n,{id:n,name:typeof i.name==`string`&&i.name.trim()?i.name.trim():a.target.pageTitle.trim()||o,pathname:typeof i.pathname==`string`&&i.pathname.trim()?i.pathname.trim():o}),a});O(i,`comment`);let a=new Map(i.map(e=>[e.id,e])),o=n.map(t=>{let n=A(t.pageId,`reply pageId`),r=k(t.comment,`reply ${String(t.id)} comment`),i=A(t.commentId,`reply ${String(t.id)} commentId`);if(A(r.id,`reply ${String(t.id)} comment relation id`)!==i)throw new h(`Reply ${String(t.id)} has an inconsistent comment relation`);Me(r.page,n,e,`reply ${String(t.id)}`);let o=Pe(t,n),s=a.get(o.commentId);if(!s||s.pageId!==n)throw new h(`Reply ${o.id} references a comment outside the project snapshot`);return o});return O(o,`reply`),{projectId:e,pages:[...r.values()].sort((e,t)=>e.pathname.localeCompare(t.pathname)||e.id.localeCompare(t.id)),comments:i,replies:o}}function Me(e,t,n,r){let i=k(e,`${r} page`);if(A(i.id,`${r} page id`)!==t)throw new h(`${r} escaped its page relation`);if(A(k(i.project,`${r} project`).id,`${r} project id`)!==n)throw new h(`${r} escaped its project scope`)}function Ne(e,t){let n=k(e,`comment`),r=A(n.id,`comment id`);if(A(n.pageId,`comment ${r} pageId`)!==t)throw new h(`Comment ${r} escaped its page scope`);A(n.authorAuthUserId,`comment ${r} authorAuthUserId`);let i=!(Object.hasOwn(n,`anchor`)&&Object.hasOwn(n,`target`)),a=i?ee(n,n.targetElements,`comment ${r} target`):ie(n.target,`comment ${r} target`),o=i?{...a.anchor}:Fe(n.anchor,`comment ${r} anchor`);if(!Ie(o,a.anchor))throw new h(`Comment ${r} has inconsistent anchors`);let s=n.status;if(s!==`open`&&s!==`resolved`)throw new h(`Comment ${r} has an invalid status`);let c=M(n.createdAt,`comment ${r} createdAt`),l=M(n.updatedAt,`comment ${r} updatedAt`);if(l<c)throw new h(`Comment ${r} updatedAt precedes createdAt`);let u=He(n.resolvedAt,`comment ${r} resolvedAt`),d=Ue(n.resolvedById,`comment ${r} resolvedById`);if(s===`open`&&(u!==void 0||d!==void 0))throw new h(`Open comment ${r} contains resolution metadata`);if(s===`resolved`&&(u===void 0||d===void 0||u!==l))throw new h(`Resolved comment ${r} has invalid workflow metadata`);return{id:r,pageId:t,authorId:A(n.authorId,`comment ${r} authorId`),authorName:A(n.authorName,`comment ${r} authorName`),body:y(n.body,`comment ${r} body`),anchor:o,target:a,...i?Le(v(n.scopeEntries)):n.scope==null?{}:{scope:oe(n.scope)},status:s,workflowRevision:Ve(n.workflowRevision,`comment ${r} workflowRevision`),createdAt:c,updatedAt:l,...u===void 0?{}:{resolvedAt:u},...d===void 0?{}:{resolvedById:d}}}function Pe(e,t){let n=k(e,`reply`),r=A(n.id,`reply id`);if(A(n.pageId,`reply ${r} pageId`)!==t)throw new h(`Reply ${r} escaped its page scope`);A(n.authorAuthUserId,`reply ${r} authorAuthUserId`);let i=M(n.createdAt,`reply ${r} createdAt`),a=M(n.updatedAt,`reply ${r} updatedAt`);if(a<i)throw new h(`Reply ${r} updatedAt precedes createdAt`);return{id:r,commentId:A(n.commentId,`reply ${r} commentId`),authorId:A(n.authorId,`reply ${r} authorId`),authorName:A(n.authorName,`reply ${r} authorName`),body:y(n.body,`reply ${r} body`),createdAt:i,updatedAt:a}}function Fe(e,t){let n=k(e,t);if(Object.keys(n).length!==5||!Object.hasOwn(n,`selector`)||!Object.hasOwn(n,`offsetX`)||!Object.hasOwn(n,`offsetY`)||!Object.hasOwn(n,`viewportX`)||!Object.hasOwn(n,`viewportY`))throw new h(`${t} has invalid fields`);return{selector:Be(n.selector,`${t} selector`),offsetX:j(n.offsetX,`${t} offsetX`),offsetY:j(n.offsetY,`${t} offsetY`),viewportX:j(n.viewportX,`${t} viewportX`),viewportY:j(n.viewportY,`${t} viewportY`)}}function Ie(e,t){return e.selector===t.selector&&e.offsetX===t.offsetX&&e.offsetY===t.offsetY&&e.viewportX===t.viewportX&&e.viewportY===t.viewportY}function Le(e){return e===void 0?{}:{scope:e}}function O(e,t){let n=new Set;for(let r of e){if(n.has(r.id))throw new h(`Duplicate ${t} ${r.id}`);n.add(r.id)}}function Re(e){let t=ze(e).toLowerCase();return t.includes(`expired`)||t.includes(`token`)?{type:`access-lost`,code:`session-expired`,recovery:`reauthenticate`,clearSnapshot:!0}:t.includes(`permission`)||t.includes(`forbidden`)||t.includes(`unauthorized`)?{type:`access-lost`,code:`permission-denied`,recovery:`reauthenticate`,clearSnapshot:!0}:{type:`error`,code:`transport`,recovery:`retry`,clearSnapshot:!0}}function ze(e){return e instanceof Error?e.message:e&&typeof e==`object`&&`message`in e?String(e.message):``}function k(e,t){if(!e||typeof e!=`object`||Array.isArray(e))throw new h(`${t} is missing or invalid`);return e}function Be(e,t){if(typeof e!=`string`)throw new h(`${t} is invalid`);return e}function A(e,t){let n=Be(e,t);if(!n.trim())throw new h(`${t} is empty`);return n}function j(e,t){if(typeof e!=`number`||!Number.isFinite(e)||e<0||e>1)throw new h(`${t} is invalid`);return e}function M(e,t){if(!Number.isSafeInteger(e)||e<0||e>0xe677d21fdbff)throw new h(`${t} is invalid`);return e}function Ve(e,t){if(!Number.isSafeInteger(e)||e<0)throw new h(`${t} is invalid`);return e}function He(e,t){return e==null?void 0:M(e,t)}function Ue(e,t){return e==null?void 0:A(e,t)}Object.freeze({field:`createdAt`,direction:`desc`,tieBreaker:`id`,tieDirection:`desc`}),Object.freeze({comments:200,replies:1e3,sourceContexts:200});var We=class{db;session;roomCredential;#e=new Map;constructor(e,t,n){this.db=e,this.session=t,this.roomCredential=n}subscribe(e,t,n,r){let i=[],a=[],o=!1,s=[],c=()=>{o||n({pageId:e,peers:structuredClone(i),messages:structuredClone(a)})};if(t.cursors){let n=et(e,t.roomId),a,l,u=this.roomCredential?.id===t.roomId?this.roomCredential:void 0,d=u??{id:t.roomId,expiresAt:2**53-1,refresh:async()=>void 0},f=t=>{let o=this.db.joinRoom(`visualReview`,t),s=o.subscribePresence({},e=>{if(e.error){r?.(nt(e.error));return}i=Object.values(e.peers).map(e=>Ke(e)).filter(e=>e!==null).sort((e,t)=>e.displayName.localeCompare(t.displayName)||e.peerId.localeCompare(t.peerId)),c()}),l=a;a=()=>{s(),o.leaveRoom()},this.#e.set(n,{pageId:e,roomId:t,publishPresence:e=>o.publishPresence(e)}),l?.()},p=()=>{if(!u||o)return;let e=Math.max(1e3,d.expiresAt-Date.now()+250);l=setTimeout(()=>{m()},e)},m=async()=>{try{let e=await d.refresh();if(o||!e)return;d={...e,refresh:d.refresh},u&&(u.id=e.id,u.expiresAt=e.expiresAt),f(e.id),p()}catch(e){if(o)return;r?.(nt(e)),o||(l=setTimeout(()=>{m()},5e3))}};f(d.id),p(),s.push(()=>{l&&clearTimeout(l),this.#e.delete(n),a?.()})}return t.chat&&s.push(this.db.subscribeQuery(Ge(e,this.session.authUserId),t=>{if(t.error){r?.(nt(t.error));return}if(t.data)try{a=t.data.reviewMessages.map(t=>Ye(t,e)).sort(tt),c()}catch{r?.({type:`error`,code:`data-integrity`,recovery:`retry`,clearSnapshot:!0})}})),queueMicrotask(c),()=>{if(!o){o=!0;for(let e of s.reverse())try{e()}catch{}}}}publishPresence(e,t,n){let r=this.#e.get(et(e,t));r&&r.publishPresence({reviewerId:this.session.reviewerId,displayName:this.session.displayName,color:n.color,active:n.active,pathname:Je(n.pathname),...n.cursorX===void 0?{}:{cursorX:n.cursorX},...n.cursorY===void 0?{}:{cursorY:n.cursorY},...n.viewportWidth===void 0?{}:{viewportWidth:n.viewportWidth},...n.viewportHeight===void 0?{}:{viewportHeight:n.viewportHeight},cursorChat:qe(n.cursorChat)})}async sendMessage(e,t){if(t.pageId!==e)throw Error(`Review message page mismatch`);if(t.authorId!==this.session.reviewerId)throw Error(`Review message author mismatch`);let n=Xe(t.body),r=Ze(t.pathname),i=F(t.createdAt,`Review message createdAt`),a=F(t.updatedAt,`Review message updatedAt`);if(i!==a)throw Error(`New review messages must be immutable`);await this.db.transact(this.db.tx.reviewMessages[t.id].update({pageId:e,pathname:r,authorId:this.session.reviewerId,authorAuthUserId:this.session.authUserId,authorName:this.session.displayName,body:n,bodyContentMarker:ae(n,`Review message body`),createdAt:i,updatedAt:a}).link({page:e,author:this.session.reviewerId}))}};function Ge(e,t){return{reviewMessages:{$:{where:{pageId:e},order:{createdAt:`asc`}}},$users:{$:{where:{id:t}},activeReviewInvitation:{project:{}}}}}function Ke(e){let t=Qe(e.reviewerId,128),n=Qe(e.displayName,512),r=typeof e.color==`string`&&/^#[0-9a-f]{6}$/iu.test(e.color)?e.color:null;if(!t||!n||!r||typeof e.active!=`boolean`)return null;let i=P(e.cursorX),a=P(e.cursorY),o=$e(e.viewportWidth),s=$e(e.viewportHeight),c=qe(e.cursorChat),l=Je(e.pathname);return{peerId:e.peerId,reviewerId:t,displayName:n,color:r,active:e.active,pathname:l,...i===void 0?{}:{cursorX:i},...a===void 0?{}:{cursorY:a},...o===void 0?{}:{viewportWidth:o},...s===void 0?{}:{viewportHeight:s},...c?{cursorChat:c}:{}}}function qe(e){return typeof e==`string`?e.trim().slice(0,280):``}function Je(e){if(typeof e!=`string`)return`/`;let t=e.trim();return t.startsWith(`/`)?t.slice(0,2e3):`/`}function Ye(e,t){let n=N(e.id,`Review message id`,128);if(N(e.pageId,`Review message pageId`,128)!==t)throw Error(`Review message page mismatch`);return{id:n,pageId:t,pathname:Ze(e.pathname),authorId:N(e.authorId,`Review message authorId`,128),authorName:N(e.authorName,`Review message authorName`,512),body:Xe(e.body),createdAt:F(e.createdAt,`Review message createdAt`),updatedAt:F(e.updatedAt,`Review message updatedAt`)}}function Xe(e){return N(e,`Review message body`,4e3)}function Ze(e){let t=N(e,`Review message pathname`,2e3);if(!t.startsWith(`/`))throw Error(`Review message pathname is invalid`);return t}function N(e,t,n){if(typeof e!=`string`)throw Error(`${t} is invalid`);let r=e.trim();if(!r||r.length>n)throw Error(`${t} is invalid`);return r}function Qe(e,t){if(typeof e!=`string`)return null;let n=e.trim();return n&&n.length<=t?n:null}function P(e){return typeof e==`number`&&Number.isFinite(e)?e:void 0}function $e(e){let t=P(e);return t!==void 0&&t>0?t:void 0}function F(e,t){if(!Number.isSafeInteger(e)||e<0)throw Error(`${t} is invalid`);return e}function et(e,t){return JSON.stringify([e,t])}function tt(e,t){return e.createdAt-t.createdAt||e.id.localeCompare(t.id)}function nt(e){let t=e&&typeof e==`object`&&`code`in e?String(e.code):``;if(/^INVITATION_(?:EXPIRED|NOT_FOUND|REQUIRED|REVOKED)$/u.test(t))return{type:`access-lost`,code:t===`INVITATION_EXPIRED`?`session-expired`:`membership-revoked`,recovery:`reauthenticate`,clearSnapshot:!0};let n=String(e instanceof Error||e&&typeof e==`object`&&`message`in e?e.message:e).toLowerCase();return n.includes(`expired`)||n.includes(`token`)?{type:`access-lost`,code:`session-expired`,recovery:`reauthenticate`,clearSnapshot:!0}:n.includes(`permission`)||n.includes(`forbidden`)||n.includes(`unauthorized`)?{type:`access-lost`,code:`permission-denied`,recovery:`reauthenticate`,clearSnapshot:!0}:{type:`error`,code:`transport`,recovery:`retry`,clearSnapshot:!0}}Object.freeze({field:`createdAt`,direction:`desc`,tieBreaker:`id`,tieDirection:`desc`});const I={$default:`false`},L={$default:`false`},R=`$user.activeReviewInvitation.project.id`;function z(e){return[`auth.id != null`,`size(auth.ref('$user.activeReviewInvitation.id')) == 1`,`size(auth.ref('${R}')) == 1`,`size(auth.ref('$user.activeReviewInvitation.status')) == 1`,`size(auth.ref('$user.activeReviewInvitation.expiresAt')) == 1`,`size(auth.ref('$user.activeReviewInvitation.revokedAt')) == 0`,`size(auth.ref('$user.activeReviewInvitation.project.originDisconnectedAt')) == 0`,`auth.ref('$user.activeReviewInvitation.status')[0] == 'accepted'`,`request.time < timestamp(auth.ref('$user.activeReviewInvitation.expiresAt')[0])`,e].join(` && `)}function B(...e){return e.map(e=>`(${e})`).join(` && `)}function V(...e){return e.map(e=>`(${e})`).join(` || `)}function H(e,t){return`!has(${e}.${t}) || ${e}.${t} == null`}const rt=`actions.data == 'create' && actions.linkedData == 'update'`,it=e=>`${e}.matches('[^ \\t\\n\\r\\f\\u000b\\u00a0\\u1680\\u2000-\\u200a\\u2028\\u2029\\u202f\\u205f\\u3000\\ufeff]')`,at=e=>B(`${e} >= 0`,`${e} <= 253402300799999`,`${e} % 1 == 0`),ot=e=>B(at(e),`(request.time - timestamp(${e})).getSeconds() <= 86400`,`(request.time - timestamp(${e})).getSeconds() >= -300`);function U(e){let t=`data.ref('${e}project.allowedOrigin')`,n=`data.ref('${e}stagingOrigin')`;return V(`size(${t}) == 0`,B(`size(${n}) == 1`,`${n}[0] in ${t}`))}const st=z(`auth.ref('${R}')[0] in data.ref('project.id')`);V(`size(data.ref('project.allowedOrigin')) == 0`,B(`has(data.stagingOrigin) && data.stagingOrigin != null`,`data.stagingOrigin in data.ref('project.allowedOrigin')`)),B(`actions.data == 'update' && actions.linkedData == 'create'`,V(`auth.id != null && auth.id in data.ref('project.owners.id')`,st));const ct=z(`auth.ref('${R}')[0] in data.ref('page.project.id')`);U(`page.`),B(rt,V(`auth.id != null && auth.id in data.ref('page.project.owners.id')`,ct),`auth.id != null && auth.id == data.authorAuthUserId && auth.id in data.ref('author.$user.id')`,`data.pageId in data.ref('page.id')`,`data.authorId in data.ref('author.id') && data.authorAuthUserId in data.ref('author.$user.id') && data.authorName in data.ref('author.displayName')`,`data.pageId in data.ref('author.project.pages.id')`),B(rt,`data.pageId == linkedData.id`,`auth.id != null && auth.id == data.authorAuthUserId`,`data.authorId in auth.ref('$user.reviewerMemberships.id')`,`data.authorId in linkedData.ref('project.reviewers.id')`,V(`auth.id != null && auth.id in linkedData.ref('project.owners.id')`,z(`auth.ref('${R}')[0] in linkedData.ref('project.id')`))),V(`auth.id != null && auth.id in data.ref('comment.page.project.owners.id')`,B(z(`auth.ref('${R}')[0] in data.ref('comment.page.project.id')`),U(`comment.page.`))),z(`auth.ref('${R}')[0] in data.ref('comment.page.project.id')`),U(`comment.page.`),z(`auth.ref('${R}')[0] in data.ref('page.project.id')`),U(`page.`);const lt=B(`data.reviewerId != null`,`data.projectId in data.ref('project.id')`,`data.reviewerId in data.ref('reviewer.id')`,`data.projectId in data.ref('reviewer.project.id')`,`auth.id in data.ref('reviewer.$user.id')`,`auth.email in data.ref('reviewer.email')`);B(`auth.id != null`,`data.revokedAt == null`,`data.status in ['pending', 'accepted']`,`data.status == 'pending' || data.claimedByAuthUserId == auth.id`,`request.time < timestamp(data.expiresAt)`,`request.modifiedFields.all(field, field in ['status', 'claimedByAuthUserId', 'acceptedAt', 'claimRevision', 'activeUser'])`,`'status' in request.modifiedFields`,`'claimedByAuthUserId' in request.modifiedFields`,`'acceptedAt' in request.modifiedFields`,`'claimRevision' in request.modifiedFields`,`'activeUser' in request.modifiedFields`,`newData.status == 'accepted'`,`newData.claimedByAuthUserId == auth.id`,`newData.claimRevision == data.claimRevision + 1`,`math.abs((request.time - timestamp(newData.acceptedAt)).getMinutes()) <= 1`,lt),B(`actions.data == 'update'`,`actions.linkedData == 'update'`,`auth.id != null`,`auth.email != null`,`linkedData.id == auth.id`,`linkedData.email == auth.email`,`data.email == auth.email`,`data.revokedAt == null`,`data.status in ['pending', 'accepted']`,`data.status == 'pending' || data.claimedByAuthUserId == auth.id`,`request.time < timestamp(data.expiresAt)`,`newData.status == 'accepted'`,`newData.claimedByAuthUserId == auth.id`,`newData.claimRevision == data.claimRevision + 1`,`math.abs((request.time - timestamp(newData.acceptedAt)).getMinutes()) <= 1`,lt),B(`actions.data == 'update'`,`actions.linkedData == 'update'`,`auth.id != null`,`auth.email != null`,`data.id == auth.id`,`data.email == auth.email`,`linkedData.email == auth.email`,`linkedData.revokedAt == null`,`linkedData.status == 'accepted'`,`linkedData.claimedByAuthUserId == auth.id`,`request.time < timestamp(linkedData.expiresAt)`,`math.abs((request.time - timestamp(linkedData.acceptedAt)).getMinutes()) <= 1`,`linkedData.projectId in linkedData.ref('project.id')`,`linkedData.reviewerId in linkedData.ref('reviewer.id')`,`linkedData.projectId in linkedData.ref('reviewer.project.id')`,`auth.id in linkedData.ref('reviewer.$user.id')`,`auth.email in linkedData.ref('reviewer.email')`),B(`auth.id != null`,`auth.email != null`,`linkedData.id == auth.id`,`linkedData.email == auth.email`,`data.email == auth.email`,`data.claimedByAuthUserId == auth.id`,`auth.id in data.ref('activeUser.id')`),B(`auth.id != null`,`auth.email != null`,`data.id == auth.id`,`data.email == auth.email`,`linkedData.email == auth.email`,`linkedData.claimedByAuthUserId == auth.id`,`auth.id in linkedData.ref('activeUser.id')`),{...I},{...I},{...L},{...L},z(`data.id == auth.ref('${R}')[0]`),{...I},B(`isOwner`,V(B(H(`data`,`allowedOrigin`),H(`newData`,`allowedOrigin`)),`newData.allowedOrigin == data.allowedOrigin`),V(B(H(`data`,`originDisconnectedAt`),H(`newData`,`originDisconnectedAt`)),`newData.originDisconnectedAt == data.originDisconnectedAt`)),{...L},{...I},B(`isOwner`,V(B(H(`data`,`autoRegistrationSlot`),H(`newData`,`autoRegistrationSlot`)),`newData.autoRegistrationSlot == data.autoRegistrationSlot`)),{...L},{...I},{...L},z(`auth.ref('${R}')[0] in data.ref('project.id')`),{...I},{...L},{...I},{...I},{...L},{...L},{...I},{...L},{...I},{...I},{...I},{...I},{...I},B(`data.createdAt == data.updatedAt`,ot(`data.createdAt`),`size(data.body) > 0`,`size(data.body) <= 4000`,`size(data.bodyContentMarker) == 1`,it(`data.bodyContentMarker`),`data.body.startsWith(data.bodyContentMarker)`,`size(data.authorName) > 0`,`size(data.authorName) <= 512`,it(`data.authorName`),`size(data.pathname) > 0`,`size(data.pathname) <= 2000`,`request.modifiedFields.all(field, field in ['pageId', 'pathname', 'authorId', 'authorAuthUserId', 'authorName', 'body', 'bodyContentMarker', 'createdAt', 'updatedAt', 'page', 'author'])`),{...I},{...L};var W=class extends Error{code;constructor(e,t){super(t),this.code=e,this.name=`ReviewerCommentSaveError`}};function ut(e,t){let n=e.replace(/\/+$/,``),r=async(e,r)=>{let i=await t();if(!i)throw new W(`AUTH_REQUIRED`,`로그인 세션이 만료되었습니다. 새로고침 후 다시 시도해 주세요.`);let a;try{a=await fetch(`${n}${e}`,{method:`POST`,headers:{authorization:`Bearer ${i}`,"content-type":`application/json`},body:JSON.stringify(r)})}catch{throw new W(`NETWORK`,`리뷰 서버에 연결하지 못했습니다. 연결을 확인하고 다시 시도해 주세요.`)}if(!a.ok)throw new W(...await ft(a))};return{createComment:e=>r(`/v1/comments`,e),createReply:e=>r(`/v1/replies`,e),uploadScreenshot:async({pageId:e,commentId:r,screenshot:i})=>{let a=await t();if(!a)throw new W(`AUTH_REQUIRED`,`로그인 세션이 만료되어 위치 캡처를 저장하지 못했습니다.`);let o;try{o=await fetch(`${n}/v1/comments/${encodeURIComponent(r)}/screenshot`,{method:`PUT`,headers:{authorization:`Bearer ${a}`,"content-type":i.contentType,"x-review-page-id":e,"x-review-image-width":String(i.width),"x-review-image-height":String(i.height)},body:dt(i.bytes)})}catch{throw new W(`NETWORK`,`리뷰 서버에 연결하지 못해 위치 캡처를 저장하지 못했습니다.`)}if(!o.ok)throw new W(...await ft(o))}}}function dt(e){let t=new Uint8Array(e.byteLength);return t.set(e),t.buffer}async function ft(e){let t=e.status>=500?`리뷰 서버가 코멘트를 저장하지 못했습니다. 잠시 후 다시 시도해 주세요.`:`코멘트를 저장하지 못했습니다.`;try{let n=await e.json();if(!n||typeof n!=`object`)return[`UNKNOWN`,t];let r=n;return[typeof r.error==`string`?r.error:`UNKNOWN`,typeof r.message==`string`&&r.message.trim()?r.message:t]}catch{return[`UNKNOWN`,t]}}var G=class extends Error{code;constructor(e,t){super(t),this.code=e,this.name=`ReviewBootstrapError`}};const K=new Map;function pt(e,t={}){let n=e.trim();if(!n)throw Error(`InstantDB app ID is required`);return{async resolve(e){let r=(t.databaseFactory??Ee)(n),i=await gt(n,r,e.authHost,e.signal,e.styleNonce,t.reviewerToken);for(;;)try{await mt(t.acceptInvitation,{refreshToken:i.refresh_token,invitationId:e.invitationId,suggestedDisplayName:kt(i.email),authHost:e.authHost,signal:e.signal,styleNonce:e.styleNonce});break}catch(a){if(!At(a,`INVITATION_EMAIL_MISMATCH`))throw a;await St(e.authHost,e.signal,e.styleNonce),i=await _t(n,r,i,e.authHost,e.signal,e.styleNonce,t.reviewerToken)}let{data:a}=await r.queryOnce({reviewers:{$:{where:{authUserId:i.id}}},reviewPages:{$:{where:{stagingOrigin:e.location.origin}}},invitations:{}}),o=ht(a.invitations,a.reviewers,a.reviewPages,{invitationId:e.invitationId,authUserId:i.id,email:i.email??``,location:e.location,now:Date.now()});if(!o.ok)throw new G(o.code,Pt(o.code));let s={authUserId:i.id,reviewerId:o.reviewer.id,projectId:o.reviewer.projectId,invitationId:e.invitationId,email:o.reviewer.email||i.email||``,displayName:o.reviewer.displayName||i.email||`Reviewer`,role:o.reviewer.role===`agency`?`agency`:`reviewer`},c=o.page.id,l=e.collaboration?.scopeId,u=(e.collaboration?.cursors===!0||e.collaboration?.chat===!0)&&t.resolveCollaborationRoom?await t.resolveCollaborationRoom({refreshToken:i.refresh_token,invitationId:e.invitationId,pageId:o.page.id,scopeId:e.collaboration.scopeId,signal:e.signal}):void 0,d=u&&t.resolveCollaborationRoom?{...u,refresh:async()=>{let n=await r.getAuth();if(!(!n?.refresh_token||l===void 0))return t.resolveCollaborationRoom?.({refreshToken:n.refresh_token,invitationId:e.invitationId,pageId:c,scopeId:l,signal:new AbortController().signal})}}:void 0,f=0;return{pageId:o.page.id,resolvePage:async n=>{let i=++f,a=()=>i!==f||n.signal.aborted,o=(e,t,n)=>({pageId:e,...n&&d?{collaborationRoomId:n.id}:{},commit:()=>{a()||(c=e,t!==void 0&&(l=t),!(!n||!d)&&(d.id=n.id,d.expiresAt=n.expiresAt))}});if(n.location.origin!==e.location.origin)throw new G(`PAGE_NOT_FOUND`,Pt(`PAGE_NOT_FOUND`));let{data:u}=await r.queryOnce({reviewPages:{$:{where:{stagingOrigin:n.location.origin}}}});if(a())throw jt();let p=Z(n.location.pathname),m=u.reviewPages.find(e=>e.projectId===s.projectId&&e.stagingOrigin===n.location.origin&&Z(e.pathname)===p);if(!m)throw new G(`PAGE_NOT_FOUND`,Pt(`PAGE_NOT_FOUND`));if(n.collaboration?.cursors!==!0&&n.collaboration?.chat!==!0||d===void 0||t.resolveCollaborationRoom===void 0||!n.collaboration)return o(m.id,n.collaboration?.scopeId);let h=await r.getAuth();if(a())throw jt();if(!h?.refresh_token)throw Error(`리뷰 세션이 만료되어 실시간 협업 연결을 갱신할 수 없습니다.`);let g=await t.resolveCollaborationRoom({refreshToken:h.refresh_token,invitationId:e.invitationId,pageId:m.id,scopeId:n.collaboration.scopeId,signal:n.signal});if(a())throw jt();return o(m.id,n.collaboration.scopeId,g)},session:s,repository:new De(r,s,{...t.serviceUrl===void 0?{}:{commentTransport:ut(t.serviceUrl,async()=>(await r.getAuth())?.refresh_token??null)}}),...e.collaboration?.cursors===!0||e.collaboration?.chat===!0?{collaborationRepository:new We(r,s,d)}:{},...(e.collaboration?.cursors===!0||e.collaboration?.chat===!0)&&d?{collaborationRoomId:d.id}:{},allowedStagingHosts:[e.location.hostname]}}}}async function mt(e,t){if(!e)return;let n={refreshToken:t.refreshToken,invitationId:t.invitationId,signal:t.signal};try{await e(n);return}catch(e){if(!At(e,`DISPLAY_NAME_REQUIRED`))throw e}let r=await xt(t.authHost,t.signal,t.suggestedDisplayName,t.styleNonce);await e({...n,displayName:r})}function ht(e,t,n,r){let i=e.find(({id:e})=>e===r.invitationId);if(!i||Nt(i.email)!==Nt(r.email))return{ok:!1,code:`INVITATION_REQUIRED`};if(i.status===`revoked`)return{ok:!1,code:`INVITATION_REVOKED`};if(i.status===`expired`||i.expiresAt<=r.now)return{ok:!1,code:`INVITATION_EXPIRED`};if(i.status!==`accepted`)return{ok:!1,code:`INVITATION_NOT_ACCEPTED`};let a=t.find(e=>e.authUserId===r.authUserId&&e.projectId===i.projectId);if(!a)return{ok:!1,code:`MEMBERSHIP_REQUIRED`};let o=Z(r.location.pathname),s=n.find(e=>e.projectId===i.projectId&&e.stagingOrigin===r.location.origin&&Z(e.pathname)===o);return s?{ok:!0,invitation:i,reviewer:a,page:s}:{ok:!1,code:`PAGE_NOT_FOUND`}}async function gt(e,t,n,r,i,a){let o=await q(r,()=>t.getAuth());if(o)return o;let s=await vt(e,r);try{return await q(r,()=>t.getAuth())||(a?await q(r,async()=>{await t.auth.signInWithToken(a);let e=await t.getAuth();if(!e)throw Error(`Reviewer session did not establish`);return e}):await bt(t,n,r,i))}finally{s()}}async function _t(e,t,n,r,i,a,o){J(i);let s=await vt(e,i);try{let e=await q(i,()=>t.getAuth());return e&&e.id!==n.id?e:(e&&await q(i,async()=>{await t.auth.signOut()}),J(i),o?await q(i,async()=>{await t.auth.signInWithToken(o);let e=await t.getAuth();if(!e)throw Error(`Reviewer session did not establish`);return e}):await bt(t,r,i,a))}finally{s()}}async function vt(e,t){J(t);let n=K.get(e);return n||(n={held:!1,waiters:[]},K.set(e,n)),n.held?new Promise((e,r)=>{let i,a=()=>{let e=n.waiters.indexOf(i);e<0||(n.waiters.splice(e,1),t.removeEventListener(`abort`,a),r(X()))};i={signal:t,resolve:e,reject:r,abort:a},n.waiters.push(i),t.addEventListener(`abort`,a,{once:!0}),t.aborted&&a()}):(n.held=!0,yt(e,n))}function yt(e,t){let n=!1;return()=>{if(!n){for(n=!0;t.waiters.length>0;){let n=t.waiters.shift();if(n.signal.removeEventListener(`abort`,n.abort),n.signal.aborted){n.reject(X());continue}n.resolve(yt(e,t));return}t.held=!1,K.get(e)===t&&K.delete(e)}}}async function q(e,t){J(e);let n=await t();return J(e),n}function J(e){if(e.aborted)throw X()}function bt(e,t,n,r){try{J(n)}catch(e){return Promise.reject(e)}let i=wt(t);i.replaceChildren(Tt(i,r),Et(i));let a=i.querySelector(`form`),o=i.querySelector(`h2`),s=i.querySelector(`.description`),c=a.elements.namedItem(`email`),l=a.elements.namedItem(`code`),u=i.querySelector(`.code`),d=i.querySelector(`button`),f=i.querySelector(`.error`),p=!1;return new Promise((t,r)=>{let m=!1,h=!1,g=!1,ee=()=>{n.removeEventListener(`abort`,v),i.removeEventListener(`keydown`,te),a.removeEventListener(`submit`,ne)},_=e=>{m||(m=!0,ee(),e())},v=()=>{m||(g=!0,ee(),h||_(()=>r(X())))},te=e=>{let t=e;t.key===`Escape`?(t.preventDefault(),v()):t.key===`Tab`&&Mt(i,t)},ne=async i=>{if(i.preventDefault(),!(m||h)){h=!0,f.textContent=``,d.disabled=!0,a.setAttribute(`aria-busy`,`true`);try{if(J(n),!p){let t=c.value.trim();await q(n,async()=>{await e.auth.sendMagicCode({email:t})}),p=!0,c.readOnly=!0,u.hidden=!1,l.required=!0,o.textContent=`인증 코드`,s.textContent=`${t}로 보낸 코드를 입력하세요.`,d.textContent=`확인`,l.focus();return}await q(n,async()=>{await e.auth.signInWithMagicCode({email:c.value.trim(),code:l.value.trim()})});let r=await q(n,()=>e.getAuth());if(!r)throw Error(`인증 세션을 확인할 수 없습니다.`);_(()=>t(r))}catch(e){if(m||n.aborted||At(e,`AUTH_CANCELLED`))return;f.textContent=Ct(e)}finally{h=!1,!m&&(g||n.aborted)?_(()=>r(X())):m||(d.disabled=!1,a.removeAttribute(`aria-busy`))}}};n.addEventListener(`abort`,v,{once:!0}),i.addEventListener(`keydown`,te),a.addEventListener(`submit`,ne)})}function xt(e,t,n=``,r){if(t.aborted)return Promise.reject(X());let i=wt(e);i.replaceChildren(Tt(i,r),Dt(i));let a=i.querySelector(`form`),o=a.elements.namedItem(`displayName`),s=i.querySelector(`button`),c=i.querySelector(`.error`);return o.value=n.trim().slice(0,120),o.focus(),o.select(),new Promise((e,n)=>{let r=!1,l=e=>{r||(r=!0,t.removeEventListener(`abort`,u),i.removeEventListener(`keydown`,p),a.removeEventListener(`submit`,f),e())},u=()=>l(()=>n(X())),d=()=>{let t=o.value.trim();if(!t){c.textContent=`이름을 입력해 주세요.`,o.focus();return}if(t.length>120){c.textContent=`이름은 120자 이하여야 합니다.`,o.focus();return}c.textContent=``,s.disabled=!0,a.setAttribute(`aria-busy`,`true`),l(()=>e(t))},f=e=>{e.preventDefault(),d()},p=e=>{let t=e;if(t.key===`Escape`){t.preventDefault(),u();return}if(t.key===`Tab`){Mt(i,t);return}t.key===`Enter`&&!t.isComposing&&t.target===o&&(t.preventDefault(),d())};t.addEventListener(`abort`,u,{once:!0}),i.addEventListener(`keydown`,p),a.addEventListener(`submit`,f)})}function St(e,t,n){if(t.aborted)return Promise.reject(X());let r=wt(e);r.replaceChildren(Tt(r,n),Ot(r));let i=r.querySelector(`form`),a=r.querySelector(`button`);return a.focus(),new Promise((e,n)=>{let o=!1,s=e=>{o||(o=!0,t.removeEventListener(`abort`,c),r.removeEventListener(`keydown`,u),i.removeEventListener(`submit`,l),e())},c=()=>s(()=>n(X())),l=t=>{t.preventDefault(),a.disabled=!0,i.setAttribute(`aria-busy`,`true`),s(e)},u=e=>{let t=e;t.key===`Escape`?(t.preventDefault(),c()):t.key===`Tab`&&Mt(r,t)};t.addEventListener(`abort`,c,{once:!0}),r.addEventListener(`keydown`,u),i.addEventListener(`submit`,l)})}function Ct(e){if(e&&typeof e==`object`&&`body`in e){let t=e.body;if(t?.message)return t.message}return e instanceof Error?e.message:`로그인에 실패했습니다. 다시 시도해 주세요.`}function wt(e){return e.shadowRoot??e.attachShadow({mode:`open`})}function Tt(e,t){let n=e.ownerDocument.createElement(`style`);return t&&(n.nonce=t),n.textContent=Ft,n}function Et(e){let t=e.ownerDocument,n=t.createElement(`form`);n.setAttribute(`role`,`dialog`),n.setAttribute(`aria-modal`,`true`),n.setAttribute(`aria-labelledby`,`visual-review-login-title`),n.setAttribute(`aria-describedby`,`visual-review-login-description`);let r=Y(t,`p`,`01.works`,`eyebrow`),i=Y(t,`h2`,`Visual Review`);i.id=`visual-review-login-title`;let a=Y(t,`p`,`초대받은 이메일로 계속하세요.`,`description`);a.id=`visual-review-login-description`;let o=t.createElement(`label`);o.append(`이메일`);let s=t.createElement(`input`);s.name=`email`,s.type=`email`,s.autocomplete=`email`,s.required=!0,o.append(s);let c=t.createElement(`label`);c.className=`code`,c.hidden=!0,c.append(`인증 코드`);let l=t.createElement(`input`);l.name=`code`,l.inputMode=`numeric`,l.autocomplete=`one-time-code`,c.append(l);let u=Y(t,`p`,``,`error`);u.setAttribute(`role`,`alert`);let d=Y(t,`button`,`코드 받기`);return d.type=`submit`,n.append(r,i,a,o,c,u,d),n}function Dt(e){let t=e.ownerDocument,n=t.createElement(`form`);n.setAttribute(`role`,`dialog`),n.setAttribute(`aria-modal`,`true`),n.setAttribute(`aria-labelledby`,`visual-review-name-title`),n.setAttribute(`aria-describedby`,`visual-review-name-description`);let r=Y(t,`p`,`01.works`,`eyebrow`),i=Y(t,`h2`,`표시 이름`);i.id=`visual-review-name-title`;let a=Y(t,`p`,`피드백에 이 이름이 표시됩니다.`,`description`);a.id=`visual-review-name-description`;let o=Y(t,`label`,`이름`);o.htmlFor=`visual-review-display-name`;let s=t.createElement(`input`);s.id=`visual-review-display-name`,s.name=`displayName`,s.autocomplete=`name`,s.maxLength=120,s.required=!0;let c=Y(t,`p`,``,`error`);c.setAttribute(`role`,`alert`);let l=Y(t,`button`,`리뷰 시작`);return l.type=`submit`,n.append(r,i,a,o,s,c,l),n}function Ot(e){let t=e.ownerDocument,n=t.createElement(`form`);n.setAttribute(`role`,`dialog`),n.setAttribute(`aria-modal`,`true`),n.setAttribute(`aria-labelledby`,`visual-review-account-title`),n.setAttribute(`aria-describedby`,`visual-review-account-description`);let r=Y(t,`p`,`01.works`,`eyebrow`),i=Y(t,`h2`,`계정 확인`);i.id=`visual-review-account-title`;let a=Y(t,`p`,`이 초대는 현재 로그인한 계정과 일치하지 않습니다.`,`description`);a.id=`visual-review-account-description`;let o=Y(t,`button`,`다른 계정으로 계속`);return o.type=`submit`,n.append(r,i,a,o),n}function Y(e,t,n,r){let i=e.createElement(t);return i.textContent=n,r&&(i.className=r),i}function kt(e){return e?.split(`@`)[0]?.trim().slice(0,120)??``}function At(e,t){return!!(e&&typeof e==`object`&&`code`in e&&e.code===t)}function jt(){return new DOMException(`Aborted`,`AbortError`)}function X(){return new G(`AUTH_CANCELLED`,`리뷰 로그인이 취소되었습니다.`)}function Mt(e,t){let n=Array.from(e.querySelectorAll(`input:not([disabled]),button:not([disabled])`)).filter(e=>!e.closest(`[hidden]`));if(n.length===0)return;let r=n[0],i=n.at(-1);t.shiftKey&&e.activeElement===r?(t.preventDefault(),i.focus()):!t.shiftKey&&e.activeElement===i&&(t.preventDefault(),r.focus())}function Z(e){return e.replace(/\/+$/,``)||`/`}function Nt(e){return e.trim().toLowerCase()}function Pt(e){switch(e){case`INVITATION_REQUIRED`:return`현재 계정과 일치하는 리뷰 초대를 찾을 수 없습니다.`;case`INVITATION_NOT_ACCEPTED`:return`아직 수락되지 않은 리뷰 초대입니다.`;case`INVITATION_REVOKED`:return`취소된 리뷰 초대입니다. 계속 검토하려면 담당자에게 다시 요청하세요.`;case`INVITATION_EXPIRED`:return`만료된 리뷰 초대입니다. 담당자에게 새 링크를 요청하세요.`;case`MEMBERSHIP_REQUIRED`:return`이 프로젝트의 reviewer membership이 없습니다.`;case`PAGE_NOT_FOUND`:return`이 페이지는 아직 리뷰 대상이 아닙니다. 담당자에게 문의하세요.`}}const Ft=`
2
2
  :host{all:initial;--vr-panel:#fff;--vr-text:#161616;--vr-muted:#707070;--vr-label:#3f3f3f;--vr-control:#fff;--vr-border:#d9d9d9;--vr-action:#161616;--vr-action-text:#fff;position:fixed;inset:0;z-index:2147483646;display:grid;place-items:center;overflow:auto;padding:8px;box-sizing:border-box;background:rgba(15,15,15,.34);font-family:Inter,ui-sans-serif,system-ui,sans-serif;color:var(--vr-text)}
3
3
  form{box-sizing:border-box;width:min(320px,calc(100vw - 16px));padding:20px;border:0;border-radius:14px;background:var(--vr-panel);box-shadow:0 18px 56px rgba(0,0,0,.18)}
4
4
  .eyebrow{margin:0 0 10px;color:var(--vr-muted);font-size:10px;font-weight:700;letter-spacing:.09em;text-transform:uppercase}
@@ -10,4 +10,4 @@ import{r as e}from"./install-DvwZzCFL.js";import{t}from"./embedded-source-e0Drdx
10
10
  @media (pointer:coarse){input,button{height:44px}}
11
11
  @media (max-width:480px){form{padding:18px}input{font-size:16px}}
12
12
  @media (prefers-reduced-motion:reduce){*,*::before,*::after{scroll-behavior:auto!important;transition:none!important;animation:none!important}}
13
- `;var Q=class extends Error{code;status;constructor(e,t,n){super(t),this.code=e,this.status=n,this.name=`HostedBootstrapError`}};function Pt(e={}){return Ft(e)}function Ft(t={},n={}){let r=e(t.serviceUrl??`https://visual-review.01.works`),i=t.fetch??globalThis.fetch,a=n.instantRuntimeFactory??dt,o=n.now??Date.now;if(typeof i!=`function`)throw Error(`Visual Review bootstrap requires the Fetch API`);return{async resolve(e){let t=Lt(e),n=await zt(r,i,t,e.signal),s=o(),c=await a(n.instantAppId,{serviceUrl:r,...n.reviewer?{reviewerToken:n.reviewer.token}:{},acceptInvitation:async e=>{let t=await i(`${r}/v1/invitations/accept`,{method:`POST`,headers:{accept:`application/json`,authorization:`Bearer ${e.refreshToken}`,"content-type":`application/json`},body:JSON.stringify({invitationId:e.invitationId,...e.displayName===void 0?{}:{displayName:e.displayName}}),cache:`no-store`,credentials:`omit`,signal:e.signal}),n=await Vt(t);if(!t.ok)throw new Q($(n,`error`)??`INVITATION_ACCEPT_FAILED`,$(n,`message`)??`리뷰 초대 수락에 실패했습니다.`,t.status)},...e.collaboration?.cursors===!0?{resolveCollaborationRoom:e=>Rt(r,i,e)}:{}}).resolve(e),l=c.resolvePage;if(!l)return c;let u=async t=>{await zt(r,i,{invitationId:e.invitationId,origin:t.location.origin,pathname:t.location.pathname},t.signal),s=o()};return{...c,resolvePage:async e=>{o()-s>=3e5&&await u(e);try{return await l(e)}catch(t){if(!It(t,`PAGE_NOT_FOUND`))throw t;return await u(e),await l(e)}}}}}}function It(e,t){return!!(e&&typeof e==`object`&&`code`in e&&e.code===t)}function Lt(e){return{invitationId:e.invitationId,origin:e.location.origin,pathname:e.location.pathname}}async function Rt(e,t,n){let r=await t(`${e}/v1/collaboration/room`,{method:`POST`,headers:{accept:`application/json`,authorization:`Bearer ${n.refreshToken}`,"content-type":`application/json`},body:JSON.stringify({invitationId:n.invitationId,pageId:n.pageId,scopeId:n.scopeId}),cache:`no-store`,credentials:`omit`,signal:n.signal}),i=await Vt(r);if(!r.ok)throw new Q($(i,`error`)??`COLLABORATION_ROOM_FAILED`,$(i,`message`)??`실시간 협업 연결에 실패했습니다.`,r.status);if(!i||typeof i!=`object`||Array.isArray(i))throw new Q(`INVALID_COLLABORATION_ROOM`,`잘못된 협업 응답입니다.`,502);let a=i,o=$(a,`id`);if(!o||!/^vr_[A-Za-z0-9_-]{43}$/u.test(o)||!Number.isSafeInteger(a.expiresAt))throw new Q(`INVALID_COLLABORATION_ROOM`,`잘못된 협업 응답입니다.`,502);return{id:o,expiresAt:a.expiresAt}}async function zt(e,t,n,r){let i=await t(`${e}/v1/bootstrap`,{method:`POST`,headers:{accept:`application/json`,"content-type":`application/json`},body:JSON.stringify(n),cache:`no-store`,credentials:`omit`,signal:r}),a=await Vt(i);if(!i.ok)throw new Q($(a,`error`)??`BOOTSTRAP_FAILED`,$(a,`message`)??`Visual Review bootstrap에 실패했습니다.`,i.status);return Bt(a)}function Bt(e){if(!e||typeof e!=`object`||Array.isArray(e))throw new Q(`INVALID_BOOTSTRAP_RESPONSE`,`잘못된 bootstrap 응답입니다.`,502);let t=e,n=$(t,`instantAppId`);if(t.apiVersion!==1||!n||!Ht(n))throw new Q(`INVALID_BOOTSTRAP_RESPONSE`,`잘못된 bootstrap 응답입니다.`,502);let r=t.reviewer;if(r==null)return{apiVersion:1,instantAppId:n};let i=$(r,`token`),a=$(r,`email`);if(!i||!a)throw new Q(`INVALID_BOOTSTRAP_RESPONSE`,`잘못된 bootstrap 응답입니다.`,502);return{apiVersion:1,instantAppId:n,reviewer:{token:i,email:a}}}async function Vt(e){try{return await e.json()}catch{throw new Q(`INVALID_BOOTSTRAP_RESPONSE`,`JSON bootstrap 응답이 필요합니다.`,502)}}function $(e,t){if(!e||typeof e!=`object`||Array.isArray(e))return null;let n=e[t];return typeof n==`string`&&n.trim()?n.trim():null}function Ht(e){return/^[0-9a-f]{8}-[0-9a-f]{4}-[1-8][0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/i.test(e)}export{Pt as createHostedReviewRuntime};
13
+ `;var Q=class extends Error{code;status;constructor(e,t,n){super(t),this.code=e,this.status=n,this.name=`HostedBootstrapError`}};function It(e={}){return Lt(e)}function Lt(t={},n={}){let r=e(t.serviceUrl??`https://visual-review.01.works`),i=t.fetch??globalThis.fetch,a=n.instantRuntimeFactory??pt,o=n.now??Date.now;if(typeof i!=`function`)throw Error(`Visual Review bootstrap requires the Fetch API`);return{async resolve(e){let t=zt(e),n=await Vt(r,i,t,e.signal),s=o(),c=await a(n.instantAppId,{serviceUrl:r,...n.reviewer?{reviewerToken:n.reviewer.token}:{},acceptInvitation:async e=>{let t=await i(`${r}/v1/invitations/accept`,{method:`POST`,headers:{accept:`application/json`,authorization:`Bearer ${e.refreshToken}`,"content-type":`application/json`},body:JSON.stringify({invitationId:e.invitationId,...e.displayName===void 0?{}:{displayName:e.displayName}}),cache:`no-store`,credentials:`omit`,signal:e.signal}),n=await Ut(t);if(!t.ok)throw new Q($(n,`error`)??`INVITATION_ACCEPT_FAILED`,$(n,`message`)??`리뷰 초대 수락에 실패했습니다.`,t.status)},...e.collaboration?.cursors===!0||e.collaboration?.chat===!0?{resolveCollaborationRoom:e=>Bt(r,i,e)}:{}}).resolve(e),l=c.resolvePage;if(!l)return c;let u=async t=>{await Vt(r,i,{invitationId:e.invitationId,origin:t.location.origin,pathname:t.location.pathname},t.signal),s=o()};return{...c,resolvePage:async e=>{o()-s>=3e5&&await u(e);try{return await l(e)}catch(t){if(!Rt(t,`PAGE_NOT_FOUND`))throw t;return await u(e),await l(e)}}}}}}function Rt(e,t){return!!(e&&typeof e==`object`&&`code`in e&&e.code===t)}function zt(e){return{invitationId:e.invitationId,origin:e.location.origin,pathname:e.location.pathname}}async function Bt(e,t,n){let r=await t(`${e}/v1/collaboration/room`,{method:`POST`,headers:{accept:`application/json`,authorization:`Bearer ${n.refreshToken}`,"content-type":`application/json`},body:JSON.stringify({invitationId:n.invitationId,pageId:n.pageId,scopeId:n.scopeId}),cache:`no-store`,credentials:`omit`,signal:n.signal}),i=await Ut(r);if(!r.ok)throw new Q($(i,`error`)??`COLLABORATION_ROOM_FAILED`,$(i,`message`)??`실시간 협업 연결에 실패했습니다.`,r.status);if(!i||typeof i!=`object`||Array.isArray(i))throw new Q(`INVALID_COLLABORATION_ROOM`,`잘못된 협업 응답입니다.`,502);let a=i,o=$(a,`id`);if(!o||!/^vr_[A-Za-z0-9_-]{43}$/u.test(o)||!Number.isSafeInteger(a.expiresAt))throw new Q(`INVALID_COLLABORATION_ROOM`,`잘못된 협업 응답입니다.`,502);return{id:o,expiresAt:a.expiresAt}}async function Vt(e,t,n,r){let i=await t(`${e}/v1/bootstrap`,{method:`POST`,headers:{accept:`application/json`,"content-type":`application/json`},body:JSON.stringify(n),cache:`no-store`,credentials:`omit`,signal:r}),a=await Ut(i);if(!i.ok)throw new Q($(a,`error`)??`BOOTSTRAP_FAILED`,$(a,`message`)??`Visual Review bootstrap에 실패했습니다.`,i.status);return Ht(a)}function Ht(e){if(!e||typeof e!=`object`||Array.isArray(e))throw new Q(`INVALID_BOOTSTRAP_RESPONSE`,`잘못된 bootstrap 응답입니다.`,502);let t=e,n=$(t,`instantAppId`);if(t.apiVersion!==1||!n||!Wt(n))throw new Q(`INVALID_BOOTSTRAP_RESPONSE`,`잘못된 bootstrap 응답입니다.`,502);let r=t.reviewer;if(r==null)return{apiVersion:1,instantAppId:n};let i=$(r,`token`),a=$(r,`email`);if(!i||!a)throw new Q(`INVALID_BOOTSTRAP_RESPONSE`,`잘못된 bootstrap 응답입니다.`,502);return{apiVersion:1,instantAppId:n,reviewer:{token:i,email:a}}}async function Ut(e){try{return await e.json()}catch{throw new Q(`INVALID_BOOTSTRAP_RESPONSE`,`JSON bootstrap 응답이 필요합니다.`,502)}}function $(e,t){if(!e||typeof e!=`object`||Array.isArray(e))return null;let n=e[t];return typeof n==`string`&&n.trim()?n.trim():null}function Wt(e){return/^[0-9a-f]{8}-[0-9a-f]{4}-[1-8][0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/i.test(e)}export{It as createHostedReviewRuntime};
package/dist/index.js CHANGED
@@ -1 +1 @@
1
- import{t as e}from"./install-DvwZzCFL.js";export{e as installVisualReview};
1
+ import{t as e}from"./install-B5CNlFQl.js";export{e as installVisualReview};
@@ -0,0 +1 @@
1
+ const e=`https://visual-review.01.works`;function t(e){let t=new URL(e),n=t.hostname===`localhost`||t.hostname===`127.0.0.1`||t.hostname.endsWith(`.test`)||t.hostname.endsWith(`.local`);if(t.protocol!==`https:`&&!(n&&t.protocol===`http:`))throw Error(`Visual Review serviceUrl must use HTTPS outside local development`);if(t.username||t.password||t.search||t.hash)throw Error(`Visual Review serviceUrl must be a plain origin or base path`);return t.toString().replace(/\/+$/,``)}const n=()=>{let e=Promise.resolve(null);return{ready:e,refresh:()=>e,dispose(){}}},r=new Map,i=6e4,a=1e4;function o(e={}){if(e.enabled!==!0||typeof window>`u`||typeof document>`u`)return n();let r=!1,i=0,a=null,o=null,p=null,h=null,g=!1,_=null,S=null,E=document.baseURI,j=new WeakMap,N=new Map,P=G(window),F=Z(e.styleNonce,document),I=e.activationParam??`visual-review`,L=v(window.location,I),R=m(window,e=>{let t=v(e,I);if(t===L)return;let n=O(I,e.href);n&&N.set(e.origin,n),L=t,B(e)}),z=e=>{r||!h||e.target!==h||(L=v(window.location,I),W())};return window.addEventListener(`visual-review:reauthenticate-required`,z),{ready:W(),refresh(){return r?Promise.resolve(null):(L=v(window.location,I),B(y(window.location),!0))},dispose(){r||(r=!0,i+=1,H(),h?.remove(),h=null,S=null,_?.remove(),_=null,N.clear(),R.unsubscribe(),window.removeEventListener(`visual-review:reauthenticate-required`,z))}};function B(e,t=!1){return!h||!S||S.origin!==e.origin||O(I,e.href)?W():V(h,S,e,t)}function V(t,n,r,c){let l=++i;a!==o&&a?.abort();let u=new AbortController;a=u;let d=s(e.build,r),f=(async()=>{try{let i=await A(n.resolvePage({location:r,signal:u.signal,collaboration:{cursors:e.collaboration?.cursors===!0,chat:e.collaboration?.chat===!0,scopeId:d}}),u.signal);return Q(l,u)?(i.commit?.(),t.setPage({pageId:i.pageId,collaboration:{roomId:i.collaborationRoomId,scopeId:d}},{reload:c}),t.isConnected||document.body?.append(t),t):$(l)}catch{return Q(l,u)?W():$(l)}})();return p=f,f}function H(){a?.abort(),o?.abort(),a=null,o=null}function W(){let t=++i;H(),h?.remove(),h=null,S=null,_?.remove();let n=new AbortController,r=document.createElement(`div`);r.dataset.agencyReviewRoot=``,a=n,o=n,_=r;let s=q(t,n,r);return p=s,s.then(r=>{r&&Q(t,n)&&h===r&&e.onReady?.(r)}),s}async function q(t,n,i){try{let e=document.body??await M(document,n.signal);if(!Q(t,n))return $(t);e.append(i);let r=await J(t,n,i);return Q(t,n)?r:(i.remove(),$(t))}catch(a){if(!Q(t,n))return i.remove(),$(t);if(d(a,`AUTH_CANCELLED`))return i.remove(),_===i&&(_=null),null;let o=j.get(i)?.[3];X(a,i);let s=Y(a,j.get(i)?.[2]);if(o!==`storage`||g||!f(a)){let{renderBootstrapError:e}=await import(`./bootstrap-error-X9PqxFnS.js`);if(!Q(t,n))return i.remove(),$(t);let o=f(a)?void 0:()=>{r||_!==i||(L=v(window.location,I),W())};e(i,s.message,F,o)}else i.remove(),_===i&&(_=null);return e.onError?.(s),window.dispatchEvent(new CustomEvent(`visual-review:error`,{detail:s})),null}}async function J(n,r,i){let a=t(e.serviceUrl??`https://visual-review.01.works`),o=y(window.location),d=D(a,I,o,P,e.runtime!==void 0),f=b(N.get(o.origin)),p=x(C(a,o.origin)),m=d?.source===`url`?d:f??p??d;if(!m)return j.delete(i),i.remove(),_===i&&(_=null),null;let O=m.invitationId;j.set(i,[a,o.origin,O,m.source]),m.source===`url`?(K(a,o.origin,P),N.set(o.origin,O),w(a,o.origin,O),R.suppress(()=>k(I))):m.source===`handoff`&&N.set(o.origin,O),L=v(window.location,I);let M=await A((e.runtime??await c(a)).resolve({invitationId:O,location:o,signal:r.signal,authHost:i,styleNonce:F,collaboration:{cursors:e.collaboration?.cursors===!0,chat:e.collaboration?.chat===!0,scopeId:s(e.build,o)}}),r.signal);if(!Q(n,r))return null;T(a,o.origin,O),U(a,O,o,P),N.set(o.origin,O);let z=e.sourceContextResolver??await u(e.build,E,r.signal,F);if(!Q(n,r))return null;let{mountReviewWidget:B}=await l(r.signal);return Q(n,r)?(h=B({...M,collaboration:{cursors:e.collaboration?.cursors===!0&&!!(M.collaborationRepository&&M.collaborationRoomId),chat:e.collaboration?.chat===!0&&!!M.collaborationRepository,repository:M.collaborationRepository,roomId:M.collaborationRoomId,scopeId:s(e.build,o)},developerTools:e.developerTools,onNavigateToFeedback:async t=>{let n=new URL(t,window.location.href);if(n.origin!==window.location.origin)throw Error(`Visual Review route navigation must stay on the staging origin`);if(e.navigateToFeedback){await e.navigateToFeedback(n.href);return}window.location.assign(n.href)},sourceContextResolver:z,styleNonce:F}),S=M.resolvePage?{origin:o.origin,resolvePage:e=>M.resolvePage(e)}:null,i.remove(),_===i&&(_=null),g=!0,window.dispatchEvent(new CustomEvent(`visual-review:ready`,{detail:h})),h):null}function X(e,t){if(!f(e))return;let n=j.get(t);if(!n)return;let[r,i,a]=n;T(r,i,a),N.get(i)===a&&N.delete(i),K(r,i,P,a)}function Q(e,t){return!r&&i===e&&a===t&&!t.signal.aborted}function $(e){return!r&&i!==e?p:null}}function s(e,t){return JSON.stringify([N(e).buildId,t.pathname,t.search])}async function c(e){let{createHostedReviewRuntime:t}=await import(`./hosted-runtime-CqSQ5Wjc.js`);return t({serviceUrl:e})}async function l(e){return j(import(`./src-Dr9YOMMS.js`),e,a,`리뷰 위젯을 불러오는 시간이 초과되었습니다. 다시 시도해 주세요.`)}async function u(e,t,n,r){let i=N(e),{createGeneratedSourceContextResolver:o}=await j(import(`./generated-source-context-R_klctZM.js`),n,a,`리뷰 소스 정보를 불러오는 시간이 초과되었습니다. 다시 시도해 주세요.`),s=o({build:i}),c=s.resolve.bind(s),l=null;return s.resolve=async(e,t)=>{let n=await c(e,t);if(n.source)return n;try{if(!l){let{createReactSourceContextResolver:e}=await import(`./source-context-leuy5fdX.js`).then(e=>e.t);l=e({build:i,styleNonce:r})}let a=await l.resolve(e,t);return a.source?a:n}catch{return n}},s}function d(e,t){return e instanceof Error&&`code`in e&&e.code===t}function f(e){let t=e instanceof Error&&`code`in e?e.code:void 0;return typeof t==`string`&&/^INVITATION_(?:EXPIRED|NOT_FOUND|REVOKED)$/.test(t)}const p=new WeakMap;function m(e,t){let n=p.get(e);if(!n){let t=e.history,r=t.pushState,i=t.replaceState,a=new Set;n={history:t,originalPushStateDescriptor:Object.getOwnPropertyDescriptor(t,`pushState`),originalReplaceStateDescriptor:Object.getOwnPropertyDescriptor(t,`replaceState`),patchedPushState:function(t,n,i){r.call(this,t,n,i),h(e)},patchedReplaceState:function(t,n,r){i.call(this,t,n,r),h(e)},popstateListener:()=>h(e),subscribers:a,suppressionDepth:0},p.set(e,n),g(t,`pushState`,n.patchedPushState),g(t,`replaceState`,n.patchedReplaceState),e.addEventListener(`popstate`,n.popstateListener)}n.subscribers.add(t);let r=!0;return{suppress(e){n.suppressionDepth+=1;try{return e()}finally{--n.suppressionDepth}},unsubscribe(){r&&(r=!1,n.subscribers.delete(t),!(n.subscribers.size>0)&&(e.removeEventListener(`popstate`,n.popstateListener),_(n.history,`pushState`,n.patchedPushState,n.originalPushStateDescriptor),_(n.history,`replaceState`,n.patchedReplaceState,n.originalReplaceStateDescriptor),p.delete(e)))}}}function h(e){let t=p.get(e);if(!t||t.suppressionDepth>0)return;let n=y(e.location);[...t.subscribers].forEach(e=>e(n))}function g(e,t,n){Object.defineProperty(e,t,{configurable:!0,enumerable:!1,writable:!0,value:n})}function _(e,t,n,r){if(Object.getOwnPropertyDescriptor(e,t)?.value===n){if(r){Object.defineProperty(e,t,r);return}delete e[t]}}function v(e,t){return`${e.origin}\n${e.pathname}\n${O(t,e.href)??``}`}function y(e){return new URL(e.href)}function b(e){return e?{invitationId:e,source:`memory`}:null}function x(e){return e?{invitationId:e,source:`handoff`}:null}function S(e,t){return JSON.stringify([e,t])}function C(e,t,n=Date.now()){let i=S(e,t),a=r.get(i);if(a){if(a.expiresAt>n)return a.invitationId;clearTimeout(a.timeout),r.delete(i)}}function w(e,t,n,a=Date.now()){E(a);let o=S(e,t),s=r.get(o);for(s&&(clearTimeout(s.timeout),r.delete(o));r.size>=32;){let e=r.keys().next().value;if(!e)break;let t=r.get(e);t&&clearTimeout(t.timeout),r.delete(e)}let c=a+i,l=setTimeout(()=>{r.get(o)?.expiresAt===c&&r.delete(o)},i);r.set(o,{invitationId:n,expiresAt:c,timeout:l})}function T(e,t,n){let i=S(e,t),a=r.get(i);a?.invitationId===n&&(clearTimeout(a.timeout),r.delete(i))}function E(e){for(let[t,n]of r)n.expiresAt>e||(clearTimeout(n.timeout),r.delete(t))}function D(e,t,n,r,i){let a=O(t,n.href);if(a)return{invitationId:a,source:`url`};let o=W(r,q(e,n.origin));return o?{invitationId:o,source:`storage`}:i&&J(n.hostname)?{invitationId:`local-preview`,source:`local-preview`}:null}function O(e,t){let n=new URL(t);return(n.searchParams.get(e)??n.searchParams.get(`agency-review`)??n.searchParams.get(`agency-review-invite`))?.trim()||null}function k(e){let t=new URL(window.location.href),n=new Set([e,`visual-review`,`agency-review`,`agency-review-invite`]),r=!1;n.forEach(e=>{t.searchParams.has(e)&&(t.searchParams.delete(e),r=!0)}),r&&window.history.replaceState(window.history.state,``,`${t.pathname}${t.search}${t.hash}`)}function A(e,t){return new Promise((n,r)=>{let i=()=>r(new DOMException(`Aborted`,`AbortError`));if(t.aborted){i();return}t.addEventListener(`abort`,i,{once:!0}),e.then(e=>{t.removeEventListener(`abort`,i),n(e)},e=>{t.removeEventListener(`abort`,i),r(e)})})}function j(e,t,n,r){return new Promise((i,a)=>{let o=!1,s=e=>{o||(o=!0,clearTimeout(l),t.removeEventListener(`abort`,c),e())},c=()=>{s(()=>a(new DOMException(`Aborted`,`AbortError`)))},l=setTimeout(()=>{s(()=>a(Error(r)))},n);if(t.aborted){c();return}t.addEventListener(`abort`,c,{once:!0}),e.then(e=>s(()=>i(e)),e=>s(()=>a(e)))})}function M(e,t){return e.body?Promise.resolve(e.body):t.aborted?Promise.reject(new DOMException(`Aborted`,`AbortError`)):new Promise((n,r)=>{let i=!1,a=new MutationObserver(()=>c()),o=()=>{e.removeEventListener(`DOMContentLoaded`,c),t.removeEventListener(`abort`,l),a.disconnect()},s=e=>{i||(i=!0,o(),e())},c=()=>{let t=e.body;t&&s(()=>n(t))},l=()=>{s(()=>r(new DOMException(`Aborted`,`AbortError`)))};e.addEventListener(`DOMContentLoaded`,c),t.addEventListener(`abort`,l,{once:!0}),a.observe(e,{childList:!0,subtree:!0}),c()})}function N(e){let t=document.querySelector(`meta[name="visual-review-build"]`),n=document.querySelector(`meta[name="visual-review-commit"]`),r=H(I()),i=H(L());return{buildId:V(e?.buildId)??B(t)??r??`unversioned`,gitCommit:R(e,n,i),generatedAt:e?.generatedAt,mode:e?.mode??F(P())??(J(window.location.hostname)?`development`:`production`)}}function P(){try{return process.env.VISUAL_REVIEW_PUBLIC_BUILD_MODE}catch{return}}function F(e){return e===`development`||e===`preview`||e===`production`?e:void 0}function I(){try{return process.env.VISUAL_REVIEW_PUBLIC_BUILD_ID}catch{return}}function L(){try{return process.env.VISUAL_REVIEW_PUBLIC_GIT_COMMIT}catch{return}}function R(e,t,n){return e?.gitCommit===null?null:typeof e?.gitCommit==`string`?z(e.gitCommit):z(t?.content)??z(n)}function z(e){if(typeof e!=`string`)return null;let t=e.trim().toLowerCase();return/^(?:[0-9a-f]{40}|[0-9a-f]{64})$/.test(t)?t:null}function B(e){return H(e?.content)}function V(e){let t=typeof e==`string`?e.trim():``;return t.length>0?t:null}function H(e){return typeof e==`string`&&e.length>0?e:null}function U(e,t,n,r){try{r?.setItem(q(e,n.origin),t)}catch{}}function W(e,t){try{return e?.getItem(t)??null}catch{return null}}function G(e){try{return e.localStorage}catch{return null}}function K(e,t,n,r){try{if(!n)return;let i=q(e,t),a=n.getItem(i);if(a===null||r!==void 0&&a!==r)return;n.removeItem(i)}catch{}}function q(e,t){return`visual-review:${e}:${t}:invitation`}function J(e){return e===`localhost`||e===`127.0.0.1`||e.endsWith(`.test`)||e.endsWith(`.local`)}function Y(e,t){let n=e instanceof Error?e.message:String(e),r=Error(X(n,t));if(e&&typeof e==`object`){let n=`code`in e?e.code:void 0,i=`status`in e?e.status:void 0;typeof n==`string`&&Object.defineProperty(r,"code",{configurable:!0,enumerable:!0,value:X(n,t)}),typeof i==`number`&&Number.isFinite(i)&&Object.defineProperty(r,"status",{configurable:!0,enumerable:!0,value:i})}return r}function X(e,t){if(!t)return e;let n=new Set([t,encodeURIComponent(t)]),r=e;for(let e of n)e&&(r=r.split(e).join(`[redacted]`));return r}function Z(e,t){if(e!==void 0)return $(e);let n=t.currentScript,r=n?Q(n):void 0;if(r)return r;try{for(let e of t.querySelectorAll(`script[nonce],style[nonce]`)){let t=Q(e);if(t)return t}}catch{}}function Q(e){let t=`nonce`in e?e.nonce:void 0;return typeof t==`string`?$(t):void 0}function $(e){return e.trim()||void 0}export{e as n,t as r,o as t};
package/dist/react.js CHANGED
@@ -1 +1 @@
1
- import{t as e}from"./install-DvwZzCFL.js";import{useEffect as t,useRef as n}from"react";function r({activationParam:r,build:i,collaboration:a,developerTools:o,enabled:s,navigateToFeedback:c,onError:l,onReady:u,runtime:d,serviceUrl:f,sourceContextResolver:p,styleNonce:m}){let h=n(l),g=n(u),_=i?.buildId,v=i?.gitCommit,y=i?.generatedAt,b=i?.mode,x=o?.reactGrab===!0,S=a?.cursors===!0,C=a?.chat===!0;return h.current=l,g.current=u,t(()=>{if(s!==!0)return;let t=e({activationParam:r,build:_===void 0&&v===void 0&&y===void 0&&b===void 0?void 0:{buildId:_,gitCommit:v,generatedAt:y,mode:b},collaboration:S||C?{cursors:S,chat:C}:void 0,developerTools:x?{reactGrab:!0}:void 0,enabled:s,navigateToFeedback:c,onError:e=>h.current?.(e),onReady:e=>g.current?.(e),runtime:d,serviceUrl:f,sourceContextResolver:p,styleNonce:m});return()=>t.dispose()},[r,_,b,C,S,x,s,y,v,c,d,f,p,m]),null}r.displayName=`VisualReview`;export{r as VisualReview};
1
+ import{t as e}from"./install-B5CNlFQl.js";import{useEffect as t,useRef as n}from"react";function r({activationParam:r,build:i,collaboration:a,developerTools:o,enabled:s,navigateToFeedback:c,onError:l,onReady:u,runtime:d,serviceUrl:f,sourceContextResolver:p,styleNonce:m}){let h=n(l),g=n(u),_=i?.buildId,v=i?.gitCommit,y=i?.generatedAt,b=i?.mode,x=o?.reactGrab===!0,S=a?.cursors===!0,C=a?.chat===!0;return h.current=l,g.current=u,t(()=>{if(s!==!0)return;let t=e({activationParam:r,build:_===void 0&&v===void 0&&y===void 0&&b===void 0?void 0:{buildId:_,gitCommit:v,generatedAt:y,mode:b},collaboration:S||C?{cursors:S,chat:C}:void 0,developerTools:x?{reactGrab:!0}:void 0,enabled:s,navigateToFeedback:c,onError:e=>h.current?.(e),onReady:e=>g.current?.(e),runtime:d,serviceUrl:f,sourceContextResolver:p,styleNonce:m});return()=>t.dispose()},[r,_,b,C,S,x,s,y,v,c,d,f,p,m]),null}r.displayName=`VisualReview`;export{r as VisualReview};