Skip to content

Commit b8e42fb

Browse files
author
Benjamin Kniffler
committed
Merge branch 'master' into toolbar-plugin
Conflicts: docs/client/routes.js
2 parents b77685f + 93241e0 commit b8e42fb

File tree

22 files changed

+634
-290
lines changed

22 files changed

+634
-290
lines changed
Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
import React, { Component } from 'react';
2+
import colorStyleMap from '../../colorStyleMap';
3+
4+
const styles = {
5+
styleButton: {
6+
color: '#999',
7+
cursor: 'pointer',
8+
marginRight: 16,
9+
padding: '2px 0',
10+
},
11+
};
12+
13+
export default class StyleButton extends Component {
14+
constructor(props) {
15+
super(props);
16+
this.onToggle = (e) => {
17+
e.preventDefault();
18+
this.props.onToggle(this.props.style);
19+
};
20+
}
21+
22+
render() {
23+
let style;
24+
if (this.props.active) {
25+
style = { ...styles.styleButton, ...colorStyleMap[this.props.style] };
26+
} else {
27+
style = styles.styleButton;
28+
}
29+
30+
return (
31+
<span style={style} onMouseDown={this.onToggle}>
32+
{this.props.label}
33+
</span>
34+
);
35+
}
36+
}
Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
import React from 'react';
2+
import StyleButton from './StyleButton';
3+
4+
const COLORS = [
5+
{ label: 'Red', style: 'red' },
6+
{ label: 'Orange', style: 'orange' },
7+
{ label: 'Yellow', style: 'yellow' },
8+
{ label: 'Green', style: 'green' },
9+
{ label: 'Blue', style: 'blue' },
10+
{ label: 'Indigo', style: 'indigo' },
11+
{ label: 'Violet', style: 'violet' },
12+
];
13+
14+
const styles = {
15+
controls: {
16+
fontFamily: '\'Helvetica\', sans-serif',
17+
fontSize: 14,
18+
marginBottom: 10,
19+
userSelect: 'none',
20+
},
21+
};
22+
23+
const ColorControls = (props) => {
24+
const currentStyle = props.editorState.getCurrentInlineStyle();
25+
return (
26+
<div style={styles.controls}>
27+
{COLORS.map((type, index) =>
28+
<StyleButton
29+
active={currentStyle.has(type.style)}
30+
label={type.label}
31+
onToggle={props.onToggle}
32+
style={type.style}
33+
key={ index }
34+
/>
35+
)}
36+
</div>
37+
);
38+
};
39+
40+
export default ColorControls;
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
import colorStyleMap from './colorStyleMap';
2+
3+
export const customStyleMap = colorStyleMap;
Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
const colorStyleMap = {
2+
red: {
3+
color: 'rgba(255, 0, 0, 1.0)',
4+
},
5+
orange: {
6+
color: 'rgba(255, 127, 0, 1.0)',
7+
},
8+
yellow: {
9+
color: 'rgba(180, 180, 0, 1.0)',
10+
},
11+
green: {
12+
color: 'rgba(0, 180, 0, 1.0)',
13+
},
14+
blue: {
15+
color: 'rgba(0, 0, 255, 1.0)',
16+
},
17+
indigo: {
18+
color: 'rgba(75, 0, 130, 1.0)',
19+
},
20+
violet: {
21+
color: 'rgba(127, 0, 255, 1.0)',
22+
},
23+
};
24+
25+
export default colorStyleMap;
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
.editor {
2+
border: 1px solid #ddd;
3+
cursor: text;
4+
padding: 16px;
5+
border-radius: 4px;
6+
margin-bottom: 2em;
7+
box-shadow: inset 0px 1px 8px -3px #ABABAB;
8+
background: #fefefe;
9+
}
10+
11+
.editor :global(.public-DraftEditor-content) {
12+
min-height: 140px;
13+
}
Lines changed: 88 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,88 @@
1+
import React, { Component } from 'react';
2+
import Editor, { createEditorStateWithText } from 'draft-js-plugins-editor';
3+
import createHashtagPlugin from 'draft-js-hashtag-plugin';
4+
import editorStyles from './editorStyles.css';
5+
import colorStyleMap from './colorStyleMap';
6+
import ColorControls from './ColorControls';
7+
import {
8+
EditorState,
9+
Modifier,
10+
RichUtils,
11+
} from 'draft-js';
12+
import * as colorPlugin from './colorPlugin';
13+
14+
const hashtagPlugin = createHashtagPlugin();
15+
const plugins = [hashtagPlugin, colorPlugin];
16+
const text = `#TIL: This editor can have all sorts of #hashtags. Pretty #cool :)
17+
Try it yourself by starting a word with a # (hash character) …
18+
`;
19+
20+
export default class SimpleHashtagEditor extends Component {
21+
22+
state = {
23+
editorState: createEditorStateWithText(text),
24+
};
25+
26+
onChange = (editorState) => {
27+
this.setState({
28+
editorState,
29+
});
30+
};
31+
32+
focus = () => {
33+
this.refs.editor.focus();
34+
};
35+
36+
toggleColor = (toggledColor) => {
37+
const { editorState } = this.state;
38+
const selection = editorState.getSelection();
39+
40+
// Let's just allow one color at a time. Turn off all active colors.
41+
const nextContentState = Object.keys(colorStyleMap)
42+
.reduce((contentState, color) => (
43+
Modifier.removeInlineStyle(contentState, selection, color)
44+
), editorState.getCurrentContent());
45+
46+
let nextEditorState = EditorState.push(
47+
editorState,
48+
nextContentState,
49+
'change-inline-style'
50+
);
51+
52+
const currentStyle = editorState.getCurrentInlineStyle();
53+
54+
// Unset style override for current color.
55+
if (selection.isCollapsed()) {
56+
nextEditorState = currentStyle.reduce((state, color) => (
57+
RichUtils.toggleInlineStyle(state, color)
58+
), nextEditorState);
59+
}
60+
61+
// If the color is being toggled on, apply it.
62+
if (!currentStyle.has(toggledColor)) {
63+
nextEditorState = RichUtils.toggleInlineStyle(
64+
nextEditorState,
65+
toggledColor
66+
);
67+
}
68+
69+
this.onChange(nextEditorState);
70+
};
71+
72+
render() {
73+
return (
74+
<div className={ editorStyles.editor } onClick={ this.focus }>
75+
<Editor
76+
editorState={this.state.editorState}
77+
onChange={this.onChange}
78+
plugins={plugins}
79+
ref="editor"
80+
/>
81+
<ColorControls
82+
editorState={this.state.editorState}
83+
onToggle={this.toggleColor}
84+
/>
85+
</div>
86+
);
87+
}
88+
}
Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
import React, { Component } from 'react';
2+
import Container from '../../shared/Container';
3+
import Heading from '../../shared/Heading';
4+
import PlaygroundEditor from './PlaygroundEditor';
5+
import NavBar from '../../shared/NavBar';
6+
import Separator from '../../shared/Separator';
7+
8+
export default class App extends Component {
9+
render() {
10+
return (
11+
<div>
12+
<NavBar />
13+
<Separator />
14+
<Container>
15+
<Heading level={ 2 }>Development Playground</Heading>
16+
</Container>
17+
<Container>
18+
<PlaygroundEditor />
19+
</Container>
20+
</div>
21+
22+
);
23+
}
24+
}

