fix(local-workspace): boite de renommage a la taille du nom + bouton Open a cote
- La boite d'edition inline est desormais large comme le nom du fichier (largeur mesuree a l'ouverture via _fitNameWidth, min 60px, bornee a l'espace disponible pour les tres longs noms — le texte defile dedans). - Le bouton Open est place juste a droite de la boite (marge 6px) au lieu du bord du panneau : deplace dans la cellule .name.file, passee en inline-flex (overflow hidden + max-width) pour ne jamais passer a la ligne. - Applique aux deux rendus de l'arbre (vue principale x-for + renderChildren). - Verifie en Chrome headless : input = largeur du nom (38%/12% de la ligne au lieu de 100%), bouton Open a 6px de la boite, pas de passage a la ligne. - Tests : 278 passent.
This commit is contained in:
@@ -104,7 +104,7 @@
|
||||
.ws-checkbox.checked svg{width:10px;height:10px;color:#fff;}
|
||||
|
||||
/* ── OPEN button ── */
|
||||
.btn-open{display:inline-flex;align-items:center;gap:4px;padding:3px 8px;border:1px solid var(--border);border-radius:4px;font-size:11px;font-weight:500;color:var(--text-primary);background:var(--bg-tertiary);cursor:pointer;white-space:nowrap;transition:all 0.1s;flex-shrink:0;text-decoration:none;margin-left:auto;}
|
||||
.btn-open{display:inline-flex;align-items:center;gap:4px;padding:3px 8px;border:1px solid var(--border);border-radius:4px;font-size:11px;font-weight:500;color:var(--text-primary);background:var(--bg-tertiary);cursor:pointer;white-space:nowrap;transition:all 0.1s;flex-shrink:0;text-decoration:none;margin-left:6px;}
|
||||
.btn-open:hover{background:var(--bg-active);}
|
||||
.btn-open svg{width:12px;height:12px;}
|
||||
|
||||
@@ -162,6 +162,9 @@
|
||||
.ws-tree-item .name.folder:hover{color:var(--accent);}
|
||||
.ws-tree-item .name.file{cursor:pointer;}
|
||||
.ws-tree-item .name.file:hover{color:var(--accent);}
|
||||
.ws-tree-item .name.file{display:inline-flex;align-items:center;max-width:100%;overflow:hidden;}
|
||||
.ws-tree-item .name.file .inline-rename-input{flex:0 1 auto;}
|
||||
.ws-tree-item .name.file .btn-open{flex:0 0 auto;}
|
||||
.ws-tree-item .actions{display:none;gap:2px;}
|
||||
.ws-tree-item:hover .actions{display:flex;}
|
||||
.ws-chevron{width:16px;height:16px;flex-shrink:0;display:inline-flex;align-items:center;justify-content:center;background:none;border:none;color:var(--text-tertiary);cursor:pointer;font-size:8px;padding:0;border-radius:3px;transition:transform 150ms,color 100ms;}
|
||||
@@ -277,7 +280,7 @@
|
||||
.child-count{font-size:11px;color:var(--text-tertiary);margin-left:4px;}
|
||||
|
||||
/* Inline rename */
|
||||
.inline-rename-input{background:var(--bg);border:1px solid var(--accent);border-radius:4px;color:var(--text);font-size:13px;padding:2px 6px;outline:none;min-width:100px;}
|
||||
.inline-rename-input{background:var(--bg);border:1px solid var(--accent);border-radius:4px;color:var(--text);font-size:13px;padding:2px 6px;outline:none;min-width:60px;}
|
||||
|
||||
/* Drag count badge */
|
||||
.drag-badge{position:fixed;pointer-events:none;z-index:999;background:var(--accent);color:#fff;font-size:12px;font-weight:700;padding:2px 8px;border-radius:10px;transform:translate(-50%,-50%);}
|
||||
@@ -1208,18 +1211,16 @@ window._wsInitData = (function() {
|
||||
+ ' onmouseenter="var d=window._wsData;if(d)d.showPreview(event,{id:'+escId+',name:\''+escName+'\',is_folder:false,content_format:\''+(c.content_format||'')+'\'})"'
|
||||
+ ' onmouseleave="var d=window._wsData;if(d)d.hidePreview()">'
|
||||
+ '<span id="rc-name-'+escId+'">'+c.name+'</span>'
|
||||
+ '<input id="rc-input-'+escId+'" class="inline-rename-input" style="display:none;width:100%"'
|
||||
+ '<input id="rc-input-'+escId+'" class="inline-rename-input" style="display:none"'
|
||||
+ ' onkeydown="if(event.key===\'Enter\')window._wsData.commitRenderChildRename('+escId+')"'
|
||||
+ ' onblur="window._wsData.commitRenderChildRename('+escId+')"'
|
||||
+ ' onclick="event.stopPropagation()">'
|
||||
+ '<a href="#" class="btn-open hover-only"'
|
||||
+ ' onclick="event.stopPropagation();event.preventDefault();var d=window._wsData;if(d)d.openSidePeek('+escId+')"'
|
||||
+ ' title="Open in side preview">↢ Open</a>'
|
||||
+ '</span>';
|
||||
}
|
||||
// Open button for files — to the right of title (like Library)
|
||||
if (!c.is_folder) {
|
||||
html += '<a href="#" class="btn-open hover-only" style="margin-left:auto;"'
|
||||
+ ' onclick="event.stopPropagation();event.preventDefault();var d=window._wsData;if(d)d.openSidePeek('+escId+')"'
|
||||
+ ' title="Open in side preview">↢ Open</a>';
|
||||
}
|
||||
html += '<div class="actions">';
|
||||
if (c.is_folder) {
|
||||
html += '<span style="display:flex;gap:2px">';
|
||||
@@ -1258,6 +1259,9 @@ window._wsInitData = (function() {
|
||||
nameSpan.style.display = 'none';
|
||||
input.style.display = '';
|
||||
input.value = currentName;
|
||||
var w = this._fitNameWidth(currentName);
|
||||
var avail = input.parentElement ? input.parentElement.clientWidth : 0;
|
||||
if (avail > 60) input.style.width = Math.min(w, avail) + 'px'; else input.style.width = w + 'px';
|
||||
input.focus();
|
||||
input.select();
|
||||
},
|
||||
@@ -1290,6 +1294,16 @@ window._wsInitData = (function() {
|
||||
return s.replace(/\\/g,'\\\\').replace(/'/g,"\\'").replace(/"/g,'"');
|
||||
},
|
||||
|
||||
_fitNameWidth(text) {
|
||||
var off = document.createElement('span');
|
||||
off.style.cssText = 'position:absolute;visibility:hidden;white-space:pre;font-size:13px;';
|
||||
off.textContent = (text || '').toString();
|
||||
document.body.appendChild(off);
|
||||
var w = off.offsetWidth;
|
||||
document.body.removeChild(off);
|
||||
return Math.max(w + 16, 60);
|
||||
},
|
||||
|
||||
// ── Event delegation for renderChildren action buttons ──
|
||||
handleTreeAction(ev) {
|
||||
var btn = (ev.target.closest && ev.target.closest('[data-ws-action]'))
|
||||
@@ -1425,7 +1439,12 @@ window._wsInitData = (function() {
|
||||
var self = this;
|
||||
this.$nextTick(function() {
|
||||
var inp = self.$el.querySelector('.inline-rename-input:not([style*="display: none"])');
|
||||
if (inp) { inp.focus(); inp.select(); }
|
||||
if (inp) {
|
||||
var w = self._fitNameWidth(self.renamingName);
|
||||
var avail = inp.parentElement ? inp.parentElement.clientWidth : 0;
|
||||
if (avail > 60) inp.style.width = Math.min(w, avail) + 'px'; else inp.style.width = w + 'px';
|
||||
inp.focus(); inp.select();
|
||||
}
|
||||
});
|
||||
},
|
||||
async commitRename(node) {
|
||||
@@ -2521,7 +2540,7 @@ console.log('FLOWDECK v2.4.6 — IIFE done, _wsInitData keys:', Object.keys(wind
|
||||
x-text="'(' + node.child_count + ')'"></span>
|
||||
<input x-show="renamingId === node.id" class="inline-rename-input" x-model="renamingName"
|
||||
@keydown.enter="commitRename(node)" @keydown.escape="cancelRename()"
|
||||
@blur="commitRename(node)" @click.stop style="width:100%">
|
||||
@blur="commitRename(node)" @click.stop>
|
||||
</span>
|
||||
</template>
|
||||
<template x-if="!node.is_folder">
|
||||
@@ -2532,12 +2551,10 @@ console.log('FLOWDECK v2.4.6 — IIFE done, _wsInitData keys:', Object.keys(wind
|
||||
<span x-show="renamingId !== node.id" x-text="node.name"></span>
|
||||
<input x-show="renamingId === node.id" class="inline-rename-input" x-model="renamingName"
|
||||
@keydown.enter="commitRename(node)" @keydown.escape="cancelRename()"
|
||||
@blur="commitRename(node)" @click.stop style="width:100%">
|
||||
@blur="commitRename(node)" @click.stop>
|
||||
<a href="#" class="btn-open hover-only" @click.prevent.stop="selectForPreview(node)" title="Open in side preview">↢ Open</a>
|
||||
</span>
|
||||
</template>
|
||||
<template x-if="!node.is_folder">
|
||||
<a href="#" class="btn-open hover-only" @click.prevent.stop="selectForPreview(node)" title="Open in side preview" style="margin-left:auto;">↢ Open</a>
|
||||
</template>
|
||||
|
||||
<div class="actions">
|
||||
<template x-if="node.is_folder">
|
||||
|
||||
Reference in New Issue
Block a user