diff --git a/CHANGELOG.md b/CHANGELOG.md
index 0793127..0e8e9fa 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -6,6 +6,7 @@
- Set the theme for the editor
- Set the theme for the output
- Settings and input are persisted between app restarts
+- Editor pane can be resized
# 1.0.0
diff --git a/example.gif b/example.gif
index 9eb02b8..ad93453 100644
Binary files a/example.gif and b/example.gif differ
diff --git a/package.json b/package.json
index 0ac85b1..07161b8 100644
--- a/package.json
+++ b/package.json
@@ -31,6 +31,7 @@
"react-codemirror": "^0.3.0",
"react-dom": "^15.3.1",
"react-redux": "^4.4.5",
+ "react-split-pane": "0.1.66",
"redux": "^3.6.0",
"redux-persist": "4.8.3",
"redux-thunk": "^2.1.0"
diff --git a/src/app/components/App/index.js b/src/app/components/App/index.js
deleted file mode 100644
index 70c681a..0000000
--- a/src/app/components/App/index.js
+++ /dev/null
@@ -1,42 +0,0 @@
-import React from 'react'
-import { connect } from 'react-redux'
-import Editor from '../../containers/Editor'
-import Status from '../Status'
-import Output from '../Output'
-import Settings from '../../containers/Settings'
-
-import './styles.css'
-
-const App = ({ coffeeScriptVersion, editorTheme, outputTheme, input, output, status }) => {
- return (
-
-
-
-
-
- {input}
-
-
-
-
-
-
- )
-}
-
-const mapStateToProps = (state) => {
- return {
- coffeeScriptVersion: state.app.coffeeScriptVersion,
- editorTheme: state.app.editorTheme,
- outputTheme: state.app.outputTheme,
- input: state.app.input,
- output: state.app.output,
- status: state.app.status
- }
-}
-
-export default connect(mapStateToProps)(App)
diff --git a/src/app/components/Output/styles.css b/src/app/components/Output/styles.css
index 487d753..67f62fa 100644
--- a/src/app/components/Output/styles.css
+++ b/src/app/components/Output/styles.css
@@ -1,13 +1,10 @@
.Output {
- flex: 0 0 50%;
- display: flex;
- flex-direction: column;
overflow: hidden;
+ height: 100%;
}
.Output .ReactCodeMirror {
- flex: 0 0 100%;
- overflow: hidden;
+ height: 100%;
}
.Output .CodeMirror {
diff --git a/src/app/components/Setting/CoffeeScriptVersion/index.js b/src/app/components/Setting/CoffeeScriptVersion/index.js
index fdae764..ccb1069 100644
--- a/src/app/components/Setting/CoffeeScriptVersion/index.js
+++ b/src/app/components/Setting/CoffeeScriptVersion/index.js
@@ -1,21 +1,14 @@
import React from 'react'
-import { connect } from 'react-redux'
-import { setCoffeeScriptVersion } from '../../../actions/settings'
+import Selector from '../Selector'
import { getAllVersions as getAllCoffeeScriptVersions } from '../../../coffeescript'
-const CoffeeScriptVersionSetting = ({ dispatch, version }) => {
+export default function ({ version, onChange }) {
return (
-
-
-
-
+
)
}
-
-export default connect()(CoffeeScriptVersionSetting)
diff --git a/src/app/components/Setting/EditorTheme/index.js b/src/app/components/Setting/EditorTheme/index.js
index 272b55f..ff78a84 100644
--- a/src/app/components/Setting/EditorTheme/index.js
+++ b/src/app/components/Setting/EditorTheme/index.js
@@ -1,21 +1,14 @@
import React from 'react'
-import { connect } from 'react-redux'
-import { setEditorTheme } from '../../../actions/settings'
+import Selector from '../Selector'
import { getAllThemes as getAllEditorThemes } from '../../../editor'
-const EditorThemeSetting = ({ dispatch, theme }) => {
+export default function ({ theme, onChange }) {
return (
-
-
-
-
+
)
}
-
-export default connect()(EditorThemeSetting)
diff --git a/src/app/components/Setting/OutputTheme/index.js b/src/app/components/Setting/OutputTheme/index.js
index 61df7c1..841c0ea 100644
--- a/src/app/components/Setting/OutputTheme/index.js
+++ b/src/app/components/Setting/OutputTheme/index.js
@@ -1,21 +1,14 @@
import React from 'react'
-import { connect } from 'react-redux'
-import { setOutputTheme } from '../../../actions/settings'
+import Selector from '../Selector'
import { getAllThemes as getAllEditorThemes } from '../../../editor'
-const OutputThemeSetting = ({ dispatch, theme }) => {
+export default function ({ theme, onChange }) {
return (
-
-
-
-
+
)
}
-
-export default connect()(OutputThemeSetting)
diff --git a/src/app/components/Setting/Selector/index.js b/src/app/components/Setting/Selector/index.js
new file mode 100644
index 0000000..8335797
--- /dev/null
+++ b/src/app/components/Setting/Selector/index.js
@@ -0,0 +1,14 @@
+import React from 'react'
+
+export default function ({ label, initialValue, options, onChange }) {
+ return (
+
+
+
+
+ )
+}
diff --git a/src/app/containers/App/index.js b/src/app/containers/App/index.js
new file mode 100644
index 0000000..3043c94
--- /dev/null
+++ b/src/app/containers/App/index.js
@@ -0,0 +1,38 @@
+import React from 'react'
+import { connect } from 'react-redux'
+import SplitPane from 'react-split-pane'
+import Editor from '../Editor'
+import Status from '../../components/Status'
+import Output from '../../components/Output'
+import Settings from '../Settings'
+
+import './styles.css'
+
+const App = ({ outputTheme, output, status }) => {
+ return (
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ )
+}
+
+const mapStateToProps = state => {
+ return {
+ outputTheme: state.app.outputTheme,
+ output: state.app.output,
+ status: state.app.status
+ }
+}
+
+export default connect(mapStateToProps)(App)
diff --git a/src/app/components/App/styles.css b/src/app/containers/App/styles.css
similarity index 67%
rename from src/app/components/App/styles.css
rename to src/app/containers/App/styles.css
index a79bf0b..78eecdf 100644
--- a/src/app/components/App/styles.css
+++ b/src/app/containers/App/styles.css
@@ -15,3 +15,9 @@
flex-direction: row;
flex: 2 0 auto;
}
+
+.Resizer.vertical {
+ border-left: 3px solid #ddd;
+ border-right: 3px solid #ddd;
+ cursor: col-resize;
+}
diff --git a/src/app/containers/Editor/index.js b/src/app/containers/Editor/index.js
index 8a9ea12..cd919cb 100644
--- a/src/app/containers/Editor/index.js
+++ b/src/app/containers/Editor/index.js
@@ -1,4 +1,4 @@
-import React from 'react'
+import React, { Component } from 'react'
import Codemirror from 'react-codemirror'
import { connect } from 'react-redux'
import { compileInput } from '../../actions/editor'
@@ -6,12 +6,12 @@ import 'codemirror/mode/coffeescript/coffeescript'
import './styles.css'
-class Editor extends React.Component {
+class Editor extends Component {
get options () {
return {
lineNumbers: true,
mode: 'coffeescript',
- theme: this.props.theme
+ theme: this.props.editorTheme
}
}
@@ -31,22 +31,24 @@ class Editor extends React.Component {
}
handleFocusChange (focused) {
- if (focused && this.props.children === this.defaultValue) {
+ if (focused && this.props.input === this.defaultValue) {
this.props.dispatch(compileInput('', this.props.coffeeScriptVersion))
}
- if (!focused && this.props.children === '') {
+ if (!focused && this.props.input === '') {
this.props.dispatch(compileInput(this.defaultValue, this.props.coffeeScriptVersion))
}
}
componentDidMount () {
- this.props.dispatch(compileInput(this.props.children, this.props.coffeeScriptVersion))
+ // re-compile input when the component is mounted
+ this.props.dispatch(compileInput(this.props.input, this.props.coffeeScriptVersion))
}
componentDidUpdate (prevProps) {
+ // re-compile input if the CoffeeScript version changed
if (this.props.coffeeScriptVersion !== prevProps.coffeeScriptVersion) {
- this.props.dispatch(compileInput(this.props.children, this.props.coffeeScriptVersion))
+ this.props.dispatch(compileInput(this.props.input, this.props.coffeeScriptVersion))
}
}
@@ -57,11 +59,19 @@ class Editor extends React.Component {
options={this.options}
onChange={this.handleInputChange}
onFocusChange={this.handleFocusChange}
- value={this.props.children}
+ value={this.props.input}
/>
)
}
}
-export default connect()(Editor)
+const mapStateToProps = state => {
+ return {
+ coffeeScriptVersion: state.app.coffeeScriptVersion,
+ editorTheme: state.app.editorTheme,
+ input: state.app.input
+ }
+}
+
+export default connect(mapStateToProps)(Editor)
diff --git a/src/app/containers/Editor/styles.css b/src/app/containers/Editor/styles.css
index f447a6c..d656901 100644
--- a/src/app/containers/Editor/styles.css
+++ b/src/app/containers/Editor/styles.css
@@ -1,13 +1,10 @@
.Editor {
- flex: 0 0 50%;
- display: flex;
- flex-direction: column;
overflow: hidden;
+ height: 100%
}
.Editor .ReactCodeMirror {
- flex: 0 0 100%;
- overflow: hidden;
+ height: 100%
}
.Editor .CodeMirror {
diff --git a/src/app/containers/Settings/index.js b/src/app/containers/Settings/index.js
index 152eece..3b86a88 100644
--- a/src/app/containers/Settings/index.js
+++ b/src/app/containers/Settings/index.js
@@ -1,4 +1,6 @@
import React from 'react'
+import { connect } from 'react-redux'
+import { setCoffeeScriptVersion, setEditorTheme, setOutputTheme } from '../../actions/settings'
import CoffeeScriptVersion from '../../components/Setting/CoffeeScriptVersion'
import EditorTheme from '../../components/Setting/EditorTheme'
import OutputTheme from '../../components/Setting/OutputTheme'
@@ -6,12 +8,28 @@ import OutputTheme from '../../components/Setting/OutputTheme'
import './styles.css'
import '../../components/Setting/styles.css'
-export default function ({ coffeeScriptVersion, editorTheme, outputTheme }) {
+const Settings = ({ dispatch, coffeeScriptVersion, editorTheme, outputTheme }) => {
return (
-
-
-
+ {
+ dispatch(setOutputTheme(e.target.value))
+ }} />
+ {
+ dispatch(setEditorTheme(e.target.value))
+ }} />
+ {
+ dispatch(setCoffeeScriptVersion(e.target.value))
+ }} />
)
}
+
+const mapStateToProps = state => {
+ return {
+ coffeeScriptVersion: state.app.coffeeScriptVersion,
+ editorTheme: state.app.editorTheme,
+ outputTheme: state.app.outputTheme
+ }
+}
+
+export default connect(mapStateToProps)(Settings)
diff --git a/src/app/index.js b/src/app/index.js
index 663c005..977e3d1 100644
--- a/src/app/index.js
+++ b/src/app/index.js
@@ -1,9 +1,8 @@
import React from 'react'
import ReactDOM from 'react-dom'
import { Provider } from 'react-redux'
-
import store from './store'
-import App from './components/App'
+import App from './containers/App'
import 'normalize.css'
import 'codemirror/lib/codemirror.css'
diff --git a/src/app/store.js b/src/app/store.js
index e615f73..67101b4 100644
--- a/src/app/store.js
+++ b/src/app/store.js
@@ -1,5 +1,5 @@
-import {compose, applyMiddleware, createStore} from 'redux'
-import {persistStore, autoRehydrate} from 'redux-persist'
+import { applyMiddleware, compose, createStore } from 'redux'
+import { autoRehydrate, persistStore } from 'redux-persist'
import thunk from 'redux-thunk'
import reducer from './reducers'
@@ -13,7 +13,6 @@ const store = createStore(
)
persistStore(store, {
- blacklist: [], // todo
keyPrefix: 'CoffeeWriter-'
})
diff --git a/src/app/styles.css b/src/app/styles.css
index 01511ae..ed13fc2 100644
--- a/src/app/styles.css
+++ b/src/app/styles.css
@@ -1,9 +1,13 @@
body {
font-size: 14px;
- font-family: "Helvetica Neue", Helvetica, Arial, sans-serif;
+ font-family: 'Helvetica Neue', Helvetica, Arial, sans-serif;
}
.CodeMirror {
font-size: 15px;
font-family: 'Source Code Pro', monospace;
}
+
+*, *:before, *:after {
+ position: relative;
+}
diff --git a/src/electron/main.js b/src/electron/main.js
index 2a17bce..f0b799e 100644
--- a/src/electron/main.js
+++ b/src/electron/main.js
@@ -13,10 +13,10 @@ const createWindow = () => {
let windowOptions = {
width: 800,
height: 600,
+ titleBarStyle: 'hidden',
webPreferences: {
preload: path.resolve(__dirname, 'preload.js')
- },
- titleBarStyle: 'hidden'
+ }
}
let url = `file://${path.resolve(__dirname, '../app/index.html')}`
@@ -39,21 +39,42 @@ const createWindow = () => {
})
}
-const createMainMenu = (app) => {
+const createMainMenu = app => {
var template = [
{
label: app.getName(),
submenu: [
- { label: `About ${app.getName()}`, selector: 'orderFrontStandardAboutPanel:' },
- { type: 'separator' },
- { label: 'Quit', accelerator: 'Command+Q', click: () => app.quit() }
+ {
+ label: `About ${app.getName()}`,
+ selector: 'orderFrontStandardAboutPanel:'
+ },
+ {
+ type: 'separator'
+ },
+ {
+ label: 'Quit',
+ accelerator: 'Command+Q',
+ click: () => app.quit()
+ }
]
}, {
label: 'Edit',
submenu: [
- { label: 'Cut', accelerator: 'CmdOrCtrl+X', selector: 'cut:' },
- { label: 'Copy', accelerator: 'CmdOrCtrl+C', selector: 'copy:' },
- { label: 'Paste', accelerator: 'CmdOrCtrl+V', selector: 'paste:' }
+ {
+ label: 'Cut',
+ accelerator: 'CmdOrCtrl+X',
+ selector: 'cut:'
+ },
+ {
+ label: 'Copy',
+ accelerator: 'CmdOrCtrl+C',
+ selector: 'copy:'
+ },
+ {
+ label: 'Paste',
+ accelerator: 'CmdOrCtrl+V',
+ selector: 'paste:'
+ }
]}
]
diff --git a/src/electron/preload.js b/src/electron/preload.js
index 22837b2..cf7a18c 100644
--- a/src/electron/preload.js
+++ b/src/electron/preload.js
@@ -7,13 +7,16 @@ const Menu = remote.Menu
const InputMenu = Menu.buildFromTemplate([
{
type: 'separator'
- }, {
+ },
+ {
label: 'Cut',
role: 'cut'
- }, {
+ },
+ {
label: 'Copy',
role: 'copy'
- }, {
+ },
+ {
label: 'Paste',
role: 'paste'
}
@@ -21,7 +24,7 @@ const InputMenu = Menu.buildFromTemplate([
// https://github.com/electron/electron/issues/4068#issuecomment-170911307
window.addEventListener('DOMContentLoaded', () => {
- document.body.addEventListener('contextmenu', (e) => {
+ document.body.addEventListener('contextmenu', e => {
e.preventDefault()
e.stopPropagation()
@@ -30,6 +33,7 @@ window.addEventListener('DOMContentLoaded', () => {
while (node) {
if (node.nodeName.match(/DIV/) && node.className && node.className.match(/^CodeMirror.*$/i)) {
InputMenu.popup(remote.getCurrentWindow())
+
break
}
diff --git a/yarn.lock b/yarn.lock
index 5cd9686..b47afe1 100644
--- a/yarn.lock
+++ b/yarn.lock
@@ -819,6 +819,10 @@ boom@2.x.x:
dependencies:
hoek "2.x.x"
+bowser@^1.6.0:
+ version "1.7.1"
+ resolved "https://registry.yarnpkg.com/bowser/-/bowser-1.7.1.tgz#a4de8f18a1a0dc9531eb2a92a1521fb6a9ba96a5"
+
brace-expansion@^1.0.0:
version "1.1.6"
resolved "https://registry.yarnpkg.com/brace-expansion/-/brace-expansion-1.1.6.tgz#7197d7eaa9b87e648390ea61fc66c84427420df9"
@@ -1197,6 +1201,12 @@ css-color-names@0.0.4:
version "0.0.4"
resolved "https://registry.yarnpkg.com/css-color-names/-/css-color-names-0.0.4.tgz#808adc2e79cf84738069b646cb20ec27beb629e0"
+css-in-js-utils@^1.0.3:
+ version "1.0.3"
+ resolved "https://registry.yarnpkg.com/css-in-js-utils/-/css-in-js-utils-1.0.3.tgz#9ac7e02f763cf85d94017666565ed68a5b5f3215"
+ dependencies:
+ hyphenate-style-name "^1.0.2"
+
css-loader@^0.25.0:
version "0.25.0"
resolved "https://registry.yarnpkg.com/css-loader/-/css-loader-0.25.0.tgz#c3febc8ce28f4c83576b6b13707f47f90c390223"
@@ -1859,6 +1869,18 @@ fbjs@^0.8.1, fbjs@^0.8.4:
setimmediate "^1.0.5"
ua-parser-js "^0.7.9"
+fbjs@^0.8.9:
+ version "0.8.14"
+ resolved "https://registry.yarnpkg.com/fbjs/-/fbjs-0.8.14.tgz#d1dbe2be254c35a91e09f31f9cd50a40b2a0ed1c"
+ dependencies:
+ core-js "^1.0.0"
+ isomorphic-fetch "^2.1.1"
+ loose-envify "^1.0.0"
+ object-assign "^4.1.0"
+ promise "^7.1.1"
+ setimmediate "^1.0.5"
+ ua-parser-js "^0.7.9"
+
fd-slicer@~1.0.1:
version "1.0.1"
resolved "https://registry.yarnpkg.com/fd-slicer/-/fd-slicer-1.0.1.tgz#8b5bcbd9ec327c5041bf9ab023fd6750f1177e65"
@@ -2316,6 +2338,10 @@ https-browserify@0.0.1:
version "0.0.1"
resolved "https://registry.yarnpkg.com/https-browserify/-/https-browserify-0.0.1.tgz#3f91365cabe60b77ed0ebba24b454e3e09d95a82"
+hyphenate-style-name@^1.0.2:
+ version "1.0.2"
+ resolved "https://registry.yarnpkg.com/hyphenate-style-name/-/hyphenate-style-name-1.0.2.tgz#31160a36930adaf1fc04c6074f7eb41465d4ec4b"
+
iconv-lite@~0.4.13:
version "0.4.15"
resolved "https://registry.yarnpkg.com/iconv-lite/-/iconv-lite-0.4.15.tgz#fe265a218ac6a57cfe854927e9d04c19825eddeb"
@@ -2369,6 +2395,13 @@ ini@~1.3.0:
version "1.3.4"
resolved "https://registry.yarnpkg.com/ini/-/ini-1.3.4.tgz#0537cb79daf59b59a1a517dff706c86ec039162e"
+inline-style-prefixer@^3.0.6:
+ version "3.0.7"
+ resolved "https://registry.yarnpkg.com/inline-style-prefixer/-/inline-style-prefixer-3.0.7.tgz#0ccc92e5902fe6e0d28d975c4258443f880615f8"
+ dependencies:
+ bowser "^1.6.0"
+ css-in-js-utils "^1.0.3"
+
inquirer@^0.12.0:
version "0.12.0"
resolved "https://registry.yarnpkg.com/inquirer/-/inquirer-0.12.0.tgz#1ef2bfd63504df0bc75785fff8c2c41df12f077e"
@@ -2597,6 +2630,10 @@ js-tokens@^2.0.0:
version "2.0.0"
resolved "https://registry.yarnpkg.com/js-tokens/-/js-tokens-2.0.0.tgz#79903f5563ee778cc1162e6dcf1a0027c97f9cb5"
+js-tokens@^3.0.0:
+ version "3.0.2"
+ resolved "https://registry.yarnpkg.com/js-tokens/-/js-tokens-3.0.2.tgz#9866df395102130e38f7f996bceb65443209c25b"
+
js-yaml@^3.5.1:
version "3.7.0"
resolved "https://registry.yarnpkg.com/js-yaml/-/js-yaml-3.7.0.tgz#5c967ddd837a9bfdca5f2de84253abe8a1c03b80"
@@ -2799,6 +2836,12 @@ loose-envify@^1.0.0, loose-envify@^1.1.0:
dependencies:
js-tokens "^2.0.0"
+loose-envify@^1.3.1:
+ version "1.3.1"
+ resolved "https://registry.yarnpkg.com/loose-envify/-/loose-envify-1.3.1.tgz#d1a8ad33fa9ce0e713d65fdd0ac8b748d478c848"
+ dependencies:
+ js-tokens "^3.0.0"
+
loud-rejection@^1.0.0:
version "1.6.0"
resolved "https://registry.yarnpkg.com/loud-rejection/-/loud-rejection-1.6.0.tgz#5b46f80147edee578870f086d04821cf998e551f"
@@ -3628,6 +3671,13 @@ promise@^7.1.1:
dependencies:
asap "~2.0.3"
+prop-types@^15.5.10, prop-types@^15.5.4:
+ version "15.5.10"
+ resolved "https://registry.yarnpkg.com/prop-types/-/prop-types-15.5.10.tgz#2797dfc3126182e3a95e3dfbb2e893ddd7456154"
+ dependencies:
+ fbjs "^0.8.9"
+ loose-envify "^1.3.1"
+
proxy-addr@~1.1.2:
version "1.1.2"
resolved "https://registry.yarnpkg.com/proxy-addr/-/proxy-addr-1.1.2.tgz#b4cc5f22610d9535824c123aef9d3cf73c40ba37"
@@ -3731,6 +3781,20 @@ react-redux@^4.4.5:
lodash "^4.2.0"
loose-envify "^1.1.0"
+react-split-pane:
+ version "0.1.66"
+ resolved "https://registry.yarnpkg.com/react-split-pane/-/react-split-pane-0.1.66.tgz#369085dd07ec1237bda123e73813dcc7dc6502c1"
+ dependencies:
+ inline-style-prefixer "^3.0.6"
+ prop-types "^15.5.10"
+ react-style-proptype "^3.0.0"
+
+react-style-proptype@^3.0.0:
+ version "3.0.0"
+ resolved "https://registry.yarnpkg.com/react-style-proptype/-/react-style-proptype-3.0.0.tgz#89e0b646f266c656abb0f0dd8202dbd5036c31e6"
+ dependencies:
+ prop-types "^15.5.4"
+
react@^15.3.1:
version "15.4.1"
resolved "https://registry.yarnpkg.com/react/-/react-15.4.1.tgz#498e918602677a3983cd0fd206dfe700389a0dd6"