diff --git a/memento-note/components/rich-text-editor.tsx b/memento-note/components/rich-text-editor.tsx index 8da4e8f..735e01a 100644 --- a/memento-note/components/rich-text-editor.tsx +++ b/memento-note/components/rich-text-editor.tsx @@ -1,6 +1,7 @@ 'use client' import { useEffect, useRef, useState, useCallback, forwardRef, useImperativeHandle } from 'react' +import { useLanguage } from '@/lib/i18n' import { useEditor, EditorContent } from '@tiptap/react' import { BubbleMenu } from '@tiptap/react/menus' import StarterKit from '@tiptap/starter-kit' @@ -323,6 +324,7 @@ function BubbleToolbar({ editor }: { editor: Editor | null }) { } function SlashCommandMenu({ editor, onInsertImage }: { editor: Editor; onInsertImage: (editor: Editor) => void }) { + const { t } = useLanguage() const [isOpen, setIsOpen] = useState(false) const [query, setQuery] = useState('') const [selectedIndex, setSelectedIndex] = useState(0) @@ -332,6 +334,38 @@ function SlashCommandMenu({ editor, onInsertImage }: { editor: Editor; onInsertI const menuRef = useRef(null) const selectedItemRef = useRef(null) + // Translated category names (keys match slashCommands category field) + const CAT_LABELS: Record = { + 'Basic blocks': t('richTextEditor.slashCatBasic'), + 'Media': t('richTextEditor.slashCatMedia'), + 'Formatting': t('richTextEditor.slashCatFormatting'), + 'IA Note': t('richTextEditor.slashCatAi'), + } + + // Translated command list (keeps same order/icons/shortcuts as global slashCommands) + const localCommands: SlashItem[] = [ + { ...slashCommands[0], title: t('richTextEditor.slashText'), description: t('richTextEditor.slashTextDesc'), category: 'Basic blocks' }, + { ...slashCommands[1], title: t('richTextEditor.slashH1'), description: t('richTextEditor.slashH1Desc'), category: 'Basic blocks' }, + { ...slashCommands[2], title: t('richTextEditor.slashH2'), description: t('richTextEditor.slashH2Desc'), category: 'Basic blocks' }, + { ...slashCommands[3], title: t('richTextEditor.slashH3'), description: t('richTextEditor.slashH3Desc'), category: 'Basic blocks' }, + { ...slashCommands[4], title: t('richTextEditor.slashBullet'), description: t('richTextEditor.slashBulletDesc'), category: 'Basic blocks' }, + { ...slashCommands[5], title: t('richTextEditor.slashNumbered'), description: t('richTextEditor.slashNumberedDesc'), category: 'Basic blocks' }, + { ...slashCommands[6], title: t('richTextEditor.slashTodo'), description: t('richTextEditor.slashTodoDesc'), category: 'Basic blocks' }, + { ...slashCommands[7], title: t('richTextEditor.slashQuote'), description: t('richTextEditor.slashQuoteDesc'), category: 'Basic blocks' }, + { ...slashCommands[8], title: t('richTextEditor.slashCode'), description: t('richTextEditor.slashCodeDesc'), category: 'Basic blocks' }, + { ...slashCommands[9], title: t('richTextEditor.slashDivider'), description: t('richTextEditor.slashDividerDesc'), category: 'Basic blocks' }, + { ...slashCommands[10], title: t('richTextEditor.slashImage'), description: t('richTextEditor.slashImageDesc'), category: 'Media' }, + { ...slashCommands[11], title: t('richTextEditor.slashAlignLeft'), description: t('richTextEditor.slashAlignLeftDesc'), category: 'Formatting' }, + { ...slashCommands[12], title: t('richTextEditor.slashAlignCenter'), description: t('richTextEditor.slashAlignCenterDesc'), category: 'Formatting' }, + { ...slashCommands[13], title: t('richTextEditor.slashAlignRight'), description: t('richTextEditor.slashAlignRightDesc'), category: 'Formatting' }, + { ...slashCommands[14], title: t('richTextEditor.slashSuperscript'), description: t('richTextEditor.slashSuperscriptDesc'), category: 'Formatting' }, + { ...slashCommands[15], title: t('richTextEditor.slashSubscript'), description: t('richTextEditor.slashSubscriptDesc'), category: 'Formatting' }, + { ...slashCommands[16], title: t('richTextEditor.slashClarify'), description: t('richTextEditor.slashClarifyDesc'), category: 'IA Note' }, + { ...slashCommands[17], title: t('richTextEditor.slashShorten'), description: t('richTextEditor.slashShortenDesc'), category: 'IA Note' }, + { ...slashCommands[18], title: t('richTextEditor.slashImprove'), description: t('richTextEditor.slashImproveDesc'), category: 'IA Note' }, + { ...slashCommands[19], title: t('richTextEditor.slashExpand'), description: t('richTextEditor.slashExpandDesc'), category: 'IA Note' }, + ] + const closeMenu = useCallback(() => { setIsOpen(false); setQuery(''); setSelectedIndex(0); setActiveCategory(null) }, []) @@ -364,10 +398,9 @@ function SlashCommandMenu({ editor, onInsertImage }: { editor: Editor; onInsertI }, [editor, closeMenu, deleteSlashText, onInsertImage]) // All category names in order - const allCategories = Array.from(new Set(slashCommands.map(c => c.category || 'Basic blocks'))) + const allCategories = Array.from(new Set(localCommands.map(c => c.category || 'Basic blocks'))) - // Filtered by text query, then optionally by active tab - const textFiltered = slashCommands.filter(c => c.title.toLowerCase().includes(query.toLowerCase()) || c.description.toLowerCase().includes(query.toLowerCase())) + const textFiltered = localCommands.filter(c => c.title.toLowerCase().includes(query.toLowerCase()) || c.description.toLowerCase().includes(query.toLowerCase())) const filtered = activeCategory ? textFiltered.filter(c => (c.category || 'Basic blocks') === activeCategory) : textFiltered const categories = filtered.reduce((acc, item) => { @@ -413,7 +446,11 @@ function SlashCommandMenu({ editor, onInsertImage }: { editor: Editor; onInsertI }, [isOpen, editor, query]) useEffect(() => { - const handleClick = () => { if (isOpen) closeMenu() } + const handleClick = (e: MouseEvent) => { + if (isOpen && menuRef.current && !menuRef.current.contains(e.target as Node)) { + closeMenu() + } + } document.addEventListener('click', handleClick) return () => document.removeEventListener('click', handleClick) }, [isOpen, closeMenu]) @@ -447,7 +484,7 @@ function SlashCommandMenu({ editor, onInsertImage }: { editor: Editor; onInsertI onMouseDown={(e) => e.preventDefault()} onClick={() => { setActiveCategory(null); setSelectedIndex(0) }} > - Tout + {t('richTextEditor.slashTabAll')} {allCategories.filter(cat => categories[cat]).map(cat => (