docs/client/routes.js

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ import Undo from './components/pages/Undo';
1313
import Mention from './components/pages/Mention';
1414
import Dnd from './components/pages/Dnd';
1515
import Toolbar from './components/pages/Toolbar';
16+
import Playground from './components/pages/Playground';
1617

1718
export const routes = (
1819
<Route path="/" title="App" component={App}>
@@ -27,6 +28,7 @@ export const routes = (
2728
<Route path="plugin/dnd" title="App - Drag & Drop" component={Dnd} />
2829
<Route path="plugin/toolbar" title="App - Toolbar" component={Toolbar} />
2930
</Route>
31+
<Route path="playground" title="App - Development Playground" component={Playground} />
3032
<Route path="*" title="404: Not Found" component={NotFound} />
3133
</Route>
3234
);

draft-js-dnd-plugin/src/blockRendererFn.js

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ import { Entity } from 'draft-js';
22
import removeBlock from './modifiers/removeBlock';
33
import refreshEditorState from './modifiers/refreshEditorState';
44

5-
export default (config) => (contentBlock, getEditorState, updateEditorState) => {
5+
export default (config) => (contentBlock, { getEditorState, setEditorState }) => {
66
const type = contentBlock.getType();
77
if (type === 'image') {
88
const entityKey = contentBlock.getEntityAt(0);
@@ -11,10 +11,10 @@ export default (config) => (contentBlock, getEditorState, updateEditorState) =>
1111
component: config.Image,
1212
props: {
1313
...data,
14-
remove: () => updateEditorState(removeBlock(getEditorState(), contentBlock.key)),
14+
remove: () => setEditorState(removeBlock(getEditorState(), contentBlock.key)),
1515

1616
// This is for block-alignment-wrapper, only temporarily living here
17-
refreshEditorState: () => updateEditorState(refreshEditorState(getEditorState())),
17+
refreshEditorState: () => setEditorState(refreshEditorState(getEditorState())),
1818
},
1919
};
2020
}

draft-js-dnd-plugin/src/modifiers/onDropBlock.js

Lines changed: 3 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -4,9 +4,7 @@ import { Entity } from 'draft-js';
44
import { DRAFTJS_BLOCK_KEY, DRAFTJS_BLOCK_TYPE } from '../constants';
55

66
export default function onDropBlock() {
7-
return function onDropBlockInner(event) {
8-
const { selection, dataTransfer, getEditorState, updateEditorState } = event;
9-
7+
return function onDropBlockInner(selection, dataTransfer, isInternal, { getEditorState, setEditorState }) {
108
const state = getEditorState();
119

1210
// Get data 'text' (anything else won't move the cursor) and expecting kind of data (text/key)
@@ -24,7 +22,7 @@ export default function onDropBlock() {
2422
// Get content, selection, block
2523
const block = state.getCurrentContent().getBlockForKey(blockKey);
2624
const editorStateAfterInsert = addBlock(state, selection, block.getType(), Entity.get(block.getEntityAt(0)).data);
27-
updateEditorState(removeBlock(editorStateAfterInsert, blockKey));
25+
setEditorState(removeBlock(editorStateAfterInsert, blockKey));
2826
}
2927

3028
// New block dropped
@@ -33,7 +31,7 @@ export default function onDropBlock() {
3331

3432
// Get content, selection, block
3533
const editorStateAfterInsert = addBlock(state, selection, blockType, {});
36-
updateEditorState(editorStateAfterInsert);
34+
setEditorState(editorStateAfterInsert);
3735
}
3836

3937
return true;

0 commit comments

Comments
 (0)