import { type ReactNode, useEffect, useState } from "react"; import { isElectron } from "~/env"; import { useResizableWidth } from "~/hooks/useResizableWidth"; import { cn } from "~/lib/utils"; import { RightPanelResizeHandle } from "./RightPanelResizeHandle"; export type PreviewPanelMode = "inline" | "sheet" | "sidebar" | "embedded"; const PREVIEW_PANEL_WIDTH_STORAGE_KEY = "t3code:preview-panel-width"; const PREVIEW_PANEL_MIN_WIDTH = 360; /** Fraction of the viewport allowed, preserving the remaining space for chat. */ const PREVIEW_PANEL_MAX_WIDTH_FRACTION = 0.7; const PREVIEW_PANEL_DEFAULT_WIDTH = 540; export function getPreviewPanelMaxWidth(viewportWidth: number): number { return Math.floor(viewportWidth * PREVIEW_PANEL_MAX_WIDTH_FRACTION); } /** * Shell for the preview panel. In inline mode the panel is user-resizable * via a drag handle on the left edge; width persists per browser. In * sheet/sidebar modes the parent owns the size. */ export function PreviewPanelShell(props: { mode: PreviewPanelMode; maximized?: boolean; children: ReactNode; }) { const useDragRegion = isElectron && props.mode !== "sheet" && props.mode !== "embedded"; const isInline = props.mode === "inline"; const maxWidth = useViewportClampedMaxWidth(); const { width, handlers } = useResizableWidth({ storageKey: PREVIEW_PANEL_WIDTH_STORAGE_KEY, defaultWidth: PREVIEW_PANEL_DEFAULT_WIDTH, minWidth: PREVIEW_PANEL_MIN_WIDTH, maxWidth, edge: "left", }); return (