backpack-viewer 0.7.15 → 0.7.16
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,4 +1,4 @@
|
|
|
1
|
-
var Jn=Object.defineProperty;var Kn=(t,e,s)=>e in t?Jn(t,e,{enumerable:!0,configurable:!0,writable:!0,value:s}):t[e]=s;var At=(t,e,s)=>Kn(t,typeof e!="symbol"?e+"":e,s);(function(){const e=document.createElement("link").relList;if(e&&e.supports&&e.supports("modulepreload"))return;for(const m of document.querySelectorAll('link[rel="modulepreload"]'))l(m);new MutationObserver(m=>{for(const r of m)if(r.type==="childList")for(const d of r.addedNodes)d.tagName==="LINK"&&d.rel==="modulepreload"&&l(d)}).observe(document,{childList:!0,subtree:!0});function s(m){const r={};return m.integrity&&(r.integrity=m.integrity),m.referrerPolicy&&(r.referrerPolicy=m.referrerPolicy),m.crossOrigin==="use-credentials"?r.credentials="include":m.crossOrigin==="anonymous"?r.credentials="omit":r.credentials="same-origin",r}function l(m){if(m.ep)return;m.ep=!0;const r=s(m);fetch(m.href,r)}})();const Zn="modulepreload",Qn=function(t){return"/"+t},hn={},eo=function(e,s,l){let m=Promise.resolve();if(s&&s.length>0){let d=function(g){return Promise.all(g.map(i=>Promise.resolve(i).then(c=>({status:"fulfilled",value:c}),c=>({status:"rejected",reason:c}))))};document.getElementsByTagName("link");const o=document.querySelector("meta[property=csp-nonce]"),n=(o==null?void 0:o.nonce)||(o==null?void 0:o.getAttribute("nonce"));m=d(s.map(g=>{if(g=Qn(g),g in hn)return;hn[g]=!0;const i=g.endsWith(".css"),c=i?'[rel="stylesheet"]':"";if(document.querySelector(`link[href="${g}"]${c}`))return;const I=document.createElement("link");if(I.rel=i?"stylesheet":Zn,i||(I.as="script"),I.crossOrigin="",I.href=g,n&&I.setAttribute("nonce",n),document.head.appendChild(I),i)return new Promise((M,x)=>{I.addEventListener("load",M),I.addEventListener("error",()=>x(new Error(`Unable to preload CSS for ${g}`)))})}))}function r(d){const o=new Event("vite:preloadError",{cancelable:!0});if(o.payload=d,window.dispatchEvent(o),!o.defaultPrevented)throw d}return m.then(d=>{for(const o of d||[])o.status==="rejected"&&r(o.reason);return e().catch(r)})};async function vt(){const t=await fetch("/api/ontologies");return t.ok?t.json():[]}async function Pt(t){const e=await fetch(`/api/ontologies/${encodeURIComponent(t)}`);if(!e.ok)throw new Error(`Failed to load ontology: ${t}`);return e.json()}async function to(){const t=await fetch("/api/remotes");return t.ok?t.json():[]}async function no(t){const e=await fetch(`/api/remotes/${encodeURIComponent(t)}`);if(!e.ok)throw new Error(`Failed to load remote graph: ${t}`);return e.json()}async function zt(t,e){if(!(await fetch(`/api/ontologies/${encodeURIComponent(t)}`,{method:"PUT",headers:{"Content-Type":"application/json"},body:JSON.stringify(e)})).ok)throw new Error(`Failed to save ontology: ${t}`)}async function oo(t,e){if(!(await fetch(`/api/ontologies/${encodeURIComponent(t)}/rename`,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({name:e})})).ok)throw new Error(`Failed to rename ontology: ${t}`)}async function so(t){const e=await fetch(`/api/graphs/${encodeURIComponent(t)}/branches`);return e.ok?e.json():[]}async function fn(t,e,s){const l=await fetch(`/api/graphs/${encodeURIComponent(t)}/branches`,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({name:e,from:s})});if(!l.ok){const m=await l.json().catch(()=>({}));throw new Error(m.error||"Failed to create branch")}}async function gn(t,e){const s=await fetch(`/api/graphs/${encodeURIComponent(t)}/branches/switch`,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({name:e})});if(!s.ok){const l=await s.json().catch(()=>({}));throw new Error(l.error||"Failed to switch branch")}}async function ao(t,e){const s=await fetch(`/api/graphs/${encodeURIComponent(t)}/branches/${encodeURIComponent(e)}`,{method:"DELETE"});if(!s.ok){const l=await s.json().catch(()=>({}));throw new Error(l.error||"Failed to delete branch")}}async function co(t){const e=await fetch(`/api/graphs/${encodeURIComponent(t)}/snapshots`);return e.ok?e.json():[]}async function io(t,e){const s=await fetch(`/api/graphs/${encodeURIComponent(t)}/snapshots`,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({label:e})});if(!s.ok){const l=await s.json().catch(()=>({}));throw new Error(l.error||"Failed to create snapshot")}}async function lo(t,e){const s=await fetch(`/api/graphs/${encodeURIComponent(t)}/rollback`,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({version:e})});if(!s.ok){const l=await s.json().catch(()=>({}));throw new Error(l.error||"Failed to rollback")}}async function ro(t){const e=await fetch(`/api/graphs/${encodeURIComponent(t)}/snippets`);return e.ok?e.json():[]}async function yn(t,e,s,l,m){const r=await fetch(`/api/graphs/${encodeURIComponent(t)}/snippets`,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({label:e,description:m,nodeIds:s,edgeIds:l})});if(!r.ok)throw new Error("Failed to save snippet");return(await r.json()).id}async function po(t,e){const s=await fetch(`/api/graphs/${encodeURIComponent(t)}/snippets/${encodeURIComponent(e)}`);if(!s.ok)throw new Error("Snippet not found");return s.json()}async function uo(t,e){if(!(await fetch(`/api/graphs/${encodeURIComponent(t)}/snippets/${encodeURIComponent(e)}`,{method:"DELETE"})).ok)throw new Error("Failed to delete snippet")}const Cn="bp-dialog-overlay";function nn(){var e;(e=document.querySelector(`.${Cn}`))==null||e.remove();const t=document.createElement("div");return t.className=Cn,document.body.appendChild(t),t}function on(t,e){const s=document.createElement("div");s.className="bp-dialog";const l=document.createElement("h4");return l.className="bp-dialog-title",l.textContent=e,s.appendChild(l),t.appendChild(s),t.addEventListener("click",m=>{m.target===t&&t.remove()}),s}function sn(t,e){const s=document.createElement("div");s.className="bp-dialog-buttons";for(const l of e){const m=document.createElement("button");m.className="bp-dialog-btn",l.accent&&m.classList.add("bp-dialog-btn-accent"),l.danger&&m.classList.add("bp-dialog-btn-danger"),m.textContent=l.label,m.addEventListener("click",l.onClick),s.appendChild(m)}t.appendChild(s)}function jn(t,e){return new Promise(s=>{var d;const l=nn(),m=on(l,t),r=document.createElement("p");r.className="bp-dialog-message",r.textContent=e,m.appendChild(r),sn(m,[{label:"Cancel",onClick:()=>{l.remove(),s(!1)}},{label:"Confirm",accent:!0,onClick:()=>{l.remove(),s(!0)}}]),(d=m.querySelector(".bp-dialog-btn-accent"))==null||d.focus()})}function Dt(t,e,s){return new Promise(l=>{const m=nn(),r=on(m,t),d=document.createElement("input");d.type="text",d.className="bp-dialog-input",d.placeholder=e??"",d.value="",r.appendChild(d);const o=()=>{const n=d.value.trim();m.remove(),l(n||null)};d.addEventListener("keydown",n=>{n.key==="Enter"&&o(),n.key==="Escape"&&(m.remove(),l(null))}),sn(r,[{label:"Cancel",onClick:()=>{m.remove(),l(null)}},{label:"OK",accent:!0,onClick:o}]),d.focus(),d.select()})}function mo(){return new Promise(t=>{const e=nn(),s=on(e,"Add Backpack"),l=document.createElement("p");l.className="bp-dialog-message",l.textContent="Enter the absolute path to a directory that should become a backpack. It will be shown in the sidebar using the last segment of the path as its display name.",s.appendChild(l);const m=document.createElement("label");m.className="bp-dialog-label",m.textContent="Path",s.appendChild(m);const r=document.createElement("div");r.className="bp-dialog-path-row",s.appendChild(r);const d=document.createElement("input");d.type="text",d.className="bp-dialog-input bp-dialog-path-input",d.placeholder="/Users/you/OneDrive/work",r.appendChild(d);const o=document.createElement("button");o.type="button",o.className="bp-dialog-btn bp-dialog-browse-btn",o.textContent="Browse...",r.appendChild(o),typeof window.showDirectoryPicker=="function"||(o.disabled=!0,o.title="Browser doesn't support native folder picker — paste the path manually"),o.addEventListener("click",async x=>{x.preventDefault();try{const F=await window.showDirectoryPicker({mode:"read"});g.textContent=`Picked "${F.name}" — paste the absolute path to it below.`,d.focus()}catch{}});const g=document.createElement("div");g.className="bp-dialog-picker-hint",s.appendChild(g);const i=document.createElement("div");i.className="bp-dialog-activate-row";const c=document.createElement("input");c.type="checkbox",c.id="bp-dialog-activate",c.checked=!0;const I=document.createElement("label");I.htmlFor="bp-dialog-activate",I.textContent="Switch to this backpack after registering",i.appendChild(c),i.appendChild(I),s.appendChild(i),d.addEventListener("dragover",x=>{x.preventDefault(),d.classList.add("bp-dialog-drag-over")}),d.addEventListener("dragleave",()=>{d.classList.remove("bp-dialog-drag-over")}),d.addEventListener("drop",x=>{var V,_,X;x.preventDefault(),d.classList.remove("bp-dialog-drag-over");const F=(V=x.dataTransfer)==null?void 0:V.items;if(!F||F.length===0)return;const W=(X=(_=F[0]).webkitGetAsEntry)==null?void 0:X.call(_);W!=null&&W.isDirectory&&(g.textContent=`Dropped "${W.name}" — paste the absolute path to it below.`)});const M=()=>{const x=d.value.trim();x&&(e.remove(),t({path:x,activate:c.checked}))};d.addEventListener("keydown",x=>{x.key==="Enter"&&M(),x.key==="Escape"&&(e.remove(),t(null))}),sn(s,[{label:"Cancel",onClick:()=>{e.remove(),t(null)}},{label:"Register",accent:!0,onClick:M}]),d.focus()})}function kt(t,e=3e3){const s=document.querySelector(".bp-toast");s&&s.remove();const l=document.createElement("div");l.className="bp-toast",l.textContent=t,document.body.appendChild(l),setTimeout(()=>l.classList.add("bp-toast-visible"),10),setTimeout(()=>{l.classList.remove("bp-toast-visible"),setTimeout(()=>l.remove(),300)},e)}const bn="http://www.w3.org/2000/svg";function at(t,e){const s=document.createElementNS(bn,"svg"),l=t.size??16;s.setAttribute("width",String(l)),s.setAttribute("height",String(l)),s.setAttribute("viewBox",t.viewBox??"0 0 24 24"),s.setAttribute("fill","none"),s.setAttribute("stroke","currentColor"),s.setAttribute("stroke-width",String(t.strokeWidth??2)),t.strokeLinecap&&s.setAttribute("stroke-linecap",t.strokeLinecap),t.strokeLinejoin&&s.setAttribute("stroke-linejoin",t.strokeLinejoin),t.className&&s.setAttribute("class",t.className);for(const m of e){const r=document.createElementNS(bn,m.tag);for(const[d,o]of Object.entries(m.attrs))r.setAttribute(d,String(o));s.appendChild(r)}return s}function ho(t){return Array.from(t.childNodes).map(e=>e.cloneNode(!0))}function fo(t,e){t.replaceChildren(...e)}function vn(t){return t>=1e3?`${(t/1e3).toFixed(1)}k tokens`:`${t} tokens`}function xn(t,e){return t*50+e*25+50}function go(t,e){const s=typeof e=="function"?{onSelect:e}:e,l=document.createElement("h2");l.textContent="Backpack Viewer";const m=document.createElement("input");m.type="text",m.placeholder="Filter...",m.id="filter";const r=document.createElement("ul");r.id="ontology-list";const d=document.createElement("h3");d.className="sidebar-section-heading",d.textContent="REMOTE GRAPHS",d.hidden=!0;const o=document.createElement("ul");o.id="remote-list",o.className="remote-list",o.hidden=!0;const n=document.createElement("div");n.className="sidebar-footer";const g=document.createElement("a");g.href="mailto:support@backpackontology.com",g.textContent="support@backpackontology.com";const i=document.createElement("span");i.textContent="Feedback & support";const c=document.createElement("span");c.className="sidebar-version",c.textContent="v0.7.15",n.append(g,i,c);const I=document.createElement("button");I.className="sidebar-collapse-btn",I.title="Toggle sidebar (Tab)",I.appendChild(at({size:14},[{tag:"polyline",attrs:{points:"11 17 6 12 11 7"}},{tag:"polyline",attrs:{points:"18 17 13 12 18 7"}}]));let M=!1;function x(){M=!M,t.classList.toggle("sidebar-collapsed",M),ye.classList.toggle("hidden",!M)}I.addEventListener("click",x);const F=document.createElement("div");F.className="sidebar-heading-row",F.appendChild(l),F.appendChild(I),t.appendChild(F);const W=document.createElement("div");W.className="sidebar-stale-banner",W.hidden=!0,t.appendChild(W);const V=document.createElement("button");V.className="backpack-picker-pill",V.type="button",V.setAttribute("aria-haspopup","listbox"),V.setAttribute("aria-expanded","false");const _=document.createElement("span");_.className="backpack-picker-dot";const X=document.createElement("span");X.className="backpack-picker-name",X.textContent="...";const Y=document.createElement("span");Y.className="backpack-picker-caret",Y.textContent="▾",V.appendChild(_),V.appendChild(X),V.appendChild(Y);const Z=document.createElement("div");Z.className="backpack-picker-dropdown",Z.hidden=!0,Z.setAttribute("role","listbox");const q=document.createElement("div");q.className="backpack-picker-container",q.appendChild(V),q.appendChild(Z),t.appendChild(q);let me=!1;function U(){me=!1,Z.hidden=!0,V.setAttribute("aria-expanded","false")}function pe(){me=!0,Z.hidden=!1,V.setAttribute("aria-expanded","true")}V.addEventListener("click",p=>{p.stopPropagation(),me?U():pe()}),document.addEventListener("click",p=>{q.contains(p.target)||U()});let Ee=[],te=null;function G(){Z.replaceChildren();for(const E of Ee){const u=document.createElement("button");u.className="backpack-picker-item",u.type="button",u.setAttribute("role","option"),E.active&&u.classList.add("active");const b=document.createElement("span");b.className="backpack-picker-item-dot",b.style.setProperty("--backpack-color",E.color);const S=document.createElement("span");S.className="backpack-picker-item-name",S.textContent=E.name;const h=document.createElement("span");h.className="backpack-picker-item-path",h.textContent=E.path,u.appendChild(b),u.appendChild(S),u.appendChild(h),u.addEventListener("click",T=>{T.stopPropagation(),U(),!E.active&&s.onBackpackSwitch&&s.onBackpackSwitch(E.name)}),Z.appendChild(u)}const p=document.createElement("div");p.className="backpack-picker-divider",Z.appendChild(p);const C=document.createElement("button");C.className="backpack-picker-item backpack-picker-add",C.type="button",C.textContent="+ Add new backpack…",C.addEventListener("click",async E=>{if(E.stopPropagation(),U(),!s.onBackpackRegister)return;const u=await mo();u&&s.onBackpackRegister(u.path,u.activate)}),Z.appendChild(C)}const ye=document.createElement("button");ye.className="tools-pane-toggle hidden",ye.title="Show sidebar (Tab)",ye.appendChild(at({size:14},[{tag:"polyline",attrs:{points:"13 7 18 12 13 17"}},{tag:"polyline",attrs:{points:"6 7 11 12 6 17"}}])),ye.addEventListener("click",x),t.appendChild(m),t.appendChild(r),t.appendChild(d),t.appendChild(o),t.appendChild(n);let Ce=[],se=[],ge="";return m.addEventListener("input",()=>{const p=m.value.toLowerCase();for(const C of Ce){const E=C.dataset.name??"";C.style.display=E.includes(p)?"":"none"}for(const C of se){const E=C.dataset.name??"";C.style.display=E.includes(p)?"":"none"}}),{setStaleVersionBanner(p,C){W.replaceChildren();const E=document.createElement("div");E.className="sidebar-stale-banner-title",E.textContent=`Viewer ${p} is out of date`;const u=document.createElement("div");u.className="sidebar-stale-banner-subtitle",u.textContent=`Latest is ${C}. Your version is stuck because of an npx cache.`;const b=document.createElement("pre");b.className="sidebar-stale-banner-hint",b.textContent=`npm cache clean --force
|
|
1
|
+
var Jn=Object.defineProperty;var Kn=(t,e,s)=>e in t?Jn(t,e,{enumerable:!0,configurable:!0,writable:!0,value:s}):t[e]=s;var At=(t,e,s)=>Kn(t,typeof e!="symbol"?e+"":e,s);(function(){const e=document.createElement("link").relList;if(e&&e.supports&&e.supports("modulepreload"))return;for(const m of document.querySelectorAll('link[rel="modulepreload"]'))l(m);new MutationObserver(m=>{for(const r of m)if(r.type==="childList")for(const d of r.addedNodes)d.tagName==="LINK"&&d.rel==="modulepreload"&&l(d)}).observe(document,{childList:!0,subtree:!0});function s(m){const r={};return m.integrity&&(r.integrity=m.integrity),m.referrerPolicy&&(r.referrerPolicy=m.referrerPolicy),m.crossOrigin==="use-credentials"?r.credentials="include":m.crossOrigin==="anonymous"?r.credentials="omit":r.credentials="same-origin",r}function l(m){if(m.ep)return;m.ep=!0;const r=s(m);fetch(m.href,r)}})();const Zn="modulepreload",Qn=function(t){return"/"+t},hn={},eo=function(e,s,l){let m=Promise.resolve();if(s&&s.length>0){let d=function(g){return Promise.all(g.map(i=>Promise.resolve(i).then(c=>({status:"fulfilled",value:c}),c=>({status:"rejected",reason:c}))))};document.getElementsByTagName("link");const o=document.querySelector("meta[property=csp-nonce]"),n=(o==null?void 0:o.nonce)||(o==null?void 0:o.getAttribute("nonce"));m=d(s.map(g=>{if(g=Qn(g),g in hn)return;hn[g]=!0;const i=g.endsWith(".css"),c=i?'[rel="stylesheet"]':"";if(document.querySelector(`link[href="${g}"]${c}`))return;const I=document.createElement("link");if(I.rel=i?"stylesheet":Zn,i||(I.as="script"),I.crossOrigin="",I.href=g,n&&I.setAttribute("nonce",n),document.head.appendChild(I),i)return new Promise((M,x)=>{I.addEventListener("load",M),I.addEventListener("error",()=>x(new Error(`Unable to preload CSS for ${g}`)))})}))}function r(d){const o=new Event("vite:preloadError",{cancelable:!0});if(o.payload=d,window.dispatchEvent(o),!o.defaultPrevented)throw d}return m.then(d=>{for(const o of d||[])o.status==="rejected"&&r(o.reason);return e().catch(r)})};async function vt(){const t=await fetch("/api/ontologies");return t.ok?t.json():[]}async function Pt(t){const e=await fetch(`/api/ontologies/${encodeURIComponent(t)}`);if(!e.ok)throw new Error(`Failed to load ontology: ${t}`);return e.json()}async function to(){const t=await fetch("/api/remotes");return t.ok?t.json():[]}async function no(t){const e=await fetch(`/api/remotes/${encodeURIComponent(t)}`);if(!e.ok)throw new Error(`Failed to load remote graph: ${t}`);return e.json()}async function zt(t,e){if(!(await fetch(`/api/ontologies/${encodeURIComponent(t)}`,{method:"PUT",headers:{"Content-Type":"application/json"},body:JSON.stringify(e)})).ok)throw new Error(`Failed to save ontology: ${t}`)}async function oo(t,e){if(!(await fetch(`/api/ontologies/${encodeURIComponent(t)}/rename`,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({name:e})})).ok)throw new Error(`Failed to rename ontology: ${t}`)}async function so(t){const e=await fetch(`/api/graphs/${encodeURIComponent(t)}/branches`);return e.ok?e.json():[]}async function fn(t,e,s){const l=await fetch(`/api/graphs/${encodeURIComponent(t)}/branches`,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({name:e,from:s})});if(!l.ok){const m=await l.json().catch(()=>({}));throw new Error(m.error||"Failed to create branch")}}async function gn(t,e){const s=await fetch(`/api/graphs/${encodeURIComponent(t)}/branches/switch`,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({name:e})});if(!s.ok){const l=await s.json().catch(()=>({}));throw new Error(l.error||"Failed to switch branch")}}async function ao(t,e){const s=await fetch(`/api/graphs/${encodeURIComponent(t)}/branches/${encodeURIComponent(e)}`,{method:"DELETE"});if(!s.ok){const l=await s.json().catch(()=>({}));throw new Error(l.error||"Failed to delete branch")}}async function co(t){const e=await fetch(`/api/graphs/${encodeURIComponent(t)}/snapshots`);return e.ok?e.json():[]}async function io(t,e){const s=await fetch(`/api/graphs/${encodeURIComponent(t)}/snapshots`,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({label:e})});if(!s.ok){const l=await s.json().catch(()=>({}));throw new Error(l.error||"Failed to create snapshot")}}async function lo(t,e){const s=await fetch(`/api/graphs/${encodeURIComponent(t)}/rollback`,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({version:e})});if(!s.ok){const l=await s.json().catch(()=>({}));throw new Error(l.error||"Failed to rollback")}}async function ro(t){const e=await fetch(`/api/graphs/${encodeURIComponent(t)}/snippets`);return e.ok?e.json():[]}async function yn(t,e,s,l,m){const r=await fetch(`/api/graphs/${encodeURIComponent(t)}/snippets`,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({label:e,description:m,nodeIds:s,edgeIds:l})});if(!r.ok)throw new Error("Failed to save snippet");return(await r.json()).id}async function po(t,e){const s=await fetch(`/api/graphs/${encodeURIComponent(t)}/snippets/${encodeURIComponent(e)}`);if(!s.ok)throw new Error("Snippet not found");return s.json()}async function uo(t,e){if(!(await fetch(`/api/graphs/${encodeURIComponent(t)}/snippets/${encodeURIComponent(e)}`,{method:"DELETE"})).ok)throw new Error("Failed to delete snippet")}const Cn="bp-dialog-overlay";function nn(){var e;(e=document.querySelector(`.${Cn}`))==null||e.remove();const t=document.createElement("div");return t.className=Cn,document.body.appendChild(t),t}function on(t,e){const s=document.createElement("div");s.className="bp-dialog";const l=document.createElement("h4");return l.className="bp-dialog-title",l.textContent=e,s.appendChild(l),t.appendChild(s),t.addEventListener("click",m=>{m.target===t&&t.remove()}),s}function sn(t,e){const s=document.createElement("div");s.className="bp-dialog-buttons";for(const l of e){const m=document.createElement("button");m.className="bp-dialog-btn",l.accent&&m.classList.add("bp-dialog-btn-accent"),l.danger&&m.classList.add("bp-dialog-btn-danger"),m.textContent=l.label,m.addEventListener("click",l.onClick),s.appendChild(m)}t.appendChild(s)}function jn(t,e){return new Promise(s=>{var d;const l=nn(),m=on(l,t),r=document.createElement("p");r.className="bp-dialog-message",r.textContent=e,m.appendChild(r),sn(m,[{label:"Cancel",onClick:()=>{l.remove(),s(!1)}},{label:"Confirm",accent:!0,onClick:()=>{l.remove(),s(!0)}}]),(d=m.querySelector(".bp-dialog-btn-accent"))==null||d.focus()})}function Dt(t,e,s){return new Promise(l=>{const m=nn(),r=on(m,t),d=document.createElement("input");d.type="text",d.className="bp-dialog-input",d.placeholder=e??"",d.value="",r.appendChild(d);const o=()=>{const n=d.value.trim();m.remove(),l(n||null)};d.addEventListener("keydown",n=>{n.key==="Enter"&&o(),n.key==="Escape"&&(m.remove(),l(null))}),sn(r,[{label:"Cancel",onClick:()=>{m.remove(),l(null)}},{label:"OK",accent:!0,onClick:o}]),d.focus(),d.select()})}function mo(){return new Promise(t=>{const e=nn(),s=on(e,"Add Backpack"),l=document.createElement("p");l.className="bp-dialog-message",l.textContent="Enter the absolute path to a directory that should become a backpack. It will be shown in the sidebar using the last segment of the path as its display name.",s.appendChild(l);const m=document.createElement("label");m.className="bp-dialog-label",m.textContent="Path",s.appendChild(m);const r=document.createElement("div");r.className="bp-dialog-path-row",s.appendChild(r);const d=document.createElement("input");d.type="text",d.className="bp-dialog-input bp-dialog-path-input",d.placeholder="/Users/you/OneDrive/work",r.appendChild(d);const o=document.createElement("button");o.type="button",o.className="bp-dialog-btn bp-dialog-browse-btn",o.textContent="Browse...",r.appendChild(o),typeof window.showDirectoryPicker=="function"||(o.disabled=!0,o.title="Browser doesn't support native folder picker — paste the path manually"),o.addEventListener("click",async x=>{x.preventDefault();try{const F=await window.showDirectoryPicker({mode:"read"});g.textContent=`Picked "${F.name}" — paste the absolute path to it below.`,d.focus()}catch{}});const g=document.createElement("div");g.className="bp-dialog-picker-hint",s.appendChild(g);const i=document.createElement("div");i.className="bp-dialog-activate-row";const c=document.createElement("input");c.type="checkbox",c.id="bp-dialog-activate",c.checked=!0;const I=document.createElement("label");I.htmlFor="bp-dialog-activate",I.textContent="Switch to this backpack after registering",i.appendChild(c),i.appendChild(I),s.appendChild(i),d.addEventListener("dragover",x=>{x.preventDefault(),d.classList.add("bp-dialog-drag-over")}),d.addEventListener("dragleave",()=>{d.classList.remove("bp-dialog-drag-over")}),d.addEventListener("drop",x=>{var V,_,X;x.preventDefault(),d.classList.remove("bp-dialog-drag-over");const F=(V=x.dataTransfer)==null?void 0:V.items;if(!F||F.length===0)return;const W=(X=(_=F[0]).webkitGetAsEntry)==null?void 0:X.call(_);W!=null&&W.isDirectory&&(g.textContent=`Dropped "${W.name}" — paste the absolute path to it below.`)});const M=()=>{const x=d.value.trim();x&&(e.remove(),t({path:x,activate:c.checked}))};d.addEventListener("keydown",x=>{x.key==="Enter"&&M(),x.key==="Escape"&&(e.remove(),t(null))}),sn(s,[{label:"Cancel",onClick:()=>{e.remove(),t(null)}},{label:"Register",accent:!0,onClick:M}]),d.focus()})}function kt(t,e=3e3){const s=document.querySelector(".bp-toast");s&&s.remove();const l=document.createElement("div");l.className="bp-toast",l.textContent=t,document.body.appendChild(l),setTimeout(()=>l.classList.add("bp-toast-visible"),10),setTimeout(()=>{l.classList.remove("bp-toast-visible"),setTimeout(()=>l.remove(),300)},e)}const bn="http://www.w3.org/2000/svg";function at(t,e){const s=document.createElementNS(bn,"svg"),l=t.size??16;s.setAttribute("width",String(l)),s.setAttribute("height",String(l)),s.setAttribute("viewBox",t.viewBox??"0 0 24 24"),s.setAttribute("fill","none"),s.setAttribute("stroke","currentColor"),s.setAttribute("stroke-width",String(t.strokeWidth??2)),t.strokeLinecap&&s.setAttribute("stroke-linecap",t.strokeLinecap),t.strokeLinejoin&&s.setAttribute("stroke-linejoin",t.strokeLinejoin),t.className&&s.setAttribute("class",t.className);for(const m of e){const r=document.createElementNS(bn,m.tag);for(const[d,o]of Object.entries(m.attrs))r.setAttribute(d,String(o));s.appendChild(r)}return s}function ho(t){return Array.from(t.childNodes).map(e=>e.cloneNode(!0))}function fo(t,e){t.replaceChildren(...e)}function vn(t){return t>=1e3?`${(t/1e3).toFixed(1)}k tokens`:`${t} tokens`}function xn(t,e){return t*50+e*25+50}function go(t,e){const s=typeof e=="function"?{onSelect:e}:e,l=document.createElement("h2");l.textContent="Backpack Viewer";const m=document.createElement("input");m.type="text",m.placeholder="Filter...",m.id="filter";const r=document.createElement("ul");r.id="ontology-list";const d=document.createElement("h3");d.className="sidebar-section-heading",d.textContent="REMOTE GRAPHS",d.hidden=!0;const o=document.createElement("ul");o.id="remote-list",o.className="remote-list",o.hidden=!0;const n=document.createElement("div");n.className="sidebar-footer";const g=document.createElement("a");g.href="mailto:support@backpackontology.com",g.textContent="support@backpackontology.com";const i=document.createElement("span");i.textContent="Feedback & support";const c=document.createElement("span");c.className="sidebar-version",c.textContent="v0.7.16",n.append(g,i,c);const I=document.createElement("button");I.className="sidebar-collapse-btn",I.title="Toggle sidebar (Tab)",I.appendChild(at({size:14},[{tag:"polyline",attrs:{points:"11 17 6 12 11 7"}},{tag:"polyline",attrs:{points:"18 17 13 12 18 7"}}]));let M=!1;function x(){M=!M,t.classList.toggle("sidebar-collapsed",M),ye.classList.toggle("hidden",!M)}I.addEventListener("click",x);const F=document.createElement("div");F.className="sidebar-heading-row",F.appendChild(l),F.appendChild(I),t.appendChild(F);const W=document.createElement("div");W.className="sidebar-stale-banner",W.hidden=!0,t.appendChild(W);const V=document.createElement("button");V.className="backpack-picker-pill",V.type="button",V.setAttribute("aria-haspopup","listbox"),V.setAttribute("aria-expanded","false");const _=document.createElement("span");_.className="backpack-picker-dot";const X=document.createElement("span");X.className="backpack-picker-name",X.textContent="...";const Y=document.createElement("span");Y.className="backpack-picker-caret",Y.textContent="▾",V.appendChild(_),V.appendChild(X),V.appendChild(Y);const Z=document.createElement("div");Z.className="backpack-picker-dropdown",Z.hidden=!0,Z.setAttribute("role","listbox");const q=document.createElement("div");q.className="backpack-picker-container",q.appendChild(V),q.appendChild(Z),t.appendChild(q);let me=!1;function U(){me=!1,Z.hidden=!0,V.setAttribute("aria-expanded","false")}function pe(){me=!0,Z.hidden=!1,V.setAttribute("aria-expanded","true")}V.addEventListener("click",p=>{p.stopPropagation(),me?U():pe()}),document.addEventListener("click",p=>{q.contains(p.target)||U()});let Ee=[],te=null;function G(){Z.replaceChildren();for(const E of Ee){const u=document.createElement("button");u.className="backpack-picker-item",u.type="button",u.setAttribute("role","option"),E.active&&u.classList.add("active");const b=document.createElement("span");b.className="backpack-picker-item-dot",b.style.setProperty("--backpack-color",E.color);const S=document.createElement("span");S.className="backpack-picker-item-name",S.textContent=E.name;const h=document.createElement("span");h.className="backpack-picker-item-path",h.textContent=E.path,u.appendChild(b),u.appendChild(S),u.appendChild(h),u.addEventListener("click",T=>{T.stopPropagation(),U(),!E.active&&s.onBackpackSwitch&&s.onBackpackSwitch(E.name)}),Z.appendChild(u)}const p=document.createElement("div");p.className="backpack-picker-divider",Z.appendChild(p);const C=document.createElement("button");C.className="backpack-picker-item backpack-picker-add",C.type="button",C.textContent="+ Add new backpack…",C.addEventListener("click",async E=>{if(E.stopPropagation(),U(),!s.onBackpackRegister)return;const u=await mo();u&&s.onBackpackRegister(u.path,u.activate)}),Z.appendChild(C)}const ye=document.createElement("button");ye.className="tools-pane-toggle hidden",ye.title="Show sidebar (Tab)",ye.appendChild(at({size:14},[{tag:"polyline",attrs:{points:"13 7 18 12 13 17"}},{tag:"polyline",attrs:{points:"6 7 11 12 6 17"}}])),ye.addEventListener("click",x),t.appendChild(m),t.appendChild(r),t.appendChild(d),t.appendChild(o),t.appendChild(n);let Ce=[],se=[],ge="";return m.addEventListener("input",()=>{const p=m.value.toLowerCase();for(const C of Ce){const E=C.dataset.name??"";C.style.display=E.includes(p)?"":"none"}for(const C of se){const E=C.dataset.name??"";C.style.display=E.includes(p)?"":"none"}}),{setStaleVersionBanner(p,C){W.replaceChildren();const E=document.createElement("div");E.className="sidebar-stale-banner-title",E.textContent=`Viewer ${p} is out of date`;const u=document.createElement("div");u.className="sidebar-stale-banner-subtitle",u.textContent=`Latest is ${C}. Your version is stuck because of an npx cache.`;const b=document.createElement("pre");b.className="sidebar-stale-banner-hint",b.textContent=`npm cache clean --force
|
|
2
2
|
npx backpack-viewer@latest`,W.appendChild(E),W.appendChild(u),W.appendChild(b),W.hidden=!1},setBackpacks(p){Ee=p.slice();const C=p.find(E=>E.active)??null;te=C,C&&(X.textContent=C.name,_.style.setProperty("--backpack-color",C.color),t.style.setProperty("--backpack-color",C.color)),G()},setActiveBackpack(p){te=p,Ee=Ee.map(C=>({...C,active:C.name===p.name})),Ee.some(C=>C.name===p.name)||Ee.push({...p,active:!0}),X.textContent=p.name,_.style.setProperty("--backpack-color",p.color),t.style.setProperty("--backpack-color",p.color),G()},getActiveBackpack(){return te},setSummaries(p){r.replaceChildren();const C=fetch("/api/locks").then(u=>u.json()).catch(()=>({})),E=fetch("/api/sync-status").then(u=>u.json()).then(u=>new Set(u.synced)).catch(()=>new Set);Ce=p.map(u=>{const b=document.createElement("li");b.className="ontology-item",b.dataset.name=u.name;const S=document.createElement("span");S.className="name",S.textContent=u.name;const h=document.createElement("span");h.className="stats";const T=xn(u.nodeCount,u.edgeCount);h.textContent=`${u.nodeCount} nodes, ${u.edgeCount} edges · ~${vn(T)}`;const w=document.createElement("span");w.className="sidebar-branch",w.dataset.graph=u.name;const N=document.createElement("span");N.className="sidebar-lock-badge",N.dataset.graph=u.name,C.then(y=>{if(!N.isConnected)return;const P=y[u.name];P&&typeof P=="object"&&P.author&&(N.textContent=`editing: ${P.author}`,N.title=`Last activity: ${P.lastActivity??""}`,N.classList.add("active"))});const L=document.createElement("span");if(L.className="sidebar-sync-badge",L.dataset.graph=u.name,E.then(y=>{L.isConnected&&y.has(u.name)&&(L.textContent="synced",L.title="This graph has been synced",L.classList.add("active"))}),b.appendChild(S),b.appendChild(h),b.appendChild(N),b.appendChild(L),b.appendChild(w),s.onRename){const y=document.createElement("button");y.className="sidebar-edit-btn",y.textContent="✎",y.title="Rename";const P=s.onRename;y.addEventListener("click",$=>{$.stopPropagation();const K=document.createElement("input");K.type="text",K.className="sidebar-rename-input",K.value=u.name,S.textContent="",S.appendChild(K),y.style.display="none",K.focus(),K.select();const ae=()=>{const ce=K.value.trim();ce&&ce!==u.name?P(u.name,ce):(S.textContent=u.name,y.style.display="")};K.addEventListener("blur",ae),K.addEventListener("keydown",ce=>{ce.key==="Enter"&&K.blur(),ce.key==="Escape"&&(K.value=u.name,K.blur())})}),b.appendChild(y)}return b.addEventListener("click",()=>s.onSelect(u.name)),r.appendChild(b),b}),ge&&this.setActive(ge)},setActive(p){ge=p;for(const C of Ce)C.classList.toggle("active",C.dataset.name===p);for(const C of se)C.classList.toggle("active",C.dataset.name===p)},setRemotes(p){o.replaceChildren(),se=p.map(E=>{const u=document.createElement("li");u.className="ontology-item ontology-item-remote",u.dataset.name=E.name;const b=document.createElement("div");b.className="remote-name-row";const S=document.createElement("span");S.className="name",S.textContent=E.name;const h=document.createElement("span");h.className="remote-badge",h.textContent=E.pinned?"remote · pinned":"remote",h.title=`Source: ${E.source??E.url}`,b.appendChild(S),b.appendChild(h);const T=document.createElement("span");T.className="stats";const w=xn(E.nodeCount,E.edgeCount);T.textContent=`${E.nodeCount} nodes, ${E.edgeCount} edges · ~${vn(w)}`;const N=document.createElement("span");return N.className="remote-source",N.textContent=E.source??new URL(E.url).hostname,N.title=E.url,u.appendChild(b),u.appendChild(T),u.appendChild(N),u.addEventListener("click",()=>s.onSelect(E.name)),o.appendChild(u),u});const C=p.length>0;d.hidden=!C,o.hidden=!C,ge&&this.setActive(ge)},setActiveBranch(p,C,E){const u=r.querySelectorAll(`.sidebar-branch[data-graph="${p}"]`);for(const b of u){b.textContent=`/ ${C}`,b.title="Click to switch branch",b.style.cursor="pointer";const S=b.cloneNode(!0);b.replaceWith(S),S.addEventListener("click",h=>{h.stopPropagation(),be(p,S,E??[])})}},setSnippets(p,C){var b;const E=Ce.find(S=>S.dataset.name===p);if(!E||((b=E.querySelector(".sidebar-snippets"))==null||b.remove(),C.length===0))return;const u=document.createElement("div");u.className="sidebar-snippets";for(const S of C){const h=document.createElement("div");h.className="sidebar-snippet";const T=document.createElement("span");T.className="sidebar-snippet-label",T.textContent=`◆ ${S.label}`,T.title=`${S.nodeCount} nodes — click to load`;const w=document.createElement("button");w.className="sidebar-snippet-delete",w.textContent="×",w.title="Delete snippet",w.addEventListener("click",N=>{var L;N.stopPropagation(),(L=s.onSnippetDelete)==null||L.call(s,p,S.id)}),h.appendChild(T),h.appendChild(w),h.addEventListener("click",N=>{var L;N.stopPropagation(),(L=s.onSnippetLoad)==null||L.call(s,p,S.id)}),u.appendChild(h)}E.appendChild(u)},toggle:x,expandBtn:ye};function be(p,C,E){const u=t.querySelector(".branch-picker");u&&u.remove();const b=document.createElement("div");b.className="branch-picker";for(const h of E){const T=document.createElement("div");T.className="branch-picker-item",h.active&&T.classList.add("branch-picker-active");const w=document.createElement("span");if(w.textContent=h.name,T.appendChild(w),!h.active&&s.onBranchDelete){const N=document.createElement("button");N.className="branch-picker-delete",N.textContent="×",N.title=`Delete ${h.name}`,N.addEventListener("click",L=>{L.stopPropagation(),jn("Delete branch",`Delete branch "${h.name}"?`).then(y=>{y&&(s.onBranchDelete(p,h.name),b.remove())})}),T.appendChild(N)}h.active||T.addEventListener("click",()=>{var N;(N=s.onBranchSwitch)==null||N.call(s,p,h.name),b.remove()}),b.appendChild(T)}if(s.onBranchCreate){const h=document.createElement("div");h.className="branch-picker-item branch-picker-create",h.textContent="+ New branch",h.addEventListener("click",()=>{Dt("New branch","Branch name").then(T=>{T&&(s.onBranchCreate(p,T),b.remove())})}),b.appendChild(h)}C.after(b);const S=h=>{b.contains(h.target)||(b.remove(),document.removeEventListener("click",S))};setTimeout(()=>document.addEventListener("click",S),0)}}function Zt(t,e,s,l){return{x0:t,y0:e,x1:s,y1:l,cx:0,cy:0,mass:0,children:[null,null,null,null],body:null}}function En(t,e,s){const l=(t.x0+t.x1)/2,m=(t.y0+t.y1)/2;return(e<l?0:1)+(s<m?0:2)}function wn(t,e){const s=(t.x0+t.x1)/2,l=(t.y0+t.y1)/2;switch(e){case 0:return[t.x0,t.y0,s,l];case 1:return[s,t.y0,t.x1,l];case 2:return[t.x0,l,s,t.y1];default:return[s,l,t.x1,t.y1]}}function Qt(t,e){if(t.mass===0&&t.body===null){t.body=e,t.cx=e.x,t.cy=e.y,t.mass=1;return}if(t.body!==null){const m=t.body;t.body=null,m.x===e.x&&m.y===e.y&&(e.x+=(Math.random()-.5)*.1,e.y+=(Math.random()-.5)*.1);const r=En(t,m.x,m.y);if(t.children[r]===null){const[d,o,n,g]=wn(t,r);t.children[r]=Zt(d,o,n,g)}Qt(t.children[r],m)}const s=En(t,e.x,e.y);if(t.children[s]===null){const[m,r,d,o]=wn(t,s);t.children[s]=Zt(m,r,d,o)}Qt(t.children[s],e);const l=t.mass+1;t.cx=(t.cx*t.mass+e.x)/l,t.cy=(t.cy*t.mass+e.y)/l,t.mass=l}function yo(t){if(t.length===0)return null;let e=1/0,s=1/0,l=-1/0,m=-1/0;for(const i of t)i.x<e&&(e=i.x),i.y<s&&(s=i.y),i.x>l&&(l=i.x),i.y>m&&(m=i.y);const r=Math.max(l-e,m-s)*.1+50,d=(e+l)/2,o=(s+m)/2,n=Math.max(l-e,m-s)/2+r,g=Zt(d-n,o-n,d+n,o+n);for(const i of t)Qt(g,i);return g}function Co(t,e,s,l,m,r){zn(t,e,s,l,m,r)}function zn(t,e,s,l,m,r){if(t.mass===0)return;const d=t.cx-e.x,o=t.cy-e.y,n=d*d+o*o;if(t.body!==null){if(t.body!==e){let i=Math.sqrt(n);i<r&&(i=r);const c=l*m/(i*i),I=d/i*c,M=o/i*c;e.vx-=I,e.vy-=M}return}const g=t.x1-t.x0;if(g*g/n<s*s){let i=Math.sqrt(n);i<r&&(i=r);const c=l*t.mass*m/(i*i),I=d/i*c,M=o/i*c;e.vx-=I,e.vy-=M;return}for(let i=0;i<4;i++)t.children[i]!==null&&zn(t.children[i],e,s,l,m,r)}const _n={clusterStrength:.08,spacing:1.5},kn=6e3,bo=12e3,vo=.004,Hn=140,Yn=350,Sn=.9,Nn=.01,xt=30,_t=50;let Ze={..._n};function lt(t){t.clusterStrength!==void 0&&(Ze.clusterStrength=t.clusterStrength),t.spacing!==void 0&&(Ze.spacing=t.spacing)}function wt(){return{...Ze}}function xo(t){if(t<=30)return{..._n};const e=Math.log2(t/30);return{clusterStrength:Math.min(.5,.08+.06*e),spacing:Math.min(15,1.5+1.2*e)}}function Eo(t,e){for(const s of Object.values(t))if(typeof s=="string")return s;return e}function Ln(t,e,s){const l=new Set(e);let m=new Set(e);for(let r=0;r<s;r++){const d=new Set;for(const o of t.edges)m.has(o.sourceId)&&!l.has(o.targetId)&&d.add(o.targetId),m.has(o.targetId)&&!l.has(o.sourceId)&&d.add(o.sourceId);for(const o of d)l.add(o);if(m=d,d.size===0)break}return{nodes:t.nodes.filter(r=>l.has(r.id)),edges:t.edges.filter(r=>l.has(r.sourceId)&&l.has(r.targetId)),metadata:t.metadata}}function Ht(t){const e=new Map,s=[...new Set(t.nodes.map(n=>n.type))],l=Math.sqrt(s.length)*Yn*.6*Math.max(1,Ze.spacing),m=new Map,r=new Map;for(const n of t.nodes)r.set(n.type,(r.get(n.type)??0)+1);const d=t.nodes.map(n=>{const g=s.indexOf(n.type),i=2*Math.PI*g/Math.max(s.length,1),c=Math.cos(i)*l,I=Math.sin(i)*l,M=m.get(n.type)??0;m.set(n.type,M+1);const x=r.get(n.type)??1,F=2*Math.PI*M/x,W=Hn*.6,V={id:n.id,x:c+Math.cos(F)*W,y:I+Math.sin(F)*W,vx:0,vy:0,label:Eo(n.properties,n.id),type:n.type};return e.set(n.id,V),V}),o=t.edges.map(n=>({sourceId:n.sourceId,targetId:n.targetId,type:n.type}));return{nodes:d,edges:o,nodeMap:e}}const wo=.7,ko=80;function So(t,e){const{nodes:s,edges:l,nodeMap:m}=t,r=bo*Ze.spacing;if(s.length>=ko){const o=yo(s);if(o)for(const g of s)Co(o,g,wo,r,e,xt);const n=r-kn;if(n>0){const g=new Map;for(const i of s){let c=g.get(i.type);c||(c=[],g.set(i.type,c)),c.push(i)}for(const i of g.values())for(let c=0;c<i.length;c++)for(let I=c+1;I<i.length;I++){const M=i[c],x=i[I];let F=x.x-M.x,W=x.y-M.y,V=Math.sqrt(F*F+W*W);V<xt&&(V=xt);const _=n*e/(V*V),X=F/V*_,Y=W/V*_;M.vx+=X,M.vy+=Y,x.vx-=X,x.vy-=Y}}}else for(let o=0;o<s.length;o++)for(let n=o+1;n<s.length;n++){const g=s[o],i=s[n];let c=i.x-g.x,I=i.y-g.y,M=Math.sqrt(c*c+I*I);M<xt&&(M=xt);const F=(g.type===i.type?kn:r)*e/(M*M),W=c/M*F,V=I/M*F;g.vx-=W,g.vy-=V,i.vx+=W,i.vy+=V}for(const o of l){const n=m.get(o.sourceId),g=m.get(o.targetId);if(!n||!g)continue;const i=g.x-n.x,c=g.y-n.y,I=Math.sqrt(i*i+c*c);if(I===0)continue;const M=n.type===g.type?Hn*Ze.spacing:Yn*Ze.spacing,x=vo*(I-M)*e,F=i/I*x,W=c/I*x;n.vx+=F,n.vy+=W,g.vx-=F,g.vy-=W}for(const o of s)o.vx-=o.x*Nn*e,o.vy-=o.y*Nn*e;const d=new Map;for(const o of s){const n=d.get(o.type)??{x:0,y:0,count:0};n.x+=o.x,n.y+=o.y,n.count++,d.set(o.type,n)}for(const o of d.values())o.x/=o.count,o.y/=o.count;for(const o of s){const n=d.get(o.type);o.vx+=(n.x-o.x)*Ze.clusterStrength*e,o.vy+=(n.y-o.y)*Ze.clusterStrength*e}for(const o of s){if(o.pinned){o.vx=0,o.vy=0;continue}o.vx*=Sn,o.vy*=Sn;const n=Math.sqrt(o.vx*o.vx+o.vy*o.vy);n>_t&&(o.vx=o.vx/n*_t,o.vy=o.vy/n*_t),o.x+=o.vx,o.y+=o.vy}return e*.995}const In=["#d4a27f","#c17856","#b07a5e","#d4956b","#a67c5a","#cc9e7c","#c4866a","#cb8e6c","#b8956e","#a88a70","#d9b08c","#c4a882","#e8b898","#b5927a","#a8886e","#d1a990"],Mn=new Map;function Ae(t){const e=Mn.get(t);if(e)return e;let s=0;for(let m=0;m<t.length;m++)s=(s<<5)-s+t.charCodeAt(m)|0;const l=In[Math.abs(s)%In.length];return Mn.set(t,l),l}class No{constructor(e){At(this,"cells",new Map);At(this,"cellSize");At(this,"invCell");this.cellSize=e,this.invCell=1/e}key(e,s){const l=e+32768|0,m=s+32768|0;return l*73856093^m*19349663}clear(){this.cells.clear()}insert(e){const s=Math.floor(e.x*this.invCell),l=Math.floor(e.y*this.invCell),m=this.key(s,l),r=this.cells.get(m);r?r.push(e):this.cells.set(m,[e])}rebuild(e){this.cells.clear();for(const s of e)this.insert(s)}query(e,s,l){const m=l*l,r=Math.floor((e-l)*this.invCell),d=Math.floor((e+l)*this.invCell),o=Math.floor((s-l)*this.invCell),n=Math.floor((s+l)*this.invCell);let g=null,i=m;for(let c=r;c<=d;c++)for(let I=o;I<=n;I++){const M=this.cells.get(this.key(c,I));if(M)for(const x of M){const F=x.x-e,W=x.y-s,V=F*F+W*W;V<=i&&(i=V,g=x)}}return g}}const pt=new Map,Lo=2e3;function Io(t,e,s){return`${t}|${e}|${s}`}const Mo=new OffscreenCanvas(1,1),Tn=Mo.getContext("2d");function To(t,e,s){Tn.font=e;const l=Tn.measureText(t),m=Math.ceil(l.width)+2,r=Math.ceil(l.actualBoundingBoxAscent+l.actualBoundingBoxDescent)+4,d=new OffscreenCanvas(m,r),o=d.getContext("2d");return o.font=e,o.fillStyle=s,o.textAlign="left",o.textBaseline="top",o.fillText(t,1,1),{canvas:d,width:m,height:r}}function An(t,e,s,l,m,r,d){const o=Io(e,m,r);let n=pt.get(o);if(!n){if(pt.size>=Lo){const c=pt.keys().next().value;c!==void 0&&pt.delete(c)}n=To(e,m,r),pt.set(o,n)}const g=s-n.width/2,i=d==="top"?l:l-n.height;t.drawImage(n.canvas,g,i)}function Ao(){pt.clear()}function we(t){return getComputedStyle(document.documentElement).getPropertyValue(t).trim()}const Ue=20,Yt=.001,Po={hideBadges:.4,hideLabels:.25,hideEdgeLabels:.35,smallNodes:.2,hideArrows:.15,dotNodes:.1,hullsOnly:.05},Ro={zoomFactor:1.3,zoomMin:.05,zoomMax:10,panAnimationMs:300};function Rt(t,e,s,l,m,r=100){const d=(t-s.x)*s.scale,o=(e-s.y)*s.scale;return d>=-r&&d<=l+r&&o>=-r&&o<=m+r}function Bo(t,e,s,l){const m={...Po,...(l==null?void 0:l.lod)??{}},r={...Ro,...(l==null?void 0:l.navigation)??{}},d={pulseSpeed:.02,...(l==null?void 0:l.walk)??{}},o=t.querySelector("canvas"),n=o.getContext("2d"),g=window.devicePixelRatio||1;let i={x:0,y:0,scale:1},c=null,I=1,M=0,x=new Set,F=null,W=!0,V=!0,_=!0,X=!0,Y="idle",Z=[],q=0,me=0,U=null,pe=new Set;const Ee=5;let te=null,G=null,ye=1,Ce=null,se=null,ge=null,be=!1,p=[],C=0,E=0;const u=400,b=new No(Ue*2);let S=0;function h(){ae(),S||(S=requestAnimationFrame(()=>{S=0,Xe()}))}const T=150;let w=null,N=!1;function L(){if(!w)try{w=new Worker(new URL("/assets/layout-worker-4xak23M6.js",import.meta.url),{type:"module"}),w.onmessage=y,w.onerror=()=>{N=!1,w=null,j()}}catch{return N=!1,null}return w}function y(f){const k=f.data;if(k.type==="tick"&&c){const B=k.positions,D=c.nodes;for(let H=0;H<D.length;H++)D[H].x=B[H*4],D[H].y=B[H*4+1],D[H].vx=B[H*4+2],D[H].vy=B[H*4+3];I=k.alpha,b.rebuild(D),Xe()}k.type==="settled"&&(I=0,be&&p.length>0&&!a&&(a=requestAnimationFrame(v)))}let P=null,$=null,K=!0;function ae(){K=!0}let ce=null,ue=null;const ve=r.panAnimationMs;function $e(){o.width=o.clientWidth*g,o.height=o.clientHeight*g,ae(),h()}const Qe=new ResizeObserver($e);Qe.observe(t),$e();function Re(f,k){return[f/i.scale+i.x,k/i.scale+i.y]}function et(f,k){if(!c)return null;const[B,D]=Re(f,k);return b.query(B,D,Ue)}function ct(){if(!U)return;n.save();const f=Math.min(U.x1,U.x2),k=Math.max(U.x1,U.x2),B=Math.min(U.y1,U.y2),D=Math.max(U.y1,U.y2);n.strokeStyle=we("--accent")||"#d4a27f",n.fillStyle=we("--accent")||"#d4a27f",n.globalAlpha=.12,n.fillRect(f,B,k-f,D-B),n.globalAlpha=.8,n.lineWidth=1/Math.max(i.scale,.5),n.setLineDash([6/Math.max(i.scale,.5),4/Math.max(i.scale,.5)]),n.strokeRect(f,B,k-f,D-B),n.setLineDash([]),n.restore()}function Ot(){if(!c)return;C+=d.pulseSpeed;const f=new Set(p);n.save(),n.setTransform(g,0,0,g,0,0),P&&(n.clearRect(0,0,o.clientWidth,o.clientHeight),n.drawImage(P,0,0,o.clientWidth,o.clientHeight)),n.save(),n.translate(-i.x*i.scale,-i.y*i.scale),n.scale(i.scale,i.scale);const k=we("--canvas-walk-edge")||"#1a1a1a",B=[];for(const z of c.edges){if(!f.has(z.sourceId)||!f.has(z.targetId)||z.sourceId===z.targetId)continue;const O=c.nodeMap.get(z.sourceId),J=c.nodeMap.get(z.targetId);!O||!J||B.push(O.x,O.y,J.x,J.y)}if(B.length>0){n.beginPath();for(let z=0;z<B.length;z+=4)n.moveTo(B[z],B[z+1]),n.lineTo(B[z+2],B[z+3]);n.strokeStyle=k,n.lineWidth=3,n.globalAlpha=.5+.5*Math.sin(C),n.stroke(),n.globalAlpha=1}const D=i.scale<m.smallNodes?Ue*.5:Ue,H=we("--accent")||"#d4a27f";for(const z of p){const O=c.nodeMap.get(z);if(!O||!Rt(O.x,O.y,i,o.clientWidth,o.clientHeight))continue;const J=z===p[p.length-1],Q=.5+.5*Math.sin(C);n.strokeStyle=H,n.lineWidth=J?3:2,n.globalAlpha=J?.5+.5*Q:.3+.4*Q,n.beginPath(),n.arc(O.x,O.y,D+(J?6:4),0,Math.PI*2),n.stroke()}n.globalAlpha=1,ct(),n.restore(),X&&c.nodes.length>1&&Wt(),n.restore()}function Xe(){var ln;if(!c){n.clearRect(0,0,o.width,o.height);return}if(!K&&P&&be&&p.length>0&&I<Yt){Ot();return}const f=I<Yt&&be&&p.length>0;be&&p.length>0&&(C+=d.pulseSpeed);const k=be&&!f?new Set(p):null,B=we("--canvas-edge"),D=we("--canvas-edge-highlight"),H=we("--canvas-edge-dim"),z=we("--canvas-edge-label"),O=we("--canvas-edge-label-highlight"),J=we("--canvas-edge-label-dim"),Q=we("--canvas-arrow"),re=we("--canvas-arrow-highlight"),fe=we("--canvas-node-label"),ke=we("--canvas-node-label-dim"),Se=we("--canvas-type-badge"),Te=we("--canvas-type-badge-dim"),Be=we("--canvas-selection-border"),je=we("--canvas-node-border");if(n.save(),n.setTransform(g,0,0,g,0,0),n.clearRect(0,0,o.clientWidth,o.clientHeight),n.save(),n.translate(-i.x*i.scale,-i.y*i.scale),n.scale(i.scale,i.scale),_&&i.scale>=m.smallNodes){const ee=new Map;for(const Pe of c.nodes){if(F!==null&&!F.has(Pe.id))continue;const Oe=ee.get(Pe.type)??[];Oe.push(Pe),ee.set(Pe.type,Oe)}for(const[Pe,Oe]of ee){if(Oe.length<2)continue;const st=Ae(Pe),nt=Ue*2.5;let He=1/0,qe=1/0,Fe=-1/0,Ke=-1/0;for(const We of Oe)We.x<He&&(He=We.x),We.y<qe&&(qe=We.y),We.x>Fe&&(Fe=We.x),We.y>Ke&&(Ke=We.y);n.beginPath();const oe=(Fe-He)/2+nt,Ie=(Ke-qe)/2+nt,Ne=(He+Fe)/2,ze=(qe+Ke)/2;n.ellipse(Ne,ze,oe,Ie,0,0,Math.PI*2),n.fillStyle=st,n.globalAlpha=.05,n.fill(),n.strokeStyle=st,n.globalAlpha=.12,n.lineWidth=1,n.setLineDash([4,4]),n.stroke(),n.setLineDash([]),n.globalAlpha=1}}let Ye=null;if(x.size>0){Ye=new Set;for(const ee of c.edges)x.has(ee.sourceId)&&Ye.add(ee.targetId),x.has(ee.targetId)&&Ye.add(ee.sourceId)}const tt=we("--accent")||"#d4a27f",_e=we("--canvas-walk-edge")||"#1a1a1a",it=i.scale>=m.hideArrows,Mt=V&&i.scale>=m.hideEdgeLabels;if(W){const ee=[],Pe=[],Oe=[],st=[],nt=[],He=[];for(const oe of c.edges){const Ie=c.nodeMap.get(oe.sourceId),Ne=c.nodeMap.get(oe.targetId);if(!Ie||!Ne||!Rt(Ie.x,Ie.y,i,o.clientWidth,o.clientHeight,200)&&!Rt(Ne.x,Ne.y,i,o.clientWidth,o.clientHeight,200))continue;const ze=F===null||F.has(oe.sourceId),We=F===null||F.has(oe.targetId),rn=ze&&We;if(F!==null&&!ze&&!We)continue;const jt=x.size>0&&(x.has(oe.sourceId)||x.has(oe.targetId))||F!==null&&rn,dn=F!==null&&!rn,pn=k!==null&&k.has(oe.sourceId)&&k.has(oe.targetId),un=ge?te==null?void 0:te.edges.find(Tt=>Tt.sourceId===oe.sourceId&&Tt.targetId===oe.targetId||Tt.targetId===oe.sourceId&&Tt.sourceId===oe.targetId):null,mn=!!(ge&&un&&ge.edgeIds.has(un.id));if(oe.sourceId===oe.targetId){St(Ie,oe.type,jt,B,D,z,O);continue}(mn?nt:pn?st:jt?Pe:dn?Oe:ee).push(Ie.x,Ie.y,Ne.x,Ne.y),(it||Mt)&&He.push({sx:Ie.x,sy:Ie.y,tx:Ne.x,ty:Ne.y,type:oe.type,highlighted:jt,edgeDimmed:dn,isPathEdge:mn,isWalkEdge:pn})}const qe=it?1.5:1,Ke=[{lines:ee,color:B,width:qe,alpha:1},{lines:Oe,color:H,width:qe,alpha:1},{lines:Pe,color:D,width:it?2.5:1,alpha:1},{lines:nt,color:tt,width:3,alpha:1},{lines:st,color:_e,width:3,alpha:.5+.5*Math.sin(C)}];for(const oe of Ke)if(oe.lines.length!==0){n.beginPath();for(let Ie=0;Ie<oe.lines.length;Ie+=4)n.moveTo(oe.lines[Ie],oe.lines[Ie+1]),n.lineTo(oe.lines[Ie+2],oe.lines[Ie+3]);n.strokeStyle=oe.color,n.lineWidth=oe.width,n.globalAlpha=oe.alpha,n.stroke()}n.globalAlpha=1;for(const oe of He)if(it&&ut(oe.sx,oe.sy,oe.tx,oe.ty,oe.highlighted||oe.isPathEdge,Q,re),Mt){const Ie=(oe.sx+oe.tx)/2,Ne=(oe.sy+oe.ty)/2;n.fillStyle=oe.highlighted?O:oe.edgeDimmed?J:z,n.font="9px system-ui, sans-serif",n.textAlign="center",n.textBaseline="bottom",n.fillText(oe.type,Ie,Ne-4)}}const Ut=performance.now()-E,Le=Math.min(1,Ut/u),Ve=1-(1-Le)*(1-Le),Je=Le<1,cn=i.scale<m.hullsOnly,Vn=!cn&&i.scale<m.dotNodes;if(!cn)for(const ee of c.nodes){if(!Rt(ee.x,ee.y,i,o.clientWidth,o.clientHeight))continue;const Pe=Ae(ee.type);if(Vn){const Ne=F!==null&&!F.has(ee.id);n.fillStyle=Pe;const ze=Ne?.1:.8;n.globalAlpha=Je?ze*Ve:ze,n.fillRect(ee.x-2,ee.y-2,4,4);continue}const Oe=x.has(ee.id),st=Ye!==null&&Ye.has(ee.id),nt=F!==null&&!F.has(ee.id),He=nt||x.size>0&&!Oe&&!st,qe=i.scale<m.smallNodes?Ue*.5:Ue,Fe=Je?qe*Ve:qe;if(k!=null&&k.has(ee.id)){const Ne=p[p.length-1]===ee.id,ze=.5+.5*Math.sin(C),We=we("--accent")||"#d4a27f";n.save(),n.strokeStyle=We,n.lineWidth=Ne?3:2,n.globalAlpha=Ne?.5+.5*ze:.3+.4*ze,n.beginPath(),n.arc(ee.x,ee.y,Fe+(Ne?6:4),0,Math.PI*2),n.stroke(),n.restore()}Oe&&(n.save(),n.shadowColor=Pe,n.shadowBlur=20,n.beginPath(),n.arc(ee.x,ee.y,Fe+3,0,Math.PI*2),n.fillStyle=Pe,n.globalAlpha=.3,n.fill(),n.restore()),n.beginPath(),n.arc(ee.x,ee.y,Fe,0,Math.PI*2),n.fillStyle=Pe;const Ke=nt?.1:He?.3:1;n.globalAlpha=Je?Ke*Ve:Ke,n.fill(),n.strokeStyle=Oe?Be:je,n.lineWidth=Oe?3:1.5,n.stroke(),n.globalAlpha=1,ee.pinned&&(n.save(),n.strokeStyle=je,n.globalAlpha=.55,n.lineWidth=1,n.setLineDash([3,3]),n.beginPath(),n.arc(ee.x,ee.y,Fe+4,0,Math.PI*2),n.stroke(),n.setLineDash([]),n.restore()),ge&&ge.nodeIds.has(ee.id)&&!Oe&&(n.save(),n.shadowColor=we("--accent")||"#d4a27f",n.shadowBlur=15,n.beginPath(),n.arc(ee.x,ee.y,Fe+2,0,Math.PI*2),n.strokeStyle=we("--accent")||"#d4a27f",n.globalAlpha=.5,n.lineWidth=2,n.stroke(),n.restore());const oe=te==null?void 0:te.nodes.find(Ne=>Ne.id===ee.id);if(((ln=oe==null?void 0:oe.properties)==null?void 0:ln._starred)===!0&&(n.fillStyle="#ffd700",n.font="10px system-ui, sans-serif",n.textAlign="left",n.textBaseline="bottom",n.fillText("★",ee.x+Fe-2,ee.y-Fe+2)),i.scale>=m.hideLabels){const Ne=ee.label.length>24?ee.label.slice(0,22)+"...":ee.label,ze=He?ke:fe;An(n,Ne,ee.x,ee.y+Fe+4,"11px system-ui, sans-serif",ze,"top")}if(i.scale>=m.hideBadges){const Ne=He?Te:Se;An(n,ee.type,ee.x,ee.y-Fe-3,"9px system-ui, sans-serif",Ne,"bottom")}n.globalAlpha=1}if(n.restore(),n.restore(),f){const ee=o.width,Pe=o.height;(!P||P.width!==ee||P.height!==Pe)&&(P=new OffscreenCanvas(ee,Pe),$=P.getContext("2d")),$&&($.clearRect(0,0,ee,Pe),$.drawImage(o,0,0),K=!1),Ot();return}X&&c.nodes.length>1&&Wt(),U&&(n.save(),n.setTransform(g,0,0,g,0,0),n.translate(-i.x*i.scale,-i.y*i.scale),n.scale(i.scale,i.scale),ct(),n.restore())}function Wt(){if(!c)return;const f=140,k=100,B=8,D=o.clientWidth-f-16,H=o.clientHeight-k-16;let z=1/0,O=1/0,J=-1/0,Q=-1/0;for(const Le of c.nodes)Le.x<z&&(z=Le.x),Le.y<O&&(O=Le.y),Le.x>J&&(J=Le.x),Le.y>Q&&(Q=Le.y);const re=J-z||1,fe=Q-O||1,ke=Math.min((f-B*2)/re,(k-B*2)/fe),Se=D+B+(f-B*2-re*ke)/2,Te=H+B+(k-B*2-fe*ke)/2;n.save(),n.setTransform(g,0,0,g,0,0),n.fillStyle=we("--bg-surface")||"#1a1a1a",n.globalAlpha=.85,n.beginPath(),n.roundRect(D,H,f,k,8),n.fill(),n.strokeStyle=we("--border")||"#2a2a2a",n.globalAlpha=1,n.lineWidth=1,n.stroke(),n.globalAlpha=.15,n.strokeStyle=we("--canvas-edge")||"#555",n.lineWidth=.5;for(const Le of c.edges){const Ve=c.nodeMap.get(Le.sourceId),Je=c.nodeMap.get(Le.targetId);!Ve||!Je||Le.sourceId===Le.targetId||(n.beginPath(),n.moveTo(Se+(Ve.x-z)*ke,Te+(Ve.y-O)*ke),n.lineTo(Se+(Je.x-z)*ke,Te+(Je.y-O)*ke),n.stroke())}n.globalAlpha=.8;for(const Le of c.nodes){const Ve=Se+(Le.x-z)*ke,Je=Te+(Le.y-O)*ke;n.beginPath(),n.arc(Ve,Je,2,0,Math.PI*2),n.fillStyle=Ae(Le.type),n.fill()}const Be=i.x,je=i.y,Ye=i.x+o.clientWidth/i.scale,tt=i.y+o.clientHeight/i.scale,_e=Se+(Be-z)*ke,it=Te+(je-O)*ke,Mt=(Ye-Be)*ke,Ut=(tt-je)*ke;n.globalAlpha=.3,n.strokeStyle=we("--accent")||"#d4a27f",n.lineWidth=1.5,n.strokeRect(Math.max(D,Math.min(_e,D+f)),Math.max(H,Math.min(it,H+k)),Math.min(Mt,f),Math.min(Ut,k)),n.globalAlpha=1,n.restore()}function ut(f,k,B,D,H,z,O){const J=Math.atan2(D-k,B-f),Q=B-Math.cos(J)*Ue,re=D-Math.sin(J)*Ue,fe=8;n.beginPath(),n.moveTo(Q,re),n.lineTo(Q-fe*Math.cos(J-.4),re-fe*Math.sin(J-.4)),n.lineTo(Q-fe*Math.cos(J+.4),re-fe*Math.sin(J+.4)),n.closePath(),n.fillStyle=H?O:z,n.fill()}function St(f,k,B,D,H,z,O){const J=f.x+Ue+15,Q=f.y-Ue-15;n.beginPath(),n.arc(J,Q,15,0,Math.PI*2),n.strokeStyle=B?H:D,n.lineWidth=B?2.5:1.5,n.stroke(),V&&(n.fillStyle=B?O:z,n.font="9px system-ui, sans-serif",n.textAlign="center",n.fillText(k,J,Q-18))}function mt(){if(!ce||!ue)return;const f=performance.now()-ue.time,k=Math.min(f/ve,1),B=1-Math.pow(1-k,3);i.x=ue.x+(ce.x-ue.x)*B,i.y=ue.y+(ce.y-ue.y)*B,ae(),Xe(),k<1?requestAnimationFrame(mt):(ce=null,ue=null)}let a=0;function v(){if(!be||p.length===0){a=0;return}Xe(),a=requestAnimationFrame(v)}function R(){if(!c||c.nodes.length===0)return;let f=1/0,k=1/0,B=-1/0,D=-1/0;for(const re of c.nodes)re.x<f&&(f=re.x),re.y<k&&(k=re.y),re.x>B&&(B=re.x),re.y>D&&(D=re.y);const H=Ue*4,z=B-f+H*2,O=D-k+H*2,J=o.clientWidth/Math.max(z,1),Q=o.clientHeight/Math.max(O,1);i.scale=Math.min(J,Q,2),i.x=(f+B)/2-o.clientWidth/(2*i.scale),i.y=(k+D)/2-o.clientHeight/(2*i.scale),h()}function j(){if(!c||I<Yt){M=0,be&&p.length>0&&!a&&(a=requestAnimationFrame(v));return}I=So(c,I),b.rebuild(c.nodes),Xe(),M=requestAnimationFrame(j)}let ne=!1,de=0,le=0,he=0,Me=0;o.addEventListener("mousedown",f=>{Y="pending",ne=!1,de=f.clientX,le=f.clientY,he=f.clientX,Me=f.clientY;const k=o.getBoundingClientRect(),B=f.clientX-k.left,D=f.clientY-k.top,H=et(B,D);if(H&&!be){if(Z=[],x.has(H.id)&&x.size>1)for(const J of x){const Q=c==null?void 0:c.nodeMap.get(J);Q&&Z.push({node:Q,startX:Q.x,startY:Q.y})}else Z.push({node:H,startX:H.x,startY:H.y});const[z,O]=Re(B,D);q=z,me=O}else if(!H&&f.shiftKey){const[z,O]=Re(B,D);U={x1:z,y1:O,x2:z,y2:O}}}),o.addEventListener("mousemove",f=>{if(Y==="idle")return;const k=f.clientX-de,B=f.clientY-le,D=Math.abs(f.clientX-he),H=Math.abs(f.clientY-Me);if(Y==="pending"&&(D>Ee||H>Ee)&&(ne=!0,Z.length>0?(Y="nodeDrag",N&&w&&w.postMessage({type:"stop"})):U?Y="rubberBand":Y="pan"),Y==="nodeDrag"){const z=o.getBoundingClientRect(),O=f.clientX-z.left,J=f.clientY-z.top,[Q,re]=Re(O,J),fe=Q-q,ke=re-me;for(const Se of Z)Se.node.x=Se.startX+fe,Se.node.y=Se.startY+ke,Se.node.vx=0,Se.node.vy=0,Se.node.pinned=!0,pe.add(Se.node.id);b.rebuild((c==null?void 0:c.nodes)??[]),h()}else if(Y==="rubberBand"&&U){const z=o.getBoundingClientRect(),O=f.clientX-z.left,J=f.clientY-z.top,[Q,re]=Re(O,J);U.x2=Q,U.y2=re,h()}else Y==="pan"&&(i.x-=k/i.scale,i.y-=B/i.scale,h());de=f.clientX,le=f.clientY}),o.addEventListener("mouseup",f=>{const k=Y==="nodeDrag",B=Y==="rubberBand";if(Z.map(Q=>Q.node.id),k){if(N&&w&&c){const Q=Z.map(re=>({id:re.node.id,x:re.node.x,y:re.node.y}));w.postMessage({type:"pin",updates:Q}),w.postMessage({type:"resume",alpha:.5})}else I=Math.max(I,.5),M||j();Y="idle",Z=[],h();return}if(B&&U&&c){const Q=Math.min(U.x1,U.x2),re=Math.max(U.x1,U.x2),fe=Math.min(U.y1,U.y2),ke=Math.max(U.y1,U.y2);f.shiftKey||x.clear();for(const Te of c.nodes)Te.x>=Q&&Te.x<=re&&Te.y>=fe&&Te.y<=ke&&x.add(Te.id);const Se=[...x];e==null||e(Se.length>0?Se:null),U=null,Y="idle",h();return}if(Y==="pan"){Y="idle";return}if(Y="idle",U=null,ne)return;const D=o.getBoundingClientRect(),H=f.clientX-D.left,z=f.clientY-D.top,O=et(H,z),J=f.ctrlKey||f.metaKey||f.shiftKey;if(be&&G&&O&&c){const Q=p.length>0?p[p.length-1]:G[0],re=new Set([Q]),fe=[{id:Q,path:[Q]}];let ke=null;for(;fe.length>0;){const{id:je,path:Ye}=fe.shift();if(je===O.id){ke=Ye;break}for(const tt of c.edges){let _e=null;tt.sourceId===je?_e=tt.targetId:tt.targetId===je&&(_e=tt.sourceId),_e&&!re.has(_e)&&(re.add(_e),fe.push({id:_e,path:[...Ye,_e]}))}}if(!ke)return;for(const je of ke.slice(1))p.includes(je)||p.push(je);G=[O.id];const Se=Math.max(1,ye);ye=Se;const Te=Ln(te,[O.id],Se);cancelAnimationFrame(M),w&&w.postMessage({type:"stop"}),c=Ht(Te),b.rebuild(c.nodes),I=1,x=new Set([O.id]),F=null,i={x:0,y:0,scale:1},N=Te.nodes.length>=T;const Be=N?L():null;Be?Be.postMessage({type:"start",data:Te}):(N=!1,j()),setTimeout(()=>{c&&R()},300),s==null||s({seedNodeIds:[O.id],hops:Se,totalNodes:Te.nodes.length}),e==null||e([O.id]);return}if(O){J?x.has(O.id)?x.delete(O.id):x.add(O.id):x.size===1&&x.has(O.id)?x.clear():(x.clear(),x.add(O.id));const Q=[...x];e==null||e(Q.length>0?Q:null)}else x.clear(),e==null||e(null);h()}),o.addEventListener("mouseleave",()=>{if(Y==="nodeDrag")if(N&&w&&Z.length>0){const f=Z.map(k=>({id:k.node.id,x:k.node.x,y:k.node.y}));w.postMessage({type:"pin",updates:f}),w.postMessage({type:"resume",alpha:.5})}else I=Math.max(I,.5),M||j();Y==="rubberBand"&&(U=null,h()),Y="idle",Z=[]}),o.addEventListener("wheel",f=>{f.preventDefault();const k=o.getBoundingClientRect(),B=f.clientX-k.left,D=f.clientY-k.top,[H,z]=Re(B,D),O=f.ctrlKey?1-f.deltaY*.01:f.deltaY>0?.9:1.1;i.scale=Math.max(r.zoomMin,Math.min(r.zoomMax,i.scale*O)),i.x=H-B/i.scale,i.y=z-D/i.scale,h()},{passive:!1});let xe=[],Ge=0,Nt=1,ht=0,Lt=0,ft=!1;o.addEventListener("touchstart",f=>{f.preventDefault(),xe=Array.from(f.touches),xe.length===2?(Ge=an(xe[0],xe[1]),Nt=i.scale):xe.length===1&&(de=xe[0].clientX,le=xe[0].clientY,ht=xe[0].clientX,Lt=xe[0].clientY,ft=!1)},{passive:!1}),o.addEventListener("touchmove",f=>{f.preventDefault();const k=Array.from(f.touches);if(k.length===2&&xe.length===2){const D=an(k[0],k[1])/Ge;i.scale=Math.max(r.zoomMin,Math.min(r.zoomMax,Nt*D)),h()}else if(k.length===1){const B=k[0].clientX-de,D=k[0].clientY-le;(Math.abs(k[0].clientX-ht)>10||Math.abs(k[0].clientY-Lt)>10)&&(ft=!0),i.x-=B/i.scale,i.y-=D/i.scale,de=k[0].clientX,le=k[0].clientY,h()}xe=k},{passive:!1}),o.addEventListener("touchend",f=>{if(f.preventDefault(),ft||f.changedTouches.length!==1)return;const k=f.changedTouches[0],B=o.getBoundingClientRect(),D=k.clientX-B.left,H=k.clientY-B.top,z=et(D,H);if(z){x.size===1&&x.has(z.id)?x.clear():(x.clear(),x.add(z.id));const O=[...x];e==null||e(O.length>0?O:null)}else x.clear(),e==null||e(null);h()},{passive:!1}),o.addEventListener("gesturestart",f=>f.preventDefault()),o.addEventListener("gesturechange",f=>f.preventDefault());function an(f,k){const B=f.clientX-k.clientX,D=f.clientY-k.clientY;return Math.sqrt(B*B+D*D)}const gt=document.createElement("div");gt.className="zoom-controls";const yt=document.createElement("button");yt.className="zoom-btn",yt.textContent="+",yt.title="Zoom in",yt.addEventListener("click",()=>{const f=o.clientWidth/2,k=o.clientHeight/2,[B,D]=Re(f,k);i.scale=Math.min(r.zoomMax,i.scale*r.zoomFactor),i.x=B-f/i.scale,i.y=D-k/i.scale,h()});const Ct=document.createElement("button");Ct.className="zoom-btn",Ct.textContent="−",Ct.title="Zoom out",Ct.addEventListener("click",()=>{const f=o.clientWidth/2,k=o.clientHeight/2,[B,D]=Re(f,k);i.scale=Math.max(r.zoomMin,i.scale/r.zoomFactor),i.x=B-f/i.scale,i.y=D-k/i.scale,h()});const bt=document.createElement("button");bt.className="zoom-btn",bt.textContent="○",bt.title="Reset zoom",bt.addEventListener("click",()=>{if(c){if(i={x:0,y:0,scale:1},c.nodes.length>0){let f=1/0,k=1/0,B=-1/0,D=-1/0;for(const O of c.nodes)O.x<f&&(f=O.x),O.y<k&&(k=O.y),O.x>B&&(B=O.x),O.y>D&&(D=O.y);const H=(f+B)/2,z=(k+D)/2;i.x=H-o.clientWidth/2,i.y=z-o.clientHeight/2}h()}}),gt.appendChild(yt),gt.appendChild(bt),gt.appendChild(Ct),t.appendChild(gt);const De=document.createElement("div");De.className="node-tooltip",De.style.display="none",t.appendChild(De);let It=null,ot=null;return o.addEventListener("mousemove",f=>{if(Y!=="idle"&&Y!=="pending"){De.style.display!=="none"&&(De.style.display="none",It=null);return}const k=o.getBoundingClientRect(),B=f.clientX-k.left,D=f.clientY-k.top,H=et(B,D),z=(H==null?void 0:H.id)??null;z!==It?(It=z,De.style.display="none",ot&&clearTimeout(ot),ot=null,z&&H&&(ot=setTimeout(()=>{if(!c||!te)return;const O=c.edges.filter(J=>J.sourceId===z||J.targetId===z).length;De.textContent=`${H.label} · ${H.type} · ${O} edge${O!==1?"s":""}`,De.style.left=`${f.clientX-k.left+12}px`,De.style.top=`${f.clientY-k.top-8}px`,De.style.display="block"},200))):z&&De.style.display==="block"&&(De.style.left=`${f.clientX-k.left+12}px`,De.style.top=`${f.clientY-k.top-8}px`)}),o.addEventListener("mouseleave",()=>{De.style.display="none",It=null,ot&&clearTimeout(ot),ot=null}),{loadGraph(f){if(cancelAnimationFrame(M),w&&w.postMessage({type:"stop"}),Ao(),te=f,G=null,Ce=null,se=null,E=performance.now(),c=Ht(f),b.rebuild(c.nodes),I=1,x=new Set,F=null,pe.clear(),Y="idle",Z=[],U=null,i={x:0,y:0,scale:1},c.nodes.length>0){let B=1/0,D=1/0,H=-1/0,z=-1/0;for(const fe of c.nodes)fe.x<B&&(B=fe.x),fe.y<D&&(D=fe.y),fe.x>H&&(H=fe.x),fe.y>z&&(z=fe.y);const O=(B+H)/2,J=(D+z)/2,Q=o.clientWidth,re=o.clientHeight;i.x=O-Q/2,i.y=J-re/2}N=f.nodes.length>=T;const k=N?L():null;k?k.postMessage({type:"start",data:f}):(N=!1,j())},setFilteredNodeIds(f){F=f,h()},releaseAllPins(){if(!c)return!1;let f=!1;for(const k of c.nodes)k.pinned&&(f=!0,k.pinned=!1);return pe.clear(),Y="idle",Z=[],U=null,f&&(N&&w?w.postMessage({type:"unpin",ids:"all"}):(I=Math.max(I,.5),M||j()),h()),f},hasPinnedNodes(){if(!c)return!1;for(const f of c.nodes)if(f.pinned)return!0;return!1},clearSelection(){x.size!==0&&(x.clear(),e==null||e(null),h())},getSelectedNodeIds(){return[...x]},panToNode(f){this.panToNodes([f])},panToNodes(f){if(!c||f.length===0)return;const k=f.map(H=>c.nodeMap.get(H)).filter(Boolean);if(k.length===0)return;x=new Set(f),e==null||e(f);const B=o.clientWidth,D=o.clientHeight;if(k.length===1)ue={x:i.x,y:i.y,time:performance.now()},ce={x:k[0].x-B/(2*i.scale),y:k[0].y-D/(2*i.scale)};else{let H=1/0,z=1/0,O=-1/0,J=-1/0;for(const Be of k)Be.x<H&&(H=Be.x),Be.y<z&&(z=Be.y),Be.x>O&&(O=Be.x),Be.y>J&&(J=Be.y);const Q=Ue*4,re=O-H+Q*2,fe=J-z+Q*2,ke=Math.min(B/re,D/fe,i.scale);i.scale=ke;const Se=(H+O)/2,Te=(z+J)/2;ue={x:i.x,y:i.y,time:performance.now()},ce={x:Se-B/(2*i.scale),y:Te-D/(2*i.scale)}}mt()},setEdges(f){W=f,h()},setEdgeLabels(f){V=f,h()},setTypeHulls(f){_=f,h()},setMinimap(f){X=f,h()},centerView(){R()},panBy(f,k){i.x+=f/i.scale,i.y+=k/i.scale,h()},zoomBy(f){const k=o.clientWidth/2,B=o.clientHeight/2,[D,H]=Re(k,B);i.scale=Math.max(r.zoomMin,Math.min(r.zoomMax,i.scale*f)),i.x=D-k/i.scale,i.y=H-B/i.scale,h()},reheat(){N&&w?w.postMessage({type:"params",params:wt()}):(I=.5,cancelAnimationFrame(M),j())},exportImage(f){if(!c)return"";const k=o.width,B=o.height;if(f==="png"){const O=document.createElement("canvas");O.width=k,O.height=B;const J=O.getContext("2d");return J.fillStyle=we("--bg")||"#141414",J.fillRect(0,0,k,B),J.drawImage(o,0,0),Gn(J,k,B),O.toDataURL("image/png")}const D=o.toDataURL("image/png"),H=Math.max(16,Math.round(k/80)),z=`<svg xmlns="http://www.w3.org/2000/svg" width="${k}" height="${B}">
|
|
3
3
|
<image href="${D}" width="${k}" height="${B}"/>
|
|
4
4
|
<text x="${k-20}" y="${B-16}" text-anchor="end" font-family="system-ui, sans-serif" font-size="${H}" fill="#ffffff" opacity="0.4">backpackontology.com</text>
|
package/dist/app/index.html
CHANGED
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
<meta charset="UTF-8" />
|
|
5
5
|
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
|
6
6
|
<title>Backpack Viewer</title>
|
|
7
|
-
<script type="module" crossorigin src="/assets/index-
|
|
7
|
+
<script type="module" crossorigin src="/assets/index-o1FBgY0r.js"></script>
|
|
8
8
|
<link rel="stylesheet" crossorigin href="/assets/index-Cab62Pxr.css">
|
|
9
9
|
</head>
|
|
10
10
|
<body>
|
|
@@ -1,8 +1,8 @@
|
|
|
1
|
-
const
|
|
2
|
-
let g =
|
|
3
|
-
const
|
|
1
|
+
const P = "https://app.backpackontology.com";
|
|
2
|
+
let g = P, L = `${g}/.well-known/oauth-authorization-server`;
|
|
3
|
+
const R = new Uint8Array([66, 80, 65, 75]), I = 1;
|
|
4
4
|
let m = null;
|
|
5
|
-
async function
|
|
5
|
+
async function W(t) {
|
|
6
6
|
const e = await t.settings.get("relay_url");
|
|
7
7
|
e && (g = e, L = `${g}/.well-known/oauth-authorization-server`), t.registerTaskbarIcon({
|
|
8
8
|
label: "Share",
|
|
@@ -27,11 +27,11 @@ function B(t) {
|
|
|
27
27
|
onClose: () => {
|
|
28
28
|
m = null;
|
|
29
29
|
}
|
|
30
|
-
})),
|
|
30
|
+
})), w(t, s);
|
|
31
31
|
}
|
|
32
|
-
async function
|
|
32
|
+
async function w(t, e) {
|
|
33
33
|
const s = await t.settings.get("relay_token");
|
|
34
|
-
e.replaceChildren(), s ?
|
|
34
|
+
e.replaceChildren(), s ? F(t, e, s) : O(t, e);
|
|
35
35
|
}
|
|
36
36
|
function O(t, e) {
|
|
37
37
|
const s = document.createElement("div");
|
|
@@ -41,7 +41,7 @@ function O(t, e) {
|
|
|
41
41
|
const r = document.createElement("p");
|
|
42
42
|
r.textContent = "Encrypt your graph and get a shareable link. Recipients open it in their browser — no install needed.", s.appendChild(r);
|
|
43
43
|
const o = document.createElement("button");
|
|
44
|
-
o.className = "share-cta-btn", o.textContent = "Sign in to share", o.addEventListener("click", () =>
|
|
44
|
+
o.className = "share-cta-btn", o.textContent = "Sign in to share", o.addEventListener("click", () => M(t, e)), s.appendChild(o);
|
|
45
45
|
const a = document.createElement("button");
|
|
46
46
|
a.className = "share-token-link", a.textContent = "Or paste an API token", a.addEventListener("click", () => D(t, e)), s.appendChild(a);
|
|
47
47
|
const c = document.createElement("p");
|
|
@@ -59,12 +59,12 @@ function D(t, e) {
|
|
|
59
59
|
const a = document.createElement("button");
|
|
60
60
|
a.className = "share-btn-primary", a.textContent = "Save", a.addEventListener("click", async () => {
|
|
61
61
|
const i = r.value.trim();
|
|
62
|
-
i && (await t.settings.set("relay_token", i),
|
|
62
|
+
i && (await t.settings.set("relay_token", i), w(t, e));
|
|
63
63
|
}), o.appendChild(a);
|
|
64
64
|
const c = document.createElement("button");
|
|
65
|
-
c.className = "share-btn-secondary", c.textContent = "Back", c.addEventListener("click", () =>
|
|
65
|
+
c.className = "share-btn-secondary", c.textContent = "Back", c.addEventListener("click", () => w(t, e)), o.appendChild(c), s.appendChild(o), e.replaceChildren(s);
|
|
66
66
|
}
|
|
67
|
-
async function
|
|
67
|
+
async function j(t) {
|
|
68
68
|
try {
|
|
69
69
|
const e = await fetch(`${g}/api/graphs`, {
|
|
70
70
|
headers: { Authorization: `Bearer ${t}` }
|
|
@@ -77,17 +77,52 @@ async function F(t) {
|
|
|
77
77
|
return { graphs: [], error: e.message };
|
|
78
78
|
}
|
|
79
79
|
}
|
|
80
|
-
async function
|
|
80
|
+
async function F(t, e, s) {
|
|
81
81
|
const n = t.getGraphName(), r = document.createElement("div");
|
|
82
82
|
r.className = "share-loading", r.textContent = "Checking account…", e.replaceChildren(r);
|
|
83
|
-
const o = await
|
|
83
|
+
const o = await j(s);
|
|
84
84
|
if (o.error === "unauthorized") {
|
|
85
|
-
await t.settings.remove("relay_token"),
|
|
85
|
+
await t.settings.remove("relay_token"), w(t, e);
|
|
86
86
|
return;
|
|
87
87
|
}
|
|
88
88
|
e.replaceChildren();
|
|
89
89
|
const a = o.graphs.find((c) => c.name === n);
|
|
90
|
-
a ? z(t, e, s, a) : Y(t, e, s);
|
|
90
|
+
a && a.source === "cloud" ? G(t, e, s) : a ? z(t, e, s, a) : Y(t, e, s);
|
|
91
|
+
}
|
|
92
|
+
function G(t, e, s) {
|
|
93
|
+
const n = document.createElement("div");
|
|
94
|
+
n.className = "share-form";
|
|
95
|
+
const r = document.createElement("p");
|
|
96
|
+
r.className = "share-description", r.textContent = "Share this graph with a link. No sync needed — this graph lives in the cloud.", n.appendChild(r);
|
|
97
|
+
const o = document.createElement("button");
|
|
98
|
+
o.className = "share-cta-btn", o.textContent = "Get share link", o.addEventListener("click", async () => {
|
|
99
|
+
o.disabled = !0, o.textContent = "Creating link…";
|
|
100
|
+
try {
|
|
101
|
+
await V(t, e, s);
|
|
102
|
+
} catch (a) {
|
|
103
|
+
o.disabled = !1, o.textContent = "Get share link", N(n), C(n, a.message);
|
|
104
|
+
}
|
|
105
|
+
}), n.appendChild(o), x(t, e, n);
|
|
106
|
+
}
|
|
107
|
+
async function V(t, e, s) {
|
|
108
|
+
const n = t.getGraphName();
|
|
109
|
+
if (!n) throw new Error("No graph loaded");
|
|
110
|
+
const r = await A(s, `${g}/api/graphs/${encodeURIComponent(n)}/share`, {
|
|
111
|
+
method: "POST"
|
|
112
|
+
});
|
|
113
|
+
if (!r.ok) {
|
|
114
|
+
if (r.status === 401)
|
|
115
|
+
throw await t.settings.remove("relay_token"), new Error("Session expired. Please sign in again.");
|
|
116
|
+
let a = `Share failed (${r.status})`;
|
|
117
|
+
try {
|
|
118
|
+
const c = await r.json();
|
|
119
|
+
c.error && (a = c.error);
|
|
120
|
+
} catch {
|
|
121
|
+
}
|
|
122
|
+
throw new Error(a);
|
|
123
|
+
}
|
|
124
|
+
const o = await r.json();
|
|
125
|
+
v(e, o.url, !1, o.expires_at);
|
|
91
126
|
}
|
|
92
127
|
function z(t, e, s, n) {
|
|
93
128
|
const r = document.createElement("div");
|
|
@@ -103,9 +138,9 @@ function z(t, e, s, n) {
|
|
|
103
138
|
c.className = "share-cta-btn", c.textContent = "Update & Share", c.addEventListener("click", async () => {
|
|
104
139
|
c.disabled = !0, c.textContent = n.encrypted ? "Encrypting…" : "Syncing…";
|
|
105
140
|
try {
|
|
106
|
-
await
|
|
141
|
+
await T(t, e, s, n.encrypted);
|
|
107
142
|
} catch (d) {
|
|
108
|
-
c.disabled = !1, c.textContent = "Update & Share", N(r),
|
|
143
|
+
c.disabled = !1, c.textContent = "Update & Share", N(r), C(r, d.message);
|
|
109
144
|
}
|
|
110
145
|
}), r.appendChild(c);
|
|
111
146
|
const i = document.createElement("a");
|
|
@@ -120,21 +155,21 @@ function Y(t, e, s) {
|
|
|
120
155
|
o.className = "share-cta-btn", o.textContent = "Sync & Share", o.addEventListener("click", async () => {
|
|
121
156
|
o.disabled = !0, o.textContent = "Encrypting…";
|
|
122
157
|
try {
|
|
123
|
-
await
|
|
158
|
+
await T(t, e, s, !0);
|
|
124
159
|
} catch (c) {
|
|
125
160
|
o.disabled = !1, o.textContent = "Sync & Share";
|
|
126
161
|
const i = c.message;
|
|
127
162
|
if (i.includes("encrypted") && i.includes("limit")) {
|
|
128
|
-
|
|
163
|
+
K(t, e, s);
|
|
129
164
|
return;
|
|
130
165
|
}
|
|
131
|
-
N(n),
|
|
166
|
+
N(n), C(n, i);
|
|
132
167
|
}
|
|
133
168
|
}), n.appendChild(o);
|
|
134
169
|
const a = document.createElement("p");
|
|
135
170
|
a.className = "share-trust", a.textContent = "Your first encrypted graph is free. Data is encrypted before upload — we can’t read it.", n.appendChild(a), x(t, e, n);
|
|
136
171
|
}
|
|
137
|
-
function
|
|
172
|
+
function K(t, e, s) {
|
|
138
173
|
const n = document.createElement("div");
|
|
139
174
|
n.className = "share-quota";
|
|
140
175
|
const r = document.createElement("h4");
|
|
@@ -161,9 +196,9 @@ function j(t, e, s) {
|
|
|
161
196
|
}), h.addEventListener("click", async () => {
|
|
162
197
|
h.disabled = !0, h.textContent = "Syncing…";
|
|
163
198
|
try {
|
|
164
|
-
await
|
|
199
|
+
await T(t, e, s, !1, "public");
|
|
165
200
|
} catch (f) {
|
|
166
|
-
h.disabled = !1, h.textContent = "Share as public graph", N(n),
|
|
201
|
+
h.disabled = !1, h.textContent = "Share as public graph", N(n), C(n, f.message);
|
|
167
202
|
}
|
|
168
203
|
}), n.appendChild(h), x(t, e, n);
|
|
169
204
|
}
|
|
@@ -172,27 +207,27 @@ function x(t, e, s) {
|
|
|
172
207
|
n.className = "share-footer";
|
|
173
208
|
const r = document.createElement("button");
|
|
174
209
|
r.className = "share-token-link", r.textContent = "Sign out", r.addEventListener("click", async () => {
|
|
175
|
-
await t.settings.remove("relay_token"),
|
|
210
|
+
await t.settings.remove("relay_token"), w(t, e);
|
|
176
211
|
}), n.appendChild(r), s.appendChild(n), e.replaceChildren(s);
|
|
177
212
|
}
|
|
178
213
|
function N(t) {
|
|
179
214
|
for (const e of t.querySelectorAll(".share-error")) e.remove();
|
|
180
215
|
}
|
|
181
|
-
function
|
|
216
|
+
function C(t, e) {
|
|
182
217
|
const s = document.createElement("p");
|
|
183
218
|
s.className = "share-error", s.textContent = e, t.appendChild(s);
|
|
184
219
|
}
|
|
185
|
-
async function
|
|
220
|
+
async function M(t, e) {
|
|
186
221
|
try {
|
|
187
|
-
const n = await (await fetch(L)).json(), o = await (await fetch(n.registration_endpoint, { method: "POST" })).json(), a =
|
|
222
|
+
const n = await (await fetch(L)).json(), o = await (await fetch(n.registration_endpoint, { method: "POST" })).json(), a = q(), c = await Q(a), i = window.location.origin + "/oauth/callback", d = crypto.randomUUID(), l = new URL(n.authorization_endpoint);
|
|
188
223
|
l.searchParams.set("client_id", o.client_id), l.searchParams.set("redirect_uri", i), l.searchParams.set("response_type", "code"), l.searchParams.set("code_challenge", c), l.searchParams.set("code_challenge_method", "S256"), l.searchParams.set("state", d), l.searchParams.has("scope") || l.searchParams.set("scope", "openid email profile offline_access"), sessionStorage.setItem("share_oauth_state", d), sessionStorage.setItem("share_oauth_token_endpoint", n.token_endpoint), sessionStorage.setItem("share_oauth_client_id", o.client_id), sessionStorage.setItem("share_oauth_code_verifier", a), sessionStorage.setItem("share_oauth_redirect_uri", i);
|
|
189
224
|
const u = window.open(l.toString(), "backpack-share-auth", "width=500,height=700"), p = async (h) => {
|
|
190
|
-
var
|
|
191
|
-
if (((
|
|
225
|
+
var b;
|
|
226
|
+
if (((b = h.data) == null ? void 0 : b.type) !== "backpack-oauth-callback") return;
|
|
192
227
|
window.removeEventListener("message", p);
|
|
193
228
|
const { code: f, returnedState: _ } = h.data;
|
|
194
229
|
if (_ === d) {
|
|
195
|
-
|
|
230
|
+
J();
|
|
196
231
|
try {
|
|
197
232
|
const y = await (await fetch(n.token_endpoint, {
|
|
198
233
|
method: "POST",
|
|
@@ -200,66 +235,66 @@ async function G(t, e) {
|
|
|
200
235
|
body: new URLSearchParams({ grant_type: "authorization_code", code: f, redirect_uri: i, client_id: o.client_id, code_verifier: a }).toString()
|
|
201
236
|
})).json();
|
|
202
237
|
if (!y.access_token) {
|
|
203
|
-
|
|
238
|
+
C(e, "Token exchange failed: no access token returned.");
|
|
204
239
|
return;
|
|
205
240
|
}
|
|
206
|
-
await t.settings.set("relay_token", y.access_token),
|
|
241
|
+
await t.settings.set("relay_token", y.access_token), w(t, e);
|
|
207
242
|
} catch (S) {
|
|
208
|
-
|
|
243
|
+
C(e, `Token exchange failed: ${S.message}`);
|
|
209
244
|
}
|
|
210
245
|
}
|
|
211
246
|
};
|
|
212
247
|
window.addEventListener("message", p), (!u || u.closed) && (window.location.href = l.toString());
|
|
213
248
|
} catch (s) {
|
|
214
|
-
|
|
249
|
+
C(e, `Auth failed: ${s.message}`);
|
|
215
250
|
}
|
|
216
251
|
}
|
|
217
|
-
async function
|
|
252
|
+
async function T(t, e, s, n, r = "private") {
|
|
218
253
|
const o = t.getGraph(), a = t.getGraphName();
|
|
219
254
|
if (!o || !a) throw new Error("No graph loaded");
|
|
220
255
|
const c = new TextEncoder().encode(JSON.stringify(o));
|
|
221
256
|
let i, d, l = "";
|
|
222
257
|
if (n) {
|
|
223
|
-
const y = await import("../index-B8_hkT8R.js"),
|
|
224
|
-
let k =
|
|
225
|
-
k || (k = await y.generateX25519Identity(),
|
|
226
|
-
const
|
|
227
|
-
|
|
258
|
+
const y = await import("../index-B8_hkT8R.js"), E = await t.settings.get("keys") || {};
|
|
259
|
+
let k = E[a];
|
|
260
|
+
k || (k = await y.generateX25519Identity(), E[a] = k, await t.settings.set("keys", E));
|
|
261
|
+
const $ = await y.identityToRecipient(k), U = new y.Encrypter();
|
|
262
|
+
U.addRecipient($), i = await U.encrypt(c), d = "age-v1", l = btoa(k).replace(/\+/g, "-").replace(/\//g, "_").replace(/=+$/, "");
|
|
228
263
|
} else
|
|
229
264
|
i = c, d = "plaintext";
|
|
230
|
-
const u = await
|
|
265
|
+
const u = await H(a, i, d, o), p = `${g}/api/graphs/${encodeURIComponent(a)}/sync${r === "public" ? "?visibility=public" : ""}`, h = await A(s, p, {
|
|
231
266
|
method: "PUT",
|
|
232
267
|
headers: { "Content-Type": "application/octet-stream" },
|
|
233
268
|
body: u
|
|
234
269
|
});
|
|
235
270
|
if (!h.ok) {
|
|
236
271
|
if (h.status === 401)
|
|
237
|
-
throw await t.settings.remove("relay_token"),
|
|
272
|
+
throw await t.settings.remove("relay_token"), w(t, e), new Error("Session expired. Please sign in again.");
|
|
238
273
|
let y = `Sync failed (${h.status})`;
|
|
239
274
|
try {
|
|
240
|
-
const
|
|
241
|
-
|
|
275
|
+
const E = await h.json();
|
|
276
|
+
E.error && (y = E.error);
|
|
242
277
|
} catch {
|
|
243
278
|
}
|
|
244
279
|
throw new Error(y);
|
|
245
280
|
}
|
|
246
281
|
const f = await t.settings.get("synced") || {};
|
|
247
282
|
f[a] || (f[a] = !0, await t.settings.set("synced", f));
|
|
248
|
-
const _ = await
|
|
283
|
+
const _ = await A(s, `${g}/api/graphs/${encodeURIComponent(a)}/share`, {
|
|
249
284
|
method: "POST"
|
|
250
285
|
});
|
|
251
286
|
if (!_.ok) {
|
|
252
|
-
|
|
287
|
+
v(e, null, n, void 0);
|
|
253
288
|
return;
|
|
254
289
|
}
|
|
255
|
-
const
|
|
256
|
-
|
|
290
|
+
const b = await _.json(), S = l ? `${b.url}#k=${l}` : b.url;
|
|
291
|
+
v(e, S, n, b.expires_at);
|
|
257
292
|
}
|
|
258
|
-
async function
|
|
293
|
+
async function A(t, e, s = {}) {
|
|
259
294
|
const n = new Headers(s.headers);
|
|
260
295
|
return n.set("Authorization", `Bearer ${t}`), fetch(e, { ...s, headers: n });
|
|
261
296
|
}
|
|
262
|
-
async function
|
|
297
|
+
async function H(t, e, s, n) {
|
|
263
298
|
const r = new Uint8Array(e).buffer, o = await crypto.subtle.digest("SHA-256", r), a = "sha256:" + Array.from(new Uint8Array(o)).map((h) => h.toString(16).padStart(2, "0")).join(""), c = /* @__PURE__ */ new Set();
|
|
264
299
|
for (const h of n.nodes) c.add(h.type);
|
|
265
300
|
const i = JSON.stringify({
|
|
@@ -275,9 +310,9 @@ async function K(t, e, s, n) {
|
|
|
275
310
|
new DataView(l).setUint32(0, d.length, !1);
|
|
276
311
|
const u = new Uint8Array(9 + d.length + e.length);
|
|
277
312
|
let p = 0;
|
|
278
|
-
return u.set(
|
|
313
|
+
return u.set(R, p), p += 4, u[p] = I, p += 1, u.set(new Uint8Array(l), p), p += 4, u.set(d, p), p += d.length, u.set(e, p), u;
|
|
279
314
|
}
|
|
280
|
-
function
|
|
315
|
+
function v(t, e, s, n) {
|
|
281
316
|
const r = document.createElement("div");
|
|
282
317
|
r.className = "share-success";
|
|
283
318
|
const o = document.createElement("h4");
|
|
@@ -312,17 +347,17 @@ function U(t, e, s, n) {
|
|
|
312
347
|
}
|
|
313
348
|
t.replaceChildren(r);
|
|
314
349
|
}
|
|
315
|
-
function
|
|
350
|
+
function J() {
|
|
316
351
|
sessionStorage.removeItem("share_oauth_state"), sessionStorage.removeItem("share_oauth_token_endpoint"), sessionStorage.removeItem("share_oauth_client_id"), sessionStorage.removeItem("share_oauth_code_verifier"), sessionStorage.removeItem("share_oauth_redirect_uri");
|
|
317
352
|
}
|
|
318
|
-
function
|
|
353
|
+
function q() {
|
|
319
354
|
const t = new Uint8Array(32);
|
|
320
355
|
return crypto.getRandomValues(t), btoa(String.fromCharCode(...t)).replace(/\+/g, "-").replace(/\//g, "_").replace(/=+$/, "");
|
|
321
356
|
}
|
|
322
|
-
async function
|
|
357
|
+
async function Q(t) {
|
|
323
358
|
const e = new TextEncoder().encode(t), s = new Uint8Array(e).buffer, n = await crypto.subtle.digest("SHA-256", s);
|
|
324
359
|
return btoa(String.fromCharCode(...new Uint8Array(n))).replace(/\+/g, "-").replace(/\//g, "_").replace(/=+$/, "");
|
|
325
360
|
}
|
|
326
361
|
export {
|
|
327
|
-
|
|
362
|
+
W as activate
|
|
328
363
|
};
|
package/package.json
CHANGED