@flozy/editor 1.0.5 → 1.0.7
Sign up to get free protection for your applications and to get access to all the features.
- package/dist/Editor/CollaborativeEditor.js +116 -0
- package/dist/Editor/CommonEditor.js +132 -0
- package/dist/Editor/Editor.css +115 -0
- package/dist/Editor/Elements/CodeToText/CodeToText.css +57 -0
- package/dist/Editor/Elements/CodeToText/CodeToText.js +112 -0
- package/dist/Editor/Elements/CodeToText/CodeToTextButton.js +18 -0
- package/dist/Editor/Elements/CodeToText/HtmlCode.js +54 -0
- package/dist/Editor/Elements/CodeToText/HtmlContextMenu.js +39 -0
- package/dist/Editor/Elements/Color Picker/ColorPicker.css +38 -0
- package/dist/Editor/Elements/Color Picker/ColorPicker.js +116 -0
- package/dist/Editor/Elements/Color Picker/defaultColors.js +1 -0
- package/dist/Editor/Elements/Embed/Embed.css +14 -0
- package/dist/Editor/Elements/Embed/Embed.js +94 -0
- package/dist/Editor/Elements/Embed/Image.js +70 -0
- package/dist/Editor/Elements/Embed/Video.js +62 -0
- package/dist/Editor/Elements/Equation/Equation.js +24 -0
- package/dist/Editor/Elements/Equation/EquationButton.js +66 -0
- package/dist/Editor/Elements/Equation/styles.css +4 -0
- package/dist/Editor/Elements/Grid/Grid.js +53 -0
- package/dist/Editor/Elements/Grid/GridButton.js +19 -0
- package/dist/Editor/Elements/Grid/GridItem.js +53 -0
- package/dist/Editor/Elements/ID/Id.js +56 -0
- package/dist/Editor/Elements/Link/Link.js +34 -0
- package/dist/Editor/Elements/Link/LinkButton.js +77 -0
- package/dist/Editor/Elements/Link/styles.css +20 -0
- package/dist/Editor/Elements/Mentions/Mentions.js +34 -0
- package/dist/Editor/Elements/NewLine/NewLineButton.js +22 -0
- package/dist/Editor/Elements/Table/Table.js +15 -0
- package/dist/Editor/Elements/Table/TableSelector.css +18 -0
- package/dist/Editor/Elements/Table/TableSelector.js +93 -0
- package/dist/Editor/Elements/TableContextMenu/TableContextMenu.js +91 -0
- package/dist/Editor/Elements/TableContextMenu/styles.css +18 -0
- package/dist/Editor/RemoteCursorOverlay/Overlay.js +75 -0
- package/dist/Editor/Toolbar/Toolbar.js +166 -0
- package/dist/Editor/Toolbar/styles.css +28 -0
- package/dist/Editor/Toolbar/toolbarGroups.js +131 -0
- package/dist/Editor/Toolbar/toolbarIcons/align-center.svg +1 -0
- package/dist/Editor/Toolbar/toolbarIcons/align-left.svg +1 -0
- package/dist/Editor/Toolbar/toolbarIcons/align-right.svg +1 -0
- package/dist/Editor/Toolbar/toolbarIcons/blockquote.svg +1 -0
- package/dist/Editor/Toolbar/toolbarIcons/bold.png +0 -0
- package/dist/Editor/Toolbar/toolbarIcons/fontColor.svg +4 -0
- package/dist/Editor/Toolbar/toolbarIcons/headingOne.svg +3 -0
- package/dist/Editor/Toolbar/toolbarIcons/headingTwo.svg +3 -0
- package/dist/Editor/Toolbar/toolbarIcons/italic.png +0 -0
- package/dist/Editor/Toolbar/toolbarIcons/link.svg +1 -0
- package/dist/Editor/Toolbar/toolbarIcons/orderedList.svg +1 -0
- package/dist/Editor/Toolbar/toolbarIcons/strikethrough.png +0 -0
- package/dist/Editor/Toolbar/toolbarIcons/subscript.svg +1 -0
- package/dist/Editor/Toolbar/toolbarIcons/superscript.svg +1 -0
- package/dist/Editor/Toolbar/toolbarIcons/textColor.png +0 -0
- package/dist/Editor/Toolbar/toolbarIcons/underline.png +0 -0
- package/dist/Editor/Toolbar/toolbarIcons/unlink.svg +1 -0
- package/dist/Editor/Toolbar/toolbarIcons/unorderedList.svg +1 -0
- package/dist/Editor/YjsProvider.js +9 -0
- package/dist/Editor/common/Button.js +21 -0
- package/dist/Editor/common/Icon.js +114 -0
- package/dist/Editor/common/MentionsPopup.js +54 -0
- package/dist/Editor/hooks/useMentions.js +44 -0
- package/dist/Editor/hooks/withCollaborative.js +15 -0
- package/dist/Editor/hooks/withCommon.js +11 -0
- package/dist/Editor/plugins/withEmbeds.js +29 -0
- package/dist/Editor/plugins/withEquation.js +8 -0
- package/dist/Editor/plugins/withLinks.js +8 -0
- package/dist/Editor/plugins/withMentions.js +18 -0
- package/dist/Editor/plugins/withTable.js +61 -0
- package/dist/Editor/utils/SlateUtilityFunctions.js +224 -0
- package/dist/Editor/utils/customHooks/useContextMenu.js +37 -0
- package/dist/Editor/utils/customHooks/useFormat.js +21 -0
- package/dist/Editor/utils/customHooks/usePopup.js +21 -0
- package/dist/Editor/utils/customHooks/useResize.js +47 -0
- package/dist/Editor/utils/draftToSlate.js +111 -0
- package/dist/Editor/utils/embed.js +24 -0
- package/dist/Editor/utils/equation.js +23 -0
- package/dist/Editor/utils/events.js +76 -0
- package/dist/Editor/utils/grid.js +13 -0
- package/dist/Editor/utils/gridItem.js +19 -0
- package/dist/Editor/utils/link.js +52 -0
- package/dist/Editor/utils/mentions.js +12 -0
- package/dist/Editor/utils/paragraph.js +6 -0
- package/dist/Editor/utils/serializer.js +28 -0
- package/dist/Editor/utils/table.js +129 -0
- package/dist/index.js +4 -0
- package/package.json +18 -8
@@ -0,0 +1,116 @@
|
|
1
|
+
import React, { useEffect, useMemo, useState } from "react";
|
2
|
+
import * as Y from "yjs";
|
3
|
+
import { HocuspocusProvider } from "@hocuspocus/provider";
|
4
|
+
import { Editor, Transforms } from "slate";
|
5
|
+
import { YjsEditor } from "@slate-yjs/core";
|
6
|
+
import "./Editor.css";
|
7
|
+
import { draftToSlate } from "./utils/draftToSlate";
|
8
|
+
import withCommon from "./hooks/withCommon";
|
9
|
+
import withCollaborative from "./hooks/withCollaborative";
|
10
|
+
import CommonEditor from "./CommonEditor";
|
11
|
+
const CollaborativeEditor = props => {
|
12
|
+
const {
|
13
|
+
id,
|
14
|
+
content,
|
15
|
+
onSave,
|
16
|
+
user,
|
17
|
+
socketURL
|
18
|
+
} = props;
|
19
|
+
const convertedContent = draftToSlate({
|
20
|
+
data: content
|
21
|
+
});
|
22
|
+
const [value] = useState(convertedContent);
|
23
|
+
const [connected, setConnected] = useState(null);
|
24
|
+
const [authenticated, setAuthenticated] = useState({
|
25
|
+
status: null,
|
26
|
+
scope: null
|
27
|
+
});
|
28
|
+
const provider = useMemo(() => {
|
29
|
+
return new HocuspocusProvider({
|
30
|
+
url: socketURL,
|
31
|
+
name: `document-${id}`,
|
32
|
+
connect: false,
|
33
|
+
token: user?.token
|
34
|
+
});
|
35
|
+
}, []);
|
36
|
+
|
37
|
+
// setup changes for Yjs
|
38
|
+
const editor = useMemo(() => {
|
39
|
+
if (!connected) return null;
|
40
|
+
const sharedType = provider.document.get("content", Y.XmlText);
|
41
|
+
const e = withCommon(withCollaborative({
|
42
|
+
provider,
|
43
|
+
sharedType,
|
44
|
+
data: user
|
45
|
+
}));
|
46
|
+
|
47
|
+
// Ensure editor always has at least 1 valid child
|
48
|
+
const {
|
49
|
+
normalizeNode
|
50
|
+
} = e;
|
51
|
+
e.normalizeNode = entry => {
|
52
|
+
const [node] = entry;
|
53
|
+
if (!Editor.isEditor(node) || node.children.length > 0) {
|
54
|
+
return normalizeNode(entry);
|
55
|
+
}
|
56
|
+
Transforms.insertNodes(editor, value, {
|
57
|
+
at: [0]
|
58
|
+
});
|
59
|
+
};
|
60
|
+
return e;
|
61
|
+
}, [provider.document, provider.awareness, connected]);
|
62
|
+
|
63
|
+
// connect Yjs
|
64
|
+
useEffect(() => {
|
65
|
+
provider.connect();
|
66
|
+
return () => {
|
67
|
+
provider.disconnect(editor);
|
68
|
+
};
|
69
|
+
}, [provider]);
|
70
|
+
|
71
|
+
// connect to editor
|
72
|
+
useEffect(() => {
|
73
|
+
if (editor) {
|
74
|
+
YjsEditor.connect(editor);
|
75
|
+
}
|
76
|
+
return () => {
|
77
|
+
if (editor) {
|
78
|
+
YjsEditor.disconnect(editor);
|
79
|
+
}
|
80
|
+
};
|
81
|
+
}, [editor]);
|
82
|
+
provider.on("authenticated", () => {
|
83
|
+
setAuthenticated({
|
84
|
+
status: true,
|
85
|
+
scope: provider.authorizedScope
|
86
|
+
});
|
87
|
+
});
|
88
|
+
provider.on("authenticationFailed", () => {
|
89
|
+
setAuthenticated({
|
90
|
+
status: false,
|
91
|
+
scope: null
|
92
|
+
});
|
93
|
+
});
|
94
|
+
provider.on("synced", () => {
|
95
|
+
setConnected(true);
|
96
|
+
});
|
97
|
+
provider.on("disconnect", () => {
|
98
|
+
setConnected(false);
|
99
|
+
});
|
100
|
+
provider.on("close", () => {
|
101
|
+
setConnected(false);
|
102
|
+
});
|
103
|
+
if (authenticated.status === null || !connected === null || !editor) {
|
104
|
+
return /*#__PURE__*/React.createElement("h1", {
|
105
|
+
"data-status": connected
|
106
|
+
}, "Loading...");
|
107
|
+
}
|
108
|
+
return /*#__PURE__*/React.createElement(CommonEditor, {
|
109
|
+
editor: editor,
|
110
|
+
id: id,
|
111
|
+
content: [],
|
112
|
+
onSave: onSave,
|
113
|
+
readOnly: authenticated.scope
|
114
|
+
});
|
115
|
+
};
|
116
|
+
export default CollaborativeEditor;
|
@@ -0,0 +1,132 @@
|
|
1
|
+
function _extends() { _extends = Object.assign ? Object.assign.bind() : function (target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i]; for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { target[key] = source[key]; } } } return target; }; return _extends.apply(this, arguments); }
|
2
|
+
import React, { useCallback, useEffect, useMemo, useState } from "react";
|
3
|
+
import { Slate, Editable } from "slate-react";
|
4
|
+
import Toolbar from "./Toolbar/Toolbar";
|
5
|
+
import { getMarked, getBlock } from "./utils/SlateUtilityFunctions";
|
6
|
+
import "./Editor.css";
|
7
|
+
import CodeToText from "./Elements/CodeToText/CodeToText";
|
8
|
+
import { draftToSlate } from "./utils/draftToSlate";
|
9
|
+
import useMentions from "./hooks/useMentions";
|
10
|
+
import MentionsPopup from "./common/MentionsPopup";
|
11
|
+
import { RemoteCursorOverlay } from "./RemoteCursorOverlay/Overlay";
|
12
|
+
import { mentionsEvent, commands } from "./utils/events";
|
13
|
+
import withCommon from "./hooks/withCommon";
|
14
|
+
import { createEditor } from "slate";
|
15
|
+
const Element = props => {
|
16
|
+
return getBlock(props);
|
17
|
+
};
|
18
|
+
const Leaf = ({
|
19
|
+
attributes,
|
20
|
+
children,
|
21
|
+
leaf
|
22
|
+
}) => {
|
23
|
+
children = getMarked(leaf, children);
|
24
|
+
return /*#__PURE__*/React.createElement("span", attributes, children);
|
25
|
+
};
|
26
|
+
const CommonEditor = props => {
|
27
|
+
const {
|
28
|
+
id,
|
29
|
+
content,
|
30
|
+
onSave,
|
31
|
+
editor: collaborativeEditor,
|
32
|
+
readOnly
|
33
|
+
} = props;
|
34
|
+
const convertedContent = draftToSlate({
|
35
|
+
data: content
|
36
|
+
});
|
37
|
+
const [value, setValue] = useState(convertedContent);
|
38
|
+
const editor = useMemo(() => {
|
39
|
+
if (collaborativeEditor) return collaborativeEditor;
|
40
|
+
return withCommon(createEditor());
|
41
|
+
}, [collaborativeEditor]);
|
42
|
+
useEffect(() => {
|
43
|
+
setValue(draftToSlate({
|
44
|
+
data: content
|
45
|
+
}));
|
46
|
+
}, [id, content]);
|
47
|
+
const [htmlAction, setHtmlAction] = useState({
|
48
|
+
showInput: false,
|
49
|
+
html: "",
|
50
|
+
action: "",
|
51
|
+
location: ""
|
52
|
+
});
|
53
|
+
const [mentions, setMentions] = useMentions({
|
54
|
+
editor,
|
55
|
+
selection: editor?.selection
|
56
|
+
});
|
57
|
+
const {
|
58
|
+
search,
|
59
|
+
target,
|
60
|
+
index
|
61
|
+
} = mentions;
|
62
|
+
const chars = CHARACTERS.filter(c => c.toLowerCase().startsWith(search?.toLowerCase())).slice(0, 10);
|
63
|
+
const handleEditorChange = newValue => {
|
64
|
+
setValue(newValue);
|
65
|
+
const isAstChange = editor.operations.some(op => "set_selection" !== op.type);
|
66
|
+
if (isAstChange && onSave) {
|
67
|
+
// send the value to onSave api
|
68
|
+
onSave(JSON.stringify(value));
|
69
|
+
}
|
70
|
+
};
|
71
|
+
const renderElement = useCallback(props => /*#__PURE__*/React.createElement(Element, props), []);
|
72
|
+
const renderLeaf = useCallback(props => {
|
73
|
+
return /*#__PURE__*/React.createElement(Leaf, props);
|
74
|
+
}, []);
|
75
|
+
const handleCodeToText = partialState => {
|
76
|
+
setHtmlAction(prev => ({
|
77
|
+
...prev,
|
78
|
+
...partialState
|
79
|
+
}));
|
80
|
+
};
|
81
|
+
const onKeyDown = useCallback(event => {
|
82
|
+
const isCtrlKey = event.ctrlKey || event.metaKey && event.keyCode >= 65 && event.keyCode <= 90;
|
83
|
+
if (target && chars.length > 0 && !isCtrlKey) {
|
84
|
+
mentionsEvent({
|
85
|
+
event,
|
86
|
+
mentions,
|
87
|
+
setMentions,
|
88
|
+
chars,
|
89
|
+
target,
|
90
|
+
editor
|
91
|
+
});
|
92
|
+
} else if (isCtrlKey) {
|
93
|
+
commands({
|
94
|
+
event,
|
95
|
+
editor
|
96
|
+
});
|
97
|
+
}
|
98
|
+
}, [chars, editor, target, mentions, setMentions]);
|
99
|
+
const isReadOnly = readOnly === "readonly";
|
100
|
+
const Overlay = collaborativeEditor && !isReadOnly ? RemoteCursorOverlay : React.Fragment;
|
101
|
+
return /*#__PURE__*/React.createElement(Slate, {
|
102
|
+
key: id,
|
103
|
+
editor: editor,
|
104
|
+
initialValue: value,
|
105
|
+
onChange: handleEditorChange
|
106
|
+
}, /*#__PURE__*/React.createElement(Overlay, null, !isReadOnly ? /*#__PURE__*/React.createElement(Toolbar, {
|
107
|
+
handleCodeToText: handleCodeToText
|
108
|
+
}) : null, /*#__PURE__*/React.createElement("div", {
|
109
|
+
className: "editor-wrapper",
|
110
|
+
style: {
|
111
|
+
border: "1px solid #f3f3f3",
|
112
|
+
padding: "0 10px"
|
113
|
+
}
|
114
|
+
}, /*#__PURE__*/React.createElement(Editable, {
|
115
|
+
readOnly: isReadOnly,
|
116
|
+
placeholder: "Write something",
|
117
|
+
renderElement: renderElement,
|
118
|
+
renderLeaf: renderLeaf,
|
119
|
+
onKeyDown: onKeyDown
|
120
|
+
}), /*#__PURE__*/React.createElement(MentionsPopup, {
|
121
|
+
mentions: mentions,
|
122
|
+
setMentions: setMentions,
|
123
|
+
editor: editor,
|
124
|
+
target: target,
|
125
|
+
index: index,
|
126
|
+
chars: chars
|
127
|
+
}))), htmlAction.showInput && /*#__PURE__*/React.createElement(CodeToText, _extends({}, htmlAction, {
|
128
|
+
handleCodeToText: handleCodeToText
|
129
|
+
})));
|
130
|
+
};
|
131
|
+
const CHARACTERS = ["Aayla Secura", "Adi Gallia", "Admiral Dodd Rancit", "Admiral Firmus Piett", "Admiral Gial Ackbar", "Admiral Ozzel", "Admiral Raddus", "Admiral Terrinald Screed", "Admiral Trench", "Admiral U.O. Statura", "Agen Kolar", "Agent Kallus", "Aiolin and Morit Astarte", "Aks Moe", "Almec", "Alton Kastle", "Amee", "AP-5", "Armitage Hux", "Artoo", "Arvel Crynyd", "Asajj Ventress", "Aurra Sing", "AZI-3", "Bala-Tik", "Barada", "Bargwill Tomder", "Baron Papanoida", "Barriss Offee", "Baze Malbus", "Bazine Netal", "BB-8", "BB-9E", "Ben Quadinaros", "Berch Teller", "Beru Lars", "Bib Fortuna", "Biggs Darklighter", "Black Krrsantan", "Bo-Katan Kryze", "Boba Fett", "Bobbajo", "Bodhi Rook", "Borvo the Hutt", "Boss Nass", "Bossk", "Breha Antilles-Organa", "Bren Derlin", "Brendol Hux", "BT-1", "C-3PO", "C1-10P", "Cad Bane", "Caluan Ematt", "Captain Gregor", "Captain Phasma", "Captain Quarsh Panaka", "Captain Rex", "Carlist Rieekan", "Casca Panzoro", "Cassian Andor", "Cassio Tagge", "Cham Syndulla", "Che Amanwe Papanoida", "Chewbacca", "Chi Eekway Papanoida", "Chief Chirpa", "Chirrut Îmwe", "Ciena Ree", "Cin Drallig", "Clegg Holdfast", "Cliegg Lars", "Coleman Kcaj", "Coleman Trebor", "Colonel Kaplan", "Commander Bly", "Commander Cody (CC-2224)", "Commander Fil (CC-3714)", "Commander Fox", "Commander Gree", "Commander Jet", "Commander Wolffe", "Conan Antonio Motti", "Conder Kyl", "Constable Zuvio", "Cordé", "Cpatain Typho", "Crix Madine", "Cut Lawquane", "Dak Ralter", "Dapp", "Darth Bane", "Darth Maul", "Darth Tyranus", "Daultay Dofine", "Del Meeko", "Delian Mors", "Dengar", "Depa Billaba", "Derek Klivian", "Dexter Jettster", "Dineé Ellberger", "DJ", "Doctor Aphra", "Doctor Evazan", "Dogma", "Dormé", "Dr. Cylo", "Droidbait", "Droopy McCool", "Dryden Vos", "Dud Bolt", "Ebe E. Endocott", "Echuu Shen-Jon", "Eeth Koth", "Eighth Brother", "Eirtaé", "Eli Vanto", "Ellé", "Ello Asty", "Embo", "Eneb Ray", "Enfys Nest", "EV-9D9", "Evaan Verlaine", "Even Piell", "Ezra Bridger", "Faro Argyus", "Feral", "Fifth Brother", "Finis Valorum", "Finn", "Fives", "FN-1824", "FN-2003", "Fodesinbeed Annodue", "Fulcrum", "FX-7", "GA-97", "Galen Erso", "Gallius Rax", 'Garazeb "Zeb" Orrelios', "Gardulla the Hutt", "Garrick Versio", "Garven Dreis", "Gavyn Sykes", "Gideon Hask", "Gizor Dellso", "Gonk droid", "Grand Inquisitor", "Greeata Jendowanian", "Greedo", "Greer Sonnel", "Grievous", "Grummgar", "Gungi", "Hammerhead", "Han Solo", "Harter Kalonia", "Has Obbit", "Hera Syndulla", "Hevy", "Hondo Ohnaka", "Huyang", "Iden Versio", "IG-88", "Ima-Gun Di", "Inquisitors", "Inspector Thanoth", "Jabba", "Jacen Syndulla", "Jan Dodonna", "Jango Fett", "Janus Greejatus", "Jar Jar Binks", "Jas Emari", "Jaxxon", "Jek Tono Porkins", "Jeremoch Colton", "Jira", "Jobal Naberrie", "Jocasta Nu", "Joclad Danva", "Joh Yowza", "Jom Barell", "Joph Seastriker", "Jova Tarkin", "Jubnuk", "Jyn Erso", "K-2SO", "Kanan Jarrus", "Karbin", "Karina the Great", "Kes Dameron", "Ketsu Onyo", "Ki-Adi-Mundi", "King Katuunko", "Kit Fisto", "Kitster Banai", "Klaatu", "Klik-Klak", "Korr Sella", "Kylo Ren", "L3-37", "Lama Su", "Lando Calrissian", "Lanever Villecham", "Leia Organa", "Letta Turmond", "Lieutenant Kaydel Ko Connix", "Lieutenant Thire", "Lobot", "Logray", "Lok Durd", "Longo Two-Guns", "Lor San Tekka", "Lorth Needa", "Lott Dod", "Luke Skywalker", "Lumat", "Luminara Unduli", "Lux Bonteri", "Lyn Me", "Lyra Erso", "Mace Windu", "Malakili", "Mama the Hutt", "Mars Guo", "Mas Amedda", "Mawhonic", "Max Rebo", "Maximilian Veers", "Maz Kanata", "ME-8D9", "Meena Tills", "Mercurial Swift", "Mina Bonteri", "Miraj Scintel", "Mister Bones", "Mod Terrik", "Moden Canady", "Mon Mothma", "Moradmin Bast", "Moralo Eval", "Morley", "Mother Talzin", "Nahdar Vebb", "Nahdonnis Praji", "Nien Nunb", "Niima the Hutt", "Nines", "Norra Wexley", "Nute Gunray", "Nuvo Vindi", "Obi-Wan Kenobi", "Odd Ball", "Ody Mandrell", "Omi", "Onaconda Farr", "Oola", "OOM-9", "Oppo Rancisis", "Orn Free Taa", "Oro Dassyne", "Orrimarko", "Osi Sobeck", "Owen Lars", "Pablo-Jill", "Padmé Amidala", "Pagetti Rook", "Paige Tico", "Paploo", "Petty Officer Thanisson", "Pharl McQuarrie", "Plo Koon", "Po Nudo", "Poe Dameron", "Poggle the Lesser", "Pong Krell", "Pooja Naberrie", "PZ-4CO", "Quarrie", "Quay Tolsite", "Queen Apailana", "Queen Jamillia", "Queen Neeyutnee", "Qui-Gon Jinn", "Quiggold", "Quinlan Vos", "R2-D2", "R2-KT", "R3-S6", "R4-P17", "R5-D4", "RA-7", "Rabé", "Rako Hardeen", "Ransolm Casterfo", "Rappertunie", "Ratts Tyerell", "Raymus Antilles", "Ree-Yees", "Reeve Panzoro", "Rey", "Ric Olié", "Riff Tamson", "Riley", "Rinnriyin Di", "Rio Durant", "Rogue Squadron", "Romba", "Roos Tarpals", "Rose Tico", "Rotta the Hutt", "Rukh", "Rune Haako", "Rush Clovis", "Ruwee Naberrie", "Ryoo Naberrie", "Sabé", "Sabine Wren", "Saché", "Saelt-Marae", "Saesee Tiin", "Salacious B. Crumb", "San Hill", "Sana Starros", "Sarco Plank", "Sarkli", "Satine Kryze", "Savage Opress", "Sebulba", "Senator Organa", "Sergeant Kreel", "Seventh Sister", "Shaak Ti", "Shara Bey", "Shmi Skywalker", "Shu Mai", "Sidon Ithano", "Sifo-Dyas", "Sim Aloo", "Siniir Rath Velus", "Sio Bibble", "Sixth Brother", "Slowen Lo", "Sly Moore", "Snaggletooth", "Snap Wexley", "Snoke", "Sola Naberrie", "Sora Bulq", "Strono Tuggs", "Sy Snootles", "Tallissan Lintra", "Tarfful", "Tasu Leech", "Taun We", "TC-14", "Tee Watt Kaa", "Teebo", "Teedo", "Teemto Pagalies", "Temiri Blagg", "Tessek", "Tey How", "Thane Kyrell", "The Bendu", "The Smuggler", "Thrawn", "Tiaan Jerjerrod", "Tion Medon", "Tobias Beckett", "Tulon Voidgazer", "Tup", "U9-C4", "Unkar Plutt", "Val Beckett", "Vanden Willard", "Vice Admiral Amilyn Holdo", "Vober Dand", "WAC-47", "Wag Too", "Wald", "Walrus Man", "Warok", "Wat Tambor", "Watto", "Wedge Antilles", "Wes Janson", "Wicket W. Warrick", "Wilhuff Tarkin", "Wollivan", "Wuher", "Wullf Yularen", "Xamuel Lennox", "Yaddle", "Yarael Poof", "Yoda", "Zam Wesell", "Zev Senesca", "Ziro the Hutt", "Zuckuss"];
|
132
|
+
export default CommonEditor;
|
@@ -0,0 +1,115 @@
|
|
1
|
+
blockquote{
|
2
|
+
border-left: 2px solid #ddd;
|
3
|
+
margin-left: 0;
|
4
|
+
margin-right: 0;
|
5
|
+
padding-left: 10px;
|
6
|
+
color: #aaa;
|
7
|
+
font-style: italic;
|
8
|
+
}
|
9
|
+
table, th, td {
|
10
|
+
border: 1px solid black;
|
11
|
+
}
|
12
|
+
table{
|
13
|
+
border-collapse: collapse;
|
14
|
+
}
|
15
|
+
button{
|
16
|
+
background-color: white;
|
17
|
+
border:none;
|
18
|
+
opacity: 0.5;
|
19
|
+
}
|
20
|
+
.btnActive{
|
21
|
+
opacity: 1;
|
22
|
+
}
|
23
|
+
.editor-wrapper{
|
24
|
+
font-family:'Helvetica','Arial', sans-serif;
|
25
|
+
border-radius: 10px;
|
26
|
+
background: #ffffff;
|
27
|
+
box-shadow: -8px 8px 13px #ededed,
|
28
|
+
8px -8px 13px #ffffff;
|
29
|
+
min-height: 400px;
|
30
|
+
min-width: 100%;
|
31
|
+
width: fit-content;
|
32
|
+
height: fit-content;
|
33
|
+
padding: 12px 10px;
|
34
|
+
max-width: 100%;
|
35
|
+
}
|
36
|
+
table{
|
37
|
+
width:100%;
|
38
|
+
}
|
39
|
+
td{
|
40
|
+
height: 50px;
|
41
|
+
padding:0 5px;
|
42
|
+
}
|
43
|
+
.popup-wrapper{
|
44
|
+
display: inline;
|
45
|
+
position: relative;
|
46
|
+
}
|
47
|
+
.popup{
|
48
|
+
position: fixed;
|
49
|
+
left: 0;
|
50
|
+
right: 0;
|
51
|
+
top: 0;
|
52
|
+
bottom: 0;
|
53
|
+
margin: auto;
|
54
|
+
background-color: white;
|
55
|
+
padding: 6px 10px;
|
56
|
+
border: 1px solid lightgray;
|
57
|
+
height: fit-content;
|
58
|
+
z-index: 1;
|
59
|
+
width: 300px;
|
60
|
+
|
61
|
+
}
|
62
|
+
button{
|
63
|
+
cursor: pointer;
|
64
|
+
}
|
65
|
+
code {
|
66
|
+
font-family: source-code-pro, Menlo, Monaco, Consolas, 'Courier New',
|
67
|
+
monospace;
|
68
|
+
}
|
69
|
+
[data-slate-node="element"] {
|
70
|
+
margin: 10px 0;
|
71
|
+
}
|
72
|
+
html{
|
73
|
+
scroll-behavior: smooth;
|
74
|
+
}
|
75
|
+
.editor-wrapper *:focus-visible {
|
76
|
+
outline: none;
|
77
|
+
}
|
78
|
+
|
79
|
+
.grid-container {
|
80
|
+
display: flex;
|
81
|
+
border-radius: 12px;
|
82
|
+
background-color: #F3F6F9;
|
83
|
+
border: 1px solid #E5EAF2;
|
84
|
+
padding: 16px;
|
85
|
+
position: relative;
|
86
|
+
flex-wrap: wrap;
|
87
|
+
}
|
88
|
+
|
89
|
+
.grid-container-toolbar,
|
90
|
+
.grid-item-toolbar {
|
91
|
+
position: absolute;
|
92
|
+
right: 0;
|
93
|
+
top: 0;
|
94
|
+
}
|
95
|
+
|
96
|
+
.grid-item {
|
97
|
+
padding: 16px;
|
98
|
+
background-color: #fff;
|
99
|
+
position: relative;
|
100
|
+
}
|
101
|
+
|
102
|
+
@media (max-width: 480px) {
|
103
|
+
.toolbar {
|
104
|
+
display: flex;
|
105
|
+
flex-wrap: nowrap;
|
106
|
+
overflow-x: scroll;
|
107
|
+
}
|
108
|
+
.toolbar-grp,
|
109
|
+
.toolbar-grp > div {
|
110
|
+
display: flex;
|
111
|
+
}
|
112
|
+
.grid-item {
|
113
|
+
width: 100% !important;
|
114
|
+
}
|
115
|
+
}
|
@@ -0,0 +1,57 @@
|
|
1
|
+
|
2
|
+
.code-wrapper{
|
3
|
+
position: fixed;
|
4
|
+
top: 0;
|
5
|
+
left: 0;
|
6
|
+
width: 100vw;
|
7
|
+
height: 100vh;
|
8
|
+
background:rgba(0,0, 0,0.9);
|
9
|
+
z-index:2;
|
10
|
+
display: flex;
|
11
|
+
justify-content: center;
|
12
|
+
align-items: center;
|
13
|
+
|
14
|
+
}
|
15
|
+
.codeToTextWrapper{
|
16
|
+
width: 80%;
|
17
|
+
height: 80%;
|
18
|
+
grid-template-columns: 45% 10% 45%;
|
19
|
+
}
|
20
|
+
.codeToText{
|
21
|
+
width: 100%;
|
22
|
+
height: 90%;
|
23
|
+
display: grid;
|
24
|
+
grid-template-columns: 45% 10% 45%;
|
25
|
+
}
|
26
|
+
.codeToText textarea,.textOutput{
|
27
|
+
border-radius: 15px;
|
28
|
+
padding: 10px;
|
29
|
+
}
|
30
|
+
|
31
|
+
.codeToText textarea{
|
32
|
+
resize: none;
|
33
|
+
}
|
34
|
+
.codeToText textarea:focus{
|
35
|
+
outline: none;
|
36
|
+
}
|
37
|
+
.textOutput{
|
38
|
+
background: #fff;
|
39
|
+
overflow: scroll;
|
40
|
+
}
|
41
|
+
.codeToTextWrapper button{
|
42
|
+
margin: 3% 1%;
|
43
|
+
padding: 10px 37px;
|
44
|
+
cursor: pointer;
|
45
|
+
border-radius: 5px;
|
46
|
+
opacity: 1;
|
47
|
+
font-weight: bolder;
|
48
|
+
}
|
49
|
+
.done{
|
50
|
+
background: #44c767;
|
51
|
+
color:#fff;
|
52
|
+
}
|
53
|
+
.clear{
|
54
|
+
background: #fff;
|
55
|
+
color:#a9a4a4;
|
56
|
+
border:1px solid lightgray;
|
57
|
+
}
|
@@ -0,0 +1,112 @@
|
|
1
|
+
import React, { useEffect, useRef } from "react";
|
2
|
+
import "./CodeToText.css";
|
3
|
+
import Icon from "../../common/Icon";
|
4
|
+
import { Interweave } from "interweave";
|
5
|
+
import { Transforms } from "slate";
|
6
|
+
import { useSlateStatic } from "slate-react";
|
7
|
+
const CodeToText = props => {
|
8
|
+
const {
|
9
|
+
html,
|
10
|
+
action,
|
11
|
+
location,
|
12
|
+
handleCodeToText
|
13
|
+
} = props;
|
14
|
+
const codeToTextRef = useRef();
|
15
|
+
const wrapperRef = useRef();
|
16
|
+
const editor = useSlateStatic();
|
17
|
+
const checkClick = e => {
|
18
|
+
const clickedComponent = e.target;
|
19
|
+
if (wrapperRef?.current?.contains(clickedComponent) && !codeToTextRef?.current?.contains(clickedComponent)) {
|
20
|
+
let partialState = {
|
21
|
+
showInput: false
|
22
|
+
};
|
23
|
+
if (html) {
|
24
|
+
partialState.html = action === "update" ? "" : html;
|
25
|
+
}
|
26
|
+
handleCodeToText(partialState);
|
27
|
+
}
|
28
|
+
};
|
29
|
+
useEffect(() => {
|
30
|
+
document.addEventListener("click", checkClick);
|
31
|
+
return () => {
|
32
|
+
document.removeEventListener("click", checkClick);
|
33
|
+
};
|
34
|
+
}, []);
|
35
|
+
const codeOnChange = async e => {
|
36
|
+
// e.preventDefault();
|
37
|
+
handleCodeToText({
|
38
|
+
html: e.target.value
|
39
|
+
});
|
40
|
+
};
|
41
|
+
const addHtml = () => {
|
42
|
+
if (html) {
|
43
|
+
if (action === "update") {
|
44
|
+
Transforms.setNodes(editor, {
|
45
|
+
html
|
46
|
+
}, {
|
47
|
+
at: location
|
48
|
+
});
|
49
|
+
} else {
|
50
|
+
Transforms.insertNodes(editor, {
|
51
|
+
type: "htmlCode",
|
52
|
+
html: html,
|
53
|
+
children: [{
|
54
|
+
text: ""
|
55
|
+
}]
|
56
|
+
}, {
|
57
|
+
select: true
|
58
|
+
});
|
59
|
+
Transforms.insertNodes(editor, {
|
60
|
+
type: "paragraph",
|
61
|
+
children: [{
|
62
|
+
text: ""
|
63
|
+
}]
|
64
|
+
});
|
65
|
+
}
|
66
|
+
}
|
67
|
+
handleCodeToText({
|
68
|
+
showInput: false,
|
69
|
+
html: ""
|
70
|
+
});
|
71
|
+
};
|
72
|
+
const clearHtml = () => {
|
73
|
+
handleCodeToText({
|
74
|
+
html: ""
|
75
|
+
});
|
76
|
+
};
|
77
|
+
return /*#__PURE__*/React.createElement("div", {
|
78
|
+
className: "code-wrapper",
|
79
|
+
ref: wrapperRef
|
80
|
+
}, /*#__PURE__*/React.createElement("div", {
|
81
|
+
ref: codeToTextRef,
|
82
|
+
className: "codeToTextWrapper"
|
83
|
+
}, /*#__PURE__*/React.createElement("div", {
|
84
|
+
className: "codeToText"
|
85
|
+
}, /*#__PURE__*/React.createElement("textarea", {
|
86
|
+
name: "",
|
87
|
+
id: "",
|
88
|
+
value: html,
|
89
|
+
onChange: codeOnChange,
|
90
|
+
placeholder: "Write html here..."
|
91
|
+
}), /*#__PURE__*/React.createElement("div", {
|
92
|
+
style: {
|
93
|
+
display: "flex",
|
94
|
+
alignItems: "center",
|
95
|
+
justifyContent: "center",
|
96
|
+
color: "white"
|
97
|
+
}
|
98
|
+
}, /*#__PURE__*/React.createElement(Icon, {
|
99
|
+
icon: "arrowRight"
|
100
|
+
})), /*#__PURE__*/React.createElement("div", {
|
101
|
+
className: "textOutput"
|
102
|
+
}, /*#__PURE__*/React.createElement(Interweave, {
|
103
|
+
content: html
|
104
|
+
}))), /*#__PURE__*/React.createElement("div", null, /*#__PURE__*/React.createElement("button", {
|
105
|
+
onClick: addHtml,
|
106
|
+
className: "done"
|
107
|
+
}, "Done"), /*#__PURE__*/React.createElement("button", {
|
108
|
+
className: "clear",
|
109
|
+
onClick: clearHtml
|
110
|
+
}, "Clear"))));
|
111
|
+
};
|
112
|
+
export default CodeToText;
|
@@ -0,0 +1,18 @@
|
|
1
|
+
import React from 'react';
|
2
|
+
import Button from '../../common/Button';
|
3
|
+
import Icon from '../../common/Icon';
|
4
|
+
const CodeToTextButton = props => {
|
5
|
+
const {
|
6
|
+
handleButtonClick
|
7
|
+
} = props;
|
8
|
+
return /*#__PURE__*/React.createElement(React.Fragment, null, /*#__PURE__*/React.createElement(Button, {
|
9
|
+
format: "insert Html",
|
10
|
+
onClick: () => handleButtonClick({
|
11
|
+
showInput: true,
|
12
|
+
action: 'insert'
|
13
|
+
})
|
14
|
+
}, /*#__PURE__*/React.createElement(Icon, {
|
15
|
+
icon: "insertHtml"
|
16
|
+
})));
|
17
|
+
};
|
18
|
+
export default CodeToTextButton;
|
@@ -0,0 +1,54 @@
|
|
1
|
+
function _extends() { _extends = Object.assign ? Object.assign.bind() : function (target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i]; for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { target[key] = source[key]; } } } return target; }; return _extends.apply(this, arguments); }
|
2
|
+
import { Interweave } from "interweave";
|
3
|
+
import React, { useEffect } from "react";
|
4
|
+
import { Transforms, Path } from "slate";
|
5
|
+
import { useSelected, useFocused, useSlateStatic } from "slate-react";
|
6
|
+
import useFormat from "../../utils/customHooks/useFormat";
|
7
|
+
const HtmlCode = props => {
|
8
|
+
const {
|
9
|
+
attributes,
|
10
|
+
element,
|
11
|
+
children
|
12
|
+
} = props;
|
13
|
+
const selected = useSelected();
|
14
|
+
const focused = useFocused();
|
15
|
+
const editor = useSlateStatic();
|
16
|
+
const isHtmlEmbed = useFormat(editor, "htmlCode");
|
17
|
+
const handleKeyUp = e => {
|
18
|
+
if (!isHtmlEmbed) return;
|
19
|
+
if (e.keyCode === 13) {
|
20
|
+
const parentPath = Path.parent(editor.selection.focus.path);
|
21
|
+
const nextPath = Path.next(parentPath);
|
22
|
+
Transforms.insertNodes(editor, {
|
23
|
+
type: "paragraph",
|
24
|
+
children: [{
|
25
|
+
text: ""
|
26
|
+
}]
|
27
|
+
}, {
|
28
|
+
at: nextPath,
|
29
|
+
select: true // Focus on this node once inserted
|
30
|
+
});
|
31
|
+
} else if (e.keyCode === 8) {
|
32
|
+
Transforms.removeNodes(editor);
|
33
|
+
}
|
34
|
+
// console.log(e);
|
35
|
+
};
|
36
|
+
|
37
|
+
useEffect(() => {
|
38
|
+
document.addEventListener("keyup", handleKeyUp);
|
39
|
+
return () => {
|
40
|
+
document.removeEventListener("keyup", handleKeyUp);
|
41
|
+
};
|
42
|
+
}, [isHtmlEmbed]);
|
43
|
+
return /*#__PURE__*/React.createElement("div", _extends({}, attributes, element.attr, {
|
44
|
+
style: {
|
45
|
+
boxShadow: selected && focused && "0 0 3px 3px lightgray",
|
46
|
+
marginRight: "20px"
|
47
|
+
}
|
48
|
+
}), /*#__PURE__*/React.createElement("div", {
|
49
|
+
contentEditable: false
|
50
|
+
}, /*#__PURE__*/React.createElement(Interweave, {
|
51
|
+
content: element.html
|
52
|
+
})), children);
|
53
|
+
};
|
54
|
+
export default HtmlCode;
|
@@ -0,0 +1,39 @@
|
|
1
|
+
import React, { useState } from "react";
|
2
|
+
import useContextMenu from "../../utils/customHooks/useContextMenu.js";
|
3
|
+
import Icon from "../../common/Icon.jsx";
|
4
|
+
import { Transforms, Node, Path } from "slate";
|
5
|
+
const HtmlContextMenu = props => {
|
6
|
+
const {
|
7
|
+
editor,
|
8
|
+
handleCodeToText
|
9
|
+
} = props;
|
10
|
+
const [selection, setSelection] = useState();
|
11
|
+
const [showMenu, {
|
12
|
+
top,
|
13
|
+
left
|
14
|
+
}] = useContextMenu(editor, "htmlCode", setSelection);
|
15
|
+
const handleEditHtml = () => {
|
16
|
+
Transforms.select(editor, selection);
|
17
|
+
const parentPath = Path.parent(selection.focus.path);
|
18
|
+
const htmlNode = Node.get(editor, parentPath);
|
19
|
+
handleCodeToText({
|
20
|
+
showInput: true,
|
21
|
+
html: htmlNode.html,
|
22
|
+
action: "update",
|
23
|
+
location: selection
|
24
|
+
});
|
25
|
+
};
|
26
|
+
return showMenu && /*#__PURE__*/React.createElement("div", {
|
27
|
+
className: "contextMenu",
|
28
|
+
style: {
|
29
|
+
top,
|
30
|
+
left
|
31
|
+
}
|
32
|
+
}, /*#__PURE__*/React.createElement("div", {
|
33
|
+
className: "menuOption",
|
34
|
+
onClick: handleEditHtml
|
35
|
+
}, /*#__PURE__*/React.createElement(Icon, {
|
36
|
+
icon: "pen"
|
37
|
+
}), /*#__PURE__*/React.createElement("span", null, "Edit HTML")));
|
38
|
+
};
|
39
|
+
export default HtmlContextMenu;
|
@@ -0,0 +1,38 @@
|
|
1
|
+
|
2
|
+
.color-options{
|
3
|
+
display: grid;
|
4
|
+
grid-template-columns: auto auto auto auto auto auto auto;
|
5
|
+
align-items: center;
|
6
|
+
gap: 5px;
|
7
|
+
}
|
8
|
+
.clicked{
|
9
|
+
border: 1px solid lightgray;
|
10
|
+
border-bottom: none;
|
11
|
+
}
|
12
|
+
.option,.hexPreview{
|
13
|
+
width: 16px;
|
14
|
+
height: 16px;
|
15
|
+
background-color: #000000;
|
16
|
+
|
17
|
+
}
|
18
|
+
.color-picker form{
|
19
|
+
display: flex;
|
20
|
+
align-items: center;
|
21
|
+
column-gap: 5px;
|
22
|
+
width: 100%;
|
23
|
+
}
|
24
|
+
.color-picker input{
|
25
|
+
width: 65%;
|
26
|
+
height:1.3em;
|
27
|
+
border:1px solid lightgray;
|
28
|
+
border-radius: 5px;
|
29
|
+
padding-left:5px
|
30
|
+
}
|
31
|
+
.color-picker button{
|
32
|
+
margin:0;
|
33
|
+
padding:0;
|
34
|
+
cursor: pointer;
|
35
|
+
}
|
36
|
+
.color-picker input:focus{
|
37
|
+
outline: none;
|
38
|
+
}
|