diff --git a/package.json b/package.json index ecc866c..f68ec84 100644 --- a/package.json +++ b/package.json @@ -19,8 +19,9 @@ "react-dom": "^16.5.0", "react-dropdown": "^1.6.2", "react-dropzone": "^5.0.1", + "react-loadable": "^5.5.0", "react-scripts": "1.1.5", - "styled-components": "^4.0.0-beta.0-2" + "styled-components": "^4.0.0-beta.5" }, "scripts": { "analyze": "source-map-explorer build/static/js/main.*", diff --git a/src/App.js b/src/App.js index 3235e58..40fa164 100644 --- a/src/App.js +++ b/src/App.js @@ -2,7 +2,7 @@ import React, { PureComponent } from "react"; import { ThemeProvider } from "styled-components"; import Grid from "hedron"; -import Editor from "./containers/Editor"; +import Editor from "./containers/Editor/Async"; import Header from "./components/Header"; import { downloadMarkdown } from "./utils"; @@ -32,16 +32,12 @@ export default class App extends PureComponent { markdown: "", theme, // TODO: implement a less ugly method to handle this require - theme_data: require(`./styles/themes/${theme}`).default, + theme_data: require(`./styles/themes/${theme}`).default }; // bind(this) allows `this` to be used from within our functions this.download = this.download.bind(this); this.editorChanged = this.editorChanged.bind(this); - - // Initialize all the themes - // TODO: figure out how to avoid loading themes until they're changed - config.themes.forEach(theme => require(`brace/theme/${theme.value}`)); } componentDidMount() { @@ -61,7 +57,7 @@ export default class App extends PureComponent { this.setState( { theme: theme.value, - theme_data: require(`./styles/themes/${theme.value}`).default, + theme_data: require(`./styles/themes/${theme.value}`).default }, () => localStorage.setItem("theme", theme.value) ); @@ -104,6 +100,7 @@ export default class App extends PureComponent { diff --git a/src/components/LoadingState/Wrapper.js b/src/components/LoadingState/Wrapper.js new file mode 100644 index 0000000..569129a --- /dev/null +++ b/src/components/LoadingState/Wrapper.js @@ -0,0 +1,48 @@ +import styled from "styled-components"; + +const Wrapper = styled.div` + position: absolute; + top: 0; + width: 100%; + height: 100%; + display: flex; + align-items: center; + justify-content: center; + background: ${props => props.theme.header_background}; + + div { + display: inline-block; + position: relative; + width: 64px; + height: 64px; + } + div span { + position: absolute; + border: 4px solid #fff; + opacity: 1; + border-radius: 50%; + animation: lds-ripple 1s cubic-bezier(0, 0.2, 0.8, 1) infinite; + } + div span:nth-child(2) { + animation-delay: -0.5s; + } + + @keyframes lds-ripple { + 0% { + top: 28px; + left: 28px; + width: 0; + height: 0; + opacity: 1; + } + 100% { + top: -1px; + left: -1px; + width: 58px; + height: 58px; + opacity: 0; + } + } +`; + +export default Wrapper; diff --git a/src/components/LoadingState/index.js b/src/components/LoadingState/index.js new file mode 100644 index 0000000..98dcb02 --- /dev/null +++ b/src/components/LoadingState/index.js @@ -0,0 +1,14 @@ +import React from "react"; + +import Wrapper from "./Wrapper"; + +const LoadingState = () => ( + +
+ + +
+
+); + +export default LoadingState; diff --git a/src/components/Preview/index.js b/src/components/Preview/index.js index bc78a43..e9e0c46 100644 --- a/src/components/Preview/index.js +++ b/src/components/Preview/index.js @@ -11,4 +11,5 @@ export default styled(Grid.Box)` overflow: auto; word-wrap: break-word; padding: 5px 25px; + background: white; `; diff --git a/src/containers/Editor/Async.js b/src/containers/Editor/Async.js new file mode 100644 index 0000000..e743274 --- /dev/null +++ b/src/containers/Editor/Async.js @@ -0,0 +1,11 @@ +import React from "react"; +import Loadable from "react-loadable"; + +import LoadingState from "../../components/LoadingState"; + +const EditorAsync = Loadable({ + loader: () => import("./"), + loading: LoadingState +}); + +export default EditorAsync; diff --git a/src/containers/Editor/index.js b/src/containers/Editor/index.js index 84cb29a..195e4f9 100644 --- a/src/containers/Editor/index.js +++ b/src/containers/Editor/index.js @@ -24,7 +24,7 @@ class Editor extends PureComponent { super(props); this.state = { - code: null, + code: null }; } componentWillMount() { @@ -32,6 +32,14 @@ class Editor extends PureComponent { this.onDrop = this.onDrop.bind(this); } + componentDidMount = () => { + if (typeof this.props.themes === "object") { + // Initialize all the themes + // TODO: figure out how to avoid loading themes until they're changed + this.props.themes.forEach(theme => require(`brace/theme/${theme.value}`)); + } + }; + setTheme = theme => { require(`brace/theme/${theme}`); }; @@ -57,7 +65,7 @@ class Editor extends PureComponent { let options = { fontFamily: "Monaco, monospace", showLineNumbers: false, - showGutter: false, + showGutter: false }; return ( @@ -65,6 +73,7 @@ class Editor extends PureComponent { {window && ( diff --git a/src/styles/global.js b/src/styles/global.js index f0ff352..66c524c 100644 --- a/src/styles/global.js +++ b/src/styles/global.js @@ -6,5 +6,11 @@ export default createGlobalStyle` padding: 0; font-family: 'Inter UI', sans-serif; font-weight: 300; + background: ${props => props.theme.header_background}; + } + + /* Prevent flicker when loading ace theme */ + .ace_scroller { + background: ${props => props.theme.header_background} !important; } `; diff --git a/yarn.lock b/yarn.lock index d1aab64..d4ae70a 100644 --- a/yarn.lock +++ b/yarn.lock @@ -5511,7 +5511,7 @@ promise@^7.1.1: dependencies: asap "~2.0.3" -prop-types@^15.0.0, prop-types@^15.5.10, prop-types@^15.5.4, prop-types@^15.5.7, prop-types@^15.5.8, prop-types@^15.6.2: +prop-types@^15.0.0, prop-types@^15.5.0, prop-types@^15.5.10, prop-types@^15.5.4, prop-types@^15.5.7, prop-types@^15.5.8, prop-types@^15.6.2: version "15.6.2" resolved "https://registry.yarnpkg.com/prop-types/-/prop-types-15.6.2.tgz#05d5ca77b4453e985d60fc7ff8c859094a497102" dependencies: @@ -5702,6 +5702,12 @@ react-is@^16.3.1, react-is@^16.3.2, react-is@^16.5.0: version "16.5.0" resolved "https://registry.yarnpkg.com/react-is/-/react-is-16.5.0.tgz#2ec7c192709698591efe13722fab3ef56144ba55" +react-loadable@^5.5.0: + version "5.5.0" + resolved "https://registry.yarnpkg.com/react-loadable/-/react-loadable-5.5.0.tgz#582251679d3da86c32aae2c8e689c59f1196d8c4" + dependencies: + prop-types "^15.5.0" + react-scripts@1.1.5: version "1.1.5" resolved "https://registry.yarnpkg.com/react-scripts/-/react-scripts-1.1.5.tgz#3041610ab0826736b52197711a4c4e3756e97768" @@ -6558,9 +6564,9 @@ style-loader@0.19.0: loader-utils "^1.0.2" schema-utils "^0.3.0" -styled-components@^4.0.0-beta.0-2: - version "4.0.0-beta.0-2" - resolved "https://registry.yarnpkg.com/styled-components/-/styled-components-4.0.0-beta.0-2.tgz#a9982c4f4593cd55b0c614176c3ab5625c846c9c" +styled-components@^4.0.0-beta.5: + version "4.0.0-beta.5" + resolved "https://registry.yarnpkg.com/styled-components/-/styled-components-4.0.0-beta.5.tgz#b6092346e49720b0e6df8a1d2e42334ca298735a" dependencies: "@emotion/is-prop-valid" "^0.6.5" css-to-react-native "^2.0.3"