Skip to content
This repository was archived by the owner on Oct 11, 2022. It is now read-only.

Commit b20468a

Browse files
committed
fixed readonly change, styled demo select
1 parent a494c28 commit b20468a

File tree

6 files changed

+182
-99
lines changed

6 files changed

+182
-99
lines changed

demo/client/components/DemoEditor/index.js

Lines changed: 30 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,36 @@ const prismPlugin = createPrismPlugin({
2727
prism: Prism,
2828
});
2929

30-
const plugins = [prismPlugin, createMarkdownShortcutsPlugin()];
30+
const renderLanguageSelect = ({
31+
options,
32+
onChange,
33+
selectedValue,
34+
selectedLabel,
35+
}) => (
36+
<div className={styles.switcherContainer}>
37+
<div className={styles.switcher}>
38+
<select
39+
className={styles.switcherSelect}
40+
value={selectedValue}
41+
onChange={onChange}
42+
>
43+
{options.map(({ label, value }) => (
44+
<option key={value} value={value}>
45+
{label}
46+
</option>
47+
))}
48+
</select>
49+
<div className={styles.switcherLabel}>
50+
{selectedLabel} {String.fromCharCode(9662)}
51+
</div>
52+
</div>
53+
</div>
54+
);
55+
56+
const plugins = [
57+
prismPlugin,
58+
createMarkdownShortcutsPlugin({ renderLanguageSelect }),
59+
];
3160

3261
const initialEditorState = EditorState.createWithContent(
3362
convertFromRaw(initialState)
@@ -45,7 +74,6 @@ export default class DemoEditor extends Component {
4574
};
4675

4776
focus = () => {
48-
console.log("damnit");
4977
this.editor.focus();
5078
};
5179

demo/client/components/DemoEditor/styles.css

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,3 +11,37 @@
1111
height: 100%;
1212
width: 100%;
1313
}
14+
15+
pre {
16+
background: #f9f9f9;
17+
padding: 0.2em 0.5em;
18+
position: relative;
19+
}
20+
21+
.switcherContainer {
22+
position: absolute;
23+
text-align: right;
24+
bottom: -23px;
25+
right: 3px;
26+
}
27+
28+
.switcher {
29+
display: inline-block;
30+
font-family: sans-serif;
31+
color: #ccc;
32+
letter-spacing: 0.05em;
33+
font-size: 12px;
34+
padding: 0.3em;
35+
cursor: pointer;
36+
position: relative;
37+
}
38+
39+
.switcherSelect {
40+
position: absolute;
41+
top: 0;
42+
cursor: pointer;
43+
opacity: 0;
44+
left: 0;
45+
width: 100%;
46+
height: 100%;
47+
}

package.json

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -96,7 +96,6 @@
9696
"draft-js-plugins-editor": "~2.0.0-rc.1 || 2.0.0-rc2 || 2.0.0-rc1 || 2.0.0-beta12",
9797
"react": "^15.0.0",
9898
"react-dom": "^15.0.0",
99-
"react-modal": "3.x",
10099
"react-portal": "^4.1.4"
101100
},
102101
"contributors": [
@@ -108,7 +107,6 @@
108107
"draft-js-checkable-list-item": "^2.0.5",
109108
"draft-js-prism-plugin": "^0.1.1",
110109
"immutable": "~3.7.4",
111-
"react-modal": "^3.3.2",
112-
"react-popover": "^0.4.0"
110+
"react-click-outside": "^3.0.1"
113111
}
114112
}

src/components/Code/index.js

Lines changed: 80 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,12 @@
11
import React, { PureComponent } from "react";
22
import { Map } from "immutable";
33
import { EditorState, EditorBlock, Modifier } from "draft-js";
4-
import Modal from "react-modal";
4+
import enhanceWithClickOutside from "react-click-outside";
5+
6+
const alias = {
7+
javascript: "js",
8+
jsx: "js",
9+
};
510

