index.tsx 2.2 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889
  1. import React from "react";
  2. import styled from "styled-components";
  3. import MonacoEditor, { loader } from "@monaco-editor/react";
  4. import { ErrorContainer } from "src/components/ErrorContainer/ErrorContainer";
  5. import useConfig from "src/hooks/store/useConfig";
  6. import { Loading } from "src/components/Loading";
  7. import useStored from "src/hooks/store/useStored";
  8. loader.config({
  9. paths: {
  10. vs: "https://microsoft.github.io/monaco-editor/node_modules/monaco-editor/min/vs",
  11. },
  12. });
  13. const StyledEditorWrapper = styled.div`
  14. display: flex;
  15. flex-direction: column;
  16. height: 100%;
  17. overflow: auto;
  18. user-select: none;
  19. `;
  20. const editorOptions = {
  21. formatOnPaste: true,
  22. minimap: {
  23. enabled: false,
  24. },
  25. };
  26. const StyledWrapper = styled.div`
  27. display: grid;
  28. height: calc(100vh - 36px);
  29. grid-template-columns: 100%;
  30. grid-template-rows: minmax(0, 1fr);
  31. `;
  32. export const JsonEditor: React.FC = () => {
  33. const [value, setValue] = React.useState<string | undefined>("");
  34. const [hasError, setHasError] = React.useState(false);
  35. const json = useConfig((state) => state.json);
  36. const lightmode = useStored((state) => state.lightmode);
  37. const setJson = useConfig((state) => state.setJson);
  38. const editorTheme = React.useMemo(
  39. () => (lightmode ? "light" : "vs-dark"),
  40. [lightmode]
  41. );
  42. React.useEffect(() => {
  43. setValue(JSON.stringify(JSON.parse(json), null, 2));
  44. }, [json]);
  45. React.useEffect(() => {
  46. const formatTimer = setTimeout(() => {
  47. try {
  48. if (!value) {
  49. setHasError(false);
  50. return setJson("{}");
  51. }
  52. JSON.parse(value);
  53. setJson(value);
  54. setHasError(false);
  55. } catch (jsonError: any) {
  56. setHasError(true);
  57. }
  58. }, 1500);
  59. return () => clearTimeout(formatTimer);
  60. }, [value, setJson]);
  61. return (
  62. <StyledEditorWrapper>
  63. <ErrorContainer hasError={hasError} />
  64. <StyledWrapper>
  65. <MonacoEditor
  66. height="100%"
  67. defaultLanguage="json"
  68. value={value}
  69. theme={editorTheme}
  70. options={editorOptions}
  71. onChange={setValue}
  72. loading={<Loading message="Loading Editor..." />}
  73. />
  74. </StyledWrapper>
  75. </StyledEditorWrapper>
  76. );
  77. };