Skip to content
This repository was archived by the owner on Nov 4, 2025. It is now read-only.

Commit 0f94142

Browse files
author
Mykhailo Malykov
committed
temp
1 parent 7070b11 commit 0f94142

8 files changed

Lines changed: 145 additions & 59 deletions

File tree

package.json

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,12 +5,13 @@
55
"dependencies": {
66
"react": "^16.2.0",
77
"react-dom": "^16.2.0",
8-
"react-scripts": "1.1.1"
8+
"react-scripts": "1.1.1",
9+
"rxjs": "^6.5.5"
910
},
1011
"scripts": {
1112
"start": "react-scripts start",
1213
"build": "react-scripts build",
1314
"test": "react-scripts test --env=jsdom",
1415
"eject": "react-scripts eject"
1516
}
16-
}
17+
}

src/App.js

Lines changed: 20 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -1,28 +1,25 @@
1-
import React, {Component} from 'react';
1+
import React, {useEffect, useState} from 'react';
22
import './App.css';
3-
import ControlPanel from "./control-panel/ControlPanel";
4-
import FileZone from "./file-zone/FileZone";
5-
import getMockText from './text.service';
3+
import getMockText from "./text.service";
4+
import TextEditor from "./text-editor/TextEditor";
65

7-
class App extends Component {
8-
getText() {
9-
getMockText().then(function (result) {
10-
console.log(result);
11-
});
12-
}
13-
render() {
14-
return (
15-
<div className="App">
16-
<header>
17-
<span>Simple Text Editor</span>
18-
</header>
19-
<main>
20-
<ControlPanel/>
21-
<FileZone/>
22-
</main>
23-
</div>
24-
);
25-
}
6+
function App() {
7+
const [text, setText] = useState('');
8+
9+
useEffect(() => {
10+
getMockText().then(mockText => setText(mockText))
11+
});
12+
13+
return (
14+
<div className="App">
15+
<header>
16+
<span>Simple Text Editor</span>
17+
</header>
18+
<main>
19+
<TextEditor text={text}/>
20+
</main>
21+
</div>
22+
);
2623
}
2724

2825
export default App;

src/control-panel/ControlPanel.js

Lines changed: 0 additions & 18 deletions
This file was deleted.

src/file-zone/FileZone.js

Lines changed: 0 additions & 16 deletions
This file was deleted.

src/control-panel/ControlPanel.css renamed to src/text-editor/control-panel/ControlPanel.css

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,3 +10,7 @@
1010
width: 200px;
1111
margin-right: 400px;
1212
}
13+
14+
.active {
15+
background-color: red;
16+
}
Lines changed: 99 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,99 @@
1+
import React, {useState, useEffect} from 'react';
2+
import './ControlPanel.css';
3+
import {formatSelection} from "../format/format.utils";
4+
import {fromEvent} from "rxjs";
5+
import {map, tap} from "rxjs/operators";
6+
7+
const store = new WeakMap();
8+
9+
function storeFormat(node, format) {
10+
if (store.has(node)) {
11+
const formats = store.get(node);
12+
formats.has(format) ? formats.delete(format) : formats.add(format);
13+
if (formats.size) {
14+
store.set(node, formats)
15+
} else {
16+
store.delete(node);
17+
}
18+
} else {
19+
store.set(node, new Set([format]));
20+
}
21+
22+
console.info(store);
23+
}
24+
25+
function ControlPanel() {
26+
const [isBold, setIsBold] = useState(false);
27+
const [isItalic, setItalic] = useState(false);
28+
const [isUnderline, setUnderline] = useState(false);
29+
30+
useEffect(() => {
31+
const sink = fromEvent(document, 'selectionchange')
32+
.pipe(
33+
map(() => getSelection()),
34+
tap(Selection => console.info(Selection, Selection.focusOffset)),
35+
map(selection => selection.focusNode)
36+
)
37+
.subscribe(
38+
(focusNode) => {
39+
if (store.has(focusNode)) {
40+
const formats = Array.from(store.get(focusNode));
41+
setIsBold(formats.includes('bold'));
42+
setItalic(formats.includes('italic'));
43+
setUnderline(formats.includes('underline'));
44+
45+
console.info(focusNode, formats);
46+
} else {
47+
setIsBold(false);
48+
setItalic(false);
49+
setUnderline(false);
50+
}
51+
}
52+
);
53+
54+
return () => sink.unsubscribe();
55+
});
56+
57+
58+
function makeSelectionBold() {
59+
formatSelection('bold');
60+
storeFormat(getSelection().focusNode, 'bold');
61+
}
62+
63+
function makeSelectionItalic() {
64+
formatSelection('italic');
65+
storeFormat(getSelection().focusNode, 'italic');
66+
}
67+
68+
function makeSelectionUnderline() {
69+
formatSelection('underline');
70+
storeFormat(getSelection().focusNode, 'underline');
71+
}
72+
73+
return (
74+
<div id="control-panel">
75+
<div id="format-actions">
76+
<button
77+
className={`format-action${ isBold ? ' active' : '' }`}
78+
type="button"
79+
onClick={makeSelectionBold}>
80+
<b>B</b>
81+
</button>
82+
<button
83+
className={`format-action${ isItalic ? ' active' : '' }`}
84+
type="button"
85+
onClick={makeSelectionItalic}>
86+
<i>I</i>
87+
</button>
88+
<button
89+
className={`format-action${ isUnderline ? ' active' : '' }`}
90+
type="button"
91+
onClick={makeSelectionUnderline}>
92+
<u>U</u>
93+
</button>
94+
</div>
95+
</div>
96+
);
97+
}
98+
99+
export default ControlPanel;
Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
import React, {useState, useEffect} from 'react';
2+
import './FileZone.css';
3+
4+
function FileZone({text}) {
5+
console.log('render FileZone');
6+
7+
return (
8+
<div id="file-zone">
9+
<div
10+
id="file"
11+
contentEditable="true"
12+
suppressContentEditableWarning={true}>
13+
{text}
14+
</div>
15+
</div>
16+
);
17+
}
18+
19+
export default FileZone;

0 commit comments

Comments
 (0)