feat(BlockEditor): add image alignment, link, and replace/delete controls
- add align (left/center/right/full), href, newTab fields to image block - render floating toolbar on image hover with alignment buttons and link popover - add replace and delete actions to image toolbar - wrap image in <a> in disabled mode and HTML export when href is set - update htmlToBlocks/blocksToHtml to serialize/parse align, href, newTab - guard handleContainerMouseDown to prevent multi-block selection on input/textarea focus - add alignment and link icons to shared icons index - update README with image block spec and toolbar behaviour
This commit is contained in:
@@ -30,7 +30,7 @@ Chaque bloc a un `id` (UUID) et un `type`. Selon le type :
|
||||
| `quote` | `content` | citation |
|
||||
| `code` | `content` | bloc de code (monospace) |
|
||||
| `divider` | — | séparateur horizontal |
|
||||
| `image` | `src`, `alt`, `caption` | image (URL uniquement) |
|
||||
| `image` | `src`, `alt`, `caption`, `align`, `href`, `newTab` | image (URL uniquement) — `align` ∈ `left\|center\|right\|full`, `href` optionnel |
|
||||
|
||||
`content` est un **tableau `InlineNode[]`** depuis Phase 2 — voir ci-dessous.
|
||||
|
||||
@@ -285,9 +285,37 @@ page) sont traversés pour atteindre les éléments block-level
|
||||
descendants. Les styles CSS inline (`font-weight`, `font-style`,
|
||||
`text-decoration`) sont également lus en plus des tags sémantiques.
|
||||
|
||||
## Bloc image
|
||||
|
||||
Une fois l'URL insérée, l'image affiche au survol une **toolbar flottante**
|
||||
(coin haut-droit) reprenant le style `BOX_CLASS` partagé :
|
||||
|
||||
- **Alignement** : 4 boutons (gauche / centre / droite / pleine largeur).
|
||||
Persisté dans `block.align`. Le wrapper applique `justify-content` selon
|
||||
la valeur ; `'full'` passe l'image à `width: 100%` (l'image étire la
|
||||
largeur du conteneur de bloc, pas du viewport).
|
||||
- **Lien** : ouvre un mini-popover (input URL + case « nouvel onglet »).
|
||||
Persisté dans `block.href` et `block.newTab`. Côté éditeur l'image n'est
|
||||
jamais wrappée dans `<a>` pour ne pas piéger les clics ; en mode `disabled`
|
||||
et à l'export HTML (`blocksToHtml`), l'image est wrappée dans `<a>` avec
|
||||
`target="_blank" rel="noopener noreferrer"` quand `newTab` est vrai.
|
||||
- **Remplacer** : remet le formulaire URL avec l'URL courante préremplie.
|
||||
Conserve `alt`, `caption`, `align`, `href`. Échap pour annuler.
|
||||
- **Supprimer** : vide tous les champs ; le formulaire URL réapparaît.
|
||||
|
||||
Les inputs *Légende* et *Texte alternatif* sous l'image sont des `<input>`
|
||||
HTML standards. Le clic dans ces inputs ne déclenche pas la sélection
|
||||
multi-blocs (cf. garde dans `handleContainerMouseDown` : tout `input`,
|
||||
`textarea`, `select` ou `[contenteditable="true"]` reçoit son focus normal
|
||||
et n'entre pas en mode sélection).
|
||||
|
||||
Sérialisation HTML : `<figure data-align="…"><a href><img></a><figcaption></figcaption></figure>`.
|
||||
Le parser inverse (`htmlToBlocks`) lit `data-align`, et descend dans `<a>`
|
||||
quand l'`<img>` y est imbriqué pour récupérer `href` / `target`.
|
||||
|
||||
## Limitations connues
|
||||
|
||||
- Pas d'imbrication de listes.
|
||||
- Image : URL uniquement, pas d'upload de fichier (Phase 2). La caption est
|
||||
une string plate (pas de formatage inline pour l'instant).
|
||||
- Image : URL uniquement, pas d'upload de fichier. La caption est une
|
||||
string plate (pas de formatage inline pour l'instant).
|
||||
- Tables : Phase 3.
|
||||
|
||||
Reference in New Issue
Block a user