Files
Momento/docs/story-nextgen-editor-us4-redesign.md

477 lines
23 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# US-4 Redesign — Vue Structurée Inline dans l'Éditeur
> **Status :** DRAFT — En attente de validation fondateur
> **Remplace :** US-4 « Bloc de Base de Données Relationnelle Inline » (DEPRECATED)
> **Epic :** US-NEXTGEN-EDITOR
> **Dépend de :** US-STRUCTURED-VIEWS ✅ (livré), US-LIVING-BLOCKS ✅ (livré)
---
## 1. Problem Statement — Pourquoi l'ancienne US-4 est morte
L'implémentation actuelle (fichiers `tiptap-database-block-extension.tsx`, `database-block-editor.tsx`, `database-block-types.ts`) a été rejetée pour les raisons suivantes :
### 1.1 Copie de démo marketing, pas une feature produit
Le code source dans `createDefaultDatabaseBlockData()` insère **Jules Verne** et **Liu Cixin** avec leurs œuvres en données pré-remplies. C'est une copie directe du prototype `architectural-grid1/ModernBlockNoteEditor.tsx` qui était conçu pour une landing page, pas pour un produit de prise de notes réel.
### 1.2 Modèle de données parallèle et isolé
L'implémentation stocke `dbAuthorsJson` et `dbBooksJson` comme attributs HTML dans le nœud TipTap :
```html
<div data-database-block="true" data-db-id="authors-works-abc123"
data-db-authors='[{"id":"a1","name":"Jules Verne"}]'
data-db-books='[{"id":"bk1","title":"Vingt Mille Lieues..."}]'>
```
Problèmes critiques :
- **Isolation totale** : ces données n'ont aucun lien avec le carnet, les notes, ni les propriétés Prisma.
- **Scalabilité zéro** : stocker des listes entières de rows dans les attributs d'un nœud TipTap = explostion de la taille du HTML à chaque sauvegarde.
- **Duplication du modèle** : `NotebookSchema` + `NotebookProperty` + `NoteProperty` existent déjà en BDD et fonctionnent.
### 1.3 Confusion utilisateur
Un utilisateur qui tape `/database` s'attend à voir ses propres données structurées — pas un jeu de rôle bibliothèque de SF. Cette confusion est documentée comme rejet non-négociable par le fondateur.
### 1.4 Audit du code à supprimer
| Fichier | Statut | Raison |
|---------|--------|--------|
| `memento-note/components/tiptap-database-block-extension.tsx` | **SUPPRIMER** | Extension TipTap avec modèle `dbAuthors`/`dbBooks` |
| `memento-note/components/database-block-editor.tsx` | **SUPPRIMER** | UI Auteurs & Œuvres, hardcodé |
| `memento-note/lib/editor/database-block-types.ts` | **SUPPRIMER** | Types + données Verne/Liu Cixin |
| `rich-text-editor.tsx` L28, L193-194, L395, L412-420, L1286, L1335-1338, L1397-1401 | **MODIFIER** | Retirer imports et références `/database` anciens |
| `block-action-menu.tsx` L15-17, L33, L39, L51, L134-135 | **MODIFIER** | Retirer option `database` du menu "Transformer en" |
| `locales/*.json` — clés `databaseBlock.*` | **SUPPRIMER** | ~15 clés obsolètes |
---
## 2. Personas & Jobs-to-be-Done
### Persona 1 — Chloé, chercheuse (carnet "Thèse Linguistique")
Chloé a configuré son carnet avec des propriétés : `Statut` (select), `Langue` (select), `Lu` (checkbox), `Source` (text). Elle a 47 notes dans ce carnet. Elle rédige un chapitre synthétique et veut **voir le tableau de ses sources directement sous son paragraphe d'introduction**, sans quitter l'éditeur.
**Job-to-be-done :** *"Quand je rédige, je veux voir le tableau de mes données structurées en contexte, sans naviguer vers le carnet."*
### Persona 2 — Mehdi, chef de projet (carnet "Sprint Q2 2026")
Carnet structuré avec propriétés `Statut` (Kanban), `Priorité`, `Assigné`. Il prend ses notes de réunion et veut **insérer une vue en lecture de son Kanban** pour partager l'état du sprint dans la note de compte-rendu.
**Job-to-be-done :** *"Dans ma note de réunion, je veux une vue rapide de l'état des tâches du sprint."*
### Persona 3 — Yasmin, étudiante (carnet "Lectures Persan")
Carnet avec propriétés `Lu` (checkbox), `Note` (number). Elle lit en persan (RTL). Elle veut **voir sa liste de lectures sous forme de tableau** inline dans ses notes de révision.
**Job-to-be-done :** *"Dans mes notes, je veux voir mon tableau de lectures avec les bonnes valeurs — en persan, dans le bon sens."*
---
## 3. Options Produit pour `/database` — Analyse & Recommandation
### Option A — Embed Structured View (Recommandée ✅)
**Description :** Le bloc inline affiche une vue filtrée (Table ou Galerie) du schéma du carnet courant. Données lues depuis l'API existante. Le bloc stocke seulement `notebookId`, `displayMode`, `filterJson` dans ses attributs TipTap.
**Avantages :**
- Réutilise `NotesStructuredTable` et `NotesGalleryView` existants (quasi plug-and-play).
- Données cohérentes avec `/home` (même source de vérité).
- Léger : 3 attributs string dans le nœud TipTap, pas de payload.
- Facile à migrer : si le schéma du carnet change, le bloc se met à jour automatiquement.
- Clair pour l'utilisateur : "c'est mon carnet, mes données."
**Risques :**
- Éditeur doit recevoir `notebookId` (actuellement absent — patch mineur dans `note-content-area.tsx`).
- Si le carnet n'a pas de schéma, le bloc doit le gérer gracieusement.
**Verdict :** Option principale retenue.
### Option B — Linked Database Block (style Notion)
**Description :** L'utilisateur choisit n'importe quel carnet structuré (pas forcément le carnet de la note courante), avec filtre et vue configurables dans le bloc.
**Avantages :** Plus puissant — permet de croiser des carnets.
**Risques :**
- UI de sélection de carnet complexe dans le NodeView.
- Scope plus large que ce que justifie une US-4 isolée.
- Cross-notebook = scope Living Blocks étendu → reporter à v2.
**Verdict :** Déféré à v2 après que l'Option A soit stabilisée.
### Option C — Mini-table locale (colonnes libres dans la note)
**Description :** Table simple dans la note, indépendante des carnets, avec colonnes définissables par l'utilisateur.
**Avantages :** Pas de dépendance à Structured Views.
**Risques :**
- Crée exactement le second système de données parallèle qu'on veut éviter.
- Ne répond pas aux personas (Chloé et Mehdi veulent leurs vraies données).
- Rejectée explicitement par le fondateur.
**Verdict :** Hors scope. Ne pas implémenter.
### Option D — Supprimer `/database`
**Description :** Retirer complètement la commande slash et l'option du menu.
**Avantages :** Simple, propre.
**Risques :**
- Perd une surface UX qui a du sens (une fois bien connectée).
- L'annonce "database inline" est une attente utilisateur légitime.
**Verdict :** Fallback si l'Option A prend trop de temps — mais l'Option A est faisable en taille M.
---
## 4. User Story & Critères d'Acceptation (Given/When/Then)
### US-4 (Nouvelle) : Vue Structurée de Carnet Inline dans l'Éditeur
**En tant que** rédacteur dans un carnet structuré,
**Je veux** insérer une vue en lecture de mon tableau de notes directement dans le corps de ma note,
**Afin de** voir mes données structurées en contexte, sans quitter l'éditeur ni naviguer vers le carnet.
---
#### Scénario 1 — Insertion dans un carnet structuré
**Given** que ma note est dans un carnet qui a un schéma (`NotebookSchema` défini)
**When** je tape `/database` dans l'éditeur
**Then** un bloc `structuredViewBlock` est inséré, affichant la vue Table du carnet (colonnes = propriétés du schéma, lignes = notes du carnet)
**And** aucune donnée de démo n'est insérée
**And** l'utilisateur peut modifier les valeurs simples directement dans le bloc (checkbox, select, texte) — les changements se sauvegardent via `PATCH /api/notes/:id/properties`
---
#### Scénario 2 — Carnet sans schéma
**Given** que ma note est dans un carnet sans `NotebookSchema`
**When** j'insère un bloc `/database`
**Then** le bloc affiche un message contextuel : *"Ce carnet n'a pas encore de vue structurée. Configurez-en une depuis l'en-tête du carnet."* avec un lien vers le wizard
**And** aucune donnée n'est chargée, aucun crash
---
#### Scénario 3 — Note sans carnet
**Given** que ma note n'appartient à aucun carnet (notebookId absent)
**When** j'insère un bloc `/database`
**Then** le bloc affiche : *"Ce bloc nécessite un carnet. Déplacez cette note dans un carnet pour l'utiliser."*
---
#### Scénario 4 — Migration des blocs legacy
**Given** qu'une note contient un ancien nœud `data-database-block="true"` (auteurs/œuvres)
**When** la note est ouverte
**Then** le bloc obsolète est silencieusement retiré (ou affiché comme placeholder "bloc obsolète")
**And** le reste du contenu de la note est intact
**And** aucun crash ne se produit
---
#### Scénario 5 — RTL / locale persane
**Given** que la langue de l'app est `fa` (persan, RTL)
**When** le bloc est affiché
**Then** le wrapper du bloc a `dir="auto"`, le tableau s'aligne correctement en RTL
**And** les libellés du bloc sont traduits en persan (via `useLanguage()`)
---
#### Scénario 6 — Bascule de vue (Table → Galerie)
**Given** que le bloc est inséré dans un carnet avec `illustrationSvg` ou couleur
**When** l'utilisateur clique sur le sélecteur de vue dans le bloc
**Then** il peut basculer entre `Table` et `Galerie`
**And** l'attribut `displayMode` du nœud TipTap est mis à jour
**And** la vue se met à jour sans re-insertion du bloc
---
## 5. Out of Scope Explicite
| Fonctionnalité | Raison |
|----------------|--------|
| Vue Kanban inline | Drag-and-drop dans un NodeView TipTap = mauvaise UX, reporté en v2 |
| Sélection d'un carnet différent de la note courante | Scope trop large → v2 |
| Formules / rollups calculés | Hors scope Structured Views v1 |
| Relations multi-carnets | Hors scope — nécessite migration Prisma dédiée |
| Filtre personnalisé via UI dans le bloc | v2 — le bloc affiche tout le carnet en v1 |
| Pagination dans le bloc | v2 si le carnet dépasse 50 notes |
| Export PDF/CSV depuis le bloc | Fonctionnalité séparée |
---
## 6. Composants Prototype à Référencer
| Composant prototype | Usage | Note |
|--------------------|-------|------|
| `architectural-grid/``NotesStructuredTable` pattern | Colonnes et cellules — **référence design** | Utiliser le composant prod `notes-structured-table.tsx` |
| `architectural-grid/``NotesGalleryView` pattern | Vue galerie — **référence design** | Utiliser le composant prod `notes-gallery-view.tsx` |
| `architectural-grid1/ModernBlockNoteEditor.tsx` L1704+ | **NE PAS COPIER** — démo marketing Verne/Liu Cixin | Audit uniquement |
> ⚠️ Le prototype `architectural-grid1` est la référence de ce qu'il **ne faut pas** shipper. Le prototype `architectural-grid` (sans `1`) est la référence de design courant.
---
## 7. Modèle de Données
### 7.1 Nœud TipTap — Attributs (référence légère uniquement)
```typescript
// Extension TipTap — tiptap-structured-view-block-extension.tsx
Node.create({
name: 'structuredViewBlock',
group: 'block',
atom: true,
draggable: true,
addAttributes() {
return {
notebookId: {
default: null,
parseHTML: (el) => el.getAttribute('data-sv-notebook-id'),
renderHTML: (attrs) => attrs.notebookId
? { 'data-sv-notebook-id': attrs.notebookId }
: {},
},
displayMode: {
default: 'table',
parseHTML: (el) => el.getAttribute('data-sv-mode') || 'table',
renderHTML: (attrs) => ({ 'data-sv-mode': attrs.displayMode }),
},
filterJson: {
default: '{}',
parseHTML: (el) => el.getAttribute('data-sv-filter') || '{}',
renderHTML: (attrs) => ({ 'data-sv-filter': attrs.filterJson }),
},
}
},
parseHTML: () => [{ tag: 'div[data-structured-view-block]' }],
renderHTML: ({ HTMLAttributes }) =>
['div', mergeAttributes(HTMLAttributes, { 'data-structured-view-block': 'true' })],
addNodeView: () => ReactNodeViewRenderer(StructuredViewBlockEmbed),
})
```
### 7.2 Aucune migration Prisma requise
Le bloc réutilise le schéma Prisma existant :
- `NotebookSchema` / `NotebookProperty` → définition des colonnes
- `NoteProperty` → valeurs par note
- `Note` → lignes du tableau
Aucune nouvelle table. Aucun risque BDD.
### 7.3 Diagramme de relations
```mermaid
graph TD
A["structuredViewBlock node<br/>(TipTap attrs)"] -->|"notebookId"| B["GET /api/notebooks/:id/schema"]
B --> C["NotebookSchema<br/>(Prisma)"]
C --> D["NotebookProperty[]<br/>(colonnes)"]
A -->|"notebookId"| E["GET /api/notebooks/:id/notes<br/>(avec properties)"]
E --> F["Note[]<br/>(lignes)"]
F --> G["NoteProperty[]<br/>(valeurs)"]
D & G --> H["NotesStructuredTable<br/>(composant prod réutilisé)"]
H --> I["Rendu inline dans l'éditeur"]
```
---
## 8. Plan de Migration & Rollback du Code Actuel
### 8.1 Ordre de suppression (pour éviter les imports cassés)
1. **Supprimer** `memento-note/lib/editor/database-block-types.ts`
2. **Supprimer** `memento-note/components/database-block-editor.tsx`
3. **Supprimer** `memento-note/components/tiptap-database-block-extension.tsx`
4. **Modifier** `block-action-menu.tsx` — retirer import + option `database`
5. **Modifier** `rich-text-editor.tsx` — retirer import + slash entry + extension registration
6. **Créer** `tiptap-structured-view-block-extension.tsx` + `structured-view-block-embed.tsx`
7. **Modifier** `note-content-area.tsx` — passer `notebookId`
8. **Modifier** `locales/en.json` + `fr.json` — swap clés i18n
### 8.2 Gestion des notes existantes avec l'ancien bloc
Le nœud `databaseBlock` sera inconnu de TipTap après suppression de l'extension. Par défaut ProseMirror le drop silencieusement. Options :
- **Option simple (v1) :** Laisser ProseMirror supprimer le nœud inconnu au premier rendu — aucune action développeur.
- **Option propre (recommandée) :** Ajouter dans la nouvelle extension une règle `parseHTML` qui matche `div[data-database-block]` et le convertit en paragraphe `⚠️ Bloc base de données obsolète — ce contenu a été retiré.`
### 8.3 Rollback possible
Si le fondateur rejette l'Option A après implémentation :
- Les 3 fichiers supprimés sont dans git history — `git checkout HEAD~1 -- <fichier>` les restaure.
- La suppression de l'extension de `rich-text-editor.tsx` est une ligne — réversible en 2 minutes.
---
## 9. Risques Performance & Mitigations
| Risque | Probabilité | Impact | Mitigation |
|--------|-------------|--------|-----------|
| NodeView React lourd — re-render à chaque transaction TipTap | Haute | Haute | `shouldRerenderOnTransaction: false` sur l'éditeur (US-EDITOR-PERF) + `React.memo` sur le bloc embed + `trackNodeViewPosition: false` |
| SWR fetch bloque le rendu initial de la note | Moyenne | Moyenne | Suspense avec skeleton loader ; ne pas bloquer le rendu éditeur ; lazy-mount après 500ms |
| Note dans carnet avec 200+ notes — tableau trop long | Basse | Moyenne | Afficher les 20 premières notes avec `"Voir toutes les N notes dans le carnet"` CTA |
| RTL — cellules du tableau cassées | Basse | Haute | `dir="auto"` sur le wrapper ; tester avec locale `fa` avant merge |
---
## 10. i18n — Clés à Ajouter / Supprimer
### 10.1 Clés à ajouter (EN/FR minimum)
| Clé | EN | FR |
|-----|----|----|
| `structuredViewBlock.insertLabel` | Structured View | Vue structurée du carnet |
| `structuredViewBlock.insertDesc` | Embed your notebook's structured data | Intégrez les données structurées de votre carnet |
| `structuredViewBlock.noSchema` | This notebook has no structured view yet. Set one up from the notebook header. | Ce carnet n'a pas encore de vue structurée. Configurez-en une depuis l'en-tête du carnet. |
| `structuredViewBlock.noNotebook` | This block requires a notebook. Move this note to a notebook first. | Ce bloc nécessite un carnet. Déplacez cette note dans un carnet pour l'utiliser. |
| `structuredViewBlock.openInNotebook` | Open in notebook | Ouvrir dans le carnet |
| `structuredViewBlock.displayModeTable` | Table | Tableau |
| `structuredViewBlock.displayModeGallery` | Gallery | Galerie |
| `structuredViewBlock.loadError` | Failed to load structured data. | Impossible de charger les données structurées. |
| `structuredViewBlock.retry` | Retry | Réessayer |
| `structuredViewBlock.deprecatedBlock` | Outdated block removed. | Bloc obsolète retiré. |
> **Note :** Si l'utilisateur demande à compléter les 15 locales, ne remplir que les clés — laisser la traduction des 13 autres locales à l'outil de traduction externe (règle AGENTS.md).
### 10.2 Clés à supprimer (après vérification pas d'autre consommateur)
`databaseBlock.title`, `databaseBlock.viewTable`, `databaseBlock.viewCards`, `databaseBlock.hint`, `databaseBlock.colAuthor`, `databaseBlock.colWorks`, `databaseBlock.colRollup`, `databaseBlock.noLinkedWorks`, `databaseBlock.deleteShort`, `databaseBlock.addAuthor`, `databaseBlock.authorPlaceholder`, `databaseBlock.createAuthor`, `databaseBlock.worksBase`, `databaseBlock.storedCount`, `databaseBlock.addWork`, `databaseBlock.bookTitlePlaceholder`, `databaseBlock.selectAuthor`, `databaseBlock.tagPlaceholder`, `databaseBlock.coverPlaceholder`, `databaseBlock.insertWork`, `databaseBlock.deleteCard`, `databaseBlock.insertFailed`, `databaseBlock.defaultTag`
---
## 11. Checklist QA Manuelle
### 11.1 Français (LTR)
- [ ] Taper `/database` dans une note d'un carnet structuré → bloc s'insère avec les données réelles
- [ ] Taper `/database` → même résultat (rétrocompatibilité keyword)
- [ ] Taper `/database` dans une note sans carnet → message "nécessite un carnet"
- [ ] Taper `/database` dans une note d'un carnet sans schéma → callout wizard avec lien
- [ ] Ouvrir une note avec un ancien bloc `databaseBlock` → note s'ouvre, bloc absent ou placeholder, pas de crash
- [ ] Menu "Transformer en" → option "Vue structurée" présente, option "Base de données" (ancienne) absente
- [ ] Bascule Table ↔ Galerie dans le bloc → vue change, pas de réinsertion du bloc
- [ ] `npm run build` → 0 erreur, aucun import vers fichiers supprimés
### 11.2 Persan / RTL (fa)
- [ ] Changer la langue en `fa` → libellés du bloc en persan
- [ ] Le bloc wrapper est `dir="auto"` → tableau aligné à droite
- [ ] Cellules du tableau RTL lisibles (pas de texte coupé)
- [ ] Callout "no schema" en persan → texte lisible RTL
---
## 12. Estimation Effort
| Tâche | Taille |
|-------|--------|
| Supprimer 3 fichiers legacy | XS |
| Patcher `rich-text-editor.tsx` + `block-action-menu.tsx` | S |
| Patcher `note-content-area.tsx` (`notebookId` prop) | XS |
| Créer `tiptap-structured-view-block-extension.tsx` | S |
| Créer `structured-view-block-embed.tsx` (SWR + états + RTL) | M |
| i18n EN + FR | XS |
| QA manuelle FR + fa | S |
| **Total estimé** | **M** (~12 jours dev) |
---
## 13. Décisions Produit Actées
### Édition inline — ACTIVÉE en v1
L'utilisateur peut modifier les valeurs simples directement dans le bloc (checkbox, select, texte court). Les changements se sauvegardent via `PATCH /api/notes/:id/properties` avec mise à jour optimiste. C'est la meilleure expérience utilisateur — un bloc en lecture seule n'aurait aucun intérêt.
### Kanban inline — REPORTÉ en v2
Table + Galerie uniquement en v1. Le drag-and-drop dans un NodeView TipTap crée de mauvaises interactions. Le Kanban s'utilisera depuis le carnet comme aujourd'hui.
---
## Annexe — Diff Proposé pour `docs/story-nextgen-editor.md`
Remplacer la section `### US-4: Bloc de Base de Données Relationnelle Inline` (lignes 7185) par :
```markdown
### US-4: Vue Structurée de Carnet Inline *(Redesign — voir `docs/story-nextgen-editor-us4-redesign.md`)*
> ⚠️ **DEPRECATED** — La spécification précédente (bloc "Auteurs & Œuvres") est rejetée.
> Voir [`docs/story-nextgen-editor-us4-redesign.md`](./story-nextgen-editor-us4-redesign.md) pour la nouvelle spec.
**En tant que** rédacteur dans un carnet structuré,
**Je veux** insérer une vue en lecture de mon tableau de notes directement dans le corps de ma note,
**Afin de** voir mes données structurées en contexte, sans quitter l'éditeur.
*(Critères d'acceptation détaillés dans le fichier redesign ci-dessus.)*
```
Et remplacer la section `### 1. Structure du Nœud de Base de Données Tiptap` + `### 2.` + `### 3.` dans les Spécifications Techniques (lignes 90109) par :
```markdown
### 1. Structure du Nœud `structuredViewBlock` (TipTap)
Extension TipTap `StructuredViewBlockExtension` dans `tiptap-structured-view-block-extension.tsx` :
- Attributs : `notebookId` (string), `displayMode` ('table'|'gallery'), `filterJson` (string JSON)
- ReactNodeViewRenderer → `structured-view-block-embed.tsx`
### 2. Suppression du code legacy
- Supprimer : `tiptap-database-block-extension.tsx`, `database-block-editor.tsx`, `lib/editor/database-block-types.ts`
- Modifier : `rich-text-editor.tsx`, `block-action-menu.tsx`, `locales/*.json`
- Voir plan complet dans `docs/story-nextgen-editor-us4-redesign.md` §8.
```
---
## Annexe — Diff Proposé pour `docs/user-stories.md`
### Dans le tableau de bord (ligne 23)
```diff
-| **US-NEXTGEN-EDITOR** | Éditeur Next-Gen : Drag Handle + Menu Bloc + DB Inline + Smart Paste | 🚧 **PLANIFIÉ** | Voir `docs/story-nextgen-editor.md` |
+| **US-NEXTGEN-EDITOR** | Éditeur Next-Gen : Drag Handle + Menu Bloc + Vue Structurée Inline + Smart Paste | 🚧 **PLANIFIÉ** | Voir `docs/story-nextgen-editor.md` + `docs/story-nextgen-editor-us4-redesign.md` |
```
### Dans la section US-NEXTGEN-EDITOR (US-4, ligne 622626)
```diff
-### US-4 : Bloc de Base de Données Relationnelle Inline
-- Slash `/database` → insère un React NodeView
-- Vues Tableau / Fiches avec Rollup dynamique
-- Modèle relationnel local (auteurs/livres par défaut, ou lié au carnet)
+### US-4 : Vue Structurée de Carnet Inline *(Redesign)*
+> Spec complète : [`docs/story-nextgen-editor-us4-redesign.md`](./story-nextgen-editor-us4-redesign.md)
+- Slash `/database` (+ keywords `db`, `tableau`, `structured`) → insère un `structuredViewBlock`
+- Affiche Table ou Galerie du carnet courant via l'API Structured Views existante
+- Bloc stocke uniquement `notebookId` + `displayMode` (pas de données en attrs)
+- Graceful fallback si carnet sans schéma ou note sans carnet
+- Supprime le code legacy `tiptap-database-block-extension.tsx` (Verne/Liu Cixin)
+- **Dépend de :** US-STRUCTURED-VIEWS ✅ (livré)
```
### Dans la liste de fichiers (ligne 627631)
```diff
-### Fichiers
-- `[NEW]` `tiptap-drag-handle-plugin.ts` — Plugin ProseMirror pur
-- `[NEW]` `tiptap-database-block-extension.tsx` — NodeView React
-- `[MODIFY]` `rich-text-editor.tsx` — Intégration drag handle + DB + paste intercept
-- `[MODIFY]` `globals.css` — Gutter, poignée, glassmorphic dropdowns
+### Fichiers
+- `[NEW]` `tiptap-drag-handle-plugin.ts` — Plugin ProseMirror pur (US-1, inchangé)
+- `[NEW]` `tiptap-structured-view-block-extension.tsx` — NodeView Vue Structurée (remplace DB)
+- `[NEW]` `structured-view-block-embed.tsx` — Composant embed avec SWR + states
+- `[DELETE]` `tiptap-database-block-extension.tsx` — Bloc legacy auteurs/œuvres rejeté
+- `[DELETE]` `database-block-editor.tsx` — UI legacy rejetée
+- `[DELETE]` `lib/editor/database-block-types.ts` — Types legacy rejetés
+- `[MODIFY]` `rich-text-editor.tsx` — Intégration drag handle + Vue Structurée + paste intercept
+- `[MODIFY]` `note-content-area.tsx` — Passer `notebookId` à l'éditeur
+- `[MODIFY]` `block-action-menu.tsx` — Remplacer option "Database" par "Vue structurée"
+- `[MODIFY]` `globals.css` — Gutter, poignée, glassmorphic dropdowns
```