fix: repositionnement dynamique du menu contextuel dans le viewport
- Remplacé le clamping statique (Math.min 200/300) par mesure réelle du menu après rendu DOM via $nextTick + getBoundingClientRect() - Si le menu dépasse à droite → repositionné à gauche - Si le menu dépasse en bas → repositionné vers le haut - Marge de 4px des bords pour éviter le clipping - Fonctionne pour toutes les tailles de menu (tags, sous-menus dépliés)
This commit is contained in:
@@ -1257,28 +1257,41 @@ document.addEventListener('alpine:init', function() {
|
|||||||
|
|
||||||
// ── Context menu ──
|
// ── Context menu ──
|
||||||
onContextMenu(ev) {
|
onContextMenu(ev) {
|
||||||
// Find closest element with data-ws-id (works on all views)
|
|
||||||
var el = ev.target.closest('[data-ws-id]');
|
var el = ev.target.closest('[data-ws-id]');
|
||||||
if (!el) { this.ctxMenu.visible = false; return; }
|
if (!el) { this.ctxMenu.visible = false; return; }
|
||||||
var id = parseInt(el.getAttribute('data-ws-id'));
|
var id = parseInt(el.getAttribute('data-ws-id'));
|
||||||
if (!id) { this.ctxMenu.visible = false; return; }
|
if (!id) { this.ctxMenu.visible = false; return; }
|
||||||
// Find node in tree
|
|
||||||
var node = this._findNodeById(this.displayTree, id);
|
var node = this._findNodeById(this.displayTree, id);
|
||||||
if (!node) { this.ctxMenu.visible = false; return; }
|
if (!node) { this.ctxMenu.visible = false; return; }
|
||||||
this.ctxMenu = {
|
this.ctxMenu = {
|
||||||
visible: true,
|
visible: true,
|
||||||
x: Math.min(ev.clientX, window.innerWidth - 200),
|
x: ev.clientX,
|
||||||
y: Math.min(ev.clientY, window.innerHeight - 300),
|
y: ev.clientY,
|
||||||
node: node,
|
node: node,
|
||||||
tags: [...(node.tags||[])]
|
tags: [...(node.tags||[])]
|
||||||
};
|
};
|
||||||
this.ctxTagAdding = false;
|
this.ctxTagAdding = false;
|
||||||
this.ctxTagExistingOpen = false;
|
this.ctxTagExistingOpen = false;
|
||||||
this.ctxNewTagColor = '#787774';
|
this.ctxNewTagColor = '#787774';
|
||||||
// Load available tags (not already on the item)
|
// Load available tags
|
||||||
this.ctxAvailTags = (this.workspaceTags || []).filter(function(t) {
|
this.ctxAvailTags = (this.workspaceTags || []).filter(function(t) {
|
||||||
return !(node.tags||[]).some(function(nt) { return nt.id === t.id; });
|
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) {
|
ctxAddExistingTag(tag) {
|
||||||
|
|||||||
Reference in New Issue
Block a user