Files
Capture/kb/.obsidian/plugins/bases-canvas/main.js
T

22 lines
134 KiB
JavaScript

/*
THIS IS A GENERATED/BUNDLED FILE BY ESBUILD
if you want to view the source, please visit the github repository of this plugin
*/
var be=Object.defineProperty;var Je=Object.getOwnPropertyDescriptor;var Xe=Object.getOwnPropertyNames;var Ze=Object.prototype.hasOwnProperty;var et=(u,s)=>{for(var e in s)be(u,e,{get:s[e],enumerable:!0})},tt=(u,s,e,t)=>{if(s&&typeof s=="object"||typeof s=="function")for(let n of Xe(s))!Ze.call(u,n)&&n!==e&&be(u,n,{get:()=>s[n],enumerable:!(t=Je(s,n))||t.enumerable});return u};var nt=u=>tt(be({},"__esModule",{value:!0}),u);var pt={};et(pt,{default:()=>we});module.exports=nt(pt);var z=require("obsidian");function se(u,s){let e=Object.keys(s).map(t=>at(u,t,s[t]));return e.length===1?e[0]:function(){e.forEach(t=>t())}}function at(u,s,e){let t=u[s],n=u.hasOwnProperty(s),a=n?t:function(){return Object.getPrototypeOf(u)[s].apply(this,arguments)},i=e(a);return t&&Object.setPrototypeOf(i,t),Object.setPrototypeOf(r,i),u[s]=r,o;function r(...l){return i===a&&u[s]===r&&o(),i.apply(this,l)}function o(){u[s]===r&&(n?u[s]=a:delete u[s]),i!==a&&(i=a,Object.setPrototypeOf(r,t||Function))}}var Pe=class{constructor(s=50){this.cache=new Map;this.accessOrder=[];this.stats={hits:0,misses:0,evictions:0};this.subscribers=[];this.capacity=s}get(s,e){let t=this.cache.get(s);return t?e!==void 0&&t.key!==e?(this.invalidate(s),this.stats.misses++,null):(this.stats.hits++,t.lastAccess=Date.now(),this.updateAccessOrder(s),t.edges):(this.stats.misses++,null)}set(s,e,t){!this.cache.has(s)&&this.cache.size>=this.capacity&&this.evictLRU();let n=Date.now(),a={edges:e.map(i=>({...i})),key:t,canvasId:s,lastAccess:n,created:n};this.cache.set(s,a),this.updateAccessOrder(s),this.notifySubscribers(s,e)}invalidate(s){this.cache.delete(s)&&(this.accessOrder=this.accessOrder.filter(e=>e!==s))}clear(){this.cache.clear(),this.accessOrder=[]}getCacheKey(s){return this.hashString(s)}getStats(){let s=this.stats.hits+this.stats.misses,e=s>0?this.stats.hits/s:0;return{hits:this.stats.hits,misses:this.stats.misses,size:this.cache.size,capacity:this.capacity,hitRate:e,evictions:this.stats.evictions}}resetStats(){this.stats={hits:0,misses:0,evictions:0}}subscribe(s){return this.subscribers.push(s),()=>{this.subscribers=this.subscribers.filter(e=>e!==s)}}getCachedCanvasIds(){return Array.from(this.cache.keys())}has(s){return this.cache.has(s)}updateAccessOrder(s){this.accessOrder=this.accessOrder.filter(e=>e!==s),this.accessOrder.push(s)}evictLRU(){if(this.accessOrder.length===0)return;let s=this.accessOrder[0];this.cache.delete(s),this.accessOrder.shift(),this.stats.evictions++}notifySubscribers(s,e){for(let t of this.subscribers)try{t(s,e)}catch(n){console.error("Cache subscriber error",n)}}hashString(s){let e=5381;for(let n=0;n<s.length;n++)e=(e<<5)+e+s.charCodeAt(n),e=e&e;return(e>>>0).toString(16).padStart(8,"0")}},Se=null;function Re(u=50){return Se||(Se=new Pe(u)),Se}var j=class{constructor(){this.listeners=new Map;this.history=[];this.maxHistorySize=100;this.eventCounter=0}static getInstance(){return j.instance||(j.instance=new j),j.instance}static resetInstance(){j.instance=null}on(s,e){return this.listeners.has(s)||this.listeners.set(s,new Set),this.listeners.get(s).add(e),()=>{let t=this.listeners.get(s);t&&(t.delete(e),t.size===0&&this.listeners.delete(s))}}once(s,e){let t=a=>{e(a),n()},n=this.on(s,t);return n}emit(s){let e={eventId:s.eventId||this.generateEventId(),timestamp:s.timestamp||Date.now(),...s};this.addToHistory(e);let t=this.listeners.get(e.type);!t||t.size===0||Promise.all(Array.from(t).map(n=>this.safeInvokeHandler(n,e))).catch(n=>{console.error("Event bus handler execution failed",n)})}getHistory(s){let e=[...this.history];return s&&(s.type&&(e=e.filter(t=>t.type===s.type)),s.canvasId&&(e=e.filter(t=>t.canvasId===s.canvasId)),s.from!==void 0&&(e=e.filter(t=>t.timestamp>=s.from)),s.to!==void 0&&(e=e.filter(t=>t.timestamp<=s.to)),s.limit!==void 0&&(e=e.slice(-s.limit))),e}clearHistory(){this.history=[]}getListenerCount(s){var e;return((e=this.listeners.get(s))==null?void 0:e.size)||0}removeAllListeners(){this.listeners.clear()}generateEventId(){return this.eventCounter++,`evt_${Date.now()}_${this.eventCounter}`}addToHistory(s){this.history.push(s),this.history.length>this.maxHistorySize&&this.history.shift()}async safeInvokeHandler(s,e){try{let t=s(e);t&&typeof t.then=="function"&&await t}catch(t){console.error(`Event handler failed for ${e.type}:`,t,`
Event:`,e)}}},ie=j;ie.instance=null;function Ve(){return ie.getInstance()}var q=class{constructor(s,e,t=null){this.operations=[];this.status="active";this.parent=null;this.error=null;this.id=this.generateTransactionId(),this.canvasId=s,this.manager=e,this.parent=t,this.snapshot=this.captureSnapshot()}addOperation(s){if(this.status!=="active")throw new Error(`Cannot add operation to transaction in ${this.status} status`);this.operations.push(s)}async commit(){if(this.status!=="active")throw new Error(`Cannot commit transaction in ${this.status} status`);this.status="committing";try{let s=[...this.operations].sort((e,t)=>e.timestamp-t.timestamp);for(let e of s)await this.applyOperation(e);this.status="committed"}catch(s){throw this.error=s,this.status="failed",await this.rollback(),new Error(`Transaction ${this.id} commit failed: ${s.message}`)}}async rollback(){if(this.status!=="active"&&this.status!=="failed"){console.warn(`Rollback called on transaction in ${this.status} status`);return}this.status="rolling-back";try{this.manager&&typeof this.manager.setEdges=="function"&&this.manager.setEdges(this.canvasId,this.snapshot.edges),this.status="rolled-back"}catch(s){throw console.error("Transaction rollback failed",s),this.status="failed",s}}getSnapshot(){return{...this.snapshot}}getOperations(){return[...this.operations]}getStatus(){return this.status}getError(){return this.error}isActive(){return this.status==="active"}createChild(){return new q(this.canvasId,this.manager,this)}async applyOperation(s){if(!this.manager)throw new Error("Transaction manager not available");switch(s.type){case"add":await this.manager.addEdgeInternal(this.canvasId,s.edge);break;case"remove":await this.manager.removeEdgeInternal(this.canvasId,s.edge.id);break;case"update":await this.manager.updateEdgeInternal(this.canvasId,s.edge);break;default:throw new Error(`Unknown operation type: ${s.type}`)}}captureSnapshot(){let s=this.manager&&typeof this.manager.getEdges=="function"?this.manager.getEdges(this.canvasId)||[]:[];return{canvasId:this.canvasId,edges:s.map(e=>({...e})),timestamp:Date.now()}}generateTransactionId(){return`tx_${Date.now()}_${Math.random().toString(36).substring(2,9)}`}};var G=class{constructor(){this.persistHandler=null;this.persistQueue=new Map;this.persisting=new Set;this.subscribers=new Map;this.persistedEdgesCache=new Map;this.cache=Re(),this.eventBus=Ve()}static getInstance(){return G.instance||(G.instance=new G),G.instance}static resetInstance(){G.instance=null}setPersistHandler(s){this.persistHandler=s}getEdges(s){let e=this.cache.get(s);return e?[...e]:[]}setEdges(s,e){let t=this.cache.getCacheKey(JSON.stringify({edges:e}));this.cache.set(s,e,t)}async addEdgeOptimistic(s,e){let n=[...this.getEdges(s),e];this.setEdges(s,n),this.eventBus.emit({type:"edge:added",canvasId:s,edge:e,optimistic:!0}),this.queuePersist(s,n).catch(a=>{console.error("Failed to persist edge addition",a),this.rollbackEdge(s,e)})}async removeEdgeOptimistic(s,e){let t=this.getEdges(s),n=t.find(i=>i.id===e);if(!n){console.warn(`Edge ${e} not found in canvas ${s}`);return}let a=t.filter(i=>i.id!==e);this.setEdges(s,a),this.eventBus.emit({type:"edge:removed",canvasId:s,edgeId:e,edge:n,optimistic:!0}),this.queuePersist(s,a).catch(i=>{console.error("Failed to persist edge removal",i);let r=[...this.getEdges(s),n];this.setEdges(s,r),this.eventBus.emit({type:"edge:rollback",canvasId:s,edge:n,reason:"persist-failed"})})}async withTransaction(s,e){let t=new q(s,this);try{let n=await e(t);await t.commit(),this.eventBus.emit({type:"edge:batch-changed",canvasId:s,operations:t.getOperations()});let a=this.getEdges(s);return await this.queuePersist(s,a),n}catch(n){throw await t.rollback(),n}}detectChanges(s,e){let t=this.getEdges(s),n=new Map(t.map(l=>[l.id,l])),a=new Map(e.map(l=>[l.id,l])),i=[],r=[],o=[];for(let[l,c]of a){let h=n.get(l);h?this.isEdgeEqual(h,c)||o.push(c):i.push(c)}for(let[l,c]of n)a.has(l)||r.push(c);return{added:i,removed:r,updated:o}}async persist(s){let e=this.getEdges(s);await this.executePersist(s,e)}subscribe(s,e){return this.subscribers.has(s)||this.subscribers.set(s,new Set),this.subscribers.get(s).add(e),()=>{let t=this.subscribers.get(s);t&&(t.delete(e),t.size===0&&this.subscribers.delete(s))}}async healthCheck(s){let e=this.getEdges(s),t=this.persistedEdgesCache.get(s)||await this.loadPersistedEdges(s),n=this.detectChanges(s,t);return{healthy:n.added.length===0&&n.removed.length===0&&n.updated.length===0,memoryCount:e.length,persistedCount:t.length,drift:n}}async addEdgeInternal(s,e){let n=[...this.getEdges(s),e];this.setEdges(s,n)}async removeEdgeInternal(s,e){let n=this.getEdges(s).filter(a=>a.id!==e);this.setEdges(s,n)}async updateEdgeInternal(s,e){let n=this.getEdges(s).map(a=>a.id===e.id?e:a);this.setEdges(s,n)}async queuePersist(s,e){this.persistQueue.set(s,{canvasId:s,edges:e,timestamp:Date.now(),attempts:0}),this.persisting.has(s)||await this.processPersistQueue(s)}async processPersistQueue(s){if(!this.persisting.has(s)){this.persisting.add(s);try{for(;this.persistQueue.has(s);){let e=this.persistQueue.get(s);this.persistQueue.delete(s),await this.executePersist(e.canvasId,e.edges)}}finally{this.persisting.delete(s)}}}async executePersist(s,e){if(!this.persistHandler){console.warn("No persist handler set for EdgeStateManager");return}let t=Date.now();this.eventBus.emit({type:"state:persist-start",canvasId:s,edgeCount:e.length});try{await this.persistHandler(s,e),this.persistedEdgesCache.set(s,e);let n=Date.now()-t;this.eventBus.emit({type:"state:persist-success",canvasId:s,edgeCount:e.length,duration:n})}catch(n){throw this.eventBus.emit({type:"state:persist-failed",canvasId:s,error:n,rollbackData:e}),n}}rollbackEdge(s,e){let n=this.getEdges(s).filter(a=>a.id!==e.id);this.setEdges(s,n),this.eventBus.emit({type:"edge:rollback",canvasId:s,edge:e,reason:"persist-failed"})}isEdgeEqual(s,e){return s.id===e.id&&s.fromNode===e.fromNode&&s.toNode===e.toNode&&s.fromSide===e.fromSide&&s.toSide===e.toSide&&s.fromEnd===e.fromEnd&&s.toEnd===e.toEnd&&s.color===e.color&&s.label===e.label}async loadPersistedEdges(s){return this.persistedEdgesCache.get(s)||[]}notifySubscribers(s,e){let t=this.subscribers.get(s);if(t)for(let n of t)try{n(s,e)}catch(a){console.error("Subscriber callback error",a)}}},re=G;re.instance=null;function ze(){return re.getInstance()}var De={["manual-save"]:100,["edge-change"]:80,["node-change"]:60,["viewport-change"]:40};function $e(u,s,e,t){var n;return{id:`${s}-${u}-${Date.now()}-${Math.random().toString(36).slice(2,9)}`,type:u,priority:De[u],canvasId:s,timestamp:Date.now(),execute:e,canBeMerged:(n=t==null?void 0:t.canBeMerged)!=null?n:!1,metadata:{description:t==null?void 0:t.description,context:t==null?void 0:t.context}}}var W=class{constructor(){this.queues=new Map;this.executing=new Map;this.protectionLocks=new Map;this.processingTimers=new Map;this.lastOperationTime=new Map;this.MERGE_WINDOW_MS=200;this.DEFAULT_PROTECTION_MS=300}static getInstance(){return W.instance||(W.instance=new W),W.instance}static resetInstance(){let s=W.instance;if(s){for(let e of s.processingTimers.values())clearTimeout(e);s.queues.clear(),s.executing.clear(),s.protectionLocks.clear(),s.processingTimers.clear(),s.lastOperationTime.clear()}W.instance=null}enqueue(s){let{canvasId:e,type:t,priority:n}=s;if(this.isProtected(e)&&t==="viewport-change"){let r=this.getRemainingProtectionTime(e);console.debug(`[SaveQueue] Deferring viewport save for ${e} (protection period: ${r}ms remaining)`),setTimeout(()=>{this.enqueue(s)},r+50);return}this.queues.has(e)||this.queues.set(e,[]);let a=this.queues.get(e);if(s.canBeMerged&&this.tryMergeOperation(a,s)){console.debug(`[SaveQueue] Merged ${t} operation for ${e}`),this.scheduleProcessing(e);return}let i=this.executing.get(e);i&&n>i.priority&&console.debug(`[SaveQueue] High priority ${t} (${n}) interrupting ${i.type} (${i.priority}) for ${e}`),a.push(s),a.sort((r,o)=>o.priority-r.priority),console.debug(`[SaveQueue] Enqueued ${t} operation for ${e} (queue size: ${a.length})`),this.scheduleProcessing(e)}setProtectionPeriod(s,e=this.DEFAULT_PROTECTION_MS){let t=Date.now()+e;this.protectionLocks.set(s,t),console.debug(`[SaveQueue] Protection period set for ${s}: ${e}ms`),setTimeout(()=>{this.protectionLocks.get(s)===t&&(this.protectionLocks.delete(s),console.debug(`[SaveQueue] Protection period ended for ${s}`))},e)}isProtected(s){let e=this.protectionLocks.get(s);return e?Date.now()>=e?(this.protectionLocks.delete(s),!1):!0:!1}getRemainingProtectionTime(s){let e=this.protectionLocks.get(s);if(!e)return 0;let t=e-Date.now();return Math.max(0,t)}clear(s){this.queues.delete(s);let e=this.processingTimers.get(s);e&&(clearTimeout(e),this.processingTimers.delete(s)),console.debug(`[SaveQueue] Cleared queue for ${s}`)}getStats(s){let e=this.queues.get(s)||[];return{queueSize:e.length,isExecuting:this.executing.has(s),isProtected:this.isProtected(s),operations:e.map(t=>({type:t.type,priority:t.priority}))}}scheduleProcessing(s){let e=this.processingTimers.get(s);if(e&&clearTimeout(e),this.executing.has(s))return;let t=this.queues.get(s);if(!t||t.length===0)return;if(t[0].priority>=De["edge-change"])this.processQueue(s);else{let i=setTimeout(()=>{this.processingTimers.delete(s),this.processQueue(s)},100);this.processingTimers.set(s,i)}}async processQueue(s){if(this.executing.has(s))return;let e=this.queues.get(s);if(!e||e.length===0)return;let t=e.shift();this.executing.set(s,t),console.debug(`[SaveQueue] Executing ${t.type} for ${s}`);let n=Date.now(),a=!1,i;try{await t.execute(),a=!0,console.debug(`[SaveQueue] Completed ${t.type} for ${s} in ${Date.now()-n}ms`)}catch(o){a=!1,i=o,console.error(`[SaveQueue] Failed ${t.type} for ${s}:`,o)}finally{this.executing.delete(s),this.lastOperationTime.set(s,Date.now()),e.length>0&&this.scheduleProcessing(s)}let r={operation:t,success:a,error:i,duration:Date.now()-n}}tryMergeOperation(s,e){let t=Date.now(),n=s.findIndex(a=>a.type===e.type&&a.canBeMerged&&t-a.timestamp<this.MERGE_WINDOW_MS);return n===-1?!1:(s[n]=e,s.sort((a,i)=>i.priority-a.priority),!0)}},oe=W;oe.instance=null;function xe(){return oe.getInstance()}var le=class{constructor(s,e,t){this.started=!1;this.disposers=[];this.patchedViews=new Map;this.sessions=new Map;this.rendererFactory=null;this.rendererListeners=[];this.debuggedRuntimes=new WeakSet;this.edgeChangeListeners=[];this.app=s,this.handler=e,this.sessionFactory=t}start(s){if(this.started)return;this.started=!0;let e=this.app.workspace,t=()=>this.patchExistingLeaves(),n=a=>{var r;if(!a)return;let i=a.view;i&&((r=i.getViewType)==null?void 0:r.call(i))==="canvas"&&(this.patchView(i),this.tryCaptureRenderer(i))};this.disposers.push(()=>{this.started=!1}),this.disposers.push(()=>{for(let a of this.patchedViews.values())try{a()}catch(i){console.error("Failed to revert Canvas save patch",i)}this.patchedViews.clear(),this.sessions.clear()}),s.registerEvent(e.on("layout-change",t)),s.registerEvent(e.on("active-leaf-change",n)),e.onLayoutReady(()=>{setTimeout(()=>{this.tryEagerRendererCapture()},100)}),t()}stop(){for(;this.disposers.length>0;){let s=this.disposers.pop();try{s==null||s()}catch(e){console.error("Failed to dispose Canvas bridge",e)}}this.rendererListeners.length=0}attachSession(s,e){this.sessions.set(s,e),this.patchView(s)}detachSession(s){this.sessions.delete(s)}patchExistingLeaves(){var t,n;let s=this.app.workspace,e=(n=(t=s.getLeavesOfType)==null?void 0:t.call(s,"canvas"))!=null?n:[];for(let a of e){if(!a)continue;let i=a.view;i&&(this.patchView(i),this.tryCaptureRenderer(i))}}tryEagerRendererCapture(){var s,e;if(this.rendererFactory){console.debug("[Canvas Bridge] Renderer already available, skipping eager capture");return}try{let t=this.app,n=t.viewRegistry;if(!n||typeof n!="object"){console.debug("[Canvas Bridge] View registry not available");return}let a=(s=n.viewByType)==null?void 0:s.canvas;if(typeof a!="function"){console.debug("[Canvas Bridge] Canvas view constructor not found in registry");return}let i=t.internalPlugins;if(!i||typeof i!="object"){console.debug("[Canvas Bridge] Internal plugins not available");return}let r=(e=i.plugins)==null?void 0:e.canvas;if(!r||typeof r!="object"){console.debug("[Canvas Bridge] Canvas plugin wrapper not found");return}let o=r.instance;if(!o){console.debug("[Canvas Bridge] Canvas plugin instance not available");return}let l=document.body.createDiv();l.style.display="none",l.style.position="absolute",l.style.visibility="hidden",l.style.width="0",l.style.height="0";let c={view:null,app:this.app,containerEl:l,workspace:this.app.workspace,getViewState:()=>({type:"canvas",state:{}}),setViewState:()=>Promise.resolve(),history:{backHistory:[],forwardHistory:[]},parentSplit:this.app.workspace.leftSplit,getDisplayText:()=>"Canvas",getIcon:()=>"lucide-layout-dashboard"};try{console.debug("[Canvas Bridge] Attempting to create temporary canvas view for renderer capture");let h=new a(c,o);if(h&&typeof h=="object"){this.tryCaptureRenderer(h),this.rendererFactory?console.log("[Canvas Bridge] \u2713 Successfully captured canvas renderer eagerly"):console.debug("[Canvas Bridge] Temporary view created but renderer capture failed");try{typeof h.unload=="function"&&h.unload()}catch(d){console.debug("[Canvas Bridge] Temporary view cleanup had minor issues (safe to ignore)",d)}}}finally{try{l.remove()}catch(h){console.debug("[Canvas Bridge] Failed to remove temporary container (safe to ignore)",h)}}}catch(t){console.debug("[Canvas Bridge] Eager renderer capture failed (will use fallback mechanism):",t)}}patchView(s){if(!s||typeof s!="object")return;if(!this.sessions.has(s)&&this.sessionFactory){let a=this.sessionFactory(s);a&&this.sessions.set(s,a)}if(this.patchedViews.has(s))return;let e=typeof s.getViewData=="function"?()=>{var a,i;try{return(i=(a=s.getViewData)==null?void 0:a.call(s))!=null?i:""}catch(r){return console.error("Failed to read Canvas view data",r),""}}:null,t=typeof s.save=="function"?"save":typeof s.saveLocalData=="function"?"saveLocalData":typeof s.requestSave=="function"?"requestSave":null;if(!t||!e){this.patchedViews.set(s,()=>{});return}let n=se(s,{[t]:a=>{let i=this;return async function(...o){var d;let l=i.sessions.get(this);if(!l)return a==null?void 0:a.apply(this,o);let c=e();if(!c||c.trim().length===0)return a==null?void 0:a.apply(this,o);let h=c;if(l.beforeSave)try{let p=await l.beforeSave({session:l,data:h,view:this});if(p==null)return a==null?void 0:a.apply(this,o);h=p}catch(p){return console.error("Canvas beforeSave hook failed",p),a==null?void 0:a.apply(this,o)}try{await i.handler({session:l,data:h,view:this}),(d=l.onSaved)==null||d.call(l,{session:l,data:h,view:this})}catch(p){console.error("Canvas save handler failed",p)}return a==null?void 0:a.apply(this,o)}}});this.patchedViews.set(s,n)}tryCaptureRenderer(s){var a,i,r,o;if(this.rendererFactory)return;let e=s;if(typeof e.createCanvasEmbed=="function"){this.rendererFactory=l=>{try{let c=e.createCanvasEmbed(l);return this.wrapRuntime(c)}catch(c){return console.error("Failed to create Canvas embed via createCanvasEmbed",c),null}},this.notifyRendererListeners();return}let t=(r=(i=(a=e.canvas)!=null?a:e.engine)!=null?i:e.runtime)!=null?r:null;if(t){if(this.debugRuntime(s,t),typeof t.createEmbed=="function"){this.rendererFactory=l=>{try{let c=t.createEmbed({containerEl:l});return this.wrapRuntime(c)}catch(c){return console.error("Failed to create Canvas embed via runtime.createEmbed",c),null}},this.notifyRendererListeners();return}if(t.constructor&&typeof t.constructor=="function"){let l=t.constructor;this.rendererFactory=c=>{var p,v,f,m;let h=c.createDiv("bases-canvas-runtime"),d=h.createDiv("bases-canvas-runtime-content");try{let b=d.createDiv("bases-canvas-runtime-stage"),D={app:this.app,containerEl:h,contentEl:d,canvasEl:b,leaf:(p=s.leaf)!=null?p:null,file:(v=s.file)!=null?v:null,scope:(f=s.scope)!=null?f:null,plugin:(m=s.plugin)!=null?m:null,hoverPopover:null,isPlaintext:!1,requestSave:()=>{},save:async()=>{},saveLocalData:()=>{},getLocalData:()=>null},k=new l(D);return this.wrapRuntime(k,()=>{typeof h.detach=="function"?h.detach():h.remove()})}catch(b){return typeof h.detach=="function"?h.detach():h.remove(),console.error("Failed to bootstrap Canvas runtime via constructor reflection",b),null}},this.notifyRendererListeners();return}}let n=(o=window.canvas)!=null?o:window.Canvas;n!=null&&n.createEmbed&&(this.rendererFactory=l=>{try{let c=n.createEmbed({containerEl:l,app:this.app});return this.wrapRuntime(c)}catch(c){return console.error("Failed to create Canvas embed via global helper",c),null}},this.notifyRendererListeners())}debugRuntime(s,e){if(!(!e||typeof e!="object")&&!this.debuggedRuntimes.has(e)){this.debuggedRuntimes.add(e);try{let t=Object.getPrototypeOf(e),n=Object.getPrototypeOf(s),a=e.constructor,i={runtimeKeys:Object.keys(e).slice(0,25),runtimeProto:t?Object.getOwnPropertyNames(t).slice(0,25):[],viewProto:n?Object.getOwnPropertyNames(n).slice(0,25):[],hasCreateEmbedInstance:typeof(e==null?void 0:e.createEmbed)=="function",hasCreateEmbedStatic:typeof(a==null?void 0:a.createEmbed)=="function",constructorProps:a?Object.getOwnPropertyNames(a).slice(0,25):[]};if(console.debug("[Views for Bases] Canvas runtime introspection",i),typeof a=="function"){let r=a.toString();console.debug("[Views for Bases] Canvas runtime constructor head",r.length>400?`${r.slice(0,400)}\u2026`:r)}}catch(t){console.warn("[Views for Bases] Failed to introspect Canvas runtime",t)}}}resolveRuntimeCanvas(s){return!s||typeof s!="object"?null:s.canvas&&typeof s.canvas=="object"?s.canvas:s.engine&&typeof s.engine=="object"?s.engine:s.runtime&&typeof s.runtime=="object"?s.runtime:null}serializeCanvasState(s,e){var i,r,o,l,c,h;let t=null,n=e!=null?e:s;if(n)try{typeof n.getState=="function"?t=n.getState():n.x!==void 0&&n.y!==void 0&&(t={x:(i=n.tx)!=null?i:n.x,y:(r=n.ty)!=null?r:n.y,zoom:(o=n.tZoom)!=null?o:n.zoom})}catch(d){console.debug("Could not extract viewport state",d)}let a=null;try{if(typeof(s==null?void 0:s.getViewData)=="function"){let d=s.getViewData();if(typeof d=="string")try{a=JSON.parse(d)}catch(p){return d}else d!=null&&(a=d)}}catch(d){console.error("Failed to read Canvas runtime view data",d)}if(!a&&n)try{if(typeof n.getSerializedData=="function"){let d=n.getSerializedData();if(typeof d=="string")try{a=JSON.parse(d)}catch(p){return d}else d!=null&&(a=d)}}catch(d){console.error("Failed to read Canvas serialized data",d)}if(!a&&n)try{typeof n.getData=="function"&&(a=n.getData())}catch(d){console.error("Failed to read Canvas data via getData",d)}if(!a&&n)try{Object.prototype.hasOwnProperty.call(n,"data")&&(a=n.data)}catch(d){console.error("Failed to access Canvas runtime data",d)}if(a==null)return null;if(t&&typeof a=="object"){let d={...a,x:(l=t.x)!=null?l:a.x,y:(c=t.y)!=null?c:a.y,zoom:(h=t.zoom)!=null?h:a.zoom};return JSON.stringify(d)}return JSON.stringify(a)}wrapRuntime(s,e){var P;if(!s)return null;let t=this.resolveRuntimeCanvas(s),n=[],a=new WeakMap,i=null,r=!1,o=!1,l=ze(),c={getViewType:()=>"canvas-embedded",getViewData:()=>{var g;return(g=this.serializeCanvasState(s,t))!=null?g:""},requestSave:()=>h(),save:async()=>{h()}},h=(g="viewport-change")=>{if(!i||r||o)return;let C=xe(),x=$e(g,i.targetFile.path,async()=>{let M=this.serializeCanvasState(s,t);M!=null&&await d(M,i,c)},{canBeMerged:g==="viewport-change",description:`Canvas ${g} save`});C.enqueue(x)},d=async(g,C,x)=>{var M;if(C)try{if(C.beforeSave)try{let E=await C.beforeSave({session:C,data:g,view:x});if(E==null)return;g=E}catch(E){console.error("Canvas beforeSave hook failed",E);return}try{let E=JSON.parse(g),T=Array.isArray(E==null?void 0:E.edges)?E.edges:[],$=C.targetFile.path,F=l.detectChanges($,T);(F.added.length>0||F.removed.length>0||F.updated.length>0)&&(xe().setProtectionPeriod($,300),l.setEdges($,T),this.notifyEdgeChangeListeners({session:C,added:F.added.map(w=>({from:w.fromNode,to:w.toNode,id:w.id})),removed:F.removed.map(w=>({from:w.fromNode,to:w.toNode,id:w.id})),current:T.map(w=>({from:w.fromNode,to:w.toNode,id:w.id})),view:x,data:g}))}catch(E){console.debug("Edge processing failed",E)}await this.handler({session:C,data:g,view:x}),(M=C.onSaved)==null||M.call(C,{session:C,data:g,view:x})}catch(E){console.error("Canvas save handler failed for embedded runtime",E)}},p=(g,C,x="node-change")=>{if(!g||typeof g!="object"||typeof g[C]!="function")return;let E=a.get(g);if(E!=null&&E.has(C))return;let T=E!=null?E:new Set;T.add(C),E||a.set(g,T);let $=se(g,{[C]:F=>function(...w){let ae=F==null?void 0:F.apply(this,w);return h(x),ae}});n.push(()=>{try{$()}catch(F){console.error("Failed to revert Canvas runtime save patch",F)}})},v=["addEdge","removeEdge","updateEdge","createEdge","deleteEdge"],f=["requestSave","save","requestPushHistory","pushHistory","setData","load","undo","redo","applyHistory"];for(let g of v)typeof s[g]=="function"&&p(s,g,"edge-change");for(let g of f)p(s,g,"node-change");if(t&&t!==s){for(let g of v)typeof t[g]=="function"&&p(t,g,"edge-change");for(let g of f)p(t,g,"node-change")}let m=s&&typeof s=="object"&&(P=s.history)!=null?P:null;if(m&&typeof m=="object"){let g=["undo","redo","apply","applyHistory"];for(let C of g)p(m,C,"node-change")}let b=["panBy","panTo","zoomBy","setState","setViewport"],D=t!=null?t:s;if(D){for(let g of b)if(typeof D[g]=="function"){let C=se(D,{[g]:x=>function(...E){let T=x==null?void 0:x.apply(this,E);return setTimeout(()=>h(),500),T}});n.push(()=>{try{C()}catch(x){console.error("Failed to revert Canvas viewport patch",x)}})}}return{load:g=>{var C,x,M,E,T,$;try{o=!0;let F=this.normalizePayload(g);typeof s.setData=="function"?s.setData(F):typeof s.loadData=="function"?s.loadData(F):typeof s.applyState=="function"?s.applyState(F):t&&typeof t.setData=="function"?t.setData(F):console.warn("Canvas runtime does not expose a recognized load method.");let N=t!=null?t:s;if(N&&typeof F=="object"&&F!==null){let w=F;try{(typeof w.x=="number"||typeof w.y=="number"||typeof w.zoom=="number")&&(typeof N.setState=="function"?N.setState({x:(C=w.x)!=null?C:0,y:(x=w.y)!=null?x:0,zoom:(M=w.zoom)!=null?M:0}):typeof N.setViewport=="function"?N.setViewport((E=w.x)!=null?E:0,(T=w.y)!=null?T:0,($=w.zoom)!=null?$:0):(typeof w.x=="number"&&(N.x!==void 0&&(N.x=w.x),N.tx!==void 0&&(N.tx=w.x)),typeof w.y=="number"&&(N.y!==void 0&&(N.y=w.y),N.ty!==void 0&&(N.ty=w.y)),typeof w.zoom=="number"&&(N.zoom!==void 0&&(N.zoom=w.zoom),N.tZoom!==void 0&&(N.tZoom=w.zoom)),typeof N.markViewportChanged=="function"&&N.markViewportChanged()))}catch(ae){console.debug("Could not apply viewport state",ae)}}}catch(F){console.error("Failed to apply Canvas payload to runtime",F)}finally{Promise.resolve().then(()=>{o=!1})}},destroy:()=>{if(!r){for(r=!0,i=null;n.length>0;){let g=n.pop();try{g==null||g()}catch(C){console.error("Failed to revert Canvas runtime patch",C)}}try{if(e)try{e()}catch(g){console.error("Failed to run Canvas runtime teardown",g)}typeof s.destroy=="function"?s.destroy():typeof s.unload=="function"&&s.unload()}catch(g){console.error("Failed to dispose Canvas runtime",g)}}},setSession:g=>{i=g,g?c.file=g.targetFile:delete c.file},getData:()=>this.serializeCanvasState(s,t),getCanvas:()=>t||s}}normalizePayload(s){if(typeof s=="string")try{return JSON.parse(s)}catch(e){return s}return s}getRendererFactory(){return this.rendererFactory}onRendererAvailable(s){return this.rendererFactory?(s(this.rendererFactory),()=>{}):(this.rendererListeners.push(s),()=>{this.rendererListeners=this.rendererListeners.filter(e=>e!==s)})}notifyRendererListeners(){if(!this.rendererFactory)return;let s=[...this.rendererListeners];this.rendererListeners.length=0;for(let e of s)try{e(this.rendererFactory)}catch(t){console.error("Renderer listener threw an error",t)}}onEdgesChanged(s){return this.edgeChangeListeners.push(s),()=>{this.edgeChangeListeners=this.edgeChangeListeners.filter(e=>e!==s)}}notifyEdgeChangeListeners(s){for(let e of this.edgeChangeListeners)try{e(s)}catch(t){console.error("Edge-change listener failed",t)}}};async function ke(u,s,e){await u.fileManager.processFrontMatter(s,t=>{Object.prototype.hasOwnProperty.call(t,e)&&delete t[e]})}var K=require("obsidian"),H={metadataProperty:"linkTo",linkMetadataEnabled:!0,linkMetadataProperty:"linkto",nonMarkdownPositions:{},autoBackupEnabled:!1,autoBackupFolder:"",pinnedCanvases:[],pinnedNodes:{}},ce=class extends K.PluginSettingTab{constructor(e,t){super(e,t);this.plugin=t}display(){let{containerEl:e}=this;e.empty(),e.createEl("h2",{text:"Views for Bases"}),new K.Setting(e).setName("Automatic link metadata").setDesc("Populate connected Markdown notes into frontmatter when saving Canvas.").addToggle(t=>t.setValue(this.plugin.settings.linkMetadataEnabled).onChange(async n=>{this.plugin.settings.linkMetadataEnabled=n,await this.plugin.saveSettings()})),new K.Setting(e).setName("Link metadata property").setDesc("Frontmatter key used to store outgoing links discovered from Canvas.").addText(t=>t.setPlaceholder("linkto").setValue(this.plugin.settings.linkMetadataProperty).onChange(async n=>{this.plugin.settings.linkMetadataProperty=n.trim()||H.linkMetadataProperty,await this.plugin.saveSettings()})),e.createEl("h3",{text:"Auto Backup"}),new K.Setting(e).setName("Enable auto backup").setDesc("Automatically save canvas to a backup folder when filter changes would cause data loss. When enabled, no confirmation dialog will be shown.").addToggle(t=>t.setValue(this.plugin.settings.autoBackupEnabled).onChange(async n=>{this.plugin.settings.autoBackupEnabled=n,await this.plugin.saveSettings(),this.display()})),this.plugin.settings.autoBackupEnabled&&new K.Setting(e).setName("Auto backup folder").setDesc("Folder path where canvas backups will be automatically saved. Leave empty to use vault root.").addText(t=>t.setPlaceholder("canvas-backups").setValue(this.plugin.settings.autoBackupFolder).onChange(async n=>{this.plugin.settings.autoBackupFolder=n.trim(),await this.plugin.saveSettings()}))}};var y=require("obsidian");var _=class{constructor(){this.dataSourceInstances=new Map;this.viewportStates=new Map;this.updateCallbacks=new Map;this.fullStates=new Map;this.fullStateCallbacks=new Map;this.isUpdating=new Set;this.locks=new Map}static getInstance(){return _.instance||(_.instance=new _),_.instance}registerInstance(s,e,t,n){this.dataSourceInstances.has(e)||this.dataSourceInstances.set(e,new Set),this.dataSourceInstances.get(e).add(s),this.updateCallbacks.set(s,t);let a=this.getLatestStateForDataSource(e);if(a&&t(a),n){this.fullStateCallbacks.set(s,n);let i=this.getLatestFullStateForDataSource(e);i&&n(i)}}unregisterInstance(s,e){let t=this.dataSourceInstances.get(e);t&&(t.delete(s),t.size===0&&this.dataSourceInstances.delete(e)),this.viewportStates.delete(s),this.updateCallbacks.delete(s),this.fullStates.delete(s),this.fullStateCallbacks.delete(s),this.isUpdating.delete(s)}updateViewport(s,e,t){let n=this.viewportStates.get(s);if(n&&this.isSameViewportState(n,t))return;this.viewportStates.set(s,t);let a=this.dataSourceInstances.get(e);if(a){for(let i of a)if(i!==s){let r=this.updateCallbacks.get(i);r&&r(t)}}}isSameViewportState(s,e){return Math.abs(s.x-e.x)<.001&&Math.abs(s.y-e.y)<.001&&Math.abs(s.zoom-e.zoom)<.001}updateFullState(s,e,t){if(this.isUpdating.has(s)){console.debug(`[Canvas Sync] Skipping update from ${s} - already updating`);return}this.fullStates.set(s,t);let n=this.dataSourceInstances.get(e);if(n){for(let a of n)if(a!==s){let i=this.fullStateCallbacks.get(a);if(i){this.isUpdating.add(a);try{i(t)}finally{setTimeout(()=>{this.isUpdating.delete(a)},500)}}}console.debug(`[Canvas Sync] Broadcasted full state from ${s} to ${n.size-1} instances`)}}async runExclusive(s,e){let t=await this.acquireLock(s);try{return await Promise.resolve(e())}finally{t()}}isLocked(s){let e=this.locks.get(s);return!!e&&e.locked===!0}acquireLock(s){let e=this.locks.get(s);return e||(e={locked:!1,queue:[]},this.locks.set(s,e)),e.locked?new Promise(t=>{e.queue.push(()=>{e.locked=!0,t(()=>this.releaseLock(s))})}):(e.locked=!0,Promise.resolve(()=>this.releaseLock(s)))}releaseLock(s){let e=this.locks.get(s);if(!e)return;let t=e.queue.shift();t?t():e.locked=!1}isInstanceUpdating(s){return this.isUpdating.has(s)}getLatestStateForDataSource(s){var n;let e=this.dataSourceInstances.get(s);if(!e||e.size===0)return null;let t=Array.from(e)[0];return(n=this.viewportStates.get(t))!=null?n:null}getLatestFullStateForDataSource(s){let e=this.dataSourceInstances.get(s);if(!e||e.size===0)return null;let t=null,n=0;for(let a of e){let i=this.fullStates.get(a);i&&i.timestamp>n&&(t=i,n=i.timestamp)}return t}},Y=_;Y.instance=null;var B=require("obsidian");var J=require("obsidian");async function Fe(u,s,e){let t=(0,J.normalizePath)(e);if(!t.endsWith(".canvas"))throw new Error("File must have .canvas extension");if(!s||typeof s!="object")throw new Error("Invalid canvas data");if(!Array.isArray(s.nodes)||!Array.isArray(s.edges))throw new Error("Canvas must have nodes and edges arrays");let n=JSON.stringify(s,null,2);if(await u.vault.adapter.exists(t)){let r=u.vault.getAbstractFileByPath(t);if(r instanceof J.TFile)return await u.vault.modify(r,n),r;throw new Error(`Cannot save canvas: ${t} is not a file`)}let i=t.lastIndexOf("/");if(i>0){let r=t.substring(0,i);if(!await u.vault.adapter.exists(r))try{await We(u,r)}catch(l){throw new Error(`Failed to create folder "${r}": ${l instanceof Error?l.message:"Unknown error"}`)}}try{return await u.vault.create(t,n)}catch(r){if(r instanceof Error){if(r.message.includes("already exists"))throw new Error(`File already exists: ${t}`);if(r.message.includes("parent folder"))throw new Error(`Parent folder does not exist for: ${t}`)}throw r}}async function We(u,s){if(await u.vault.adapter.exists(s))return;let t=s.lastIndexOf("/");if(t>0){let n=s.substring(0,t);await We(u,n)}try{await u.vault.createFolder(s)}catch(n){if(n instanceof Error&&!n.message.includes("already exists"))throw n}}function Ne(u){return`${u.basename}-canvas.canvas`}function Me(u){var s,e;return(e=(s=u.parent)==null?void 0:s.path)!=null?e:""}async function Ue(u,s){let e=(0,J.normalizePath)(s);return await u.vault.adapter.exists(e)}function je(u){if(!u||u.trim().length===0)return{isValid:!1,error:"Filename cannot be empty"};let s=u.trim();if(s.includes("../")||s.startsWith("..\\"))return{isValid:!1,error:"Relative paths (../) are not supported"};let t=s.replace(/\\/g,"/").split("/");for(let i of t){if(i.length===0)continue;if(/[*"<>:|?\x00-\x1F]/.test(i))return{isValid:!1,error:'Path contains invalid characters: * " < > : | ?'}}let n=t[t.length-1];return n.endsWith(".canvas")?n.slice(0,-7).length===0?{isValid:!1,error:"Filename cannot be just .canvas"}:{isValid:!0}:{isValid:!1,error:"Filename must end with .canvas extension"}}var X=class extends B.Modal{constructor(e,t,n,a){super(e);this.isProcessing=!1;this.locationDescEl=null;this.filename=t,this.suggestedFolder=n,this.onSave=a}onOpen(){let{contentEl:e}=this;e.empty(),e.createEl("h2",{text:"Save Canvas As"}),new B.Setting(e).setName("Filename").setDesc("Enter a name for the .canvas file (can include path like 'folder/file.canvas')").addText(n=>{n.setPlaceholder("my-canvas.canvas").setValue(this.filename).onChange(a=>{this.filename=a,this.updateLocationDisplay()}),n.inputEl.focus(),n.inputEl.select(),n.inputEl.addEventListener("keydown",a=>{a.key==="Enter"&&(a.preventDefault(),this.handleSave())})});let t=new B.Setting(e).setName("Location");this.locationDescEl=t.descEl,this.updateLocationDisplay(),new B.Setting(e).addButton(n=>n.setButtonText("Cancel").onClick(()=>{this.close()})).addButton(n=>n.setButtonText("Save").setCta().onClick(async()=>{await this.handleSave()}))}async handleSave(){var e;if(!this.isProcessing){this.isProcessing=!0;try{let t=this.filename.trim();if(!t){new B.Notice("Please enter a filename"),this.isProcessing=!1;return}t.endsWith(".canvas")||(t+=".canvas");let n=je(t);if(!n.isValid){new B.Notice((e=n.error)!=null?e:"Invalid filename"),this.isProcessing=!1;return}let a=this.suggestedFolder?`${this.suggestedFolder}/${t}`:t;if(await Ue(this.app,a)&&!await this.confirmOverwrite(a)){this.isProcessing=!1;return}try{await this.onSave(a),this.close()}catch(r){console.error("Failed to save canvas file:",r);let o=r instanceof Error?r.message:"Unknown error occurred";new B.Notice(`Failed to save canvas: ${o}`),this.isProcessing=!1}}catch(t){console.error("Error in save handler:",t),new B.Notice("An unexpected error occurred. See console for details."),this.isProcessing=!1}}}async confirmOverwrite(e){return new Promise(t=>{let n=new B.Modal(this.app);n.titleEl.setText("Confirm Overwrite"),n.contentEl.createEl("p",{text:`The file "${e}" already exists. Do you want to overwrite it?`}),new B.Setting(n.contentEl).addButton(a=>a.setButtonText("Cancel").onClick(()=>{n.close(),t(!1)})).addButton(a=>a.setButtonText("Overwrite").setWarning().onClick(()=>{n.close(),t(!0)})),n.open()})}updateLocationDisplay(){if(!this.locationDescEl)return;let e=this.filename.trim(),t=Math.max(e.lastIndexOf("/"),e.lastIndexOf("\\")),n;t>0?n=e.substring(0,t):this.suggestedFolder&&this.suggestedFolder.length>0?n=this.suggestedFolder:n="",n&&n.length>0?this.locationDescEl.setText(`File will be saved in: ${n}`):this.locationDescEl.setText("File will be saved in vault root")}onClose(){let{contentEl:e}=this;e.empty(),this.isProcessing=!1}};var he=require("obsidian");var de=class extends he.Modal{constructor(e,t,n){super(e);this.message=t,this.onDecision=n}onOpen(){let{contentEl:e}=this;e.empty(),e.createEl("h2",{text:"Unsaved Canvas Changes"}),e.createEl("p",{text:this.message});let t=new he.Setting(e);t.addButton(n=>n.setButtonText("Cancel").onClick(()=>{this.onDecision("cancel"),this.close()})),t.addButton(n=>n.setButtonText("Don't Save").setWarning().onClick(()=>{this.onDecision("discard"),this.close()})),t.addButton(n=>n.setButtonText("Save").setCta().onClick(()=>{this.onDecision("save"),this.close()}))}onClose(){let{contentEl:e}=this;e.empty()}};function Te(u){let s=[],e=[];for(let n of u.nodes){let a=it(n);a&&s.push(a)}let t=new Set(s.map(n=>n.id));for(let n of u.edges){let a=rt(n,t);a&&e.push(a)}return{nodes:s,edges:e}}function it(u){var e;if(!u.id||!u.type)return console.warn("[Canvas Converter] Skipping node with missing required fields:",u),null;let s={id:u.id,x:typeof u.x=="number"?u.x:0,y:typeof u.y=="number"?u.y:0,width:typeof u.width=="number"?u.width:320,height:typeof u.height=="number"?u.height:200,color:Ge(u.color)};switch(u.type){case"file":return u.file?{...s,type:"file",file:u.file}:(console.warn("[Canvas Converter] Skipping file node without file path:",u),null);case"text":return{...s,type:"text",text:(e=u.text)!=null?e:""};case"link":return u.url?{...s,type:"link",url:u.url}:(console.warn("[Canvas Converter] Skipping link node without URL:",u),null);case"group":{let t={...s,type:"group"};return u.label&&(t.label=u.label),u.background&&(t.background=u.background),u.backgroundStyle&&(t.backgroundStyle=u.backgroundStyle),t}default:return console.warn(`[Canvas Converter] Unknown node type: ${u.type}`,u),null}}function rt(u,s){if(!u.fromNode||!u.toNode)return console.warn("[Canvas Converter] Skipping edge with missing endpoints:",u),null;if(!s.has(u.fromNode)||!s.has(u.toNode))return console.warn("[Canvas Converter] Skipping edge with invalid node references:",u),null;let e={id:u.id,fromNode:u.fromNode,toNode:u.toNode};u.fromSide&&(e.fromSide=u.fromSide),u.toSide&&(e.toSide=u.toSide),u.fromEnd&&(e.fromEnd=u.fromEnd),u.toEnd&&(e.toEnd=u.toEnd),u.label&&(e.label=u.label);let t=Ge(u.color);return t&&(e.color=t),e}function Ge(u){if(u){if(u.startsWith("#")){if(/^#[0-9A-Fa-f]{6}$/.test(u))return u;if(/^#[0-9A-Fa-f]{3}$/.test(u)){let s=u[1],e=u[2],t=u[3];return`#${s}${s}${e}${e}${t}${t}`}console.warn(`[Canvas Converter] Invalid hex color format: ${u}`);return}if(/^[1-6]$/.test(u))return u;console.warn(`[Canvas Converter] Invalid color value: ${u}`)}}var Ae="CanvasForBases",Ke=["viewsForBases"],ue=320,pe=200,qe=80,ot=80,Le="entryCanvasStates",Ie="canvas-view",Z=class extends y.BasesView{constructor(e,t,n){super(e);this.type=Ie;this.rendererHandle=null;this.rendererUnsubscribe=null;this.canvasPropertyId=null;this.canvasPropertyName=null;this.activeEntry=null;this.activeItemEl=null;this.currentCanvasData=null;this.activeSession=null;this.autoLayoutCompareKey=null;this.suppressNextSave=!1;this.autoLayoutActive=!1;this.sidebarCollapsed=!0;this.pendingFocusEntryPath=null;this.reselectingActiveEntry=!1;this.lastRenderedEntryPath=null;this.lastRenderableEntriesSignature=null;this.skipNextDataRefresh=!1;this.suppressNextAutoImport=!1;this.canvasModified=!1;this.initialCanvasDataSignature=null;this.lastDataSignature=null;this.pendingCanvasData=null;this.lastSaveCheckTime=0;this.saveCheckThrottleMs=1e3;this.viewportSyncIntervalId=null;this.boundHandleWheel=null;this.lastSaveTimestamp=0;this.fileChangeUnsubscribe=null;this.lastFileModTime=new Map;this.suppressViewportBroadcast=!1;this.lastViewportState=null;this.historyRecords=[];this.historyIntervalId=null;this.lastHistorySignature=null;console.log(this),this.instanceId=`canvas-view-${Date.now()}-${Math.random().toString(36).substr(2,9)}`,this.stateSynchronizer=Y.getInstance(),this.app=n.app,this.bridge=n.bridge,this.getDefaultMetadataKey=n.getDefaultMetadataKey,this.getLinkMetadataKey=n.getLinkMetadataKey,this.readNonMarkdownPositions=n.getNonMarkdownPositions,this.writeNonMarkdownPositions=n.setNonMarkdownPositions,this.getSettings=n.getSettings,this.rendererFactory=this.bridge.getRendererFactory(),this.metadataKey=this.getDefaultMetadataKey(),this.rootEl=t.createDiv("bases-canvas-view"),this.sidebarEl=this.rootEl.createDiv("bases-canvas-sidebar"),this.stageEl=this.rootEl.createDiv("bases-canvas-stage");let a=this.handleWheel.bind(this);this.boundHandleWheel=a,this.rootEl.addEventListener("wheel",a,{passive:!0}),this.sidebarToggleEl=new y.ExtraButtonComponent(this.stageEl).onClick(this.toggleSidebar.bind(this)).extraSettingsEl,this.sidebarToggleEl.setAttr("aria-expanded",!0),this.sidebarToggleEl.toggleClass(["bases-canvas-sidebar-toggle"],!0),this.hostEl=this.stageEl.createDiv("bases-canvas-host"),this.messageEl=this.stageEl.createDiv("bases-canvas-message"),this.applySidebarState(),this.rendererUnsubscribe=this.bridge.onRendererAvailable(i=>{this.rendererFactory=i,this.renderCanvas()}),this.registerCanvasKeymapHandlers(),this.debouncedRenderCanvas=(0,y.debounce)(()=>{this.pendingCanvasData&&(this.performRenderCanvas(this.pendingCanvasData),this.pendingCanvasData=null)},150),this.debouncedBroadcastState=(0,y.debounce)(()=>{this.performBroadcastState()},500)}registerCanvasKeymapHandlers(){let e=(a,i,r)=>{let o=this.app.scope.register(a,i,l=>{this.shouldHandleCanvasHotkey(l)&&r(l)});this.registerKeymapHandler(o)};e(["Mod"],"z",a=>{this.invokeCanvasMethod("undo")&&a.preventDefault()}),e(["Mod"],"a",()=>{this.invokeCanvasMethod("selectAll")});let t=a=>{this.invokeCanvasMethod("redo")&&a.preventDefault()};e(["Mod","Shift"],"z",t),e(["Mod"],"y",t),e(["Shift"],"1",()=>{this.invokeCanvasMethod("zoomToFit")}),e(["Shift"],"2",()=>{this.invokeCanvasMethod("zoomToSelection")});let n=a=>i=>{this.invokeCanvasMethod("nudgeSelection",i,a)&&i.preventDefault()};e([],"ArrowRight",n("right")),e(["Shift"],"ArrowRight",n("right")),e([],"ArrowLeft",n("left")),e(["Shift"],"ArrowLeft",n("left")),e([],"ArrowUp",n("up")),e(["Shift"],"ArrowUp",n("up")),e([],"ArrowDown",n("down")),e(["Shift"],"ArrowDown",n("down"))}registerKeymapHandler(e){this.registerScopeEvent(e)}shouldHandleCanvasHotkey(e){var i;let t=e,n=this.normalizeNodeToElement((i=t.targetNode)!=null?i:null);return n||(n=this.normalizeNodeToElement(e.target instanceof Node?e.target:null)),!n&&document.activeElement instanceof Element&&(n=document.activeElement),!(!n||!(n===this.hostEl||this.hostEl.contains(n)||Boolean(n.closest(".bases-canvas-embed")))||this.isEditableElement(n))}normalizeNodeToElement(e){return e?e instanceof Element?e:e instanceof Text?e.parentElement:null:null}isEditableElement(e){return e?e instanceof HTMLElement&&e.isContentEditable?!0:Boolean(e.closest("input, textarea, select, [contenteditable], .cm-editor")):!1}getRuntimeCanvas(){if(!this.rendererHandle||typeof this.rendererHandle.getCanvas!="function")return null;try{let e=this.rendererHandle.getCanvas();return e&&typeof e=="object"?e:null}catch(e){return console.error("Failed to access Canvas runtime",e),null}}invokeCanvasMethod(e,...t){let n=this.getRuntimeCanvas();if(!n)return!1;let a=n[e];if(typeof a!="function")return!1;try{return a.apply(n,t),!0}catch(i){return console.error(`Canvas runtime ${e} invocation failed`,i),!1}}onunload(){var e;if(this.activeEntry){let t=this.getEntryPath(this.activeEntry);this.stateSynchronizer.unregisterInstance(this.instanceId,t)}this.viewportSyncIntervalId!==null&&(clearInterval(this.viewportSyncIntervalId),this.viewportSyncIntervalId=null),this.fileChangeUnsubscribe&&(this.fileChangeUnsubscribe(),this.fileChangeUnsubscribe=null),this.destroyRenderer(),(e=this.rendererUnsubscribe)==null||e.call(this),this.rendererUnsubscribe=null,this.boundHandleWheel&&(this.rootEl.removeEventListener("wheel",this.boundHandleWheel),this.boundHandleWheel=null),this.rootEl.empty()}openHistoryMenu(e,t){if(this.historyRecords.length===0){new y.Notice("No history yet");return}let n=this.historyRecords.slice().reverse(),a=new y.Menu;n.forEach((r,o)=>{var p,v;let c=new Date(r.timestamp).toLocaleTimeString(),h=Array.isArray((p=r.data)==null?void 0:p.nodes)?r.data.nodes.length:0,d=Array.isArray((v=r.data)==null?void 0:v.edges)?r.data.edges.length:0;a.addItem(f=>{f.setTitle(`${o+1}. ${c} (${h} nodes, ${d} edges)`).setIcon("history").onClick(()=>this.restoreFromHistory(r))})});let i=a;if(e&&typeof i.showAtMouseEvent=="function")i.showAtMouseEvent(e);else if(t&&typeof i.showAtPosition=="function"&&typeof t.getBoundingClientRect=="function"){let r=t.getBoundingClientRect();i.showAtPosition({x:r.left,y:r.bottom})}else typeof i.showAtPosition=="function"&&i.showAtPosition({x:window.innerWidth/2,y:window.innerHeight/2})}async restoreFromHistory(e){if(!this.rendererHandle)return;let t=this.activeEntry?this.getEntryPath(this.activeEntry):null,n=async()=>{let a=this.cloneCanvasPayload(e.data);this.rendererHandle.load(a),this.currentCanvasData=this.cloneCanvasPayload(a),this.resetCanvasModificationState(),this.lastDataSignature=this.computeContentSignature(this.currentCanvasData),new y.Notice("Canvas restored to selected snapshot")};try{t?await this.stateSynchronizer.runExclusive(t,n):await n()}catch(a){console.error("Failed to restore canvas snapshot",a),new y.Notice("Failed to restore snapshot")}}startHistoryRecorder(){this.historyIntervalId==null&&(this.captureHistorySnapshot(),this.historyIntervalId=window.setInterval(()=>this.captureHistorySnapshot(),5e3))}stopHistoryRecorder(){this.historyIntervalId!=null&&(clearInterval(this.historyIntervalId),this.historyIntervalId=null)}captureHistorySnapshot(){let e=null;try{if(this.rendererHandle&&typeof this.rendererHandle.getData=="function"){let r=this.rendererHandle.getData();e=typeof r=="string"?r:null}}catch(r){console.debug("Failed to read canvas data for history snapshot",r)}let t=null;if(e&&e.trim().length>0)try{t=this.normalizeCanvasData(JSON.parse(e))}catch(r){console.debug("Failed to parse canvas snapshot",r)}else this.currentCanvasData&&(t=this.cloneCanvasPayload(this.currentCanvasData));if(!t)return;let n=this.computeContentSignature(t);if(!n)return;let a=this.historyRecords[this.historyRecords.length-1];if(a&&a.signature===n)return;this.historyRecords.push({timestamp:Date.now(),signature:n,data:t});let i=200;this.historyRecords.length>i&&this.historyRecords.splice(0,this.historyRecords.length-i)}async onDataUpdated(){var a;if(this.skipNextDataRefresh){this.skipNextDataRefresh=!1;return}this.loadConfig();let e=this.getRenderableEntries(),t=this.computeRenderableEntriesSignature(e),n=t!==this.lastRenderableEntriesSignature;if(n&&this.currentCanvasData&&this.getManagedEntryPaths(this.currentCanvasData).size>0&&this.hasCanvasBeenModified()){let i=this.getSettings();if(i.autoBackupEnabled&&i.autoBackupFolder)try{await this.autoSaveCanvas(i.autoBackupFolder)}catch(r){if(console.error("Auto-save failed, falling back to confirmation dialog:",r),new y.Notice("Auto-save failed. Please save manually or discard changes."),!await this.confirmCanvasSaveBeforeDataChange())return}else if(!await this.confirmCanvasSaveBeforeDataChange())return}this.lastRenderableEntriesSignature=t,n&&this.currentCanvasData&&this.getManagedEntryPaths(this.currentCanvasData).size>0&&(this.autoLayoutActive=!0),this.renderEntryList(),!this.activeEntry&&((a=this.data)!=null&&a.data.length)?this.selectEntry(this.data.data[0]):this.activeEntry?this.renderCanvas():(this.hideSidebar(),this.showMessage("No entries available in this Base."))}loadConfig(){var n;this.canvasPropertyId=this.config.getAsPropertyId("canvasProperty");let e=this.config.get("metadataKey"),t=this.getDefaultMetadataKey();typeof e=="string"&&e.trim().length>0?this.metadataKey=e.trim():this.metadataKey=t,!this.canvasPropertyId&&this.metadataKey&&(this.canvasPropertyId=`note.${this.metadataKey}`),this.canvasPropertyName=(n=this.getFrontmatterPropertyName(this.canvasPropertyId))!=null?n:this.metadataKey}toggleSidebar(){this.sidebarCollapsed=!this.sidebarCollapsed,this.applySidebarState()}applySidebarState(){this.rootEl.toggleClass("is-sidebar-collapsed",this.sidebarCollapsed),this.sidebarCollapsed?((0,y.setIcon)(this.sidebarToggleEl,"panel-right"),this.sidebarToggleEl.setAttribute("aria-expanded","false")):((0,y.setIcon)(this.sidebarToggleEl,"panel-right-open"),this.sidebarToggleEl.setAttribute("aria-expanded","true"))}handleWheel(e){e.stopPropagation()}renderEntryList(){var d,p;this.sidebarEl.empty();let e=this.sidebarEl.createDiv("bases-canvas-controls"),t=new y.ExtraButtonComponent(e).onClick(()=>this.importAllEntries()).setIcon("copy-plus").setTooltip("Import all file"),n=new y.ExtraButtonComponent(e).onClick(()=>this.clearImportedEntries()).setIcon("rotate-ccw").setTooltip("Clear all files"),a=new y.ExtraButtonComponent(e).onClick(()=>this.saveCanvasAsFile()).setIcon("download").setTooltip("Save canvas as .canvas file");new y.ExtraButtonComponent(e).setIcon("history").setTooltip("History (2s snapshots)").onClick(()=>{let v=e.lastElementChild;this.openHistoryMenu(void 0,v)}),(!this.currentCanvasData||this.currentCanvasData.nodes.length===0)&&a.setDisabled(!0);let r=(p=(d=this.data)==null?void 0:d.data)!=null?p:[],o=this.getManagedEntryIdentifiers(),l=o.paths,c=o.basenames,h=this.getEntryBasenameCounts(r);if(r.length===0){t.setDisabled(!0),n.setDisabled(!0),this.sidebarEl.createDiv("bases-canvas-empty").setText("No entries found.");return}l.size===0&&n.setDisabled(!0);for(let v of r){let f=this.getEntryPath(v),m=this.sidebarEl.createDiv({cls:"bases-canvas-entry",attr:{"aria-label":v.file.basename}});m.createSpan({cls:"bases-canvas-entry-text",text:v.file.basename}),v===this.activeEntry&&(m.addClass("is-active"),this.activeItemEl=m);let b=!!f&&l.has(f);!b&&h.get(v.file.basename)===1&&c.get(v.file.basename)===1&&(b=!0),b&&(m.addClass("is-imported"),m.createSpan({cls:"bases-canvas-entry-status clickable-icon"},D=>{(0,y.setIcon)(D,"pin")})),this.registerDomEvent(m,"click",()=>{this.selectEntry(v,m)})}}selectEntry(e,t){var i,r,o;let n=(o=(r=(i=this.activeEntry)==null?void 0:i.file)==null?void 0:r.path)!=null?o:null;this.reselectingActiveEntry=n===e.file.path,this.activeEntry=e,this.activeItemEl&&this.activeItemEl!==t&&this.activeItemEl.removeClass("is-active"),t&&(t.addClass("is-active"),this.activeItemEl=t);let a=this.getEntryPath(e);this.pendingFocusEntryPath=a||null,this.renderCanvas()}scheduleFocus(e){let t=this.getEntryPath(e);if(!t){this.pendingFocusEntryPath=null;return}let n=a=>{if(this.pendingFocusEntryPath!==t)return;if(this.focusOnEntry(e)){this.pendingFocusEntryPath===t&&(this.pendingFocusEntryPath=null);return}a>0&&window.setTimeout(()=>n(a-1),100)};window.setTimeout(()=>n(3),100)}focusOnEntry(e){var n;if(!this.rendererHandle||!this.rendererHandle.getCanvas)return!1;let t=this.getEntryPath(e);if(!t||!this.currentCanvasData)return!1;try{let a=this.rendererHandle.getCanvas();if(!a)return!1;let i=this.getNodeIdForPath(t),r=this.currentCanvasData.nodes.find(l=>{let c=this.getNodeMeta(l);return(c==null?void 0:c.entryPath)===t||l.id===i||l.type==="file"&&typeof l.file=="string"&&this.canonicalizeEntryPath(l.file)===t});if(!r)return!1;let o=(n=this.resolveCanvasRuntimeNode(a,r.id))!=null?n:this.resolveCanvasRuntimeNode(a,i);return this.trySelectCanvasNode(a,o,r.id)?(this.tryZoomCanvasToSelection(a),!0):!1}catch(a){return console.error("Failed to focus on entry node",a),!1}}resolveCanvasRuntimeNode(e,t){if(!e||!t)return null;let n=e,a=r=>{if(!r)return null;if(Array.isArray(r)){if(r.length>=2){let o=a(r[1]);if(o)return o}for(let o of r){let l=a(o);if(l)return l}return null}return typeof r=="object"&&r.id===t?r:null},i=r=>{if(!r)return null;try{for(let o of r){let l=a(o);if(l)return l}}catch(o){console.debug("Failed to iterate Canvas nodes collection",o)}return null};try{let r=typeof n.getNode=="function"?n.getNode:null;if(r){let c=r(t);if(c)return c}let o=typeof n.getNodeById=="function"?n.getNodeById:null;if(o){let c=o(t);if(c)return c}let l=n.nodes;if(!l)return null;if(typeof l.get=="function")try{let h=l.get.call(l,t);if(h)return h}catch(c){console.debug("Canvas nodes.get failed",c)}if(typeof l.values=="function"){let c=l.values.call(l),h=i(c);if(h)return h}if(typeof l[Symbol.iterator]=="function"){let c=i(l);if(c)return c}if(Array.isArray(l)){let c=i(l);if(c)return c}else if(l&&typeof l=="object")for(let c of Object.values(l)){let h=a(c);if(h)return h}}catch(r){console.debug("Failed to resolve Canvas runtime node",r)}return null}trySelectCanvasNode(e,t,n){let a=e,i=t!=null?t:null,r=n&&n.length>0?n:null,o=typeof a.selectOnly=="function"?a.selectOnly:null,l=typeof a.select=="function"?a.select:null,c=typeof a.selectOnlyById=="function"?a.selectOnlyById:null,h=typeof a.selectById=="function"?a.selectById:null;if(i){if(o)try{return o.call(a,i),!0}catch(d){console.debug("Canvas selectOnly failed",d)}if(l)try{return l.call(a,i),!0}catch(d){console.debug("Canvas select failed",d)}}if(r){if(c)try{return c.call(a,r),!0}catch(d){console.debug("Canvas selectOnlyById failed",d)}if(h)try{return h.call(a,r),!0}catch(d){console.debug("Canvas selectById failed",d)}if(!i){let d=this.resolveCanvasRuntimeNode(e,r);if(d)return this.trySelectCanvasNode(e,d,r)}}if(i&&a.selection instanceof Set)try{return a.selection.clear(),a.selection.add(i),typeof a.requestFrame=="function"&&a.requestFrame.call(a),!0}catch(d){console.debug("Canvas manual selection fallback failed",d)}return!1}tryZoomCanvasToSelection(e){let t=e;try{typeof t.zoomToSelection=="function"?t.zoomToSelection.call(t):typeof t.zoomToFit=="function"&&t.zoomToFit.call(t)}catch(n){console.debug("Canvas zoom operation failed",n)}}renderCanvas(){var l,c;let e=this.activeEntry;if(!e){this.destroyRenderer(),this.hideSidebar(),this.showMessage("Select an entry to import it into the Canvas.");return}if(!this.rendererFactory){this.destroyRenderer(),this.hideSidebar(),this.showMessage("Canvas renderer is not available yet. Open a Canvas once to initialise the runtime.");return}this.showSidebar();let t=this.getCanvasPayload(e),n=null,a=e.file.path,i=this.lastRenderedEntryPath===a,r=this.reselectingActiveEntry;if(!t&&(r||i)&&(n=this.currentCanvasData?this.cloneCanvasPayload(this.currentCanvasData):null),!t&&!n&&((l=this.rendererHandle)!=null&&l.getData)){let h=this.rendererHandle.getData();if(typeof h=="string"&&h.trim().length>0)try{n=this.normalizeCanvasData(JSON.parse(h))}catch(d){console.debug("Failed to recover Canvas payload from renderer",d)}}let o=(c=t!=null?t:n)!=null?c:this.createEmptyCanvasState();this.pendingCanvasData=o,this.debouncedRenderCanvas()}performRenderCanvas(e){var o,l,c,h;let t=this.activeEntry;if(!t)return;let n=t.file.path,a=this.reselectingActiveEntry;if(this.reselectingActiveEntry=!1,!this.rendererFactory){this.showMessage("Canvas renderer is not available yet. Open a Canvas once to initialise the runtime.");return}if(!this.rendererHandle){this.hostEl.empty();let d=this.hostEl.createDiv("bases-canvas-embed");if(this.rendererHandle=this.rendererFactory(d),!this.rendererHandle){this.hideSidebar(),this.showMessage("Failed to create Canvas renderer.");return}}this.currentCanvasData=this.cloneCanvasPayload(e),this.autoLayoutCompareKey=null,this.suppressNextSave=!1;let i={targetFile:t.file,metadataKey:this.metadataKey,beforeSave:async d=>this.handleBeforeSave(d.data),onSaved:d=>this.handleAfterSave(d.data)};this.activeSession=i,(l=(o=this.rendererHandle).setSession)==null||l.call(o,i),this.lastRenderedEntryPath!==n&&(this.historyRecords=[]),this.stopHistoryRecorder();try{this.rendererHandle.load(this.cloneCanvasPayload(e)),this.lastRenderedEntryPath=n,this.resetCanvasModificationState(),this.startHistoryRecorder()}catch(d){console.error("Failed to load Canvas payload",d),(h=(c=this.rendererHandle).setSession)==null||h.call(c,null),this.showMessage("Unable to load Canvas data.");return}if(this.currentCanvasData.nodes.length===0){if(this.showMessage('Use "Import all" on the left to import entries into the Canvas.'),t)if(this.suppressNextAutoImport)this.pendingFocusEntryPath=null,this.suppressNextAutoImport=!1;else{let d=this.getEntryPath(t);this.pendingFocusEntryPath=d||null,this.importEntries([t])}}else{this.hideMessage();let d=this.getManagedEntryPaths(this.currentCanvasData);if(t){let p=this.getEntryPath(t);if(!p)this.pendingFocusEntryPath=null;else{let v=this.pendingFocusEntryPath===p;d.has(p)||(this.suppressNextAutoImport?(this.pendingFocusEntryPath=null,this.suppressNextAutoImport=!1):(this.pendingFocusEntryPath=p,this.importEntries([t])))}}}if(this.autoLayoutActive){let d=this.getManagedEntryPaths(this.currentCanvasData);d.size>0&&this.applyManagedEntries(d,{triggeredByDataUpdate:!0}),this.autoLayoutActive=!1}let r=this.getEntryPath(t);this.stateSynchronizer.registerInstance(this.instanceId,r,d=>this.applyViewportState(d),d=>this.applyFullCanvasState(d)),this.listenToViewportChanges(),this.registerFileChangeListener(t),this.renderEntryList()}mergeManagedEntries(e,t,n){let a=new Map;for(let d of t){let p=this.getEntryPath(d);!p||a.has(p)||a.set(p,d)}let i=new Map,r=new Set;for(let d of e.nodes){if(!this.isPluginManagedNode(d))continue;let p=this.resolveEntryPathFromNode(d);if(!p||!n.has(p)){r.add(d.id);continue}i.set(p,d);let v=a.get(p);v&&(d.label=v.file.basename,d.type==="file"&&(d.file=p))}r.size>0&&(e.nodes=e.nodes.filter(d=>!r.has(d.id)),e.edges=e.edges.filter(d=>!r.has(d.fromNode)&&!r.has(d.toNode)));let o=[];for(let[d,p]of a)i.has(d)||o.push(p);let l=e.nodes.filter(d=>{if(!this.isPluginManagedNode(d))return!1;let p=this.getNodeMeta(d);return!!(p!=null&&p.entryPath)&&n.has(p.entryPath)});if(o.length>0){let d=this.createNodesForEntries(o);this.applyGridLayout(d);let p=this.computeManagedBounds(l);if(p){let v=p.maxX+qe,f=p.minY;for(let m of d)m.x+=v,m.y+=f}for(let v of d){let f=this.getNodeMeta(v);f!=null&&f.entryPath&&i.set(f.entryPath,v)}e.nodes.push(...d)}let c=new Set,h=[];for(let[d,p]of i){let v=a.get(d);v&&(c.add(p.id),h.push(v))}if(c.size>0){e.edges=e.edges.filter(p=>!this.isManagedEdge(p,c));let d=this.buildEdgesForEntries(h,e.nodes);e.edges.push(...d)}}rebuildManagedEntries(e,t){if(this.removeManagedGraph(e),t.length===0)return;let n=this.createNodesForEntries(t);this.applyGridLayout(n),e.nodes.push(...n);let a=this.buildEdgesForEntries(t,e.nodes);e.edges.push(...a)}getCanvasPayload(e){let t=this.readCanvasConfig(e);return t||this.buildCanvasFromSettings(e)}async handleBeforeSave(e){var v,f,m;let t=Date.now(),n=t-this.lastSaveCheckTime;if(n<this.saveCheckThrottleMs&&this.lastDataSignature!==null)return console.debug(`[Canvas Save] Throttled (${n}ms since last check)`),null;if(this.lastSaveCheckTime=t,this.markCanvasAsModified(),this.suppressNextSave)return this.suppressNextSave=!1,null;let a;try{a=this.normalizeCanvasData(JSON.parse(e))}catch(b){return console.error("Failed to parse Canvas payload before save",b),e}let i=this.computeContentSignature(a);if(i===this.lastDataSignature)return console.debug("Canvas content unchanged, skipping save"),null;this.lastDataSignature=i;let r=this.computeCanvasCompareKey(a);if(this.autoLayoutCompareKey&&r&&r===this.autoLayoutCompareKey)return null;this.autoLayoutCompareKey=null,this.autoLayoutActive=!1;for(let b of a.nodes){let D=this.getNodeMeta(b);D!=null&&D.autoPlaced&&(D.autoPlaced=!1,this.setNodeMeta(b,D))}let o=this.computeManagedEntrySignature(this.currentCanvasData);this.currentCanvasData=this.cloneCanvasPayload(a);let l=this.computeManagedEntrySignature(this.currentCanvasData);this.skipNextDataRefresh=o===l;let c=(v=this.activeEntry)!=null?v:null,h=(f=c==null?void 0:c.file)!=null?f:null,d=((m=h==null?void 0:h.extension)==null?void 0:m.toLowerCase())==="md",p=this.getEntryPathsFromCanvas(a);if(this.syncEntryCanvasConfigs(p,p.size>0?a:null),!d)return await this.persistNonMarkdownPositions(a),null;try{return JSON.stringify(a)}catch(b){return console.error("Failed to serialise Canvas payload",b),e}}handleAfterSave(e){try{this.lastSaveTimestamp=Date.now(),this.currentCanvasData=this.normalizeCanvasData(JSON.parse(e)),this.debouncedBroadcastState()}catch(t){console.error("Failed to parse Canvas payload after save",t)}}performBroadcastState(){try{if(this.activeEntry&&!this.stateSynchronizer.isInstanceUpdating(this.instanceId)){let e=this.getEntryPath(this.activeEntry),n={viewport:this.getViewportState()||{x:0,y:0,zoom:1},nodes:this.currentCanvasData.nodes,edges:this.currentCanvasData.edges,timestamp:Date.now(),instanceId:this.instanceId};this.stateSynchronizer.updateFullState(this.instanceId,e,n),console.debug("[Canvas View] Broadcasted full state after save")}else this.activeEntry&&console.debug("[Canvas View] Skipping broadcast - instance is being updated")}catch(e){console.error("Failed to broadcast canvas state",e)}}importEntries(e){if(!e||e.length===0)return;let t=this.getManagedEntryPaths();for(let n of e){let a=this.getEntryPath(n);a&&t.add(a)}this.applyManagedEntries(t)}importAllEntries(){let e=this.getRenderableEntries(),t=new Set;for(let n of e){let a=this.getEntryPath(n);a&&t.add(a)}this.applyManagedEntries(t)}clearImportedEntries(){this.suppressNextAutoImport=!0,this.pendingFocusEntryPath=null,this.applyManagedEntries(new Set)}applyManagedEntries(e,t={}){var d,p,v,f,m,b,D,k,L;let n=this.activeEntry;if(!n)return;let a=new Set;for(let S of e){let P=this.canonicalizeEntryPath(S);P&&a.add(P)}if(!this.rendererHandle&&(this.renderCanvas(),!this.rendererHandle))return;let i=this.getRenderableEntries().filter(S=>{var M;let P=this.getEntryPath(S);if(P&&a.has(P))return!0;let g=this.findEntryByBasename(S.file.basename);if(!g)return!1;let C=(M=this.getBasenameFrequency(this.getManagedEntryIdentifiers().basenames,g.file.basename))!=null?M:0;return this.getEntryBasenameCounts(this.getRenderableEntries()).get(g.file.basename)===1&&C>0}),r=this.cloneCanvasPayload((d=this.currentCanvasData)!=null?d:this.createEmptyCanvasState());t.triggeredByDataUpdate?this.rebuildManagedEntries(r,i):this.mergeManagedEntries(r,i,a);let o=(p=this.activeSession)!=null?p:null;this.suppressNextSave=!0,this.autoLayoutCompareKey=this.computeCanvasCompareKey(r),this.currentCanvasData=this.cloneCanvasPayload(r);try{(v=this.rendererHandle)==null||v.load(this.cloneCanvasPayload(r)),o&&((m=(f=this.rendererHandle)==null?void 0:f.setSession)==null||m.call(f,o))}catch(S){console.error("Failed to apply Canvas import",S),o&&((D=(b=this.rendererHandle)==null?void 0:b.setSession)==null||D.call(b,o));return}let l=this.pendingFocusEntryPath;if(l){let S=null;this.activeEntry&&this.getEntryPath(this.activeEntry)===l&&(S=this.activeEntry),S||(S=(k=i.find(P=>this.getEntryPath(P)===l))!=null?k:null)}let c=(L=n.file.extension)==null?void 0:L.toLowerCase(),h=this.getEntryPathsFromCanvas(r);this.syncEntryCanvasConfigs(h,h.size>0?r:null),c&&c!=="md"&&this.persistNonMarkdownPositions(r),t.triggeredByDataUpdate||(this.autoLayoutActive=!1),a.size===0?this.showMessage('No entries imported yet. Select entries or use "Import all".'):this.hideMessage(),this.renderEntryList()}getRenderableEntries(){var e,t;return(t=(e=this.data)==null?void 0:e.data)!=null?t:[]}getManagedEntryPaths(e=this.currentCanvasData){return this.getManagedEntryIdentifiers(e).paths}getManagedEntryIdentifiers(e=this.currentCanvasData){var a;let t=new Set,n=new Map;if(!e)return{paths:t,basenames:n};for(let i of e.nodes){let r=this.resolveEntryPathFromNode(i);if(!r)continue;t.add(r);let o=this.getPathBasename(r);o&&n.set(o,((a=n.get(o))!=null?a:0)+1)}return{paths:t,basenames:n}}getEntryBasenameCounts(e){var n;let t=new Map;for(let a of e){let i=a.file.basename;t.set(i,((n=t.get(i))!=null?n:0)+1)}return t}computeRenderableEntriesSignature(e){if(!e||e.length===0)return"";let t=[];for(let n of e){let a=this.getEntryPath(n);a&&t.push(a)}return t.length===0?"":(t.sort((n,a)=>n.localeCompare(a)),t.join("|"))}getEntryPathsFromCanvas(e){let t=new Set;for(let n of e.nodes){let a=this.resolveEntryPathFromNode(n);a&&t.add(a)}return t}getBasenameFrequency(e,t){return e.get(t)}findEntryByBasename(e){if(!e)return null;let t=this.getRenderableEntries(),n=null;for(let a of t)if(a.file.basename===e){if(n)return null;n=a}return n}computeManagedEntrySignature(e){return e?Array.from(this.getEntryPathsFromCanvas(e)).sort().join("|"):""}computeManagedBounds(e){if(e.length===0)return null;let t=Number.POSITIVE_INFINITY,n=Number.POSITIVE_INFINITY,a=Number.NEGATIVE_INFINITY,i=Number.NEGATIVE_INFINITY,r=!1;for(let o of e){let l=typeof o.x=="number"?o.x:0,c=typeof o.y=="number"?o.y:0,h=typeof o.width=="number"?o.width:ue,d=typeof o.height=="number"?o.height:pe;t=Math.min(t,l),n=Math.min(n,c),a=Math.max(a,l+h),i=Math.max(i,c+d),r=!0}return r?{minX:t,maxX:a,minY:n,maxY:i}:null}removeManagedGraph(e){let t=new Set(e.nodes.filter(n=>this.isPluginManagedNode(n)).map(n=>n.id));t.size!==0&&(e.nodes=e.nodes.filter(n=>!t.has(n.id)),e.edges=e.edges.filter(n=>!this.isManagedEdge(n,t)))}createNodesForEntries(e){let t=[];for(let n of e)t.push(this.createNodeForEntry(n));return t}createNodeForEntry(e){let t=this.getEntryPath(e),a={id:this.getNodeIdForPath(t),type:"file",file:t,label:e.file.basename,x:0,y:0,width:ue,height:pe,unknownData:{}};return this.setNodeMeta(a,{entryPath:t,autoPlaced:!0}),a}applyGridLayout(e){if(e.length===0)return;let t=Math.max(1,Math.ceil(Math.sqrt(e.length))),n=ue,a=pe,i=qe,r=ot;for(let o=0;o<e.length;o++){let l=o%t,c=Math.floor(o/t),h=e[o];h.x=l*(n+i),h.y=c*(a+r)}}buildEdgesForEntries(e,t){if(e.length===0||t.length===0)return[];let n=new Map;for(let r of t){let o=this.getNodeMeta(r);o!=null&&o.entryPath&&n.set(o.entryPath,r)}let a=[],i=new Set;for(let r of e){let o=this.getEntryPath(r),l=n.get(o);if(!l)continue;let c=this.extractOutgoingLinks(r);for(let h of c){let d=this.resolveLinkTarget(h,r.file);if(!d)continue;let p=this.canonicalizeEntryPath(d.path),v=n.get(p);if(!v)continue;let f=`${l.id}->${v.id}`;i.has(f)||(i.add(f),a.push({id:`edge-${f}`,fromNode:l.id,toNode:v.id,fromSide:"right",toSide:"left",fromEnd:"none",toEnd:"arrow"}))}}return a}extractOutgoingLinks(e){var r,o,l;let t=(r=this.app.metadataCache.getFileCache(e.file))==null?void 0:r.frontmatter;if(!t)return[];let n=new Set,a=c=>{if(c==null)return;if(Array.isArray(c)){for(let p of c)a(p);return}let d=(typeof c=="string"?c:String(c)).trim();d.length>0&&n.add(d)},i=((l=(o=this.getLinkMetadataKey)==null?void 0:o.call(this))!=null?l:"").trim();return i.length>0&&a(t[i]),Array.from(n)}resolveLinkTarget(e,t){var i;if(!e||typeof e!="string")return null;let n=e.trim();if(n.length===0)return null;let a=n;if(n.startsWith("[[")&&n.endsWith("]]")){let r=n.slice(2,-2),o=r.indexOf("|");a=o>=0?r.substring(0,o):r}return(i=this.app.metadataCache.getFirstLinkpathDest(a,t.path))!=null?i:null}computeCanvasCompareKey(e){let t=e.nodes.map(i=>{let r=this.getNodeMeta(i);return!(r!=null&&r.entryPath)||r.autoPlaced!==!0?null:{entryPath:r.entryPath,x:i.x,y:i.y,width:i.width,height:i.height}}).filter(i=>i!=null).sort((i,r)=>i.entryPath.localeCompare(r.entryPath));if(t.length===0)return null;let n=new Set(e.nodes.filter(i=>{let r=this.getNodeMeta(i);return(r==null?void 0:r.entryPath)&&r.autoPlaced===!0}).map(i=>i.id)),a=e.edges.filter(i=>n.has(i.fromNode)&&n.has(i.toNode)).map(i=>({from:i.fromNode,to:i.toNode})).sort((i,r)=>i.from===r.from?i.to.localeCompare(r.to):i.from.localeCompare(r.from));return JSON.stringify({nodes:t,edges:a})}buildCanvasFromSettings(e){let t=this.getEntryPath(e),n=this.getStoredPositionsForCanvas(t,e.file.path);if(!n)return null;let a=this.getRenderableEntries();if(a.length===0)return this.createEmptyCanvasState();let i=this.createNodesForEntries(a);this.applyStoredPositionsToNodes(i,n);let r=i.filter(l=>{let c=this.getNodeMeta(l);return!(c!=null&&c.entryPath)||!n[c.entryPath]});r.length>0&&this.applyGridLayout(r);let o=this.buildEdgesForEntries(a,i);return{nodes:i,edges:o,x:0,y:0,zoom:1}}getStoredPositionsForCanvas(e,t){var l,c,h;let n=this.canonicalizeEntryPath(e),a=t&&t!==n?t:void 0,i=(l=this.readNonMarkdownPositions)==null?void 0:l.call(this);if(!i)return null;let r=(c=i[n])!=null?c:a?i[a]:void 0;if(!r||typeof r!="object")return null;let o={};for(let[d,p]of Object.entries(r)){if(!p||typeof p!="object")continue;let v=typeof p.note=="string"&&p.note.trim().length>0?p.note:d,f=this.canonicalizeEntryPath(v);if(!f||f.trim().length===0)continue;let m=(h=p.pos)!=null?h:p.pos;if(!m||typeof m!="object")continue;let b=typeof m.x=="number"?m.x:0,D=typeof m.y=="number"?m.y:0;o[f]={note:f,pos:{x:b,y:D}}}return Object.keys(o).length>0?o:null}async persistNonMarkdownPositions(e){let t=this.activeEntry;if(!t)return;let n=this.buildPositionSnapshot(e),a=this.getEntryPath(t);await this.writeNonMarkdownPositions(a,n)}buildPositionSnapshot(e){let t={};for(let n of e.nodes){let a=this.getNodeMeta(n);if(!(a!=null&&a.entryPath))continue;let i=this.canonicalizeEntryPath(a.entryPath);if(!i||i.trim().length===0)continue;let r=Number.isFinite(n.x)?n.x:0,o=Number.isFinite(n.y)?n.y:0;t[i]={note:i,pos:{x:r,y:o}}}return t}getEntryPath(e){let t=this.canonicalizeEntryPath(e.file.path);return t&&t.length>0?t:typeof e.file.path=="string"?e.file.path.trim():""}applyStoredPositionsToNodes(e,t){for(let n of e){let a=this.getNodeMeta(n);if(!(a!=null&&a.entryPath))continue;let i=t[a.entryPath];i&&(typeof i.pos.x=="number"&&(n.x=i.pos.x),typeof i.pos.y=="number"&&(n.y=i.pos.y),a.autoPlaced=!1,this.setNodeMeta(n,a))}}normalizeCanvasData(e){var i;if(!e||typeof e!="object")return this.createEmptyCanvasState();let t=e,n=[];if(Array.isArray(t.nodes))for(let r of t.nodes){if(!r||typeof r!="object")continue;let o=r,l={id:typeof o.id=="string"?o.id:this.generateNodeId(typeof o.file=="string"?o.file:void 0),type:(i=o.type)!=null?i:"file",file:typeof o.file=="string"?o.file:void 0,text:typeof o.text=="string"?o.text:void 0,label:typeof o.label=="string"?o.label:void 0,x:typeof o.x=="number"?o.x:0,y:typeof o.y=="number"?o.y:0,width:typeof o.width=="number"?o.width:ue,height:typeof o.height=="number"?o.height:pe,styleAttributes:o.styleAttributes?{...o.styleAttributes}:void 0,color:o.color,unknownData:o.unknownData?{...o.unknownData}:void 0};n.push(l)}let a=[];if(Array.isArray(t.edges))for(let r of t.edges){if(!r||typeof r!="object")continue;let o=r;if(typeof o.fromNode!="string"||typeof o.toNode!="string")continue;let l={id:typeof o.id=="string"?o.id:`edge-${o.fromNode}-${o.toNode}`,fromNode:o.fromNode,toNode:o.toNode,fromSide:o.fromSide,toSide:o.toSide,fromEnd:o.fromEnd,toEnd:o.toEnd,styleAttributes:o.styleAttributes?{...o.styleAttributes}:void 0,label:o.label};a.push(l)}return{nodes:n,edges:a,x:typeof t.x=="number"?t.x:void 0,y:typeof t.y=="number"?t.y:void 0,zoom:typeof t.zoom=="number"?t.zoom:void 0}}getNodeMeta(e){if(!e.unknownData)return null;let t=e.unknownData[Ae],n=null;if(!t){for(let o of Ke)if(Object.prototype.hasOwnProperty.call(e.unknownData,o)){t=e.unknownData[o],n=o;break}}if(!t||typeof t!="object")return null;let a=t,i;typeof a.entryPath=="string"&&(i=this.canonicalizeEntryPath(a.entryPath));let r={entryPath:i,autoPlaced:typeof a.autoPlaced=="boolean"?a.autoPlaced:void 0};return n&&this.setNodeMeta(e,{entryPath:i,autoPlaced:typeof a.autoPlaced=="boolean"?a.autoPlaced:void 0}),r}setNodeMeta(e,t){let n={entryPath:typeof t.entryPath=="string"?this.canonicalizeEntryPath(t.entryPath):void 0,autoPlaced:t.autoPlaced};e.unknownData||(e.unknownData={}),e.unknownData[Ae]=n;for(let a of Ke)a in e.unknownData&&a!==Ae&&delete e.unknownData[a]}resolveEntryPathFromNode(e){var i;let t=this.getNodeMeta(e),n=(i=t==null?void 0:t.entryPath)!=null?i:null,a=null;if(e.type==="file"&&typeof e.file=="string"){let r=e.file.trim();r.length>0&&(a=this.canonicalizeEntryPath(r))}return n&&a&&n!==a?(this.setNodeMeta(e,{entryPath:a,autoPlaced:t==null?void 0:t.autoPlaced}),a):n||a}canonicalizeEntryPath(e){let t=typeof e=="string"?e.trim():"";if(!t)return"";if(t.includes("://"))return t;let n=t;try{n=(0,y.normalizePath)(t)}catch(i){n=t}let a=this.app.vault.getAbstractFileByPath(n);return a instanceof y.TFile?a.path:n}getPathBasename(e){let t=this.canonicalizeEntryPath(e);if(!t)return null;let n=t.lastIndexOf("/"),i=(n>=0?t.substring(n+1):t).trim();return i.length>0?i:null}isPluginManagedNode(e){let t=this.getNodeMeta(e);return!!(t!=null&&t.entryPath)}isManagedEdge(e,t){return t.has(e.fromNode)||t.has(e.toNode)}getNodeIdForPath(e){return this.generateNodeId(e)}generateNodeId(e){let t=e!=null?e:Math.random().toString(36),n=0;for(let a=0;a<t.length;a++)n=(n<<5)-n+t.charCodeAt(a),n|=0;return`bases-${Math.abs(n).toString(36)}`}detachRendererSession(){if(this.rendererHandle&&this.rendererHandle.setSession)try{this.rendererHandle.setSession(null)}catch(e){console.error("Failed to detach Canvas renderer session",e)}this.activeSession=null}destroyRenderer(){if(this.detachRendererSession(),this.stopHistoryRecorder(),this.rendererHandle)try{this.rendererHandle.destroy()}catch(e){console.error("Failed to dispose Canvas renderer",e)}this.rendererHandle=null,this.currentCanvasData=null,this.autoLayoutCompareKey=null,this.autoLayoutActive=!1,this.pendingFocusEntryPath=null,this.lastRenderedEntryPath=null,this.reselectingActiveEntry=!1,this.skipNextDataRefresh=!1,this.hostEl.empty()}createEmptyCanvasState(){return{nodes:[],edges:[],x:0,y:0,zoom:1}}getConfigKeyForEntry(e){let t=this.getEntryPath(e);return t&&t.length>0?t:e.file.path}readCanvasConfig(e){let t=this.config.get(Le);if(!t||typeof t!="object"||Array.isArray(t))return null;let n=t,a=n.managedPaths;if(!Array.isArray(a))return null;let i=this.getConfigKeyForEntry(e),r=this.canonicalizeEntryPath(i),o=a.map(c=>typeof c=="string"?this.canonicalizeEntryPath(c.trim()):"").filter(c=>c.length>0);if(!r||!o.includes(r))return null;let l=n.canvas;if(l==null)return null;try{if(typeof l=="string")return this.normalizeCanvasData(JSON.parse(l));if(typeof l=="object")return this.normalizeCanvasData(l)}catch(c){console.error("Failed to parse Canvas payload from Base config",c)}return null}syncEntryCanvasConfigs(e,t){let n=new Set;for(let i of e){let r=this.canonicalizeEntryPath(i);r&&n.add(r)}if(!t||n.size===0){let i={canvas:null,managedPaths:[]};this.config.set(Le,i);return}let a={canvas:this.cloneCanvasPayload(t),managedPaths:Array.from(n).sort((i,r)=>i.localeCompare(r))};this.config.set(Le,a)}cloneCanvasPayload(e){if(e==null)return e;if(typeof structuredClone=="function")try{return structuredClone(e)}catch(t){}try{return JSON.parse(JSON.stringify(e))}catch(t){return e}}showMessage(e){this.messageEl.setText(e),this.messageEl.removeClass("is-hidden"),this.hostEl.addClass("is-hidden")}hideMessage(){this.messageEl.addClass("is-hidden"),this.hostEl.removeClass("is-hidden")}hideSidebar(){var e,t;(e=this.sidebarToggleEl)==null||e.hide(),(t=this.sidebarEl)==null||t.hide()}showSidebar(){var e,t;(e=this.sidebarToggleEl)==null||e.show(),(t=this.sidebarEl)==null||t.show()}getFrontmatterPropertyName(e){return!e||!e.startsWith("note.")?null:e.substring(5)}saveCanvasAsFile(){if(!this.activeEntry){new y.Notice("No active entry to save canvas from");return}if(!this.currentCanvasData||this.currentCanvasData.nodes.length===0){new y.Notice("Canvas is empty. Nothing to save.");return}let e=Ne(this.activeEntry.file),t=Me(this.activeEntry.file);new X(this.app,e,t,async a=>{await this.performCanvasSave(a)}).open()}async performCanvasSave(e){if(!this.currentCanvasData){new y.Notice("No canvas data to save");return}try{let t=Te(this.currentCanvasData),n=await Fe(this.app,t,e);new y.Notice(`Canvas saved to ${n.path}`)}catch(t){console.error("Failed to save canvas file:",t);let n=t instanceof Error?t.message:"Unknown error occurred";new y.Notice(`Failed to save canvas: ${n}`)}}markCanvasAsModified(){this.canvasModified=!0}resetCanvasModificationState(){this.canvasModified=!1,this.initialCanvasDataSignature=this.computeCanvasDataSignature(this.currentCanvasData)}computeCanvasDataSignature(e){if(!e)return null;try{return JSON.stringify(e)}catch(t){return null}}computeContentSignature(e){var t,n,a;if(!e)return null;try{let i=e.nodes.map(l=>({id:l.id,type:l.type,file:l.file,label:l.label,x:Math.round(l.x/10)*10,y:Math.round(l.y/10)*10,width:l.width,height:l.height})),r=e.edges.map(l=>({from:l.fromNode,to:l.toNode,fromSide:l.fromSide,toSide:l.toSide})),o={x:Math.round(((t=e.x)!=null?t:0)/10)*10,y:Math.round(((n=e.y)!=null?n:0)/10)*10,zoom:Math.round(((a=e.zoom)!=null?a:1)*100)/100};return JSON.stringify({nodes:i,edges:r,viewport:o})}catch(i){return null}}hasCanvasBeenModified(){return this.canvasModified?!0:this.computeCanvasDataSignature(this.currentCanvasData)!==this.initialCanvasDataSignature}async confirmCanvasSaveBeforeDataChange(){return new Promise(e=>{let t=()=>{new de(this.app,"You have unsaved changes in the canvas. The filter change will clear the current entries. Do you want to save before proceeding?",async a=>{switch(a){case"save":{await this.openSaveDialogAndWait()?e(!0):t();break}case"discard":e(!0);break;case"cancel":e(!1);break}}).open()};t()})}async autoSaveCanvas(e){if(!(!this.currentCanvasData||!this.activeEntry))try{let t=new Date,n=t.toISOString().split("T")[0],a=t.toISOString().split("T")[1].split(".")[0].replace(/:/g,""),i=`${n}-${a}`,r=this.activeEntry.file.basename,o=`${i}-${r}-autosave.canvas`,l=e?`${e.trim()}/${o}`:o,c=Te(this.currentCanvasData);await Fe(this.app,c,l),new y.Notice(`Canvas auto-saved to ${l}`),this.resetCanvasModificationState()}catch(t){console.error("Auto-save failed:",t),new y.Notice("Failed to auto-save canvas. See console for details.")}}async openSaveDialogAndWait(){return this.activeEntry?!this.currentCanvasData||this.currentCanvasData.nodes.length===0?(new y.Notice("Canvas is empty. Nothing to save."),!1):new Promise(e=>{let t=!1,n=Ne(this.activeEntry.file),a=Me(this.activeEntry.file),i=new X(this.app,n,a,async o=>{try{await this.performCanvasSave(o),t=!0,e(!0)}catch(l){console.error("Failed to save canvas:",l),e(!1)}}),r=i.onClose.bind(i);i.onClose=function(){r.call(this),t||e(!1)},i.open()}):(new y.Notice("No active entry to save canvas from"),!1)}applyViewportState(e){let t=this.getRuntimeCanvas();if(t){this.suppressViewportBroadcast=!0,setTimeout(()=>{this.suppressViewportBroadcast=!1},1e3),this.lastViewportState={...e};try{let n=t;typeof n.setViewport=="function"?n.setViewport(e.x,e.y,e.zoom):(n.x=e.x,n.y=e.y,n.zoom=e.zoom,typeof n.requestFrame=="function"&&n.requestFrame())}catch(n){console.debug("Failed to apply viewport state",n)}}}applyFullCanvasState(e){var i;if(e.instanceId===this.instanceId)return;let t=((i=this.currentCanvasData)==null?void 0:i.timestamp)||0;if(e.timestamp<=t){console.debug("[Canvas View] Ignoring older canvas state from",e.instanceId);return}let n=this.activeEntry?this.getEntryPath(this.activeEntry):null,a=async()=>{try{console.log(`[Canvas View] Applying full state from instance ${e.instanceId}`),this.currentCanvasData={nodes:e.nodes,edges:e.edges,timestamp:e.timestamp},this.lastViewportState={...e.viewport},this.suppressNextSave=!0,this.suppressViewportBroadcast=!0,setTimeout(()=>{this.suppressNextSave=!1,this.suppressViewportBroadcast=!1},5e3),this.rendererHandle&&this.rendererHandle.load(this.cloneCanvasPayload(this.currentCanvasData)),this.applyViewportState(e.viewport),console.log(`[Canvas View] Successfully applied state from ${e.instanceId}`)}catch(r){console.error("[Canvas View] Failed to apply full canvas state",r)}};n?this.stateSynchronizer.runExclusive(n,a):a()}listenToViewportChanges(){this.viewportSyncIntervalId!==null&&clearInterval(this.viewportSyncIntervalId);let e=(0,y.debounce)(()=>{try{if(this.suppressViewportBroadcast||this.stateSynchronizer.isInstanceUpdating(this.instanceId))return;let t=this.getViewportState();if(t&&this.activeEntry&&this.hasViewportChanged(t)){let n=this.getEntryPath(this.activeEntry);this.stateSynchronizer.updateViewport(this.instanceId,n,t),this.lastViewportState=t}}catch(t){console.debug("Failed to capture viewport state",t)}},200);this.viewportSyncIntervalId=window.setInterval(e,500)}hasViewportChanged(e){if(!this.lastViewportState)return!0;let t=.001;return Math.abs(e.x-this.lastViewportState.x)>t||Math.abs(e.y-this.lastViewportState.y)>t||Math.abs(e.zoom-this.lastViewportState.zoom)>t}getViewportState(){let e=this.getRuntimeCanvas();if(!e)return null;try{let t=e;return{x:typeof t.x=="number"?t.x:0,y:typeof t.y=="number"?t.y:0,zoom:typeof t.zoom=="number"?t.zoom:1}}catch(t){return null}}registerFileChangeListener(e){this.fileChangeUnsubscribe&&(this.fileChangeUnsubscribe(),this.fileChangeUnsubscribe=null);let t=e.file.path,n=this.app.metadataCache.on("changed",a=>{a.path===t&&this.handleFileChanged(a)});this.fileChangeUnsubscribe=()=>{this.app.metadataCache.offref(n)},console.debug(`[File Watcher] Registered listener for ${t}`)}async handleFileChanged(e){try{let t=await this.app.vault.adapter.stat(e.path);if(!t)return;let n=this.lastFileModTime.get(e.path)||0,a=t.mtime;if(a<=n)return;if(this.lastFileModTime.set(e.path,a),Date.now()-this.lastSaveTimestamp<1e3){console.debug("[File Watcher] Ignoring own save");return}console.log("[File Watcher] Detected external file change, reloading..."),await this.reloadCanvasFromFile()}catch(t){console.error("[File Watcher] Error handling file change",t)}}async reloadCanvasFromFile(){if(this.activeEntry)try{let e=this.getCanvasPayload(this.activeEntry);if(!e){console.debug("[File Watcher] No data to reload");return}let t=this.computeContentSignature(e);if(t===this.lastDataSignature){console.debug("[File Watcher] Data unchanged, skipping reload");return}this.suppressNextSave=!0,setTimeout(()=>{this.suppressNextSave=!1},5e3),this.currentCanvasData=e,this.rendererHandle&&(this.rendererHandle.load(this.cloneCanvasPayload(e)),this.lastDataSignature=t,console.log("[File Watcher] Canvas reloaded successfully"))}catch(e){console.error("[File Watcher] Failed to reload canvas",e)}}static getViewOptions(){return[{displayName:"Link key",type:"text",key:"metadataKey",placeholder:"linkTo"}]}};var O=require("obsidian");var _e=require("obsidian"),lt={minColumnWidth:320,maxColumnWidth:Number.POSITIVE_INFINITY,columnGap:16,rowGap:16,containerPadding:16},Q=class extends _e.Component{constructor(e,t){super();this.columnCount=1;this.columnWidth=0;this.horizontalOffset=0;this.columnHeights=[];this.resizeObserver=null;this.items=[];this.container=e,this.config={...lt,...t},this.setupContainer(),this.setupResizeObserver(),this.calculateColumns()}setupContainer(){this.container.style.position="relative",this.container.style.padding=`${this.config.containerPadding}px`}setupResizeObserver(){let e=null;this.resizeObserver=new ResizeObserver(()=>{e!==null&&window.cancelAnimationFrame(e),e=window.requestAnimationFrame(()=>{this.calculateColumns(),this.layout(),e=null})}),this.resizeObserver.observe(this.container);let t=this.container.parentElement;t&&this.resizeObserver.observe(t)}calculateColumns(){var h;if(this.container.clientWidth===0&&this.container.offsetParent===null)return;let e=this.container.clientWidth,t=Math.max(0,e-this.config.containerPadding*2),n=t*.04,a=Math.max(0,t-n*2),i=Math.max(1,Math.floor((a+this.config.columnGap)/(this.config.minColumnWidth+this.config.columnGap)));i!==this.columnCount?(this.columnCount=i,this.columnHeights=new Array(this.columnCount).fill(0)):this.columnHeights.length!==this.columnCount&&(this.columnHeights=new Array(this.columnCount).fill(0));let r=(this.columnCount-1)*this.config.columnGap,o=this.columnCount>0?(a-r)/this.columnCount:a,l=(h=this.config.maxColumnWidth)!=null?h:Number.POSITIVE_INFINITY;this.columnWidth=Math.max(0,Math.min(o,l));let c=this.columnWidth*this.columnCount+r;this.horizontalOffset=this.config.containerPadding+n/2+Math.max(0,(a-c)/2)}getColumnWidth(){return this.columnWidth<=0&&this.calculateColumns(),this.columnWidth}getShortestColumnIndex(){let e=this.columnHeights[0],t=0;for(let n=1;n<this.columnHeights.length;n++)this.columnHeights[n]<e&&(e=this.columnHeights[n],t=n);return t}calculatePosition(e){let t=this.getShortestColumnIndex(),n=this.config.containerPadding+this.horizontalOffset+t*(this.getColumnWidth()+this.config.columnGap),a=this.config.containerPadding+this.columnHeights[t];return this.columnHeights[t]+=e+this.config.rowGap,{column:t,left:n,top:a}}addItem(e){this.items.push(e),this.container.appendChild(e),e.style.position="absolute",e.style.width=`${this.getColumnWidth()}px`,e.style.opacity="0"}clear(){this.items.forEach(e=>e.remove()),this.items=[],this.columnHeights=new Array(this.columnCount).fill(0),this.updateContainerHeight()}layout(){if(this.items.length===0){this.updateContainerHeight();return}if(this.container.clientWidth===0&&this.container.offsetParent===null){let e=()=>{this.container.clientWidth>0||this.container.offsetParent!==null?(this.calculateColumns(),this.performLayout()):setTimeout(e,100)};setTimeout(e,100);return}this.calculateColumns(),this.performLayout()}performLayout(){if(this.items.length===0){this.updateContainerHeight();return}this.columnHeights=new Array(this.columnCount).fill(0);let e=this.getColumnWidth();this.items.forEach(t=>{t.style.width=`${e}px`,t.offsetHeight;let n=t.offsetHeight,a=this.calculatePosition(n);t.style.left=`${a.left}px`,t.style.top=`${a.top}px`,t.style.opacity="1"}),this.updateContainerHeight()}updateContainerHeight(){if(this.columnHeights.length===0){this.container.style.height=`${this.config.containerPadding}px`;return}let e=Math.max(...this.columnHeights,0);this.container.style.height=`${e+this.config.containerPadding}px`}forceLayout(){this.calculateColumns(),this.layout()}getColumnCount(){return this.columnCount}getItems(){return this.items}removeItem(e){let t=this.items.indexOf(e);t>-1&&(this.items.splice(t,1),e.remove(),this.layout())}onunload(){this.resizeObserver&&(this.resizeObserver.disconnect(),this.resizeObserver=null),this.clear()}destroy(){this.onunload()}};var U=require("obsidian");var R=require("obsidian"),V="http://www.w3.org/2000/svg",ee=240,ve=160,ct=48,dt=400,Be={1:"#5b8def",2:"#6cbf7d",3:"#f1a85b",4:"#d8667b",5:"#9d7be6",6:"#60b7c6"},ge=class extends R.Component{constructor(e){var n;super();this.svgEl=null;this.hoverToken=0;this.hoverPopover=null;this.fileContentCache=new Map;this.canvasFile=null;this.canvasData=null;this.highlightedNodeIds=new Set;this.containerEl=e.containerEl,this.app=e.app,this.sourcePath=e.sourcePath,this.maxPreviewLength=(n=e.maxPreviewLength)!=null?n:dt;let t=typeof crypto!="undefined"&&"randomUUID"in crypto?crypto.randomUUID():Math.random().toString(36).slice(2);this.markerId=`canvas-svg-preview-arrow-${t}`,this.hoverParent={hoverPopover:null},this.debouncedUpdateHoverPosition=(0,R.debounce)(a=>this.updateHoverPosition(a),50)}loadCanvas(e,t){var i;if(this.reset(),!e||!Array.isArray(e.nodes)||e.nodes.length===0){this.showPlaceholder("No nodes");return}let n=this.app.vault.getAbstractFileByPath(this.sourcePath);n instanceof R.TFile&&(this.canvasFile=n),this.canvasData=e,this.highlightedNodeIds=t!=null?t:new Set;let a=this.computeBounds(e.nodes);this.createSvgRoot(a),this.renderEdges((i=e.edges)!=null?i:[],e.nodes),this.renderNodes(e.nodes)}updateHighlightedNodes(e){if(this.highlightedNodeIds=e!=null?e:new Set,!this.svgEl)return;this.svgEl.querySelectorAll(".canvas-svg-preview-node").forEach(n=>{let a=n.getAttribute("data-node-id");a&&(this.highlightedNodeIds.has(a)?n.classList.add("is-highlighted"):n.classList.remove("is-highlighted"))})}destroy(){this.onunload()}onunload(){this.reset(),this.disposeHoverPopover()}reset(){this.clearHoverState(),this.svgEl&&(this.svgEl.remove(),this.svgEl=null),this.containerEl.empty(),this.canvasFile=null,this.canvasData=null}showPlaceholder(e){this.containerEl.createDiv("canvas-preview-placeholder").setText(e)}computeBounds(e){let t=Number.POSITIVE_INFINITY,n=Number.POSITIVE_INFINITY,a=Number.NEGATIVE_INFINITY,i=Number.NEGATIVE_INFINITY;for(let c of e){let h=c.width||ee,d=c.height||ve;t=Math.min(t,c.x),n=Math.min(n,c.y),a=Math.max(a,c.x+h),i=Math.max(i,c.y+d)}(!isFinite(t)||!isFinite(n))&&(t=0,n=0,a=ee,i=ve);let r=Math.max(a-t,1),o=Math.max(i-n,1),l=Math.max(ct,Math.min(r,o)*.1);return{minX:t-l,minY:n-l,width:r+l*2,height:o+l*2}}createSvgRoot(e){let t=document.createElementNS(V,"svg");t.classList.add("canvas-svg-preview"),t.setAttribute("viewBox",`${e.minX} ${e.minY} ${e.width} ${e.height}`),t.setAttribute("preserveAspectRatio","xMidYMid meet"),t.setAttribute("width","100%"),t.setAttribute("height","100%");let n=document.createElementNS(V,"defs"),a=document.createElementNS(V,"marker");a.setAttribute("id",this.markerId),a.setAttribute("viewBox","0 0 10 10"),a.setAttribute("refX","8"),a.setAttribute("refY","5"),a.setAttribute("markerWidth","6"),a.setAttribute("markerHeight","6"),a.setAttribute("orient","auto-start-reverse");let i=document.createElementNS(V,"path");i.setAttribute("d","M 0 0 L 10 5 L 0 10 z"),i.setAttribute("fill","currentColor"),a.appendChild(i),n.appendChild(a),t.appendChild(n);let r=document.createElementNS(V,"rect");r.setAttribute("x",e.minX.toString()),r.setAttribute("y",e.minY.toString()),r.setAttribute("width",e.width.toString()),r.setAttribute("height",e.height.toString()),r.setAttribute("fill","var(--background-secondary-alt)"),t.appendChild(r),this.containerEl.appendChild(t),this.svgEl=t}renderEdges(e,t){if(!this.svgEl||!e.length)return;let n=new Map;for(let a of t)n.set(a.id,a);for(let a of e){let i=n.get(a.fromNode),r=n.get(a.toNode);if(!i||!r)continue;let o=this.getConnectionPoint(i,a.fromSide),l=this.getConnectionPoint(r,a.toSide),c=document.createElementNS(V,"line");c.setAttribute("x1",o.x.toString()),c.setAttribute("y1",o.y.toString()),c.setAttribute("x2",l.x.toString()),c.setAttribute("y2",l.y.toString()),c.classList.add("canvas-svg-preview-edge");let h=this.resolveStrokeColor(a.color);if(c.setAttribute("stroke",h),this.shouldShowArrow(a.toEnd)&&c.setAttribute("marker-end",`url(#${this.markerId})`),this.svgEl.appendChild(c),a.label){let d=this.getMidpoint(o,l),p=document.createElementNS(V,"text");p.textContent=a.label,p.setAttribute("x",d.x.toString()),p.setAttribute("y",d.y.toString()),p.classList.add("canvas-svg-preview-edge-label"),this.svgEl.appendChild(p)}}}renderNodes(e){if(this.svgEl)for(let t of e){let n=document.createElementNS(V,"g");n.classList.add("canvas-svg-preview-node"),n.setAttribute("data-node-id",t.id),this.highlightedNodeIds.has(t.id)&&n.classList.add("is-highlighted");let a=document.createElementNS(V,"rect");a.setAttribute("x",t.x.toString()),a.setAttribute("y",t.y.toString()),a.setAttribute("width",(t.width||ee).toString()),a.setAttribute("height",(t.height||ve).toString());let i=this.resolveNodeColor(t);a.setAttribute("fill",i.background),a.setAttribute("stroke",i.border),n.appendChild(a);let r=this.getNodeLabel(t);if(r){let o=document.createElementNS(V,"text");o.textContent=r,o.setAttribute("x",(t.x+Math.max(12,(t.width||ee)*.05)).toString()),o.setAttribute("y",(t.y+24).toString()),o.classList.add("canvas-svg-preview-node-label"),n.appendChild(o)}this.isHoverable(t)&&(n.classList.add("is-interactive"),this.attachHoverHandlers(n,t)),this.isClickable(t)&&this.attachClickHandler(n,t),this.svgEl.appendChild(n)}}attachHoverHandlers(e,t){let n=r=>{r.stopPropagation(),this.handleNodeHover(t,r,e)},a=r=>{r.stopPropagation(),this.debouncedUpdateHoverPosition(r)},i=r=>{r.stopPropagation(),this.clearHoverState()};e.addEventListener("mouseenter",n),e.addEventListener("mousemove",a),e.addEventListener("mouseleave",i),this.register(()=>e.removeEventListener("mouseenter",n)),this.register(()=>e.removeEventListener("mousemove",a)),this.register(()=>e.removeEventListener("mouseleave",i))}attachClickHandler(e,t){let n=a=>{a.stopPropagation(),this.handleNodeClick(t).catch(i=>{console.error("Failed to open canvas node file",i)})};e.addEventListener("click",n),this.register(()=>e.removeEventListener("click",n))}async handleNodeHover(e,t,n){let a=++this.hoverToken,i=this.createHoverPopover(t,n);if(i){this.updateHoverPosition(t),this.setPopoverLoading(i);try{let r=await this.getNodePreviewContent(e);if(a!==this.hoverToken)return;let l=typeof r=="string"&&r.trim().length>0?r:"No content";await this.renderPopoverMarkdown(i,l)}catch(r){if(a!==this.hoverToken)return;console.error("Failed to load preview content",r),await this.renderPopoverMarkdown(i,"Failed to load preview")}finally{a===this.hoverToken&&i.hoverEl.removeClass("is-loading")}}}async handleNodeClick(e){var t,n,a,i,r;if(!this.canvasFile||!this.canvasData){let o=e.subpath?`${e.file}${e.subpath}`:e.file;await this.app.workspace.openLinkText(o,this.sourcePath,!1);return}try{let o=this.app.workspace.getLeaf("tab");await o.openFile(this.canvasFile),await new Promise(d=>setTimeout(d,100));let l=o.view;if(!l||!l.canvas){console.warn("Failed to access canvas view");return}let c=l.canvas,h=(n=(t=c.nodes)==null?void 0:t.get)==null?void 0:n.call(t,e.id);if(!h){console.warn(`Node not found in canvas: ${e.id}`);return}(a=c.deselectAll)==null||a.call(c),(i=c.selectOnly)==null||i.call(c,h),(r=c.zoomToSelection)==null||r.call(c)}catch(o){console.error("Failed to jump to node:",o);let l=e.subpath?`${e.file}${e.subpath}`:e.file;await this.app.workspace.openLinkText(l,this.sourcePath,!1)}}createHoverPopover(e,t){this.disposeHoverPopover();try{let n=this.containerEl instanceof HTMLElement?this.containerEl:null,a=new R.HoverPopover(this.hoverParent,n,2e3);return a.hoverEl.toggleClass("canvas-svg-preview-popover",!0),this.hoverPopover=a,this.hoverParent.hoverPopover=a,a.hoverEl.addClass("canvas-svg-preview-popover"),a}catch(n){return console.error("Failed to create hover popover",n),null}}updateHoverPosition(e){var a,i,r;if(!this.hoverPopover)return;let t=this.hoverPopover.position;if(typeof t!="function")return;let n=(r=(i=(a=e.view)==null?void 0:a.document)!=null?i:this.containerEl.ownerDocument)!=null?r:document;try{t.call(this.hoverPopover,{x:e.clientX,y:e.clientY,doc:n})}catch(o){console.error("Failed to position hover popover",o)}}setPopoverLoading(e){e.hoverEl.empty(),e.hoverEl.addClass("canvas-svg-preview-popover"),e.hoverEl.addClass("is-loading"),e.hoverEl.setText("Loading...")}async renderPopoverMarkdown(e,t){e.hoverEl.empty(),e.hoverEl.removeClass("is-loading");let n=e.hoverEl.createDiv("canvas-svg-preview-popover-content");try{await R.MarkdownRenderer.render(this.app,t,n,this.sourcePath,e)}catch(a){console.error("Failed to render hover markdown",a),n.setText(t)}}clearHoverState(){this.hoverToken++,this.disposeHoverPopover()}disposeHoverPopover(){if(!this.hoverPopover)return;let e=this.hoverPopover;this.hoverPopover=null,this.hoverParent.hoverPopover=null;try{let t=e.hide;typeof t=="function"?t.call(e):e.unload()}catch(t){console.error("Failed to dispose hover popover",t)}}async getNodePreviewContent(e){if(e.type==="text")return this.truncateText(e.text);if(e.type==="link")return e.url;let t=e.subpath?`${e.file}|${e.subpath}`:e.file,n=this.fileContentCache.get(t);if(n)return n;let a=this.app.vault.getAbstractFileByPath(e.file);if(!a||!(a instanceof R.TFile))return"File not found";let i=a.extension==="md"||a.extension==="markdown",r;if(i)if(e.subpath&&e.subpath.startsWith("#")){let o=await this.app.vault.cachedRead(a);r=this.extractSubpathContent(o,e.subpath)}else r=await this.extractFirstBlocks(a);else return r=`![[${e.subpath?`${e.file}${e.subpath}`:e.file}]]`,this.fileContentCache.set(t,r),r;return this.fileContentCache.set(t,r),r}async extractFirstBlocks(e){var t,n,a,i,r,o,l,c,h;try{let d=this.app.metadataCache.getFileCache(e);if(!d||!d.blocks){let k=await this.app.vault.cachedRead(e);return this.removeFrontmatter(k,d)}let p=(a=(n=(t=d.frontmatterPosition)==null?void 0:t.end)==null?void 0:n.line)!=null?a:-1,v=await this.app.vault.cachedRead(e),f=v.split(`
`),b=Object.values(d.blocks).filter(k=>{var S,P,g;return((g=(P=(S=k.position)==null?void 0:S.start)==null?void 0:P.line)!=null?g:-1)>p}).sort((k,L)=>{var g,C,x,M,E,T;let S=(x=(C=(g=k.position)==null?void 0:g.start)==null?void 0:C.line)!=null?x:0,P=(T=(E=(M=L.position)==null?void 0:M.start)==null?void 0:E.line)!=null?T:0;return S-P}).slice(0,3);if(b.length===0)return this.removeFrontmatter(v,d);let D=[];for(let k of b){let L=(o=(r=(i=k.position)==null?void 0:i.start)==null?void 0:r.line)!=null?o:0,S=(h=(c=(l=k.position)==null?void 0:l.end)==null?void 0:c.line)!=null?h:L,P=f.slice(L,S+1);D.push(P.join(`
`))}return D.join(`
`)}catch(d){console.error("Failed to extract blocks:",d);let p=await this.app.vault.cachedRead(e),v=this.app.metadataCache.getFileCache(e);return this.removeFrontmatter(p,v)}}removeFrontmatter(e,t){if(!(t!=null&&t.frontmatterPosition))return e;let n=t.frontmatterPosition.end.line;return e.split(`
`).slice(n+1).join(`
`)}extractSubpathContent(e,t){if(!t||!t.startsWith("#"))return e;let n=t.slice(1);if(n.startsWith("^")){let c=n.slice(1),h=new RegExp(`^.*?\\^${Ye(c)}$`,"m").exec(e);return h?h[0]:e}let i=new RegExp(`^#{1,6}\\s+${Ye(n)}\\s*$`,"m").exec(e);if(!i)return e;let r=i.index+i[0].length,o=e.slice(r),l=/^#{1,6}\s+/m.exec(o);return l?o.slice(0,l.index).trim():o.trim()}truncateText(e){if(!e)return"";let t=e.trim();return t.length<=this.maxPreviewLength?t:`${t.slice(0,this.maxPreviewLength)}\u2026`}resolveNodeColor(e){let t=typeof e.color=="string"?e.color.trim():void 0;if(t!=null&&t.startsWith("#"))return{background:Qe(t,.18),border:t};if(t&&Be[t]){let n=Be[t];return{background:Qe(n,.2),border:n}}return e.type==="group"?{background:"rgba(130, 130, 130, 0.08)",border:"rgba(130, 130, 130, 0.4)"}:{background:"var(--background-primary)",border:"var(--background-modifier-border)"}}resolveStrokeColor(e){var t;return e?e.startsWith("#")?e:(t=Be[e])!=null?t:"var(--text-muted)":"var(--text-muted)"}shouldShowArrow(e){return!e||e==="arrow"}getConnectionPoint(e,t){let n=e.x,a=e.y,i=e.width||ee,r=e.height||ve;switch(t){case"top":return{x:n+i/2,y:a};case"bottom":return{x:n+i/2,y:a+r};case"left":return{x:n,y:a+r/2};case"right":return{x:n+i,y:a+r/2};default:return{x:n+i/2,y:a+r/2}}}getMidpoint(e,t){return{x:(e.x+t.x)/2,y:(e.y+t.y)/2}}getNodeLabel(e){var t,n;switch(e.type){case"text":return ht(e.text);case"file":return(t=e.file.split("/").pop())!=null?t:e.file;case"link":return e.url;case"group":return(n=e.label)!=null?n:"Group";default:return null}}isHoverable(e){return e.type==="file"||e.type==="text"||e.type==="link"}isClickable(e){return e.type==="file"}};function ht(u,s=40){let e=u.trim();return e.length<=s?e:`${e.slice(0,s)}\u2026`}function Qe(u,s){let e=u.replace("#","");if(e.length!==6)return u;let t=parseInt(e.slice(0,2),16),n=parseInt(e.slice(2,4),16),a=parseInt(e.slice(4,6),16);return`rgba(${t}, ${n}, ${a}, ${s})`}function Ye(u){return u.replace(/[.*+?^${}()|[\]\\]/g,"\\$&")}var fe=class extends U.Component{constructor(e){super();this.preview=null;this.footerLeft=null;this.footerRight=null;this.options=e,this.container=this.createCard()}createCard(){var l,c;let e=document.createElement("div");e.addClass("canvas-card"),this.options.item.isPinned&&e.addClass("is-pinned");let t=e.createDiv("canvas-card-header"),n=t.createDiv("canvas-card-title");n.textContent=this.options.item.file.basename;let a=t.createDiv("canvas-card-pin-icon");(0,U.setIcon)(a,this.options.item.isPinned?"pin-off":"pin"),this.registerDomEvent(a,"click",h=>{h.stopPropagation(),this.togglePin()});let i=e.createDiv("canvas-card-preview");if(this.options.item.data)try{let h=i.createDiv("canvas-preview-container");this.preview=new ge({containerEl:h,app:this.options.app,sourcePath:this.options.item.file.path}),this.addChild(this.preview),this.preview.loadCanvas(this.options.item.data,this.options.item.matchedNodeIds)}catch(h){console.error("Failed to render canvas preview:",h),i.createDiv("canvas-preview-error").setText("Preview unavailable")}else i.createDiv("canvas-preview-placeholder").setText("No preview");let r=e.createDiv("canvas-card-footer");this.footerLeft=r.createSpan("canvas-card-footer-left");let o=((c=(l=this.options.item.data)==null?void 0:l.nodes)==null?void 0:c.length)||0;return this.footerLeft.setText(`${o} nodes`),this.footerRight=r.createSpan("canvas-card-footer-right"),this.updateMatchedNodeCount(),this.registerDomEvent(e,"click",()=>{this.options.onOpen(this.options.item)}),this.registerDomEvent(e,"contextmenu",h=>{h.preventDefault(),this.showContextMenu(h)}),e}togglePin(){if(this.options.item.isPinned){this.options.onUnpin(this.options.item),this.options.item.isPinned=!1,this.container.removeClass("is-pinned");let e=this.container.querySelector(".canvas-card-pin-icon");e&&(e.empty(),(0,U.setIcon)(e,"pin-off"))}else{this.options.onPin(this.options.item),this.options.item.isPinned=!0,this.container.addClass("is-pinned");let e=this.container.querySelector(".canvas-card-pin-icon");e&&(e.empty(),(0,U.setIcon)(e,"pin"))}}showContextMenu(e){let t=new U.Menu;t.addItem(n=>n.setTitle("Open").setIcon("file-open").onClick(()=>{this.options.onOpen(this.options.item)})),t.addItem(n=>n.setIcon(this.options.item.isPinned?"pin-off":"pin").onClick(()=>{this.togglePin()})),t.addItem(n=>n.setTitle("Copy path").setIcon("copy").onClick(()=>{navigator.clipboard.writeText(this.options.item.file.path)})),t.addSeparator(),t.addItem(n=>n.setTitle("Delete").setIcon("trash").setWarning(!0).onClick(()=>{this.options.onDelete(this.options.item)})),t.showAtMouseEvent(e)}updateHighlightedNodes(e){this.options.item.matchedNodeIds=e,this.preview&&this.preview.updateHighlightedNodes(e),this.updateMatchedNodeCount()}updateMatchedNodeCount(){var t,n;if(!this.footerRight)return;let e=(n=(t=this.options.item.matchedNodeIds)==null?void 0:t.size)!=null?n:0;e>0?(this.footerRight.setText(`match ${e} nodes`),this.footerRight.style.display=""):this.footerRight.style.display="none"}getElement(){return this.container}onunload(){this.preview&&(this.removeChild(this.preview),this.preview=null),this.container.remove()}};var Oe="canvas-list-view",te=class extends O.BasesView{constructor(e,t,n){super(e);this.type=Oe;this.searchBar=null;this.layout=null;this.cards=[];this.allItems=[];this.filteredItems=[];this.searchQuery="";this.searchableTextCache=new Map;console.log(this),this.pinDataService=n.pinDataService,this.rootEl=t.createDiv("canvas-list-view"),this.pinDataService.onChange(()=>{this.refreshCards()})}async onDataUpdated(){this.renderView(),await this.loadCanvasItems()}async loadCanvasItems(){var n,a;let e=(a=(n=this.data)==null?void 0:n.data)!=null?a:[];this.allItems=[],this.searchableTextCache.clear();let t=new Set(this.pinDataService.getPinnedCanvases());this.renderView(),this.layout&&(this.cards.forEach(i=>{this.removeChild(i)}),this.cards=[],this.layout.clear());for(let i of e)if(i.file.extension==="canvas")try{let r=await this.app.vault.read(i.file),o=JSON.parse(r),l={file:i.file,data:o,isPinned:t.has(i.file.path),lastModified:i.file.stat.mtime},c=this.extractInitialSearchableText(o);this.searchableTextCache.set(i.file.path,c),this.allItems.push(l),this.applyFilters(),this.extractSearchableTextAsync(o,i.file).then(h=>{this.searchableTextCache.set(i.file.path,h),this.applyFilters()})}catch(r){console.warn(`Failed to parse canvas file: ${i.file.path}`,r),this.searchableTextCache.set(i.file.path,""),this.allItems.push({file:i.file,data:null,isPinned:t.has(i.file.path),lastModified:i.file.stat.mtime}),this.applyFilters()}}extractInitialSearchableText(e){if(!e||!Array.isArray(e.nodes))return"";let t=[];for(let n of e.nodes)if(n.type==="text"){let a=n;a.text&&t.push(a.text.toLowerCase())}else if(n.type==="file"){let a=n;if(a.file&&!a.file.toLowerCase().endsWith(".canvas")){t.push(a.file.toLowerCase());let i=a.file.split("/").pop()||"";i&&t.push(i.toLowerCase())}}return t.join(" ")}async extractSearchableTextAsync(e,t){if(!e||!Array.isArray(e.nodes))return"";let n=[this.extractInitialSearchableText(e)],a=[];for(let c of e.nodes)if(c.type==="file"){let h=c;h.file&&!h.file.toLowerCase().endsWith(".canvas")&&a.push(h)}let i=new Map,r=this.extractInitialSearchableText(e),o=a.map(async c=>{try{let h=this.app.metadataCache.getFirstLinkpathDest(c.file,t.path);if(h&&h.extension!=="canvas"){let p=(await this.app.vault.read(h)).toLowerCase();i.set(c.file,p);let v=Array.from(i.values()).join(" "),f=r+(v?" "+v:"");return this.searchableTextCache.set(t.path,f),this.applyFilters(),p}return""}catch(h){return console.debug(`Failed to read file content for search: ${c.file}`,h),""}}),l=await Promise.all(o);return n.push(...l.filter(c=>c.length>0)),n.join(" ")}renderView(){var e,t;if(!this.searchBar){let n=(t=(e=this.queryController)==null?void 0:e.viewHeaderEl)==null?void 0:t.find(".bases-toolbar-item.bases-toolbar-result-count"),a=n==null?void 0:n.nextElementSibling;this.searchBar=new O.SearchComponent(a),this.searchBar.setPlaceholder("Search canvases..."),this.searchBar.onChange(i=>{this.searchQuery=i,this.applyFilters()})}if(!this.layout){let n=this.rootEl.createDiv("canvas-list-container");this.layout=new Q(n,{minColumnWidth:350,maxColumnWidth:400,columnGap:16,rowGap:16}),this.addChild(this.layout)}}applyFilters(){if(!this.layout)return;let e=[...this.allItems],t=this.searchQuery.trim();if(t){let n=(0,O.prepareSimpleSearch)(t),a=t.toLowerCase();e=e.map(i=>{var h;let r=n(i.file.basename)!==null||i.file.basename.toLowerCase().includes(a),o=this.searchableTextCache.get(i.file.path)||"",l=n(o)!==null||o.includes(a),c=new Set;if(l&&((h=i.data)!=null&&h.nodes))for(let d of i.data.nodes){let p=!1;if(d.type==="text"){let v=d;if(v.text){let f=v.text.toLowerCase();p=n(v.text)!==null||f.includes(a)}}else if(d.type==="file"){let v=d;if(v.file&&!v.file.toLowerCase().endsWith(".canvas")){let f=v.file.toLowerCase(),m=f.split("/").pop()||"";p=n(v.file)!==null||f.includes(a)||m.includes(a)}}p&&c.add(d.id)}return i.matchedNodeIds=c.size>0?c:void 0,r||l?i:null}).filter(i=>i!==null)}else e.forEach(n=>{n.matchedNodeIds=void 0});this.filteredItems=e,this.renderCards()}renderCards(){if(!this.layout)return;this.cards.forEach(n=>{this.removeChild(n)}),this.cards=[],this.layout.clear();let e=new Set(this.pinDataService.getPinnedCanvases()),t=[...this.filteredItems].sort((n,a)=>{let i=e.has(n.file.path),r=e.has(a.file.path);return i!==r?i?-1:1:a.lastModified-n.lastModified});for(let n of t){let a=new fe({item:n,app:this.app,onOpen:()=>this.handleOpen(n),onPin:()=>this.handlePinItem(n),onUnpin:()=>this.handleUnpinItem(n),onDelete:()=>this.handleDelete(n)});this.addChild(a),this.cards.push(a),this.layout.addItem(a.getElement())}requestAnimationFrame(()=>{this.layout&&this.layout.layout()})}refreshCards(){this.renderCards()}async handleOpen(e){await this.app.workspace.getLeaf("tab").openFile(e.file)}handlePinItem(e){this.pinDataService.pinCanvas(e.file.path),new O.Notice(`Pinned ${e.file.basename}`),this.refreshCards()}handleUnpinItem(e){this.pinDataService.unpinCanvas(e.file.path),new O.Notice(`Unpinned ${e.file.basename}`),this.refreshCards()}async handleDelete(e){if(await this.showDeleteConfirmation(e.file.basename))try{await this.app.vault.trash(e.file,!0),new O.Notice(`Deleted ${e.file.basename}`),this.allItems=this.allItems.filter(n=>n.file.path!==e.file.path),this.applyFilters()}catch(n){console.error("Failed to delete canvas:",n),new O.Notice(`Failed to delete ${e.file.basename}`)}}async showDeleteConfirmation(e){return new Promise(t=>{let n=new O.Modal(this.app);n.titleEl.setText("Delete Canvas"),n.contentEl.setText(`Are you sure you want to delete "${e}"? This will move it to trash.`);let a=n.contentEl.createDiv("modal-button-container");a.style.display="flex",a.style.justifyContent="flex-end",a.style.gap="8px",a.style.marginTop="16px",a.createEl("button",{text:"Cancel"}).addEventListener("click",()=>{n.close(),t(!1)}),a.createEl("button",{text:"Delete",cls:"mod-warning"}).addEventListener("click",()=>{n.close(),t(!0)}),n.open()})}onunload(){var e,t,n;this.cards.forEach(a=>{this.removeChild(a)}),this.cards=[],this.layout&&(this.removeChild(this.layout),this.layout=null),(t=(e=this.searchBar)==null?void 0:e.inputEl)==null||t.detach(),(n=this.searchBar)==null||n.clearButtonEl.detach(),this.searchBar=null,this.searchableTextCache.clear()}static getViewOptions(){return[]}};var A=require("obsidian");var ye=require("obsidian");var me=class extends ye.Component{constructor(e){super();this.filterButtons=new Map;this.colorButtons=new Map;this.availableColors=[];this.filterOptions=[{type:"all",label:"All",icon:"list"},{type:"file",label:"Files",icon:"file"},{type:"text",label:"Text",icon:"text"},{type:"group",label:"Groups",icon:"folder"},{type:"link",label:"Links",icon:"link"}];this.onFilterChange=e.onFilterChange,this.onColorFilterChange=e.onColorFilterChange,this.activeFilters=e.initialFilters||new Set(["all"]),this.activeColorFilters=e.initialColorFilters||new Set,this.availableColors=e.availableColors||[],this.container=this.createFilterBar()}createFilterBar(){let e=document.createElement("div");e.addClass("filter-bar-container");let t=e.createDiv("filter-bar-type-section");if(this.filterOptions.forEach(n=>{let a=this.createFilterButton(n);this.filterButtons.set(n.type,a),t.appendChild(a)}),this.onColorFilterChange){let n=e.createDiv("filter-bar-color-section");["1","2","3","4","5","6"].forEach(i=>{let r=this.createColorButton(i);this.colorButtons.set(i,r),n.appendChild(r)}),this.updateColorButtonStates()}return this.updateButtonStates(),e}createFilterButton(e){let t=document.createElement("button");t.addClass("filter-button"),t.setAttribute("data-filter-type",e.type);let n=t.createDiv("filter-button-icon");return(0,ye.setIcon)(n,e.icon),t.createSpan({text:e.label,cls:"filter-button-label"}),this.registerDomEvent(t,"click",()=>{this.toggleFilter(e.type)}),t}toggleFilter(e){e==="all"?(this.activeFilters.clear(),this.activeFilters.add("all")):(this.activeFilters.delete("all"),this.activeFilters.has(e)?this.activeFilters.delete(e):this.activeFilters.add(e),this.activeFilters.size===0&&this.activeFilters.add("all")),this.updateButtonStates(),this.onFilterChange(new Set(this.activeFilters))}createColorButton(e){let t=document.createElement("div");return t.addClass("canvas-color-picker-item"),/^[1-6]$/.test(e)&&t.addClass(`mod-canvas-color-${e}`),t.setAttribute("data-color",e),this.registerDomEvent(t,"click",()=>{this.toggleColorFilter(e)}),t}toggleColorFilter(e){this.activeColorFilters.has(e)?this.activeColorFilters.delete(e):this.activeColorFilters.add(e),this.updateColorButtonStates(),this.onColorFilterChange&&this.onColorFilterChange(new Set(this.activeColorFilters))}updateButtonStates(){this.filterButtons.forEach((e,t)=>{this.activeFilters.has(t)?e.addClass("is-active"):e.removeClass("is-active")})}updateColorButtonStates(){this.colorButtons.forEach((e,t)=>{this.activeColorFilters.has(t)?(e.addClass("is-active"),e.style.outline="2px solid var(--interactive-accent)",e.style.outlineOffset="2px"):(e.removeClass("is-active"),e.style.outline="",e.style.outlineOffset="")})}getElement(){return this.container}getActiveFilters(){return new Set(this.activeFilters)}setActiveFilters(e){this.activeFilters=new Set(e),this.activeFilters.size===0&&this.activeFilters.add("all"),this.updateButtonStates()}setActiveColorFilters(e){this.activeColorFilters=new Set(e),this.updateColorButtonStates()}setAvailableColors(e){}reset(){this.activeFilters.clear(),this.activeFilters.add("all"),this.activeColorFilters.clear(),this.updateButtonStates(),this.updateColorButtonStates()}};var I=require("obsidian"),Ce=class extends I.Component{constructor(e){super();this.contentEl=null;this.renderContentPromise=null;this.options=e,this.container=this.createCard()}createCard(){let e=createDiv();e.toggleClass("node-card",!0),e.toggleClass(`node-card-${this.options.item.node.type}`,!0),this.options.item.isPinned&&e.toggleClass("is-pinned",!0);let t=e.createDiv("node-card-header"),n=t.createDiv("node-card-type-badge");n.addClass(`node-card-type-badge-${this.options.item.node.type}`);let a=n.createDiv("node-card-icon");(0,I.setIcon)(a,this.getIconForNodeType(this.options.item.node.type)),n.createSpan("node-card-type-label").setText(this.getTypeLabel(this.options.item.node.type));let i=t.createDiv("node-card-pin-icon");(0,I.setIcon)(i,this.options.item.isPinned?"pin-off":"pin"),this.registerDomEvent(i,"click",l=>{l.stopPropagation(),this.togglePin()});let r=e.createDiv("node-card-content");return this.contentEl=r.createDiv("node-card-content-inner"),this.renderContentPromise=this.renderContent(),e.createDiv("node-card-footer").createSpan("node-card-source").setText(`From: ${this.options.item.canvasFile.basename}`),this.registerDomEvent(e,"click",()=>{this.options.onOpen(this.options.item)}),this.registerDomEvent(e,"contextmenu",l=>{l.preventDefault(),this.showContextMenu(l)}),e}async renderContent(){if(!this.contentEl)return;let e=this.options.item.node,t="";if(e.type==="text"){t=e.text||"(Empty text node)";try{await I.MarkdownRenderer.render(this.options.app,t,this.contentEl,this.options.item.canvasFile.path,this)}catch(n){console.error("Failed to render markdown:",n),this.contentEl.textContent=t}}else if(e.type==="file"){let n=e.file||"(No file)";try{let a=this.options.app.vault.getFileByPath(n);if(a&&a instanceof I.TFile)if(a.extension==="md"||a.extension==="markdown"){let r="";if(e.subpath&&e.subpath.startsWith("#")){let o=await this.options.app.vault.cachedRead(a);r=this.extractSubpathContent(o,e.subpath)}else r=await this.extractFirstBlocks(a);try{await I.MarkdownRenderer.render(this.options.app,r,this.contentEl,n,this)}catch(o){console.error("Failed to render file markdown:",o),this.contentEl.textContent=r||"(Empty file)"}}else{let o=`![[${e.subpath?`${n}${e.subpath}`:n}]]`;this.contentEl.toggleClass("special-node",!0);try{await I.MarkdownRenderer.render(this.options.app,o,this.contentEl,this.options.item.canvasFile.path,this)}catch(l){console.error("Failed to render embed:",l);let c=this.contentEl.createDiv("node-card-file-link");c.textContent=n,c.addClass("internal-link"),c.setAttribute("data-href",n)}}else{let i=this.contentEl.createDiv("node-card-file-link");i.textContent=n,i.addClass("internal-link"),i.setAttribute("data-href",n)}}catch(a){console.error("Failed to load file content:",a);let i=this.contentEl.createDiv("node-card-file-link");i.textContent=n,i.addClass("internal-link"),i.setAttribute("data-href",n)}}else if(e.type==="link"){let n=e.url||"(No URL)",a=this.contentEl.createEl("a",{href:n,text:n,cls:"external-link"});a.setAttribute("target","_blank"),a.setAttribute("rel","noopener")}else if(e.type==="group"){let n=e.label||"(Group)";this.contentEl.textContent=n}else this.contentEl.textContent=this.options.item.displayText||"(Empty)"}async extractFirstBlocks(e){var t,n,a,i,r,o,l,c,h;try{let d=this.options.app.metadataCache.getFileCache(e);if(!d||!d.blocks){let k=await this.options.app.vault.cachedRead(e);return this.removeFrontmatter(k,d)}let p=(a=(n=(t=d.frontmatterPosition)==null?void 0:t.end)==null?void 0:n.line)!=null?a:-1,v=await this.options.app.vault.cachedRead(e),f=v.split(`
`),b=Object.values(d.blocks).filter(k=>{var S,P,g;return((g=(P=(S=k.position)==null?void 0:S.start)==null?void 0:P.line)!=null?g:-1)>p}).sort((k,L)=>{var g,C,x,M,E,T;let S=(x=(C=(g=k.position)==null?void 0:g.start)==null?void 0:C.line)!=null?x:0,P=(T=(E=(M=L.position)==null?void 0:M.start)==null?void 0:E.line)!=null?T:0;return S-P}).slice(0,3);if(b.length===0)return this.removeFrontmatter(v,d);let D=[];for(let k of b){let L=(o=(r=(i=k.position)==null?void 0:i.start)==null?void 0:r.line)!=null?o:0,S=(h=(c=(l=k.position)==null?void 0:l.end)==null?void 0:c.line)!=null?h:L,P=f.slice(L,S+1);D.push(P.join(`
`))}return D.join(`
`)}catch(d){console.error("Failed to extract blocks:",d);let p=await this.options.app.vault.cachedRead(e),v=this.options.app.metadataCache.getFileCache(e);return this.removeFrontmatter(p,v)}}removeFrontmatter(e,t){if(!(t!=null&&t.frontmatterPosition))return e;let n=t.frontmatterPosition.end.line;return e.split(`
`).slice(n+1).join(`
`)}extractSubpathContent(e,t){if(!t||!t.startsWith("#"))return e;let n=t.slice(1);if(n.startsWith("^")){let c=n.slice(1),h=new RegExp(`^.*?\\^${this.escapeRegExp(c)}$`,"m").exec(e);return h?h[0]:e}let i=new RegExp(`^#{1,6}\\s+${this.escapeRegExp(n)}\\s*$`,"m").exec(e);if(!i)return e;let r=i.index+i[0].length,o=e.slice(r),l=/^#{1,6}\s+/m.exec(o);return l?o.slice(0,l.index).trim():o.trim()}escapeRegExp(e){return e.replace(/[.*+?^${}()|[\]\\]/g,"\\$&")}getTypeLabel(e){switch(e){case"file":return"File";case"text":return"Text";case"group":return"Group";case"link":return"Link";default:return"Node"}}getIconForNodeType(e){switch(e){case"file":return"file";case"text":return"file-text";case"group":return"folder";case"link":return"link";default:return"square"}}togglePin(){if(this.options.item.isPinned){this.options.onUnpin(this.options.item),this.options.item.isPinned=!1,this.container.removeClass("is-pinned");let e=this.container.querySelector(".node-card-pin-icon");e&&(e.empty(),(0,I.setIcon)(e,"pin-off"))}else{this.options.onPin(this.options.item),this.options.item.isPinned=!0,this.container.addClass("is-pinned");let e=this.container.querySelector(".node-card-pin-icon");e&&(e.empty(),(0,I.setIcon)(e,"pin"))}}showContextMenu(e){let t=new I.Menu;t.addItem(n=>n.setTitle("Open in canvas").setIcon("file").onClick(()=>{this.options.onOpen(this.options.item)})),t.addItem(n=>n.setIcon(this.options.item.isPinned?"pin-off":"pin").setTitle(this.options.item.isPinned?"Unpin":"Pin").onClick(()=>{this.togglePin()})),t.addItem(n=>n.setTitle("Copy content").setIcon("copy").onClick(()=>{navigator.clipboard.writeText(this.options.item.displayText)})),t.addSeparator(),t.addItem(n=>n.setTitle("Delete node").setIcon("trash").setWarning(!0).onClick(()=>{this.options.onDelete(this.options.item)})),t.showAtMouseEvent(e)}getElement(){return this.container}needsExtraLoadTime(e){if(!e)return!1;let t=e.extension.toLowerCase();return["png","jpg","jpeg","gif","svg","webp","bmp","pdf","canvas"].includes(t)}async waitForEmbeddedContent(){if(!this.contentEl)return;let e=this.contentEl.querySelectorAll("img"),t=Array.from(e).map(n=>n.complete?Promise.resolve():new Promise(a=>{n.onload=()=>a(),n.onerror=()=>a(),setTimeout(()=>a(),3e3)}));await Promise.all(t),await new Promise(n=>{requestAnimationFrame(()=>{requestAnimationFrame(()=>{requestAnimationFrame(()=>{setTimeout(()=>n(),300)})})})})}async waitForContent(){if(this.renderContentPromise){await this.renderContentPromise;let e=this.options.item.node;if(e.type==="file"){let t=e.file||"",n=this.options.app.vault.getFileByPath(t);this.needsExtraLoadTime(n)&&await this.waitForEmbeddedContent()}}}async updateContent(){this.contentEl&&(this.contentEl.empty(),this.renderContentPromise=this.renderContent(),await this.renderContentPromise)}onunload(){super.onunload()}};var He="canvas-node-list-view",ne=class extends A.BasesView{constructor(e,t,n){super(e);this.type=He;this.searchBar=null;this.filterBar=null;this.layout=null;this.cards=[];this.allItems=[];this.filteredItems=[];this.searchQuery="";this.activeFilters=new Set(["all"]);this.activeColorFilters=new Set;this.availableColors=[];this.bridge=n.bridge,this.pinDataService=n.pinDataService,this.rootEl=t.createDiv("canvas-node-list-view"),this.pinDataService.onChange(async()=>{await this.refreshCards()}),this.registerDomEvent(window,"visibilitychange",()=>{!document.hidden&&this.layout&&setTimeout(()=>{this.layout&&this.layout.forceLayout()},100)}),this.registerDomEvent(window,"focus",()=>{this.layout&&setTimeout(()=>{this.layout&&this.layout.forceLayout()},100)})}async onDataUpdated(){await this.loadNodeItems(),this.renderView()}async loadNodeItems(){var n,a;let e=(a=(n=this.data)==null?void 0:n.data)!=null?a:[],t=[];for(let i of e)if(i.file.extension==="canvas")try{let r=await this.app.vault.read(i.file),o=JSON.parse(r);if(!Array.isArray(o.nodes))continue;for(let l of o.nodes){let c="";l.type==="text"?c=l.text||"(Empty text node)":l.type==="file"?c=l.file||"(No file)":l.type==="link"?c=l.url||"(No URL)":l.type==="group"&&(c=l.label||"(Group)");let h=this.pinDataService.isNodePinned(i.file.path,l.id);t.push({id:l.id,canvasFile:i.file,canvasPath:i.file.path,node:l,isPinned:h,displayText:c})}}catch(r){console.warn(`Failed to parse canvas file: ${i.file.path}`,r)}this.allItems=t,this.availableColors=["1","2","3","4","5","6"],this.applyFilters()}async renderView(){this.rootEl.empty(),this.rootEl.addClass("canvas-node-list-view");let e=this.rootEl.createDiv("canvas-node-list-view-header-section"),t=e.createDiv("canvas-node-list-view-search-wrapper");this.searchBar=new A.SearchComponent(t),this.searchBar.setPlaceholder("Search nodes..."),this.searchBar.onChange(r=>{this.searchQuery=r,this.applyFilters()});let n=e.createDiv("canvas-node-list-view-filter-wrapper");this.filterBar=new me({onFilterChange:r=>{this.activeFilters=r,this.applyFilters()},initialFilters:this.activeFilters,onColorFilterChange:r=>{this.activeColorFilters=r,this.applyFilters()},availableColors:this.availableColors,initialColorFilters:this.activeColorFilters}),this.addChild(this.filterBar),n.appendChild(this.filterBar.getElement());let i=this.rootEl.createDiv("canvas-node-list-view-content").createDiv("canvas-node-list-container");this.layout=new Q(i,{minColumnWidth:290,maxColumnWidth:320,columnGap:12,rowGap:12,containerPadding:16}),this.addChild(this.layout),await this.renderCards()}async applyFilters(){let e=[...this.allItems];if(this.activeFilters.has("all")||(e=e.filter(t=>this.activeFilters.has(t.node.type))),this.activeColorFilters.size>0&&(e=e.filter(t=>{if(!t.node.color)return!1;let n=t.node.color.trim();return this.activeColorFilters.has(n)})),this.searchQuery.trim()){let t=this.searchQuery.trim(),n=(0,A.prepareSimpleSearch)(t),a=t.toLowerCase();e=e.filter(i=>!!(i.displayText&&(n(i.displayText)!==null||i.displayText.toLowerCase().includes(a))||n(i.canvasFile.basename)!==null||i.canvasFile.basename.toLowerCase().includes(a)))}this.filteredItems=e,await this.renderCards()}async renderCards(){if(!this.layout)return;this.cards.forEach(t=>{this.removeChild(t),t.onunload()}),this.cards=[],this.layout.clear();let e=[...this.filteredItems].sort((t,n)=>{let a=this.pinDataService.isNodePinned(t.canvasPath,t.id),i=this.pinDataService.isNodePinned(n.canvasPath,n.id);if(a!==i)return a?-1:1;let r=t.canvasFile.basename.localeCompare(n.canvasFile.basename);return r!==0?r:t.id.localeCompare(n.id)});for(let t of e){let n=new Ce({item:t,app:this.app,onOpen:()=>this.handleJumpToNode(t),onPin:()=>this.handlePinItem(t),onUnpin:()=>this.handleUnpinItem(t),onDelete:()=>this.handleDelete(t)});this.addChild(n),this.cards.push(n),this.layout.addItem(n.getElement())}await Promise.all(this.cards.map(t=>t.waitForContent())),requestAnimationFrame(()=>{requestAnimationFrame(()=>{requestAnimationFrame(()=>{this.layout&&this.layout.layout()})})})}async refreshCards(){await this.renderCards()}async handleJumpToNode(e){var t,n,a,i,r;try{let o=this.app.workspace.getLeaf("tab");await o.openFile(e.canvasFile),await new Promise(d=>setTimeout(d,100));let l=o.view;if(!l||!l.canvas){new A.Notice("Failed to access canvas view");return}let c=l.canvas,h=(n=(t=c.nodes)==null?void 0:t.get)==null?void 0:n.call(t,e.id);if(!h){new A.Notice("Node not found in canvas");return}(a=c.deselectAll)==null||a.call(c),(i=c.selectOnly)==null||i.call(c,h),(r=c.zoomToSelection)==null||r.call(c),new A.Notice(`Jumped to node in ${e.canvasFile.basename}`)}catch(o){console.error("Failed to jump to node:",o),new A.Notice("Failed to jump to node")}}async handlePinItem(e){this.pinDataService.pinNode(e.canvasPath,e.id),new A.Notice(`Pinned node from ${e.canvasFile.basename}`),await this.refreshCards()}async handleUnpinItem(e){this.pinDataService.unpinNode(e.canvasPath,e.id),new A.Notice(`Unpinned node from ${e.canvasFile.basename}`),await this.refreshCards()}async handleDelete(e){var n;if(await this.showDeleteConfirmation(e))try{let a=await this.app.vault.read(e.canvasFile),i=JSON.parse(a);i.nodes=i.nodes.filter(r=>r.id!==e.id),i.edges=((n=i.edges)==null?void 0:n.filter(r=>r.fromNode!==e.id&&r.toNode!==e.id))||[],await this.app.vault.modify(e.canvasFile,JSON.stringify(i,null,2)),new A.Notice(`Deleted node from ${e.canvasFile.basename}`),this.allItems=this.allItems.filter(r=>!(r.canvasPath===e.canvasPath&&r.id===e.id)),this.applyFilters()}catch(a){console.error("Failed to delete node:",a),new A.Notice("Failed to delete node")}}async showDeleteConfirmation(e){return new Promise(t=>{let n=new A.Modal(this.app);n.titleEl.setText("Delete Node"),n.contentEl.setText(`Are you sure you want to delete this node from "${e.canvasFile.basename}"? This action cannot be undone.`);let a=n.contentEl.createDiv("modal-button-container");a.style.display="flex",a.style.justifyContent="flex-end",a.style.gap="8px",a.style.marginTop="16px",a.createEl("button",{text:"Cancel"}).addEventListener("click",()=>{n.close(),t(!1)}),a.createEl("button",{text:"Delete",cls:"mod-warning"}).addEventListener("click",()=>{n.close(),t(!0)}),n.open()})}onunload(){this.cards.forEach(e=>{this.removeChild(e)}),this.cards=[],this.layout&&(this.removeChild(this.layout),this.layout=null),this.filterBar&&(this.removeChild(this.filterBar),this.filterBar=null),this.searchBar=null,super.onunload()}static getViewOptions(){return[]}};var Ee=class{constructor(s){this.onChangeCallback=null;if(this.pinnedCanvases=new Set((s==null?void 0:s.pinnedCanvases)||[]),this.pinnedNodes=new Map,s!=null&&s.pinnedNodes)for(let[e,t]of Object.entries(s.pinnedNodes))this.pinnedNodes.set(e,new Set(t))}onChange(s){this.onChangeCallback=s}notifyChange(){this.onChangeCallback&&this.onChangeCallback()}getPinnedCanvases(){return Array.from(this.pinnedCanvases)}getPinnedNodes(s){return Array.from(this.pinnedNodes.get(s)||[])}getAllPinnedNodes(){let s={};for(let[e,t]of this.pinnedNodes.entries())t.size>0&&(s[e]=Array.from(t));return s}isCanvasPinned(s){return this.pinnedCanvases.has(s)}isNodePinned(s,e){var t;return((t=this.pinnedNodes.get(s))==null?void 0:t.has(e))||!1}pinCanvas(s){this.pinnedCanvases.has(s)||(this.pinnedCanvases.add(s),this.notifyChange())}unpinCanvas(s){this.pinnedCanvases.has(s)&&(this.pinnedCanvases.delete(s),this.notifyChange())}toggleCanvasPin(s){return this.pinnedCanvases.has(s)?(this.unpinCanvas(s),!1):(this.pinCanvas(s),!0)}pinNode(s,e){let t=this.pinnedNodes.get(s);t||(t=new Set,this.pinnedNodes.set(s,t)),t.has(e)||(t.add(e),this.notifyChange())}unpinNode(s,e){let t=this.pinnedNodes.get(s);t&&t.has(e)&&(t.delete(e),t.size===0&&this.pinnedNodes.delete(s),this.notifyChange())}toggleNodePin(s,e){return this.isNodePinned(s,e)?(this.unpinNode(s,e),!1):(this.pinNode(s,e),!0)}exportData(){return{pinnedCanvases:this.getPinnedCanvases(),pinnedNodes:this.getAllPinnedNodes()}}importData(s){if(this.pinnedCanvases=new Set(s.pinnedCanvases||[]),this.pinnedNodes.clear(),s.pinnedNodes)for(let[e,t]of Object.entries(s.pinnedNodes))this.pinnedNodes.set(e,new Set(t));this.notifyChange()}};var ut="CanvasForBases",we=class extends z.Plugin{constructor(){super(...arguments);this.settings=H;this.bridge=null;this.syncingStates=new Set;this.nodeIndexCache=new Map;this.edgeListenerUnsubscribe=null;this.updatingNodes=new Set;this.pinDataService=null}async onload(){await this.loadSettings(),this.pinDataService=new Ee({pinnedCanvases:this.settings.pinnedCanvases||[],pinnedNodes:this.settings.pinnedNodes||{}}),this.pinDataService.onChange(()=>{this.saveSettings()});let e=async({session:r,data:o})=>{var p,v;let l=r.targetFile.extension.toLowerCase()==="md",c=((p=this.settings.linkMetadataProperty)==null?void 0:p.trim())||H.linkMetadataProperty,h=c.length>0&&l,d=((v=this.settings.metadataProperty)==null?void 0:v.trim())||H.metadataProperty;if(d.length>0&&l&&await ke(this.app,r.targetFile,d),!this.settings.linkMetadataEnabled){h&&await ke(this.app,r.targetFile,c);return}},t=r=>{let o=r.file;if(!o)return null;let l=this.resolveTargetNote(o);return l?{targetFile:l,metadataKey:this.settings.metadataProperty}:null};this.bridge=new le(this.app,e,t),this.bridge.start(this),this.edgeListenerUnsubscribe=this.bridge.onEdgesChanged(async r=>{var l;if(!this.settings.linkMetadataEnabled)return;let o=((l=this.settings.linkMetadataProperty)==null?void 0:l.trim())||H.linkMetadataProperty;o.length!==0&&(console.debug(`Edge changes detected: ${r.added.length} added, ${r.removed.length} removed`),await this.handleEdgeChanges(r.added,r.removed,r.current,r.data,o))});let n={app:this.app,bridge:this.bridge,getDefaultMetadataKey:()=>this.settings.metadataProperty,getLinkMetadataKey:()=>{var o,l;let r=(l=(o=this.settings.linkMetadataProperty)==null?void 0:o.trim())!=null?l:"";return r.length>0?r:H.linkMetadataProperty},getNonMarkdownPositions:()=>this.settings.nonMarkdownPositions,getSettings:()=>this.settings,setNonMarkdownPositions:async(r,o)=>{var c;let l={};for(let[h,d]of Object.entries(o!=null?o:{})){if(!d||typeof d!="object")continue;let p=typeof d.note=="string"&&d.note.trim().length>0?d.note:h,v=(c=d.pos)!=null?c:{x:0,y:0},f=typeof v.x=="number"?v.x:0,m=typeof v.y=="number"?v.y:0;l[p]={note:p,pos:{x:f,y:m}}}Object.keys(l).length===0?delete this.settings.nonMarkdownPositions[r]:this.settings.nonMarkdownPositions[r]=l,await this.saveSettings()}};this.registerBasesView(Ie,{name:"Bases Canvas",icon:"layout-dashboard",factory:(r,o)=>new Z(r,o,n),options:Z.getViewOptions});let a={app:this.app,pinDataService:this.pinDataService};this.registerBasesView(Oe,{name:"Canvas List",icon:"layout-grid",factory:(r,o)=>new te(r,o,a),options:te.getViewOptions});let i={app:this.app,bridge:this.bridge,pinDataService:this.pinDataService};this.registerBasesView(He,{name:"Canvas Nodes",icon:"blocks",factory:(r,o)=>new ne(r,o,i),options:ne.getViewOptions}),this.addSettingTab(new ce(this.app,this)),this.addCommand({id:"clean-canvas-metadata",name:"Clean erroneous Canvas metadata from all files",callback:async()=>{await this.cleanErroneousCanvasMetadata()}})}onunload(){var e;(e=this.bridge)==null||e.stop(),this.bridge=null,this.edgeListenerUnsubscribe&&(this.edgeListenerUnsubscribe(),this.edgeListenerUnsubscribe=null),this.nodeIndexCache.clear(),this.updatingNodes.clear(),this.pinDataService=null}resolveTargetNote(e){if(e.extension==="canvas"){let t=e.path.replace(/\.canvas$/i,".md"),n=this.app.vault.getAbstractFileByPath(t);return n instanceof z.TFile&&n.extension==="md"?n:(console.warn(`Unable to locate markdown companion for Canvas file: ${e.path}`),null)}return e.extension==="md"?e:null}async loadSettings(){let e=await this.loadData();this.settings=Object.assign({},H,e!=null?e:{}),(!this.settings.metadataProperty||this.settings.metadataProperty.trim().length===0)&&(this.settings.metadataProperty=H.metadataProperty),(!this.settings.nonMarkdownPositions||typeof this.settings.nonMarkdownPositions!="object")&&(this.settings.nonMarkdownPositions={}),typeof this.settings.linkMetadataEnabled!="boolean"&&(this.settings.linkMetadataEnabled=H.linkMetadataEnabled),(!this.settings.linkMetadataProperty||this.settings.linkMetadataProperty.trim().length===0)&&(this.settings.linkMetadataProperty=H.linkMetadataProperty),(!this.settings.pinnedCanvases||!Array.isArray(this.settings.pinnedCanvases))&&(this.settings.pinnedCanvases=[]),(!this.settings.pinnedNodes||typeof this.settings.pinnedNodes!="object")&&(this.settings.pinnedNodes={})}async saveSettings(){await this.saveData(this.settings)}async syncLinkMetadata(e){var l;if(!this.settings.linkMetadataEnabled)return;let t=((l=this.settings.linkMetadataProperty)==null?void 0:l.trim())||H.linkMetadataProperty;if(t.length===0)return;if(this.syncingStates.has(e)){console.debug("Skipping concurrent sync for same Canvas state");return}let n;try{n=JSON.parse(e)}catch(c){console.warn("Failed to parse Canvas payload while updating link metadata.",c);return}let a=Array.isArray(n.nodes)?n.nodes:[],i=this.buildNodePathIndex(a);if(i.size===0)return;let r=Array.isArray(n.edges)?n.edges:[],o=this.buildEdgeAdjacency(r,i);this.syncingStates.add(e);try{for(let c of i.values())o.has(c)||o.set(c,new Set);for(let[c,h]of o){let d=this.app.vault.getFileByPath(c);if(!d)continue;let p=this.buildLinkStrings(c,h);console.log("linkStrings",p,d),await this.app.fileManager.processFrontMatter(d,v=>{this.applyLinkMetadata(v,t,p)})}}finally{this.syncingStates.delete(e)}}buildNodePathIndex(e){let t=new Map;for(let n of e){if(!n||typeof n!="object")continue;let a=n;if(typeof a.id!="string"||a.id.length===0)continue;let i=null;if(typeof a.file=="string"&&a.file.trim().length>0)i=a.file.trim();else if(a.unknownData&&typeof a.unknownData=="object"){let o=a.unknownData[ut];if(o&&typeof o=="object"){let l=o.entryPath;typeof l=="string"&&l.trim().length>0&&(i=l.trim())}}if(!i)continue;let r=this.canonicalizeEntryPath(i);r&&t.set(a.id,r)}return t}buildEdgeAdjacency(e,t){var a;let n=new Map;for(let i of e){if(!i||typeof i!="object")continue;let r=i,o=typeof r.fromNode=="string"?r.fromNode:typeof r.from=="string"?r.from:null,l=typeof r.toNode=="string"?r.toNode:typeof r.to=="string"?r.to:null;if(!o||!l)continue;let c=t.get(o),h=t.get(l);!c||!h||(n.has(c)||n.set(c,new Set),(a=n.get(c))==null||a.add(h))}return n}canonicalizeEntryPath(e){let t=typeof e=="string"?e.trim():"";if(t.length===0)return"";if(t.includes("://"))return t;let n=t;try{n=(0,z.normalizePath)(t)}catch(i){n=t}let a=this.app.vault.getAbstractFileByPath(n);return a instanceof z.TFile?a.path:n}applyLinkMetadata(e,t,n){let a=this.normalizeLinkValues(e[t]),i=[...n];if(i.length===0){if(a.length===0&&e[t]===void 0)return;delete e[t];return}let r=i.length>1,o=r?i:i[0];this.areLinkListsEqual(a,i)&&r===Array.isArray(e[t])||(e[t]=o)}normalizeLinkValues(e){if(Array.isArray(e))return e.map(t=>typeof t=="string"?t.trim():String(t)).filter(t=>t.length>0).sort((t,n)=>t.localeCompare(n,void 0,{sensitivity:"base"}));if(typeof e=="string"){let t=e.trim();return t.length>0?[t]:[]}return[]}areLinkListsEqual(e,t){if(e.length!==t.length)return!1;for(let n=0;n<e.length;n++)if(e[n]!==t[n])return!1;return!0}async handleEdgeChanges(e,t,n,a,i){var c;let r=this.getOrBuildNodeIndex(a);if(!r){console.warn("Failed to get node index for edge sync");return}let o=new Map;for(let h of n){let d=r.get(h.from),p=r.get(h.to);!d||!p||(o.has(d)||o.set(d,new Set),(c=o.get(d))==null||c.add(p))}let l=new Set;for(let h of[...e,...t]){let d=r.get(h.from);d&&l.add(d)}for(let h of l){let d=o.get(h)||new Set;await this.updateNodeLinkMetadata(h,d,i)}console.debug(`Updated link metadata for ${l.size} nodes`)}getOrBuildNodeIndex(e){let t=e.substring(0,100);if(this.nodeIndexCache.has(t))return this.nodeIndexCache.get(t);let n;try{n=JSON.parse(e)}catch(r){return console.warn("Failed to parse Canvas data for node index",r),null}let a=Array.isArray(n.nodes)?n.nodes:[],i=this.buildNodePathIndex(a);if(this.nodeIndexCache.size>10){let r=this.nodeIndexCache.keys().next().value;this.nodeIndexCache.delete(r)}return this.nodeIndexCache.set(t,i),i}async cleanErroneousCanvasMetadata(){let e=this.app.vault.getMarkdownFiles(),t=0,n=0;for(let i of e)try{let r=!1;await this.app.fileManager.processFrontMatter(i,o=>{let l=[];for(let[c,h]of Object.entries(o))(h&&typeof h=="object"&&!Array.isArray(h)&&"nodes"in h&&Array.isArray(h.nodes)||c.includes("/")&&c.endsWith(".md")&&h&&typeof h=="object")&&(l.push(c),r=!0);for(let c of l)delete o[c],console.log(`Removing erroneous Canvas data from ${i.path}: ${c}`)}),r&&t++}catch(r){console.error(`Failed to clean metadata from ${i.path}:`,r),n++}let a=`Canvas metadata cleanup complete.
Cleaned: ${t} files
Errors: ${n} files`;new z.Notice(a),console.log(a)}buildLinkStrings(e,t){let n=this.app.vault.getFileByPath(e);return n?Array.from(t).map(i=>i.trim()).filter(i=>i.length>0&&i!==e).map(i=>this.app.vault.getFileByPath(i)).filter(i=>i instanceof z.TFile).map(i=>`[[${this.app.metadataCache.fileToLinktext(i,n.path)}]]`).sort((i,r)=>i.localeCompare(r,void 0,{sensitivity:"base"})):[]}async updateNodeLinkMetadata(e,t,n){if(this.updatingNodes.has(e)){console.debug(`Skipping concurrent update for ${e}`);return}let a=this.app.vault.getFileByPath(e);if(a){this.updatingNodes.add(e);try{let i=this.buildLinkStrings(e,t);console.debug(`Updating links for ${e}: ${i.join(", ")}`),await this.app.fileManager.processFrontMatter(a,r=>{this.applyLinkMetadata(r,n,i)})}finally{this.updatingNodes.delete(e)}}}};