Phase 2 : mind map bilaterale, relations, templates et Markdown
Format .mmap v4 : `node.side` (cote d'une branche de niveau 1) et `MindMap.relations` (relations secondaires). Migration v3 -> v4 sans perte, les cartes v1/v2/v3 restent ouvrables telles quelles. Une relation est une connexion purement visuelle : elle ne touche jamais parentId, order, les enfants, le repli ni l'auto-layout. `withEdges()` continue de deriver les liens de parentId et se contente de retirer les relations dont une extremite a disparu. Mind map bilaterale : repartition gloutonne et deterministe des branches selon la taille des sous-arbres, heritage du cote par sous-arbre, deux passes dagre recalees sur la racine. Choisir une disposition ne deplace plus la carte : seul Reorganiser applique. Ajoute aussi une galerie de huit modeles locaux, l'import Markdown (fichier ou texte, nouvelle carte ou sous-arbre) reutilisant l'analyseur d'outline existant, et l'export Markdown de la hierarchie. Corrige un bug de rendu : React Flow ne remesure pas les poignees quand elles changent de cote, ce qui faisait disparaitre les liens concernes. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
@@ -28,6 +28,7 @@ import {
|
||||
} from '@/features/editor/nodeStyleResolver';
|
||||
import { BUILTIN_ICONS, BUILTIN_ICON_IDS, EMOJI_ICONS } from '@/features/editor/nodeIcons';
|
||||
import { PanelSection } from '@/features/editor/panel/PanelSection';
|
||||
import { RelationProperties } from '@/features/editor/RelationProperties';
|
||||
import {
|
||||
ColorField,
|
||||
NumberField,
|
||||
@@ -90,6 +91,7 @@ const ICON_SIZES = [16, 20, 24, 32];
|
||||
export function PropertiesPanel() {
|
||||
const map = useEditorStore((state) => state.map);
|
||||
const selectedIds = useEditorStore((state) => state.selectedNodeIds);
|
||||
const selectedRelationId = useEditorStore((state) => state.selectedRelationId);
|
||||
|
||||
const updateNode = useEditorStore((state) => state.updateNode);
|
||||
const updateNodeText = useEditorStore((state) => state.updateNodeText);
|
||||
@@ -135,6 +137,8 @@ export function PropertiesPanel() {
|
||||
const palette = paletteForDepth(theme, referenceDepth);
|
||||
const reference = single ? resolveNodeAppearance(single, referenceDepth, theme) : undefined;
|
||||
|
||||
const relation = map?.relations.find((candidate) => candidate.id === selectedRelationId);
|
||||
|
||||
const header = (
|
||||
<header className="flex items-center justify-between gap-2 border-b border-zinc-100 px-4 py-3 dark:border-zinc-800">
|
||||
<h2 className="text-sm font-semibold text-zinc-900 dark:text-zinc-50">
|
||||
@@ -153,6 +157,20 @@ export function PropertiesPanel() {
|
||||
</header>
|
||||
);
|
||||
|
||||
// Une relation selectionnee prend la place du panneau de noeud : les deux
|
||||
// selections s'excluent, le panneau ne montre donc jamais les deux a la fois.
|
||||
if (nodes.length === 0 && relation) {
|
||||
return (
|
||||
<aside
|
||||
className="no-print flex h-full w-72 shrink-0 flex-col overflow-y-auto border-l border-zinc-200 bg-white dark:border-zinc-800 dark:bg-zinc-900"
|
||||
aria-label="Panneau de proprietes"
|
||||
>
|
||||
{header}
|
||||
<RelationProperties relationId={relation.id} />
|
||||
</aside>
|
||||
);
|
||||
}
|
||||
|
||||
if (nodes.length === 0) {
|
||||
return (
|
||||
<aside
|
||||
@@ -162,7 +180,8 @@ export function PropertiesPanel() {
|
||||
{header}
|
||||
<p className="px-4 py-6 text-sm leading-relaxed text-zinc-500 dark:text-zinc-400">
|
||||
Selectionnez un noeud pour modifier son contenu, sa typographie, son apparence et sa mise
|
||||
en page. Selectionnez-en plusieurs pour appliquer un reglage a tout le lot.
|
||||
en page. Selectionnez-en plusieurs pour appliquer un reglage a tout le lot. Cliquez une
|
||||
relation pour en modifier le libelle et le trace.
|
||||
</p>
|
||||
</aside>
|
||||
);
|
||||
|
||||
Reference in New Issue
Block a user