/* Copyright 2026 Marimo. All rights reserved. */ import { Fill, Slot, useSlot } from "@marimo-team/react-slotz"; import { useAtom } from "jotai"; import { CrosshairIcon, PinIcon, PinOffIcon, XIcon } from "lucide-react"; import type { PropsWithChildren } from "react"; import { Panel, PanelResizeHandle } from "react-resizable-panels"; import { raf2 } from "@/components/editor/navigation/focus-utils"; import { Button } from "@/components/ui/button"; import { Toggle } from "@/components/ui/toggle"; import { Tooltip } from "@/components/ui/tooltip"; import { SlotNames } from "@/core/slots/slots"; import { useResizeHandle } from "@/hooks/useResizeHandle"; import { cn } from "@/utils/cn"; import { ErrorBoundary } from "../../../boundary/ErrorBoundary"; import { handleDragging } from "../../wrapper/utils"; import { contextAwarePanelOpen, contextAwarePanelOwner, isCellAwareAtom, isPinnedAtom, } from "./atoms"; export const PANEL_TYPES = { ROW_VIEWER: "row-viewer", COLUMN_EXPLORER: "column-explorer", } as const; export type PanelType = (typeof PANEL_TYPES)[keyof typeof PANEL_TYPES]; export const ContextAwarePanel: React.FC = () => { const [owner, setOwner] = useAtom(contextAwarePanelOwner); const [isPanelOpen, setIsPanelOpen] = useAtom(contextAwarePanelOpen); const [isPinned, setIsPinned] = useAtom(isPinnedAtom); const [isCellAware, setIsCellAware] = useAtom(isCellAwareAtom); const closePanel = () => { setOwner(null); setIsPanelOpen(false); }; const slots = useSlot(SlotNames.CONTEXT_AWARE_PANEL); if (slots.length === 0 || !owner || !isPanelOpen) { return null; } const renderModeToggle = () => { return (
setIsPinned(!isPinned)} pressed={isPinned} aria-label={isPinned ? "Unpin panel" : "Pin panel"} > {isPinned ? ( ) : ( )} Follow focused table The panel updates as cells that output tables are focused. Click to fix to the current cell.
) : (
Focus on current table The panel is focused on the current table. Click to update based on which cell is focused.
) } > setIsCellAware(!isCellAware)} pressed={isCellAware} aria-label={isCellAware ? "Follow focused cell" : "Fixed"} > ); }; const renderBody = () => { return (
{renderModeToggle()}
{/* TODO: This usually doesn't trigger, and the whole panel closes */}
); }; if (!isPinned) { return {renderBody()}; } return ( <> {renderBody()} ); }; export const ContextAwarePanelItem: React.FC = ({ children, }) => { return ( {children} ); }; interface ResizableComponentProps { children: React.ReactNode; } const ResizableComponent = ({ children }: ResizableComponentProps) => { const { resizableDivRef, handleRefs, style } = useResizeHandle({ startingWidth: 400, minWidth: 400, maxWidth: 1500, onResize: () => { raf2(() => { window.dispatchEvent(new Event("resize")); }); }, }); return (
{children}
); };