From 19e79d51a3707704bd536b8ee3eb55f3ae107f76 Mon Sep 17 00:00:00 2001 From: Pavel Date: Wed, 5 Jun 2019 19:49:35 +0300 Subject: [PATCH] Initial commit --- .firebaserc | 5 + .gitignore | 4 + firebase.json | 16 ++ package.json | 63 +++--- public/circle.svg | 3 + public/copy.svg | 1 + public/favicon.ico | Bin 3870 -> 0 bytes public/flow.svg | 1 + public/index.html | 60 +++-- public/manifest.json | 26 +-- public/new.svg | 1 + src/App.css | 33 --- src/App.js | 38 ++-- src/Reboot.css | 349 ++++++++++++++++++++++++++++++ src/components/AutosizeInput.js | 263 ++++++++++++++++++++++ src/components/CopyToClipboard.js | 65 ++++++ src/components/Menu.js | 60 +++++ src/components/NewFile.js | 44 ++++ src/components/TextEditor.js | 180 +++++++++++++++ src/index.css | 20 +- src/index.js | 13 +- src/store/action-types.js | 3 + src/store/actions.js | 22 ++ src/store/reducer.js | 36 +++ yarn.lock | 154 ++++++++++++- 25 files changed, 1319 insertions(+), 141 deletions(-) create mode 100644 .firebaserc create mode 100644 firebase.json create mode 100644 public/circle.svg create mode 100644 public/copy.svg delete mode 100644 public/favicon.ico create mode 100644 public/flow.svg create mode 100644 public/new.svg create mode 100644 src/Reboot.css create mode 100644 src/components/AutosizeInput.js create mode 100644 src/components/CopyToClipboard.js create mode 100644 src/components/Menu.js create mode 100644 src/components/NewFile.js create mode 100644 src/components/TextEditor.js create mode 100644 src/store/action-types.js create mode 100644 src/store/actions.js create mode 100644 src/store/reducer.js diff --git a/.firebaserc b/.firebaserc new file mode 100644 index 0000000..176fcfa --- /dev/null +++ b/.firebaserc @@ -0,0 +1,5 @@ +{ + "projects": { + "default": "flow-writer-com" + } +} diff --git a/.gitignore b/.gitignore index 4d29575..1bc07ef 100644 --- a/.gitignore +++ b/.gitignore @@ -21,3 +21,7 @@ npm-debug.log* yarn-debug.log* yarn-error.log* + +/build +.firebase + diff --git a/firebase.json b/firebase.json new file mode 100644 index 0000000..340ed5b --- /dev/null +++ b/firebase.json @@ -0,0 +1,16 @@ +{ + "hosting": { + "public": "build", + "ignore": [ + "firebase.json", + "**/.*", + "**/node_modules/**" + ], + "rewrites": [ + { + "source": "**", + "destination": "/index.html" + } + ] + } +} diff --git a/package.json b/package.json index 95abf45..6167627 100644 --- a/package.json +++ b/package.json @@ -1,31 +1,36 @@ { - "name": "murmur", - "version": "0.1.0", - "private": true, - "dependencies": { - "react": "^16.8.6", - "react-dom": "^16.8.6", - "react-scripts": "3.0.1" - }, - "scripts": { - "start": "react-scripts start", - "build": "react-scripts build", - "test": "react-scripts test", - "eject": "react-scripts eject" - }, - "eslintConfig": { - "extends": "react-app" - }, - "browserslist": { - "production": [ - ">0.2%", - "not dead", - "not op_mini all" - ], - "development": [ - "last 1 chrome version", - "last 1 firefox version", - "last 1 safari version" - ] - } + "name": "flow", + "version": "0.1.0", + "private": true, + "dependencies": { + "clipboard-polyfill": "^2.8.1", + "react": "^16.8.6", + "react-dom": "^16.8.6", + "react-redux": "^7.0.3", + "react-scripts": "3.0.1", + "rebass": "^3.1.1", + "redux": "^4.0.1", + "styled-components": "^4.2.0" + }, + "scripts": { + "start": "react-scripts start", + "build": "react-scripts build", + "test": "react-scripts test", + "eject": "react-scripts eject" + }, + "eslintConfig": { + "extends": "react-app" + }, + "browserslist": { + "production": [ + ">0.2%", + "not dead", + "not op_mini all" + ], + "development": [ + "last 1 chrome version", + "last 1 firefox version", + "last 1 safari version" + ] + } } diff --git a/public/circle.svg b/public/circle.svg new file mode 100644 index 0000000..e453ead --- /dev/null +++ b/public/circle.svg @@ -0,0 +1,3 @@ +Layer 1 \ No newline at end of file diff --git a/public/copy.svg b/public/copy.svg new file mode 100644 index 0000000..9b5c3cf --- /dev/null +++ b/public/copy.svg @@ -0,0 +1 @@ +04Layer 1 \ No newline at end of file diff --git a/public/favicon.ico b/public/favicon.ico deleted file mode 100644 index a11777cc471a4344702741ab1c8a588998b1311a..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 3870 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 baj7?x%VD!5Cxk2YbYLNVeiXvvpMCWYo=by@ diff --git a/public/flow.svg b/public/flow.svg new file mode 100644 index 0000000..32bed63 --- /dev/null +++ b/public/flow.svg @@ -0,0 +1 @@ +Icon Design 3Created by Ian Rahmadi Kurniawanfrom the Noun Project \ No newline at end of file diff --git a/public/index.html b/public/index.html index dd1ccfd..04a8459 100644 --- a/public/index.html +++ b/public/index.html @@ -1,16 +1,31 @@ - - - - - - + + + + + + + + - - - React App - - - -
- - + + + + + + + + +
+ diff --git a/public/manifest.json b/public/manifest.json index 1f2f141..7dc6e3a 100644 --- a/public/manifest.json +++ b/public/manifest.json @@ -1,15 +1,15 @@ { - "short_name": "React App", - "name": "Create React App Sample", - "icons": [ - { - "src": "favicon.ico", - "sizes": "64x64 32x32 24x24 16x16", - "type": "image/x-icon" - } - ], - "start_url": ".", - "display": "standalone", - "theme_color": "#000000", - "background_color": "#ffffff" + "short_name": "Flow", + "name": "Flow: Distraction-Free Writing App", + "icons": [ + { + "src": "circle.svg", + "sizes": "64x64 32x32 24x24 16x16", + "type": "image/svg+xml" + } + ], + "start_url": ".", + "display": "standalone", + "theme_color": "#000000", + "background_color": "#ffffff" } diff --git a/public/new.svg b/public/new.svg new file mode 100644 index 0000000..4e62c88 --- /dev/null +++ b/public/new.svg @@ -0,0 +1 @@ +Layer 1 \ No newline at end of file diff --git a/src/App.css b/src/App.css index b41d297..e69de29 100644 --- a/src/App.css +++ b/src/App.css @@ -1,33 +0,0 @@ -.App { - text-align: center; -} - -.App-logo { - animation: App-logo-spin infinite 20s linear; - height: 40vmin; - pointer-events: none; -} - -.App-header { - background-color: #282c34; - min-height: 100vh; - display: flex; - flex-direction: column; - align-items: center; - justify-content: center; - font-size: calc(10px + 2vmin); - color: white; -} - -.App-link { - color: #61dafb; -} - -@keyframes App-logo-spin { - from { - transform: rotate(0deg); - } - to { - transform: rotate(360deg); - } -} diff --git a/src/App.js b/src/App.js index ce9cbd2..8e4b84b 100644 --- a/src/App.js +++ b/src/App.js @@ -1,26 +1,22 @@ -import React from 'react'; -import logo from './logo.svg'; -import './App.css'; +import React from "react"; +import { createStore } from "redux"; +import { Provider } from "react-redux"; + +import Menu from "./components/Menu"; +import TextEditor from "./components/TextEditor"; +import reducer from "./store/reducer"; + +import "./App.css"; + +const store = createStore(reducer); function App() { - return ( -
-
- logo -

- Edit src/App.js and save to reload. -

-
- Learn React - -
-
- ); + return ( + + + + + ); } export default App; diff --git a/src/Reboot.css b/src/Reboot.css new file mode 100644 index 0000000..ce796b5 --- /dev/null +++ b/src/Reboot.css @@ -0,0 +1,349 @@ +/*! + * Bootstrap Reboot v4.3.1 (https://getbootstrap.com/) + * Copyright 2011-2019 The Bootstrap Authors + * Copyright 2011-2019 Twitter, Inc. + * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE) + * Forked from Normalize.css, licensed MIT (https://github.com/necolas/normalize.css/blob/master/LICENSE.md) + */ +*, +*::before, +*::after { + box-sizing: border-box; +} + +html { + font-family: sans-serif; + line-height: 1.15; + -webkit-text-size-adjust: 100%; + -webkit-tap-highlight-color: rgba(0, 0, 0, 0); +} + +article, +aside, +figcaption, +figure, +footer, +header, +hgroup, +main, +nav, +section { + display: block; +} + +body { + margin: 0; + font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, + "Helvetica Neue", Arial, "Noto Sans", sans-serif, "Apple Color Emoji", + "Segoe UI Emoji", "Segoe UI Symbol", "Noto Color Emoji"; + font-size: 1rem; + font-weight: 400; + line-height: 1.5; + color: #212529; + text-align: left; + background-color: #fff; +} + +[tabindex="-1"]:focus { + outline: 0 !important; +} + +hr { + box-sizing: content-box; + height: 0; + overflow: visible; +} + +h1, +h2, +h3, +h4, +h5, +h6 { + margin-top: 0; + margin-bottom: 0.5rem; +} + +p { + margin-top: 0; + margin-bottom: 1rem; +} + +abbr[title], +abbr[data-original-title] { + text-decoration: underline; + -webkit-text-decoration: underline dotted; + text-decoration: underline dotted; + cursor: help; + border-bottom: 0; + -webkit-text-decoration-skip-ink: none; + text-decoration-skip-ink: none; +} + +address { + margin-bottom: 1rem; + font-style: normal; + line-height: inherit; +} + +ol, +ul, +dl { + margin-top: 0; + margin-bottom: 1rem; +} + +ol ol, +ul ul, +ol ul, +ul ol { + margin-bottom: 0; +} + +dt { + font-weight: 700; +} + +dd { + margin-bottom: 0.5rem; + margin-left: 0; +} + +blockquote { + margin: 0 0 1rem; +} + +b, +strong { + font-weight: bolder; +} + +small { + font-size: 80%; +} + +sub, +sup { + position: relative; + font-size: 75%; + line-height: 0; + vertical-align: baseline; +} + +sub { + bottom: -0.25em; +} + +sup { + top: -0.5em; +} + +a { + color: #007bff; + text-decoration: none; + background-color: transparent; +} + +a:hover { + color: #0056b3; + text-decoration: underline; +} + +a:not([href]):not([tabindex]) { + color: inherit; + text-decoration: none; +} + +a:not([href]):not([tabindex]):hover, +a:not([href]):not([tabindex]):focus { + color: inherit; + text-decoration: none; +} + +a:not([href]):not([tabindex]):focus { + outline: 0; +} + +pre, +code, +kbd, +samp { + font-family: SFMono-Regular, Menlo, Monaco, Consolas, "Liberation Mono", + "Courier New", monospace; + font-size: 1em; +} + +pre { + margin-top: 0; + margin-bottom: 1rem; + overflow: auto; +} + +figure { + margin: 0 0 1rem; +} + +img { + vertical-align: middle; + border-style: none; +} + +svg { + overflow: hidden; + vertical-align: middle; +} + +table { + border-collapse: collapse; +} + +caption { + padding-top: 0.75rem; + padding-bottom: 0.75rem; + color: #6c757d; + text-align: left; + caption-side: bottom; +} + +th { + text-align: inherit; +} + +label { + display: inline-block; + margin-bottom: 0.5rem; +} + +button { + border-radius: 0; +} + +button:focus { + outline: 1px dotted; + outline: 5px auto -webkit-focus-ring-color; +} + +input, +button, +select, +optgroup, +textarea { + margin: 0; + font-family: inherit; + font-size: inherit; + line-height: inherit; +} + +button, +input { + overflow: visible; +} + +button, +select { + text-transform: none; +} + +select { + word-wrap: normal; +} + +button, +[type="button"], +[type="reset"], +[type="submit"] { + -webkit-appearance: button; +} + +button:not(:disabled), +[type="button"]:not(:disabled), +[type="reset"]:not(:disabled), +[type="submit"]:not(:disabled) { + cursor: pointer; +} + +button::-moz-focus-inner, +[type="button"]::-moz-focus-inner, +[type="reset"]::-moz-focus-inner, +[type="submit"]::-moz-focus-inner { + padding: 0; + border-style: none; +} + +input[type="radio"], +input[type="checkbox"] { + box-sizing: border-box; + padding: 0; +} + +input[type="date"], +input[type="time"], +input[type="datetime-local"], +input[type="month"] { + -webkit-appearance: listbox; +} + +textarea { + overflow: auto; + resize: vertical; +} + +fieldset { + min-width: 0; + padding: 0; + margin: 0; + border: 0; +} + +legend { + display: block; + width: 100%; + max-width: 100%; + padding: 0; + margin-bottom: 0.5rem; + font-size: 1.5rem; + line-height: inherit; + color: inherit; + white-space: normal; +} + +progress { + vertical-align: baseline; +} + +[type="number"]::-webkit-inner-spin-button, +[type="number"]::-webkit-outer-spin-button { + height: auto; +} + +[type="search"] { + outline-offset: -2px; + -webkit-appearance: none; +} + +[type="search"]::-webkit-search-decoration { + -webkit-appearance: none; +} + +::-webkit-file-upload-button { + font: inherit; + -webkit-appearance: button; +} + +output { + display: inline-block; +} + +summary { + display: list-item; + cursor: pointer; +} + +template { + display: none; +} + +[hidden] { + display: none !important; +} +/*# sourceMappingURL=bootstrap-reboot.css.map */ diff --git a/src/components/AutosizeInput.js b/src/components/AutosizeInput.js new file mode 100644 index 0000000..ffd9541 --- /dev/null +++ b/src/components/AutosizeInput.js @@ -0,0 +1,263 @@ +/* +[License] +This source code is part of react-input-autosize +https://github.com/JedWatson/react-input-autosize +packege destributed under the MIT license. + +[Changes] +- All
elements were changed top elements in component render() method. +- Quick fix added to disable outline on element. Search file for "Quickfix". +*/ + +import React, { Component } from "react"; +import PropTypes from "prop-types"; + +const sizerStyle = { + position: "absolute", + top: 0, + left: 0, + visibility: "hidden", + height: 0, + overflow: "scroll", + whiteSpace: "pre" +}; + +const INPUT_PROPS_BLACKLIST = [ + "extraWidth", + "injectStyles", + "inputClassName", + "inputRef", + "inputStyle", + "minWidth", + "onAutosize", + "placeholderIsMinWidth" +]; + +const cleanInputProps = inputProps => { + INPUT_PROPS_BLACKLIST.forEach(field => delete inputProps[field]); + return inputProps; +}; + +const copyStyles = (styles, node) => { + node.style.fontSize = styles.fontSize; + node.style.fontFamily = styles.fontFamily; + node.style.fontWeight = styles.fontWeight; + node.style.fontStyle = styles.fontStyle; + node.style.letterSpacing = styles.letterSpacing; + node.style.textTransform = styles.textTransform; + node.style.outline = styles.outlineStyle; + node.style.outlineStyle = styles.outline; + node.style.outlineWidth = styles.outlineWidth; + node.style.border = styles.border; +}; + +const isIE = + typeof window !== "undefined" && window.navigator + ? /MSIE |Trident\/|Edge\//.test(window.navigator.userAgent) + : false; + +const generateId = () => { + // we only need an auto-generated ID for stylesheet injection, which is only + // used for IE. so if the browser is not IE, this should return undefined. + return isIE + ? "_" + + Math.random() + .toString(36) + .substr(2, 12) + : undefined; +}; + +class AutosizeInput extends Component { + constructor(props) { + super(props); + this.state = { + inputWidth: props.minWidth, + inputId: props.id || generateId() + }; + } + componentDidMount() { + this.mounted = true; + this.copyInputStyles(); + this.updateInputWidth(); + } + componentWillReceiveProps(nextProps) { + const { id } = nextProps; + if (id !== this.props.id) { + this.setState({ inputId: id || generateId() }); + } + } + componentDidUpdate(prevProps, prevState) { + if (prevState.inputWidth !== this.state.inputWidth) { + if (typeof this.props.onAutosize === "function") { + this.props.onAutosize(this.state.inputWidth); + } + } + this.updateInputWidth(); + } + componentWillUnmount() { + this.mounted = false; + } + inputRef = el => { + this.input = el; + if (typeof this.props.inputRef === "function") { + this.props.inputRef(el); + } + }; + placeHolderSizerRef = el => { + this.placeHolderSizer = el; + }; + sizerRef = el => { + this.sizer = el; + }; + copyInputStyles() { + if (!this.mounted || !window.getComputedStyle) { + return; + } + const inputStyles = this.input && window.getComputedStyle(this.input); + if (!inputStyles) { + return; + } + copyStyles(inputStyles, this.sizer); + if (this.placeHolderSizer) { + copyStyles(inputStyles, this.placeHolderSizer); + } + } + updateInputWidth() { + if ( + !this.mounted || + !this.sizer || + typeof this.sizer.scrollWidth === "undefined" + ) { + return; + } + let newInputWidth; + if ( + this.props.placeholder && + (!this.props.value || + (this.props.value && this.props.placeholderIsMinWidth)) + ) { + newInputWidth = + Math.max(this.sizer.scrollWidth, this.placeHolderSizer.scrollWidth) + 2; + } else { + newInputWidth = this.sizer.scrollWidth + 2; + } + // add extraWidth to the detected width. for number types, this defaults to 16 to allow for the stepper UI + const extraWidth = + this.props.type === "number" && this.props.extraWidth === undefined + ? 16 + : parseInt(this.props.extraWidth) || 0; + newInputWidth += extraWidth; + if (newInputWidth < this.props.minWidth) { + newInputWidth = this.props.minWidth; + } + if (newInputWidth !== this.state.inputWidth) { + this.setState({ + inputWidth: newInputWidth + }); + } + } + getInput() { + return this.input; + } + focus() { + this.input.focus(); + } + blur() { + this.input.blur(); + } + select() { + this.input.select(); + } + renderStyles() { + // this method injects styles to hide IE's clear indicator, which messes + // with input size detection. the stylesheet is only injected when the + // browser is IE, and can also be disabled by the `injectStyles` prop. + const { injectStyles } = this.props; + return isIE && injectStyles ? ( +