make a edit text out of content editable
This commit is contained in:
parent
3f9dea8467
commit
6ce35c509e
|
@ -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: ->
|
||||
<div className="content-wrapper">
|
||||
<div className="content">
|
||||
<Pastebin />
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
|
24
src/web/pastebin.coffee
Normal file
24
src/web/pastebin.coffee
Normal file
|
@ -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: ->
|
||||
<div className="content-pastebin">
|
||||
<ContentEditable
|
||||
className="content-pastebin-edit"
|
||||
onUpdate={@onEditTextUpdate}
|
||||
value={@state.text}
|
||||
plainText/>
|
||||
</div>
|
||||
|
||||
export default Pastebin
|
15
src/web/styles/contentEditable.scss
Normal file
15
src/web/styles/contentEditable.scss
Normal file
|
@ -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;
|
||||
}
|
|
@ -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;
|
||||
}
|
||||
|
||||
/*
|
||||
|
|
|
@ -1,3 +1,10 @@
|
|||
// -- Prelude --
|
||||
@import './vars.scss';
|
||||
// -- Styles --
|
||||
@import './contentEditable.scss';
|
||||
@import './home.scss';
|
||||
@import './pastebin.scss';
|
||||
|
||||
body, html {
|
||||
margin: 0px;
|
||||
padding: 0px;
|
||||
|
|
14
src/web/styles/pastebin.scss
Normal file
14
src/web/styles/pastebin.scss
Normal file
|
@ -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;
|
||||
}
|
10
src/web/styles/vars.scss
Normal file
10
src/web/styles/vars.scss
Normal file
|
@ -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;
|
60
src/web/util/contentEditable.coffee
Normal file
60
src/web/util/contentEditable.coffee
Normal file
|
@ -0,0 +1,60 @@
|
|||
import React from "react"
|
||||
import ReactDOM from "react-dom"
|
||||
|
||||
# Wrapper for a content-editable div
|
||||
# <https://stackoverflow.com/questions/22677931/react-js-onchange-event-for-contenteditable>
|
||||
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
|
||||
# <https://developer.mozilla.org/en-US/docs/Web/API/Element/paste_event>
|
||||
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: ->
|
||||
<div
|
||||
className={"#{@props.className} editable"}
|
||||
onInput={@emitUpdate}
|
||||
onBlur={@emitUpdate}
|
||||
onPaste={@onPaste}
|
||||
spellCheck={false}
|
||||
contentEditable/>
|
||||
|
||||
export default ContentEditable
|
Loading…
Reference in a new issue