diff --git a/apps/react-app/package.json b/apps/react-app/package.json index 8b03596c..ed7cc504 100644 --- a/apps/react-app/package.json +++ b/apps/react-app/package.json @@ -7,12 +7,14 @@ "build": "vite build" }, "dependencies": { + "@codemirror/lang-json": "^6.0.1", "@emotion/css": "^11.10.6", "@fontsource/inter": "^5.0.3", "@fontsource/sanchez": "^5.0.3", "@lemoncode/manfred2html": "*", "@lemoncode/manfred2md": "*", "@lemoncode/manfred2word": "*", + "codemirror": "^6.0.1", "react": "^18.2.0", "react-dom": "^18.2.0", "react-router-dom": "^6.8.1" diff --git a/apps/react-app/src/app.global-styles.ts b/apps/react-app/src/app.global-styles.ts index 26619adf..e0f77b7c 100644 --- a/apps/react-app/src/app.global-styles.ts +++ b/apps/react-app/src/app.global-styles.ts @@ -44,4 +44,22 @@ body { overflow: hidden; box-sizing: border-box; } + & ::-webkit-scrollbar { + width: 8px; + } + + & ::-webkit-scrollbar-track { + background-color: none; + border-radius: 4px; + + &:hover { + background-color: rgba(0, 0, 0, 0.6); + } + } + + & ::-webkit-scrollbar-thumb { + background-color: #9e9e9e; + border-radius: 4px; + } + `; diff --git a/apps/react-app/src/common-app/components/codemirror/codemirror.component.tsx b/apps/react-app/src/common-app/components/codemirror/codemirror.component.tsx new file mode 100644 index 00000000..f2f8e89b --- /dev/null +++ b/apps/react-app/src/common-app/components/codemirror/codemirror.component.tsx @@ -0,0 +1,42 @@ +import React from 'react'; + +import { EditorState } from '@codemirror/state'; +import { json } from '@codemirror/lang-json'; +import { basicSetup } from 'codemirror'; +import { EditorView, ViewUpdate, placeholder } from '@codemirror/view'; + +import { codeMirrorTheme } from './codemirror.styles'; + +interface Props { + value: string; + onChange: (value: string) => void; + className?: string; +} + +export const CodeMirrorComponent: React.FC = props => { + const { value, onChange, className } = props; + const codeRef = React.useRef(null); + const editorView = React.useRef(); + React.useEffect(() => { + if (codeRef.current) { + editorView.current = new EditorView({ + state: EditorState.create({ + doc: value, + extensions: [ + basicSetup, + json(), + EditorView.lineWrapping, + EditorView.updateListener.of((u: ViewUpdate) => onChange(u.state.doc.toString())), + placeholder('Pega aquí tu JSON en formato MAC'), + codeMirrorTheme, + ], + }), + parent: codeRef.current, + }); + } + + return () => editorView.current?.destroy(); + }, []); + + return
; +}; diff --git a/apps/react-app/src/common-app/components/codemirror/codemirror.styles.ts b/apps/react-app/src/common-app/components/codemirror/codemirror.styles.ts new file mode 100644 index 00000000..90536ba0 --- /dev/null +++ b/apps/react-app/src/common-app/components/codemirror/codemirror.styles.ts @@ -0,0 +1,26 @@ +import { theme } from '@/core'; +import { EditorView } from 'codemirror'; + +export const codeMirrorTheme = EditorView.theme({ + '&': { + fontSize: '14px', + flexDirection: 'column', + display: 'flex', + flexGrow: '1', + maxHeight: '40vh', + height: '100%', + width: '100%', + }, + '.cm-scroller': { overflow: 'auto' }, + '.cm-gutterElement': { display: 'none' }, + '.cm content, .cm-gutters,': { + minHeight: '100%', + backgroundColor: '#152128', + color: theme.palette.light[500], + textAlign: 'start', + border: 'none', + }, + '.cm-line > span': { + color: theme.palette.primary[500], + }, +}); diff --git a/apps/react-app/src/common-app/components/codemirror/index.ts b/apps/react-app/src/common-app/components/codemirror/index.ts new file mode 100644 index 00000000..db091091 --- /dev/null +++ b/apps/react-app/src/common-app/components/codemirror/index.ts @@ -0,0 +1 @@ +export * from './codemirror.component'; diff --git a/apps/react-app/src/common-app/components/index.ts b/apps/react-app/src/common-app/components/index.ts index 291de313..00e6f514 100644 --- a/apps/react-app/src/common-app/components/index.ts +++ b/apps/react-app/src/common-app/components/index.ts @@ -6,3 +6,4 @@ export * from './card'; export * from './modal'; export * from './export-config'; export * from './alert-message'; +export * from './codemirror'; diff --git a/apps/react-app/src/pods/template-export/template-export.component.tsx b/apps/react-app/src/pods/template-export/template-export.component.tsx index b1ed94a3..ecef284d 100644 --- a/apps/react-app/src/pods/template-export/template-export.component.tsx +++ b/apps/react-app/src/pods/template-export/template-export.component.tsx @@ -1,7 +1,16 @@ import React from 'react'; import { ExportHTMLSettings } from '@lemoncode/manfred2html'; import { useUserChoiceContext } from '@/core'; -import { Button, Footer, Header, Modal, Navbar, ExportConfig, AlertMessage } from '@/common-app/components'; +import { + Button, + Footer, + Header, + Modal, + Navbar, + ExportConfig, + AlertMessage, + CodeMirrorComponent, +} from '@/common-app/components'; import * as classes from './template-export.styles'; interface Props { @@ -19,9 +28,7 @@ export const TemplateExport: React.FC = props => { const [text, setText] = React.useState(''); const [openSettingsModal, setOpenSettingsModal] = React.useState(false); - const handleChange = (event: React.ChangeEvent) => { - setText(event.target.value); - }; + const handleChange = (value: string) => setText(value); const handleOnExportToWord = () => { setUserChoice({ ...userChoice, manfredJsonContent: text }); @@ -55,12 +62,7 @@ export const TemplateExport: React.FC = props => {
- +