'use client' import React, { useState, useMemo, useRef, useCallback, useEffect } from 'react' import { ChevronRight, ChevronDown, Folder, Check } from 'lucide-react' import { createPortal } from 'react-dom' import { AnimatePresence } from 'motion/react' import { getNotebookPickerPosition, NotebookHierarchyPanel, type NotebookPickerItem, } from '@/components/notebook-hierarchy-panel' interface HierarchicalNotebookSelectorProps { notebooks: NotebookPickerItem[] selectedId: string | null onSelect: (id: string) => void className?: string placeholder?: string dropUp?: boolean size?: 'default' | 'sm' } export function HierarchicalNotebookSelector({ notebooks, selectedId, onSelect, className = '', placeholder = 'Select a notebook...', dropUp = false, size = 'default', }: HierarchicalNotebookSelectorProps) { const [isOpen, setIsOpen] = useState(false) const triggerRef = useRef(null) const [panelStyle, setPanelStyle] = useState() const updatePosition = useCallback(() => { if (!triggerRef.current) return setPanelStyle(getNotebookPickerPosition(triggerRef.current.getBoundingClientRect(), { preferDropUp: dropUp })) }, [dropUp]) useEffect(() => { if (!isOpen) { setPanelStyle(undefined) return } updatePosition() window.addEventListener('scroll', updatePosition, true) window.addEventListener('resize', updatePosition) return () => { window.removeEventListener('scroll', updatePosition, true) window.removeEventListener('resize', updatePosition) } }, [isOpen, updatePosition]) const selectedNotebook = notebooks.find((nb) => nb.id === selectedId) const path = useMemo(() => { if (!selectedNotebook) return [] const trail: typeof notebooks = [] let current: typeof notebooks[0] | undefined = selectedNotebook while (current) { trail.unshift(current) if (!current.parentId) break const parent = notebooks.find((nb) => nb.id === current!.parentId) if (!parent) break current = parent } return trail }, [selectedNotebook, notebooks]) return (
setIsOpen((prev) => !prev)} className={`w-full bg-card dark:bg-white/5 border border-border/80 rounded-xl outline-none focus:ring-4 ring-brand-accent/10 focus:border-brand-accent/40 transition-all cursor-pointer text-ink flex items-center gap-3 ${size === 'sm' ? 'px-3 py-2 text-xs' : 'px-4 py-3 text-sm'}`} >
{path.length > 0 ? (
{path.map((item, i) => ( {i > 0 && /} {item.name} ))}
) : ( {placeholder} )}
{isOpen && typeof window !== 'undefined' && panelStyle && createPortal( <>
setIsOpen(false)} aria-hidden /> { onSelect(id) setIsOpen(false) }} onClose={() => setIsOpen(false)} searchPlaceholder={placeholder} footerLabel={`${notebooks.filter((nb) => !nb.trashedAt).length} notebooks`} style={panelStyle} /> , document.body, )}
) }