Skip to content

Commit b09fb42

Browse files
committed
Merge pull request draft-js-plugins#170 from draft-js-plugins/dev-playground
add dev playground to explore custom style maps
2 parents 6d91785 + 6649aa0 commit b09fb42

File tree

7 files changed

+228
-0
lines changed

7 files changed

+228
-0
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: 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+
13+
const hashtagPlugin = createHashtagPlugin();
14+
const plugins = [hashtagPlugin];
15+
const text = `#TIL: This editor can have all sorts of #hashtags. Pretty #cool :)
16+
Try it yourself by starting a word with a # (hash character) …
17+
`;
18+
19+
export default class SimpleHashtagEditor extends Component {
20+
21+
state = {
22+
editorState: createEditorStateWithText(text),
23+
};
24+
25+
onChange = (editorState) => {
26+
this.setState({
27+
editorState,
28+
});
29+
};
30+
31+
focus = () => {
32+
this.refs.editor.focus();
33+
};
34+
35+
toggleColor = (toggledColor) => {
36+
const { editorState } = this.state;
37+
const selection = editorState.getSelection();
38+
39+
// Let's just allow one color at a time. Turn off all active colors.
40+
const nextContentState = Object.keys(colorStyleMap)
41+
.reduce((contentState, color) => (
42+
Modifier.removeInlineStyle(contentState, selection, color)
43+
), editorState.getCurrentContent());
44+
45+
let nextEditorState = EditorState.push(
46+
editorState,
47+
nextContentState,
48+
'change-inline-style'
49+
);
50+
51+
const currentStyle = editorState.getCurrentInlineStyle();
52+
53+
// Unset style override for current color.
54+
if (selection.isCollapsed()) {
55+
nextEditorState = currentStyle.reduce((state, color) => (
56+
RichUtils.toggleInlineStyle(state, color)
57+
), nextEditorState);
58+
}
59+
60+
// If the color is being toggled on, apply it.
61+
if (!currentStyle.has(toggledColor)) {
62+
nextEditorState = RichUtils.toggleInlineStyle(
63+
nextEditorState,
64+
toggledColor
65+
);
66+
}
67+
68+
this.onChange(nextEditorState);
69+
};
70+
71+
render() {
72+
return (
73+
<div className={ editorStyles.editor } onClick={ this.focus }>
74+
<Editor
75+
customStyleMap={colorStyleMap}
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
@@ -12,6 +12,7 @@ import Sticker from './components/pages/Sticker';
1212
import Undo from './components/pages/Undo';
1313
import Mention from './components/pages/Mention';
1414
import Dnd from './components/pages/Dnd';
15+
import Playground from './components/pages/Playground';
1516

1617
export const routes = (
1718
<Route path="/" title="App" component={App}>
@@ -25,6 +26,7 @@ export const routes = (
2526
<Route path="plugin/mention" title="App - Mention" component={Mention} />
2627
<Route path="plugin/dnd" title="App - Drag & Drop" component={Dnd} />
2728
</Route>
29+
<Route path="playground" title="App - Development Playground" component={Playground} />
2830
<Route path="*" title="404: Not Found" component={NotFound} />
2931
</Route>
3032
);

0 commit comments

Comments
 (0)