@qwanyx/ai-editor 1.1.0 → 1.2.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,20 +1,23 @@
1
- import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
- import { useRef, useState, useCallback, useEffect } from 'react';
3
- import { useAIEditor } from '../hooks/useAIEditor';
4
- import { useSelection } from '../hooks/useSelection';
5
- import { AIToolbar } from './AIToolbar';
6
- import { PromptModal } from './PromptModal';
7
- import { MarkdownPreview } from './MarkdownPreview';
8
- export function AIEditor({ initialContent = '', onChange, onAIRequest, placeholder = 'Commencez à écrire...', className = '', minHeight = '300px' }) {
9
- const previewRef = useRef(null);
10
- const textareaRef = useRef(null);
11
- const [state, actions] = useAIEditor(initialContent);
12
- const { selection, clearSelection } = useSelection(previewRef);
13
- const [isEditMode, setIsEditMode] = useState(true); // Start in edit mode
14
- const [isPromptModalOpen, setIsPromptModalOpen] = useState(false);
15
- const [isLoading, setIsLoading] = useState(false);
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.AIEditor = AIEditor;
4
+ const jsx_runtime_1 = require("react/jsx-runtime");
5
+ const react_1 = require("react");
6
+ const useAIEditor_1 = require("../hooks/useAIEditor");
7
+ const useSelection_1 = require("../hooks/useSelection");
8
+ const AIToolbar_1 = require("./AIToolbar");
9
+ const PromptModal_1 = require("./PromptModal");
10
+ const MarkdownPreview_1 = require("./MarkdownPreview");
11
+ function AIEditor({ initialContent = '', onChange, onAIRequest, placeholder = 'Commencez à écrire...', className = '', minHeight = '300px' }) {
12
+ const previewRef = (0, react_1.useRef)(null);
13
+ const textareaRef = (0, react_1.useRef)(null);
14
+ const [state, actions] = (0, useAIEditor_1.useAIEditor)(initialContent);
15
+ const { selection, clearSelection } = (0, useSelection_1.useSelection)(previewRef);
16
+ const [isEditMode, setIsEditMode] = (0, react_1.useState)(true); // Start in edit mode
17
+ const [isPromptModalOpen, setIsPromptModalOpen] = (0, react_1.useState)(false);
18
+ const [isLoading, setIsLoading] = (0, react_1.useState)(false);
16
19
  // Helper to wrap selected text with markdown syntax
17
- const wrapSelection = useCallback((before, after) => {
20
+ const wrapSelection = (0, react_1.useCallback)((before, after) => {
18
21
  const textarea = textareaRef.current;
19
22
  if (!textarea)
20
23
  return;
@@ -32,7 +35,7 @@ export function AIEditor({ initialContent = '', onChange, onAIRequest, placehold
32
35
  }, 0);
33
36
  }, [state.content, actions]);
34
37
  // Helper to insert text at line start
35
- const insertAtLineStart = useCallback((prefix) => {
38
+ const insertAtLineStart = (0, react_1.useCallback)((prefix) => {
36
39
  const textarea = textareaRef.current;
37
40
  if (!textarea)
38
41
  return;
@@ -51,16 +54,16 @@ export function AIEditor({ initialContent = '', onChange, onAIRequest, placehold
51
54
  }, 0);
52
55
  }, [state.content, actions]);
53
56
  // Formatting handlers
54
- const handleBold = useCallback(() => wrapSelection('**', '**'), [wrapSelection]);
55
- const handleItalic = useCallback(() => wrapSelection('*', '*'), [wrapSelection]);
56
- const handleHeading = useCallback((level) => {
57
+ const handleBold = (0, react_1.useCallback)(() => wrapSelection('**', '**'), [wrapSelection]);
58
+ const handleItalic = (0, react_1.useCallback)(() => wrapSelection('*', '*'), [wrapSelection]);
59
+ const handleHeading = (0, react_1.useCallback)((level) => {
57
60
  const prefix = '#'.repeat(level) + ' ';
58
61
  insertAtLineStart(prefix);
59
62
  }, [insertAtLineStart]);
60
- const handleBulletList = useCallback(() => insertAtLineStart('- '), [insertAtLineStart]);
61
- const handleNumberedList = useCallback(() => insertAtLineStart('1. '), [insertAtLineStart]);
62
- const handleQuote = useCallback(() => insertAtLineStart('> '), [insertAtLineStart]);
63
- const handleLink = useCallback(() => {
63
+ const handleBulletList = (0, react_1.useCallback)(() => insertAtLineStart('- '), [insertAtLineStart]);
64
+ const handleNumberedList = (0, react_1.useCallback)(() => insertAtLineStart('1. '), [insertAtLineStart]);
65
+ const handleQuote = (0, react_1.useCallback)(() => insertAtLineStart('> '), [insertAtLineStart]);
66
+ const handleLink = (0, react_1.useCallback)(() => {
64
67
  const textarea = textareaRef.current;
65
68
  if (!textarea)
66
69
  return;
@@ -78,11 +81,11 @@ export function AIEditor({ initialContent = '', onChange, onAIRequest, placehold
78
81
  }, 0);
79
82
  }, [state.content, actions]);
80
83
  // Notify parent of changes
81
- useEffect(() => {
84
+ (0, react_1.useEffect)(() => {
82
85
  onChange?.(state.content);
83
86
  }, [state.content, onChange]);
84
87
  // Keyboard shortcuts
85
- useEffect(() => {
88
+ (0, react_1.useEffect)(() => {
86
89
  const handleKeyDown = (e) => {
87
90
  if ((e.ctrlKey || e.metaKey) && e.key === 'z') {
88
91
  if (e.shiftKey) {
@@ -101,7 +104,7 @@ export function AIEditor({ initialContent = '', onChange, onAIRequest, placehold
101
104
  window.addEventListener('keydown', handleKeyDown);
102
105
  return () => window.removeEventListener('keydown', handleKeyDown);
103
106
  }, [actions]);
104
- const handleAIAction = useCallback(async (action, customPrompt) => {
107
+ const handleAIAction = (0, react_1.useCallback)(async (action, customPrompt) => {
105
108
  if (!onAIRequest) {
106
109
  console.warn('AIEditor: onAIRequest handler not provided');
107
110
  return;
@@ -134,21 +137,21 @@ export function AIEditor({ initialContent = '', onChange, onAIRequest, placehold
134
137
  setIsPromptModalOpen(false);
135
138
  }
136
139
  }, [state.content, selection, onAIRequest, actions, clearSelection]);
137
- const handleRewrite = useCallback(() => {
140
+ const handleRewrite = (0, react_1.useCallback)(() => {
138
141
  handleAIAction('rewrite');
139
142
  }, [handleAIAction]);
140
- const handleProofread = useCallback(() => {
143
+ const handleProofread = (0, react_1.useCallback)(() => {
141
144
  handleAIAction('proofread');
142
145
  }, [handleAIAction]);
143
- const handleCustomPrompt = useCallback(() => {
146
+ const handleCustomPrompt = (0, react_1.useCallback)(() => {
144
147
  setIsPromptModalOpen(true);
145
148
  }, []);
146
- const handlePromptSubmit = useCallback((prompt) => {
149
+ const handlePromptSubmit = (0, react_1.useCallback)((prompt) => {
147
150
  handleAIAction('custom', prompt);
148
151
  }, [handleAIAction]);
149
- return (_jsxs("div", { className: `border border-gray-200 rounded-lg overflow-hidden ${className}`, children: [_jsx(AIToolbar, { onRewrite: handleRewrite, onProofread: handleProofread, onCustomPrompt: handleCustomPrompt, onUndo: actions.undo, onRedo: actions.redo, canUndo: actions.canUndo, canRedo: actions.canRedo, hasSelection: !!selection, isLoading: isLoading, isEditMode: isEditMode, onToggleMode: () => setIsEditMode(!isEditMode), onBold: handleBold, onItalic: handleItalic, onHeading: handleHeading, onBulletList: handleBulletList, onNumberedList: handleNumberedList, onLink: handleLink, onQuote: handleQuote }), _jsxs("div", { className: "relative", style: { minHeight }, children: [isEditMode ? (
152
+ return ((0, jsx_runtime_1.jsxs)("div", { className: `border border-gray-200 rounded-lg overflow-hidden ${className}`, children: [(0, jsx_runtime_1.jsx)(AIToolbar_1.AIToolbar, { onRewrite: handleRewrite, onProofread: handleProofread, onCustomPrompt: handleCustomPrompt, onUndo: actions.undo, onRedo: actions.redo, canUndo: actions.canUndo, canRedo: actions.canRedo, hasSelection: !!selection, isLoading: isLoading, isEditMode: isEditMode, onToggleMode: () => setIsEditMode(!isEditMode), onBold: handleBold, onItalic: handleItalic, onHeading: handleHeading, onBulletList: handleBulletList, onNumberedList: handleNumberedList, onLink: handleLink, onQuote: handleQuote }), (0, jsx_runtime_1.jsxs)("div", { className: "relative", style: { minHeight }, children: [isEditMode ? (
150
153
  // Edit mode - raw markdown
151
- _jsx("textarea", { ref: textareaRef, value: state.content, onChange: (e) => actions.setContent(e.target.value), className: "w-full h-full p-4 font-mono text-sm resize-none border-0 focus:ring-0 focus:outline-none text-gray-900", style: { minHeight }, placeholder: placeholder })) : (
154
+ (0, jsx_runtime_1.jsx)("textarea", { ref: textareaRef, value: state.content, onChange: (e) => actions.setContent(e.target.value), className: "w-full h-full p-4 font-mono text-sm resize-none border-0 focus:ring-0 focus:outline-none text-gray-900", style: { minHeight }, placeholder: placeholder })) : (
152
155
  // Preview mode - rendered markdown with selection
153
- _jsx("div", { className: "p-4 overflow-auto", style: { minHeight }, children: state.content ? (_jsx(MarkdownPreview, { ref: previewRef, content: state.content, className: "cursor-text" })) : (_jsx("p", { className: "text-gray-400 italic", children: placeholder })) })), isLoading && (_jsx("div", { className: "absolute inset-0 bg-white/80 flex items-center justify-center", children: _jsxs("div", { className: "flex items-center gap-2 text-blue-600", children: [_jsx("span", { className: "material-icons animate-spin", children: "sync" }), _jsx("span", { children: "L'IA travaille..." })] }) }))] }), _jsx(PromptModal, { isOpen: isPromptModalOpen, onClose: () => setIsPromptModalOpen(false), onSubmit: handlePromptSubmit, selectedText: selection?.text, isLoading: isLoading })] }));
156
+ (0, jsx_runtime_1.jsx)("div", { className: "p-4 overflow-auto", style: { minHeight }, children: state.content ? ((0, jsx_runtime_1.jsx)(MarkdownPreview_1.MarkdownPreview, { ref: previewRef, content: state.content, className: "cursor-text" })) : ((0, jsx_runtime_1.jsx)("p", { className: "text-gray-400 italic", children: placeholder })) })), isLoading && ((0, jsx_runtime_1.jsx)("div", { className: "absolute inset-0 bg-white/80 flex items-center justify-center", children: (0, jsx_runtime_1.jsxs)("div", { className: "flex items-center gap-2 text-blue-600", children: [(0, jsx_runtime_1.jsx)("span", { className: "material-icons animate-spin", children: "sync" }), (0, jsx_runtime_1.jsx)("span", { children: "L'IA travaille..." })] }) }))] }), (0, jsx_runtime_1.jsx)(PromptModal_1.PromptModal, { isOpen: isPromptModalOpen, onClose: () => setIsPromptModalOpen(false), onSubmit: handlePromptSubmit, selectedText: selection?.text, isLoading: isLoading })] }));
154
157
  }
@@ -1,10 +1,16 @@
1
- import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
2
- import React from 'react';
3
- export function AIToolbar({ onRewrite, onProofread, onCustomPrompt, onUndo, onRedo, canUndo, canRedo, hasSelection, isLoading, isEditMode, onToggleMode, onBold, onItalic, onHeading, onBulletList, onNumberedList, onLink, onQuote }) {
4
- const [showHeadingMenu, setShowHeadingMenu] = React.useState(false);
5
- return (_jsxs("div", { className: "flex flex-wrap items-center gap-1 p-2 bg-gray-50 border-b border-gray-200 rounded-t-lg", children: [_jsxs("div", { className: "flex items-center bg-gray-200 rounded-lg p-0.5", children: [_jsx("button", { onClick: onToggleMode, className: `px-2 py-1 text-sm rounded-md transition-colors ${!isEditMode
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.AIToolbar = AIToolbar;
7
+ const jsx_runtime_1 = require("react/jsx-runtime");
8
+ const react_1 = __importDefault(require("react"));
9
+ function AIToolbar({ onRewrite, onProofread, onCustomPrompt, onUndo, onRedo, canUndo, canRedo, hasSelection, isLoading, isEditMode, onToggleMode, onBold, onItalic, onHeading, onBulletList, onNumberedList, onLink, onQuote }) {
10
+ const [showHeadingMenu, setShowHeadingMenu] = react_1.default.useState(false);
11
+ return ((0, jsx_runtime_1.jsxs)("div", { className: "flex flex-wrap items-center gap-1 p-2 bg-gray-50 border-b border-gray-200 rounded-t-lg", children: [(0, jsx_runtime_1.jsxs)("div", { className: "flex items-center bg-gray-200 rounded-lg p-0.5", children: [(0, jsx_runtime_1.jsx)("button", { onClick: onToggleMode, className: `px-2 py-1 text-sm rounded-md transition-colors ${!isEditMode
6
12
  ? 'bg-white text-gray-900 shadow-sm'
7
- : 'text-gray-600 hover:text-gray-900'}`, title: "Mode aper\u00E7u", children: _jsx("span", { className: "material-icons text-base", children: "visibility" }) }), _jsx("button", { onClick: onToggleMode, className: `px-2 py-1 text-sm rounded-md transition-colors ${isEditMode
13
+ : 'text-gray-600 hover:text-gray-900'}`, title: "Mode aper\u00E7u", children: (0, jsx_runtime_1.jsx)("span", { className: "material-icons text-base", children: "visibility" }) }), (0, jsx_runtime_1.jsx)("button", { onClick: onToggleMode, className: `px-2 py-1 text-sm rounded-md transition-colors ${isEditMode
8
14
  ? 'bg-white text-gray-900 shadow-sm'
9
- : 'text-gray-600 hover:text-gray-900'}`, title: "Mode \u00E9dition", children: _jsx("span", { className: "material-icons text-base", children: "edit" }) })] }), _jsx("div", { className: "w-px h-6 bg-gray-300 mx-1" }), isEditMode && (_jsxs(_Fragment, { children: [_jsx("button", { onClick: onBold, className: "p-1.5 text-gray-600 hover:text-gray-900 hover:bg-gray-200 rounded transition-colors", title: "Gras (Ctrl+B)", children: _jsx("span", { className: "material-icons text-lg", children: "format_bold" }) }), _jsx("button", { onClick: onItalic, className: "p-1.5 text-gray-600 hover:text-gray-900 hover:bg-gray-200 rounded transition-colors", title: "Italique (Ctrl+I)", children: _jsx("span", { className: "material-icons text-lg", children: "format_italic" }) }), _jsxs("div", { className: "relative", children: [_jsxs("button", { onClick: () => setShowHeadingMenu(!showHeadingMenu), className: "p-1.5 text-gray-600 hover:text-gray-900 hover:bg-gray-200 rounded transition-colors flex items-center", title: "Titres", children: [_jsx("span", { className: "material-icons text-lg", children: "title" }), _jsx("span", { className: "material-icons text-sm", children: "arrow_drop_down" })] }), showHeadingMenu && (_jsxs("div", { className: "absolute top-full left-0 mt-1 bg-white border border-gray-200 rounded-lg shadow-lg z-10 py-1", children: [_jsx("button", { onClick: () => { onHeading?.(1); setShowHeadingMenu(false); }, className: "block w-full px-4 py-1.5 text-left text-lg font-bold hover:bg-gray-100", children: "Titre 1" }), _jsx("button", { onClick: () => { onHeading?.(2); setShowHeadingMenu(false); }, className: "block w-full px-4 py-1.5 text-left text-base font-bold hover:bg-gray-100", children: "Titre 2" }), _jsx("button", { onClick: () => { onHeading?.(3); setShowHeadingMenu(false); }, className: "block w-full px-4 py-1.5 text-left text-sm font-bold hover:bg-gray-100", children: "Titre 3" })] }))] }), _jsx("div", { className: "w-px h-6 bg-gray-300 mx-1" }), _jsx("button", { onClick: onBulletList, className: "p-1.5 text-gray-600 hover:text-gray-900 hover:bg-gray-200 rounded transition-colors", title: "Liste \u00E0 puces", children: _jsx("span", { className: "material-icons text-lg", children: "format_list_bulleted" }) }), _jsx("button", { onClick: onNumberedList, className: "p-1.5 text-gray-600 hover:text-gray-900 hover:bg-gray-200 rounded transition-colors", title: "Liste num\u00E9rot\u00E9e", children: _jsx("span", { className: "material-icons text-lg", children: "format_list_numbered" }) }), _jsx("button", { onClick: onQuote, className: "p-1.5 text-gray-600 hover:text-gray-900 hover:bg-gray-200 rounded transition-colors", title: "Citation", children: _jsx("span", { className: "material-icons text-lg", children: "format_quote" }) }), _jsx("button", { onClick: onLink, className: "p-1.5 text-gray-600 hover:text-gray-900 hover:bg-gray-200 rounded transition-colors", title: "Lien", children: _jsx("span", { className: "material-icons text-lg", children: "link" }) }), _jsx("div", { className: "w-px h-6 bg-gray-300 mx-1" })] })), _jsxs("button", { onClick: onRewrite, disabled: isLoading, className: "flex items-center gap-1 px-3 py-1.5 text-sm bg-blue-500 text-white rounded-lg hover:bg-blue-600 disabled:opacity-50 disabled:cursor-not-allowed transition-colors", title: hasSelection ? "Réécrire la sélection" : "Réécrire tout le texte", children: [_jsx("span", { className: "material-icons text-base", children: "auto_fix_high" }), "R\u00E9\u00E9crire"] }), _jsxs("button", { onClick: onProofread, disabled: isLoading, className: "flex items-center gap-1 px-3 py-1.5 text-sm bg-green-500 text-white rounded-lg hover:bg-green-600 disabled:opacity-50 disabled:cursor-not-allowed transition-colors", title: hasSelection ? "Corriger la sélection" : "Corriger tout le texte", children: [_jsx("span", { className: "material-icons text-base", children: "spellcheck" }), "Proof reading"] }), _jsxs("button", { onClick: onCustomPrompt, disabled: isLoading, className: "flex items-center gap-1 px-3 py-1.5 text-sm bg-purple-500 text-white rounded-lg hover:bg-purple-600 disabled:opacity-50 disabled:cursor-not-allowed transition-colors", title: "Instruction personnalis\u00E9e", children: [_jsx("span", { className: "material-icons text-base", children: "smart_toy" }), "Custom..."] }), _jsx("div", { className: "flex-1" }), hasSelection && (_jsx("span", { className: "text-xs text-blue-600 bg-blue-50 px-2 py-1 rounded", children: "Texte s\u00E9lectionn\u00E9" })), isLoading && (_jsxs("span", { className: "text-xs text-amber-600 bg-amber-50 px-2 py-1 rounded flex items-center gap-1", children: [_jsx("span", { className: "material-icons text-sm animate-spin", children: "sync" }), "IA en cours..."] })), _jsx("div", { className: "w-px h-6 bg-gray-300 mx-1" }), _jsx("button", { onClick: onUndo, disabled: !canUndo || isLoading, className: "p-1.5 text-gray-600 hover:text-gray-900 hover:bg-gray-200 rounded disabled:opacity-30 disabled:cursor-not-allowed transition-colors", title: "Annuler (Ctrl+Z)", children: _jsx("span", { className: "material-icons text-xl", children: "undo" }) }), _jsx("button", { onClick: onRedo, disabled: !canRedo || isLoading, className: "p-1.5 text-gray-600 hover:text-gray-900 hover:bg-gray-200 rounded disabled:opacity-30 disabled:cursor-not-allowed transition-colors", title: "Refaire (Ctrl+Y)", children: _jsx("span", { className: "material-icons text-xl", children: "redo" }) })] }));
15
+ : 'text-gray-600 hover:text-gray-900'}`, title: "Mode \u00E9dition", children: (0, jsx_runtime_1.jsx)("span", { className: "material-icons text-base", children: "edit" }) })] }), (0, jsx_runtime_1.jsx)("div", { className: "w-px h-6 bg-gray-300 mx-1" }), isEditMode && ((0, jsx_runtime_1.jsxs)(jsx_runtime_1.Fragment, { children: [(0, jsx_runtime_1.jsx)("button", { onClick: onBold, className: "p-1.5 text-gray-600 hover:text-gray-900 hover:bg-gray-200 rounded transition-colors", title: "Gras (Ctrl+B)", children: (0, jsx_runtime_1.jsx)("span", { className: "material-icons text-lg", children: "format_bold" }) }), (0, jsx_runtime_1.jsx)("button", { onClick: onItalic, className: "p-1.5 text-gray-600 hover:text-gray-900 hover:bg-gray-200 rounded transition-colors", title: "Italique (Ctrl+I)", children: (0, jsx_runtime_1.jsx)("span", { className: "material-icons text-lg", children: "format_italic" }) }), (0, jsx_runtime_1.jsxs)("div", { className: "relative", children: [(0, jsx_runtime_1.jsxs)("button", { onClick: () => setShowHeadingMenu(!showHeadingMenu), className: "p-1.5 text-gray-600 hover:text-gray-900 hover:bg-gray-200 rounded transition-colors flex items-center", title: "Titres", children: [(0, jsx_runtime_1.jsx)("span", { className: "material-icons text-lg", children: "title" }), (0, jsx_runtime_1.jsx)("span", { className: "material-icons text-sm", children: "arrow_drop_down" })] }), showHeadingMenu && ((0, jsx_runtime_1.jsxs)("div", { className: "absolute top-full left-0 mt-1 bg-white border border-gray-200 rounded-lg shadow-lg z-10 py-1", children: [(0, jsx_runtime_1.jsx)("button", { onClick: () => { onHeading?.(1); setShowHeadingMenu(false); }, className: "block w-full px-4 py-1.5 text-left text-lg font-bold hover:bg-gray-100", children: "Titre 1" }), (0, jsx_runtime_1.jsx)("button", { onClick: () => { onHeading?.(2); setShowHeadingMenu(false); }, className: "block w-full px-4 py-1.5 text-left text-base font-bold hover:bg-gray-100", children: "Titre 2" }), (0, jsx_runtime_1.jsx)("button", { onClick: () => { onHeading?.(3); setShowHeadingMenu(false); }, className: "block w-full px-4 py-1.5 text-left text-sm font-bold hover:bg-gray-100", children: "Titre 3" })] }))] }), (0, jsx_runtime_1.jsx)("div", { className: "w-px h-6 bg-gray-300 mx-1" }), (0, jsx_runtime_1.jsx)("button", { onClick: onBulletList, className: "p-1.5 text-gray-600 hover:text-gray-900 hover:bg-gray-200 rounded transition-colors", title: "Liste \u00E0 puces", children: (0, jsx_runtime_1.jsx)("span", { className: "material-icons text-lg", children: "format_list_bulleted" }) }), (0, jsx_runtime_1.jsx)("button", { onClick: onNumberedList, className: "p-1.5 text-gray-600 hover:text-gray-900 hover:bg-gray-200 rounded transition-colors", title: "Liste num\u00E9rot\u00E9e", children: (0, jsx_runtime_1.jsx)("span", { className: "material-icons text-lg", children: "format_list_numbered" }) }), (0, jsx_runtime_1.jsx)("button", { onClick: onQuote, className: "p-1.5 text-gray-600 hover:text-gray-900 hover:bg-gray-200 rounded transition-colors", title: "Citation", children: (0, jsx_runtime_1.jsx)("span", { className: "material-icons text-lg", children: "format_quote" }) }), (0, jsx_runtime_1.jsx)("button", { onClick: onLink, className: "p-1.5 text-gray-600 hover:text-gray-900 hover:bg-gray-200 rounded transition-colors", title: "Lien", children: (0, jsx_runtime_1.jsx)("span", { className: "material-icons text-lg", children: "link" }) }), (0, jsx_runtime_1.jsx)("div", { className: "w-px h-6 bg-gray-300 mx-1" })] })), (0, jsx_runtime_1.jsxs)("button", { onClick: onRewrite, disabled: isLoading, className: "flex items-center gap-1 px-3 py-1.5 text-sm bg-blue-500 text-white rounded-lg hover:bg-blue-600 disabled:opacity-50 disabled:cursor-not-allowed transition-colors", title: hasSelection ? "Réécrire la sélection" : "Réécrire tout le texte", children: [(0, jsx_runtime_1.jsx)("span", { className: "material-icons text-base", children: "auto_fix_high" }), "R\u00E9\u00E9crire"] }), (0, jsx_runtime_1.jsxs)("button", { onClick: onProofread, disabled: isLoading, className: "flex items-center gap-1 px-3 py-1.5 text-sm bg-green-500 text-white rounded-lg hover:bg-green-600 disabled:opacity-50 disabled:cursor-not-allowed transition-colors", title: hasSelection ? "Corriger la sélection" : "Corriger tout le texte", children: [(0, jsx_runtime_1.jsx)("span", { className: "material-icons text-base", children: "spellcheck" }), "Proof reading"] }), (0, jsx_runtime_1.jsxs)("button", { onClick: onCustomPrompt, disabled: isLoading, className: "flex items-center gap-1 px-3 py-1.5 text-sm bg-purple-500 text-white rounded-lg hover:bg-purple-600 disabled:opacity-50 disabled:cursor-not-allowed transition-colors", title: "Instruction personnalis\u00E9e", children: [(0, jsx_runtime_1.jsx)("span", { className: "material-icons text-base", children: "smart_toy" }), "Custom..."] }), (0, jsx_runtime_1.jsx)("div", { className: "flex-1" }), hasSelection && ((0, jsx_runtime_1.jsx)("span", { className: "text-xs text-blue-600 bg-blue-50 px-2 py-1 rounded", children: "Texte s\u00E9lectionn\u00E9" })), isLoading && ((0, jsx_runtime_1.jsxs)("span", { className: "text-xs text-amber-600 bg-amber-50 px-2 py-1 rounded flex items-center gap-1", children: [(0, jsx_runtime_1.jsx)("span", { className: "material-icons text-sm animate-spin", children: "sync" }), "IA en cours..."] })), (0, jsx_runtime_1.jsx)("div", { className: "w-px h-6 bg-gray-300 mx-1" }), (0, jsx_runtime_1.jsx)("button", { onClick: onUndo, disabled: !canUndo || isLoading, className: "p-1.5 text-gray-600 hover:text-gray-900 hover:bg-gray-200 rounded disabled:opacity-30 disabled:cursor-not-allowed transition-colors", title: "Annuler (Ctrl+Z)", children: (0, jsx_runtime_1.jsx)("span", { className: "material-icons text-xl", children: "undo" }) }), (0, jsx_runtime_1.jsx)("button", { onClick: onRedo, disabled: !canRedo || isLoading, className: "p-1.5 text-gray-600 hover:text-gray-900 hover:bg-gray-200 rounded disabled:opacity-30 disabled:cursor-not-allowed transition-colors", title: "Refaire (Ctrl+Y)", children: (0, jsx_runtime_1.jsx)("span", { className: "material-icons text-xl", children: "redo" }) })] }));
10
16
  }
@@ -1,13 +1,16 @@
1
+ "use strict";
1
2
  'use client';
2
- import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
3
- import { useCallback, useEffect, useState, useRef } from 'react';
4
- import { useLexicalComposerContext } from '@lexical/react/LexicalComposerContext';
5
- import { FORMAT_TEXT_COMMAND, FORMAT_ELEMENT_COMMAND, UNDO_COMMAND, REDO_COMMAND, $getSelection, $isRangeSelection, $selectAll, CAN_UNDO_COMMAND, CAN_REDO_COMMAND, COMMAND_PRIORITY_CRITICAL, } from 'lexical';
6
- import { INSERT_OBJECT_COMMAND } from '../plugins/InsertObjectPlugin';
7
- import { INSERT_UNORDERED_LIST_COMMAND, INSERT_ORDERED_LIST_COMMAND, } from '@lexical/list';
8
- import { $createHeadingNode, $createQuoteNode, } from '@lexical/rich-text';
9
- import { $setBlocksType, $patchStyleText } from '@lexical/selection';
10
- import { $createParagraphNode } from 'lexical';
3
+ Object.defineProperty(exports, "__esModule", { value: true });
4
+ exports.EditorToolbar = EditorToolbar;
5
+ const jsx_runtime_1 = require("react/jsx-runtime");
6
+ const react_1 = require("react");
7
+ const LexicalComposerContext_1 = require("@lexical/react/LexicalComposerContext");
8
+ const lexical_1 = require("lexical");
9
+ const InsertObjectPlugin_1 = require("../plugins/InsertObjectPlugin");
10
+ const list_1 = require("@lexical/list");
11
+ const rich_text_1 = require("@lexical/rich-text");
12
+ const selection_1 = require("@lexical/selection");
13
+ const lexical_2 = require("lexical");
11
14
  const FONT_FAMILIES = [
12
15
  { label: 'Par défaut', value: '' },
13
16
  { label: 'Arial', value: 'Arial, sans-serif' },
@@ -20,8 +23,8 @@ const FONT_FAMILIES = [
20
23
  ];
21
24
  // Dropdown component using fixed positioning to escape overflow containers
22
25
  function FixedDropdown({ show, buttonRef, children }) {
23
- const [position, setPosition] = useState({ top: 0, left: 0 });
24
- useEffect(() => {
26
+ const [position, setPosition] = (0, react_1.useState)({ top: 0, left: 0 });
27
+ (0, react_1.useEffect)(() => {
25
28
  if (show && buttonRef.current) {
26
29
  const rect = buttonRef.current.getBoundingClientRect();
27
30
  setPosition({
@@ -32,7 +35,7 @@ function FixedDropdown({ show, buttonRef, children }) {
32
35
  }, [show, buttonRef]);
33
36
  if (!show)
34
37
  return null;
35
- return (_jsx("div", { style: {
38
+ return ((0, jsx_runtime_1.jsx)("div", { style: {
36
39
  position: 'fixed',
37
40
  top: position.top,
38
41
  left: position.left,
@@ -45,27 +48,27 @@ function FixedDropdown({ show, buttonRef, children }) {
45
48
  minWidth: '180px'
46
49
  }, onClick: (e) => e.stopPropagation(), children: children }));
47
50
  }
48
- export function EditorToolbar({ onAIAction, isLoading = false, isFullscreen = false, onToggleFullscreen }) {
49
- const [editor] = useLexicalComposerContext();
50
- const [canUndo, setCanUndo] = useState(false);
51
- const [canRedo, setCanRedo] = useState(false);
52
- const [isBold, setIsBold] = useState(false);
53
- const [isItalic, setIsItalic] = useState(false);
54
- const [isUnderline, setIsUnderline] = useState(false);
55
- const [isStrikethrough, setIsStrikethrough] = useState(false);
56
- const [showHeadingMenu, setShowHeadingMenu] = useState(false);
57
- const [showAIMenu, setShowAIMenu] = useState(false);
58
- const [showFontMenu, setShowFontMenu] = useState(false);
59
- const [currentFont, setCurrentFont] = useState('');
60
- const [fontSize, setFontSize] = useState(16);
61
- const fontButtonRef = useRef(null);
62
- const headingButtonRef = useRef(null);
63
- const aiButtonRef = useRef(null);
64
- const toolbarRef = useRef(null);
51
+ function EditorToolbar({ onAIAction, isLoading = false, isFullscreen = false, onToggleFullscreen }) {
52
+ const [editor] = (0, LexicalComposerContext_1.useLexicalComposerContext)();
53
+ const [canUndo, setCanUndo] = (0, react_1.useState)(false);
54
+ const [canRedo, setCanRedo] = (0, react_1.useState)(false);
55
+ const [isBold, setIsBold] = (0, react_1.useState)(false);
56
+ const [isItalic, setIsItalic] = (0, react_1.useState)(false);
57
+ const [isUnderline, setIsUnderline] = (0, react_1.useState)(false);
58
+ const [isStrikethrough, setIsStrikethrough] = (0, react_1.useState)(false);
59
+ const [showHeadingMenu, setShowHeadingMenu] = (0, react_1.useState)(false);
60
+ const [showAIMenu, setShowAIMenu] = (0, react_1.useState)(false);
61
+ const [showFontMenu, setShowFontMenu] = (0, react_1.useState)(false);
62
+ const [currentFont, setCurrentFont] = (0, react_1.useState)('');
63
+ const [fontSize, setFontSize] = (0, react_1.useState)(16);
64
+ const fontButtonRef = (0, react_1.useRef)(null);
65
+ const headingButtonRef = (0, react_1.useRef)(null);
66
+ const aiButtonRef = (0, react_1.useRef)(null);
67
+ const toolbarRef = (0, react_1.useRef)(null);
65
68
  // Update toolbar state based on selection
66
- const updateToolbar = useCallback(() => {
67
- const selection = $getSelection();
68
- if ($isRangeSelection(selection)) {
69
+ const updateToolbar = (0, react_1.useCallback)(() => {
70
+ const selection = (0, lexical_1.$getSelection)();
71
+ if ((0, lexical_1.$isRangeSelection)(selection)) {
69
72
  setIsBold(selection.hasFormat('bold'));
70
73
  setIsItalic(selection.hasFormat('italic'));
71
74
  setIsUnderline(selection.hasFormat('underline'));
@@ -73,7 +76,7 @@ export function EditorToolbar({ onAIAction, isLoading = false, isFullscreen = fa
73
76
  }
74
77
  }, []);
75
78
  // Register listeners
76
- useEffect(() => {
79
+ (0, react_1.useEffect)(() => {
77
80
  return editor.registerUpdateListener(({ editorState }) => {
78
81
  editorState.read(() => {
79
82
  updateToolbar();
@@ -81,65 +84,65 @@ export function EditorToolbar({ onAIAction, isLoading = false, isFullscreen = fa
81
84
  });
82
85
  }, [editor, updateToolbar]);
83
86
  // Register undo/redo commands
84
- useEffect(() => {
85
- return editor.registerCommand(CAN_UNDO_COMMAND, (payload) => {
87
+ (0, react_1.useEffect)(() => {
88
+ return editor.registerCommand(lexical_1.CAN_UNDO_COMMAND, (payload) => {
86
89
  setCanUndo(payload);
87
90
  return false;
88
- }, COMMAND_PRIORITY_CRITICAL);
91
+ }, lexical_1.COMMAND_PRIORITY_CRITICAL);
89
92
  }, [editor]);
90
- useEffect(() => {
91
- return editor.registerCommand(CAN_REDO_COMMAND, (payload) => {
93
+ (0, react_1.useEffect)(() => {
94
+ return editor.registerCommand(lexical_1.CAN_REDO_COMMAND, (payload) => {
92
95
  setCanRedo(payload);
93
96
  return false;
94
- }, COMMAND_PRIORITY_CRITICAL);
97
+ }, lexical_1.COMMAND_PRIORITY_CRITICAL);
95
98
  }, [editor]);
96
99
  // Format handlers
97
- const formatBold = () => editor.dispatchCommand(FORMAT_TEXT_COMMAND, 'bold');
98
- const formatItalic = () => editor.dispatchCommand(FORMAT_TEXT_COMMAND, 'italic');
99
- const formatUnderline = () => editor.dispatchCommand(FORMAT_TEXT_COMMAND, 'underline');
100
- const formatStrikethrough = () => editor.dispatchCommand(FORMAT_TEXT_COMMAND, 'strikethrough');
100
+ const formatBold = () => editor.dispatchCommand(lexical_1.FORMAT_TEXT_COMMAND, 'bold');
101
+ const formatItalic = () => editor.dispatchCommand(lexical_1.FORMAT_TEXT_COMMAND, 'italic');
102
+ const formatUnderline = () => editor.dispatchCommand(lexical_1.FORMAT_TEXT_COMMAND, 'underline');
103
+ const formatStrikethrough = () => editor.dispatchCommand(lexical_1.FORMAT_TEXT_COMMAND, 'strikethrough');
101
104
  const formatHeading = (headingTag) => {
102
105
  editor.update(() => {
103
- const selection = $getSelection();
104
- if ($isRangeSelection(selection)) {
105
- $setBlocksType(selection, () => $createHeadingNode(headingTag));
106
+ const selection = (0, lexical_1.$getSelection)();
107
+ if ((0, lexical_1.$isRangeSelection)(selection)) {
108
+ (0, selection_1.$setBlocksType)(selection, () => (0, rich_text_1.$createHeadingNode)(headingTag));
106
109
  }
107
110
  });
108
111
  setShowHeadingMenu(false);
109
112
  };
110
113
  const formatParagraph = () => {
111
114
  editor.update(() => {
112
- const selection = $getSelection();
113
- if ($isRangeSelection(selection)) {
114
- $setBlocksType(selection, () => $createParagraphNode());
115
+ const selection = (0, lexical_1.$getSelection)();
116
+ if ((0, lexical_1.$isRangeSelection)(selection)) {
117
+ (0, selection_1.$setBlocksType)(selection, () => (0, lexical_2.$createParagraphNode)());
115
118
  }
116
119
  });
117
120
  setShowHeadingMenu(false);
118
121
  };
119
122
  const formatQuote = () => {
120
123
  editor.update(() => {
121
- const selection = $getSelection();
122
- if ($isRangeSelection(selection)) {
123
- $setBlocksType(selection, () => $createQuoteNode());
124
+ const selection = (0, lexical_1.$getSelection)();
125
+ if ((0, lexical_1.$isRangeSelection)(selection)) {
126
+ (0, selection_1.$setBlocksType)(selection, () => (0, rich_text_1.$createQuoteNode)());
124
127
  }
125
128
  });
126
129
  };
127
130
  const openInsertDialog = () => {
128
- editor.dispatchCommand(INSERT_OBJECT_COMMAND, undefined);
131
+ editor.dispatchCommand(InsertObjectPlugin_1.INSERT_OBJECT_COMMAND, undefined);
129
132
  };
130
133
  const formatAlign = (alignment) => {
131
- editor.dispatchCommand(FORMAT_ELEMENT_COMMAND, alignment);
134
+ editor.dispatchCommand(lexical_1.FORMAT_ELEMENT_COMMAND, alignment);
132
135
  };
133
136
  const formatBulletList = () => {
134
- editor.dispatchCommand(INSERT_UNORDERED_LIST_COMMAND, undefined);
137
+ editor.dispatchCommand(list_1.INSERT_UNORDERED_LIST_COMMAND, undefined);
135
138
  };
136
139
  const formatNumberedList = () => {
137
- editor.dispatchCommand(INSERT_ORDERED_LIST_COMMAND, undefined);
140
+ editor.dispatchCommand(list_1.INSERT_ORDERED_LIST_COMMAND, undefined);
138
141
  };
139
- const undo = () => editor.dispatchCommand(UNDO_COMMAND, undefined);
140
- const redo = () => editor.dispatchCommand(REDO_COMMAND, undefined);
142
+ const undo = () => editor.dispatchCommand(lexical_1.UNDO_COMMAND, undefined);
143
+ const redo = () => editor.dispatchCommand(lexical_1.REDO_COMMAND, undefined);
141
144
  // Close menus when clicking outside the toolbar
142
- useEffect(() => {
145
+ (0, react_1.useEffect)(() => {
143
146
  const handleClickOutside = (e) => {
144
147
  if (toolbarRef.current && !toolbarRef.current.contains(e.target)) {
145
148
  setShowHeadingMenu(false);
@@ -153,13 +156,13 @@ export function EditorToolbar({ onAIAction, isLoading = false, isFullscreen = fa
153
156
  // Apply font family to selection
154
157
  const applyFontFamily = (fontFamily) => {
155
158
  editor.update(() => {
156
- let selection = $getSelection();
157
- if (!$isRangeSelection(selection) || selection.isCollapsed()) {
158
- $selectAll();
159
- selection = $getSelection();
159
+ let selection = (0, lexical_1.$getSelection)();
160
+ if (!(0, lexical_1.$isRangeSelection)(selection) || selection.isCollapsed()) {
161
+ (0, lexical_1.$selectAll)();
162
+ selection = (0, lexical_1.$getSelection)();
160
163
  }
161
- if ($isRangeSelection(selection)) {
162
- $patchStyleText(selection, { 'font-family': fontFamily || null });
164
+ if ((0, lexical_1.$isRangeSelection)(selection)) {
165
+ (0, selection_1.$patchStyleText)(selection, { 'font-family': fontFamily || null });
163
166
  }
164
167
  });
165
168
  setCurrentFont(fontFamily);
@@ -168,13 +171,13 @@ export function EditorToolbar({ onAIAction, isLoading = false, isFullscreen = fa
168
171
  // Apply font size to selection
169
172
  const applyFontSize = (size) => {
170
173
  editor.update(() => {
171
- let selection = $getSelection();
172
- if (!$isRangeSelection(selection) || selection.isCollapsed()) {
173
- $selectAll();
174
- selection = $getSelection();
174
+ let selection = (0, lexical_1.$getSelection)();
175
+ if (!(0, lexical_1.$isRangeSelection)(selection) || selection.isCollapsed()) {
176
+ (0, lexical_1.$selectAll)();
177
+ selection = (0, lexical_1.$getSelection)();
175
178
  }
176
- if ($isRangeSelection(selection)) {
177
- $patchStyleText(selection, { 'font-size': `${size}px` });
179
+ if ((0, lexical_1.$isRangeSelection)(selection)) {
180
+ (0, selection_1.$patchStyleText)(selection, { 'font-size': `${size}px` });
178
181
  }
179
182
  });
180
183
  setFontSize(size);
@@ -202,40 +205,40 @@ export function EditorToolbar({ onAIAction, isLoading = false, isFullscreen = fa
202
205
  if (fontSize > 72)
203
206
  setFontSize(72);
204
207
  };
205
- return (_jsxs("div", { ref: toolbarRef, className: "flex flex-wrap items-center gap-1 p-2 bg-gray-50 border-b border-gray-200 flex-shrink-0", children: [_jsx("button", { onClick: undo, disabled: !canUndo, className: "p-1.5 text-gray-600 hover:text-gray-900 hover:bg-gray-200 rounded disabled:opacity-30 disabled:cursor-not-allowed transition-colors", title: "Annuler (Ctrl+Z)", children: _jsx("span", { className: "material-icons text-lg", children: "undo" }) }), _jsx("button", { onClick: redo, disabled: !canRedo, className: "p-1.5 text-gray-600 hover:text-gray-900 hover:bg-gray-200 rounded disabled:opacity-30 disabled:cursor-not-allowed transition-colors", title: "Refaire (Ctrl+Y)", children: _jsx("span", { className: "material-icons text-lg", children: "redo" }) }), _jsx("div", { className: "w-px h-6 bg-gray-300 mx-1" }), _jsx("button", { onClick: formatBold, className: `p-1.5 rounded transition-colors ${isBold
208
+ return ((0, jsx_runtime_1.jsxs)("div", { ref: toolbarRef, className: "flex flex-wrap items-center gap-1 p-2 bg-gray-50 border-b border-gray-200 flex-shrink-0", children: [(0, jsx_runtime_1.jsx)("button", { onClick: undo, disabled: !canUndo, className: "p-1.5 text-gray-600 hover:text-gray-900 hover:bg-gray-200 rounded disabled:opacity-30 disabled:cursor-not-allowed transition-colors", title: "Annuler (Ctrl+Z)", children: (0, jsx_runtime_1.jsx)("span", { className: "material-icons text-lg", children: "undo" }) }), (0, jsx_runtime_1.jsx)("button", { onClick: redo, disabled: !canRedo, className: "p-1.5 text-gray-600 hover:text-gray-900 hover:bg-gray-200 rounded disabled:opacity-30 disabled:cursor-not-allowed transition-colors", title: "Refaire (Ctrl+Y)", children: (0, jsx_runtime_1.jsx)("span", { className: "material-icons text-lg", children: "redo" }) }), (0, jsx_runtime_1.jsx)("div", { className: "w-px h-6 bg-gray-300 mx-1" }), (0, jsx_runtime_1.jsx)("button", { onClick: formatBold, className: `p-1.5 rounded transition-colors ${isBold
206
209
  ? 'bg-gray-200 text-gray-900'
207
- : 'text-gray-600 hover:text-gray-900 hover:bg-gray-200'}`, title: "Gras (Ctrl+B)", children: _jsx("span", { className: "material-icons text-lg", children: "format_bold" }) }), _jsx("button", { onClick: formatItalic, className: `p-1.5 rounded transition-colors ${isItalic
210
+ : 'text-gray-600 hover:text-gray-900 hover:bg-gray-200'}`, title: "Gras (Ctrl+B)", children: (0, jsx_runtime_1.jsx)("span", { className: "material-icons text-lg", children: "format_bold" }) }), (0, jsx_runtime_1.jsx)("button", { onClick: formatItalic, className: `p-1.5 rounded transition-colors ${isItalic
208
211
  ? 'bg-gray-200 text-gray-900'
209
- : 'text-gray-600 hover:text-gray-900 hover:bg-gray-200'}`, title: "Italique (Ctrl+I)", children: _jsx("span", { className: "material-icons text-lg", children: "format_italic" }) }), _jsx("button", { onClick: formatUnderline, className: `p-1.5 rounded transition-colors ${isUnderline
212
+ : 'text-gray-600 hover:text-gray-900 hover:bg-gray-200'}`, title: "Italique (Ctrl+I)", children: (0, jsx_runtime_1.jsx)("span", { className: "material-icons text-lg", children: "format_italic" }) }), (0, jsx_runtime_1.jsx)("button", { onClick: formatUnderline, className: `p-1.5 rounded transition-colors ${isUnderline
210
213
  ? 'bg-gray-200 text-gray-900'
211
- : 'text-gray-600 hover:text-gray-900 hover:bg-gray-200'}`, title: "Soulign\u00E9 (Ctrl+U)", children: _jsx("span", { className: "material-icons text-lg", children: "format_underlined" }) }), _jsx("button", { onClick: formatStrikethrough, className: `p-1.5 rounded transition-colors ${isStrikethrough
214
+ : 'text-gray-600 hover:text-gray-900 hover:bg-gray-200'}`, title: "Soulign\u00E9 (Ctrl+U)", children: (0, jsx_runtime_1.jsx)("span", { className: "material-icons text-lg", children: "format_underlined" }) }), (0, jsx_runtime_1.jsx)("button", { onClick: formatStrikethrough, className: `p-1.5 rounded transition-colors ${isStrikethrough
212
215
  ? 'bg-gray-200 text-gray-900'
213
- : 'text-gray-600 hover:text-gray-900 hover:bg-gray-200'}`, title: "Barr\u00E9", children: _jsx("span", { className: "material-icons text-lg", children: "strikethrough_s" }) }), _jsx("div", { className: "w-px h-6 bg-gray-300 mx-1" }), _jsxs("div", { style: { position: 'relative' }, children: [_jsxs("button", { ref: fontButtonRef, onClick: (e) => {
216
+ : 'text-gray-600 hover:text-gray-900 hover:bg-gray-200'}`, title: "Barr\u00E9", children: (0, jsx_runtime_1.jsx)("span", { className: "material-icons text-lg", children: "strikethrough_s" }) }), (0, jsx_runtime_1.jsx)("div", { className: "w-px h-6 bg-gray-300 mx-1" }), (0, jsx_runtime_1.jsxs)("div", { style: { position: 'relative' }, children: [(0, jsx_runtime_1.jsxs)("button", { ref: fontButtonRef, onClick: (e) => {
214
217
  e.stopPropagation();
215
218
  setShowFontMenu(!showFontMenu);
216
219
  setShowHeadingMenu(false);
217
220
  setShowAIMenu(false);
218
- }, className: "h-8 px-2 text-gray-600 hover:text-gray-900 hover:bg-gray-200 rounded transition-colors flex items-center gap-1 text-sm border border-gray-300 bg-white min-w-[100px]", title: "Police", children: [_jsx("span", { className: "truncate flex-1 text-left", style: { fontFamily: currentFont || 'inherit' }, children: FONT_FAMILIES.find(f => f.value === currentFont)?.label || 'Police' }), _jsx("span", { className: "material-icons text-sm", children: "arrow_drop_down" })] }), _jsxs(FixedDropdown, { show: showFontMenu, buttonRef: fontButtonRef, children: [_jsx("button", { onClick: () => applyFontFamily(''), style: { display: 'block', width: '100%', padding: '8px 16px', textAlign: 'left', fontSize: '14px', backgroundColor: 'transparent', border: 'none', cursor: 'pointer', color: '#374151' }, onMouseEnter: (e) => e.currentTarget.style.backgroundColor = '#f3f4f6', onMouseLeave: (e) => e.currentTarget.style.backgroundColor = 'transparent', children: "Par d\u00E9faut" }), _jsx("button", { onClick: () => applyFontFamily('Arial, sans-serif'), style: { display: 'block', width: '100%', padding: '8px 16px', textAlign: 'left', fontSize: '14px', backgroundColor: 'transparent', border: 'none', cursor: 'pointer', color: '#374151', fontFamily: 'Arial, sans-serif' }, onMouseEnter: (e) => e.currentTarget.style.backgroundColor = '#f3f4f6', onMouseLeave: (e) => e.currentTarget.style.backgroundColor = 'transparent', children: "Arial" }), _jsx("button", { onClick: () => applyFontFamily('Times New Roman, serif'), style: { display: 'block', width: '100%', padding: '8px 16px', textAlign: 'left', fontSize: '14px', backgroundColor: 'transparent', border: 'none', cursor: 'pointer', color: '#374151', fontFamily: 'Times New Roman, serif' }, onMouseEnter: (e) => e.currentTarget.style.backgroundColor = '#f3f4f6', onMouseLeave: (e) => e.currentTarget.style.backgroundColor = 'transparent', children: "Times New Roman" }), _jsx("button", { onClick: () => applyFontFamily('Georgia, serif'), style: { display: 'block', width: '100%', padding: '8px 16px', textAlign: 'left', fontSize: '14px', backgroundColor: 'transparent', border: 'none', cursor: 'pointer', color: '#374151', fontFamily: 'Georgia, serif' }, onMouseEnter: (e) => e.currentTarget.style.backgroundColor = '#f3f4f6', onMouseLeave: (e) => e.currentTarget.style.backgroundColor = 'transparent', children: "Georgia" }), _jsx("button", { onClick: () => applyFontFamily('Courier New, monospace'), style: { display: 'block', width: '100%', padding: '8px 16px', textAlign: 'left', fontSize: '14px', backgroundColor: 'transparent', border: 'none', cursor: 'pointer', color: '#374151', fontFamily: 'Courier New, monospace' }, onMouseEnter: (e) => e.currentTarget.style.backgroundColor = '#f3f4f6', onMouseLeave: (e) => e.currentTarget.style.backgroundColor = 'transparent', children: "Courier New" }), _jsx("button", { onClick: () => applyFontFamily('Verdana, sans-serif'), style: { display: 'block', width: '100%', padding: '8px 16px', textAlign: 'left', fontSize: '14px', backgroundColor: 'transparent', border: 'none', cursor: 'pointer', color: '#374151', fontFamily: 'Verdana, sans-serif' }, onMouseEnter: (e) => e.currentTarget.style.backgroundColor = '#f3f4f6', onMouseLeave: (e) => e.currentTarget.style.backgroundColor = 'transparent', children: "Verdana" })] })] }), _jsxs("div", { className: "flex items-center border border-gray-300 rounded bg-white h-8", children: [_jsx("button", { onClick: decreaseFontSize, className: "px-1 h-full text-gray-600 hover:text-gray-900 hover:bg-gray-100 transition-colors", title: "R\u00E9duire la taille", children: _jsx("span", { className: "material-icons text-sm", children: "remove" }) }), _jsx("input", { type: "number", value: fontSize, onChange: handleFontSizeChange, onBlur: handleFontSizeBlur, className: "w-10 h-full text-center text-sm text-gray-900 border-x border-gray-300 focus:outline-none", min: 8, max: 72, title: "Taille de police (px)" }), _jsx("button", { onClick: increaseFontSize, className: "px-1 h-full text-gray-600 hover:text-gray-900 hover:bg-gray-100 transition-colors", title: "Augmenter la taille", children: _jsx("span", { className: "material-icons text-sm", children: "add" }) })] }), _jsx("div", { className: "w-px h-6 bg-gray-300 mx-1" }), _jsxs("div", { style: { position: 'relative' }, children: [_jsxs("button", { ref: headingButtonRef, onClick: (e) => {
221
+ }, className: "h-8 px-2 text-gray-600 hover:text-gray-900 hover:bg-gray-200 rounded transition-colors flex items-center gap-1 text-sm border border-gray-300 bg-white min-w-[100px]", title: "Police", children: [(0, jsx_runtime_1.jsx)("span", { className: "truncate flex-1 text-left", style: { fontFamily: currentFont || 'inherit' }, children: FONT_FAMILIES.find(f => f.value === currentFont)?.label || 'Police' }), (0, jsx_runtime_1.jsx)("span", { className: "material-icons text-sm", children: "arrow_drop_down" })] }), (0, jsx_runtime_1.jsxs)(FixedDropdown, { show: showFontMenu, buttonRef: fontButtonRef, children: [(0, jsx_runtime_1.jsx)("button", { onClick: () => applyFontFamily(''), style: { display: 'block', width: '100%', padding: '8px 16px', textAlign: 'left', fontSize: '14px', backgroundColor: 'transparent', border: 'none', cursor: 'pointer', color: '#374151' }, onMouseEnter: (e) => e.currentTarget.style.backgroundColor = '#f3f4f6', onMouseLeave: (e) => e.currentTarget.style.backgroundColor = 'transparent', children: "Par d\u00E9faut" }), (0, jsx_runtime_1.jsx)("button", { onClick: () => applyFontFamily('Arial, sans-serif'), style: { display: 'block', width: '100%', padding: '8px 16px', textAlign: 'left', fontSize: '14px', backgroundColor: 'transparent', border: 'none', cursor: 'pointer', color: '#374151', fontFamily: 'Arial, sans-serif' }, onMouseEnter: (e) => e.currentTarget.style.backgroundColor = '#f3f4f6', onMouseLeave: (e) => e.currentTarget.style.backgroundColor = 'transparent', children: "Arial" }), (0, jsx_runtime_1.jsx)("button", { onClick: () => applyFontFamily('Times New Roman, serif'), style: { display: 'block', width: '100%', padding: '8px 16px', textAlign: 'left', fontSize: '14px', backgroundColor: 'transparent', border: 'none', cursor: 'pointer', color: '#374151', fontFamily: 'Times New Roman, serif' }, onMouseEnter: (e) => e.currentTarget.style.backgroundColor = '#f3f4f6', onMouseLeave: (e) => e.currentTarget.style.backgroundColor = 'transparent', children: "Times New Roman" }), (0, jsx_runtime_1.jsx)("button", { onClick: () => applyFontFamily('Georgia, serif'), style: { display: 'block', width: '100%', padding: '8px 16px', textAlign: 'left', fontSize: '14px', backgroundColor: 'transparent', border: 'none', cursor: 'pointer', color: '#374151', fontFamily: 'Georgia, serif' }, onMouseEnter: (e) => e.currentTarget.style.backgroundColor = '#f3f4f6', onMouseLeave: (e) => e.currentTarget.style.backgroundColor = 'transparent', children: "Georgia" }), (0, jsx_runtime_1.jsx)("button", { onClick: () => applyFontFamily('Courier New, monospace'), style: { display: 'block', width: '100%', padding: '8px 16px', textAlign: 'left', fontSize: '14px', backgroundColor: 'transparent', border: 'none', cursor: 'pointer', color: '#374151', fontFamily: 'Courier New, monospace' }, onMouseEnter: (e) => e.currentTarget.style.backgroundColor = '#f3f4f6', onMouseLeave: (e) => e.currentTarget.style.backgroundColor = 'transparent', children: "Courier New" }), (0, jsx_runtime_1.jsx)("button", { onClick: () => applyFontFamily('Verdana, sans-serif'), style: { display: 'block', width: '100%', padding: '8px 16px', textAlign: 'left', fontSize: '14px', backgroundColor: 'transparent', border: 'none', cursor: 'pointer', color: '#374151', fontFamily: 'Verdana, sans-serif' }, onMouseEnter: (e) => e.currentTarget.style.backgroundColor = '#f3f4f6', onMouseLeave: (e) => e.currentTarget.style.backgroundColor = 'transparent', children: "Verdana" })] })] }), (0, jsx_runtime_1.jsxs)("div", { className: "flex items-center border border-gray-300 rounded bg-white h-8", children: [(0, jsx_runtime_1.jsx)("button", { onClick: decreaseFontSize, className: "px-1 h-full text-gray-600 hover:text-gray-900 hover:bg-gray-100 transition-colors", title: "R\u00E9duire la taille", children: (0, jsx_runtime_1.jsx)("span", { className: "material-icons text-sm", children: "remove" }) }), (0, jsx_runtime_1.jsx)("input", { type: "number", value: fontSize, onChange: handleFontSizeChange, onBlur: handleFontSizeBlur, className: "w-10 h-full text-center text-sm text-gray-900 border-x border-gray-300 focus:outline-none", min: 8, max: 72, title: "Taille de police (px)" }), (0, jsx_runtime_1.jsx)("button", { onClick: increaseFontSize, className: "px-1 h-full text-gray-600 hover:text-gray-900 hover:bg-gray-100 transition-colors", title: "Augmenter la taille", children: (0, jsx_runtime_1.jsx)("span", { className: "material-icons text-sm", children: "add" }) })] }), (0, jsx_runtime_1.jsx)("div", { className: "w-px h-6 bg-gray-300 mx-1" }), (0, jsx_runtime_1.jsxs)("div", { style: { position: 'relative' }, children: [(0, jsx_runtime_1.jsxs)("button", { ref: headingButtonRef, onClick: (e) => {
219
222
  e.stopPropagation();
220
223
  setShowHeadingMenu(!showHeadingMenu);
221
224
  setShowAIMenu(false);
222
225
  setShowFontMenu(false);
223
- }, className: "p-1.5 text-gray-600 hover:text-gray-900 hover:bg-gray-200 rounded transition-colors flex items-center", title: "Titres", children: [_jsx("span", { className: "material-icons text-lg", children: "title" }), _jsx("span", { className: "material-icons text-sm", children: "arrow_drop_down" })] }), _jsxs(FixedDropdown, { show: showHeadingMenu, buttonRef: headingButtonRef, children: [_jsx("button", { onClick: formatParagraph, style: { display: 'block', width: '100%', padding: '6px 16px', textAlign: 'left', fontSize: '14px', backgroundColor: 'transparent', border: 'none', cursor: 'pointer', color: '#374151' }, onMouseEnter: (e) => e.currentTarget.style.backgroundColor = '#f3f4f6', onMouseLeave: (e) => e.currentTarget.style.backgroundColor = 'transparent', children: "Paragraphe" }), _jsx("button", { onClick: () => formatHeading('h1'), style: { display: 'block', width: '100%', padding: '6px 16px', textAlign: 'left', fontSize: '20px', fontWeight: 'bold', backgroundColor: 'transparent', border: 'none', cursor: 'pointer', color: '#374151' }, onMouseEnter: (e) => e.currentTarget.style.backgroundColor = '#f3f4f6', onMouseLeave: (e) => e.currentTarget.style.backgroundColor = 'transparent', children: "Titre 1" }), _jsx("button", { onClick: () => formatHeading('h2'), style: { display: 'block', width: '100%', padding: '6px 16px', textAlign: 'left', fontSize: '18px', fontWeight: 'bold', backgroundColor: 'transparent', border: 'none', cursor: 'pointer', color: '#374151' }, onMouseEnter: (e) => e.currentTarget.style.backgroundColor = '#f3f4f6', onMouseLeave: (e) => e.currentTarget.style.backgroundColor = 'transparent', children: "Titre 2" }), _jsx("button", { onClick: () => formatHeading('h3'), style: { display: 'block', width: '100%', padding: '6px 16px', textAlign: 'left', fontSize: '16px', fontWeight: '600', backgroundColor: 'transparent', border: 'none', cursor: 'pointer', color: '#374151' }, onMouseEnter: (e) => e.currentTarget.style.backgroundColor = '#f3f4f6', onMouseLeave: (e) => e.currentTarget.style.backgroundColor = 'transparent', children: "Titre 3" })] })] }), _jsx("div", { className: "w-px h-6 bg-gray-300 mx-1" }), _jsx("button", { onClick: formatBulletList, className: "p-1.5 text-gray-600 hover:text-gray-900 hover:bg-gray-200 rounded transition-colors", title: "Liste \u00E0 puces", children: _jsx("span", { className: "material-icons text-lg", children: "format_list_bulleted" }) }), _jsx("button", { onClick: formatNumberedList, className: "p-1.5 text-gray-600 hover:text-gray-900 hover:bg-gray-200 rounded transition-colors", title: "Liste num\u00E9rot\u00E9e", children: _jsx("span", { className: "material-icons text-lg", children: "format_list_numbered" }) }), _jsx("button", { onClick: formatQuote, className: "p-1.5 text-gray-600 hover:text-gray-900 hover:bg-gray-200 rounded transition-colors", title: "Citation", children: _jsx("span", { className: "material-icons text-lg", children: "format_quote" }) }), _jsx("div", { className: "w-px h-6 bg-gray-300 mx-1" }), _jsx("button", { onClick: () => formatAlign('left'), className: "p-1.5 text-gray-600 hover:text-gray-900 hover:bg-gray-200 rounded transition-colors", title: "Aligner \u00E0 gauche", children: _jsx("span", { className: "material-icons text-lg", children: "format_align_left" }) }), _jsx("button", { onClick: () => formatAlign('center'), className: "p-1.5 text-gray-600 hover:text-gray-900 hover:bg-gray-200 rounded transition-colors", title: "Centrer", children: _jsx("span", { className: "material-icons text-lg", children: "format_align_center" }) }), _jsx("button", { onClick: () => formatAlign('right'), className: "p-1.5 text-gray-600 hover:text-gray-900 hover:bg-gray-200 rounded transition-colors", title: "Aligner \u00E0 droite", children: _jsx("span", { className: "material-icons text-lg", children: "format_align_right" }) }), _jsx("button", { onClick: () => formatAlign('justify'), className: "p-1.5 text-gray-600 hover:text-gray-900 hover:bg-gray-200 rounded transition-colors", title: "Justifier", children: _jsx("span", { className: "material-icons text-lg", children: "format_align_justify" }) }), _jsx("div", { className: "w-px h-6 bg-gray-300 mx-1" }), _jsx("button", { onClick: openInsertDialog, className: "p-1.5 text-gray-600 hover:text-gray-900 hover:bg-gray-200 rounded transition-colors", title: "Ins\u00E9rer un objet (Ctrl+K)", children: _jsx("span", { className: "material-icons text-lg", children: "add_photo_alternate" }) }), _jsx("div", { className: "flex-1" }), onAIAction && (_jsxs("div", { style: { position: 'relative' }, children: [_jsxs("button", { ref: aiButtonRef, onClick: (e) => {
226
+ }, className: "p-1.5 text-gray-600 hover:text-gray-900 hover:bg-gray-200 rounded transition-colors flex items-center", title: "Titres", children: [(0, jsx_runtime_1.jsx)("span", { className: "material-icons text-lg", children: "title" }), (0, jsx_runtime_1.jsx)("span", { className: "material-icons text-sm", children: "arrow_drop_down" })] }), (0, jsx_runtime_1.jsxs)(FixedDropdown, { show: showHeadingMenu, buttonRef: headingButtonRef, children: [(0, jsx_runtime_1.jsx)("button", { onClick: formatParagraph, style: { display: 'block', width: '100%', padding: '6px 16px', textAlign: 'left', fontSize: '14px', backgroundColor: 'transparent', border: 'none', cursor: 'pointer', color: '#374151' }, onMouseEnter: (e) => e.currentTarget.style.backgroundColor = '#f3f4f6', onMouseLeave: (e) => e.currentTarget.style.backgroundColor = 'transparent', children: "Paragraphe" }), (0, jsx_runtime_1.jsx)("button", { onClick: () => formatHeading('h1'), style: { display: 'block', width: '100%', padding: '6px 16px', textAlign: 'left', fontSize: '20px', fontWeight: 'bold', backgroundColor: 'transparent', border: 'none', cursor: 'pointer', color: '#374151' }, onMouseEnter: (e) => e.currentTarget.style.backgroundColor = '#f3f4f6', onMouseLeave: (e) => e.currentTarget.style.backgroundColor = 'transparent', children: "Titre 1" }), (0, jsx_runtime_1.jsx)("button", { onClick: () => formatHeading('h2'), style: { display: 'block', width: '100%', padding: '6px 16px', textAlign: 'left', fontSize: '18px', fontWeight: 'bold', backgroundColor: 'transparent', border: 'none', cursor: 'pointer', color: '#374151' }, onMouseEnter: (e) => e.currentTarget.style.backgroundColor = '#f3f4f6', onMouseLeave: (e) => e.currentTarget.style.backgroundColor = 'transparent', children: "Titre 2" }), (0, jsx_runtime_1.jsx)("button", { onClick: () => formatHeading('h3'), style: { display: 'block', width: '100%', padding: '6px 16px', textAlign: 'left', fontSize: '16px', fontWeight: '600', backgroundColor: 'transparent', border: 'none', cursor: 'pointer', color: '#374151' }, onMouseEnter: (e) => e.currentTarget.style.backgroundColor = '#f3f4f6', onMouseLeave: (e) => e.currentTarget.style.backgroundColor = 'transparent', children: "Titre 3" })] })] }), (0, jsx_runtime_1.jsx)("div", { className: "w-px h-6 bg-gray-300 mx-1" }), (0, jsx_runtime_1.jsx)("button", { onClick: formatBulletList, className: "p-1.5 text-gray-600 hover:text-gray-900 hover:bg-gray-200 rounded transition-colors", title: "Liste \u00E0 puces", children: (0, jsx_runtime_1.jsx)("span", { className: "material-icons text-lg", children: "format_list_bulleted" }) }), (0, jsx_runtime_1.jsx)("button", { onClick: formatNumberedList, className: "p-1.5 text-gray-600 hover:text-gray-900 hover:bg-gray-200 rounded transition-colors", title: "Liste num\u00E9rot\u00E9e", children: (0, jsx_runtime_1.jsx)("span", { className: "material-icons text-lg", children: "format_list_numbered" }) }), (0, jsx_runtime_1.jsx)("button", { onClick: formatQuote, className: "p-1.5 text-gray-600 hover:text-gray-900 hover:bg-gray-200 rounded transition-colors", title: "Citation", children: (0, jsx_runtime_1.jsx)("span", { className: "material-icons text-lg", children: "format_quote" }) }), (0, jsx_runtime_1.jsx)("div", { className: "w-px h-6 bg-gray-300 mx-1" }), (0, jsx_runtime_1.jsx)("button", { onClick: () => formatAlign('left'), className: "p-1.5 text-gray-600 hover:text-gray-900 hover:bg-gray-200 rounded transition-colors", title: "Aligner \u00E0 gauche", children: (0, jsx_runtime_1.jsx)("span", { className: "material-icons text-lg", children: "format_align_left" }) }), (0, jsx_runtime_1.jsx)("button", { onClick: () => formatAlign('center'), className: "p-1.5 text-gray-600 hover:text-gray-900 hover:bg-gray-200 rounded transition-colors", title: "Centrer", children: (0, jsx_runtime_1.jsx)("span", { className: "material-icons text-lg", children: "format_align_center" }) }), (0, jsx_runtime_1.jsx)("button", { onClick: () => formatAlign('right'), className: "p-1.5 text-gray-600 hover:text-gray-900 hover:bg-gray-200 rounded transition-colors", title: "Aligner \u00E0 droite", children: (0, jsx_runtime_1.jsx)("span", { className: "material-icons text-lg", children: "format_align_right" }) }), (0, jsx_runtime_1.jsx)("button", { onClick: () => formatAlign('justify'), className: "p-1.5 text-gray-600 hover:text-gray-900 hover:bg-gray-200 rounded transition-colors", title: "Justifier", children: (0, jsx_runtime_1.jsx)("span", { className: "material-icons text-lg", children: "format_align_justify" }) }), (0, jsx_runtime_1.jsx)("div", { className: "w-px h-6 bg-gray-300 mx-1" }), (0, jsx_runtime_1.jsx)("button", { onClick: openInsertDialog, className: "p-1.5 text-gray-600 hover:text-gray-900 hover:bg-gray-200 rounded transition-colors", title: "Ins\u00E9rer un objet (Ctrl+K)", children: (0, jsx_runtime_1.jsx)("span", { className: "material-icons text-lg", children: "add_photo_alternate" }) }), (0, jsx_runtime_1.jsx)("div", { className: "flex-1" }), onAIAction && ((0, jsx_runtime_1.jsxs)("div", { style: { position: 'relative' }, children: [(0, jsx_runtime_1.jsxs)("button", { ref: aiButtonRef, onClick: (e) => {
224
227
  e.stopPropagation();
225
228
  setShowAIMenu(!showAIMenu);
226
229
  setShowHeadingMenu(false);
227
230
  setShowFontMenu(false);
228
- }, disabled: isLoading, className: "flex items-center gap-1 px-3 py-1.5 text-sm bg-purple-500 text-white rounded-lg hover:bg-purple-600 disabled:opacity-50 disabled:cursor-not-allowed transition-colors", title: "Actions IA", children: [isLoading ? (_jsx("span", { className: "material-icons text-base animate-spin", children: "sync" })) : (_jsx("span", { className: "material-icons text-base", children: "auto_awesome" })), _jsx("span", { children: "IA" }), _jsx("span", { className: "material-icons text-sm", children: "arrow_drop_down" })] }), !isLoading && (_jsxs(FixedDropdown, { show: showAIMenu, buttonRef: aiButtonRef, children: [_jsxs("button", { onClick: () => {
231
+ }, disabled: isLoading, className: "flex items-center gap-1 px-3 py-1.5 text-sm bg-purple-500 text-white rounded-lg hover:bg-purple-600 disabled:opacity-50 disabled:cursor-not-allowed transition-colors", title: "Actions IA", children: [isLoading ? ((0, jsx_runtime_1.jsx)("span", { className: "material-icons text-base animate-spin", children: "sync" })) : ((0, jsx_runtime_1.jsx)("span", { className: "material-icons text-base", children: "auto_awesome" })), (0, jsx_runtime_1.jsx)("span", { children: "IA" }), (0, jsx_runtime_1.jsx)("span", { className: "material-icons text-sm", children: "arrow_drop_down" })] }), !isLoading && ((0, jsx_runtime_1.jsxs)(FixedDropdown, { show: showAIMenu, buttonRef: aiButtonRef, children: [(0, jsx_runtime_1.jsxs)("button", { onClick: () => {
229
232
  onAIAction('rewrite');
230
233
  setShowAIMenu(false);
231
- }, style: { display: 'flex', width: '100%', padding: '8px 16px', textAlign: 'left', fontSize: '14px', backgroundColor: 'transparent', border: 'none', cursor: 'pointer', color: '#374151', alignItems: 'center', gap: '8px' }, onMouseEnter: (e) => e.currentTarget.style.backgroundColor = '#f3f4f6', onMouseLeave: (e) => e.currentTarget.style.backgroundColor = 'transparent', children: [_jsx("span", { className: "material-icons text-base text-blue-500", children: "auto_fix_high" }), "R\u00E9\u00E9crire"] }), _jsxs("button", { onClick: () => {
234
+ }, style: { display: 'flex', width: '100%', padding: '8px 16px', textAlign: 'left', fontSize: '14px', backgroundColor: 'transparent', border: 'none', cursor: 'pointer', color: '#374151', alignItems: 'center', gap: '8px' }, onMouseEnter: (e) => e.currentTarget.style.backgroundColor = '#f3f4f6', onMouseLeave: (e) => e.currentTarget.style.backgroundColor = 'transparent', children: [(0, jsx_runtime_1.jsx)("span", { className: "material-icons text-base text-blue-500", children: "auto_fix_high" }), "R\u00E9\u00E9crire"] }), (0, jsx_runtime_1.jsxs)("button", { onClick: () => {
232
235
  onAIAction('proofread');
233
236
  setShowAIMenu(false);
234
- }, style: { display: 'flex', width: '100%', padding: '8px 16px', textAlign: 'left', fontSize: '14px', backgroundColor: 'transparent', border: 'none', cursor: 'pointer', color: '#374151', alignItems: 'center', gap: '8px' }, onMouseEnter: (e) => e.currentTarget.style.backgroundColor = '#f3f4f6', onMouseLeave: (e) => e.currentTarget.style.backgroundColor = 'transparent', children: [_jsx("span", { className: "material-icons text-base text-green-500", children: "spellcheck" }), "Corriger"] }), _jsxs("button", { onClick: () => {
237
+ }, style: { display: 'flex', width: '100%', padding: '8px 16px', textAlign: 'left', fontSize: '14px', backgroundColor: 'transparent', border: 'none', cursor: 'pointer', color: '#374151', alignItems: 'center', gap: '8px' }, onMouseEnter: (e) => e.currentTarget.style.backgroundColor = '#f3f4f6', onMouseLeave: (e) => e.currentTarget.style.backgroundColor = 'transparent', children: [(0, jsx_runtime_1.jsx)("span", { className: "material-icons text-base text-green-500", children: "spellcheck" }), "Corriger"] }), (0, jsx_runtime_1.jsxs)("button", { onClick: () => {
235
238
  const prompt = window.prompt('Instruction pour l\'IA:');
236
239
  if (prompt) {
237
240
  onAIAction('custom', prompt);
238
241
  }
239
242
  setShowAIMenu(false);
240
- }, style: { display: 'flex', width: '100%', padding: '8px 16px', textAlign: 'left', fontSize: '14px', backgroundColor: 'transparent', border: 'none', cursor: 'pointer', color: '#374151', alignItems: 'center', gap: '8px' }, onMouseEnter: (e) => e.currentTarget.style.backgroundColor = '#f3f4f6', onMouseLeave: (e) => e.currentTarget.style.backgroundColor = 'transparent', children: [_jsx("span", { className: "material-icons text-base text-purple-500", children: "smart_toy" }), "Personnalis\u00E9..."] })] }))] })), onToggleFullscreen && (_jsx("button", { onClick: onToggleFullscreen, className: "p-1.5 text-gray-600 hover:text-gray-900 hover:bg-gray-200 rounded transition-colors", title: isFullscreen ? "Quitter le plein écran" : "Plein écran", children: _jsx("span", { className: "material-icons text-lg", children: isFullscreen ? 'fullscreen_exit' : 'fullscreen' }) }))] }));
243
+ }, style: { display: 'flex', width: '100%', padding: '8px 16px', textAlign: 'left', fontSize: '14px', backgroundColor: 'transparent', border: 'none', cursor: 'pointer', color: '#374151', alignItems: 'center', gap: '8px' }, onMouseEnter: (e) => e.currentTarget.style.backgroundColor = '#f3f4f6', onMouseLeave: (e) => e.currentTarget.style.backgroundColor = 'transparent', children: [(0, jsx_runtime_1.jsx)("span", { className: "material-icons text-base text-purple-500", children: "smart_toy" }), "Personnalis\u00E9..."] })] }))] })), onToggleFullscreen && ((0, jsx_runtime_1.jsx)("button", { onClick: onToggleFullscreen, className: "p-1.5 text-gray-600 hover:text-gray-900 hover:bg-gray-200 rounded transition-colors", title: isFullscreen ? "Quitter le plein écran" : "Plein écran", children: (0, jsx_runtime_1.jsx)("span", { className: "material-icons text-lg", children: isFullscreen ? 'fullscreen_exit' : 'fullscreen' }) }))] }));
241
244
  }
@@ -1,7 +1,10 @@
1
- import { jsx as _jsx } from "react/jsx-runtime";
2
- import { forwardRef } from 'react';
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.MarkdownPreview = void 0;
4
+ const jsx_runtime_1 = require("react/jsx-runtime");
5
+ const react_1 = require("react");
3
6
  // Simple markdown renderer - can be enhanced with react-markdown
4
- export const MarkdownPreview = forwardRef(({ content, className = '' }, ref) => {
7
+ exports.MarkdownPreview = (0, react_1.forwardRef)(({ content, className = '' }, ref) => {
5
8
  // Basic markdown to HTML conversion
6
9
  const renderMarkdown = (md) => {
7
10
  let html = md
@@ -35,6 +38,6 @@ export const MarkdownPreview = forwardRef(({ content, className = '' }, ref) =>
35
38
  html = html.replace(/<p class="mb-3"><\/p>/g, '');
36
39
  return html;
37
40
  };
38
- return (_jsx("div", { ref: ref, className: `prose prose-sm max-w-none select-text ${className}`, dangerouslySetInnerHTML: { __html: renderMarkdown(content) } }));
41
+ return ((0, jsx_runtime_1.jsx)("div", { ref: ref, className: `prose prose-sm max-w-none select-text ${className}`, dangerouslySetInnerHTML: { __html: renderMarkdown(content) } }));
39
42
  });
40
- MarkdownPreview.displayName = 'MarkdownPreview';
43
+ exports.MarkdownPreview.displayName = 'MarkdownPreview';