@hazem3500/komo 0.9.10 → 0.9.12

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1 +1 @@
1
- import{b as e,c as t}from"./chunk-KMYXE4O6.js";import{i as a,j as n,k as s}from"./chunk-62YUEO4G.js";import"./chunk-I7AUKTXE.js";async function r(e,t=""){let r;try{let a=await e.request(`project/sites${t}`);r=[...a.fixed,...a.sites]}catch{return null}let i=a("div","approved-sites-editor");i.dataset.open="false";let o=a("span","approved-sites-count"),l=s("Sites with comments",()=>{let e="true"!==i.dataset.open;i.dataset.open=String(e),l.setAttribute("aria-expanded",String(e)),c.inert=!e},"approved-sites-toggle");l.replaceChildren(a("span","","Sites with comments"),o,n("chevron")),l.setAttribute("aria-expanded","false");let c=a("div","approved-sites-reveal");c.id=`approved-sites-${crypto.randomUUID()}`,c.inert=!0,l.setAttribute("aria-controls",c.id);let p=a("div","approved-sites-body"),d=a("ul","approved-site-list"),u=a("p","account-usage-status");u.setAttribute("role","status");let v=a("div","approved-site-add"),m=a("input");m.type="text",m.inputMode="url",m.spellcheck=!1,m.placeholder="your-site.com",m.setAttribute("aria-label","Site to approve"),m.setAttribute("autocomplete","off");let b=a("div","account-usage-note account-sites-note");b.append(n("info"),a("span","","Only these sites can show comments. Add * to cover preview links."));let h=async a=>{let n=r;r=a,f(),u.textContent="";try{let n=await e.request(`project/sites${t}`,"PATCH",{sites:a});return r=[...n.fixed,...n.sites],f(),!0}catch(e){return r=n,f(),u.textContent=e instanceof Error?e.message:"Try again.",!1}},y=s("Add",async()=>{let e;try{e=function(e){let t=e.trim().replace(/\/$/,"").toLowerCase();if(/^http:\/\/(localhost|127\.0\.0\.1)(:\d+)?$/.test(t))return t;let a=/^https:\/\/([^/?#@\s]+)$/.exec(t.includes("://")?t:`https://${t}`),[n="",...s]=(a?.[1]??"").split(".");if(!a||s.length<1||s.join(".").includes("*")||n.split("*").length>2||n.includes("*")&&s.length<2)throw new Error("That doesn’t look like a site. Try your-site.com or *-preview.your-site.com.");return`https://${a[1]}`}(m.value)}catch(e){return void(u.textContent=e.message)}if(r.includes(e))return m.value="",void(u.textContent="Already on the list.");let t=m.value;m.value="",y.disabled=!0,await h([...r,e])||(m.value||=t),y.disabled=!1,m.focus()},"secondary");m.addEventListener("keydown",e=>{"Enter"===e.key&&(e.preventDefault(),y.click())}),v.append(m,y);let g=e=>{let t=a("li","approved-site"),n=a("span","",e.replace(/^https:\/\//,""));return n.title=e,t.append(n,s(`Remove ${e}`,()=>{h(r.filter(t=>t!==e))},"icon","close")),t},f=()=>{o.textContent=String(r.length),d.replaceChildren(...r.map(g))};return f(),p.append(d,v,b,u),c.append(p),i.append(l,c),i}var i=new WeakMap;function o(e,n="usage",o=!0,l=!1){let c=a("section","account-usage");c.setAttribute("aria-label","Account usage");let p=(e="")=>{let t=a("span",`usage-skeleton ${e}`);return t.setAttribute("aria-hidden","true"),t},d=e.user?.id,u=e.token,v=()=>e.user?.id===d&&e.token===u,m=i.get(e);m||i.set(e,m=new Map);let b=JSON.stringify([d,u,n]),h=m.get(b);h||m.set(b,h={});let y=e=>{c.setAttribute("aria-busy","false"),c.replaceChildren(a("h3","",`${e.hosted?"Starter plan":"Self-hosted"}${l?" · Local":""}`));let{used:t,limit:n}=e.comments,s=a("div","account-usage-label account-comments"),r=a("span","account-comment-count");if(r.append(a("span","",null===n?`${t.toLocaleString()} / Unlimited`:`${t.toLocaleString()} / ${n.toLocaleString()}`)),s.title="Includes replies and deleted comments.",null!==n){let e=a("span","account-usage-ring");e.setAttribute("role","meter"),e.setAttribute("aria-label","Project comments"),e.setAttribute("aria-valuemin","0"),e.setAttribute("aria-valuemax",String(n)),e.setAttribute("aria-valuenow",String(Math.min(t,n))),e.setAttribute("aria-valuetext",`${t} of ${n} comments used, including replies and deleted comments`),e.style.setProperty("--usage",(n>0?100*Math.min(t/n,1):0)+"%"),e.dataset.full=String(t>=n),r.append(e)}if(s.append(a("span","","Project comments"),r),c.append(s),e.projects){let{used:t,limit:n}=e.projects;if(null===n){let e=a("div","account-usage-label");return e.append(a("span","","Projects"),a("span","",`${t.toLocaleString()} / Unlimited`)),void c.append(e)}let s=a("div","account-projects"),r=a("div","account-usage-label"),i=a("span","account-project-count");i.append(a("strong","",String(t)),a("span","",`of ${n}`)),r.append(a("span","","Projects"),i);let o=a("div","account-project-slots");o.setAttribute("role","meter"),o.setAttribute("aria-label","Projects"),o.setAttribute("aria-valuemin","0"),o.setAttribute("aria-valuemax",String(n)),o.setAttribute("aria-valuenow",String(t)),o.setAttribute("aria-valuetext",`${t} of ${n} projects used`);for(let e=0;e<n;e++){let n=a("span");n.dataset.used=String(e<t),o.append(n)}s.append(r,o),c.append(s)}},g=async()=>{if(!v())return c.replaceChildren(),void c.setAttribute("aria-busy","false");h.value?y(h.value):(()=>{let e=a("div","usage-skeleton-heading");e.append(p("usage-skeleton-title"));let t=a("div","account-usage-label account-comments"),n=a("span","account-comment-count");n.append(p("usage-skeleton-count"),p("usage-skeleton-ring")),t.append(p("usage-skeleton-label"),n);let s=a("div","account-projects"),r=a("div","account-usage-label");r.append(p("usage-skeleton-label"),p("usage-skeleton-count"));let i=a("div","account-project-slots");i.setAttribute("aria-hidden","true"),i.append(a("span"),a("span"),a("span")),s.append(r,i);let o=a("span","sr-only","Loading account usage");o.setAttribute("role","status"),c.setAttribute("aria-busy","true"),c.replaceChildren(e,t,s,o)})(),c.setAttribute("aria-busy","true");try{let t,a=h.pending??=e.request(n);try{t=await a}finally{h.pending===a&&(h.pending=void 0)}if(!v())return delete h.value,c.replaceChildren(),void c.setAttribute("aria-busy","false");if(h.value=t,!c.isConnected)return;y(t),o&&e.user?.verified&&(async()=>{let t=n.includes("?")?n.slice(n.indexOf("?")):"",a=await r(e,t);a&&h.value&&c.isConnected&&v()&&c.append(a)})().catch(()=>{})}catch(e){if(e instanceof t&&(401===e.status||403===e.status)&&delete h.value,!v())return delete h.value,c.replaceChildren(),void c.setAttribute("aria-busy","false");if(!c.isConnected)return;h.value?y(h.value):c.replaceChildren(),c.setAttribute("aria-busy","false");let n=a("span","account-usage-status",h.value?"Couldn’t refresh usage":"Usage unavailable");n.setAttribute("role","status"),c.append(n,s("Retry",()=>{g()},"secondary"))}};return g(),c}function l(t,r,i){let o=a("section","account-sites project-management");o.dataset.open="false";let l=s("Project settings",()=>{let e="true"!==o.dataset.open;o.dataset.open=String(e),l.setAttribute("aria-expanded",String(e)),c.inert=!e,c.setAttribute("aria-hidden",String(!e))},"account-sites-summary");l.append(n("chevron")),l.setAttribute("aria-expanded","false");let c=a("div","account-sites-reveal");c.id=`project-settings-${crypto.randomUUID()}`,l.setAttribute("aria-controls",c.id),c.inert=!0,c.setAttribute("aria-hidden","true");let p=a("div","account-sites-clip");c.append(p);let d=a("div","account-sites-content"),u=a("p","account-usage-status");u.setAttribute("role","status");let v=r?`?workspace=${encodeURIComponent(r)}`:"",m=(e,a="GET",n)=>t.request(`project${e}${v}`,a,n);o.hidden=!0,p.append(d,u),o.append(l,c);let b,h=async e=>{let t=Array.from(o.querySelectorAll("button"));t.forEach(e=>e.disabled=!0),u.textContent="";try{await e()}catch(e){u.textContent=e instanceof Error?e.message:"Try again."}finally{t.forEach(e=>e.disabled=!1)}},y=async()=>{let e,n={format:"komo-export",version:1,project:b.project,exportedAt:(new Date).toISOString(),tables:{}};for(let a of["threads","comments","reactions","users"]){n.tables[a]=[];let s=0;for(;null!==s;){let i=await t.request(`project/export?table=${a}&offset=${s}${void 0===e?"":`&revision=${e}`}${r?`&workspace=${encodeURIComponent(r)}`:""}`);e=i.revision,n.tables[a].push(...i.rows),s=i.next}}let s=URL.createObjectURL(new Blob([JSON.stringify(n,null,2)],{type:"application/json"})),i=a("a");i.href=s,i.download=`${b.project}-comments.json`,i.click(),setTimeout(()=>URL.revokeObjectURL(s),1e3),u.textContent="Export downloaded."},g=async()=>{b=await m(""),o.hidden=!1,d.replaceChildren();let t=a("div","account-name-label");t.append(a("span","","Access"));let n,r=[["public","Anyone with the link"],["private","Invited Google accounts"]],l=()=>{let a=e("Project access",r,b.access,e=>{h(async()=>{let t=b.access;b.access=e,l();try{await m("","PATCH",{access:e}),u.textContent="Access updated."}catch(e){throw b.access=t,l(),e}})});n?n.replaceWith(a):t.append(a),n=a};l(),d.append(t);let c=await m("/webhook"),p=a("details","project-webhook");p.append(a("summary","","Comment webhooks"));let v=a("p","project-help","Send signed events to your HTTPS endpoint. Signing secrets are encrypted and shown only when entered.");p.append(v),c.deliveryAvailable||(v.textContent="Secure webhook delivery is not available on this server yet.");let f=a("label","account-name-label","HTTPS endpoint"),w=a("input");w.type="url",w.autocomplete="off",w.placeholder="https://example.com/komo-webhook",w.value=c.url,f.append(w),p.append(f);let A=a("label","account-name-label",c.secretConfigured?"Replace signing secret":"Signing secret"),k=a("input");k.type="password",k.autocomplete="new-password",k.minLength=32,k.maxLength=256,A.append(k),p.append(A);let C=new Map;for(let e of c.supportedEvents){let t=a("label","account-name-label",e),n=a("input");n.type="checkbox",n.checked=c.events.includes(e),C.set(e,n),t.prepend(n),p.append(t)}let x=a("label","account-name-label","Enable delivery"),j=a("input");j.type="checkbox",j.checked=c.enabled,j.disabled=!c.deliveryAvailable&&!c.enabled,x.prepend(j),p.append(x),p.append(s("Save webhook settings",()=>{h(async()=>{await m("/webhook","PATCH",{url:w.value,secret:k.value,events:[...C].filter(([,e])=>e.checked).map(([e])=>e),enabled:j.checked}),k.value="",u.textContent="Webhook settings saved."})},"secondary")),d.append(p);let S=a("label","account-name-label","Invite someone"),$=a("input");$.type="email",$.placeholder="name@example.com",$.autocomplete="email",S.append($);let E=a("input");E.readOnly=!0,E.hidden=!0,E.setAttribute("aria-label","Invitation link");let T=s("Create invitation",()=>{h(async()=>{if(!$.checkValidity()||!$.value)throw Error("Enter an email address.");let e=await m("/invites","POST",{email:$.value});E.value=e.url,E.hidden=!1,P.hidden=!1,u.textContent="Share this link. It expires in 7 days."})},"secondary"),P=s("Copy invitation",()=>{h(async()=>{await navigator.clipboard.writeText(E.value),u.textContent="Invitation copied."})},"secondary");P.hidden=!0,d.append(S,T,E,P);for(let e of b.members){let t=a("div","project-member");t.append(a("span","",e.name),s(`Remove ${e.name}`,()=>{h(async()=>{await m("/members","DELETE",{user:e.id}),await g(),u.textContent="Member removed."})},"secondary")),d.append(t)}for(let e of b.invites){let t=a("div","project-member");t.append(a("span","",e.email),s("Revoke invitation",()=>{h(async()=>{await m("/invites","DELETE",{email:e.email}),await g(),u.textContent="Invitation revoked."})},"secondary")),d.append(t)}d.append(s("Download comments",()=>{h(y)},"secondary"));let U=a("a","project-help","Move to self-hosting");U.href="https://komo.offbr.co/hosting/#migration",U.target="_blank",U.rel="noopener noreferrer",d.append(U);let L=a("details","project-danger");L.append(a("summary","","Free space or delete project")),L.append(a("p","",`Export first. These actions permanently remove comments. Type ${b.project} to confirm.`));let R=a("input");R.placeholder=b.project,R.setAttribute("aria-label","Confirm project key"),L.append(R),L.append(s("Delete resolved threads",()=>{h(async()=>{await m("/clear-resolved","POST",{confirm:R.value}),i?.(!1),u.textContent="Resolved threads deleted.",R.value=""})},"secondary destructive")),b.hosted&&L.append(s("Delete project",()=>{h(async()=>{await m("","DELETE",{confirm:R.value}),i?.(!0),d.replaceChildren(),u.textContent="Project deleted. Its project slot is available again."})},"secondary destructive")),d.append(L)};return g().catch(e=>{403!==e?.status&&(o.hidden=!1,u.textContent="Project settings unavailable.",d.append(s("Retry",()=>{h(g)},"secondary")))}),o}function c(e,t){let r=a("section","onboarding-panel"),i=a("p","account-usage-status");i.setAttribute("role","status");let l=e=>{i.textContent=e instanceof Error?e.message:"Try again."},c=async()=>{let p=encodeURIComponent(t.workspace),d=a("div","account-sites"),u=a("div","account-sites-summary");u.append(a("span","","Approved sites"),n("chevron")),d.append(u),d.setAttribute("aria-busy","true"),i.textContent="",r.replaceChildren(o(e,`usage?workspace=${p}`,!1),d,i);try{let o=await e.request(`workspace?workspace=${p}`);if(!r.isConnected)return;i.textContent="";let c=a("section","account-sites");c.dataset.open="false";let u=s("",()=>{let e="true"!==c.dataset.open;c.dataset.open=String(e),u.setAttribute("aria-expanded",String(e)),v.inert=!e,v.setAttribute("aria-hidden",String(!e))},"account-sites-summary");u.setAttribute("aria-expanded","false");let v=a("div","account-sites-reveal");v.id=`approved-sites-${crypto.randomUUID()}`,v.inert=!0,v.setAttribute("aria-hidden","true"),u.setAttribute("aria-controls",v.id);let m=a("div","account-sites-clip"),b=a("span","account-sites-count");u.append(a("span","","Approved sites"),b,n("chevron"));let h=a("div","account-sites-content"),y=a("div","approved-sites"),g=()=>{b.textContent=String(o.sites.length),y.replaceChildren(...o.sites.map(e=>a("span","",new URL(e).host)))};g();let f=a("label","account-name-label","Website"),w=a("input");w.type="url",w.placeholder="https://your-site.com",w.setAttribute("autocomplete","url"),w.value=t.site||o.suggested.find(e=>!o.sites.includes(e))||"",f.append(w);let A=s("Approve site",async()=>{let a;try{let e=new URL(w.value.trim());if("https:"!==e.protocol||e.username||e.password)throw Error("Enter an HTTPS website address.");a=e.origin}catch(e){return void l(e)}let n=[...o.sites],s=w.value;o.sites.includes(a)||o.sites.push(a),g(),w.value="",A.disabled=!0;try{await e.request("workspace/sites","POST",{project:t.workspace,origin:a}),t.site=void 0,i.textContent="Site approved"}catch(e){o.sites=n,g(),w.value||(w.value=s),l(e)}finally{A.disabled=!1}},"secondary");w.addEventListener("keydown",e=>{"Enter"===e.key&&(e.preventDefault(),A.click())});let k=a("div","account-usage-note account-sites-note");k.append(n("info"),a("span","","Approved sites can show and share comments. Localhost comments are visible by default.")),h.append(y,f,A,k),m.append(h),v.append(m),c.append(u,v),d.replaceWith(c)}catch(e){l(e),r.append(s("Retry",()=>{c()},"secondary"))}};if(t.invite){let n=s("Accept invitation",async()=>{n.disabled=!0;try{await e.request("project/join","POST",{invite:t.invite}),t.invite=void 0,r.replaceChildren(a("p","","You’re in. Return to the website to leave comments."))}catch(e){l(e),n.disabled=!1}},"primary");r.append(n,i)}else if(t.workspace)c();else if(t.code||t.claimKey){let a=s(t.code?"Create project":"Enable comments",async()=>{a.disabled=!0;let n=a.textContent;a.textContent=t.code?"Creating project…":"Enabling comments…";try{if(t.code){let a=await e.request("setup/complete","POST",{code:t.code});t.workspace=a.project,t.code=void 0,history.replaceState(null,"",`/setup?workspace=${encodeURIComponent(a.project)}`),await c(),i.textContent="Project ready. Return to your terminal."}else await e.request("owner/claim","POST",{key:t.claimKey}),t.claimKey=void 0,r.replaceChildren(o(e),i),i.textContent="Comments are ready."}catch(e){l(e),a.disabled=!1,a.textContent=n}},"primary");r.append(a,i)}else r.append(o(e));return r}export{o as accountUsage,c as onboardingPanel,l as projectManagement};
1
+ import{b as e,c as t}from"./chunk-URGMAMH5.js";import{i as a,j as n,k as s}from"./chunk-ANKCS6NI.js";import"./chunk-I7AUKTXE.js";async function r(e,t=""){let r;try{let a=await e.request(`project/sites${t}`);r=[...a.fixed,...a.sites]}catch{return null}let i=a("div","approved-sites-editor");i.dataset.open="false";let o=a("span","approved-sites-count"),l=s("Sites with comments",()=>{let e="true"!==i.dataset.open;i.dataset.open=String(e),l.setAttribute("aria-expanded",String(e)),c.inert=!e},"approved-sites-toggle");l.replaceChildren(a("span","","Sites with comments"),o,n("chevron")),l.setAttribute("aria-expanded","false");let c=a("div","approved-sites-reveal");c.id=`approved-sites-${crypto.randomUUID()}`,c.inert=!0,l.setAttribute("aria-controls",c.id);let p=a("div","approved-sites-body"),d=a("ul","approved-site-list"),u=a("p","account-usage-status");u.setAttribute("role","status");let v=a("div","approved-site-add"),m=a("input");m.type="text",m.inputMode="url",m.spellcheck=!1,m.placeholder="your-site.com",m.setAttribute("aria-label","Site to approve"),m.setAttribute("autocomplete","off");let b=a("div","account-usage-note account-sites-note");b.append(n("info"),a("span","","Only these sites can show comments. Add * to cover preview links."));let h=async a=>{let n=r;r=a,f(),u.textContent="";try{let n=await e.request(`project/sites${t}`,"PATCH",{sites:a});return r=[...n.fixed,...n.sites],f(),!0}catch(e){return r=n,f(),u.textContent=e instanceof Error?e.message:"Try again.",!1}},y=s("Add",async()=>{let e;try{e=function(e){let t=e.trim().replace(/\/$/,"").toLowerCase();if(/^http:\/\/(localhost|127\.0\.0\.1)(:\d+)?$/.test(t))return t;let a=/^https:\/\/([^/?#@\s]+)$/.exec(t.includes("://")?t:`https://${t}`),[n="",...s]=(a?.[1]??"").split(".");if(!a||s.length<1||s.join(".").includes("*")||n.split("*").length>2||n.includes("*")&&s.length<2)throw new Error("That doesn’t look like a site. Try your-site.com or *-preview.your-site.com.");return`https://${a[1]}`}(m.value)}catch(e){return void(u.textContent=e.message)}if(r.includes(e))return m.value="",void(u.textContent="Already on the list.");let t=m.value;m.value="",y.disabled=!0,await h([...r,e])||(m.value||=t),y.disabled=!1,m.focus()},"secondary");m.addEventListener("keydown",e=>{"Enter"===e.key&&(e.preventDefault(),y.click())}),v.append(m,y);let g=e=>{let t=a("li","approved-site"),n=a("span","",e.replace(/^https:\/\//,""));return n.title=e,t.append(n,s(`Remove ${e}`,()=>{h(r.filter(t=>t!==e))},"icon","close")),t},f=()=>{o.textContent=String(r.length),d.replaceChildren(...r.map(g))};return f(),p.append(d,v,b,u),c.append(p),i.append(l,c),i}var i=new WeakMap;function o(e,n="usage",o=!0,l=!1){let c=a("section","account-usage");c.setAttribute("aria-label","Account usage");let p=(e="")=>{let t=a("span",`usage-skeleton ${e}`);return t.setAttribute("aria-hidden","true"),t},d=e.user?.id,u=e.token,v=()=>e.user?.id===d&&e.token===u,m=i.get(e);m||i.set(e,m=new Map);let b=JSON.stringify([d,u,n]),h=m.get(b);h||m.set(b,h={});let y=e=>{c.setAttribute("aria-busy","false"),c.replaceChildren(a("h3","",`${e.hosted?"Starter plan":"Self-hosted"}${l?" · Local":""}`));let{used:t,limit:n}=e.comments,s=a("div","account-usage-label account-comments"),r=a("span","account-comment-count");if(r.append(a("span","",null===n?`${t.toLocaleString()} / Unlimited`:`${t.toLocaleString()} / ${n.toLocaleString()}`)),s.title="Includes replies and deleted comments.",null!==n){let e=a("span","account-usage-ring");e.setAttribute("role","meter"),e.setAttribute("aria-label","Project comments"),e.setAttribute("aria-valuemin","0"),e.setAttribute("aria-valuemax",String(n)),e.setAttribute("aria-valuenow",String(Math.min(t,n))),e.setAttribute("aria-valuetext",`${t} of ${n} comments used, including replies and deleted comments`),e.style.setProperty("--usage",(n>0?100*Math.min(t/n,1):0)+"%"),e.dataset.full=String(t>=n),r.append(e)}if(s.append(a("span","","Project comments"),r),c.append(s),e.projects){let{used:t,limit:n}=e.projects;if(null===n){let e=a("div","account-usage-label");return e.append(a("span","","Projects"),a("span","",`${t.toLocaleString()} / Unlimited`)),void c.append(e)}let s=a("div","account-projects"),r=a("div","account-usage-label"),i=a("span","account-project-count");i.append(a("strong","",String(t)),a("span","",`of ${n}`)),r.append(a("span","","Projects"),i);let o=a("div","account-project-slots");o.setAttribute("role","meter"),o.setAttribute("aria-label","Projects"),o.setAttribute("aria-valuemin","0"),o.setAttribute("aria-valuemax",String(n)),o.setAttribute("aria-valuenow",String(t)),o.setAttribute("aria-valuetext",`${t} of ${n} projects used`);for(let e=0;e<n;e++){let n=a("span");n.dataset.used=String(e<t),o.append(n)}s.append(r,o),c.append(s)}},g=async()=>{if(!v())return c.replaceChildren(),void c.setAttribute("aria-busy","false");h.value?y(h.value):(()=>{let e=a("div","usage-skeleton-heading");e.append(p("usage-skeleton-title"));let t=a("div","account-usage-label account-comments"),n=a("span","account-comment-count");n.append(p("usage-skeleton-count"),p("usage-skeleton-ring")),t.append(p("usage-skeleton-label"),n);let s=a("div","account-projects"),r=a("div","account-usage-label");r.append(p("usage-skeleton-label"),p("usage-skeleton-count"));let i=a("div","account-project-slots");i.setAttribute("aria-hidden","true"),i.append(a("span"),a("span"),a("span")),s.append(r,i);let o=a("span","sr-only","Loading account usage");o.setAttribute("role","status"),c.setAttribute("aria-busy","true"),c.replaceChildren(e,t,s,o)})(),c.setAttribute("aria-busy","true");try{let t,a=h.pending??=e.request(n);try{t=await a}finally{h.pending===a&&(h.pending=void 0)}if(!v())return delete h.value,c.replaceChildren(),void c.setAttribute("aria-busy","false");if(h.value=t,!c.isConnected)return;y(t),o&&e.user?.verified&&(async()=>{let t=n.includes("?")?n.slice(n.indexOf("?")):"",a=await r(e,t);a&&h.value&&c.isConnected&&v()&&c.append(a)})().catch(()=>{})}catch(e){if(e instanceof t&&(401===e.status||403===e.status)&&delete h.value,!v())return delete h.value,c.replaceChildren(),void c.setAttribute("aria-busy","false");if(!c.isConnected)return;h.value?y(h.value):c.replaceChildren(),c.setAttribute("aria-busy","false");let n=a("span","account-usage-status",h.value?"Couldn’t refresh usage":"Usage unavailable");n.setAttribute("role","status"),c.append(n,s("Retry",()=>{g()},"secondary"))}};return g(),c}function l(t,r,i){let o=a("section","account-sites project-management");o.dataset.open="false";let l=s("Project settings",()=>{let e="true"!==o.dataset.open;o.dataset.open=String(e),l.setAttribute("aria-expanded",String(e)),c.inert=!e,c.setAttribute("aria-hidden",String(!e))},"account-sites-summary");l.append(n("chevron")),l.setAttribute("aria-expanded","false");let c=a("div","account-sites-reveal");c.id=`project-settings-${crypto.randomUUID()}`,l.setAttribute("aria-controls",c.id),c.inert=!0,c.setAttribute("aria-hidden","true");let p=a("div","account-sites-clip");c.append(p);let d=a("div","account-sites-content"),u=a("p","account-usage-status");u.setAttribute("role","status");let v=r?`?workspace=${encodeURIComponent(r)}`:"",m=(e,a="GET",n)=>t.request(`project${e}${v}`,a,n);o.hidden=!0,p.append(d,u),o.append(l,c);let b,h=async e=>{let t=Array.from(o.querySelectorAll("button"));t.forEach(e=>e.disabled=!0),u.textContent="";try{await e()}catch(e){u.textContent=e instanceof Error?e.message:"Try again."}finally{t.forEach(e=>e.disabled=!1)}},y=async()=>{let e,n={format:"komo-export",version:1,project:b.project,exportedAt:(new Date).toISOString(),tables:{}};for(let a of["threads","comments","reactions","users"]){n.tables[a]=[];let s=0;for(;null!==s;){let i=await t.request(`project/export?table=${a}&offset=${s}${void 0===e?"":`&revision=${e}`}${r?`&workspace=${encodeURIComponent(r)}`:""}`);e=i.revision,n.tables[a].push(...i.rows),s=i.next}}let s=URL.createObjectURL(new Blob([JSON.stringify(n,null,2)],{type:"application/json"})),i=a("a");i.href=s,i.download=`${b.project}-comments.json`,i.click(),setTimeout(()=>URL.revokeObjectURL(s),1e3),u.textContent="Export downloaded."},g=async()=>{b=await m(""),o.hidden=!1,d.replaceChildren();let t=a("div","account-name-label");t.append(a("span","","Access"));let n,r=[["public","Anyone with the link"],["private","Invited Google accounts"]],l=()=>{let a=e("Project access",r,b.access,e=>{h(async()=>{let t=b.access;b.access=e,l();try{await m("","PATCH",{access:e}),u.textContent="Access updated."}catch(e){throw b.access=t,l(),e}})});n?n.replaceWith(a):t.append(a),n=a};l(),d.append(t);let c=await m("/webhook"),p=a("details","project-webhook");p.append(a("summary","","Comment webhooks"));let v=a("p","project-help","Send signed events to your HTTPS endpoint. Signing secrets are encrypted and shown only when entered.");p.append(v),c.deliveryAvailable||(v.textContent="Secure webhook delivery is not available on this server yet.");let f=a("label","account-name-label","HTTPS endpoint"),w=a("input");w.type="url",w.autocomplete="off",w.placeholder="https://example.com/komo-webhook",w.value=c.url,f.append(w),p.append(f);let A=a("label","account-name-label",c.secretConfigured?"Replace signing secret":"Signing secret"),C=a("input");C.type="password",C.autocomplete="new-password",C.minLength=32,C.maxLength=256,A.append(C),p.append(A);let k=new Map;for(let e of c.supportedEvents){let t=a("label","account-name-label",e),n=a("input");n.type="checkbox",n.checked=c.events.includes(e),k.set(e,n),t.prepend(n),p.append(t)}let x=a("label","account-name-label","Enable delivery"),j=a("input");j.type="checkbox",j.checked=c.enabled,j.disabled=!c.deliveryAvailable&&!c.enabled,x.prepend(j),p.append(x),p.append(s("Save webhook settings",()=>{h(async()=>{await m("/webhook","PATCH",{url:w.value,secret:C.value,events:[...k].filter(([,e])=>e.checked).map(([e])=>e),enabled:j.checked}),C.value="",u.textContent="Webhook settings saved."})},"secondary")),d.append(p);let S=a("label","account-name-label","Invite someone"),$=a("input");$.type="email",$.placeholder="name@example.com",$.autocomplete="email",S.append($);let E=a("input");E.readOnly=!0,E.hidden=!0,E.setAttribute("aria-label","Invitation link");let T=s("Create invitation",()=>{h(async()=>{if(!$.checkValidity()||!$.value)throw Error("Enter an email address.");let e=await m("/invites","POST",{email:$.value});E.value=e.url,E.hidden=!1,P.hidden=!1,u.textContent="Share this link. It expires in 7 days."})},"secondary"),P=s("Copy invitation",()=>{h(async()=>{await navigator.clipboard.writeText(E.value),u.textContent="Invitation copied."})},"secondary");P.hidden=!0,d.append(S,T,E,P);for(let e of b.members){let t=a("div","project-member");t.append(a("span","",e.name),s(`Remove ${e.name}`,()=>{h(async()=>{await m("/members","DELETE",{user:e.id}),await g(),u.textContent="Member removed."})},"secondary")),d.append(t)}for(let e of b.invites){let t=a("div","project-member");t.append(a("span","",e.email),s("Revoke invitation",()=>{h(async()=>{await m("/invites","DELETE",{email:e.email}),await g(),u.textContent="Invitation revoked."})},"secondary")),d.append(t)}d.append(s("Download comments",()=>{h(y)},"secondary"));let U=a("a","project-help","Move to self-hosting");U.href="https://komo.offbr.co/hosting/#migration",U.target="_blank",U.rel="noopener noreferrer",d.append(U);let L=a("details","project-danger");L.append(a("summary","","Free space or delete project")),L.append(a("p","",`Export first. These actions permanently remove comments. Type ${b.project} to confirm.`));let R=a("input");R.placeholder=b.project,R.setAttribute("aria-label","Confirm project key"),L.append(R),L.append(s("Delete resolved threads",()=>{h(async()=>{await m("/clear-resolved","POST",{confirm:R.value}),i?.(!1),u.textContent="Resolved threads deleted.",R.value=""})},"secondary destructive")),b.hosted&&L.append(s("Delete project",()=>{h(async()=>{await m("","DELETE",{confirm:R.value}),i?.(!0),d.replaceChildren(),u.textContent="Project deleted. Its project slot is available again."})},"secondary destructive")),d.append(L)};return g().catch(e=>{403!==e?.status&&(o.hidden=!1,u.textContent="Project settings unavailable.",d.append(s("Retry",()=>{h(g)},"secondary")))}),o}function c(e,t){let r=a("section","onboarding-panel"),i=a("p","account-usage-status");i.setAttribute("role","status");let l=e=>{i.textContent=e instanceof Error?e.message:"Try again."},c=async()=>{let p=encodeURIComponent(t.workspace),d=a("div","account-sites"),u=a("div","account-sites-summary");u.append(a("span","","Approved sites"),n("chevron")),d.append(u),d.setAttribute("aria-busy","true"),i.textContent="",r.replaceChildren(o(e,`usage?workspace=${p}`,!1),d,i);try{let o=await e.request(`workspace?workspace=${p}`);if(!r.isConnected)return;i.textContent="";let c=a("section","account-sites");c.dataset.open="false";let u=s("",()=>{let e="true"!==c.dataset.open;c.dataset.open=String(e),u.setAttribute("aria-expanded",String(e)),v.inert=!e,v.setAttribute("aria-hidden",String(!e))},"account-sites-summary");u.setAttribute("aria-expanded","false");let v=a("div","account-sites-reveal");v.id=`approved-sites-${crypto.randomUUID()}`,v.inert=!0,v.setAttribute("aria-hidden","true"),u.setAttribute("aria-controls",v.id);let m=a("div","account-sites-clip"),b=a("span","account-sites-count");u.append(a("span","","Approved sites"),b,n("chevron"));let h=a("div","account-sites-content"),y=a("div","approved-sites"),g=()=>{b.textContent=String(o.sites.length),y.replaceChildren(...o.sites.map(e=>a("span","",new URL(e).host)))};g();let f=a("label","account-name-label","Website"),w=a("input");w.type="url",w.placeholder="https://your-site.com",w.setAttribute("autocomplete","url"),w.value=t.site||o.suggested.find(e=>!o.sites.includes(e))||"",f.append(w);let A=s("Approve site",async()=>{let a;try{let e=new URL(w.value.trim());if("https:"!==e.protocol||e.username||e.password)throw Error("Enter an HTTPS website address.");a=e.origin}catch(e){return void l(e)}let n=[...o.sites],s=w.value;o.sites.includes(a)||o.sites.push(a),g(),w.value="",A.disabled=!0;try{await e.request("workspace/sites","POST",{project:t.workspace,origin:a}),t.site=void 0,i.textContent="Site approved"}catch(e){o.sites=n,g(),w.value||(w.value=s),l(e)}finally{A.disabled=!1}},"secondary");w.addEventListener("keydown",e=>{"Enter"===e.key&&(e.preventDefault(),A.click())});let C=a("div","account-usage-note account-sites-note");C.append(n("info"),a("span","","Approved sites can show and share comments. Localhost comments are visible by default.")),h.append(y,f,A,C),m.append(h),v.append(m),c.append(u,v),d.replaceWith(c)}catch(e){l(e),r.append(s("Retry",()=>{c()},"secondary"))}};if(t.invite){let n=s("Accept invitation",async()=>{n.disabled=!0;try{await e.request("project/join","POST",{invite:t.invite}),t.invite=void 0,r.replaceChildren(a("p","","You’re in. Return to the website to leave comments."))}catch(e){l(e),n.disabled=!1}},"primary");r.append(n,i)}else if(t.workspace)c();else if(t.code||t.claimKey){let a=s(t.code?"Create project":"Enable comments",async()=>{a.disabled=!0;let n=a.textContent;a.textContent=t.code?"Creating project…":"Enabling comments…";try{if(t.code){let a=await e.request("setup/complete","POST",{code:t.code});t.workspace=a.project,t.code=void 0,history.replaceState(null,"",`/setup?workspace=${encodeURIComponent(a.project)}`),await c(),i.textContent="Project ready. Return to your terminal."}else await e.request("owner/claim","POST",{key:t.claimKey}),t.claimKey=void 0,r.replaceChildren(o(e),i),i.textContent="Comments are ready."}catch(e){l(e),a.disabled=!1,a.textContent=n}},"primary");r.append(a,i)}else r.append(o(e));return r}export{o as accountUsage,c as onboardingPanel,l as projectManagement};
package/dist/react.js CHANGED
@@ -1 +1 @@
1
- "use client";import{b as e,c as n,f as t,z as r}from"./chunk-JXIYWNFL.js";import{b as o}from"./chunk-VQF5NSYU.js";import"./chunk-KMYXE4O6.js";import"./chunk-DH22G2S5.js";import"./chunk-7YUXYVQA.js";import"./chunk-62YUEO4G.js";import"./chunk-I7AUKTXE.js";import{useEffect as s,useRef as c}from"react";function u(e){let n=c(null);s(()=>{if(n.current&&function(e,n){return[...new Set([...Object.keys(e),...Object.keys(n)])].every(t=>{if("shortcuts"===t||"features"===t){let r=e[t]??{},o=n[t]??{};return Object.keys({...r,...o}).every(e=>Object.is(r[e],o[e]))}if("design"===t){let t=e.design,r=n.design;if(!t||!r)return t===r;let o=t.themes??[],s=r.themes??[];return t.tokens===r.tokens&&t.components===r.components&&o.length===s.length&&o.every((e,n)=>e===s[n])}if("onboarding"!==t)return Object.is(e[t],n[t]);let r=e.onboarding,o=n.onboarding;return r&&o?Object.keys({...r,...o}).every(e=>"sites"===e?r.sites?.length===o.sites?.length&&(r.sites??[]).every((e,n)=>e===o.sites?.[n]):Object.is(r[e],o[e])):r===o})}(n.current.config,e)||(n.current?.controller.destroy(),n.current=null,!1===e.enabled))return;let t={...e,...e.onboarding?{onboarding:{...e.onboarding,...e.onboarding.sites?{sites:[...e.onboarding.sites]}:{}}}:{}};n.current={config:t,controller:o(t)}}),s(()=>()=>{n.current?.controller.destroy(),n.current=null},[])}function i(t){let r=c(null),o=c(null);return o.current||(o.current=e=>{r.current=e}),s(()=>{if(!0===t.enabled&&r.current)return e(r.current,t.component,t.props,t.onChange)},[t.enabled,t.component]),s(()=>{!0===t.enabled&&n(r.current,t.component,t.props,t.onChange)},[t.enabled,t.component,t.props,t.onChange]),{ref:o.current,"data-komo-inspectable":t.component.id}}function l(e){s(()=>{if(!0!==e.enabled)return;let n=e.root??document.documentElement;return t(n,e.tokens)},[e.root,e.tokens,e.enabled])}export{r as cssVariableTokens,u as useKomo,l as useKomoDesignTokens,i as useKomoInspectable};
1
+ "use client";import{b as e,c as n,f as t,z as r}from"./chunk-JXIYWNFL.js";import{b as o}from"./chunk-LTTJF7OZ.js";import"./chunk-URGMAMH5.js";import"./chunk-DH22G2S5.js";import"./chunk-7YUXYVQA.js";import"./chunk-ANKCS6NI.js";import"./chunk-I7AUKTXE.js";import{useEffect as s,useRef as c}from"react";function u(e){let n=c(null);s(()=>{if(n.current&&function(e,n){return[...new Set([...Object.keys(e),...Object.keys(n)])].every(t=>{if("shortcuts"===t||"features"===t){let r=e[t]??{},o=n[t]??{};return Object.keys({...r,...o}).every(e=>Object.is(r[e],o[e]))}if("design"===t){let t=e.design,r=n.design;if(!t||!r)return t===r;let o=t.themes??[],s=r.themes??[];return t.tokens===r.tokens&&t.components===r.components&&o.length===s.length&&o.every((e,n)=>e===s[n])}if("onboarding"!==t)return Object.is(e[t],n[t]);let r=e.onboarding,o=n.onboarding;return r&&o?Object.keys({...r,...o}).every(e=>"sites"===e?r.sites?.length===o.sites?.length&&(r.sites??[]).every((e,n)=>e===o.sites?.[n]):Object.is(r[e],o[e])):r===o})}(n.current.config,e)||(n.current?.controller.destroy(),n.current=null,!1===e.enabled))return;let t={...e,...e.onboarding?{onboarding:{...e.onboarding,...e.onboarding.sites?{sites:[...e.onboarding.sites]}:{}}}:{}};n.current={config:t,controller:o(t)}}),s(()=>()=>{n.current?.controller.destroy(),n.current=null},[])}function i(t){let r=c(null),o=c(null);return o.current||(o.current=e=>{r.current=e}),s(()=>{if(!0===t.enabled&&r.current)return e(r.current,t.component,t.props,t.onChange)},[t.enabled,t.component]),s(()=>{!0===t.enabled&&n(r.current,t.component,t.props,t.onChange)},[t.enabled,t.component,t.props,t.onChange]),{ref:o.current,"data-komo-inspectable":t.component.id}}function l(e){s(()=>{if(!0!==e.enabled)return;let n=e.root??document.documentElement;return t(n,e.tokens)},[e.root,e.tokens,e.enabled])}export{r as cssVariableTokens,u as useKomo,l as useKomoDesignTokens,i as useKomoInspectable};
package/dist/setup.js CHANGED
@@ -1 +1 @@
1
- import{a as o,c as n}from"./chunk-VQF5NSYU.js";import"./chunk-KMYXE4O6.js";import"./chunk-DH22G2S5.js";import"./chunk-7YUXYVQA.js";import"./chunk-62YUEO4G.js";import"./chunk-I7AUKTXE.js";function r(r){return(s={})=>n(o({...r,...s}))}export{r as defineKomo};
1
+ import{a as o,c as n}from"./chunk-LTTJF7OZ.js";import"./chunk-URGMAMH5.js";import"./chunk-DH22G2S5.js";import"./chunk-7YUXYVQA.js";import"./chunk-ANKCS6NI.js";import"./chunk-I7AUKTXE.js";function r(r){return(s={})=>n(o({...r,...s}))}export{r as defineKomo};
@@ -0,0 +1 @@
1
+ import{$ as t,A as e,B as n,C as r,D as i,E as o,F as s,G as a,H as l,I as u,J as c,K as d,L as h,M as m,N as p,O as f,P as g,Q as v,R as y,S as x,T as w,U as E,V as P,W as S,X as b,Y as C,Z as M,_ as k,a as T,aa as A,b as L,ba as D,c as I,ca as j,da as V,ea as R,fa as _,ga as N,ha as O,ia as W,j as B,ja as F,k as H,ka as U,l as $,m as G,n as Y,o as X,p as z,q,r as K,s as J,t as Q,u as Z,v as tt,w as et,x as nt,y as rt,z as it}from"./chunk-7YUXYVQA.js";import{c as ot,h as st,l as at,o as lt}from"./chunk-ANKCS6NI.js";import{a as ut}from"./chunk-I7AUKTXE.js";import{createRoot as ct}from"react-dom/client";import{flushSync as dt}from"react-dom";import{createElement as ht}from"react";import*as mt from"react";var pt=({size:t=24,color:e="currentColor",...n})=>mt.createElement("svg",{viewBox:"0 0 24 24",width:t,height:t,stroke:e,strokeWidth:"2",fill:"none",strokeLinecap:"round",strokeLinejoin:"round","aria-hidden":"true",...n},mt.createElement("path",{d:"m7 15 5 5 5-5M7 9l5-5 5 5"}));pt.displayName="ChevronSelectorVertical";import*as ft from"react";var gt=({size:t=24,color:e="currentColor",...n})=>ft.createElement("svg",{viewBox:"0 0 24 24",width:t,height:t,stroke:e,strokeWidth:"2",fill:"none",strokeLinecap:"round",strokeLinejoin:"round","aria-hidden":"true",...n},ft.createElement("path",{d:"M18 6 6 18M6 6l12 12"}));gt.displayName="XClose";import*as vt from"react";var yt=({size:t=24,color:e="currentColor",...n})=>vt.createElement("svg",{viewBox:"0 0 24 24",width:t,height:t,stroke:e,strokeWidth:"2",fill:"none",strokeLinecap:"round",strokeLinejoin:"round","aria-hidden":"true",...n},vt.createElement("path",{d:"M19 12H5m0 0 7 7m-7-7 7-7"}));yt.displayName="ArrowLeft";import*as xt from"react";var wt=({size:t=24,color:e="currentColor",...n})=>xt.createElement("svg",{viewBox:"0 0 24 24",width:t,height:t,stroke:e,strokeWidth:"2",fill:"none",strokeLinecap:"round",strokeLinejoin:"round","aria-hidden":"true",...n},xt.createElement("path",{d:"m9 18 6-6-6-6"}));wt.displayName="ChevronRight";import{useEffect as Et,useId as Pt,useLayoutEffect as St,useRef as bt,useState as Ct}from"react";import{createContext as Mt}from"react";var kt=Mt({});import{useRef as Tt}from"react";import{useLayoutEffect as At,useEffect as Lt}from"react";var Dt=typeof window<"u"?At:Lt;import{createContext as It}from"react";var jt=It(null);import{createContext as Vt}from"react";var Rt=Vt({transformPagePoint:t=>t,isStatic:!1,reducedMotion:"never"});import{useContext as _t,useId as Nt,useEffect as Ot,useCallback as Wt}from"react";import{createContext as Bt}from"react";var Ft=Bt({strict:!1}),Ht={animation:["animate","variants","whileHover","whileTap","exit","whileInView","whileFocus","whileDrag"],exit:["exit"],drag:["drag","dragControls"],focus:["whileFocus"],hover:["whileHover","onHoverStart","onHoverEnd"],tap:["whileTap","onTap","onTapStart","onTapCancel"],pan:["onPan","onPanStart","onPanSessionStart","onPanEnd"],inView:["whileInView","onViewportEnter","onViewportLeave"],layout:["layout","layoutId"]},Ut=!1;function $t(){return function(){if(Ut)return;let t={};for(let e in Ht)t[e]={isEnabled:t=>Ht[e].some(e=>!!t[e])};v(t),Ut=!0}(),y()}var Gt=new Set(["animate","exit","variants","initial","style","values","variants","transition","transformTemplate","custom","inherit","onBeforeLayoutMeasure","onAnimationStart","onAnimationComplete","onUpdate","onDragStart","onDrag","onDragEnd","onMeasureDragConstraints","onDirectionLock","onDragTransitionEnd","_dragX","_dragY","onHoverStart","onHoverEnd","onViewportEnter","onViewportLeave","globalTapTarget","propagate","ignoreStrict","viewport"]);function Yt(t){return t.startsWith("while")||t.startsWith("drag")&&"draggable"!==t||t.startsWith("layout")||t.startsWith("onTap")||t.startsWith("onPan")||t.startsWith("onLayout")||Gt.has(t)}var Xt,zt=t=>!Yt(t);try{"function"==typeof(Xt=ut("@emotion/is-prop-valid").default)&&(zt=t=>t.startsWith("on")?!Yt(t):Xt(t))}catch{}import{jsxs as qt,jsx as Kt}from"react/jsx-runtime";import{forwardRef as Jt,useContext as Qt}from"react";import{createContext as Zt}from"react";var te=Zt({});import{useContext as ee,useMemo as ne}from"react";function re(t){let{initial:e,animate:n}=function(t,e){if(h(t)){let{initial:e,animate:n}=t;return{initial:!1===e||d(e)?e:void 0,animate:d(n)?n:void 0}}return!1!==t.inherit?e:{}}(t,ee(te));return ne(()=>({initial:e,animate:n}),[ie(e),ie(n)])}function ie(t){return Array.isArray(t)?t.join(" "):t}import{Fragment as oe,useMemo as se,createElement as ae}from"react";import{useMemo as le}from"react";var ue=()=>({style:{},transform:{},transformOrigin:{},vars:{}});function ce(t,e,n){for(let r in e)!rt(e[r])&&!b(r,n)&&(t[r]=e[r])}function de(t,e){let n={};return ce(n,t.style||{},t),Object.assign(n,function({transformTemplate:t},e){return le(()=>{let n={style:{},transform:{},transformOrigin:{},vars:{}};return S(n,e,t),Object.assign({},n.vars,n.style)},[e])}(t,e)),n}function he(t,e){let n={},r=de(t,e);return t.drag&&!1!==t.dragListener&&(n.draggable=!1,r.userSelect=r.WebkitUserSelect=r.WebkitTouchCallout="none",r.touchAction=!0===t.drag?"none":"pan-"+("x"===t.drag?"y":"x")),void 0===t.tabIndex&&(t.onTap||t.onTapStart||t.whileTap)&&(n.tabIndex=0),n.style=r,n}import{useMemo as me}from"react";var pe=()=>({style:{},transform:{},transformOrigin:{},vars:{},attrs:{}});function fe(e,n,r,i){let o=me(()=>{let r={style:{},transform:{},transformOrigin:{},vars:{},attrs:{}};return k(r,n,t(i),e.transformTemplate,e.style),{...r.attrs,style:{...r.style}}},[n]);if(e.style){let t={};ce(t,e.style,e),o.style={...t,...o.style}}return o}var ge=["animate","circle","defs","desc","ellipse","g","image","line","filter","marker","mask","metadata","path","pattern","polygon","polyline","rect","stop","switch","symbol","svg","text","tspan","use","view"];function ve(t){return"string"==typeof t&&!t.includes("-")&&!!(ge.indexOf(t)>-1||/[A-Z]/u.test(t))}function ye(t,e,n,{latestValues:r},i,o=!1,s){let a=(s??ve(t)?fe:he)(e,r,i,t),l=function(t,e,n){let r={};for(let i in t)"values"===i&&"object"==typeof t.values||rt(t[i])||(zt(i)||!0===n&&Yt(i)||!e&&!Yt(i)||t.draggable&&i.startsWith("onDrag"))&&(r[i]=t[i]);return r}(e,"string"==typeof t,o),u=t!==oe?{...l,...a,ref:n}:{},{children:c}=e,d=se(()=>rt(c)?c.get():c,[c]);return ae(t,{...u,children:d})}import{useContext as xe}from"react";function we(t,e,n,r){let i={},o=r(t,{});for(let t in o)i[t]=N(o[t]);let{initial:s,animate:a}=t,l=h(t),u=m(t);e&&u&&!l&&!1!==t.inherit&&(void 0===s&&(s=e.initial),void 0===a&&(a=e.animate));let d=!!n&&!1===n.initial;d=d||!1===s;let p=d?a:s;if(p&&"boolean"!=typeof p&&!c(p)){let e=Array.isArray(p)?p:[p];for(let n=0;n<e.length;n++){let r=et(t,e[n]);if(r){let{transitionEnd:t,transition:e,...n}=r;for(let t in n){let e=n[t];if(Array.isArray(e)){e=e[d?e.length-1:0]}null!==e&&(i[t]=e)}for(let e in t)i[e]=t[e]}}}return i}var Ee=t=>(e,n)=>{let r=xe(te),i=xe(jt),o=()=>function({scrapeMotionValuesFromProps:t,createRenderState:e},n,r,i){return{latestValues:we(n,r,i,t),renderState:e()}}(t,e,r,i);return n?o():function(t){let e=Tt(null);return null===e.current&&(e.current=t()),e.current}(o)},Pe=Ee({scrapeMotionValuesFromProps:C,createRenderState:ue}),Se=Ee({scrapeMotionValuesFromProps:A,createRenderState:pe}),be=Symbol.for("motionComponentSymbol");import{useRef as Ce,useInsertionEffect as Me,useCallback as ke}from"react";function Te(t,e,n){let r=Ce(n);Me(()=>{r.current=n});let i=Ce(null);return ke(n=>{n&&t.onMount?.(n),e&&(n?e.mount(n):e.unmount());let o=r.current;if("function"==typeof o)if(n){let t=o(n);"function"==typeof t&&(i.current=t)}else i.current?(i.current(),i.current=null):o(n);else o&&(o.current=n)},[e])}import{useContext as Ae,useRef as Le,useInsertionEffect as De,useEffect as Ie}from"react";import{createContext as je}from"react";var Ve=je({});function Re(t){return t&&"object"==typeof t&&Object.prototype.hasOwnProperty.call(t,"current")}function _e(t,n,r,i,o,s){let{visualElement:a}=Ae(te),l=Ae(Ft),u=Ae(jt),c=Ae(Rt),d=c.reducedMotion,h=c.skipAnimations,m=Le(null),p=Le(!1);i=i||l.renderer,!m.current&&i&&(m.current=i(t,{visualState:n,parent:a,props:r,presenceContext:u,blockInitialAnimation:!!u&&!1===u.initial,reducedMotionConfig:d,skipAnimations:h,isSVG:s}),p.current&&m.current&&(m.current.manuallyAnimateOnMount=!0));let f=m.current,g=Ae(Ve);f&&!f.projection&&o&&("html"===f.type||"svg"===f.type)&&function(t,e,n,r){let{layoutId:i,layout:o,drag:s,dragConstraints:a,layoutScroll:l,layoutRoot:u,layoutAnchor:c,layoutCrossfade:d}=e;t.projection=new n(t.latestValues,e["data-framer-portal-id"]?void 0:Ne(t.parent)),t.projection.setOptions({layoutId:i,layout:o,alwaysMeasureLayout:!!s||a&&Re(a),visualElement:t,animationType:"string"==typeof o?o:"both",initialPromotionConfig:r,crossfade:d,layoutScroll:l,layoutRoot:u,layoutAnchor:c})}(m.current,r,o,g);let v=Le(!1);De(()=>{f&&v.current&&f.update(r,u)});let y=r[e],x=Le(!!y&&typeof window<"u"&&!window.MotionHandoffIsComplete?.(y)&&window.MotionHasOptimisedAnimation?.(y));return Dt(()=>{p.current=!0,f&&(v.current=!0,window.MotionIsMounted=!0,f.updateFeatures(),f.scheduleRenderMicrotask(),x.current&&f.animationState&&f.animationState.animateChanges())}),Ie(()=>{f&&(!x.current&&f.animationState&&f.animationState.animateChanges(),x.current&&(queueMicrotask(()=>{window.MotionHandoffMarkAsComplete?.(y)}),x.current=!1),f.enteringChildren=void 0)}),f}function Ne(t){if(t)return!1!==t.options.allowProjection?t.projection:Ne(t.parent)}function Oe(t,{forwardMotionProps:e=!1,type:n}={},r,i){r&&function(t){let e=$t();for(let n in t)e[n]={...e[n],...t[n]};v(e)}(r);let o=n?"svg"===n:ve(t),s=o?Se:Pe;function a(n,r){let a,l={...Qt(Rt),...n,layoutId:We(n)},{isStatic:u}=l,c=re(n),d=s(n,u);if(!u&&typeof window<"u"){Qt(Ft).strict;let e=function(t){let e=$t(),{drag:n,layout:r}=e;if(!n&&!r)return{};let i={...n,...r};return{MeasureLayout:n?.isEnabled(t)||r?.isEnabled(t)?i.MeasureLayout:void 0,ProjectionNode:i.ProjectionNode}}(l);a=e.MeasureLayout,c.visualElement=_e(t,d,l,i,e.ProjectionNode,o)}return qt(te.Provider,{value:c,children:[a&&c.visualElement?Kt(a,{visualElement:c.visualElement,...l}):null,ye(t,n,Te(d,c.visualElement,r),d,u,e,o)]})}a.displayName=`motion.${"string"==typeof t?t:`create(${t.displayName??t.name??""})`}`;let l=Jt(a);return l[be]=t,l}function We({layoutId:t}){let e=Qt(kt).id;return e&&void 0!==t?e+"-"+t:t}import{Fragment as Be}from"react";var Fe=0,He={animation:{Feature:class extends x{constructor(t){super(t),t.animationState||(t.animationState=j(t))}updateAnimationControlsSubscription(){let{animate:t}=this.node.getProps();c(t)&&(this.unmountControls=t.subscribe(this.node))}mount(){this.updateAnimationControlsSubscription()}update(){let{animate:t}=this.node.getProps(),{animate:e}=this.node.prevProps||{};t!==e&&this.updateAnimationControlsSubscription()}unmount(){this.node.animationState.reset(),this.unmountControls?.()}}},exit:{Feature:class extends x{constructor(){super(...arguments),this.id=Fe++,this.isExitComplete=!1}update(){if(!this.node.presenceContext)return;let{isPresent:t,onExitComplete:e}=this.node.presenceContext,{isPresent:n}=this.node.prevPresenceContext||{};if(!this.node.animationState||t===n)return;if(t&&!1===n){if(this.isExitComplete){let{initial:t,custom:e}=this.node.getProps();if("string"==typeof t||"object"==typeof t&&null!==t&&!Array.isArray(t)){let n=nt(this.node,t,e);if(n){let{transition:t,transitionEnd:e,...r}=n;for(let t in r)this.node.getValue(t)?.jump(r[t])}}this.node.animationState.reset(),this.node.animationState.animateChanges()}else this.node.animationState.setActive("exit",!1);return void(this.isExitComplete=!1)}let r=this.node.animationState.setActive("exit",!t);e&&!t&&r.then(()=>{this.isExitComplete=!0,e(this.id)})}mount(){let{register:t,onExitComplete:e}=this.node.presenceContext||{};e&&e(this.id),t&&(this.unmount=t(this.id))}unmount(){}}}};function Ue(t){return{point:{x:t.pageX,y:t.pageY}}}function $e(t,e,n,r){return _(t,e,(t=>e=>o(e)&&t(e,Ue(e)))(n),r)}var Ge=({current:t})=>t?t.ownerDocument.defaultView:null,Ye=new Set(["auto","scroll"]),Xe=class{constructor(t,e,{transformPagePoint:n,contextWindow:r=window,dragSnapToOrigin:i=!1,distanceThreshold:s=3,element:a}={}){if(this.startEvent=null,this.lastMoveEvent=null,this.lastMoveEventInfo=null,this.lastRawMoveEventInfo=null,this.handlers={},this.contextWindow=window,this.scrollPositions=new Map,this.removeScrollListeners=null,this.onElementScroll=t=>{this.handleScroll(t.target)},this.onWindowScroll=()=>{this.handleScroll(window)},this.updatePoint=()=>{if(!this.lastMoveEvent||!this.lastMoveEventInfo)return;this.lastRawMoveEventInfo&&(this.lastMoveEventInfo=ze(this.lastRawMoveEventInfo,this.transformPagePoint));let t=Ke(this.lastMoveEventInfo,this.history),e=null!==this.startEvent,n=U(t.offset,{x:0,y:0})>=this.distanceThreshold;if(!e&&!n)return;let{point:r}=t,{timestamp:i}=J;this.history.push({...r,timestamp:i});let{onStart:o,onMove:s}=this.handlers;e||(o&&o(this.lastMoveEvent,t),this.startEvent=this.lastMoveEvent),s&&s(this.lastMoveEvent,t)},this.handlePointerMove=(t,e)=>{this.lastMoveEvent=t,this.lastRawMoveEventInfo=e,this.lastMoveEventInfo=ze(e,this.transformPagePoint),q.update(this.updatePoint,!0)},this.handlePointerUp=(t,e)=>{this.end();let{onEnd:n,onSessionEnd:r,resumeAnimation:i}=this.handlers;if((this.dragSnapToOrigin||!this.startEvent)&&i&&i(),!this.lastMoveEvent||!this.lastMoveEventInfo)return;let o=Ke("pointercancel"===t.type?this.lastMoveEventInfo:ze(e,this.transformPagePoint),this.history);this.startEvent&&n&&n(t,o),r&&r(t,o)},!o(t))return;this.dragSnapToOrigin=i,this.handlers=e,this.transformPagePoint=n,this.distanceThreshold=s,this.contextWindow=r||window;let l=ze(Ue(t),this.transformPagePoint),{point:u}=l,{timestamp:c}=J;this.history=[{...u,timestamp:c}];let{onSessionStart:d}=e;d&&d(t,Ke(l,this.history));let h={passive:!0,capture:!0};this.removeListeners=G($e(this.contextWindow,"pointermove",this.handlePointerMove,h),$e(this.contextWindow,"pointerup",this.handlePointerUp,h),$e(this.contextWindow,"pointercancel",this.handlePointerUp,h)),a&&this.startScrollTracking(a)}startScrollTracking(t){let e=t.parentElement;for(;e;){let t=getComputedStyle(e);(Ye.has(t.overflowX)||Ye.has(t.overflowY))&&this.scrollPositions.set(e,{x:e.scrollLeft,y:e.scrollTop}),e=e.parentElement}this.scrollPositions.set(window,{x:window.scrollX,y:window.scrollY}),window.addEventListener("scroll",this.onElementScroll,{capture:!0}),window.addEventListener("scroll",this.onWindowScroll),this.removeScrollListeners=()=>{window.removeEventListener("scroll",this.onElementScroll,{capture:!0}),window.removeEventListener("scroll",this.onWindowScroll)}}handleScroll(t){let e=this.scrollPositions.get(t);if(!e)return;let n=t===window,r=n?{x:window.scrollX,y:window.scrollY}:{x:t.scrollLeft,y:t.scrollTop},i=r.x-e.x,o=r.y-e.y;0===i&&0===o||(n?this.lastMoveEventInfo&&(this.lastMoveEventInfo.point.x+=i,this.lastMoveEventInfo.point.y+=o):this.history.length>0&&(this.history[0].x-=i,this.history[0].y-=o),this.scrollPositions.set(t,r),q.update(this.updatePoint,!0))}updateHandlers(t){this.handlers=t}end(){this.removeListeners&&this.removeListeners(),this.removeScrollListeners&&this.removeScrollListeners(),this.scrollPositions.clear(),K(this.updatePoint)}};function ze(t,e){return e?{point:e(t.point)}:t}function qe(t,e){return{x:t.x-e.x,y:t.y-e.y}}function Ke({point:t},e){return{point:t,delta:qe(t,Qe(e)),offset:qe(t,Je(e)),velocity:Ze(e,.1)}}function Je(t){return t[0]}function Qe(t){return t[t.length-1]}function Ze(t,e){if(t.length<2)return{x:0,y:0};let n=t.length-1,r=null,i=Qe(t);for(;n>=0&&(r=t[n],!(i.timestamp-r.timestamp>X(e)));)n--;if(!r)return{x:0,y:0};r===t[0]&&t.length>2&&i.timestamp-r.timestamp>2*X(e)&&(r=t[1]);let o=z(i.timestamp-r.timestamp);if(0===o)return{x:0,y:0};let s={x:(i.x-r.x)/o,y:(i.y-r.y)/o};return s.x===1/0&&(s.x=0),s.y===1/0&&(s.y=0),s}function tn(t,e,n){return{min:void 0!==e?t.min+e:void 0,max:void 0!==n?t.max+n-(t.max-t.min):void 0}}function en(t,e){let n=e.min-t.min,r=e.max-t.max;return e.max-e.min<t.max-t.min&&([n,r]=[r,n]),{min:n,max:r}}var nn=.35;function rn(t,e,n){return{min:on(t,e),max:on(t,n)}}function on(t,e){return"number"==typeof t?t:t[e]||0}var sn=new WeakMap,an=class{constructor(t){this.openDragLock=null,this.isDragging=!1,this.currentDirection=null,this.originPoint={x:0,y:0},this.constraints=!1,this.hasMutatedConstraints=!1,this.elastic=u(),this.latestPointerEvent=null,this.latestPanInfo=null,this.visualElement=t}start(t,{snapToCursor:e=!1,distanceThreshold:n}={}){let{presenceContext:i}=this.visualElement;if(i&&!1===i.isPresent)return;let{dragSnapToOrigin:o}=this.getProps();this.panSession=new Xe(t,{onSessionStart:t=>{e&&this.snapToCursor(Ue(t).point),this.stopAnimation()},onStart:(t,e)=>{let{drag:n,dragPropagation:i,onDragStart:o}=this.getProps();if(n&&!i&&(this.openDragLock&&this.openDragLock(),this.openDragLock=r(n),!this.openDragLock))return;this.latestPointerEvent=t,this.latestPanInfo=e,this.isDragging=!0,this.currentDirection=null,this.resolveConstraints(),this.visualElement.projection&&(this.visualElement.projection.isAnimationBlocked=!0,this.visualElement.projection.target=void 0),R(t=>{let e=this.getAxisMotionValue(t).get()||0;if(Q.test(e)){let{projection:n}=this.visualElement;if(n&&n.layout){let r=n.layout.layoutBox[t];r&&(e=V(r)*(parseFloat(e)/100))}}this.originPoint[t]=e}),o&&q.update(()=>o(t,e),!1,!0),it(this.visualElement,"transform");let{animationState:s}=this.visualElement;s&&s.setActive("whileDrag",!0)},onMove:(t,e)=>{this.latestPointerEvent=t,this.latestPanInfo=e;let{dragPropagation:n,dragDirectionLock:r,onDirectionLock:i,onDrag:o}=this.getProps();if(!n&&!this.openDragLock)return;let{offset:s}=e;if(r&&null===this.currentDirection)return this.currentDirection=function(t,e=10){let n=null;return Math.abs(t.y)>e?n="y":Math.abs(t.x)>e&&(n="x"),n}(s),void(null!==this.currentDirection&&i&&i(this.currentDirection));this.updateAxis("x",e.point,s),this.updateAxis("y",e.point,s),this.visualElement.render(),o&&q.update(()=>o(t,e),!1,!0)},onSessionEnd:(t,e)=>{this.latestPointerEvent=t,this.latestPanInfo=e,this.stop(t,e),this.latestPointerEvent=null,this.latestPanInfo=null},resumeAnimation:()=>{let{dragSnapToOrigin:t}=this.getProps();(t||this.constraints)&&this.startAnimation({x:0,y:0})}},{transformPagePoint:this.visualElement.getTransformPagePoint(),dragSnapToOrigin:o,distanceThreshold:n,contextWindow:Ge(this.visualElement),element:this.visualElement.current})}stop(t,e){let n=t||this.latestPointerEvent,r=e||this.latestPanInfo,i=this.isDragging;if(this.cancel(),!i||!r||!n)return;let{velocity:o}=r;this.startAnimation(o);let{onDragEnd:s}=this.getProps();s&&q.postRender(()=>s(n,r))}cancel(){this.isDragging=!1;let{projection:t,animationState:e}=this.visualElement;t&&(t.isAnimationBlocked=!1),this.endPanSession();let{dragPropagation:n}=this.getProps();!n&&this.openDragLock&&(this.openDragLock(),this.openDragLock=null),e&&e.setActive("whileDrag",!1)}endPanSession(){this.panSession&&this.panSession.end(),this.panSession=void 0}updateAxis(t,e,n){let{drag:r}=this.getProps();if(!n||!un(t,r,this.currentDirection))return;let i=this.getAxisMotionValue(t),o=this.originPoint[t]+n[t];this.constraints&&this.constraints[t]&&(o=function(t,{min:e,max:n},r){return void 0!==e&&t<e?t=r?Z(e,t,r.min):Math.max(t,e):void 0!==n&&t>n&&(t=r?Z(n,t,r.max):Math.min(t,n)),t}(o,this.constraints[t],this.elastic[t])),i.set(o)}resolveConstraints(){let{dragConstraints:t,dragElastic:e}=this.getProps(),n=this.visualElement.projection&&!this.visualElement.projection.layout?this.visualElement.projection.measure(!1):this.visualElement.projection?.layout,r=this.constraints;t&&Re(t)?this.constraints||(this.constraints=this.resolveRefConstraints()):this.constraints=!(!t||!n)&&function(t,{top:e,left:n,bottom:r,right:i}){return{x:tn(t.x,n,i),y:tn(t.y,e,r)}}(n.layoutBox,t),this.elastic=function(t=nn){return!1===t?t=0:!0===t&&(t=nn),{x:rn(t,"left","right"),y:rn(t,"top","bottom")}}(e),r!==this.constraints&&!Re(t)&&n&&this.constraints&&!this.hasMutatedConstraints&&R(t=>{!1!==this.constraints&&this.getAxisMotionValue(t)&&(this.constraints[t]=function(t,e){let n={};return void 0!==e.min&&(n.min=e.min-t.min),void 0!==e.max&&(n.max=e.max-t.min),n}(n.layoutBox[t],this.constraints[t]))})}resolveRefConstraints(){let{dragConstraints:t,onMeasureDragConstraints:e}=this.getProps();if(!t||!Re(t))return!1;let n=t.current;H(null!==n,"If `dragConstraints` is set as a React ref, that ref must be passed to another component's `ref` prop.","drag-constraints-ref");let{projection:r}=this.visualElement;if(!r||!r.layout)return!1;r.root&&(r.root.scroll=void 0,r.root.updateScroll());let i=P(n,r.root,this.visualElement.getTransformPagePoint()),o=function(t,e){return{x:en(t.x,e.x),y:en(t.y,e.y)}}(r.layout.layoutBox,i);if(e){let t=e(E(o));this.hasMutatedConstraints=!!t,t&&(o=w(t))}return o}startAnimation(t){let{drag:e,dragMomentum:n,dragElastic:r,dragTransition:i,dragSnapToOrigin:o,onDragTransitionEnd:s}=this.getProps(),a=this.constraints||{},l=R(s=>{if(!un(s,e,this.currentDirection))return;let l=a&&a[s]||{};(!0===o||o===s)&&(l={min:0,max:0});let u=r?200:1e6,c=r?40:1e7,d={type:"inertia",velocity:n?t[s]:0,bounceStiffness:u,bounceDamping:c,timeConstant:750,restDelta:1,restSpeed:10,...i,...l};return this.startAxisValueAnimation(s,d)});return Promise.all(l).then(s)}startAxisValueAnimation(t,e){let n=this.getAxisMotionValue(t);return it(this.visualElement,t),n.start(tt(t,n,0,e,this.visualElement,!1))}stopAnimation(){R(t=>this.getAxisMotionValue(t).stop())}getAxisMotionValue(t){let e=`_drag${t.toUpperCase()}`;return this.visualElement.getProps()[e]||this.visualElement.getValue(t,this.visualElement.latestValues[t]??0)}snapToCursor(t){R(e=>{let{drag:n}=this.getProps();if(!un(e,n,this.currentDirection))return;let{projection:r}=this.visualElement,i=this.getAxisMotionValue(e);if(r&&r.layout){let{min:n,max:o}=r.layout.layoutBox[e],s=i.get()||0;i.set(t[e]-Z(n,o,.5)+s)}})}scalePositionWithinConstraints(){if(!this.visualElement.current)return;let{drag:t,dragConstraints:e}=this.getProps(),{projection:n}=this.visualElement;if(!Re(e)||!n||!this.constraints)return;this.stopAnimation();let r={x:0,y:0};R(t=>{let e=this.getAxisMotionValue(t);if(e&&!1!==this.constraints){let n=e.get();r[t]=function(t,e){let n=.5,r=V(t),i=V(e);return i>r?n=Y(e.min,e.max-r,t.min):r>i&&(n=Y(t.min,t.max-i,e.min)),B(0,1,n)}({min:n,max:n},this.constraints[t])}});let{transformTemplate:i}=this.visualElement.getProps();this.visualElement.current.style.transform=i?i({},""):"none",n.root&&n.root.updateScroll(),n.updateLayout(),this.constraints=!1,this.resolveConstraints(),R(e=>{if(!un(e,t,null))return;let n=this.getAxisMotionValue(e),{min:i,max:o}=this.constraints[e];n.set(Z(i,o,r[e]))}),this.visualElement.render()}addListeners(){if(!this.visualElement.current)return;sn.set(this.visualElement,this);let t,e=this.visualElement.current,n=$e(e,"pointerdown",t=>{let{drag:n,dragListener:r=!0}=this.getProps(),i=t.target,o=i!==e&&s(i);n&&r&&!o&&this.start(t)}),r=()=>{let{dragConstraints:n}=this.getProps();Re(n)&&n.current&&(this.constraints=this.resolveRefConstraints(),t||(t=function(t,e,n){let r=l(t,ln(n)),i=l(e,ln(n));return()=>{r(),i()}}(e,n.current,()=>this.scalePositionWithinConstraints())))},{projection:i}=this.visualElement,o=i.addEventListener("measure",r);i&&!i.layout&&(i.root&&i.root.updateScroll(),i.updateLayout()),q.read(r);let a=_(window,"resize",()=>this.scalePositionWithinConstraints()),u=i.addEventListener("didUpdate",({delta:t,hasLayoutChanged:e})=>{this.isDragging&&e&&(R(e=>{let n=this.getAxisMotionValue(e);n&&(this.originPoint[e]+=t[e].translate,n.set(n.get()+t[e].translate))}),this.visualElement.render())});return()=>{a(),n(),o(),u&&u(),t&&t()}}getProps(){let t=this.visualElement.getProps(),{drag:e=!1,dragDirectionLock:n=!1,dragPropagation:r=!1,dragConstraints:i=!1,dragElastic:o=nn,dragMomentum:s=!0}=t;return{...t,drag:e,dragDirectionLock:n,dragPropagation:r,dragConstraints:i,dragElastic:o,dragMomentum:s}}};function ln(t){let e=!0;return()=>{e?e=!1:t()}}function un(t,e,n){return!(!0!==e&&e!==t||null!==n&&n!==t)}var cn=t=>(e,n)=>{t&&q.update(()=>t(e,n),!1,!0)};import{jsx as dn}from"react/jsx-runtime";import{useContext as hn,Component as mn}from"react";var pn=!1,fn=class extends mn{componentDidMount(){let{visualElement:t,layoutGroup:e,switchLayoutGroup:n,layoutId:r}=this.props,{projection:i}=t;i&&(e.group&&e.group.add(i),n&&n.register&&r&&n.register(i),pn&&i.root.didUpdate(),i.addEventListener("animationComplete",()=>{this.safeToRemove()}),i.setOptions({...i.options,layoutDependency:this.props.layoutDependency,onExitComplete:()=>this.safeToRemove()})),O.hasEverUpdated=!0}getSnapshotBeforeUpdate(t){let{layoutDependency:e,visualElement:n,drag:r,isPresent:i}=this.props,{projection:o}=n;return o&&(o.isPresent=i,t.layoutDependency!==e&&o.setOptions({...o.options,layoutDependency:e}),pn=!0,r||t.layoutDependency!==e||void 0===e||t.isPresent!==i?o.willUpdate():this.safeToRemove(),t.isPresent!==i&&(i?o.promote():o.relegate()||q.postRender(()=>{let t=o.getStack();(!t||!t.members.length)&&this.safeToRemove()}))),null}componentDidUpdate(){let{visualElement:t,layoutAnchor:e}=this.props,{projection:r}=t;r&&(r.options.layoutAnchor=e,r.root.didUpdate(),n.postRender(()=>{!r.currentAnimation&&r.isLead()&&this.safeToRemove()}))}componentWillUnmount(){let{visualElement:t,layoutGroup:e,switchLayoutGroup:n}=this.props,{projection:r}=t;pn=!0,r&&(r.scheduleCheckAfterUnmount(),e&&e.group&&e.group.remove(r),n&&n.deregister&&n.deregister(r))}safeToRemove(){let{safeToRemove:t}=this.props;t&&t()}render(){return null}};function gn(t){let[e,n]=function(t=!0){let e=_t(jt);if(null===e)return[!0,null];let{isPresent:n,onExitComplete:r,register:i}=e,o=Nt();Ot(()=>{if(t)return i(o)},[t]);let s=Wt(()=>t&&r&&r(o),[o,r,t]);return!n&&r?[!1,s]:[!0]}(),r=hn(kt);return dn(fn,{...t,layoutGroup:r,switchLayoutGroup:hn(Ve),isPresent:e,safeToRemove:n})}var vn={pan:{Feature:class extends x{constructor(){super(...arguments),this.removePointerDownListener=$}onPointerDown(t){this.session=new Xe(t,this.createPanHandlers(),{transformPagePoint:this.node.getTransformPagePoint(),contextWindow:Ge(this.node)})}createPanHandlers(){let{onPanSessionStart:t,onPanStart:e,onPan:n,onPanEnd:r}=this.node.getProps();return{onSessionStart:cn(t),onStart:cn(e),onMove:cn(n),onEnd:(t,e)=>{delete this.session,r&&q.postRender(()=>r(t,e))}}}mount(){this.removePointerDownListener=$e(this.node.current,"pointerdown",t=>this.onPointerDown(t))}update(){this.session&&this.session.updateHandlers(this.createPanHandlers())}unmount(){this.removePointerDownListener(),this.session&&this.session.end()}}},drag:{Feature:class extends x{constructor(t){super(t),this.removeGroupControls=$,this.removeListeners=$,this.controls=new an(t)}mount(){let{dragControls:t}=this.node.getProps();t&&(this.removeGroupControls=t.subscribe(this.controls)),this.removeListeners=this.controls.addListeners()||$}update(){let{dragControls:t}=this.node.getProps(),{dragControls:e}=this.node.prevProps||{};t!==e&&(this.removeGroupControls(),t&&(this.removeGroupControls=t.subscribe(this.controls)))}unmount(){this.removeGroupControls(),this.removeListeners(),this.controls.isDragging||this.controls.endPanSession()}},ProjectionNode:W,MeasureLayout:gn}};function yn(t,e,n){let{props:r}=t;t.animationState&&r.whileHover&&t.animationState.setActive("whileHover","Start"===n);let i=r["onHover"+n];i&&q.postRender(()=>i(e,Ue(e)))}function xn(t,e,n){let{props:r}=t;if(t.current instanceof HTMLButtonElement&&t.current.disabled)return;t.animationState&&r.whileTap&&t.animationState.setActive("whileTap","Start"===n);let i=r["onTap"+("End"===n?"":n)];i&&q.postRender(()=>i(e,Ue(e)))}var wn=new WeakMap,En=new WeakMap,Pn=t=>{let e=wn.get(t.target);e&&e(t)},Sn=t=>{t.forEach(Pn)};function bn(t,e,n){let r=function({root:t,...e}){let n=t||document;En.has(n)||En.set(n,{});let r=En.get(n),i=JSON.stringify(e);return r[i]||(r[i]=new IntersectionObserver(Sn,{root:t,...e})),r[i]}(e);return wn.set(t,n),r.observe(t),()=>{wn.delete(t),r.unobserve(t)}}var Cn={some:0,all:1};var Mn={inView:{Feature:class extends x{constructor(){super(...arguments),this.hasEnteredView=!1,this.isInView=!1}startObserver(){this.stopObserver?.();let{viewport:t={}}=this.node.getProps(),{root:e,margin:n,amount:r="some",once:i}=t,o={root:e?e.current:void 0,rootMargin:n,threshold:"number"==typeof r?r:Cn[r]};this.stopObserver=bn(this.node.current,o,t=>{let{isIntersecting:e}=t;if(this.isInView===e||(this.isInView=e,i&&!e&&this.hasEnteredView))return;e&&(this.hasEnteredView=!0),this.node.animationState&&this.node.animationState.setActive("whileInView",e);let{onViewportEnter:n,onViewportLeave:r}=this.node.getProps(),o=e?n:r;o&&o(t)})}mount(){this.startObserver()}update(){if(typeof IntersectionObserver>"u")return;let{props:t,prevProps:e}=this.node;["amount","margin","root"].some(function({viewport:t={}},{viewport:e={}}={}){return n=>t[n]!==e[n]}(t,e))&&this.startObserver()}unmount(){this.stopObserver?.(),this.hasEnteredView=!1,this.isInView=!1}}},tap:{Feature:class extends x{mount(){let{current:t}=this.node;if(!t)return;let{globalTapTarget:e,propagate:n}=this.node.props;this.unmount=a(t,(t,e)=>(xn(this.node,e,"Start"),(t,{success:e})=>xn(this.node,t,e?"End":"Cancel")),{useGlobalTarget:e,stopPropagation:!1===n?.tap})}unmount(){}}},focus:{Feature:class extends x{constructor(){super(...arguments),this.isActive=!1}onFocus(){let t=!1;try{t=this.node.current.matches(":focus-visible")}catch{t=!0}!t||!this.node.animationState||(this.node.animationState.setActive("whileFocus",!0),this.isActive=!0)}onBlur(){!this.isActive||!this.node.animationState||(this.node.animationState.setActive("whileFocus",!1),this.isActive=!1)}mount(){this.unmount=G(_(this.node.current,"focus",()=>this.onFocus()),_(this.node.current,"blur",()=>this.onBlur()))}unmount(){}}},hover:{Feature:class extends x{mount(){let{current:t}=this.node;t&&(this.unmount=i(t,(t,e)=>(yn(this.node,e,"Start"),t=>yn(this.node,t,"End"))))}unmount(){}}}},kn=function(t,e){if(typeof Proxy>"u")return Oe;let n=new Map,r=(n,r)=>Oe(n,r,t,e);return new Proxy((t,e)=>r(t,e),{get:(i,o)=>"create"===o?r:(n.has(o)||n.set(o,Oe(o,void 0,t,e)),n.get(o))})}({...He,...Mn,...vn,...{layout:{ProjectionNode:W,MeasureLayout:gn}}},(t,e)=>e.isSVG??ve(t)?new D(e):new M(e,{allowProjection:t!==Be}));import{useState as Tn}from"react";var An=kn;import{Fragment as Ln,jsx as Dn,jsxs as In}from"react/jsx-runtime";function jn({items:t,defaultActiveId:e,activeId:n,edge:r="bottom",alignEnd:i=!1,onActiveChange:o,label:s="App navigation",moreLabel:a="More",backLabel:l="Back",className:u="",style:c}){let d=Pt(),[h,m]=Ct({kind:"collapsed"}),[v,y]=Ct(e??t[0]?.id),[x,w]=Ct(null),E=bt(null),P=bt(null),S=bt(r),b="left"===r||"right"===r;St(()=>{let t=P.current;if(!t||!x)return;let e=0,n=0,r=document.documentElement.clientWidth,i=window.innerHeight;for(let o=t.parentNode;o instanceof Element&&o!==document.body;o=o.parentNode instanceof ShadowRoot?o.parentNode.host:o.parentNode){let t=getComputedStyle(o),s=o.getBoundingClientRect();"visible"!==t.overflowX&&(e=Math.max(e,s.left),r=Math.min(r,s.right)),"visible"!==t.overflowY&&(n=Math.max(n,s.top),i=Math.min(i,s.bottom))}t.style.maxWidth=`${Math.max(0,r-e-16)}px`,t.style.left=`${x.x}px`,t.style.top=`${x.y}px`;let o=t.getBoundingClientRect(),s=Math.max(e+8-o.left,Math.min(0,r-8-o.right)),a=Math.max(n+8-o.top,Math.min(0,i-8-o.bottom));t.style.left=`${x.x+s}px`,t.style.top=`${x.y+a}px`},[x]);let C=bt(null),M=bt(null),k=bt(h),A=bt("more"),D=bt(!1),j=bt(!1),V=bt(!1),R=bt(null),_=bt(void 0),N=bt(void 0),O=bt(!1),W=bt(!1),B=function(){!f.current&&g();let[t]=Tn(p.current);return t}(),H=n??v,U="collapsed"!==h.kind,$=t.filter(t=>!1!==t.showInBar),G=$.find(t=>"dismiss"===t.id),Y=$.filter(t=>"dismiss"!==t.id),X=t.filter(t=>t.children?.length);function z(){clearTimeout(_.current),w(null)}function q(){z(),clearTimeout(N.current),O.current=!1}function K(t,e,n=!1){clearTimeout(_.current);let i=E.current,o=M.current;if(!i||!o||U||j.current||V.current&&!n)return;let s=i.getBoundingClientRect(),a=t.getBoundingClientRect(),l={label:e,x:"left"===r?s.width+8:"right"===r?-8:a.left-s.left+a.width/2,y:"top"===r?s.height+8:"bottom"===r?-8:a.top-s.top+a.height/2};clearTimeout(N.current);let u=()=>{O.current=!0,w(l)};n||O.current?u():_.current=setTimeout(u,400)}function J(t,e,n){q(),U||(A.current=e,D.current=n),R.current="first",m(t)}function Q(t=!0,e=A.current){q(),V.current=!0,R.current=t&&D.current?e:null,m({kind:"collapsed"})}function Z(){"group"===h.kind&&(R.current=h.id,m({kind:"main"}))}function tt(t,e){let n=!!t.children?.length,r=H===t.id||!!t.children?.some(t=>t.id===H),i=!e&&t.keepOpenOnSelect,s=(e,n=!1)=>Dn(Rn,{label:t.label,icon:n,reduced:!!B,children:e}),a=r&&t.activeIcon?t.activeIcon:t.icon,l=In(Ln,{children:[Dn("span",{className:"morphing-menu__icon","aria-hidden":"true",style:i?{display:"grid"}:void 0,children:i?s(a,!0):a}),!e&&Dn("span",{className:"morphing-menu__label",style:i?{display:"grid"}:void 0,children:i?s(t.label):t.label}),!e&&n&&Dn(Vn,{})]}),u={className:e?"morphing-menu__shortcut":"morphing-menu__row","data-menu-item":t.id,"aria-label":t.label,"aria-current":r?n?"true":"page":void 0,"aria-expanded":n?"group"===h.kind&&h.id===t.id:void 0,"aria-controls":n?`${d}-group-${t.id}`:void 0,onClick:e=>n?J({kind:"group",id:t.id},t.id,0===e.detail):function(t){y(t.id),o?.(t.id),U&&!t.keepOpenOnSelect?Q(!0,"group"===h.kind?h.id:t.id):q(),t.onSelect?.()}(t),onPointerEnter:n=>{e&&"mouse"===n.pointerType&&K(n.currentTarget,t.label)},onPointerLeave:z,onPointerDown:q,onFocus:n=>{e&&n.currentTarget.matches(":focus-visible")&&K(n.currentTarget,t.label,!0)},onBlur:z};return t.href&&!n?Dn("a",{href:t.href,...u,children:l},t.id):Dn(An.button,{layout:!!e&&"position",transition:B?{duration:0}:T,type:"button",...u,children:l},t.id)}St(()=>{let t=E.current,e=C.current,n=M.current;if(!t||!e||!n)return;let i=S.current!==r;S.current=r;let o=k.current;k.current=h;let s=[...t.querySelectorAll(".morphing-menu__panel")],a=s.find(t=>"false"===t.getAttribute("aria-hidden")),l=[],u=!1,c=t=>(l.push(t),t),d=()=>({width:a?.offsetWidth??n.offsetWidth,height:a?.offsetHeight??n.offsetHeight}),p=i||o.kind!==h.kind||"group"===o.kind&&"group"===h.kind&&o.id!==h.id,f="collapsed"===o.kind!=("collapsed"===h.kind),g=B||!p;if(g)(()=>{let t=d();e.style.width=`${t.width}px`,e.style.height=`${t.height}px`})();else if(f&&!U)c(F(e,d(),I));else if(f){let t=Math.min(n.offsetWidth,n.offsetWidth>250?280:200);c(F(e,{width:t,height:n.offsetHeight>52?32:28},L)).finished.then(()=>{u||c(F(e,d(),{...T,bounce:U?.24:.15}))}).catch(()=>{})}else c(F(e,d(),{...T,duration:.25,bounce:.1}));c(F(n,{opacity:U?0:1,scale:U&&!B?.8:1,filter:U&&!B?"blur(8px)":"blur(0px)"},{duration:g?0:U?.15:.22,delay:g||U?0:.08,...U?{}:{ease:"easeOut"}}));for(let t of s){let e=t===a;for(let[n,r]of[...t.querySelectorAll(".morphing-menu__row")].entries())e&&f&&!g&&Object.assign(r.style,{opacity:"0",transform:"translateY(48px)",filter:"blur(4px)"}),c(F(r,{opacity:e?1:0,y:e||B?0:16,filter:e||B?"blur(0px)":"blur(2px)"},{...T,duration:g?0:e?f?.4:.25:.12,bounce:f?.3:0,delay:!g&&e?(f?.2:0)+.02*n:0}))}let v=[...(U?a:n)?.querySelectorAll("[data-menu-item]")??[]],y=R.current;R.current=null,y&&(j.current=!0,(("first"===y?v[0]:v.find(t=>t.dataset.menuItem===y))??(U?void 0:v.find(t=>"more"===t.dataset.menuItem)))?.focus({preventScroll:!0}),j.current=!1);let x=()=>m(t=>({...t}));return window.addEventListener("resize",x),()=>{u=!0,l.forEach(t=>t.stop()),window.removeEventListener("resize",x)}},[h,B,r,t.length,$.length]),Et(()=>{if(!U)return;let t=new AbortController;return st(E.current,"pointerdown",t=>{t.target instanceof Node&&!t.composedPath().includes(E.current)&&Q(!1)},{signal:t.signal}),()=>t.abort()},[U]),Et(()=>()=>{clearTimeout(_.current),clearTimeout(N.current)},[]);let et=In("button",{type:"button",className:"morphing-menu__row","data-menu-item":"close",onClick:()=>Q(!0,"more"),children:[Dn(gt,{"aria-hidden":"true"}),Dn("span",{className:"morphing-menu__label",children:"Close drawer"})]});return In("nav",{ref:E,"aria-label":s,className:["morphing-menu",u].filter(Boolean).join(" "),"data-view":h.kind,"data-edge":r,"data-vertical":b,"data-align-end":i,style:{"--mm-count":$.length+1,...c},onPointerMove:t=>{if(!V.current||"mouse"!==t.pointerType||!t.movementX&&!t.movementY)return;V.current=!1;let e=t.target instanceof Element?t.target.closest(".morphing-menu__shortcut"):null;e&&K(e,e.getAttribute("aria-label")??"")},onKeyDown:t=>{"Escape"===t.key&&(V.current=!0,q(),U&&(t.preventDefault(),t.stopPropagation(),"group"===h.kind?Z():Q()))},onBlur:t=>{t.relatedTarget instanceof Node&&t.currentTarget.contains(t.relatedTarget)||(U?t.relatedTarget instanceof Node&&Q(!1):W.current||q())},children:[In("div",{ref:C,className:"morphing-menu__shell",children:[In("div",{ref:M,className:"morphing-menu__bar","aria-hidden":U,inert:U,onPointerEnter:t=>{"mouse"===t.pointerType&&(W.current=!0,clearTimeout(N.current))},onPointerLeave:t=>{"mouse"===t.pointerType&&(W.current=!1,z(),clearTimeout(N.current),N.current=setTimeout(()=>{O.current=!1},300))},children:[Y.map(t=>tt(t,!0)),Dn(An.button,{layout:"position",transition:B?{duration:0}:T,type:"button",className:"morphing-menu__shortcut","data-menu-item":"more","aria-label":a,"aria-expanded":U,"aria-controls":`${d}-main`,onClick:t=>J({kind:"main"},"more",0===t.detail),onPointerEnter:t=>{"mouse"===t.pointerType&&K(t.currentTarget,a)},onPointerLeave:z,onPointerDown:q,onBlur:z,onFocus:t=>{t.currentTarget.matches(":focus-visible")&&K(t.currentTarget,a,!0)},children:Dn(pt,{"aria-hidden":"true"})}),G&&tt(G,!0)]}),In("div",{id:`${d}-main`,className:"morphing-menu__panel","aria-hidden":"main"!==h.kind,inert:"main"!==h.kind,children:[[...t].sort((t,e)=>(t.expandedOrder??0)-(e.expandedOrder??0)).map(t=>tt(t,!1)),et]}),X.map(t=>{let e="group"===h.kind&&h.id===t.id;return In("div",{id:`${d}-group-${t.id}`,className:"morphing-menu__panel","aria-label":t.label,"aria-hidden":!e,inert:!e,children:[In("button",{type:"button",className:"morphing-menu__row","data-menu-item":"back",onClick:Z,children:[Dn(yt,{"aria-hidden":"true"}),Dn("span",{children:l})]}),t.children.map(t=>tt(t,!1)),et]},t.id)})]}),x&&!U&&Dn("div",{ref:P,className:"morphing-menu__tooltip","aria-hidden":"true",style:{left:x.x,top:x.y},children:x.label})]})}function Vn(){return Dn(wt,{className:"morphing-menu__chevron","aria-hidden":"true"})}function Rn({label:t,icon:e,reduced:n,children:r}){let i=bt(null),o=bt(null);return St(()=>{let r=i.current,s=o.current;if(o.current={label:t,node:r.cloneNode(!0)},!s||s.label===t||n)return;let a=s.node;a.setAttribute("aria-hidden","true"),r.parentElement.append(a);let l={duration:200,easing:"cubic-bezier(.22,1,.36,1)"},u=r.animate([{opacity:0,transform:e?"scale(.7)":"translateY(4px)",filter:"blur(2px)"},{opacity:1,transform:"none",filter:"blur(0px)"}],l),c=a.animate([{opacity:1,transform:"none",filter:"blur(0px)"},{opacity:0,transform:e?"scale(.7)":"translateY(-4px)",filter:"blur(2px)"}],l);return c.finished.then(()=>a.remove()).catch(()=>{}),()=>{u.cancel(),c.cancel(),a.remove()}},[t,e,n]),Dn("span",{ref:i,style:{gridArea:"1 / 1",display:"flex",alignItems:"center"},children:r})}function _n(t){if("glyph"in t)return ht("span",{style:{display:"contents"},dangerouslySetInnerHTML:{__html:ot[t.glyph]}});let{user:e}=t,n=e&&lt(e);return ht("span",{className:"review-avatar"},e?at(e.name):_n({glyph:"person"}),n&&ht("img",{key:n,src:n,alt:"",referrerPolicy:"no-referrer",decoding:"async",onError:t=>{t.currentTarget.hidden=!0}}))}var Nn=t=>ht(jn,{...t,items:t.items.map(t=>({...t,icon:_n(t.icon)}))});function On(t,e){t.replaceChildren();let n=ct(t);return dt(()=>n.render(Nn(e))),{render:t=>n.render(Nn(t)),unmount:()=>n.unmount()}}export{On as mountToolbar};
package/dist/types.d.ts CHANGED
@@ -147,6 +147,13 @@ export interface CommentsOptions {
147
147
  sourceUrl?: (source: string, branch: string) => string;
148
148
  /** Defaults to location.pathname; query strings are not stored. */
149
149
  page?: () => string;
150
+ /**
151
+ * Client-side router navigation for opening a comment on another page, e.g.
152
+ * (url) => router.navigate({ href: url.pathname + url.search }). komo opens
153
+ * the thread once its anchor renders. Defaults to a full page load; a
154
+ * rejection falls back to one.
155
+ */
156
+ navigate?: (url: URL) => void | Promise<void>;
150
157
  pollInterval?: number;
151
158
  /** Full emoji JSON URL; fetched only when choosing another emoji. */
152
159
  emojiDataSource?: string;
@@ -154,6 +161,12 @@ export interface CommentsOptions {
154
161
  sessionDomain?: string;
155
162
  /** Canonical API identity for trusted gateways to the same service. Defaults to endpoint. */
156
163
  sessionEndpoint?: string;
164
+ /**
165
+ * Photo URL for a signed-in reviewer the server has none for, e.g. IAP
166
+ * sign-in, which carries only an email (id "google:<sub>", name = the email's
167
+ * local part). HTTPS only; return undefined for the initial. Not used for guests.
168
+ */
169
+ avatar?: (user: Pick<Identity, "id" | "name">) => string | undefined;
157
170
  }
158
171
  export interface CommentsController {
159
172
  /** Open a new comment anchored to an element. */
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@hazem3500/komo",
3
- "version": "0.9.10",
3
+ "version": "0.9.12",
4
4
  "description": "Point, area, and threaded comments for website branches.",
5
5
  "type": "module",
6
6
  "license": "MIT",
package/server/index.ts CHANGED
@@ -472,10 +472,24 @@ async function oauthCallback(
472
472
  "Invalid identity."
473
473
  );
474
474
  const id = `${provider}:${provider === "google" ? profile.sub : profile.id}`;
475
- const avatarUrl = profile.picture || profile.avatar_url || "";
476
- const safeAvatar = /^https:\/\//.test(avatarUrl) ? avatarUrl : "";
475
+ // The provider photo (Google's OIDC `picture`) becomes the avatar: plain
476
+ // HTTPS only, otherwise the initial. Existing users without one (NULL) get it
477
+ // on their next sign-in; a photo they set or cleared in komo is kept.
478
+ let safeAvatar: string | null = null;
479
+ try {
480
+ const photo = new URL(profile.picture || profile.avatar_url || "");
481
+ if (
482
+ photo.protocol === "https:" &&
483
+ !photo.username &&
484
+ !photo.password &&
485
+ photo.href.length <= 2048
486
+ )
487
+ safeAvatar = photo.href;
488
+ } catch {
489
+ /* Missing or malformed: keep the initial. */
490
+ }
477
491
  await env.DB.prepare(
478
- "INSERT INTO users(id,name,verified,avatar_url) VALUES(?,?,1,?) ON CONFLICT(id) DO NOTHING"
492
+ "INSERT INTO users(id,name,verified,avatar_url) VALUES(?,?,1,?) ON CONFLICT(id) DO UPDATE SET avatar_url=excluded.avatar_url WHERE users.avatar_url IS NULL AND excluded.avatar_url IS NOT NULL"
479
493
  )
480
494
  .bind(id, (profile.name || profile.login).slice(0, 60), safeAvatar)
481
495
  .run();