diff options
| author | jackyzha0 <[email protected]> | 2021-04-11 10:27:27 -0700 |
|---|---|---|
| committer | jackyzha0 <[email protected]> | 2021-04-11 10:27:27 -0700 |
| commit | 0144bfc9cc6c616a00a8171f3950a75ec948427e (patch) | |
| tree | 101d6c12471d411e9266cffa8e90176aff2e6fdb /frontend | |
| parent | base next bump (diff) | |
| download | ctrl-v-0144bfc9cc6c616a00a8171f3950a75ec948427e.tar.xz ctrl-v-0144bfc9cc6c616a00a8171f3950a75ec948427e.zip | |
base next refactor
Diffstat (limited to 'frontend')
22 files changed, 487 insertions, 489 deletions
diff --git a/frontend/.babelrc b/frontend/.babelrc new file mode 100644 index 0000000..4722ed5 --- /dev/null +++ b/frontend/.babelrc @@ -0,0 +1,15 @@ +{ + "presets": [ + "next/babel" + ], + "plugins": [ + [ + "styled-components", + { + "ssr": true, + "displayName": true, + "preprocess": false + } + ] + ] +} diff --git a/frontend/package.json b/frontend/package.json index e50ce30..1851591 100644 --- a/frontend/package.json +++ b/frontend/package.json @@ -11,7 +11,6 @@ "react-katex": "^2.0.2", "react-markdown": "^4.3.1", "react-modal": "^3.11.2", - "react-router-dom": "^5.2.0", "react-simple-code-editor": "^0.11.0", "react-syntax-highlighter": "^12.2.1", "react-syntax-highlighter-virtualized-renderer": "^1.1.0", @@ -37,5 +36,8 @@ "last 1 firefox version", "last 1 safari version" ] + }, + "devDependencies": { + "babel-plugin-styled-components": "^1.12.0" } } diff --git a/frontend/src/App.js b/frontend/src/App.js index 0a47baa..f00397f 100644 --- a/frontend/src/App.js +++ b/frontend/src/App.js @@ -13,10 +13,7 @@ import ThemeProvider from './theme/ThemeProvider' import GlobalStyle from './theme/GlobalStyle' import {Watermark} from "./components/Watermark"; -const Main = styled.div` - margin-top: 10vh; - padding: 0 20vw 30px 20vw; -` + const GetPasteWithParam = () => { let { hash } = useParams(); diff --git a/frontend/src/components/PasteInfo.js b/frontend/src/components/PasteInfo.js index 6ab5b19..2f912fb 100644 --- a/frontend/src/components/PasteInfo.js +++ b/frontend/src/components/PasteInfo.js @@ -1,8 +1,8 @@ import React from 'react'; import styled from 'styled-components' -import { useHistory } from 'react-router-dom'; import { Theme } from './Inputs' import {Button} from "./Common/Button"; +import {useRouter} from "next/router"; const Bold = styled.span` font-weight: 700 @@ -28,10 +28,10 @@ const Flex = styled.div` ` const PasteInfo = (props) => { - const history = useHistory(); + const router = useRouter() const redirRaw = () => { const redirUrl = `/raw/${props.hash}` - history.push(redirUrl); + router.push(redirUrl); } const renderable = () => { diff --git a/frontend/src/components/modals/PasteModal.js b/frontend/src/components/modals/PasteModal.js index e7dbed2..a0fd309 100644 --- a/frontend/src/components/modals/PasteModal.js +++ b/frontend/src/components/modals/PasteModal.js @@ -1,21 +1,21 @@ import React from 'react'; import Modal from 'react-modal'; import {Form, ModalHeader, modalStyles} from './shared' -import { useHistory } from 'react-router-dom'; +import { useRouter } from 'next/router' import { Text } from '../Inputs' import { useClipboard } from 'use-clipboard-copy'; import {Button} from "../Common/Button"; const PasteModal = (props) => { - const history = useHistory(); - const fullURL = `${window.location.origin}/${props.hash}`; + const fullURL = `https://ctrl-v.app/${props.hash}`; const clipboard = useClipboard({ copiedTimeout: 3000 }); Modal.setAppElement('body'); + const router = useRouter() const redir = (e) => { e.preventDefault(); const redirUrl = `/${props.hash}` - history.push(redirUrl); + router.push(redirUrl); } return ( diff --git a/frontend/src/components/pages/NewPaste.js b/frontend/src/components/pages/NewPaste.js deleted file mode 100644 index 19161da..0000000 --- a/frontend/src/components/pages/NewPaste.js +++ /dev/null @@ -1,150 +0,0 @@ -import React, { useEffect, useState, useRef } from 'react'; -import { Text, Code } from '../Inputs' -import OptionsContainer from '../Options' -import Error from '../Err' -import PasteModal from '../modals/PasteModal' -import styled from 'styled-components' -import CodeRenderer from '../renderers/Code' -import Latex from '../renderers/Latex' -import Markdown from '../renderers/Markdown' -import {Button, SubmitButton} from "../Common/Button"; -import {newPaste} from "../hooks/shared"; - -const Flex = styled.div` - display: flex; - flex-direction: row; -` - -const FlexLeft = styled.div` - flex: 0 0 calc(50% - 1em - 2px); -` - -const FlexRight = styled.div` - flex: 0 0 50%; - max-width: calc(50% - 1em + 2px); - margin-left: 2em; -` - -const PreviewWrapper = styled.div` - margin: 2em; -` - -const NewPaste = () => { - const [title, setTitle] = useState(''); - const [content, setContent] = useState(''); - const [pass, setPass] = useState(''); - const [language, setLanguage] = useState('detect'); - const [expiry, setExpiry] = useState(''); - const [hash, setHash] = useState(''); - const [isPreview, setIsPreview] = useState(false); - const ErrorLabel = useRef(null); - - useEffect(() => { - document.title = title === "" ? `ctrl-v` : `ctrl-v | ${title}`; - }, [title]) - - function handleSubmit(e) { - e.preventDefault(); - - // prevent resubmission - if (!hash) { - newPaste({title, content, language, pass, expiry}) - .then(resp => {setHash(resp.data.hash)}) - .catch((error) => { - const resp = error.response - - // some weird err (e.g. network) - if (!resp) { - ErrorLabel.current.showMessage(error) - return - } - - // some weird err - const errTxt = `${resp.status}: ${resp.data}` - ErrorLabel.current.showMessage(errTxt) - }); - } - } - - function renderPreview() { - const pasteInput = <Code - setContentCallback={setContent} - content={content} - maxLength="100000" /> - - if (isPreview) { - var preview - switch (language) { - case 'latex': - preview = - <PreviewWrapper> - <Latex - content={content} /> - </PreviewWrapper> - break - case 'markdown': - preview = - <PreviewWrapper className='md' > - <Markdown - content={content} /> - </PreviewWrapper> - break - default: - preview = - <CodeRenderer - lang={language} - theme='atom' - content={content} /> - } - - return ( - <Flex> - <FlexLeft> - {pasteInput} - </FlexLeft> - <FlexRight className='preview' > - {preview} - </FlexRight> - </Flex> - ); - } else { - return ( - pasteInput - ); - } - } - - return ( - <form onSubmit={handleSubmit}> - <PasteModal hash={hash} /> - <Text - label="title" - onChange={(e) => {setTitle(e.target.value)}} - value={title} - autoFocus - maxLength="100" - id="titleInput" /> - {renderPreview()} - <OptionsContainer - pass={pass} - expiry={expiry} - lang={language} - onPassChange={(e) => { setPass(e.target.value) }} - onLangChange={(e) => { setLanguage(e.target.value) }} - onExpiryChange={(e) => { setExpiry(e.target.value) }} /> - <div> - <SubmitButton type="submit" value="new paste" /> - {language !== 'detect' && <Button - secondary - type="button" - onClick={() => setIsPreview(!isPreview)}> - preview - </Button>} - </div> - <br /> - <Error ref={ErrorLabel} /> - </form> - ); -} - -export default NewPaste
\ No newline at end of file diff --git a/frontend/src/components/pages/Raw.js b/frontend/src/components/pages/Raw.js deleted file mode 100644 index 23ef6bf..0000000 --- a/frontend/src/components/pages/Raw.js +++ /dev/null @@ -1,16 +0,0 @@ -import React from 'react'; -import styled from 'styled-components' -import {CodeLike} from "../Common/mixins"; -import useFetchPaste from "../hooks/useFetchPaste"; - -const RawText = styled.pre` - ${CodeLike} - padding: 0 1em; -` - -const Raw = ({hash}) => { - const { err, result } = useFetchPaste(hash) - return <RawText>{result?.content || err}</RawText> -} - -export default Raw
\ No newline at end of file diff --git a/frontend/src/components/pages/ViewPaste.js b/frontend/src/components/pages/ViewPaste.js deleted file mode 100644 index bc61314..0000000 --- a/frontend/src/components/pages/ViewPaste.js +++ /dev/null @@ -1,65 +0,0 @@ -import React, { useEffect, useState, useRef } from 'react'; -import Error from '../Err'; -import { Text } from '../Inputs'; -import CodeRenderer from '../renderers/Code' -import PasteInfo from '../PasteInfo'; -import PasswordModal from '../modals/PasswordModal' -import RenderDispatch from '../renderers/RenderDispatch' -import useFetchPaste from "../hooks/useFetchPaste"; - -const ViewPaste = (props) => { - const { err, requiresAuth, validPass, getWithPassword, result } = useFetchPaste(props.hash) - const {content, language, expiry, title} = result ?? {} - const [theme, setTheme] = useState('atom'); - const [isRenderMode, setIsRenderMode] = useState(false); - const [enteredPass, setEnteredPass] = useState(''); - const ErrorLabelRef = useRef(null); - - if (err) { - ErrorLabelRef.current.showMessage(err, -1) - } - - useEffect(() => { - setIsRenderMode(language === 'latex' || language === 'markdown') - }, [language]) - - function getDisplay() { - return isRenderMode ? <RenderDispatch - language={language} - content={content} - /> : <CodeRenderer - content={content} - lang={language} - theme={theme} - id="pasteInput" /> - } - - return ( - <div> - <PasswordModal - hasPass={requiresAuth} - validPass={validPass} - value={enteredPass} - onChange={(e) => setEnteredPass(e.target.value)} - validateCallback={getWithPassword} /> - <Text - label="title" - value={title} - id="titleInput" - readOnly /> - {getDisplay()} - <PasteInfo - hash={props.hash} - lang={language} - theme={theme} - expiry={expiry} - toggleRenderCallback={() => setIsRenderMode(!isRenderMode)} - isRenderMode={isRenderMode} - onChange={(e) => setTheme(e.target.value)} - err={<Error ref={ErrorLabelRef} />} - /> - </div> - ); -} - -export default ViewPaste
\ No newline at end of file diff --git a/frontend/src/components/renderers/Code.js b/frontend/src/components/renderers/Code.js index 29531fc..85fd5ab 100644 --- a/frontend/src/components/renderers/Code.js +++ b/frontend/src/components/renderers/Code.js @@ -1,7 +1,7 @@ import React from 'react'; import SyntaxHighlighter from 'react-syntax-highlighter'; import virtualizedRenderer from 'react-syntax-highlighter-virtualized-renderer'; -import { atomOneLight, ascetic, atomOneDark, dracula, ocean } from 'react-syntax-highlighter/dist/esm/styles/hljs'; +import { atomOneLight, ascetic, atomOneDark, dracula, ocean } from 'react-syntax-highlighter/dist/cjs/styles/hljs'; import styled from 'styled-components' import {Border, CodeLike, DropShadow, Rounded} from "../Common/mixins"; diff --git a/frontend/src/components/renderers/InlineCode.js b/frontend/src/components/renderers/InlineCode.js index 44a3f58..2156503 100644 --- a/frontend/src/components/renderers/InlineCode.js +++ b/frontend/src/components/renderers/InlineCode.js @@ -1,6 +1,6 @@ import React from 'react'; import SyntaxHighlighter from 'react-syntax-highlighter'; -import { atomOneDark } from 'react-syntax-highlighter/dist/esm/styles/hljs'; +import { atomOneDark } from 'react-syntax-highlighter/dist/cjs/styles/hljs'; import { LANGS } from './Code' const MarkdownCodeRenderer = ({language, value}) => { diff --git a/frontend/src/css/index.css b/frontend/src/css/index.css deleted file mode 100644 index 0340813..0000000 --- a/frontend/src/css/index.css +++ /dev/null @@ -1,150 +0,0 @@ -@media all and (max-width: 1000px) { - .lt-content-column { - padding: 0 calc(5vw + 1em) 0 5vw !important; - } -} - -form { - width: 100%; -} - -textarea, input[type=text], input[type=password], .Dropdown-root { - width: 100%; - font-family: 'JetBrains Mono', monospace; - font-size: 0.8em; - padding: calc(0.8em - 1px); - border-radius: 3px; - border: 1px solid #565656; - outline: none; - margin: 1.7em 0; -} - -/* fix weird symbol height in render mode */ -.large-op { - transform: translateY(-0.55em); -} - -.small-op { - transform: translateY(-0.1em); -} - -code, pre { - background: #00000000; - font-family: 'JetBrains Mono', monospace; - padding: initial; - border-radius: 3px; - outline: none; -} - -.Dropdown-root { - cursor: pointer; -} - -.Dropdown-root:hover, .Dropdown-root.is-open { - opacity: 1; -} - -.Dropdown-root + label { - top: 0.5em; - opacity: 0; -} - -.Dropdown-root.is-open + label, .Dropdown-root:hover + label { - opacity: 1; - top: -0.1em; -} - -.Dropdown-placeholder { - width: 5.5em; -} - -.Dropdown-menu { - border-top: 1px solid #111111; - margin-top: 0.5em; - bottom: auto; -} - -.Dropdown-option { - margin-top: 0.5em; - transition: all 0.5s cubic-bezier(.25,.8,.25,1); -} - -.Dropdown-option:hover { - font-weight: 700; - opacity: 0.4; -} - -textarea, input[type=text], input[type=password], .Dropdown-root { - opacity: 0.5; - transition: opacity 0.5s cubic-bezier(.25,.8,.25,1); -} - -textarea:focus, input[type=text]:focus, input[type=password]:focus { - opacity: 1; -} - -input[type=password] { - font-weight: 700; -} - -textarea { - height: max(40vh, 100%); - resize: vertical; - min-height: 40vh; -} - -a { - color: #111111; -} - -input[type=submit], button[type=submit] { - font-family: 'JetBrains Mono', serif; - font-weight: 700; - color: #faf9f5; - background-color: #111111; - padding: 0.8em 2em; - margin: 2em 0; - outline: 0; -} - -button[type=button] { - font-family: 'JetBrains Mono', serif; - font-weight: 700; - width: 8em; - padding: calc(0.8em - 1px) 1.5em; - border-radius: 3px; - color: #111111; - background-color: #faf9f5; - border: 1px solid #565656; - outline: none; - margin: 2em 2em; -} - - -/* fixing markdown renderer */ -.md h3 { - font-weight: bold; -} - -.md hr { - border-top: 1px solid #000; - border-style: solid; -} - -.md code { - background: #00000008; - font-size: 0.8em; -} - -.md pre { - padding: 0.7em; - background: #00000008; -} - -.md pre > code { - background: none; -} - -.md table { - width: 100%; -}
\ No newline at end of file diff --git a/frontend/src/components/hooks/shared.js b/frontend/src/http/shared.js index 00d41e9..00d41e9 100644 --- a/frontend/src/components/hooks/shared.js +++ b/frontend/src/http/shared.js diff --git a/frontend/src/components/hooks/useFetchPaste.js b/frontend/src/http/useFetchPaste.js index c394f5b..ba482f9 100644 --- a/frontend/src/components/hooks/useFetchPaste.js +++ b/frontend/src/http/useFetchPaste.js @@ -1,8 +1,8 @@ import {useEffect, useState} from 'react' import {fetchPaste, fmtDateStr} from './shared' -import {LANGS} from "../renderers/Code"; +import {LANGS} from "../components/renderers/Code"; -export default (id) => { +const useFetchPaste = (id) => { const [loading, setLoading] = useState(true) const [err, setErr] = useState() const [requiresAuth, setRequiresAuth] = useState(false) @@ -64,4 +64,6 @@ export default (id) => { }, [id]) return { loading, err, requiresAuth, validPass, getWithPassword, result } -}
\ No newline at end of file +} + +export default useFetchPaste
\ No newline at end of file diff --git a/frontend/src/pages/[hash].js b/frontend/src/pages/[hash].js new file mode 100644 index 0000000..27f808b --- /dev/null +++ b/frontend/src/pages/[hash].js @@ -0,0 +1,65 @@ +import React, { useEffect, useState, useRef } from 'react'; +import Error from '../components/Err'; +import { Text } from '../components/Inputs'; +import CodeRenderer from '../components/renderers/Code' +import PasteInfo from '../components/PasteInfo'; +import PasswordModal from '../components/modals/PasswordModal' +import RenderDispatch from '../components/renderers/RenderDispatch' +import useFetchPaste from "../http/useFetchPaste"; + +const ViewPaste = (props) => { + const { err, requiresAuth, validPass, getWithPassword, result } = useFetchPaste(props.hash) + const {content, language, expiry, title} = result ?? {} + const [theme, setTheme] = useState('atom'); + const [isRenderMode, setIsRenderMode] = useState(false); + const [enteredPass, setEnteredPass] = useState(''); + const ErrorLabelRef = useRef(null); + + if (err) { + ErrorLabelRef.current.showMessage(err, -1) + } + + useEffect(() => { + setIsRenderMode(language === 'latex' || language === 'markdown') + }, [language]) + + function getDisplay() { + return isRenderMode ? <RenderDispatch + language={language} + content={content} + /> : <CodeRenderer + content={content} + lang={language} + theme={theme} + id="pasteInput" /> + } + + return ( + <div> + <PasswordModal + hasPass={requiresAuth} + validPass={validPass} + value={enteredPass} + onChange={(e) => setEnteredPass(e.target.value)} + validateCallback={getWithPassword} /> + <Text + label="title" + value={title} + id="titleInput" + readOnly /> + {getDisplay()} + <PasteInfo + hash={props.hash} + lang={language} + theme={theme} + expiry={expiry} + toggleRenderCallback={() => setIsRenderMode(!isRenderMode)} + isRenderMode={isRenderMode} + onChange={(e) => setTheme(e.target.value)} + err={<Error ref={ErrorLabelRef} />} + /> + </div> + ); +} + +export default ViewPaste
\ No newline at end of file diff --git a/frontend/src/pages/_app.js b/frontend/src/pages/_app.js new file mode 100644 index 0000000..7e99f01 --- /dev/null +++ b/frontend/src/pages/_app.js @@ -0,0 +1,23 @@ +import React from 'react' +import ThemeProvider from "../theme/ThemeProvider"; +import GlobalStyle from "../theme/GlobalStyle"; +import '../theme/style.css'; +import {Watermark} from "../components/Watermark"; +import styled from "styled-components"; + +const Main = styled.div` + margin-top: 10vh; + padding: 0 20vw 30px 20vw; +` + +const App = ({ Component, pageProps }) => ( + <ThemeProvider> + <GlobalStyle /> + <Watermark/> + <Main id="appElement"> + <Component {...pageProps} /> + </Main> + </ThemeProvider> +) + +export default App
\ No newline at end of file diff --git a/frontend/src/pages/_document.js b/frontend/src/pages/_document.js new file mode 100644 index 0000000..0cbd6a3 --- /dev/null +++ b/frontend/src/pages/_document.js @@ -0,0 +1,30 @@ +import Document from 'next/document' +import { ServerStyleSheet } from 'styled-components' + +export default class StyledDocument extends Document { + static async getInitialProps(ctx) { + const sheet = new ServerStyleSheet() + const originalRenderPage = ctx.renderPage + + try { + ctx.renderPage = () => + originalRenderPage({ + enhanceApp: (App) => (props) => + sheet.collectStyles(<App {...props} />), + }) + + const initialProps = await Document.getInitialProps(ctx) + return { + ...initialProps, + styles: ( + <> + {initialProps.styles} + {sheet.getStyleElement()} + </> + ), + } + } finally { + sheet.seal() + } + } +}
\ No newline at end of file diff --git a/frontend/src/pages/index.js b/frontend/src/pages/index.js new file mode 100644 index 0000000..141ebac --- /dev/null +++ b/frontend/src/pages/index.js @@ -0,0 +1,150 @@ +import React, { useEffect, useState, useRef } from 'react'; +import { Text, Code } from '../components/Inputs' +import OptionsContainer from '../components/Options' +import Error from '../components/Err' +import PasteModal from '../components/modals/PasteModal' +import styled from 'styled-components' +import CodeRenderer from '../components/renderers/Code' +import Latex from '../components/renderers/Latex' +import Markdown from '../components/renderers/Markdown' +import {Button, SubmitButton} from "../components/Common/Button"; +import {newPaste} from "../http/shared"; + +const Flex = styled.div` + display: flex; + flex-direction: row; +` + +const FlexLeft = styled.div` + flex: 0 0 calc(50% - 1em - 2px); +` + +const FlexRight = styled.div` + flex: 0 0 50%; + max-width: calc(50% - 1em + 2px); + margin-left: 2em; +` + +const PreviewWrapper = styled.div` + margin: 2em; +` + +const NewPaste = () => { + const [title, setTitle] = useState(''); + const [content, setContent] = useState(''); + const [pass, setPass] = useState(''); + const [language, setLanguage] = useState('detect'); + const [expiry, setExpiry] = useState(''); + const [hash, setHash] = useState(''); + const [isPreview, setIsPreview] = useState(false); + const ErrorLabel = useRef(null); + + useEffect(() => { + document.title = title === "" ? `ctrl-v` : `ctrl-v | ${title}`; + }, [title]) + + function handleSubmit(e) { + e.preventDefault(); + + // prevent resubmission + if (!hash) { + newPaste({title, content, language, pass, expiry}) + .then(resp => {setHash(resp.data.hash)}) + .catch((error) => { + const resp = error.response + + // some weird err (e.g. network) + if (!resp) { + ErrorLabel.current.showMessage(error) + return + } + + // some weird err + const errTxt = `${resp.status}: ${resp.data}` + ErrorLabel.current.showMessage(errTxt) + }); + } + } + + function renderPreview() { + const pasteInput = <Code + setContentCallback={setContent} + content={content} + maxLength="100000" /> + + if (isPreview) { + var preview + switch (language) { + case 'latex': + preview = + <PreviewWrapper> + <Latex + content={content} /> + </PreviewWrapper> + break + case 'markdown': + preview = + <PreviewWrapper className='md' > + <Markdown + content={content} /> + </PreviewWrapper> + break + default: + preview = + <CodeRenderer + lang={language} + theme='atom' + content={content} /> + } + + return ( + <Flex> + <FlexLeft> + {pasteInput} + </FlexLeft> + <FlexRight className='preview' > + {preview} + </FlexRight> + </Flex> + ); + } else { + return ( + pasteInput + ); + } + } + + return ( + <form onSubmit={handleSubmit}> + <PasteModal hash={hash} /> + <Text + label="title" + onChange={(e) => {setTitle(e.target.value)}} + value={title} + autoFocus + maxLength="100" + id="titleInput" /> + {renderPreview()} + <OptionsContainer + pass={pass} + expiry={expiry} + lang={language} + onPassChange={(e) => { setPass(e.target.value) }} + onLangChange={(e) => { setLanguage(e.target.value) }} + onExpiryChange={(e) => { setExpiry(e.target.value) }} /> + <div> + <SubmitButton type="submit" value="new paste" /> + {language !== 'detect' && <Button + secondary + type="button" + onClick={() => setIsPreview(!isPreview)}> + preview + </Button>} + </div> + <br /> + <Error ref={ErrorLabel} /> + </form> + ); +} + +export default NewPaste
\ No newline at end of file diff --git a/frontend/src/pages/raw/index.js b/frontend/src/pages/raw/index.js new file mode 100644 index 0000000..86db3d4 --- /dev/null +++ b/frontend/src/pages/raw/index.js @@ -0,0 +1,14 @@ +import React from 'react'; +import useFetchPaste from "../../http/useFetchPaste"; +import { useRouter } from 'next/router' + + +export default (req, res) => { + const router = useRouter() + const { hash } = router.query + const { err, result } = useFetchPaste(hash) + res.statusCode = 200 + res.json({ + text: 'Hello World! This is the Next.js starter kit :D', + }) +}
\ No newline at end of file diff --git a/frontend/src/theme/GlobalStyle.js b/frontend/src/theme/GlobalStyle.js index 9fe80a5..94e4b57 100644 --- a/frontend/src/theme/GlobalStyle.js +++ b/frontend/src/theme/GlobalStyle.js @@ -2,10 +2,10 @@ import { createGlobalStyle } from 'styled-components' export default createGlobalStyle` body { - margin: 0; - padding: 0; - background: ${(p) => p.theme.colors.background}; - font-family: 'JetBrains Mono', monospace; - color: ${(p) => p.theme.colors.text}; + margin: 0; + padding: 0; + background: ${(p) => p.theme.colors.background}; + font-family: 'JetBrains Mono', monospace; + color: ${(p) => p.theme.colors.text}; } `
\ No newline at end of file diff --git a/frontend/src/theme/ThemeProvider.js b/frontend/src/theme/ThemeProvider.js index d9edcb0..942bc40 100644 --- a/frontend/src/theme/ThemeProvider.js +++ b/frontend/src/theme/ThemeProvider.js @@ -10,4 +10,6 @@ const theme = { }, } -export default ({ children }) => <ThemeProvider theme={theme}>{children}</ThemeProvider>
\ No newline at end of file +const Provider = ({ children }) => <ThemeProvider theme={theme}>{children}</ThemeProvider> + +export default Provider
\ No newline at end of file diff --git a/frontend/src/theme/style.css b/frontend/src/theme/style.css new file mode 100644 index 0000000..10b955b --- /dev/null +++ b/frontend/src/theme/style.css @@ -0,0 +1,150 @@ +@media all and (max-width: 1000px) { + .lt-content-column { + padding: 0 calc(5vw + 1em) 0 5vw !important; + } +} + +form { + width: 100%; +} + +textarea, input[type=text], input[type=password], .Dropdown-root { + width: 100%; + font-family: 'JetBrains Mono', monospace; + font-size: 0.8em; + padding: calc(0.8em - 1px); + border-radius: 3px; + border: 1px solid #565656; + outline: none; + margin: 1.7em 0; +} + +/* fix weird symbol height in render mode */ +.large-op { + transform: translateY(-0.55em); +} + +.small-op { + transform: translateY(-0.1em); +} + +code, pre { + background: #00000000; + font-family: 'JetBrains Mono', monospace; + padding: initial; + border-radius: 3px; + outline: none; +} + +.Dropdown-root { + cursor: pointer; +} + +.Dropdown-root:hover, .Dropdown-root.is-open { + opacity: 1; +} + +.Dropdown-root + label { + top: 0.5em; + opacity: 0; +} + +.Dropdown-root.is-open + label, .Dropdown-root:hover + label { + opacity: 1; + top: -0.1em; +} + +.Dropdown-placeholder { + width: 5.5em; +} + +.Dropdown-menu { + border-top: 1px solid #111111; + margin-top: 0.5em; + bottom: auto; +} + +.Dropdown-option { + margin-top: 0.5em; + transition: all 0.5s cubic-bezier(.25,.8,.25,1); +} + +.Dropdown-option:hover { + font-weight: 700; + opacity: 0.4; +} + +textarea, input[type=text], input[type=password], .Dropdown-root { + opacity: 0.5; + transition: opacity 0.5s cubic-bezier(.25,.8,.25,1); +} + +textarea:focus, input[type=text]:focus, input[type=password]:focus { + opacity: 1; +} + +input[type=password] { + font-weight: 700; +} + +textarea { + height: max(40vh, 100%); + resize: vertical; + min-height: 40vh; +} + +a { + color: #111111; +} + +input[type=submit], button[type=submit] { + font-family: 'JetBrains Mono', serif; + font-weight: 700; + color: #faf9f5; + background-color: #111111; + padding: 0.8em 2em; + margin: 2em 0; + outline: 0; +} + +button[type=button] { + font-family: 'JetBrains Mono', serif; + font-weight: 700; + width: 8em; + padding: calc(0.8em - 1px) 1.5em; + border-radius: 3px; + color: #111111; + background-color: #faf9f5; + border: 1px solid #565656; + outline: none; + margin: 2em 2em; +} + + +/* fixing markdown renderer */ +.md h3 { + font-weight: bold; +} + +.md hr { + border-top: 1px solid #000; + border-style: solid; +} + +.md code { + background: #00000008; + font-size: 0.8em; +} + +.md pre { + padding: 0.7em; + background: #00000008; +} + +.md pre > code { + background: none; +} + +.md table { + width: 100%; +}
\ No newline at end of file diff --git a/frontend/yarn.lock b/frontend/yarn.lock index a38a3c1..f1be868 100644 --- a/frontend/yarn.lock +++ b/frontend/yarn.lock @@ -103,7 +103,7 @@ dependencies: regenerator-runtime "^0.13.4" -"@babel/runtime@^7.1.2", "@babel/runtime@^7.3.1", "@babel/runtime@^7.5.5", "@babel/runtime@^7.7.2": +"@babel/runtime@^7.3.1", "@babel/runtime@^7.7.2": version "7.10.1" resolved "https://registry.yarnpkg.com/@babel/runtime/-/runtime-7.10.1.tgz#b6eb75cac279588d3100baecd1b9894ea2840822" integrity sha512-nQbbCbQc9u/rpg1XCxoMYQTbSMVZjCDxErQ1ClCn9Pvcmv1lGads19ep0a2VsEiIJeHqjZley6EQGEC3Yo1xMA== @@ -344,6 +344,16 @@ axios@^0.21.1: babel-plugin-syntax-jsx "^6.18.0" lodash "^4.17.11" +babel-plugin-styled-components@^1.12.0: + version "1.12.0" + resolved "https://registry.yarnpkg.com/babel-plugin-styled-components/-/babel-plugin-styled-components-1.12.0.tgz#1dec1676512177de6b827211e9eda5a30db4f9b9" + integrity sha512-FEiD7l5ZABdJPpLssKXjBUJMYqzbcNzBowfXDCdJhOpbhWiewapUaY+LZGT8R4Jg2TwOjGjG4RKeyrO5p9sBkA== + dependencies: + "@babel/helper-annotate-as-pure" "^7.0.0" + "@babel/helper-module-imports" "^7.0.0" + babel-plugin-syntax-jsx "^6.18.0" + lodash "^4.17.11" + [email protected], babel-plugin-syntax-jsx@^6.18.0: version "6.18.0" resolved "https://registry.yarnpkg.com/babel-plugin-syntax-jsx/-/babel-plugin-syntax-jsx-6.18.0.tgz#0af32a9a6e13ca7a3fd5069e62d7b0f58d0d8946" @@ -1149,18 +1159,6 @@ highlight.js@~9.15.0, highlight.js@~9.15.1: resolved "https://registry.yarnpkg.com/highlight.js/-/highlight.js-9.15.10.tgz#7b18ed75c90348c045eef9ed08ca1319a2219ad2" integrity sha512-RoV7OkQm0T3os3Dd2VHLNMoaoDVx77Wygln3n9l5YV172XonWG6rgQD3XnF/BuFFZw9A0TJgmMSO8FEWQgvcXw== -history@^4.9.0: - version "4.10.1" - resolved "https://registry.yarnpkg.com/history/-/history-4.10.1.tgz#33371a65e3a83b267434e2b3f3b1b4c58aad4cf3" - integrity sha512-36nwAD620w12kuzPAsyINPWJqlNbij+hpK1k9XRloDtym8mxzGYl2c17LnV6IAGB2Dmg4tEa7G7DlawS0+qjew== - dependencies: - "@babel/runtime" "^7.1.2" - loose-envify "^1.2.0" - resolve-pathname "^3.0.0" - tiny-invariant "^1.0.2" - tiny-warning "^1.0.0" - value-equal "^1.0.1" - hmac-drbg@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/hmac-drbg/-/hmac-drbg-1.0.1.tgz#d2745701025a6c775a6c545793ed502fc0c649a1" @@ -1170,7 +1168,7 @@ hmac-drbg@^1.0.1: minimalistic-assert "^1.0.0" minimalistic-crypto-utils "^1.0.1" -hoist-non-react-statics@^3.0.0, hoist-non-react-statics@^3.1.0: +hoist-non-react-statics@^3.0.0: version "3.3.2" resolved "https://registry.yarnpkg.com/hoist-non-react-statics/-/hoist-non-react-statics-3.3.2.tgz#ece0acaf71d62c2969c2ec59feff42a4b1a85b45" integrity sha512-/gGivxi8JPKWNm/W0jSmzcMPpfpPLc3dY/6GxhX2hQ9iGj3aDfklV4ET7NjKpSinLpJ5vafa9iiGIEZg10SfBw== @@ -1397,11 +1395,6 @@ is-word-character@^1.0.0: resolved "https://registry.yarnpkg.com/is-word-character/-/is-word-character-1.0.4.tgz#ce0e73216f98599060592f62ff31354ddbeb0230" integrity sha512-5SMO8RVennx3nZrqtKwCGyyetPE9VDba5ugvKLaD4KopPG5kR4mQ7tNt/r7feL5yt5h3lpuBbIUmCOG2eSzXHA== - version "0.0.1" - resolved "https://registry.yarnpkg.com/isarray/-/isarray-0.0.1.tgz#8a18acfca9a8f4177e09abfc6038939b05d1eedf" - integrity sha1-ihis/Kmo9Bd+Cav8YDiTmwXR7t8= - [email protected], isarray@^1.0.0, isarray@~1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/isarray/-/isarray-1.0.0.tgz#bb935d48582cba168c06834957a54a3e07124f11" @@ -1486,7 +1479,7 @@ lodash@^4.17.11, lodash@^4.17.13: resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.15.tgz#b447f6670a0455bbfeedd11392eff330ea097548" integrity sha512-8xOcRHvCjnocdS5cpwXQXVzmmh5e5+saE2QGoeQmbKmRS6J3VQppPOIt0MnmE+4xlZoumy0GPG0D0MVIQbNA1A== -loose-envify@^1.0.0, loose-envify@^1.1.0, loose-envify@^1.2.0, loose-envify@^1.3.1, loose-envify@^1.4.0: +loose-envify@^1.0.0, loose-envify@^1.1.0, loose-envify@^1.4.0: version "1.4.0" resolved "https://registry.yarnpkg.com/loose-envify/-/loose-envify-1.4.0.tgz#71ee51fa7be4caec1a63839f7e682d8132d30caf" integrity sha512-lyuxPGr/Wfhrlem2CL/UcnUc1zcqKAImBDzukY7Y5F/yQiNdko6+fRLevlw1HgMySw7f611UIY408EtxRSoK3Q== @@ -1555,14 +1548,6 @@ miller-rabin@^4.0.0: bn.js "^4.0.0" brorand "^1.0.1" -mini-create-react-context@^0.4.0: - version "0.4.0" - resolved "https://registry.yarnpkg.com/mini-create-react-context/-/mini-create-react-context-0.4.0.tgz#df60501c83151db69e28eac0ef08b4002efab040" - integrity sha512-b0TytUgFSbgFJGzJqXPKCFCBWigAjpjo+Fl7Vf7ZbKRDptszpppKxXH6DRXEABZ/gcEQczeb0iZ7JvL8e8jjCA== - dependencies: - "@babel/runtime" "^7.5.5" - tiny-warning "^1.0.3" - minimalistic-assert@^1.0.0, minimalistic-assert@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/minimalistic-assert/-/minimalistic-assert-1.0.1.tgz#2e194de044626d4a10e7f7fbc00ce73e83e4d5c7" @@ -1814,13 +1799,6 @@ path-exists@^4.0.0: resolved "https://registry.yarnpkg.com/path-exists/-/path-exists-4.0.0.tgz#513bdbe2d3b95d7762e8c1137efa195c6c61b5b3" integrity sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w== -path-to-regexp@^1.7.0: - version "1.8.0" - resolved "https://registry.yarnpkg.com/path-to-regexp/-/path-to-regexp-1.8.0.tgz#887b3ba9d84393e87a0a0b9f4cb756198b53548a" - integrity sha512-n43JRhlUKUAlibEJhPeir1ncUID16QnEjNpwzNdO3Lm4ywrBpBZ5oLD0I6br9evr1Y9JTqwRtAh7JLoOzAQdVA== - dependencies: - isarray "0.0.1" - pbkdf2@^3.0.3: version "3.1.2" resolved "https://registry.yarnpkg.com/pbkdf2/-/pbkdf2-3.1.2.tgz#dd822aa0887580e52f1a039dc3eda108efae3075" @@ -2009,7 +1987,7 @@ react-dropdown@^1.7.0: dependencies: classnames "^2.2.3" [email protected], react-is@^16.6.0, react-is@^16.7.0, react-is@^16.8.1, react-is@^16.8.6: [email protected], react-is@^16.7.0, react-is@^16.8.1, react-is@^16.8.6: version "16.13.1" resolved "https://registry.yarnpkg.com/react-is/-/react-is-16.13.1.tgz#789729a4dc36de2999dc156dd6c1d9c18cea56a4" integrity sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ== @@ -2055,35 +2033,6 @@ [email protected]: resolved "https://registry.yarnpkg.com/react-refresh/-/react-refresh-0.8.3.tgz#721d4657672d400c5e3c75d063c4a85fb2d5d68f" integrity sha512-X8jZHc7nCMjaCqoU+V2I0cOhNW+QMBwSUkeXnTi8IPe6zaRWfn60ZzvFDZqWPfmSJfjub7dDW1SP0jaHWLu/hg== -react-router-dom@^5.2.0: - version "5.2.0" - resolved "https://registry.yarnpkg.com/react-router-dom/-/react-router-dom-5.2.0.tgz#9e65a4d0c45e13289e66c7b17c7e175d0ea15662" - integrity sha512-gxAmfylo2QUjcwxI63RhQ5G85Qqt4voZpUXSEqCwykV0baaOTQDR1f0PmY8AELqIyVc0NEZUj0Gov5lNGcXgsA== - dependencies: - "@babel/runtime" "^7.1.2" - history "^4.9.0" - loose-envify "^1.3.1" - prop-types "^15.6.2" - react-router "5.2.0" - tiny-invariant "^1.0.2" - tiny-warning "^1.0.0" - - version "5.2.0" - resolved "https://registry.yarnpkg.com/react-router/-/react-router-5.2.0.tgz#424e75641ca8747fbf76e5ecca69781aa37ea293" - integrity sha512-smz1DUuFHRKdcJC0jobGo8cVbhO3x50tCL4icacOlcwDOEQPq4TMqwx3sY1TP+DvtTgz4nm3thuo7A+BK2U0Dw== - dependencies: - "@babel/runtime" "^7.1.2" - history "^4.9.0" - hoist-non-react-statics "^3.1.0" - loose-envify "^1.3.1" - mini-create-react-context "^0.4.0" - path-to-regexp "^1.7.0" - prop-types "^15.6.2" - react-is "^16.6.0" - tiny-invariant "^1.0.2" - tiny-warning "^1.0.0" - react-simple-code-editor@^0.11.0: version "0.11.0" resolved "https://registry.yarnpkg.com/react-simple-code-editor/-/react-simple-code-editor-0.11.0.tgz#bb57c7c29b570f2ab229872599eac184f5bc673c" @@ -2217,11 +2166,6 @@ [email protected]: resolved "https://registry.yarnpkg.com/replace-ext/-/replace-ext-1.0.0.tgz#de63128373fcbf7c3ccfa4de5a480c45a67958eb" integrity sha1-3mMSg3P8v3w8z6TeWkgMRaZ5WOs= -resolve-pathname@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/resolve-pathname/-/resolve-pathname-3.0.0.tgz#99d02224d3cf263689becbb393bc560313025dcd" - integrity sha512-C7rARubxI8bXFNB/hqcp/4iUeIXJhJZvFPFPiSPRnhU5UPxzMFIl+2E6yY6c4k9giDJAhtV+enfA+G89N6Csng== - ripemd160@^2.0.0, ripemd160@^2.0.1: version "2.0.2" resolved "https://registry.yarnpkg.com/ripemd160/-/ripemd160-2.0.2.tgz#a1c1a6f624751577ba5d07914cbc92850585890c" @@ -2501,16 +2445,6 @@ tiny-emitter@^2.0.0: resolved "https://registry.yarnpkg.com/tiny-emitter/-/tiny-emitter-2.1.0.tgz#1d1a56edfc51c43e863cbb5382a72330e3555423" integrity sha512-NB6Dk1A9xgQPMoGqC5CVXn123gWyte215ONT5Pp5a0yt4nlEoO1ZWeCwpncaekPHXO60i47ihFnZPiRPjRMq4Q== -tiny-invariant@^1.0.2: - version "1.1.0" - resolved "https://registry.yarnpkg.com/tiny-invariant/-/tiny-invariant-1.1.0.tgz#634c5f8efdc27714b7f386c35e6760991d230875" - integrity sha512-ytxQvrb1cPc9WBEI/HSeYYoGD0kWnGEOR8RY6KomWLBVhqz0RgTwVO9dLrGz7dC+nN9llyI7OKAgRq8Vq4ZBSw== - -tiny-warning@^1.0.0, tiny-warning@^1.0.3: - version "1.0.3" - resolved "https://registry.yarnpkg.com/tiny-warning/-/tiny-warning-1.0.3.tgz#94a30db453df4c643d0fd566060d60a875d84754" - integrity sha512-lBN9zLN/oAf68o3zNXYrdCt1kP8WsiGW8Oo2ka41b2IM5JL/S1CTyX1rW0mb/zSuJun0ZUrDxx4sqvYS2FWzPA== - to-arraybuffer@^1.0.0: version "1.0.1" resolved "https://registry.yarnpkg.com/to-arraybuffer/-/to-arraybuffer-1.0.1.tgz#7d229b1fcc637e466ca081180836a7aabff83f43" @@ -2699,11 +2633,6 @@ util@^0.11.0: dependencies: inherits "2.0.3" -value-equal@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/value-equal/-/value-equal-1.0.1.tgz#1e0b794c734c5c0cade179c437d356d931a34d6c" - integrity sha512-NOJ6JZCAWr0zlxZt+xqCHNTEKOsrks2HQd4MqhP1qy4z1SkbEP467eNx6TgDKXMvUOb+OENfJCZwM+16n7fRfw== - vfile-location@^2.0.0: version "2.0.6" resolved "https://registry.yarnpkg.com/vfile-location/-/vfile-location-2.0.6.tgz#8a274f39411b8719ea5728802e10d9e0dff1519e" |