/* Copyright 2026 Marimo. All rights reserved. */ import { sql } from "@codemirror/lang-sql"; import CodeMirror, { EditorView, type ReactCodeMirrorProps, } from "@uiw/react-codemirror"; import { CopyIcon, EyeIcon, EyeOffIcon, PlusIcon } from "lucide-react"; import { memo, useState } from "react"; import { useAddCodeToNewCell } from "@/components/editor/cell/useAddCell"; import { Button } from "@/components/ui/button"; import { Tooltip } from "@/components/ui/tooltip"; import { toast } from "@/components/ui/use-toast"; import { customPythonLanguageSupport } from "@/core/codemirror/language/languages/python"; import { useTheme } from "@/theme/useTheme"; import { cn } from "@/utils/cn"; import { copyToClipboard } from "@/utils/copy"; import { Events } from "@/utils/events"; const pythonExtensions = [ customPythonLanguageSupport(), EditorView.lineWrapping, ]; const sqlExtensions = [sql(), EditorView.lineWrapping]; /** * A readonly code component that can be used to display code in a readonly state. * * @param props.className - The class name to apply to the component. * @param props.code - The code to display. * @param props.initiallyHideCode - Whether to initially hide the code. * @param props.showHideCode - Whether to show the hide code button. * @param props.insertNewCell - Whether to add a insert new cell button; when clicked will add a new cell next to the current cell or at the end of the file * @param props.language - The language of the code. Default is "python". */ export const ReadonlyCode = memo( ( props: { className?: string; code: string; initiallyHideCode?: boolean; showHideCode?: boolean; showCopyCode?: boolean; insertNewCell?: boolean; language?: "python" | "sql"; } & ReactCodeMirrorProps, ) => { const { theme } = useTheme(); const { code, className, initiallyHideCode, showHideCode = true, showCopyCode = true, insertNewCell, language = "python", ...rest } = props; const [hideCode, setHideCode] = useState(initiallyHideCode); return (
{showHideCode && hideCode && ( setHideCode(false)} /> )}
{showCopyCode && } {insertNewCell && } {showHideCode && !hideCode && ( setHideCode(true)} /> )}
); }, ); ReadonlyCode.displayName = "ReadonlyCode"; const CopyButton = (props: { text: string }) => { const copy = Events.stopPropagation(async () => { await copyToClipboard(props.text); toast({ title: "Copied to clipboard" }); }); return ( ); }; const EyeCloseButton = (props: { onClick: () => void }) => { return ( ); }; export const HideCodeButton = (props: { tooltip?: string; className?: string; onClick: () => void; }) => { return (
); }; const InsertNewCell = (props: { code: string }) => { const addCodeToNewCell = useAddCodeToNewCell(); const handleClick = () => { addCodeToNewCell(props.code); }; return ( ); };