"use client"; import type { AddPanelOptions, DockviewApi, DockviewReadyEvent, IDockviewPanelHeaderProps, IDockviewPanelProps, } from "dockview"; import "@/styles/dockview.css"; import type { LucideIcon } from "lucide-react"; import { useEffect, useMemo, useState } from "react"; import { DockviewReact, themeAbyssSpaced } from "dockview"; interface PanelContent { icon?: LucideIcon; content?: React.ReactNode; autoAdd?: boolean; } interface DockviewProps { storageKey: string; onApiReady?: (api: DockviewApi) => void; options: AddPanelOptions[]; } export default function DockView({ storageKey, onApiReady, options }: DockviewProps) { const [api, setApi] = useState(); const { components, tabComponents } = useMemo(() => { const components: Record< string, React.FunctionComponent> > = {}; const tabComponents: Record< string, React.FunctionComponent> > = {}; options.forEach((option) => { const { id, params } = option; components[id] = () => { const content = params?.content; return <>{content}; }; tabComponents[id] = (props) => { const Icon = params?.icon; return (
{Icon && (
); }; }); return { components, tabComponents }; }, [options]); useEffect(() => { if (!api) return; const disposable = api.onDidLayoutChange(() => { const layout = api.toJSON(); localStorage.setItem(storageKey, JSON.stringify(layout)); }); return () => disposable.dispose(); }, [api, storageKey]); const onReady = (event: DockviewReadyEvent) => { setApi(event.api); onApiReady?.(event.api); let success = false; const serializedLayout = localStorage.getItem(storageKey); if (serializedLayout) { try { const layout = JSON.parse(serializedLayout); event.api.fromJSON(layout); success = true; } catch (error) { console.error("Failed to load layout:", error); localStorage.removeItem(storageKey); } } if (!success) { options.forEach((option) => { const autoAdd = option.params?.autoAdd ?? true; if (!autoAdd) return; event.api.addPanel({ ...option }); }); } }; return ( ); }