diff --git a/app/templates/local_workspace.html b/app/templates/local_workspace.html index 9498e88..7beba69 100644 --- a/app/templates/local_workspace.html +++ b/app/templates/local_workspace.html @@ -1257,28 +1257,41 @@ document.addEventListener('alpine:init', function() { // ── Context menu ── onContextMenu(ev) { - // Find closest element with data-ws-id (works on all views) var el = ev.target.closest('[data-ws-id]'); if (!el) { this.ctxMenu.visible = false; return; } var id = parseInt(el.getAttribute('data-ws-id')); if (!id) { this.ctxMenu.visible = false; return; } - // Find node in tree var node = this._findNodeById(this.displayTree, id); if (!node) { this.ctxMenu.visible = false; return; } this.ctxMenu = { visible: true, - x: Math.min(ev.clientX, window.innerWidth - 200), - y: Math.min(ev.clientY, window.innerHeight - 300), + x: ev.clientX, + y: ev.clientY, node: node, tags: [...(node.tags||[])] }; this.ctxTagAdding = false; this.ctxTagExistingOpen = false; this.ctxNewTagColor = '#787774'; - // Load available tags (not already on the item) + // Load available tags this.ctxAvailTags = (this.workspaceTags || []).filter(function(t) { return !(node.tags||[]).some(function(nt) { return nt.id === t.id; }); }); + // Reposition after DOM update + var self = this; + self.$nextTick(function() { + var menu = self.$el.querySelector('.ctx-menu'); + if (!menu) return; + var rect = menu.getBoundingClientRect(); + var x = self.ctxMenu.x; + var y = self.ctxMenu.y; + if (x + rect.width > window.innerWidth - 4) x = window.innerWidth - rect.width - 4; + if (y + rect.height > window.innerHeight - 4) y = window.innerHeight - rect.height - 4; + if (x < 4) x = 4; + if (y < 4) y = 4; + self.ctxMenu.x = x; + self.ctxMenu.y = y; + }); }, ctxAddExistingTag(tag) {