From 6ce35c509e481955824c538e92f32c9b3113c507 Mon Sep 17 00:00:00 2001 From: Peter Cai Date: Tue, 18 Feb 2020 10:13:42 +0800 Subject: [PATCH] make a edit text out of content editable --- src/web/home.coffee | 3 +- src/web/pastebin.coffee | 24 ++++++++++++ src/web/styles/contentEditable.scss | 15 ++++++++ src/web/styles/home.scss | 8 +--- src/web/styles/index.scss | 7 ++++ src/web/styles/pastebin.scss | 14 +++++++ src/web/styles/vars.scss | 10 +++++ src/web/util/contentEditable.coffee | 60 +++++++++++++++++++++++++++++ 8 files changed, 134 insertions(+), 7 deletions(-) create mode 100644 src/web/pastebin.coffee create mode 100644 src/web/styles/contentEditable.scss create mode 100644 src/web/styles/pastebin.scss create mode 100644 src/web/styles/vars.scss create mode 100644 src/web/util/contentEditable.coffee diff --git a/src/web/home.coffee b/src/web/home.coffee index 06d53a4..0704e35 100644 --- a/src/web/home.coffee +++ b/src/web/home.coffee @@ -1,5 +1,5 @@ import React from "react" -import "./styles/home.scss" +import Pastebin from "./pastebin" class Home extends React.Component constructor: (props) -> @@ -8,6 +8,7 @@ class Home extends React.Component render: ->
+
diff --git a/src/web/pastebin.coffee b/src/web/pastebin.coffee new file mode 100644 index 0000000..ba225b7 --- /dev/null +++ b/src/web/pastebin.coffee @@ -0,0 +1,24 @@ +import React from "react" +import ContentEditable from "./util/contentEditable" + +class Pastebin extends React.Component + constructor: (props) -> + super props + @state = + text: "" + + onEditTextUpdate: (ev) => + console.log ev.target.value + @setState + text: ev.target.value + + render: -> +
+ +
+ +export default Pastebin \ No newline at end of file diff --git a/src/web/styles/contentEditable.scss b/src/web/styles/contentEditable.scss new file mode 100644 index 0000000..0e34b9a --- /dev/null +++ b/src/web/styles/contentEditable.scss @@ -0,0 +1,15 @@ +.editable { + display: block; + white-space: pre-wrap; + overflow-wrap: break-word; + word-wrap: break-word; + padding: 10px; + outline: none; + border: 1px solid $editable-color; + border-radius: $editable-radius; + transition: border-color 0.4s linear; +} + +.editable:focus { + border-color: $editable-color-active; +} \ No newline at end of file diff --git a/src/web/styles/home.scss b/src/web/styles/home.scss index 7854dbb..cba420a 100644 --- a/src/web/styles/home.scss +++ b/src/web/styles/home.scss @@ -1,8 +1,3 @@ -$content-padding: 100px; -$content-width: 1000px; -$content-height: 600px; -$content-total-height: $content-height + 2 * $content-padding; - .content-wrapper { width: 100vw; padding-top: $content-padding; @@ -18,7 +13,8 @@ $content-total-height: $content-height + 2 * $content-padding; width: $content-width; height: $content-height; box-shadow: 0 2px 5px 5px rgba(0, 0, 0, 0.15); - border-radius: 20px; + border-radius: $content-radius; + padding: $content-radius; } /* diff --git a/src/web/styles/index.scss b/src/web/styles/index.scss index 4b72c98..23fae39 100644 --- a/src/web/styles/index.scss +++ b/src/web/styles/index.scss @@ -1,3 +1,10 @@ +// -- Prelude -- +@import './vars.scss'; +// -- Styles -- +@import './contentEditable.scss'; +@import './home.scss'; +@import './pastebin.scss'; + body, html { margin: 0px; padding: 0px; diff --git a/src/web/styles/pastebin.scss b/src/web/styles/pastebin.scss new file mode 100644 index 0000000..46ffa2b --- /dev/null +++ b/src/web/styles/pastebin.scss @@ -0,0 +1,14 @@ +.content-pastebin { + display: block; + height: 100%; + width: 100%; +} + +.content-pastebin-edit { + display: block; + height: 100%; + width: 100%; + overflow-y: auto; + text-align: left; + box-sizing: border-box; +} \ No newline at end of file diff --git a/src/web/styles/vars.scss b/src/web/styles/vars.scss new file mode 100644 index 0000000..da298c1 --- /dev/null +++ b/src/web/styles/vars.scss @@ -0,0 +1,10 @@ +// Configurations for contentEditable +$editable-color: rgba(0, 0, 0, 0.1); +$editable-color-active: rgba(0, 0, 0, 0.2); +$editable-radius: 5px; +// Dimensions of main content card +$content-padding: 100px; +$content-width: 1000px; +$content-height: 600px; +$content-total-height: $content-height + 2 * $content-padding; +$content-radius: 20px; \ No newline at end of file diff --git a/src/web/util/contentEditable.coffee b/src/web/util/contentEditable.coffee new file mode 100644 index 0000000..cbbc9d2 --- /dev/null +++ b/src/web/util/contentEditable.coffee @@ -0,0 +1,60 @@ +import React from "react" +import ReactDOM from "react-dom" + +# Wrapper for a content-editable div +# +class ContentEditable extends React.Component + constructor: (props) -> + super props + + getText: -> + if @props.plainText then @domNode.innerText else @domNode.innerHTML + + setText: (text) -> + if @props.plainText + @domNode.innerText = text + else + @domNode.innerHTML = text + + componentDidMount: -> + @domNode = ReactDOM.findDOMNode @ + + componentWillUnmount: -> + @domNode = null + + shouldComponentUpdate: (nextProps) -> + nextProps.value != @getText() + + componentDidUpdate: -> + if @props.value != @getText() + @setText @props.value + + emitUpdate: => + if @props.onUpdate + # Note that the parent is expected to send the content back to us + # via `@props.value` + @props.onUpdate + target: + value: @getText() + + onPaste: (ev) => + return false if not @props.plainText + # + paste = (event.clipboardData || window.clipboardData).getData 'text' + selection = window.getSelection() + return false if not selection.rangeCount + selection.deleteFromDocument() + selection.getRangeAt 0 + .insertNode document.createTextNode paste + ev.preventDefault() + + render: -> +
+ +export default ContentEditable \ No newline at end of file