import "./Toolbar.css"; import { useEffect, useLayoutEffect, useRef, useState } from "react"; import { createPortal } from "react-dom"; export type ToolbarPortalSlot = "breadcrumbs" | "search" | "actions"; export type ToolbarPortalProps = { slot: ToolbarPortalSlot; children: React.ReactNode; }; export function ToolbarPortal({ slot, children }: ToolbarPortalProps) { // Target element IDs: ob-toolbar-breadcrumbs, ob-toolbar-search, ob-toolbar-actions const target = document.getElementById(`ob-toolbar-${slot}`); if (!target) return null; return createPortal(children, target); } export type BreadcrumbItem = { label: string; href?: string; }; export type ToolbarBreadcrumbsProps = { items: BreadcrumbItem[]; }; function BreadcrumbsInner({ items }: ToolbarBreadcrumbsProps) { let [firstVisible, setFirstVisible] = useState(0); let [overflowOpen, setOverflowOpen] = useState(false); let navRef = useRef(null); let listRef = useRef(null); let overflowItemRef = useRef(null); // Detect overflow: increment firstVisible until the list fits within the nav. // Runs after every render so it keeps pushing items into overflow until the // list stops overflowing or only the last item (current page) remains. useLayoutEffect(() => { let nav = navRef.current; let list = listRef.current; if (!nav || !list) return; if (list.scrollWidth > nav.clientWidth && firstVisible < items.length - 1) { setFirstVisible((prev) => prev + 1); } }); // ResizeObserver resets firstVisible to 0 on container resize so that the // overflow calculation starts fresh at the new container width. useEffect(() => { let nav = navRef.current; if (!nav) return; let observer = new ResizeObserver(() => { setFirstVisible(0); }); observer.observe(nav); return () => observer.disconnect(); }, []); // Close the overflow dropdown when the user clicks outside of it. useEffect(() => { if (!overflowOpen) return; function handleClickOutside(event: MouseEvent) { if (overflowItemRef.current && !overflowItemRef.current.contains(event.target as Node)) { setOverflowOpen(false); } } document.addEventListener("mousedown", handleClickOutside); return () => document.removeEventListener("mousedown", handleClickOutside); }, [overflowOpen]); let hiddenItems = items.slice(0, firstVisible); let visibleItems = items.slice(firstVisible); return ( ); } export function ToolbarBreadcrumbs({ items }: ToolbarBreadcrumbsProps) { return ( ); }