import type {SandpackInitMode} from "@codesandbox/sandpack-react"; import * as React from "react"; import {FileTabs, useSandpack, useActiveCode, SandpackStack} from "@codesandbox/sandpack-react"; import {Button} from "@nextui-org/react"; import scrollIntoView from "scroll-into-view-if-needed"; import {clsx} from "@nextui-org/shared-utils"; import {Language} from "prism-react-renderer"; import {HighlightedLines} from "./types"; import {Decorators} from "./types"; import {Codeblock} from "@/components/docs/components"; export interface CodeViewerProps { showTabs?: boolean; showLineNumbers?: boolean; /** * Provides a way to draw or style a piece of the content. */ decorators?: Decorators; code?: string; highlightedLines?: HighlightedLines; wrapContent?: boolean; defaultExpanded?: boolean; /** * This provides a way to control how some components are going to * be initialized on the page. The CodeEditor and the Preview components * are quite expensive and might overload the memory usage, so this gives * a certain control of when to initialize them. */ initMode?: SandpackInitMode; containerRef?: React.RefObject; } const INITIAL_HEIGHT = "200px"; export const SandpackCodeViewer = React.forwardRef( ({showTabs, code: propCode, defaultExpanded = false, highlightedLines, containerRef}, ref) => { const {sandpack} = useSandpack(); const {code} = useActiveCode(); const {activeFile} = sandpack; const [isExpanded, setIsExpanded] = React.useState(defaultExpanded); // const id = React.useId(); // hack to make sure we re-render the code editor and change current file // TODO: open an issue on sandpack-react // const [internalKey, setInternalKey] = React.useState(() => id); const lineCountRef = React.useRef<{[key: string]: number}>({}); if (!lineCountRef.current[activeFile]) { lineCountRef.current[activeFile] = code.split("\n").length; } const shouldShowTabs = showTabs ?? sandpack.visibleFilesFromProps.length > 1; const lineCount = lineCountRef.current[activeFile]; const isExpandable = lineCount > 7 || isExpanded; const fileExt = activeFile.split(".").pop() as Language; // const isAppFile = activeFile.includes("App"); React.useEffect(() => { if (containerRef && containerRef?.current !== null && isExpandable) { containerRef.current.style.height = INITIAL_HEIGHT; } }, [containerRef]); // React.useEffect(() => { // setInternalKey(getId()); // }, [propCode, code]); React.useEffect(() => { if (defaultExpanded && containerRef && containerRef?.current !== null) { const container = containerRef?.current; container.style.height = "auto"; } }, [defaultExpanded]); const handleExpand = () => { const nextIsExpanded = !isExpanded; setIsExpanded(nextIsExpanded); if (containerRef && containerRef?.current !== null) { const container = containerRef?.current; if (nextIsExpanded) { container.style.height = "auto"; } else { container.style.height = INITIAL_HEIGHT; scrollIntoView(container, { behavior: "smooth", scrollMode: "if-needed", block: "center", }); } } }; return ( <>
{shouldShowTabs ? : null}
{/* * Disabled in favor of Codeblock due to performance issues & font size on ios * */}
{isExpandable && (
)} ); }, ); SandpackCodeViewer.displayName = "SandpackCodeViewer"; export default SandpackCodeViewer;