refactor: factorisation peek panel — NotePeekPanel réutilisable
Architecture: - components/note-peek/use-note-peek.ts: hook (fetch + state + events) - components/note-peek/note-peek-content.tsx: rendu markdown/richtext/KaTeX - components/note-peek/note-peek-panel.tsx: panel (overlay + inline modes) - components/note-peek/index.ts: exports - lib/use-scroll-to-block.ts: utilitaire scroll vers data-id insights/page.tsx: - ~95 lignes (state + fetch + KaTeX useEffect + AnimatePresence) → 10 lignes - peek.open(noteId) remplace handleNoteClick complexe - <NotePeekPanel mode=overlay /> remplace tout le JSX du panel NotePeekPanel gère: - markdown (MarkdownContent) + richtext (DOMPurify + KaTeX lazy) - RTL (slide gauche pour fa/ar) - prefers-reduced-motion - role=dialog + aria-modal (overlay mode) - loading spinner - bouton Maximize2 + X - renderContent prop pour custom (éditeur read-only)
This commit is contained in:
19
memento-note/lib/use-scroll-to-block.ts
Normal file
19
memento-note/lib/use-scroll-to-block.ts
Normal file
@@ -0,0 +1,19 @@
|
||||
import { useEffect, useRef } from 'react'
|
||||
|
||||
export function useScrollToBlock(
|
||||
scrollRef: React.RefObject<HTMLElement | null>,
|
||||
blockId: string | undefined,
|
||||
deps: React.DependencyList,
|
||||
delay = 450,
|
||||
) {
|
||||
useEffect(() => {
|
||||
if (!blockId || !scrollRef.current) return
|
||||
const timer = window.setTimeout(() => {
|
||||
const escaped = typeof CSS !== 'undefined' && CSS.escape ? CSS.escape(blockId) : blockId
|
||||
const el = scrollRef.current?.querySelector(`[data-id="${escaped}"]`)
|
||||
el?.scrollIntoView({ behavior: 'smooth', block: 'center' })
|
||||
}, delay)
|
||||
return () => window.clearTimeout(timer)
|
||||
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||||
}, [blockId, delay, ...deps])
|
||||
}
|
||||
Reference in New Issue
Block a user