'use client' import React, { useCallback, useEffect, useRef, useState } from 'react' import { createPortal } from 'react-dom' import { AnimatePresence } from 'motion/react' import { getNotebookPickerPosition, NotebookHierarchyPanel, type NotebookPickerItem, } from '@/components/notebook-hierarchy-panel' import { useLanguage } from '@/lib/i18n' type MoveToNotebookPickerProps = { notebooks: NotebookPickerItem[] currentNotebookId?: string | null onSelect: (notebookId: string | null) => void children: React.ReactElement align?: 'start' | 'end' preferDropUp?: boolean } export function MoveToNotebookPicker({ notebooks, currentNotebookId = null, onSelect, children, align = 'end', preferDropUp = false, }: MoveToNotebookPickerProps) { const { t } = useLanguage() const [open, setOpen] = useState(false) const triggerRef = useRef(null) const [panelStyle, setPanelStyle] = useState() const close = useCallback(() => setOpen(false), []) const updatePosition = useCallback(() => { if (!triggerRef.current) return setPanelStyle( getNotebookPickerPosition(triggerRef.current.getBoundingClientRect(), { align, preferDropUp }), ) }, [align, preferDropUp]) useEffect(() => { if (!open) { setPanelStyle(undefined) return } updatePosition() window.addEventListener('scroll', updatePosition, true) window.addEventListener('resize', updatePosition) return () => { window.removeEventListener('scroll', updatePosition, true) window.removeEventListener('resize', updatePosition) } }, [open, updatePosition]) const handleSelect = (notebookId: string | null) => { onSelect(notebookId) close() } const child = React.cloneElement(children, { ref: (node: HTMLElement | null) => { triggerRef.current = node const childRef = (children as React.ReactElement & { ref?: React.Ref }).ref if (typeof childRef === 'function') childRef(node) else if (childRef && typeof childRef === 'object') { ;(childRef as React.MutableRefObject).current = node } }, onClick: (e: React.MouseEvent) => { e.stopPropagation() children.props.onClick?.(e) setOpen((prev) => !prev) }, }) return ( <> {child} {typeof window !== 'undefined' && createPortal( {open && panelStyle && ( <>
handleSelect(id)} onClose={close} showGeneralNotes generalNotesLabel={t('notebookSuggestion.generalNotes') || 'Notes générales'} onSelectGeneralNotes={() => handleSelect(null)} searchPlaceholder={t('notebookSuggestion.filterNotebooks') || 'Filtrer les carnets…'} closeLabel={t('general.close') || 'Fermer'} style={panelStyle} /> )} , document.body, )} ) } type MoveToNotebookPickerPortalProps = { open: boolean onOpenChange: (open: boolean) => void anchorRef: React.RefObject notebooks: NotebookPickerItem[] currentNotebookId?: string | null onSelect: (notebookId: string | null) => void align?: 'start' | 'end' preferDropUp?: boolean } export function MoveToNotebookPickerPortal({ open, onOpenChange, anchorRef, notebooks, currentNotebookId = null, onSelect, align = 'end', preferDropUp = false, }: MoveToNotebookPickerPortalProps) { const { t } = useLanguage() const [panelStyle, setPanelStyle] = useState() useEffect(() => { if (!open || !anchorRef.current) { setPanelStyle(undefined) return } const update = () => { if (!anchorRef.current) return setPanelStyle( getNotebookPickerPosition(anchorRef.current.getBoundingClientRect(), { align, preferDropUp }), ) } update() window.addEventListener('scroll', update, true) window.addEventListener('resize', update) return () => { window.removeEventListener('scroll', update, true) window.removeEventListener('resize', update) } }, [open, anchorRef, align, preferDropUp]) const handleSelect = (notebookId: string | null) => { onSelect(notebookId) onOpenChange(false) } if (typeof window === 'undefined') return null return createPortal( {open && panelStyle && ( <>
onOpenChange(false)} aria-hidden /> handleSelect(id)} onClose={() => onOpenChange(false)} showGeneralNotes generalNotesLabel={t('notebookSuggestion.generalNotes') || 'Notes générales'} onSelectGeneralNotes={() => handleSelect(null)} searchPlaceholder={t('notebookSuggestion.filterNotebooks') || 'Filtrer les carnets…'} closeLabel={t('general.close') || 'Fermer'} style={panelStyle} /> )} , document.body, ) }