fix(editor): placeholder visible, fleches menu /, icones callout/image, largeur composer AI
- Placeholder "Press 'space'..." : la classe .empty est basculee sur l'element interne [data-bid], mais la regle CSS ciblait .block-content (l'exterieur), donc le ::before ne se rendait jamais. La regle cible desormais .block-content [data-bid].empty::before. - Fleches haut/bas du menu / : ajout d'un ecouteur keydown au niveau document (actif quand le menu est ouvert) pour naviguer quel que soit le focus (l'input vit dans #_slashMenu, voisin de #_blocksCt). Selection .selected en !important pour gagner sur :hover + auto-scroll de l'element selectionne. - Item "callout" du menu / : icone texte 'lightbulb' remplacee par l'emoji (et 'image' par ). Le texte n'est plus mal positionne. - Composer "Edit with AI" : largeur alignee sur celle du bloc (min 280px). v5.1.4
This commit is contained in:
+32
-1
@@ -1,6 +1,37 @@
|
||||
# Changelog — FlowDeck
|
||||
|
||||
## v5.1.3 (2026-09-07) — Corrections : AI inline (400), bloc vide, menu `/`, poignée, contour
|
||||
## v5.1.4 (2026-09-07) — Corrections : placeholder invisible, flèches `/`, item vocabulaire, largeur AI
|
||||
|
||||
> Résout les derniers retours UI de l'éditeur v5.1.2/5.1.3.
|
||||
|
||||
### Placeholder « Press 'space' for AI » — jamais affiché
|
||||
- **Cause réelle** : la classe `.empty` est basculée sur l'élément interne
|
||||
`[data-bid]` (sélecteur `[data-placeholder]` au render), mais la règle CSS
|
||||
ciblait l'élément **externe** `.block-content` — deux éléments différents, donc
|
||||
le `::before` d'aide ne se rendait **jamais**.
|
||||
- La règle cible désormais `.block-content [data-bid].empty::before` (l'élément
|
||||
qui porte réellement `data-placeholder` + `.empty`).
|
||||
|
||||
### Flèches ↑/↓ du menu `/`
|
||||
- La navigation dépendait de l'endroit où se trouvait le focus (`_in` vs bloc vs
|
||||
ailleurs) : `onKd` n'est lié qu'à `#_blocksCt`, l'input vit dans `#_slashMenu`
|
||||
(un voisin), d'où un comportement fragile/incohérent.
|
||||
- Ajout d'un écouteur `keydown` **au niveau document** (actif quand le menu est
|
||||
ouvert) : ↑/↓/Entrée/Échap fonctionnent quel que soit le focus, plus de double
|
||||
déclenchement.
|
||||
- La sélection `.selected` passe en `!important` pour toujours gagner sur
|
||||
`.slash-item:hover`, et l'élément sélectionné est auto-défilé (`scrollIntoView`).
|
||||
|
||||
### Item « vocabulaire / vocabulaire » du menu `/` mal positionné
|
||||
- Les icônes texte `'lightbulb'` (Callout) et `'image'` (Image) étaient injectées
|
||||
en clair dans la pastille d'icône, provoquant un texte décalé/débordant.
|
||||
- Remplacées par les emojis `💡` (Callout) et `🖼️` (Image).
|
||||
|
||||
### Composer « Edit with AI » — largeur
|
||||
- Le composer AI utilisait une largeur fixe `420px` ; il s'aligne désormais sur la
|
||||
largeur du bloc ciblé (min 280px, max 1200px).
|
||||
|
||||
|
||||
|
||||
> Résout les régressions du composer AI et de l'éditeur Notion-style v5.1.2.
|
||||
|
||||
|
||||
+1
-1
@@ -60,7 +60,7 @@ async def lifespan(_app: FastAPI):
|
||||
|
||||
app = FastAPI(
|
||||
title="FlowDeck",
|
||||
version="5.1.3",
|
||||
version="5.1.4",
|
||||
docs_url="/docs" if settings.log_level == "DEBUG" else None,
|
||||
redoc_url=None,
|
||||
lifespan=lifespan,
|
||||
|
||||
@@ -7,10 +7,10 @@
|
||||
{id:'paragraph',name:'Text',icon:'¶'},{id:'heading_1',name:'Heading 1',icon:'H1'},{id:'heading_2',name:'Heading 2',icon:'H2'},
|
||||
{id:'heading_3',name:'Heading 3',icon:'H3'},{id:'heading_4',name:'Heading 4',icon:'H4'},{id:'bulleted_list',name:'Bulleted list',icon:'•'},{id:'numbered_list',name:'Numbered list',icon:'1.'},
|
||||
{id:'to_do',name:'To-do',icon:'☐'},{id:'toggle',name:'Toggle',icon:'▶'},{id:'quote',name:'Quote',icon:'❝'},
|
||||
{id:'callout',name:'Callout',icon:'lightbulb'},{id:'table_of_contents',name:'Table of contents',icon:'☰'},{id:'math',name:'Math equation',icon:'∑'},
|
||||
{id:'callout',name:'Callout',icon:'💡'},{id:'table_of_contents',name:'Table of contents',icon:'☰'},{id:'math',name:'Math equation',icon:'∑'},
|
||||
{id:'columns',name:'Column list',icon:'▮'},{id:'divider',name:'Divider',icon:'—'},{id:'code',name:'Code block',icon:'<>'},
|
||||
{id:'table',name:'Table',icon:'⊞'},
|
||||
]},{name:'MEDIA',items:[{id:'image',name:'Image',icon:'image'}]},
|
||||
]},{name:'MEDIA',items:[{id:'image',name:'Image',icon:'🖼️'}]},
|
||||
{name:'DATA',items:[{id:'database',name:'Database / Inline database',icon:'📊'}]}];
|
||||
|
||||
let _bid=0;function genId(){return 'b'+(++_bid)+'_'+Date.now().toString(36);}
|
||||
@@ -220,10 +220,23 @@
|
||||
footer.onclick=()=>SM.close();
|
||||
const inp=document.createElement('input');inp.type='text';inp.placeholder='Type to search';
|
||||
inp.style.cssText='width:100%;padding:9px 12px;background:var(--bg-secondary);border:none;border-top:1px solid var(--border);color:var(--text-primary);font-size:14px;outline:none;box-sizing:border-box';
|
||||
inp.oninput=()=>SM.flt();inp.onkeydown=ev=>SM._kd(ev);
|
||||
inp.oninput=()=>SM.flt();
|
||||
e.appendChild(list);e.appendChild(footer);e.appendChild(inp);
|
||||
SM._e=e;SM._in=inp;SM._li=list;SM._f=footer;
|
||||
document.addEventListener('mousedown',ev=>{if(!e.contains(ev.target))SM.close();});
|
||||
if(!SM._doc){
|
||||
SM._doc=true;
|
||||
document.addEventListener('keydown',function(ev){
|
||||
if(!SM._o)return;
|
||||
if(ev.metaKey||ev.ctrlKey||ev.altKey)return;
|
||||
if(ev.key==='ArrowDown'||ev.key==='ArrowUp'||ev.key==='Enter'||ev.key==='Escape'){
|
||||
ev.preventDefault();ev.stopPropagation();SM._docKd(ev);
|
||||
}
|
||||
});
|
||||
}
|
||||
SM._docKd=function(ev){
|
||||
if(SM._o&&(ev.key==='ArrowDown'||ev.key==='ArrowUp'||ev.key==='Enter'||ev.key==='Escape'))SM._kd(ev);
|
||||
};
|
||||
},
|
||||
_hover(it){ if(!it) return; const id=it.dataset.sid; if(!id) return;
|
||||
if(!SM._pv){ const d=document.createElement('div'); d.className='sm-preview'; d.style.cssText='position:fixed;z-index:1000;background:var(--bg-modal);border:1px solid var(--border-light);border-radius:8px;box-shadow:0 8px 24px rgba(0,0,0,.5);padding:12px;width:220px;pointer-events:none;'; document.body.appendChild(d); SM._pv=d; }
|
||||
@@ -253,7 +266,7 @@
|
||||
else if(e.key==='ArrowUp'){e.preventDefault();SM._s=Math.max(SM._s-1,0);SM._rs();}
|
||||
else if(e.key==='Enter'){e.preventDefault();const c=SM._it[SM._s];if(c)SM.sel(c.id);}
|
||||
else if(e.key==='Escape'){e.preventDefault();SM.close();}},
|
||||
_rs(){const its=SM._li.querySelectorAll('.slash-item');its.forEach((el,i)=>{el.classList.toggle('selected',i===SM._s);});},
|
||||
_rs(){const its=SM._li.querySelectorAll('.slash-item');its.forEach((el,i)=>{el.classList.toggle('selected',i===SM._s);});const cur=its[SM._s];if(cur&&cur.scrollIntoView)cur.scrollIntoView({block:'nearest'});},
|
||||
sel(id){if(window.E)window.E.applySlash(id);SM.close();},
|
||||
get isOpen(){return SM._o;}};
|
||||
|
||||
@@ -266,14 +279,16 @@
|
||||
const d=document.createElement('div'); d.id='_aiC'; d.style.cssText='position:fixed;z-index:1200;width:420px;max-width:92vw;display:none';
|
||||
document.body.appendChild(d); this.ROOT=d; return d; },
|
||||
open(idx){ const self=this; this._idx=idx; this._stage='input'; this.mk();
|
||||
const r=this._anchorRect(idx); this.ROOT.style.left=Math.max(8,Math.min(r.left,window.innerWidth-440))+ 'px';
|
||||
const r=this._anchorRect(idx);
|
||||
const w=Math.max(r.width||0,280); this.ROOT.style.width=Math.min(w,1200)+'px';
|
||||
this.ROOT.style.left=Math.max(8,Math.min(r.left,window.innerWidth-r.width-16))+ 'px';
|
||||
this.ROOT.style.top=Math.max(8,(r.bottom+6>window.innerHeight-260)?r.top-180:r.bottom+6)+'px';
|
||||
this.paint(); this.ROOT.style.display='block'; this._open=true; this._focusIngest();
|
||||
document.addEventListener('mousedown',function onDoc(ev){ if(!self.ROOT.contains(ev.target)){ self.close(); document.removeEventListener('mousedown',onDoc); } });
|
||||
},
|
||||
close(){ if(this.ROOT)this.ROOT.style.display='none'; this._open=false; this._html=''; if(window.E)window.E.dirty=true; this._stage=''; },
|
||||
_anchorRect(idx){ const E=window.E; if(!E||!E.blocks)return{x:Math.max(24,window.innerWidth/2-210),bottom:window.innerHeight/2};
|
||||
const b=E.blocks[idx]; const el=E.getEl(b?b.id:null); if(el){const r=el.getBoundingClientRect();return r;} return {left:24,top:120,bottom:180}; },
|
||||
_anchorRect(idx){ const E=window.E; if(!E||!E.blocks)return{left:Math.max(24,window.innerWidth/2-210),top:window.innerHeight/2,bottom:window.innerHeight/2,width:420};
|
||||
const b=E.blocks[idx]; const el=E.getEl(b?b.id:null); if(el){const r=el.getBoundingClientRect();return r;} return {left:24,top:120,bottom:180,width:420}; },
|
||||
_focusIngest(){ const i=this.ROOT.querySelector('.aici-input'); if(i){i.focus();} },
|
||||
_escTag(tag,s){return '<'+tag+'>'+s+'</'+tag+'>';},
|
||||
_mdToHtml(md){ // compact block render (headings, lists, bold, paragraphs)
|
||||
@@ -1088,7 +1103,7 @@ applyAIBlocks(text){
|
||||
const{el,bid,idx}=ab;const block=this.blocks[idx];if(!block)return;
|
||||
if(SM.isOpen){
|
||||
if(e.key==='Escape'){e.preventDefault();SM.close();return;}
|
||||
if(e.key==='ArrowDown'||e.key==='ArrowUp'||e.key==='Enter'){e.preventDefault();SM._in.dispatchEvent(new KeyboardEvent('keydown',{key:e.key,bubbles:true}));return;}
|
||||
if(e.key==='ArrowDown'||e.key==='ArrowUp'||e.key==='Enter'){e.preventDefault();return;}
|
||||
if(e.key==='Backspace'&&!SM._q&&(el.textContent||'').trim()==='/'){e.preventDefault();SM.close();return;}
|
||||
return;
|
||||
}
|
||||
|
||||
+2
-1
@@ -2334,6 +2334,7 @@ button.breadcrumb-current { max-width: 260px; }
|
||||
min-height: 28px;
|
||||
word-break: break-word;
|
||||
}
|
||||
.block-content [data-bid].empty::before,
|
||||
.block-content.empty::before {
|
||||
content: attr(data-placeholder);
|
||||
color: var(--text-secondary);
|
||||
@@ -4585,7 +4586,7 @@ button.breadcrumb-current { max-width: 260px; }
|
||||
@keyframes ai-pulse { 0%,100%{opacity:.45} 50%{opacity:1} }
|
||||
.slash-menu { flex-direction: column; }
|
||||
.slash-menu .sm-footer:hover { background: var(--bg-hover); }
|
||||
.slash-item.selected { background: rgba(35,131,226,.16); box-shadow: inset 2px 0 0 var(--accent,#2383E2); }
|
||||
.slash-item.selected { background: rgba(35,131,226,.16) !important; box-shadow: inset 2px 0 0 var(--accent,#2383E2) !important; }
|
||||
.slash-item.selected .slash-item-name { color: var(--text); }
|
||||
.slash-item-hint { font-size: 12px; color: var(--text-dim); opacity: .7; }
|
||||
.sm-preview { font-family: inherit; }
|
||||
|
||||
Reference in New Issue
Block a user