From 00d344d2a05e7d5d7cfb2b7585cc28bd235a1a23 Mon Sep 17 00:00:00 2001 From: streaper2 Date: Wed, 25 Feb 2026 10:00:16 +0100 Subject: [PATCH] ajout de l'option base64 pour le header --- src/App.tsx | 229 +++++++++++++++++++++++++++------------------------- 1 file changed, 118 insertions(+), 111 deletions(-) diff --git a/src/App.tsx b/src/App.tsx index fd53f4a..a2744ba 100644 --- a/src/App.tsx +++ b/src/App.tsx @@ -1,4 +1,4 @@ -import { useState, useRef, useEffect } from 'react'; +import React, { useState, useRef, useEffect } from 'react'; import { Download, Type, Image as ImageIcon, Layout, MousePointer2, Trash2, Code, AlignLeft, AlignCenter, AlignRight, Loader2, Link as LinkIcon, Smile, Minus, Heading, Bold, Italic, Underline, List, ListOrdered, Upload, Save, RotateCcw, FileX } from 'lucide-react'; // --- CONFIGURATION & CONSTANTES --- @@ -22,19 +22,17 @@ interface Block { } // --- COMPOSANT TOOLTIP (AIDE AU SURVOL) --- -const Tooltip = ({ text, children }: { text: string; children: React.ReactNode }) => { +const Tooltip = ({ text, children, className = "w-full" }: { text: string; children: React.ReactNode; className?: string }) => { const [show, setShow] = useState(false); const timerRef = useRef | null>(null); const handleMouseEnter = () => { - // Démarre le timer de 2 secondes timerRef.current = setTimeout(() => { setShow(true); }, 2000); }; const handleMouseLeave = () => { - // Annule le timer si la souris part avant les 2 secondes if (timerRef.current) { clearTimeout(timerRef.current); timerRef.current = null; @@ -43,12 +41,11 @@ const Tooltip = ({ text, children }: { text: string; children: React.ReactNode } }; return ( -
+
{children} {show && (
{text} - {/* Petite flèche vers le bas */}
)} @@ -65,6 +62,8 @@ const BLOCK_TEMPLATES: Record = { subtitle: 'AUTOMNE 2025', bgColor: '#eeeeee', backgroundImage: '', + url: '', // Lien de redirection + exportAsImage: true, // Nouveau: Détermine si l'en-tête est converti en Data Base64 textColor: PURPLE_COLOR, subtitleColor: ORANGE_COLOR, padding: '30', @@ -96,7 +95,6 @@ const BLOCK_TEMPLATES: Record = { text: { id: null, type: 'text', - // On utilise du HTML par défaut maintenant pour le RTE content: '

Les 10 et 18 septembre ainsi que le 2 octobre ont rappelé que la colère ne s’était pas éteinte pendant l’été.

Au-delà des chiffres de grève, la dégradation des conditions de travail des personnels de la DGFiP s’accentue.

', bgColor: '#ffffff', textColor: '#4a4a4a', @@ -145,6 +143,7 @@ const BLOCK_TEMPLATES: Record = { id: null, type: 'image', src: 'https://via.placeholder.com/600x300', + url: '', // Ajout possible d'un lien alt: 'Image de description', bgColor: '#ffffff', padding: '0', @@ -168,7 +167,7 @@ const BLOCK_TEMPLATES: Record = { btn2Url: 'https://adherer.solidairesfinancespubliques.org/', btn2Color: '#22c55e', logoSrc: 'https://solidairesfinancespubliques.org/images/logo/pastille-122.png', - logoWidth: '80', // Nouvelle propriété pour la taille du logo + logoWidth: '80', slogan: 'Solidaires Finances Publiques est la première force syndicale de la DGFiP', address: 'Solidaires Finances Publiques\nSection DG et PR\n\n139 rue de Bercy\nBâtiment VAUBAN pièce 0060 Sud 1\n75012 PARIS\n\nTél. 01 53 18 60 36 - 01 53 18 60 14 - 01 53 18 41 47\n\nhttps://sections.solidairesfinancespubliques.info/b38/\nsolidairesfinancespubliques.servicescentraux@dgfip.finances.gouv.fr', legalText: 'Vous êtes destinataire de ce message d\'origine syndicale conformément aux dispositions de l\'article 8 de l\'arrêté du 4 novembre 2014 relatif aux conditions générales d\'utilisation par les organisations syndicales. Vous pouvez vous désabonner en répondant "Désabonnement".', @@ -181,7 +180,6 @@ const BLOCK_TEMPLATES: Record = { const SimpleRTE = ({ value, onChange }: { value: string, onChange: (val: string) => void }) => { const editorRef = useRef(null); - // Fonction pour exécuter les commandes d'édition const execCmd = (command: string, value: string | undefined = undefined) => { document.execCommand(command, false, value); if (editorRef.current) { @@ -189,11 +187,8 @@ const SimpleRTE = ({ value, onChange }: { value: string, onChange: (val: string) } }; - // Synchronisation initiale et lors des changements externes importants useEffect(() => { if (editorRef.current && editorRef.current.innerHTML !== value) { - // Petite protection pour ne pas perdre le focus/curseur si le contenu est similaire - // Dans une vraie app prod, on utiliserait une lib comme Slate ou TipTap if (document.activeElement !== editorRef.current) { editorRef.current.innerHTML = value; } @@ -202,7 +197,6 @@ const SimpleRTE = ({ value, onChange }: { value: string, onChange: (val: string) return (
- {/* Barre d'outils */}
execCmd('bold')} icon={} title="Mettre en gras" /> execCmd('italic')} icon={} title="Mettre en italique" /> @@ -212,7 +206,6 @@ const SimpleRTE = ({ value, onChange }: { value: string, onChange: (val: string) execCmd('insertOrderedList')} icon={} title="Liste numérotée" />
- {/* Zone d'édition */}
void, icon: any, title: string }) => ( - +
- - - - @@ -714,31 +685,31 @@ p { margin-top: 0; margin-bottom: 10px; }

Ajouter un bloc

- } label="En-tête" onClick={() => addBlock('header')} disabled={hasHeader} /> + } label="En-tête" onClick={() => addBlock('header')} disabled={hasHeader} isActive={selectedBlock?.type === 'header'} /> - } label="Séparateur" onClick={() => addBlock('divider')} /> + } label="Séparateur" onClick={() => addBlock('divider')} isActive={selectedBlock?.type === 'divider'} /> - } label="Titre" onClick={() => addBlock('title')} /> + } label="Titre" onClick={() => addBlock('title')} isActive={selectedBlock?.type === 'title'} /> - } label="Texte" onClick={() => addBlock('text')} /> + } label="Texte" onClick={() => addBlock('text')} isActive={selectedBlock?.type === 'text'} /> - } label="Lien Texte" onClick={() => addBlock('link')} /> + } label="Lien Texte" onClick={() => addBlock('link')} isActive={selectedBlock?.type === 'link'} /> - } label="Bouton" onClick={() => addBlock('button')} /> + } label="Bouton" onClick={() => addBlock('button')} isActive={selectedBlock?.type === 'button'} /> - } label="Image" onClick={() => addBlock('image')} /> + } label="Image" onClick={() => addBlock('image')} isActive={selectedBlock?.type === 'image'} /> - } label="Espace" onClick={() => addBlock('spacer')} /> + } label="Espace" onClick={() => addBlock('spacer')} isActive={selectedBlock?.type === 'spacer'} /> - } label="Pied" onClick={() => addBlock('footer')} disabled={hasFooter} /> + } label="Pied" onClick={() => addBlock('footer')} disabled={hasFooter} isActive={selectedBlock?.type === 'footer'} />
@@ -801,12 +772,15 @@ p { margin-top: 0; margin-bottom: 10px; } ); } -function BlockButton({ icon, label, onClick, disabled }: { icon: any, label: string, onClick: () => void, disabled?: boolean }) { +function BlockButton({ icon, label, onClick, disabled, isActive }: { icon: any, label: string, onClick: () => void, disabled?: boolean, isActive?: boolean }) { return (