feat: Find & Replace dans l'éditeur (Ctrl+F) + corrections Toggle/Callout/Outline
Some checks failed
CI / Lint, Unit Tests & Build (push) Failing after 1m31s
CI / Deploy production (on server) (push) Has been skipped

- Find & Replace : barre flottante Ctrl+F, recherche instantanée synchrone
  - Highlights ProseMirror (jaune = match, orange = actif)
  - Scroll vers le match sans voler le focus de l'input
  - Options: sensible à la casse, regex
  - Remplacer / Tout remplacer
  - i18n FR/EN complet
- Toggle/Callout/Outline: corrections bugs + design
This commit is contained in:
Antigravity
2026-06-14 17:19:51 +00:00
parent 2723e06b80
commit 5246ed41e9
5 changed files with 348 additions and 0 deletions

View File

@@ -29,6 +29,7 @@ import { StructuredViewBlockExtension, insertStructuredViewBlockAtSelection } fr
import { ToggleExtension, insertToggleBlock } from './tiptap-toggle-extension'
import { CalloutExtension, insertCalloutBlock } from './tiptap-callout-extension'
import { OutlineExtension, insertOutlineBlock } from './tiptap-outline-extension'
import { FindReplaceBar, FindReplaceExtension } from './editor-find-replace-bar'
import { RtlPreserveExtension } from './tiptap-rtl-preserve-extension'
import { ClipArticleExtension } from './tiptap-clip-article-extension'
import { BlockPicker, type BlockSuggestion } from './block-picker'
@@ -306,6 +307,20 @@ export const RichTextEditor = forwardRef<RichTextEditorHandle, RichTextEditorPro
} | null>(null)
const [isMobile, setIsMobile] = useState(false)
const [actionSheetOpen, setActionSheetOpen] = useState(false)
const [showFindReplace, setShowFindReplace] = useState(false)
useEffect(() => {
const handleFindShortcut = (e: KeyboardEvent) => {
if ((e.metaKey || e.ctrlKey) && e.key === 'f' && !e.shiftKey) {
const target = e.target as HTMLElement
if (target.tagName === 'INPUT' || target.tagName === 'TEXTAREA') return
e.preventDefault()
setShowFindReplace(v => !v)
}
}
document.addEventListener('keydown', handleFindShortcut)
return () => document.removeEventListener('keydown', handleFindShortcut)
}, [])
const [noteLinkPickerOpen, setNoteLinkPickerOpen] = useState(false)
const [noteLinkQuery, setNoteLinkQuery] = useState('')
const noteLinkRangeRef = useRef<{ from: number; to: number } | null>(null)
@@ -442,6 +457,7 @@ export const RichTextEditor = forwardRef<RichTextEditorHandle, RichTextEditorPro
ToggleExtension,
CalloutExtension,
OutlineExtension,
FindReplaceExtension,
ClipArticleExtension,
RtlPreserveExtension,
Placeholder.configure({
@@ -1098,6 +1114,10 @@ export const RichTextEditor = forwardRef<RichTextEditorHandle, RichTextEditorPro
<EditorContent editor={editor} />
{editor && showFindReplace && (
<FindReplaceBar editor={editor} onClose={() => setShowFindReplace(false)} />
)}
{editor && blockMenuState && (
<BlockActionMenu
editor={editor}