media/src/components/common/MonacoEditor.tsx (166 lines of code) (raw):

/** * @author yini-chen * @description 编辑器 */ import { Balloon } from "@alicloud/console-components"; import { Editor } from "@monaco-editor/react"; import { Button, Dropdown, message } from "antd"; import React, { ReactNode } from "react"; import { PontUIService } from "../../service/UIService"; import { DARA_SDK_LANGUAGES, LanguageSwitcher } from "../APIPage/TrySDK/LanguageSwitcher"; import { getEditorLanguage, getEditorMenuItems, getMonacoTheme } from "../utils"; import I18N from "../../utils/I18N"; export class MonacoEditorProps { languageTab?: string; setLanguageTab?: (lang) => void; languageSelector? = true; copyable? = true; header?: React.ReactNode; value? = ""; readOnly? = true; height? = 800 as string | number; languages? = DARA_SDK_LANGUAGES; theme?: string; menuItems?: Array<{ key: string; label: ReactNode | string; codicon?: string; onClick: () => void; externalLink?: string; }> = []; } export const MonacoEditor: React.FC<MonacoEditorProps> = (props) => { const { languageTab, setLanguageTab, languageSelector, languages, copyable, header, value, readOnly, height, menuItems, theme, } = props; const items: Array<{ key: string; label: ReactNode | string; codicon?: string; onClick: () => void; externalLink?: string; }> = [...getEditorMenuItems(value, getEditorLanguage(languageTab)), ...menuItems]; const tabContent = React.useMemo(() => { return value?.length ? ( <div className="tab-content"> <Editor height={height} theme={getMonacoTheme(theme)} options={{ readOnly: readOnly, tabCompletion: "on", minimap: { enabled: false, }, }} // theme='vs-dark' language={getEditorLanguage(languageTab)} value={value} /> </div> ) : null; }, [languageTab, value]); const divRef = React.useRef(null); const [width, setWidth] = React.useState(0); React.useEffect(() => { const handleResize = (entries) => { for (let entry of entries) { setWidth(entry.contentRect.width); } }; const observer = new ResizeObserver(handleResize); if (divRef.current) { observer.observe(divRef.current); } // Clean up observer on unmount return () => { if (divRef.current) { observer.unobserve(divRef.current); } }; }, []); return ( <div className="editor-content"> <div className="operations" ref={divRef}> <div className="left-area"> {languageSelector ? ( <LanguageSwitcher language={languageTab} languages={languages} extra={null} onLanguageChange={(lang) => { setLanguageTab(lang); PontUIService.updateLocalLanguage(lang); }} tabContent={null} ></LanguageSwitcher> ) : null} {header || null} </div> <div className="right-area ml-2"> {copyable ? ( <Balloon closable={false} align="t" trigger={ <Button className="copy-button" onClick={() => { if (navigator.clipboard) { navigator.clipboard.writeText(value); message.success(I18N.ide.main.explorer.copySuccess); } }} > <div className="codicon codicon-copy" /> </Button> } > {I18N.ide.main.explorer.copy} </Balloon> ) : null} {items?.length ? ( <div className="menu-icon"> {width < 500 ? ( <Dropdown menu={{ items }}> <Button onClick={(e) => e.preventDefault()}> <div className="codicon codicon-list-selection" /> </Button> </Dropdown> ) : ( <> {items?.map((item) => { return ( <Balloon closable={false} align="t" trigger={ <Button // className="copy-button" href={item.externalLink ? item.externalLink : ""} target="_blank" onClick={item.onClick} > <div className={`codicon codicon-${item.codicon}`} /> </Button> } > {item.label} </Balloon> ); })} </> )} </div> ) : null} </div> </div> {tabContent} </div> ); }; MonacoEditor.defaultProps = new MonacoEditorProps(); export default MonacoEditor;