backpack-viewer 0.7.0 → 0.7.2
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.
- package/dist/app/assets/{index-DFW3OKgJ.js → index-DERxFHor.js} +1 -1
- package/dist/app/index.html +1 -1
- package/dist/extensions/share/backpack-extension.json +20 -0
- package/dist/extensions/share/index-B-LFGJqd.js +4827 -0
- package/dist/extensions/share/src/index.js +199 -0
- package/dist/extensions/share/style.css +151 -0
- package/dist/extensions/share/vite.config.js +17 -0
- package/dist/server-api-routes.js +18 -0
- package/package.json +2 -2
|
@@ -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 It=(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 u of document.querySelectorAll('link[rel="modulepreload"]'))l(u);new MutationObserver(u=>{for(const r of u)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(u){const r={};return u.integrity&&(r.integrity=u.integrity),u.referrerPolicy&&(r.referrerPolicy=u.referrerPolicy),u.crossOrigin==="use-credentials"?r.credentials="include":u.crossOrigin==="anonymous"?r.credentials="omit":r.credentials="same-origin",r}function l(u){if(u.ep)return;u.ep=!0;const r=s(u);fetch(u.href,r)}})();const Zn="modulepreload",Qn=function(t){return"/"+t},hn={},eo=function(e,s,l){let u=Promise.resolve();if(s&&s.length>0){let d=function(g){return Promise.all(g.map(i=>Promise.resolve(i).then(a=>({status:"fulfilled",value:a}),a=>({status:"rejected",reason:a}))))};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"));u=d(s.map(g=>{if(g=Qn(g),g in hn)return;hn[g]=!0;const i=g.endsWith(".css"),a=i?'[rel="stylesheet"]':"";if(document.querySelector(`link[href="${g}"]${a}`))return;const M=document.createElement("link");if(M.rel=i?"stylesheet":Zn,i||(M.as="script"),M.crossOrigin="",M.href=g,n&&M.setAttribute("nonce",n),document.head.appendChild(M),i)return new Promise((T,x)=>{M.addEventListener("load",T),M.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 u.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 Mt(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 Ot(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 u=await l.json().catch(()=>({}));throw new Error(u.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,u){const r=await fetch(`/api/graphs/${encodeURIComponent(t)}/snippets`,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({label:e,description:u,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 Zt(){var e;(e=document.querySelector(`.${Cn}`))==null||e.remove();const t=document.createElement("div");return t.className=Cn,document.body.appendChild(t),t}function Qt(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",u=>{u.target===t&&t.remove()}),s}function en(t,e){const s=document.createElement("div");s.className="bp-dialog-buttons";for(const l of e){const u=document.createElement("button");u.className="bp-dialog-btn",l.accent&&u.classList.add("bp-dialog-btn-accent"),l.danger&&u.classList.add("bp-dialog-btn-danger"),u.textContent=l.label,u.addEventListener("click",l.onClick),s.appendChild(u)}t.appendChild(s)}function jn(t,e){return new Promise(s=>{var d;const l=Zt(),u=Qt(l,t),r=document.createElement("p");r.className="bp-dialog-message",r.textContent=e,u.appendChild(r),en(u,[{label:"Cancel",onClick:()=>{l.remove(),s(!1)}},{label:"Confirm",accent:!0,onClick:()=>{l.remove(),s(!0)}}]),(d=u.querySelector(".bp-dialog-btn-accent"))==null||d.focus()})}function Bt(t,e,s){return new Promise(l=>{const u=Zt(),r=Qt(u,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();u.remove(),l(n||null)};d.addEventListener("keydown",n=>{n.key==="Enter"&&o(),n.key==="Escape"&&(u.remove(),l(null))}),en(r,[{label:"Cancel",onClick:()=>{u.remove(),l(null)}},{label:"OK",accent:!0,onClick:o}]),d.focus(),d.select()})}function mo(){return new Promise(t=>{const e=Zt(),s=Qt(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 u=document.createElement("label");u.className="bp-dialog-label",u.textContent="Path",s.appendChild(u);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 a=document.createElement("input");a.type="checkbox",a.id="bp-dialog-activate",a.checked=!0;const M=document.createElement("label");M.htmlFor="bp-dialog-activate",M.textContent="Switch to this backpack after registering",i.appendChild(a),i.appendChild(M),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,z,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=(z=F[0]).webkitGetAsEntry)==null?void 0:X.call(z);W!=null&&W.isDirectory&&(g.textContent=`Dropped "${W.name}" — paste the absolute path to it below.`)});const T=()=>{const x=d.value.trim();x&&(e.remove(),t({path:x,activate:a.checked}))};d.addEventListener("keydown",x=>{x.key==="Enter"&&T(),x.key==="Escape"&&(e.remove(),t(null))}),en(s,[{label:"Cancel",onClick:()=>{e.remove(),t(null)}},{label:"Register",accent:!0,onClick:T}]),d.focus()})}function wt(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 vn="http://www.w3.org/2000/svg";function ct(t,e){const s=document.createElementNS(vn,"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 u of e){const r=document.createElementNS(vn,u.tag);for(const[d,o]of Object.entries(u.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 bn(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 u=document.createElement("input");u.type="text",u.placeholder="Filter...",u.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 a=document.createElement("span");a.className="sidebar-version",a.textContent="v0.7.0",n.append(g,i,a);const M=document.createElement("button");M.className="sidebar-collapse-btn",M.title="Toggle sidebar (Tab)",M.appendChild(ct({size:14},[{tag:"polyline",attrs:{points:"11 17 6 12 11 7"}},{tag:"polyline",attrs:{points:"18 17 13 12 18 7"}}]));let T=!1;function x(){T=!T,t.classList.toggle("sidebar-collapsed",T),ye.classList.toggle("hidden",!T)}M.addEventListener("click",x);const F=document.createElement("div");F.className="sidebar-heading-row",F.appendChild(l),F.appendChild(M),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 z=document.createElement("span");z.className="backpack-picker-dot";const X=document.createElement("span");X.className="backpack-picker-name",X.textContent="...";const H=document.createElement("span");H.className="backpack-picker-caret",H.textContent="▾",V.appendChild(z),V.appendChild(X),V.appendChild(H);const K=document.createElement("div");K.className="backpack-picker-dropdown",K.hidden=!0,K.setAttribute("role","listbox");const q=document.createElement("div");q.className="backpack-picker-container",q.appendChild(V),q.appendChild(K),t.appendChild(q);let ue=!1;function U(){ue=!1,K.hidden=!0,V.setAttribute("aria-expanded","false")}function de(){ue=!0,K.hidden=!1,V.setAttribute("aria-expanded","true")}V.addEventListener("click",p=>{p.stopPropagation(),ue?U():de()}),document.addEventListener("click",p=>{q.contains(p.target)||U()});let xe=[],ee=null;function G(){K.replaceChildren();for(const v of xe){const m=document.createElement("button");m.className="backpack-picker-item",m.type="button",m.setAttribute("role","option"),v.active&&m.classList.add("active");const b=document.createElement("span");b.className="backpack-picker-item-dot",b.style.setProperty("--backpack-color",v.color);const L=document.createElement("span");L.className="backpack-picker-item-name",L.textContent=v.name;const h=document.createElement("span");h.className="backpack-picker-item-path",h.textContent=v.path,m.appendChild(b),m.appendChild(L),m.appendChild(h),m.addEventListener("click",S=>{S.stopPropagation(),U(),!v.active&&s.onBackpackSwitch&&s.onBackpackSwitch(v.name)}),K.appendChild(m)}const p=document.createElement("div");p.className="backpack-picker-divider",K.appendChild(p);const y=document.createElement("button");y.className="backpack-picker-item backpack-picker-add",y.type="button",y.textContent="+ Add new backpack…",y.addEventListener("click",async v=>{if(v.stopPropagation(),U(),!s.onBackpackRegister)return;const m=await mo();m&&s.onBackpackRegister(m.path,m.activate)}),K.appendChild(y)}const ye=document.createElement("button");ye.className="tools-pane-toggle hidden",ye.title="Show sidebar (Tab)",ye.appendChild(ct({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(u),t.appendChild(r),t.appendChild(d),t.appendChild(o),t.appendChild(n);let Ce=[],se=[],ge="";return u.addEventListener("input",()=>{const p=u.value.toLowerCase();for(const y of Ce){const v=y.dataset.name??"";y.style.display=v.includes(p)?"":"none"}for(const y of se){const v=y.dataset.name??"";y.style.display=v.includes(p)?"":"none"}}),{setStaleVersionBanner(p,y){W.replaceChildren();const v=document.createElement("div");v.className="sidebar-stale-banner-title",v.textContent=`Viewer ${p} is out of date`;const m=document.createElement("div");m.className="sidebar-stale-banner-subtitle",m.textContent=`Latest is ${y}. 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 It=(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 u of document.querySelectorAll('link[rel="modulepreload"]'))l(u);new MutationObserver(u=>{for(const r of u)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(u){const r={};return u.integrity&&(r.integrity=u.integrity),u.referrerPolicy&&(r.referrerPolicy=u.referrerPolicy),u.crossOrigin==="use-credentials"?r.credentials="include":u.crossOrigin==="anonymous"?r.credentials="omit":r.credentials="same-origin",r}function l(u){if(u.ep)return;u.ep=!0;const r=s(u);fetch(u.href,r)}})();const Zn="modulepreload",Qn=function(t){return"/"+t},hn={},eo=function(e,s,l){let u=Promise.resolve();if(s&&s.length>0){let d=function(g){return Promise.all(g.map(i=>Promise.resolve(i).then(a=>({status:"fulfilled",value:a}),a=>({status:"rejected",reason:a}))))};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"));u=d(s.map(g=>{if(g=Qn(g),g in hn)return;hn[g]=!0;const i=g.endsWith(".css"),a=i?'[rel="stylesheet"]':"";if(document.querySelector(`link[href="${g}"]${a}`))return;const M=document.createElement("link");if(M.rel=i?"stylesheet":Zn,i||(M.as="script"),M.crossOrigin="",M.href=g,n&&M.setAttribute("nonce",n),document.head.appendChild(M),i)return new Promise((T,x)=>{M.addEventListener("load",T),M.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 u.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 Mt(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 Ot(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 u=await l.json().catch(()=>({}));throw new Error(u.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,u){const r=await fetch(`/api/graphs/${encodeURIComponent(t)}/snippets`,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({label:e,description:u,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 Zt(){var e;(e=document.querySelector(`.${Cn}`))==null||e.remove();const t=document.createElement("div");return t.className=Cn,document.body.appendChild(t),t}function Qt(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",u=>{u.target===t&&t.remove()}),s}function en(t,e){const s=document.createElement("div");s.className="bp-dialog-buttons";for(const l of e){const u=document.createElement("button");u.className="bp-dialog-btn",l.accent&&u.classList.add("bp-dialog-btn-accent"),l.danger&&u.classList.add("bp-dialog-btn-danger"),u.textContent=l.label,u.addEventListener("click",l.onClick),s.appendChild(u)}t.appendChild(s)}function jn(t,e){return new Promise(s=>{var d;const l=Zt(),u=Qt(l,t),r=document.createElement("p");r.className="bp-dialog-message",r.textContent=e,u.appendChild(r),en(u,[{label:"Cancel",onClick:()=>{l.remove(),s(!1)}},{label:"Confirm",accent:!0,onClick:()=>{l.remove(),s(!0)}}]),(d=u.querySelector(".bp-dialog-btn-accent"))==null||d.focus()})}function Bt(t,e,s){return new Promise(l=>{const u=Zt(),r=Qt(u,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();u.remove(),l(n||null)};d.addEventListener("keydown",n=>{n.key==="Enter"&&o(),n.key==="Escape"&&(u.remove(),l(null))}),en(r,[{label:"Cancel",onClick:()=>{u.remove(),l(null)}},{label:"OK",accent:!0,onClick:o}]),d.focus(),d.select()})}function mo(){return new Promise(t=>{const e=Zt(),s=Qt(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 u=document.createElement("label");u.className="bp-dialog-label",u.textContent="Path",s.appendChild(u);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 a=document.createElement("input");a.type="checkbox",a.id="bp-dialog-activate",a.checked=!0;const M=document.createElement("label");M.htmlFor="bp-dialog-activate",M.textContent="Switch to this backpack after registering",i.appendChild(a),i.appendChild(M),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,z,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=(z=F[0]).webkitGetAsEntry)==null?void 0:X.call(z);W!=null&&W.isDirectory&&(g.textContent=`Dropped "${W.name}" — paste the absolute path to it below.`)});const T=()=>{const x=d.value.trim();x&&(e.remove(),t({path:x,activate:a.checked}))};d.addEventListener("keydown",x=>{x.key==="Enter"&&T(),x.key==="Escape"&&(e.remove(),t(null))}),en(s,[{label:"Cancel",onClick:()=>{e.remove(),t(null)}},{label:"Register",accent:!0,onClick:T}]),d.focus()})}function wt(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 vn="http://www.w3.org/2000/svg";function ct(t,e){const s=document.createElementNS(vn,"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 u of e){const r=document.createElementNS(vn,u.tag);for(const[d,o]of Object.entries(u.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 bn(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 u=document.createElement("input");u.type="text",u.placeholder="Filter...",u.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 a=document.createElement("span");a.className="sidebar-version",a.textContent="v0.7.2",n.append(g,i,a);const M=document.createElement("button");M.className="sidebar-collapse-btn",M.title="Toggle sidebar (Tab)",M.appendChild(ct({size:14},[{tag:"polyline",attrs:{points:"11 17 6 12 11 7"}},{tag:"polyline",attrs:{points:"18 17 13 12 18 7"}}]));let T=!1;function x(){T=!T,t.classList.toggle("sidebar-collapsed",T),ye.classList.toggle("hidden",!T)}M.addEventListener("click",x);const F=document.createElement("div");F.className="sidebar-heading-row",F.appendChild(l),F.appendChild(M),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 z=document.createElement("span");z.className="backpack-picker-dot";const X=document.createElement("span");X.className="backpack-picker-name",X.textContent="...";const H=document.createElement("span");H.className="backpack-picker-caret",H.textContent="▾",V.appendChild(z),V.appendChild(X),V.appendChild(H);const K=document.createElement("div");K.className="backpack-picker-dropdown",K.hidden=!0,K.setAttribute("role","listbox");const q=document.createElement("div");q.className="backpack-picker-container",q.appendChild(V),q.appendChild(K),t.appendChild(q);let ue=!1;function U(){ue=!1,K.hidden=!0,V.setAttribute("aria-expanded","false")}function de(){ue=!0,K.hidden=!1,V.setAttribute("aria-expanded","true")}V.addEventListener("click",p=>{p.stopPropagation(),ue?U():de()}),document.addEventListener("click",p=>{q.contains(p.target)||U()});let xe=[],ee=null;function G(){K.replaceChildren();for(const v of xe){const m=document.createElement("button");m.className="backpack-picker-item",m.type="button",m.setAttribute("role","option"),v.active&&m.classList.add("active");const b=document.createElement("span");b.className="backpack-picker-item-dot",b.style.setProperty("--backpack-color",v.color);const L=document.createElement("span");L.className="backpack-picker-item-name",L.textContent=v.name;const h=document.createElement("span");h.className="backpack-picker-item-path",h.textContent=v.path,m.appendChild(b),m.appendChild(L),m.appendChild(h),m.addEventListener("click",S=>{S.stopPropagation(),U(),!v.active&&s.onBackpackSwitch&&s.onBackpackSwitch(v.name)}),K.appendChild(m)}const p=document.createElement("div");p.className="backpack-picker-divider",K.appendChild(p);const y=document.createElement("button");y.className="backpack-picker-item backpack-picker-add",y.type="button",y.textContent="+ Add new backpack…",y.addEventListener("click",async v=>{if(v.stopPropagation(),U(),!s.onBackpackRegister)return;const m=await mo();m&&s.onBackpackRegister(m.path,m.activate)}),K.appendChild(y)}const ye=document.createElement("button");ye.className="tools-pane-toggle hidden",ye.title="Show sidebar (Tab)",ye.appendChild(ct({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(u),t.appendChild(r),t.appendChild(d),t.appendChild(o),t.appendChild(n);let Ce=[],se=[],ge="";return u.addEventListener("input",()=>{const p=u.value.toLowerCase();for(const y of Ce){const v=y.dataset.name??"";y.style.display=v.includes(p)?"":"none"}for(const y of se){const v=y.dataset.name??"";y.style.display=v.includes(p)?"":"none"}}),{setStaleVersionBanner(p,y){W.replaceChildren();const v=document.createElement("div");v.className="sidebar-stale-banner-title",v.textContent=`Viewer ${p} is out of date`;const m=document.createElement("div");m.className="sidebar-stale-banner-subtitle",m.textContent=`Latest is ${y}. 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(v),W.appendChild(m),W.appendChild(b),W.hidden=!1},setBackpacks(p){xe=p.slice();const y=p.find(v=>v.active)??null;ee=y,y&&(X.textContent=y.name,z.style.setProperty("--backpack-color",y.color),t.style.setProperty("--backpack-color",y.color)),G()},setActiveBackpack(p){ee=p,xe=xe.map(y=>({...y,active:y.name===p.name})),xe.some(y=>y.name===p.name)||xe.push({...p,active:!0}),X.textContent=p.name,z.style.setProperty("--backpack-color",p.color),t.style.setProperty("--backpack-color",p.color),G()},getActiveBackpack(){return ee},setSummaries(p){r.replaceChildren();const y=fetch("/api/locks").then(v=>v.json()).catch(()=>({}));Ce=p.map(v=>{const m=document.createElement("li");m.className="ontology-item",m.dataset.name=v.name;const b=document.createElement("span");b.className="name",b.textContent=v.name;const L=document.createElement("span");L.className="stats";const h=xn(v.nodeCount,v.edgeCount);L.textContent=`${v.nodeCount} nodes, ${v.edgeCount} edges · ~${bn(h)}`;const S=document.createElement("span");S.className="sidebar-branch",S.dataset.graph=v.name;const w=document.createElement("span");if(w.className="sidebar-lock-badge",w.dataset.graph=v.name,y.then(N=>{if(!w.isConnected)return;const I=N[v.name];I&&typeof I=="object"&&I.author&&(w.textContent=`editing: ${I.author}`,w.title=`Last activity: ${I.lastActivity??""}`,w.classList.add("active"))}),m.appendChild(b),m.appendChild(L),m.appendChild(w),m.appendChild(S),s.onRename){const N=document.createElement("button");N.className="sidebar-edit-btn",N.textContent="✎",N.title="Rename";const I=s.onRename;N.addEventListener("click",C=>{C.stopPropagation();const B=document.createElement("input");B.type="text",B.className="sidebar-rename-input",B.value=v.name,b.textContent="",b.appendChild(B),N.style.display="none",B.focus(),B.select();const $=()=>{const te=B.value.trim();te&&te!==v.name?I(v.name,te):(b.textContent=v.name,N.style.display="")};B.addEventListener("blur",$),B.addEventListener("keydown",te=>{te.key==="Enter"&&B.blur(),te.key==="Escape"&&(B.value=v.name,B.blur())})}),m.appendChild(N)}return m.addEventListener("click",()=>s.onSelect(v.name)),r.appendChild(m),m}),ge&&this.setActive(ge)},setActive(p){ge=p;for(const y of Ce)y.classList.toggle("active",y.dataset.name===p);for(const y of se)y.classList.toggle("active",y.dataset.name===p)},setRemotes(p){o.replaceChildren(),se=p.map(v=>{const m=document.createElement("li");m.className="ontology-item ontology-item-remote",m.dataset.name=v.name;const b=document.createElement("div");b.className="remote-name-row";const L=document.createElement("span");L.className="name",L.textContent=v.name;const h=document.createElement("span");h.className="remote-badge",h.textContent=v.pinned?"remote · pinned":"remote",h.title=`Source: ${v.source??v.url}`,b.appendChild(L),b.appendChild(h);const S=document.createElement("span");S.className="stats";const w=xn(v.nodeCount,v.edgeCount);S.textContent=`${v.nodeCount} nodes, ${v.edgeCount} edges · ~${bn(w)}`;const N=document.createElement("span");return N.className="remote-source",N.textContent=v.source??new URL(v.url).hostname,N.title=v.url,m.appendChild(b),m.appendChild(S),m.appendChild(N),m.addEventListener("click",()=>s.onSelect(v.name)),o.appendChild(m),m});const y=p.length>0;d.hidden=!y,o.hidden=!y,ge&&this.setActive(ge)},setActiveBranch(p,y,v){const m=r.querySelectorAll(`.sidebar-branch[data-graph="${p}"]`);for(const b of m){b.textContent=`/ ${y}`,b.title="Click to switch branch",b.style.cursor="pointer";const L=b.cloneNode(!0);b.replaceWith(L),L.addEventListener("click",h=>{h.stopPropagation(),be(p,L,v??[])})}},setSnippets(p,y){var b;const v=Ce.find(L=>L.dataset.name===p);if(!v||((b=v.querySelector(".sidebar-snippets"))==null||b.remove(),y.length===0))return;const m=document.createElement("div");m.className="sidebar-snippets";for(const L of y){const h=document.createElement("div");h.className="sidebar-snippet";const S=document.createElement("span");S.className="sidebar-snippet-label",S.textContent=`◆ ${L.label}`,S.title=`${L.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 I;N.stopPropagation(),(I=s.onSnippetDelete)==null||I.call(s,p,L.id)}),h.appendChild(S),h.appendChild(w),h.addEventListener("click",N=>{var I;N.stopPropagation(),(I=s.onSnippetLoad)==null||I.call(s,p,L.id)}),m.appendChild(h)}v.appendChild(m)},toggle:x,expandBtn:ye};function be(p,y,v){const m=t.querySelector(".branch-picker");m&&m.remove();const b=document.createElement("div");b.className="branch-picker";for(const h of v){const S=document.createElement("div");S.className="branch-picker-item",h.active&&S.classList.add("branch-picker-active");const w=document.createElement("span");if(w.textContent=h.name,S.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",I=>{I.stopPropagation(),jn("Delete branch",`Delete branch "${h.name}"?`).then(C=>{C&&(s.onBranchDelete(p,h.name),b.remove())})}),S.appendChild(N)}h.active||S.addEventListener("click",()=>{var N;(N=s.onBranchSwitch)==null||N.call(s,p,h.name),b.remove()}),b.appendChild(S)}if(s.onBranchCreate){const h=document.createElement("div");h.className="branch-picker-item branch-picker-create",h.textContent="+ New branch",h.addEventListener("click",()=>{Bt("New branch","Branch name").then(S=>{S&&(s.onBranchCreate(p,S),b.remove())})}),b.appendChild(h)}y.after(b);const L=h=>{b.contains(h.target)||(b.remove(),document.removeEventListener("click",L))};setTimeout(()=>document.addEventListener("click",L),0)}}function Gt(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,u=(t.y0+t.y1)/2;return(e<l?0:1)+(s<u?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 Vt(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 u=t.body;t.body=null,u.x===e.x&&u.y===e.y&&(e.x+=(Math.random()-.5)*.1,e.y+=(Math.random()-.5)*.1);const r=En(t,u.x,u.y);if(t.children[r]===null){const[d,o,n,g]=wn(t,r);t.children[r]=Gt(d,o,n,g)}Vt(t.children[r],u)}const s=En(t,e.x,e.y);if(t.children[s]===null){const[u,r,d,o]=wn(t,s);t.children[s]=Gt(u,r,d,o)}Vt(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,u=-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>u&&(u=i.y);const r=Math.max(l-e,u-s)*.1+50,d=(e+l)/2,o=(s+u)/2,n=Math.max(l-e,u-s)/2+r,g=Gt(d-n,o-n,d+n,o+n);for(const i of t)Vt(g,i);return g}function Co(t,e,s,l,u,r){zn(t,e,s,l,u,r)}function zn(t,e,s,l,u,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 a=l*u/(i*i),M=d/i*a,T=o/i*a;e.vx-=M,e.vy-=T}return}const g=t.x1-t.x0;if(g*g/n<s*s){let i=Math.sqrt(n);i<r&&(i=r);const a=l*t.mass*u/(i*i),M=d/i*a,T=o/i*a;e.vx-=M,e.vy-=T;return}for(let i=0;i<4;i++)t.children[i]!==null&&zn(t.children[i],e,s,l,u,r)}const _n={clusterStrength:.08,spacing:1.5},kn=6e3,vo=12e3,bo=.004,Hn=140,Yn=350,Sn=.9,Nn=.01,bt=30,Wt=50;let et={..._n};function lt(t){t.clusterStrength!==void 0&&(et.clusterStrength=t.clusterStrength),t.spacing!==void 0&&(et.spacing=t.spacing)}function Et(){return{...et}}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 u=new Set(e);for(let r=0;r<s;r++){const d=new Set;for(const o of t.edges)u.has(o.sourceId)&&!l.has(o.targetId)&&d.add(o.targetId),u.has(o.targetId)&&!l.has(o.sourceId)&&d.add(o.sourceId);for(const o of d)l.add(o);if(u=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 Ut(t){const e=new Map,s=[...new Set(t.nodes.map(n=>n.type))],l=Math.sqrt(s.length)*Yn*.6*Math.max(1,et.spacing),u=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),a=Math.cos(i)*l,M=Math.sin(i)*l,T=u.get(n.type)??0;u.set(n.type,T+1);const x=r.get(n.type)??1,F=2*Math.PI*T/x,W=Hn*.6,V={id:n.id,x:a+Math.cos(F)*W,y:M+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:u}=t,r=vo*et.spacing;if(s.length>=ko){const o=yo(s);if(o)for(const g of s)Co(o,g,wo,r,e,bt);const n=r-kn;if(n>0){const g=new Map;for(const i of s){let a=g.get(i.type);a||(a=[],g.set(i.type,a)),a.push(i)}for(const i of g.values())for(let a=0;a<i.length;a++)for(let M=a+1;M<i.length;M++){const T=i[a],x=i[M];let F=x.x-T.x,W=x.y-T.y,V=Math.sqrt(F*F+W*W);V<bt&&(V=bt);const z=n*e/(V*V),X=F/V*z,H=W/V*z;T.vx+=X,T.vy+=H,x.vx-=X,x.vy-=H}}}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 a=i.x-g.x,M=i.y-g.y,T=Math.sqrt(a*a+M*M);T<bt&&(T=bt);const F=(g.type===i.type?kn:r)*e/(T*T),W=a/T*F,V=M/T*F;g.vx-=W,g.vy-=V,i.vx+=W,i.vy+=V}for(const o of l){const n=u.get(o.sourceId),g=u.get(o.targetId);if(!n||!g)continue;const i=g.x-n.x,a=g.y-n.y,M=Math.sqrt(i*i+a*a);if(M===0)continue;const T=n.type===g.type?Hn*et.spacing:Yn*et.spacing,x=bo*(M-T)*e,F=i/M*x,W=a/M*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)*et.clusterStrength*e,o.vy+=(n.y-o.y)*et.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>Wt&&(o.vx=o.vx/n*Wt,o.vy=o.vy/n*Wt),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 u=0;u<t.length;u++)s=(s<<5)-s+t.charCodeAt(u)|0;const l=In[Math.abs(s)%In.length];return Mn.set(t,l),l}class No{constructor(e){It(this,"cells",new Map);It(this,"cellSize");It(this,"invCell");this.cellSize=e,this.invCell=1/e}key(e,s){const l=e+32768|0,u=s+32768|0;return l*73856093^u*19349663}clear(){this.cells.clear()}insert(e){const s=Math.floor(e.x*this.invCell),l=Math.floor(e.y*this.invCell),u=this.key(s,l),r=this.cells.get(u);r?r.push(e):this.cells.set(u,[e])}rebuild(e){this.cells.clear();for(const s of e)this.insert(s)}query(e,s,l){const u=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=u;for(let a=r;a<=d;a++)for(let M=o;M<=n;M++){const T=this.cells.get(this.key(a,M));if(T)for(const x of T){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),u=Math.ceil(l.width)+2,r=Math.ceil(l.actualBoundingBoxAscent+l.actualBoundingBoxDescent)+4,d=new OffscreenCanvas(u,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:u,height:r}}function An(t,e,s,l,u,r,d){const o=Io(e,u,r);let n=pt.get(o);if(!n){if(pt.size>=Lo){const a=pt.keys().next().value;a!==void 0&&pt.delete(a)}n=To(e,u,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 Ee(t){return getComputedStyle(document.documentElement).getPropertyValue(t).trim()}const Ue=20,jt=.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 Tt(t,e,s,l,u,r=100){const d=(t-s.x)*s.scale,o=(e-s.y)*s.scale;return d>=-r&&d<=l+r&&o>=-r&&o<=u+r}function Bo(t,e,s,l){const u={...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},a=null,M=1,T=0,x=new Set,F=null,W=!0,V=!0,z=!0,X=!0,H="idle",K=[],q=0,ue=0,U=null,de=new Set;const xe=5;let ee=null,G=null,ye=1,Ce=null,se=null,ge=null,be=!1,p=[],y=0,v=0;const m=400,b=new No(Ue*2);let L=0;function h(){ie(),L||(L=requestAnimationFrame(()=>{L=0,c()}))}const S=150;let w=null,N=!1;function I(){if(!w)try{w=new Worker(new URL("/assets/layout-worker-4xak23M6.js",import.meta.url),{type:"module"}),w.onmessage=C,w.onerror=()=>{N=!1,w=null,we()}}catch{return N=!1,null}return w}function C(f){const k=f.data;if(k.type==="tick"&&a){const P=k.positions,D=a.nodes;for(let _=0;_<D.length;_++)D[_].x=P[_*4],D[_].y=P[_*4+1],D[_].vx=P[_*4+2],D[_].vy=P[_*4+3];M=k.alpha,b.rebuild(D),c()}k.type==="settled"&&(M=0,be&&p.length>0&&!ae&&(ae=requestAnimationFrame(pe)))}let B=null,$=null,te=!0;function ie(){te=!0}let le=null,me=null;const ve=r.panAnimationMs;function je(){o.width=o.clientWidth*g,o.height=o.clientHeight*g,ie(),h()}const qe=new ResizeObserver(je);qe.observe(t),je();function Xe(f,k){return[f/i.scale+i.x,k/i.scale+i.y]}function Je(f,k){if(!a)return null;const[P,D]=Xe(f,k);return b.query(P,D,Ue)}function ut(){if(!U)return;n.save();const f=Math.min(U.x1,U.x2),k=Math.max(U.x1,U.x2),P=Math.min(U.y1,U.y2),D=Math.max(U.y1,U.y2);n.strokeStyle=Ee("--accent")||"#d4a27f",n.fillStyle=Ee("--accent")||"#d4a27f",n.globalAlpha=.12,n.fillRect(f,P,k-f,D-P),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,P,k-f,D-P),n.setLineDash([]),n.restore()}function mt(){if(!a)return;y+=d.pulseSpeed;const f=new Set(p);n.save(),n.setTransform(g,0,0,g,0,0),B&&(n.clearRect(0,0,o.clientWidth,o.clientHeight),n.drawImage(B,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=Ee("--canvas-walk-edge")||"#1a1a1a",P=[];for(const j of a.edges){if(!f.has(j.sourceId)||!f.has(j.targetId)||j.sourceId===j.targetId)continue;const O=a.nodeMap.get(j.sourceId),J=a.nodeMap.get(j.targetId);!O||!J||P.push(O.x,O.y,J.x,J.y)}if(P.length>0){n.beginPath();for(let j=0;j<P.length;j+=4)n.moveTo(P[j],P[j+1]),n.lineTo(P[j+2],P[j+3]);n.strokeStyle=k,n.lineWidth=3,n.globalAlpha=.5+.5*Math.sin(y),n.stroke(),n.globalAlpha=1}const D=i.scale<u.smallNodes?Ue*.5:Ue,_=Ee("--accent")||"#d4a27f";for(const j of p){const O=a.nodeMap.get(j);if(!O||!Tt(O.x,O.y,i,o.clientWidth,o.clientHeight))continue;const J=j===p[p.length-1],Z=.5+.5*Math.sin(y);n.strokeStyle=_,n.lineWidth=J?3:2,n.globalAlpha=J?.5+.5*Z:.3+.4*Z,n.beginPath(),n.arc(O.x,O.y,D+(J?6:4),0,Math.PI*2),n.stroke()}n.globalAlpha=1,ut(),n.restore(),X&&a.nodes.length>1&&E(),n.restore()}function c(){var ln;if(!a){n.clearRect(0,0,o.width,o.height);return}if(!te&&B&&be&&p.length>0&&M<jt){mt();return}const f=M<jt&&be&&p.length>0;be&&p.length>0&&(y+=d.pulseSpeed);const k=be&&!f?new Set(p):null,P=Ee("--canvas-edge"),D=Ee("--canvas-edge-highlight"),_=Ee("--canvas-edge-dim"),j=Ee("--canvas-edge-label"),O=Ee("--canvas-edge-label-highlight"),J=Ee("--canvas-edge-label-dim"),Z=Ee("--canvas-arrow"),re=Ee("--canvas-arrow-highlight"),fe=Ee("--canvas-node-label"),ke=Ee("--canvas-node-label-dim"),Se=Ee("--canvas-type-badge"),Te=Ee("--canvas-type-badge-dim"),Re=Ee("--canvas-selection-border"),ze=Ee("--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),z&&i.scale>=u.smallNodes){const Q=new Map;for(const Pe of a.nodes){if(F!==null&&!F.has(Pe.id))continue;const Fe=Q.get(Pe.type)??[];Fe.push(Pe),Q.set(Pe.type,Fe)}for(const[Pe,Fe]of Q){if(Fe.length<2)continue;const at=Ae(Pe),ot=Ue*2.5;let Ye=1/0,Ve=1/0,Be=-1/0,Qe=-1/0;for(const We of Fe)We.x<Ye&&(Ye=We.x),We.y<Ve&&(Ve=We.y),We.x>Be&&(Be=We.x),We.y>Qe&&(Qe=We.y);n.beginPath();const oe=(Be-Ye)/2+ot,Me=(Qe-Ve)/2+ot,Ne=(Ye+Be)/2,_e=(Ve+Qe)/2;n.ellipse(Ne,_e,oe,Me,0,0,Math.PI*2),n.fillStyle=at,n.globalAlpha=.05,n.fill(),n.strokeStyle=at,n.globalAlpha=.12,n.lineWidth=1,n.setLineDash([4,4]),n.stroke(),n.setLineDash([]),n.globalAlpha=1}}let Ge=null;if(x.size>0){Ge=new Set;for(const Q of a.edges)x.has(Q.sourceId)&&Ge.add(Q.targetId),x.has(Q.targetId)&&Ge.add(Q.sourceId)}const nt=Ee("--accent")||"#d4a27f",He=Ee("--canvas-walk-edge")||"#1a1a1a",it=i.scale>=u.hideArrows,Nt=V&&i.scale>=u.hideEdgeLabels;if(W){const Q=[],Pe=[],Fe=[],at=[],ot=[],Ye=[];for(const oe of a.edges){const Me=a.nodeMap.get(oe.sourceId),Ne=a.nodeMap.get(oe.targetId);if(!Me||!Ne||!Tt(Me.x,Me.y,i,o.clientWidth,o.clientHeight,200)&&!Tt(Ne.x,Ne.y,i,o.clientWidth,o.clientHeight,200))continue;const _e=F===null||F.has(oe.sourceId),We=F===null||F.has(oe.targetId),rn=_e&&We;if(F!==null&&!_e&&!We)continue;const Dt=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?ee==null?void 0:ee.edges.find(Lt=>Lt.sourceId===oe.sourceId&&Lt.targetId===oe.targetId||Lt.targetId===oe.sourceId&&Lt.sourceId===oe.targetId):null,mn=!!(ge&&un&&ge.edgeIds.has(un.id));if(oe.sourceId===oe.targetId){Y(Me,oe.type,Dt,P,D,j,O);continue}(mn?ot:pn?at:Dt?Pe:dn?Fe:Q).push(Me.x,Me.y,Ne.x,Ne.y),(it||Nt)&&Ye.push({sx:Me.x,sy:Me.y,tx:Ne.x,ty:Ne.y,type:oe.type,highlighted:Dt,edgeDimmed:dn,isPathEdge:mn,isWalkEdge:pn})}const Ve=it?1.5:1,Qe=[{lines:Q,color:P,width:Ve,alpha:1},{lines:Fe,color:_,width:Ve,alpha:1},{lines:Pe,color:D,width:it?2.5:1,alpha:1},{lines:ot,color:nt,width:3,alpha:1},{lines:at,color:He,width:3,alpha:.5+.5*Math.sin(y)}];for(const oe of Qe)if(oe.lines.length!==0){n.beginPath();for(let Me=0;Me<oe.lines.length;Me+=4)n.moveTo(oe.lines[Me],oe.lines[Me+1]),n.lineTo(oe.lines[Me+2],oe.lines[Me+3]);n.strokeStyle=oe.color,n.lineWidth=oe.width,n.globalAlpha=oe.alpha,n.stroke()}n.globalAlpha=1;for(const oe of Ye)if(it&&R(oe.sx,oe.sy,oe.tx,oe.ty,oe.highlighted||oe.isPathEdge,Z,re),Nt){const Me=(oe.sx+oe.tx)/2,Ne=(oe.sy+oe.ty)/2;n.fillStyle=oe.highlighted?O:oe.edgeDimmed?J:j,n.font="9px system-ui, sans-serif",n.textAlign="center",n.textBaseline="bottom",n.fillText(oe.type,Me,Ne-4)}}const Ft=performance.now()-v,Ie=Math.min(1,Ft/m),Ke=1-(1-Ie)*(1-Ie),Ze=Ie<1,cn=i.scale<u.hullsOnly,Vn=!cn&&i.scale<u.dotNodes;if(!cn)for(const Q of a.nodes){if(!Tt(Q.x,Q.y,i,o.clientWidth,o.clientHeight))continue;const Pe=Ae(Q.type);if(Vn){const Ne=F!==null&&!F.has(Q.id);n.fillStyle=Pe;const _e=Ne?.1:.8;n.globalAlpha=Ze?_e*Ke:_e,n.fillRect(Q.x-2,Q.y-2,4,4);continue}const Fe=x.has(Q.id),at=Ge!==null&&Ge.has(Q.id),ot=F!==null&&!F.has(Q.id),Ye=ot||x.size>0&&!Fe&&!at,Ve=i.scale<u.smallNodes?Ue*.5:Ue,Be=Ze?Ve*Ke:Ve;if(k!=null&&k.has(Q.id)){const Ne=p[p.length-1]===Q.id,_e=.5+.5*Math.sin(y),We=Ee("--accent")||"#d4a27f";n.save(),n.strokeStyle=We,n.lineWidth=Ne?3:2,n.globalAlpha=Ne?.5+.5*_e:.3+.4*_e,n.beginPath(),n.arc(Q.x,Q.y,Be+(Ne?6:4),0,Math.PI*2),n.stroke(),n.restore()}Fe&&(n.save(),n.shadowColor=Pe,n.shadowBlur=20,n.beginPath(),n.arc(Q.x,Q.y,Be+3,0,Math.PI*2),n.fillStyle=Pe,n.globalAlpha=.3,n.fill(),n.restore()),n.beginPath(),n.arc(Q.x,Q.y,Be,0,Math.PI*2),n.fillStyle=Pe;const Qe=ot?.1:Ye?.3:1;n.globalAlpha=Ze?Qe*Ke:Qe,n.fill(),n.strokeStyle=Fe?Re:ze,n.lineWidth=Fe?3:1.5,n.stroke(),n.globalAlpha=1,Q.pinned&&(n.save(),n.strokeStyle=ze,n.globalAlpha=.55,n.lineWidth=1,n.setLineDash([3,3]),n.beginPath(),n.arc(Q.x,Q.y,Be+4,0,Math.PI*2),n.stroke(),n.setLineDash([]),n.restore()),ge&&ge.nodeIds.has(Q.id)&&!Fe&&(n.save(),n.shadowColor=Ee("--accent")||"#d4a27f",n.shadowBlur=15,n.beginPath(),n.arc(Q.x,Q.y,Be+2,0,Math.PI*2),n.strokeStyle=Ee("--accent")||"#d4a27f",n.globalAlpha=.5,n.lineWidth=2,n.stroke(),n.restore());const oe=ee==null?void 0:ee.nodes.find(Ne=>Ne.id===Q.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("★",Q.x+Be-2,Q.y-Be+2)),i.scale>=u.hideLabels){const Ne=Q.label.length>24?Q.label.slice(0,22)+"...":Q.label,_e=Ye?ke:fe;An(n,Ne,Q.x,Q.y+Be+4,"11px system-ui, sans-serif",_e,"top")}if(i.scale>=u.hideBadges){const Ne=Ye?Te:Se;An(n,Q.type,Q.x,Q.y-Be-3,"9px system-ui, sans-serif",Ne,"bottom")}n.globalAlpha=1}if(n.restore(),n.restore(),f){const Q=o.width,Pe=o.height;(!B||B.width!==Q||B.height!==Pe)&&(B=new OffscreenCanvas(Q,Pe),$=B.getContext("2d")),$&&($.clearRect(0,0,Q,Pe),$.drawImage(o,0,0),te=!1),mt();return}X&&a.nodes.length>1&&E(),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),ut(),n.restore())}function E(){if(!a)return;const f=140,k=100,P=8,D=o.clientWidth-f-16,_=o.clientHeight-k-16;let j=1/0,O=1/0,J=-1/0,Z=-1/0;for(const Ie of a.nodes)Ie.x<j&&(j=Ie.x),Ie.y<O&&(O=Ie.y),Ie.x>J&&(J=Ie.x),Ie.y>Z&&(Z=Ie.y);const re=J-j||1,fe=Z-O||1,ke=Math.min((f-P*2)/re,(k-P*2)/fe),Se=D+P+(f-P*2-re*ke)/2,Te=_+P+(k-P*2-fe*ke)/2;n.save(),n.setTransform(g,0,0,g,0,0),n.fillStyle=Ee("--bg-surface")||"#1a1a1a",n.globalAlpha=.85,n.beginPath(),n.roundRect(D,_,f,k,8),n.fill(),n.strokeStyle=Ee("--border")||"#2a2a2a",n.globalAlpha=1,n.lineWidth=1,n.stroke(),n.globalAlpha=.15,n.strokeStyle=Ee("--canvas-edge")||"#555",n.lineWidth=.5;for(const Ie of a.edges){const Ke=a.nodeMap.get(Ie.sourceId),Ze=a.nodeMap.get(Ie.targetId);!Ke||!Ze||Ie.sourceId===Ie.targetId||(n.beginPath(),n.moveTo(Se+(Ke.x-j)*ke,Te+(Ke.y-O)*ke),n.lineTo(Se+(Ze.x-j)*ke,Te+(Ze.y-O)*ke),n.stroke())}n.globalAlpha=.8;for(const Ie of a.nodes){const Ke=Se+(Ie.x-j)*ke,Ze=Te+(Ie.y-O)*ke;n.beginPath(),n.arc(Ke,Ze,2,0,Math.PI*2),n.fillStyle=Ae(Ie.type),n.fill()}const Re=i.x,ze=i.y,Ge=i.x+o.clientWidth/i.scale,nt=i.y+o.clientHeight/i.scale,He=Se+(Re-j)*ke,it=Te+(ze-O)*ke,Nt=(Ge-Re)*ke,Ft=(nt-ze)*ke;n.globalAlpha=.3,n.strokeStyle=Ee("--accent")||"#d4a27f",n.lineWidth=1.5,n.strokeRect(Math.max(D,Math.min(He,D+f)),Math.max(_,Math.min(it,_+k)),Math.min(Nt,f),Math.min(Ft,k)),n.globalAlpha=1,n.restore()}function R(f,k,P,D,_,j,O){const J=Math.atan2(D-k,P-f),Z=P-Math.cos(J)*Ue,re=D-Math.sin(J)*Ue,fe=8;n.beginPath(),n.moveTo(Z,re),n.lineTo(Z-fe*Math.cos(J-.4),re-fe*Math.sin(J-.4)),n.lineTo(Z-fe*Math.cos(J+.4),re-fe*Math.sin(J+.4)),n.closePath(),n.fillStyle=_?O:j,n.fill()}function Y(f,k,P,D,_,j,O){const J=f.x+Ue+15,Z=f.y-Ue-15;n.beginPath(),n.arc(J,Z,15,0,Math.PI*2),n.strokeStyle=P?_:D,n.lineWidth=P?2.5:1.5,n.stroke(),V&&(n.fillStyle=P?O:j,n.font="9px system-ui, sans-serif",n.textAlign="center",n.fillText(k,J,Z-18))}function ne(){if(!le||!me)return;const f=performance.now()-me.time,k=Math.min(f/ve,1),P=1-Math.pow(1-k,3);i.x=me.x+(le.x-me.x)*P,i.y=me.y+(le.y-me.y)*P,ie(),c(),k<1?requestAnimationFrame(ne):(le=null,me=null)}let ae=0;function pe(){if(!be||p.length===0){ae=0;return}c(),ae=requestAnimationFrame(pe)}function he(){if(!a||a.nodes.length===0)return;let f=1/0,k=1/0,P=-1/0,D=-1/0;for(const re of a.nodes)re.x<f&&(f=re.x),re.y<k&&(k=re.y),re.x>P&&(P=re.x),re.y>D&&(D=re.y);const _=Ue*4,j=P-f+_*2,O=D-k+_*2,J=o.clientWidth/Math.max(j,1),Z=o.clientHeight/Math.max(O,1);i.scale=Math.min(J,Z,2),i.x=(f+P)/2-o.clientWidth/(2*i.scale),i.y=(k+D)/2-o.clientHeight/(2*i.scale),h()}function we(){if(!a||M<jt){T=0,be&&p.length>0&&!ae&&(ae=requestAnimationFrame(pe));return}M=So(a,M),b.rebuild(a.nodes),c(),T=requestAnimationFrame(we)}let Le=!1,De=0,tt=0,ht=0,kt=0;o.addEventListener("mousedown",f=>{H="pending",Le=!1,De=f.clientX,tt=f.clientY,ht=f.clientX,kt=f.clientY;const k=o.getBoundingClientRect(),P=f.clientX-k.left,D=f.clientY-k.top,_=Je(P,D);if(_&&!be){if(K=[],x.has(_.id)&&x.size>1)for(const J of x){const Z=a==null?void 0:a.nodeMap.get(J);Z&&K.push({node:Z,startX:Z.x,startY:Z.y})}else K.push({node:_,startX:_.x,startY:_.y});const[j,O]=Xe(P,D);q=j,ue=O}else if(!_&&f.shiftKey){const[j,O]=Xe(P,D);U={x1:j,y1:O,x2:j,y2:O}}}),o.addEventListener("mousemove",f=>{if(H==="idle")return;const k=f.clientX-De,P=f.clientY-tt,D=Math.abs(f.clientX-ht),_=Math.abs(f.clientY-kt);if(H==="pending"&&(D>xe||_>xe)&&(Le=!0,K.length>0?(H="nodeDrag",N&&w&&w.postMessage({type:"stop"})):U?H="rubberBand":H="pan"),H==="nodeDrag"){const j=o.getBoundingClientRect(),O=f.clientX-j.left,J=f.clientY-j.top,[Z,re]=Xe(O,J),fe=Z-q,ke=re-ue;for(const Se of K)Se.node.x=Se.startX+fe,Se.node.y=Se.startY+ke,Se.node.vx=0,Se.node.vy=0,Se.node.pinned=!0,de.add(Se.node.id);b.rebuild((a==null?void 0:a.nodes)??[]),h()}else if(H==="rubberBand"&&U){const j=o.getBoundingClientRect(),O=f.clientX-j.left,J=f.clientY-j.top,[Z,re]=Xe(O,J);U.x2=Z,U.y2=re,h()}else H==="pan"&&(i.x-=k/i.scale,i.y-=P/i.scale,h());De=f.clientX,tt=f.clientY}),o.addEventListener("mouseup",f=>{const k=H==="nodeDrag",P=H==="rubberBand";if(K.map(Z=>Z.node.id),k){if(N&&w&&a){const Z=K.map(re=>({id:re.node.id,x:re.node.x,y:re.node.y}));w.postMessage({type:"pin",updates:Z}),w.postMessage({type:"resume",alpha:.5})}else M=Math.max(M,.5),T||we();H="idle",K=[],h();return}if(P&&U&&a){const Z=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 a.nodes)Te.x>=Z&&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,H="idle",h();return}if(H==="pan"){H="idle";return}if(H="idle",U=null,Le)return;const D=o.getBoundingClientRect(),_=f.clientX-D.left,j=f.clientY-D.top,O=Je(_,j),J=f.ctrlKey||f.metaKey||f.shiftKey;if(be&&G&&O&&a){const Z=p.length>0?p[p.length-1]:G[0],re=new Set([Z]),fe=[{id:Z,path:[Z]}];let ke=null;for(;fe.length>0;){const{id:ze,path:Ge}=fe.shift();if(ze===O.id){ke=Ge;break}for(const nt of a.edges){let He=null;nt.sourceId===ze?He=nt.targetId:nt.targetId===ze&&(He=nt.sourceId),He&&!re.has(He)&&(re.add(He),fe.push({id:He,path:[...Ge,He]}))}}if(!ke)return;for(const ze of ke.slice(1))p.includes(ze)||p.push(ze);G=[O.id];const Se=Math.max(1,ye);ye=Se;const Te=Ln(ee,[O.id],Se);cancelAnimationFrame(T),w&&w.postMessage({type:"stop"}),a=Ut(Te),b.rebuild(a.nodes),M=1,x=new Set([O.id]),F=null,i={x:0,y:0,scale:1},N=Te.nodes.length>=S;const Re=N?I():null;Re?Re.postMessage({type:"start",data:Te}):(N=!1,we()),setTimeout(()=>{a&&he()},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 Z=[...x];e==null||e(Z.length>0?Z:null)}else x.clear(),e==null||e(null);h()}),o.addEventListener("mouseleave",()=>{if(H==="nodeDrag")if(N&&w&&K.length>0){const f=K.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 M=Math.max(M,.5),T||we();H==="rubberBand"&&(U=null,h()),H="idle",K=[]}),o.addEventListener("wheel",f=>{f.preventDefault();const k=o.getBoundingClientRect(),P=f.clientX-k.left,D=f.clientY-k.top,[_,j]=Xe(P,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=_-P/i.scale,i.y=j-D/i.scale,h()},{passive:!1});let Oe=[],tn=0,nn=1,on=0,sn=0,$t=!1;o.addEventListener("touchstart",f=>{f.preventDefault(),Oe=Array.from(f.touches),Oe.length===2?(tn=an(Oe[0],Oe[1]),nn=i.scale):Oe.length===1&&(De=Oe[0].clientX,tt=Oe[0].clientY,on=Oe[0].clientX,sn=Oe[0].clientY,$t=!1)},{passive:!1}),o.addEventListener("touchmove",f=>{f.preventDefault();const k=Array.from(f.touches);if(k.length===2&&Oe.length===2){const D=an(k[0],k[1])/tn;i.scale=Math.max(r.zoomMin,Math.min(r.zoomMax,nn*D)),h()}else if(k.length===1){const P=k[0].clientX-De,D=k[0].clientY-tt;(Math.abs(k[0].clientX-on)>10||Math.abs(k[0].clientY-sn)>10)&&($t=!0),i.x-=P/i.scale,i.y-=D/i.scale,De=k[0].clientX,tt=k[0].clientY,h()}Oe=k},{passive:!1}),o.addEventListener("touchend",f=>{if(f.preventDefault(),$t||f.changedTouches.length!==1)return;const k=f.changedTouches[0],P=o.getBoundingClientRect(),D=k.clientX-P.left,_=k.clientY-P.top,j=Je(D,_);if(j){x.size===1&&x.has(j.id)?x.clear():(x.clear(),x.add(j.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 P=f.clientX-k.clientX,D=f.clientY-k.clientY;return Math.sqrt(P*P+D*D)}const ft=document.createElement("div");ft.className="zoom-controls";const gt=document.createElement("button");gt.className="zoom-btn",gt.textContent="+",gt.title="Zoom in",gt.addEventListener("click",()=>{const f=o.clientWidth/2,k=o.clientHeight/2,[P,D]=Xe(f,k);i.scale=Math.min(r.zoomMax,i.scale*r.zoomFactor),i.x=P-f/i.scale,i.y=D-k/i.scale,h()});const yt=document.createElement("button");yt.className="zoom-btn",yt.textContent="−",yt.title="Zoom out",yt.addEventListener("click",()=>{const f=o.clientWidth/2,k=o.clientHeight/2,[P,D]=Xe(f,k);i.scale=Math.max(r.zoomMin,i.scale/r.zoomFactor),i.x=P-f/i.scale,i.y=D-k/i.scale,h()});const Ct=document.createElement("button");Ct.className="zoom-btn",Ct.textContent="○",Ct.title="Reset zoom",Ct.addEventListener("click",()=>{if(a){if(i={x:0,y:0,scale:1},a.nodes.length>0){let f=1/0,k=1/0,P=-1/0,D=-1/0;for(const O of a.nodes)O.x<f&&(f=O.x),O.y<k&&(k=O.y),O.x>P&&(P=O.x),O.y>D&&(D=O.y);const _=(f+P)/2,j=(k+D)/2;i.x=_-o.clientWidth/2,i.y=j-o.clientHeight/2}h()}}),ft.appendChild(gt),ft.appendChild(Ct),ft.appendChild(yt),t.appendChild(ft);const $e=document.createElement("div");$e.className="node-tooltip",$e.style.display="none",t.appendChild($e);let St=null,st=null;return o.addEventListener("mousemove",f=>{if(H!=="idle"&&H!=="pending"){$e.style.display!=="none"&&($e.style.display="none",St=null);return}const k=o.getBoundingClientRect(),P=f.clientX-k.left,D=f.clientY-k.top,_=Je(P,D),j=(_==null?void 0:_.id)??null;j!==St?(St=j,$e.style.display="none",st&&clearTimeout(st),st=null,j&&_&&(st=setTimeout(()=>{if(!a||!ee)return;const O=a.edges.filter(J=>J.sourceId===j||J.targetId===j).length;$e.textContent=`${_.label} · ${_.type} · ${O} edge${O!==1?"s":""}`,$e.style.left=`${f.clientX-k.left+12}px`,$e.style.top=`${f.clientY-k.top-8}px`,$e.style.display="block"},200))):j&&$e.style.display==="block"&&($e.style.left=`${f.clientX-k.left+12}px`,$e.style.top=`${f.clientY-k.top-8}px`)}),o.addEventListener("mouseleave",()=>{$e.style.display="none",St=null,st&&clearTimeout(st),st=null}),{loadGraph(f){if(cancelAnimationFrame(T),w&&w.postMessage({type:"stop"}),Ao(),ee=f,G=null,Ce=null,se=null,v=performance.now(),a=Ut(f),b.rebuild(a.nodes),M=1,x=new Set,F=null,de.clear(),H="idle",K=[],U=null,i={x:0,y:0,scale:1},a.nodes.length>0){let P=1/0,D=1/0,_=-1/0,j=-1/0;for(const fe of a.nodes)fe.x<P&&(P=fe.x),fe.y<D&&(D=fe.y),fe.x>_&&(_=fe.x),fe.y>j&&(j=fe.y);const O=(P+_)/2,J=(D+j)/2,Z=o.clientWidth,re=o.clientHeight;i.x=O-Z/2,i.y=J-re/2}N=f.nodes.length>=S;const k=N?I():null;k?k.postMessage({type:"start",data:f}):(N=!1,we())},setFilteredNodeIds(f){F=f,h()},releaseAllPins(){if(!a)return!1;let f=!1;for(const k of a.nodes)k.pinned&&(f=!0,k.pinned=!1);return de.clear(),H="idle",K=[],U=null,f&&(N&&w?w.postMessage({type:"unpin",ids:"all"}):(M=Math.max(M,.5),T||we()),h()),f},hasPinnedNodes(){if(!a)return!1;for(const f of a.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(!a||f.length===0)return;const k=f.map(_=>a.nodeMap.get(_)).filter(Boolean);if(k.length===0)return;x=new Set(f),e==null||e(f);const P=o.clientWidth,D=o.clientHeight;if(k.length===1)me={x:i.x,y:i.y,time:performance.now()},le={x:k[0].x-P/(2*i.scale),y:k[0].y-D/(2*i.scale)};else{let _=1/0,j=1/0,O=-1/0,J=-1/0;for(const Re of k)Re.x<_&&(_=Re.x),Re.y<j&&(j=Re.y),Re.x>O&&(O=Re.x),Re.y>J&&(J=Re.y);const Z=Ue*4,re=O-_+Z*2,fe=J-j+Z*2,ke=Math.min(P/re,D/fe,i.scale);i.scale=ke;const Se=(_+O)/2,Te=(j+J)/2;me={x:i.x,y:i.y,time:performance.now()},le={x:Se-P/(2*i.scale),y:Te-D/(2*i.scale)}}ne()},setEdges(f){W=f,h()},setEdgeLabels(f){V=f,h()},setTypeHulls(f){z=f,h()},setMinimap(f){X=f,h()},centerView(){he()},panBy(f,k){i.x+=f/i.scale,i.y+=k/i.scale,h()},zoomBy(f){const k=o.clientWidth/2,P=o.clientHeight/2,[D,_]=Xe(k,P);i.scale=Math.max(r.zoomMin,Math.min(r.zoomMax,i.scale*f)),i.x=D-k/i.scale,i.y=_-P/i.scale,h()},reheat(){N&&w?w.postMessage({type:"params",params:Et()}):(M=.5,cancelAnimationFrame(T),we())},exportImage(f){if(!a)return"";const k=o.width,P=o.height;if(f==="png"){const O=document.createElement("canvas");O.width=k,O.height=P;const J=O.getContext("2d");return J.fillStyle=Ee("--bg")||"#141414",J.fillRect(0,0,k,P),J.drawImage(o,0,0),Gn(J,k,P),O.toDataURL("image/png")}const D=o.toDataURL("image/png"),_=Math.max(16,Math.round(k/80)),j=`<svg xmlns="http://www.w3.org/2000/svg" width="${k}" height="${P}">
|
|
3
3
|
<image href="${D}" width="${k}" height="${P}"/>
|
|
4
4
|
<text x="${k-20}" y="${P-16}" text-anchor="end" font-family="system-ui, sans-serif" font-size="${_}" 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-DERxFHor.js"></script>
|
|
8
8
|
<link rel="stylesheet" crossorigin href="/assets/index-DE73ngo-.css">
|
|
9
9
|
</head>
|
|
10
10
|
<body>
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "share",
|
|
3
|
+
"version": "0.1.0",
|
|
4
|
+
"viewerApi": "1",
|
|
5
|
+
"displayName": "Share",
|
|
6
|
+
"description": "Share encrypted backpacks via a link. Recipients decrypt in-browser — the server never sees your data.",
|
|
7
|
+
"entry": "src/index.js",
|
|
8
|
+
"stylesheet": "style.css",
|
|
9
|
+
"permissions": {
|
|
10
|
+
"graph": ["read"],
|
|
11
|
+
"viewer": [],
|
|
12
|
+
"settings": true,
|
|
13
|
+
"network": [
|
|
14
|
+
{
|
|
15
|
+
"origin": "https://app.backpackontology.com",
|
|
16
|
+
"description": "Share relay for uploading encrypted backpacks"
|
|
17
|
+
}
|
|
18
|
+
]
|
|
19
|
+
}
|
|
20
|
+
}
|