611
const languages = {
712
bash: "Bash",
@@ -11,7 +16,6 @@ const languages = {
1116
go: "Go",
1217
html: "HTML",
1318
java: "Java",
14-
javascript: "JavaScript",
1519
js: "JavaScript",
1620
kotlin: "Kotlin",
1721
mathml: "MathML",
@@ -23,7 +27,21 @@ const languages = {
2327
swift: "Swift",
2428
};
2529

26-
const hidden = {};
30+
const CodeSwitchContainer = enhanceWithClickOutside(
31+
class SwitchContainer extends PureComponent {
32+
handleClickOutside() {
33+
this.props.onClickOutside();
34+
}
35+
36+
render() {
37+
return (
38+
<div contentEditable={false} onClick={this.props.onClick}>
39+
{this.props.children}
40+
</div>
41+
);
42+
}
43+
}
44+
);
2745

2846
class CodeBlock extends PureComponent {
2947
state = {
@@ -36,57 +54,91 @@ class CodeBlock extends PureComponent {
3654
const blockKey = this.props.block.getKey();
3755
const {
3856
getEditorState,
57+
setReadOnly,
3958
setEditorState,
40-
getEditorRef,
4159
} = this.props.blockProps;
60+
4261
const editorState = getEditorState();
4362
const selection = editorState.getSelection();
4463
const language = ev.currentTarget.value;
64+
const blockSelection = selection.merge({
65+
anchorKey: blockKey,
66+
focusKey: blockKey,
67+
});
4568

4669
let content = editorState.getCurrentContent();
47-
content = Modifier.mergeBlockData(content, selection, Map({ language }));
70+
content = Modifier.mergeBlockData(
71+
content,
72+
blockSelection,
73+
Map({ language })
74+
);
75+
setReadOnly(false);
4876

4977
const newEditorState = EditorState.push(
5078
editorState,
5179
content,
5280
"change-block-data"
5381
);
5482

55-
setTimeout(() => {
56-
setEditorState(
57-
EditorState.forceSelection(newEditorState, content.getSelectionAfter())
58-
);
59-
}, 2);
83+
setEditorState(EditorState.forceSelection(newEditorState, selection));
6084
};
6185

6286
cancelClicks = event => event.preventDefault();
6387

64-
preventBubbling = event => event.stopPropagation();
88+
onSelectClick = event => {
89+
const { setReadOnly } = this.props.blockProps;
90+
event.stopPropagation();
91+
setReadOnly(true);
92+
};
93+
94+
onClickOutside = () => {
95+
const {
96+
getEditorState,
97+
setReadOnly,
98+
setEditorState,
99+
} = this.props.blockProps;
100+
101+
setReadOnly(false);
102+
103+
const editorState = getEditorState();
104+
const selection = editorState.getSelection();
65105

66-
wat = () => {
67-
console.log("yo wtf");
106+
setEditorState(EditorState.forceSelection(newEditorState, selection));
68107
};
69108

70109
render() {
71-
const { language } = this.props.blockProps;
110+
const { languages, blockProps } = this.props;
111+
const { renderLanguageSelect, language: _language } = blockProps;
112+
113+
const language = alias[_language] || _language;
114+
const selectedLabel = languages[language];
115+
const selectedValue = language;
116+
117+
const options = Object.keys(languages).reduce(
118+
(acc, val) => [
119+
...acc,
120+
{
121+
label: languages[val],
122+
value: val,
123+
},
124+
],
125+
[]
126+
);
72127

73128
return (
74129
<div>
75130
<EditorBlock {...this.props} />
76-
<div>
77-
<select
78-
contentEditable={false}
79-
onClick={this.preventBubbling}
80-
value={language}
81-
onChange={this.onChange}
82-
>
83-
{Object.keys(this.props.languages).map(lang => (
84-
<option key={lang} value={lang}>
85-
{this.props.languages[lang]}
86-
</option>
87-
))}
88-
</select>
89-
</div>
131+
<CodeSwitchContainer
132+
onClickOutside={this.onClickOutside}
133+
onClick={this.onSelectClick}
134+
>
135+
{renderLanguageSelect({
136+
selectedLabel,
137+
selectedValue,
138+
onChange: this.onChange,
139+
options,
140+
})}
141+
</CodeSwitchContainer>
90142
</div>
91143
);
92144
}

src/index.js

Lines changed: 27 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,16 @@ import { CODE_BLOCK_REGEX, CODE_BLOCK_TYPE } from "./constants";
2626

2727
const INLINE_STYLE_CHARACTERS = [" ", "*", "_"];
2828

29+
const defaultRenderSelect = ({ options, onChange, selectedValue }) => (
30+
<select value={selectedValue} onChange={onChange}>
31+
{options.map(({ label, value }) => (
32+
<option key={value} value={value}>
33+
{label}
34+
</option>
35+
))}
36+
</select>
37+
);
38+
2939
function inCodeBlock(editorState) {
3040
const startKey = editorState.getSelection().getStartKey();
3141
if (startKey) {
@@ -98,8 +108,18 @@ function checkReturnForState(editorState, ev) {
98108
return newEditorState;
99109
}
100110

101-
const createMarkdownPlugin = (config = {}) => {
111+
const defaultConfig = {
112+
renderLanguageSelect: defaultRenderSelect,
113+
};
114+
115+
const createMarkdownPlugin = (_config = {}) => {
102116
const store = {};
117+
118+
const config = {
119+
...defaultConfig,
120+
..._config,
121+
};
122+
103123
return {
104124
store,
105125
blockRenderMap: Map({
@@ -126,7 +146,10 @@ const createMarkdownPlugin = (config = {}) => {
126146
return null;
127147
},
128148

129-
blockRendererFn(block, { setEditorState, getEditorState, getEditorRef }) {
149+
blockRendererFn(
150+
block,
151+
{ setReadOnly, setEditorState, getEditorState, getEditorRef }
152+
) {
130153
switch (block.getType()) {
131154
case CHECKABLE_LIST_ITEM: {
132155
return {
@@ -144,8 +167,9 @@ const createMarkdownPlugin = (config = {}) => {
144167
return {
145168
component: CodeBlock,
146169
props: {
147-
getEditorRef,
148170
setEditorState,
171+
renderLanguageSelect: config.renderLanguageSelect,
172+
setReadOnly,
149173
language: block.getData().get("language"),
150174
getEditorState,
151175
},

0 commit comments

Comments
 (0)