mirror of
https://github.com/rowyio/rowy.git
synced 2025-12-29 00:16:39 +01:00
add full screen to monaco editors
This commit is contained in:
@@ -1,3 +1,4 @@
|
||||
import { useState } from "react";
|
||||
import {
|
||||
DiffEditor as MonacoDiffEditor,
|
||||
DiffEditorProps,
|
||||
@@ -5,16 +6,18 @@ import {
|
||||
} from "@monaco-editor/react";
|
||||
|
||||
import { useTheme, Box, BoxProps } from "@mui/material";
|
||||
import TrapFocus from "@mui/material/Unstable_TrapFocus";
|
||||
import CircularProgressOptical from "@src/components/CircularProgressOptical";
|
||||
import ResizeBottomRightIcon from "@src/assets/icons/ResizeBottomRight";
|
||||
|
||||
import useMonacoCustomizations, {
|
||||
IUseMonacoCustomizationsProps,
|
||||
} from "./useMonacoCustomizations";
|
||||
import FullScreenButton from "./FullScreenButton";
|
||||
|
||||
export interface IDiffEditorProps
|
||||
extends Partial<DiffEditorProps>,
|
||||
IUseMonacoCustomizationsProps {
|
||||
Omit<IUseMonacoCustomizationsProps, "fullScreen"> {
|
||||
onChange?: EditorProps["onChange"];
|
||||
containerProps?: Partial<BoxProps>;
|
||||
}
|
||||
@@ -34,6 +37,8 @@ export default function DiffEditor({
|
||||
}: IDiffEditorProps) {
|
||||
const theme = useTheme();
|
||||
|
||||
const [fullScreen, setFullScreen] = useState(false);
|
||||
|
||||
const { boxSx } = useMonacoCustomizations({
|
||||
minHeight,
|
||||
disabled,
|
||||
@@ -41,6 +46,7 @@ export default function DiffEditor({
|
||||
extraLibs,
|
||||
diagnosticsOptions,
|
||||
onUnmount,
|
||||
fullScreen,
|
||||
});
|
||||
|
||||
// Needs manual patch since `onMount` prop is not available in `DiffEditor`
|
||||
@@ -55,39 +61,50 @@ export default function DiffEditor({
|
||||
};
|
||||
|
||||
return (
|
||||
<Box sx={{ ...boxSx, ...containerProps?.sx }}>
|
||||
<MonacoDiffEditor
|
||||
language="javascript"
|
||||
loading={<CircularProgressOptical size={20} sx={{ m: 2 }} />}
|
||||
className="editor"
|
||||
{...props}
|
||||
onMount={handleEditorMount}
|
||||
options={
|
||||
{
|
||||
readOnly: disabled,
|
||||
fontFamily: theme.typography.fontFamilyMono,
|
||||
rulers: [80],
|
||||
minimap: { enabled: false },
|
||||
lineNumbersMinChars: 4,
|
||||
lineDecorationsWidth: "18",
|
||||
automaticLayout: true,
|
||||
fixedOverflowWidgets: true,
|
||||
tabSize: 2,
|
||||
...props.options,
|
||||
} as any
|
||||
}
|
||||
/>
|
||||
<TrapFocus open={fullScreen}>
|
||||
<Box
|
||||
sx={{ ...boxSx, ...containerProps?.sx }}
|
||||
style={fullScreen ? { height: "100%" } : {}}
|
||||
>
|
||||
<MonacoDiffEditor
|
||||
language="javascript"
|
||||
loading={<CircularProgressOptical size={20} sx={{ m: 2 }} />}
|
||||
className="editor"
|
||||
{...props}
|
||||
onMount={handleEditorMount}
|
||||
options={
|
||||
{
|
||||
readOnly: disabled,
|
||||
fontFamily: theme.typography.fontFamilyMono,
|
||||
rulers: [80],
|
||||
minimap: { enabled: false },
|
||||
lineNumbersMinChars: 4,
|
||||
lineDecorationsWidth: "18",
|
||||
automaticLayout: true,
|
||||
fixedOverflowWidgets: true,
|
||||
tabSize: 2,
|
||||
...props.options,
|
||||
} as any
|
||||
}
|
||||
/>
|
||||
|
||||
<ResizeBottomRightIcon
|
||||
aria-label="Resize code editor"
|
||||
color="action"
|
||||
sx={{
|
||||
position: "absolute",
|
||||
bottom: 1,
|
||||
right: 1,
|
||||
zIndex: 1,
|
||||
}}
|
||||
/>
|
||||
</Box>
|
||||
<FullScreenButton
|
||||
onClick={() => setFullScreen((f) => !f)}
|
||||
active={fullScreen}
|
||||
style={{ right: 32 }}
|
||||
/>
|
||||
|
||||
<ResizeBottomRightIcon
|
||||
aria-label="Resize code editor"
|
||||
color="action"
|
||||
sx={{
|
||||
position: "absolute",
|
||||
bottom: 1,
|
||||
right: 1,
|
||||
zIndex: 1,
|
||||
}}
|
||||
/>
|
||||
</Box>
|
||||
</TrapFocus>
|
||||
);
|
||||
}
|
||||
|
||||
32
src/components/CodeEditor/FullScreenButton.tsx
Normal file
32
src/components/CodeEditor/FullScreenButton.tsx
Normal file
@@ -0,0 +1,32 @@
|
||||
import { Button, ButtonProps } from "@mui/material";
|
||||
import FullscreenIcon from "@mui/icons-material/Fullscreen";
|
||||
import FullscreenExitIcon from "@mui/icons-material/FullscreenExit";
|
||||
|
||||
export interface IFullScreenButtonProps extends ButtonProps {
|
||||
active: boolean;
|
||||
}
|
||||
|
||||
export default function FullScreenButton({
|
||||
active,
|
||||
...props
|
||||
}: IFullScreenButtonProps) {
|
||||
return (
|
||||
<Button
|
||||
aria-label={`${active ? "Exit" : "Enter"} full screen`}
|
||||
variant={active ? "contained" : "outlined"}
|
||||
color={active ? "secondary" : undefined}
|
||||
{...props}
|
||||
style={{
|
||||
position: "absolute",
|
||||
bottom: 4,
|
||||
right: 16,
|
||||
zIndex: 2,
|
||||
minWidth: 32,
|
||||
padding: 0,
|
||||
...props.style,
|
||||
}}
|
||||
>
|
||||
{active ? <FullscreenExitIcon /> : <FullscreenIcon />}
|
||||
</Button>
|
||||
);
|
||||
}
|
||||
@@ -3,16 +3,18 @@ import Editor, { EditorProps } from "@monaco-editor/react";
|
||||
import type { editor } from "monaco-editor/esm/vs/editor/editor.api";
|
||||
|
||||
import { useTheme, Box, BoxProps } from "@mui/material";
|
||||
import TrapFocus from "@mui/material/Unstable_TrapFocus";
|
||||
import CircularProgressOptical from "@src/components/CircularProgressOptical";
|
||||
import ResizeBottomRightIcon from "@src/assets/icons/ResizeBottomRight";
|
||||
|
||||
import useMonacoCustomizations, {
|
||||
IUseMonacoCustomizationsProps,
|
||||
} from "./useMonacoCustomizations";
|
||||
import FullScreenButton from "./FullScreenButton";
|
||||
|
||||
export interface ICodeEditorProps
|
||||
extends Partial<EditorProps>,
|
||||
IUseMonacoCustomizationsProps {
|
||||
Omit<IUseMonacoCustomizationsProps, "fullScreen"> {
|
||||
value: string;
|
||||
containerProps?: Partial<BoxProps>;
|
||||
|
||||
@@ -44,6 +46,7 @@ export default function CodeEditor({
|
||||
// Store editor value to prevent code editor values not being saved when
|
||||
// Side Drawer is in the middle of a refresh
|
||||
const [initialEditorValue] = useState(value ?? "");
|
||||
const [fullScreen, setFullScreen] = useState(false);
|
||||
|
||||
const { boxSx } = useMonacoCustomizations({
|
||||
minHeight,
|
||||
@@ -52,6 +55,7 @@ export default function CodeEditor({
|
||||
extraLibs,
|
||||
diagnosticsOptions,
|
||||
onUnmount,
|
||||
fullScreen,
|
||||
});
|
||||
|
||||
const onValidate_: EditorProps["onValidate"] = (markers) => {
|
||||
@@ -60,38 +64,50 @@ export default function CodeEditor({
|
||||
};
|
||||
|
||||
return (
|
||||
<Box sx={{ ...boxSx, ...containerProps?.sx }}>
|
||||
<Editor
|
||||
defaultLanguage="javascript"
|
||||
value={initialEditorValue}
|
||||
loading={<CircularProgressOptical size={20} sx={{ m: 2 }} />}
|
||||
className="editor"
|
||||
{...props}
|
||||
onValidate={onValidate_}
|
||||
options={{
|
||||
readOnly: disabled,
|
||||
fontFamily: theme.typography.fontFamilyMono,
|
||||
rulers: [80],
|
||||
minimap: { enabled: false },
|
||||
lineNumbersMinChars: 4,
|
||||
lineDecorationsWidth: 0,
|
||||
automaticLayout: true,
|
||||
fixedOverflowWidgets: true,
|
||||
tabSize: 2,
|
||||
...props.options,
|
||||
}}
|
||||
/>
|
||||
<TrapFocus open={fullScreen}>
|
||||
<Box
|
||||
sx={{ ...boxSx, ...containerProps?.sx }}
|
||||
style={fullScreen ? { height: "100%" } : {}}
|
||||
>
|
||||
<Editor
|
||||
defaultLanguage="javascript"
|
||||
value={initialEditorValue}
|
||||
loading={<CircularProgressOptical size={20} sx={{ m: 2 }} />}
|
||||
className="editor"
|
||||
{...props}
|
||||
onValidate={onValidate_}
|
||||
options={{
|
||||
readOnly: disabled,
|
||||
fontFamily: theme.typography.fontFamilyMono,
|
||||
rulers: [80],
|
||||
minimap: { enabled: false },
|
||||
lineNumbersMinChars: 4,
|
||||
lineDecorationsWidth: 0,
|
||||
automaticLayout: true,
|
||||
fixedOverflowWidgets: true,
|
||||
tabSize: 2,
|
||||
...props.options,
|
||||
}}
|
||||
/>
|
||||
|
||||
<ResizeBottomRightIcon
|
||||
aria-label="Resize code editor"
|
||||
color="action"
|
||||
sx={{
|
||||
position: "absolute",
|
||||
bottom: 1,
|
||||
right: 1,
|
||||
zIndex: 1,
|
||||
}}
|
||||
/>
|
||||
</Box>
|
||||
<FullScreenButton
|
||||
onClick={() => setFullScreen((f) => !f)}
|
||||
active={fullScreen}
|
||||
/>
|
||||
|
||||
{!fullScreen && (
|
||||
<ResizeBottomRightIcon
|
||||
aria-label="Resize code editor"
|
||||
color="action"
|
||||
sx={{
|
||||
position: "absolute",
|
||||
bottom: 1,
|
||||
right: 1,
|
||||
zIndex: 1,
|
||||
}}
|
||||
/>
|
||||
)}
|
||||
</Box>
|
||||
</TrapFocus>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -26,6 +26,9 @@ export interface IUseMonacoCustomizationsProps {
|
||||
extraLibs?: string[];
|
||||
diagnosticsOptions?: languages.typescript.DiagnosticsOptions;
|
||||
onUnmount?: () => void;
|
||||
|
||||
// Internal only
|
||||
fullScreen?: boolean;
|
||||
}
|
||||
|
||||
export default function useMonacoCustomizations({
|
||||
@@ -36,6 +39,8 @@ export default function useMonacoCustomizations({
|
||||
extraLibs,
|
||||
diagnosticsOptions,
|
||||
onUnmount,
|
||||
|
||||
fullScreen,
|
||||
}: IUseMonacoCustomizationsProps) {
|
||||
const theme = useTheme();
|
||||
const { tableState } = useProjectContext();
|
||||
@@ -157,7 +162,7 @@ export default function useMonacoCustomizations({
|
||||
}
|
||||
}, [tableState?.columns, monaco, diagnosticsOptions, extraLibs]);
|
||||
|
||||
const boxSx: SxProps<Theme> = {
|
||||
let boxSx: SxProps<Theme> = {
|
||||
minWidth: 400,
|
||||
minHeight,
|
||||
height: minHeight,
|
||||
@@ -214,5 +219,22 @@ export default function useMonacoCustomizations({
|
||||
},
|
||||
};
|
||||
|
||||
if (fullScreen)
|
||||
boxSx = {
|
||||
...boxSx,
|
||||
position: "fixed",
|
||||
top: 0,
|
||||
left: 0,
|
||||
right: 0,
|
||||
bottom: 0,
|
||||
zIndex: theme.zIndex.tooltip + 1,
|
||||
m: "0 !important",
|
||||
resize: "none",
|
||||
backgroundColor: theme.palette.background.paper,
|
||||
|
||||
borderRadius: 0,
|
||||
"&::after": { display: "none" },
|
||||
};
|
||||
|
||||
return { boxSx };
|
||||
}
|
||||
|
||||
@@ -45,6 +45,9 @@ import SnackbarProgress, {
|
||||
} from "@src/components/SnackbarProgress";
|
||||
import CircularProgressOptical from "@src/components/CircularProgressOptical";
|
||||
|
||||
import CodeEditor from "@src/components/CodeEditor";
|
||||
import DiffEditor from "@src/components/CodeEditor/DiffEditor";
|
||||
|
||||
const typographyVariants = [
|
||||
"h1",
|
||||
"h2",
|
||||
@@ -928,6 +931,9 @@ export default function TestView() {
|
||||
</Stack>
|
||||
|
||||
<LinearProgress />
|
||||
|
||||
<CodeEditor value={`x\n`} />
|
||||
<DiffEditor original={`x\n`} modified="y" />
|
||||
</Stack>
|
||||
</Container>
|
||||
</Navigation>
|
||||
|
||||
Reference in New Issue
Block a user