trotl-texteditor 1.0.10 → 1.0.13
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.cjs +459 -172
- package/dist/index.cjs.map +1 -1
- package/dist/index.css +1 -1
- package/dist/index.css.map +1 -1
- package/dist/index.mjs +459 -172
- package/dist/index.mjs.map +1 -1
- package/package.json +1 -1
package/dist/index.cjs
CHANGED
|
@@ -87,6 +87,16 @@ function CodeBlock({
|
|
|
87
87
|
}));
|
|
88
88
|
}
|
|
89
89
|
|
|
90
|
+
const DEFAULT_HTML = `
|
|
91
|
+
<h1>Welcome</h1>
|
|
92
|
+
<p>This is a lightweight WYSIWYG editor built without external libraries.</p>
|
|
93
|
+
<ul>
|
|
94
|
+
<li>Edit text directly</li>
|
|
95
|
+
<li>Use the toolbar for formatting</li>
|
|
96
|
+
<li>Copy, paste, and export HTML</li>
|
|
97
|
+
</ul>
|
|
98
|
+
`;
|
|
99
|
+
|
|
90
100
|
const COMMANDS = [{
|
|
91
101
|
cmd: "bold",
|
|
92
102
|
label: "Bold",
|
|
@@ -124,24 +134,287 @@ const COMMANDS = [{
|
|
|
124
134
|
label: "Right",
|
|
125
135
|
icon: "⟹"
|
|
126
136
|
}];
|
|
137
|
+
|
|
138
|
+
const escapeHtml = value => value.replace(/&/g, "&").replace(/</g, "<").replace(/>/g, ">").replace(/\"/g, """).replace(/'/g, "'");
|
|
139
|
+
const exec = (editorRef, cmd, value = null, setHtml, onChange, updateToolbarState) => {
|
|
140
|
+
editorRef.current?.focus();
|
|
141
|
+
document.execCommand(cmd, false, value);
|
|
142
|
+
const nextHtml = editorRef.current?.innerHTML || "";
|
|
143
|
+
setHtml(nextHtml);
|
|
144
|
+
onChange({
|
|
145
|
+
html: nextHtml,
|
|
146
|
+
text: editorRef.current?.innerText || ""
|
|
147
|
+
});
|
|
148
|
+
updateToolbarState();
|
|
149
|
+
};
|
|
150
|
+
const clearAll = (editorRef, setHtml, onChange, updateToolbarState) => {
|
|
151
|
+
if (!editorRef.current) return;
|
|
152
|
+
editorRef.current.innerHTML = "<p></p>";
|
|
153
|
+
setHtml(editorRef.current.innerHTML);
|
|
154
|
+
onChange({
|
|
155
|
+
html: editorRef.current.innerHTML,
|
|
156
|
+
text: editorRef.current.innerText || ""
|
|
157
|
+
});
|
|
158
|
+
updateToolbarState();
|
|
159
|
+
};
|
|
160
|
+
const exportHtml = async editorRef => {
|
|
161
|
+
const payload = editorRef.current?.innerHTML || "";
|
|
162
|
+
await navigator.clipboard.writeText(payload);
|
|
163
|
+
alert("HTML copied to clipboard.");
|
|
164
|
+
};
|
|
165
|
+
|
|
166
|
+
const applyHeading = (next, exec) => {
|
|
167
|
+
if (next === "p") {
|
|
168
|
+
exec("formatBlock", "P");
|
|
169
|
+
return;
|
|
170
|
+
}
|
|
171
|
+
if (next === "pre") {
|
|
172
|
+
exec("formatBlock", "PRE");
|
|
173
|
+
return;
|
|
174
|
+
}
|
|
175
|
+
exec("formatBlock", next.toUpperCase());
|
|
176
|
+
};
|
|
177
|
+
const applyFontSize = (next, exec, editorRef, setHtml, updateToolbarState) => {
|
|
178
|
+
const selection = window.getSelection();
|
|
179
|
+
if (!selection || selection.rangeCount === 0) return;
|
|
180
|
+
const range = selection.getRangeAt(0);
|
|
181
|
+
if (range.collapsed) return; // No selection
|
|
182
|
+
|
|
183
|
+
exec("fontSize", "7");
|
|
184
|
+
const fontElements = editorRef.current?.querySelectorAll("font[size='7']") || [];
|
|
185
|
+
fontElements.forEach(el => {
|
|
186
|
+
el.removeAttribute("size");
|
|
187
|
+
el.style.fontSize = `${next}px`;
|
|
188
|
+
});
|
|
189
|
+
setHtml(editorRef.current?.innerHTML || "");
|
|
190
|
+
updateToolbarState();
|
|
191
|
+
};
|
|
192
|
+
const applyCustomFontSize = (value, exec, editorRef, setHtml, updateToolbarState) => {
|
|
193
|
+
if (!value || isNaN(value)) return;
|
|
194
|
+
const selection = window.getSelection();
|
|
195
|
+
if (!selection || selection.rangeCount === 0) return;
|
|
196
|
+
const range = selection.getRangeAt(0);
|
|
197
|
+
if (range.collapsed) return; // No selection
|
|
198
|
+
|
|
199
|
+
exec("fontSize", "7");
|
|
200
|
+
const fontElements = editorRef.current?.querySelectorAll("font[size='7']") || [];
|
|
201
|
+
fontElements.forEach(el => {
|
|
202
|
+
el.removeAttribute("size");
|
|
203
|
+
el.style.fontSize = `${value}px`;
|
|
204
|
+
});
|
|
205
|
+
setHtml(editorRef.current?.innerHTML || "");
|
|
206
|
+
updateToolbarState();
|
|
207
|
+
};
|
|
208
|
+
const applyTextColor = (next, exec) => {
|
|
209
|
+
exec("foreColor", next);
|
|
210
|
+
};
|
|
211
|
+
const applyBackgroundColor = (next, exec) => {
|
|
212
|
+
exec("hiliteColor", next);
|
|
213
|
+
};
|
|
214
|
+
const resetColors = (theme, setTextColor, setBackgroundColor, exec) => {
|
|
215
|
+
const defaultText = theme === "dark" ? "#e5e7eb" : "#1f2937";
|
|
216
|
+
const defaultBg = "#ffff00";
|
|
217
|
+
setTextColor(defaultText);
|
|
218
|
+
setBackgroundColor(defaultBg);
|
|
219
|
+
exec("removeFormat");
|
|
220
|
+
};
|
|
221
|
+
|
|
222
|
+
const insertCodeBlock = (codeValue, codeLanguage, codeTheme, exec, setIsCodeModalOpen, setCodeValue) => {
|
|
223
|
+
const safeCode = escapeHtml(codeValue || "");
|
|
224
|
+
const languageClass = codeLanguage ? `language-${codeLanguage}` : "language-plain";
|
|
225
|
+
const htmlBlock = `<pre class="code-block-shell" data-theme="${codeTheme}"><code class="${languageClass}">${safeCode}</code></pre>`;
|
|
226
|
+
exec("insertHTML", htmlBlock);
|
|
227
|
+
setIsCodeModalOpen(false);
|
|
228
|
+
setCodeValue("");
|
|
229
|
+
};
|
|
230
|
+
const insertLink = exec => {
|
|
231
|
+
const url = window.prompt("Enter URL", "https://");
|
|
232
|
+
if (!url) return;
|
|
233
|
+
exec("createLink", url);
|
|
234
|
+
};
|
|
235
|
+
const insertTooltip = (editorRef, setHtml, onChange, updateToolbarState) => {
|
|
236
|
+
const selection = window.getSelection();
|
|
237
|
+
if (!selection || selection.rangeCount === 0) return;
|
|
238
|
+
const selectedText = selection.toString();
|
|
239
|
+
if (!selectedText) {
|
|
240
|
+
alert("Please select some text first");
|
|
241
|
+
return;
|
|
242
|
+
}
|
|
243
|
+
const tooltip = window.prompt("Enter tooltip/note text", "");
|
|
244
|
+
if (!tooltip) return;
|
|
245
|
+
const range = selection.getRangeAt(0);
|
|
246
|
+
const span = document.createElement("span");
|
|
247
|
+
span.className = "has-tooltip";
|
|
248
|
+
span.title = tooltip;
|
|
249
|
+
try {
|
|
250
|
+
range.surroundContents(span);
|
|
251
|
+
} catch {
|
|
252
|
+
// If surroundContents fails, use alternative method
|
|
253
|
+
span.appendChild(range.extractContents());
|
|
254
|
+
range.insertNode(span);
|
|
255
|
+
}
|
|
256
|
+
selection.removeAllRanges();
|
|
257
|
+
const nextHtml = editorRef.current?.innerHTML || "";
|
|
258
|
+
setHtml(nextHtml);
|
|
259
|
+
onChange({
|
|
260
|
+
html: nextHtml,
|
|
261
|
+
text: editorRef.current?.innerText || ""
|
|
262
|
+
});
|
|
263
|
+
updateToolbarState();
|
|
264
|
+
};
|
|
265
|
+
const insertAnchor = exec => {
|
|
266
|
+
const id = window.prompt("Enter anchor ID", "");
|
|
267
|
+
if (!id) return;
|
|
268
|
+
const sanitizedId = id.replace(/[^a-zA-Z0-9-_]/g, "");
|
|
269
|
+
const anchorHtml = `<span class="anchor-marker" id="${sanitizedId}" data-anchor="${sanitizedId}">⚓${sanitizedId}</span>`;
|
|
270
|
+
exec("insertHTML", anchorHtml);
|
|
271
|
+
};
|
|
272
|
+
const insertHr = exec => {
|
|
273
|
+
exec("insertHTML", "<hr>");
|
|
274
|
+
};
|
|
275
|
+
const insertImage = exec => {
|
|
276
|
+
const url = window.prompt("Enter image URL", "https://");
|
|
277
|
+
if (!url) return;
|
|
278
|
+
const alt = window.prompt("Enter image description (alt text)", "");
|
|
279
|
+
const imageHtml = `<img src="${url}" alt="${alt || ''}" style="max-width: 100%; height: auto;" />`;
|
|
280
|
+
exec("insertHTML", imageHtml);
|
|
281
|
+
};
|
|
282
|
+
const insertVideo = exec => {
|
|
283
|
+
const url = window.prompt("Enter video URL (YouTube, MP4, etc.)", "https://");
|
|
284
|
+
if (!url) return;
|
|
285
|
+
|
|
286
|
+
// Check if it's a YouTube URL
|
|
287
|
+
const youtubeMatch = url.match(/(?:youtube\.com\/watch\?v=|youtu\.be\/)([^&\s]+)/);
|
|
288
|
+
if (youtubeMatch) {
|
|
289
|
+
const videoId = youtubeMatch[1];
|
|
290
|
+
const embedHtml = `<iframe width="560" height="315" src="https://www.youtube.com/embed/${videoId}" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture" allowfullscreen style="max-width: 100%;"></iframe>`;
|
|
291
|
+
exec("insertHTML", embedHtml);
|
|
292
|
+
} else {
|
|
293
|
+
// Assume it's a direct video URL
|
|
294
|
+
const videoHtml = `<video controls style="max-width: 100%; height: auto;"><source src="${url}" type="video/mp4">Your browser does not support the video tag.</video>`;
|
|
295
|
+
exec("insertHTML", videoHtml);
|
|
296
|
+
}
|
|
297
|
+
};
|
|
298
|
+
|
|
299
|
+
const onInput = (editorRef, setHtml, onChange, updateToolbarState) => {
|
|
300
|
+
const nextHtml = editorRef.current?.innerHTML || "";
|
|
301
|
+
setHtml(nextHtml);
|
|
302
|
+
onChange({
|
|
303
|
+
html: nextHtml,
|
|
304
|
+
text: editorRef.current?.innerText || ""
|
|
305
|
+
});
|
|
306
|
+
updateToolbarState();
|
|
307
|
+
};
|
|
308
|
+
const onPaste = (event, plainPaste) => {
|
|
309
|
+
if (!plainPaste) return;
|
|
310
|
+
event.preventDefault();
|
|
311
|
+
const text = event.clipboardData.getData("text/plain");
|
|
312
|
+
document.execCommand("insertText", false, text);
|
|
313
|
+
};
|
|
314
|
+
const createUpdateToolbarState = (editorRef, setSelectionText, setActiveToolMap) => {
|
|
315
|
+
return () => {
|
|
316
|
+
const selection = document.getSelection();
|
|
317
|
+
if (!selection || selection.rangeCount === 0 || !editorRef.current) return;
|
|
318
|
+
const anchorNode = selection.anchorNode;
|
|
319
|
+
const isInsideEditor = anchorNode && editorRef.current.contains(anchorNode);
|
|
320
|
+
if (!isInsideEditor) {
|
|
321
|
+
setSelectionText("");
|
|
322
|
+
setActiveToolMap({});
|
|
323
|
+
return;
|
|
324
|
+
}
|
|
325
|
+
setSelectionText(selection.toString());
|
|
326
|
+
const nextActive = {};
|
|
327
|
+
COMMANDS.forEach(item => {
|
|
328
|
+
try {
|
|
329
|
+
nextActive[item.cmd] = document.queryCommandState(item.cmd);
|
|
330
|
+
} catch {
|
|
331
|
+
nextActive[item.cmd] = false;
|
|
332
|
+
}
|
|
333
|
+
});
|
|
334
|
+
setActiveToolMap(nextActive);
|
|
335
|
+
};
|
|
336
|
+
};
|
|
337
|
+
|
|
127
338
|
function Editor({
|
|
128
339
|
theme = "dark",
|
|
129
340
|
tools = COMMANDS.map(item => item.cmd),
|
|
341
|
+
showDemoText = false,
|
|
130
342
|
showHeading = true,
|
|
131
343
|
showFontSize = true,
|
|
132
344
|
showAlign = true,
|
|
133
345
|
showLink = true,
|
|
346
|
+
showTooltip = true,
|
|
347
|
+
showAnchor = true,
|
|
348
|
+
showHr = true,
|
|
349
|
+
showMedia = true,
|
|
134
350
|
showUndoRedo = true,
|
|
135
351
|
showClear = true,
|
|
136
352
|
showPlainPaste = true,
|
|
137
353
|
showColor = true,
|
|
354
|
+
showFullscreen = true,
|
|
138
355
|
codeBlock = false,
|
|
139
356
|
codeBlockLanguages,
|
|
140
357
|
showLiveHtml = true,
|
|
141
358
|
showStats = true,
|
|
142
359
|
showCopyHtml = true,
|
|
143
|
-
onChange = () => {}
|
|
360
|
+
onChange = () => {},
|
|
361
|
+
initialHtml = "",
|
|
362
|
+
t
|
|
144
363
|
}) {
|
|
364
|
+
let translate;
|
|
365
|
+
if (t) {
|
|
366
|
+
translate = t;
|
|
367
|
+
} else {
|
|
368
|
+
translate = key => {
|
|
369
|
+
const translations = {
|
|
370
|
+
sample: "Sample Text",
|
|
371
|
+
Undo: "Undo",
|
|
372
|
+
Redo: "Redo",
|
|
373
|
+
Format: "Format",
|
|
374
|
+
Paragraph: "Paragraph",
|
|
375
|
+
"Heading 1": "Heading 1",
|
|
376
|
+
"Heading 2": "Heading 2",
|
|
377
|
+
"Heading 3": "Heading 3",
|
|
378
|
+
"Heading 4": "Heading 4",
|
|
379
|
+
Blockquote: "Blockquote",
|
|
380
|
+
"Code Block": "Code Block",
|
|
381
|
+
Size: "Size",
|
|
382
|
+
Custom: "Custom",
|
|
383
|
+
Font: "Font",
|
|
384
|
+
"Text color": "Text color",
|
|
385
|
+
Background: "Background",
|
|
386
|
+
"Background color": "Background color",
|
|
387
|
+
"Reset colors": "Reset colors",
|
|
388
|
+
"Insert code block": "Insert code block",
|
|
389
|
+
Align: "Align",
|
|
390
|
+
"Align Left": "Align Left",
|
|
391
|
+
"Align Center": "Align Center",
|
|
392
|
+
"Align Right": "Align Right",
|
|
393
|
+
Justify: "Justify",
|
|
394
|
+
"Add tooltip/note to selected text": "Add tooltip/note to selected text",
|
|
395
|
+
"Insert anchor": "Insert anchor",
|
|
396
|
+
"Insert horizontal line": "Insert horizontal line",
|
|
397
|
+
"Insert picture": "Insert picture",
|
|
398
|
+
"Insert video": "Insert video",
|
|
399
|
+
"Clear format": "Clear format",
|
|
400
|
+
"Clear all": "Clear all",
|
|
401
|
+
"Paste as plain text": "Paste as plain text",
|
|
402
|
+
"Exit fullscreen": "Exit fullscreen",
|
|
403
|
+
"Enter fullscreen": "Enter fullscreen",
|
|
404
|
+
words: "words",
|
|
405
|
+
characters: "characters",
|
|
406
|
+
selected: "selected",
|
|
407
|
+
"No selection": "No selection",
|
|
408
|
+
"Copy HTML": "Copy HTML",
|
|
409
|
+
"Live HTML": "Live HTML",
|
|
410
|
+
"Insert Code Block": "Insert Code Block",
|
|
411
|
+
"Paste your code here": "Paste your code here",
|
|
412
|
+
Cancel: "Cancel",
|
|
413
|
+
Insert: "Insert"
|
|
414
|
+
};
|
|
415
|
+
return translations[key] || key;
|
|
416
|
+
};
|
|
417
|
+
}
|
|
145
418
|
const editorRef = React.useRef(null);
|
|
146
419
|
const [html, setHtml] = React.useState("");
|
|
147
420
|
const [plainPaste, setPlainPaste] = React.useState(true);
|
|
@@ -152,6 +425,7 @@ function Editor({
|
|
|
152
425
|
const [textColor, setTextColor] = React.useState("#1f2937");
|
|
153
426
|
const [backgroundColor, setBackgroundColor] = React.useState("#ffff00");
|
|
154
427
|
const [activeToolMap, setActiveToolMap] = React.useState({});
|
|
428
|
+
const [isFullscreen, setIsFullscreen] = React.useState(false);
|
|
155
429
|
const [isCodeModalOpen, setIsCodeModalOpen] = React.useState(false);
|
|
156
430
|
const [codeValue, setCodeValue] = React.useState("");
|
|
157
431
|
const [codeLanguage, setCodeLanguage] = React.useState("js");
|
|
@@ -160,12 +434,8 @@ function Editor({
|
|
|
160
434
|
setCodeTheme(theme);
|
|
161
435
|
}, [theme]);
|
|
162
436
|
|
|
163
|
-
//
|
|
164
|
-
//
|
|
165
|
-
// editorRef.current.innerHTML = DEFAULT_HTML;
|
|
166
|
-
// setHtml(editorRef.current.innerHTML);
|
|
167
|
-
// }
|
|
168
|
-
// }, []);
|
|
437
|
+
// NOTE: initialization for `initialHtml` / demo text moved below `updateToolbarState` declaration to avoid referencing
|
|
438
|
+
// `updateToolbarState` before it is defined. See the effect inserted later in the file.
|
|
169
439
|
|
|
170
440
|
const stats = React.useMemo(() => {
|
|
171
441
|
const text = editorRef.current?.innerText || "";
|
|
@@ -175,144 +445,128 @@ function Editor({
|
|
|
175
445
|
chars: text.length
|
|
176
446
|
};
|
|
177
447
|
}, [html]);
|
|
178
|
-
const exec = (cmd, value = null) => {
|
|
179
|
-
editorRef
|
|
180
|
-
document.execCommand(cmd, false, value);
|
|
181
|
-
const nextHtml = editorRef.current?.innerHTML || "";
|
|
182
|
-
setHtml(nextHtml);
|
|
183
|
-
onChange({
|
|
184
|
-
html: nextHtml,
|
|
185
|
-
text: editorRef.current?.innerText || ""
|
|
186
|
-
});
|
|
187
|
-
updateToolbarState();
|
|
448
|
+
const exec$1 = (cmd, value = null) => {
|
|
449
|
+
exec(editorRef, cmd, value, setHtml, onChange, updateToolbarState);
|
|
188
450
|
};
|
|
189
|
-
const applyHeading = next => {
|
|
451
|
+
const applyHeading$1 = next => {
|
|
190
452
|
setHeading(next);
|
|
191
|
-
|
|
192
|
-
exec("formatBlock", "P");
|
|
193
|
-
return;
|
|
194
|
-
}
|
|
195
|
-
if (next === "pre") {
|
|
196
|
-
exec("formatBlock", "PRE");
|
|
197
|
-
return;
|
|
198
|
-
}
|
|
199
|
-
exec("formatBlock", next.toUpperCase());
|
|
453
|
+
applyHeading(next, exec$1);
|
|
200
454
|
};
|
|
201
|
-
const applyFontSize = next => {
|
|
455
|
+
const applyFontSize$1 = next => {
|
|
202
456
|
if (next === "custom") {
|
|
203
457
|
setFontSize("custom");
|
|
204
458
|
return;
|
|
205
459
|
}
|
|
206
460
|
setFontSize(next);
|
|
207
|
-
|
|
208
|
-
const fontElements = editorRef.current?.querySelectorAll("font[size='7']") || [];
|
|
209
|
-
fontElements.forEach(el => {
|
|
210
|
-
el.removeAttribute("size");
|
|
211
|
-
el.style.fontSize = `${next}px`;
|
|
212
|
-
});
|
|
213
|
-
setHtml(editorRef.current?.innerHTML || "");
|
|
214
|
-
updateToolbarState();
|
|
461
|
+
applyFontSize(next, exec$1, editorRef, setHtml, updateToolbarState);
|
|
215
462
|
};
|
|
216
|
-
const applyCustomFontSize = value => {
|
|
463
|
+
const applyCustomFontSize$1 = value => {
|
|
217
464
|
setCustomSize(value);
|
|
218
|
-
|
|
219
|
-
exec("fontSize", "7");
|
|
220
|
-
const fontElements = editorRef.current?.querySelectorAll("font[size='7']") || [];
|
|
221
|
-
fontElements.forEach(el => {
|
|
222
|
-
el.removeAttribute("size");
|
|
223
|
-
el.style.fontSize = `${value}px`;
|
|
224
|
-
});
|
|
225
|
-
setHtml(editorRef.current?.innerHTML || "");
|
|
226
|
-
updateToolbarState();
|
|
465
|
+
applyCustomFontSize(value, exec$1, editorRef, setHtml, updateToolbarState);
|
|
227
466
|
};
|
|
228
|
-
const applyTextColor = next => {
|
|
467
|
+
const applyTextColor$1 = next => {
|
|
229
468
|
setTextColor(next);
|
|
230
|
-
|
|
469
|
+
applyTextColor(next, exec$1);
|
|
231
470
|
};
|
|
232
|
-
const applyBackgroundColor = next => {
|
|
471
|
+
const applyBackgroundColor$1 = next => {
|
|
233
472
|
setBackgroundColor(next);
|
|
234
|
-
|
|
473
|
+
applyBackgroundColor(next, exec$1);
|
|
235
474
|
};
|
|
236
|
-
const resetColors = () => {
|
|
237
|
-
|
|
238
|
-
const defaultBg = "#ffff00";
|
|
239
|
-
setTextColor(defaultText);
|
|
240
|
-
setBackgroundColor(defaultBg);
|
|
241
|
-
exec("removeFormat");
|
|
475
|
+
const resetColors$1 = () => {
|
|
476
|
+
resetColors(theme, setTextColor, setBackgroundColor, exec$1);
|
|
242
477
|
};
|
|
243
|
-
const
|
|
244
|
-
|
|
245
|
-
const safeCode = escapeHtml(codeValue || "");
|
|
246
|
-
const languageClass = codeLanguage ? `language-${codeLanguage}` : "language-plain";
|
|
247
|
-
const htmlBlock = `<pre class="code-block-shell" data-theme="${codeTheme}"><code class="${languageClass}">${safeCode}</code></pre>`;
|
|
248
|
-
exec("insertHTML", htmlBlock);
|
|
249
|
-
setIsCodeModalOpen(false);
|
|
250
|
-
setCodeValue("");
|
|
478
|
+
const insertCodeBlock$1 = () => {
|
|
479
|
+
insertCodeBlock(codeValue, codeLanguage, codeTheme, exec$1, setIsCodeModalOpen, setCodeValue);
|
|
251
480
|
};
|
|
252
|
-
const insertLink = () => {
|
|
253
|
-
|
|
254
|
-
if (!url) return;
|
|
255
|
-
exec("createLink", url);
|
|
481
|
+
const insertLink$1 = () => {
|
|
482
|
+
insertLink(exec$1);
|
|
256
483
|
};
|
|
257
|
-
const
|
|
258
|
-
|
|
259
|
-
if (!editorRef.current) return;
|
|
260
|
-
editorRef.current.innerHTML = "<p></p>";
|
|
261
|
-
setHtml(editorRef.current.innerHTML);
|
|
262
|
-
onChange({
|
|
263
|
-
html: editorRef.current.innerHTML,
|
|
264
|
-
text: editorRef.current.innerText || ""
|
|
265
|
-
});
|
|
266
|
-
updateToolbarState();
|
|
484
|
+
const insertTooltip$1 = () => {
|
|
485
|
+
insertTooltip(editorRef, setHtml, onChange, updateToolbarState);
|
|
267
486
|
};
|
|
268
|
-
const
|
|
269
|
-
|
|
270
|
-
setHtml(nextHtml);
|
|
271
|
-
onChange({
|
|
272
|
-
html: nextHtml,
|
|
273
|
-
text: editorRef.current?.innerText || ""
|
|
274
|
-
});
|
|
275
|
-
updateToolbarState();
|
|
487
|
+
const insertAnchor$1 = () => {
|
|
488
|
+
insertAnchor(exec$1);
|
|
276
489
|
};
|
|
277
|
-
const
|
|
278
|
-
|
|
279
|
-
event.preventDefault();
|
|
280
|
-
const text = event.clipboardData.getData("text/plain");
|
|
281
|
-
document.execCommand("insertText", false, text);
|
|
490
|
+
const insertHr$1 = () => {
|
|
491
|
+
insertHr(exec$1);
|
|
282
492
|
};
|
|
283
|
-
const
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
493
|
+
const insertImage$1 = () => {
|
|
494
|
+
insertImage(exec$1);
|
|
495
|
+
};
|
|
496
|
+
const insertVideo$1 = () => {
|
|
497
|
+
insertVideo(exec$1);
|
|
498
|
+
};
|
|
499
|
+
const toggleFullscreen = () => {
|
|
500
|
+
setIsFullscreen(!isFullscreen);
|
|
501
|
+
};
|
|
502
|
+
const removeFormat = () => exec$1("removeFormat");
|
|
503
|
+
const clearAll$1 = () => {
|
|
504
|
+
clearAll(editorRef, setHtml, onChange, updateToolbarState);
|
|
505
|
+
};
|
|
506
|
+
const onInput$1 = () => {
|
|
507
|
+
onInput(editorRef, setHtml, onChange, updateToolbarState);
|
|
508
|
+
// Add key hint to all links
|
|
509
|
+
const links = editorRef.current?.querySelectorAll('a') || [];
|
|
510
|
+
links.forEach(link => {
|
|
511
|
+
if (!link.getAttribute('data-key-hint')) {
|
|
512
|
+
link.setAttribute('data-key-hint', 'Ctrl/Shift + Click to follow');
|
|
300
513
|
}
|
|
301
514
|
});
|
|
302
|
-
|
|
303
|
-
|
|
515
|
+
};
|
|
516
|
+
const onPaste$1 = event => {
|
|
517
|
+
onPaste(event, plainPaste);
|
|
518
|
+
};
|
|
519
|
+
const onEditorClick = event => {
|
|
520
|
+
if (event.target.tagName === 'A' && (event.ctrlKey || event.shiftKey || event.metaKey)) {
|
|
521
|
+
const href = event.target.getAttribute('href');
|
|
522
|
+
if (href) {
|
|
523
|
+
event.preventDefault();
|
|
524
|
+
window.open(href, '_blank');
|
|
525
|
+
}
|
|
526
|
+
}
|
|
527
|
+
};
|
|
528
|
+
const updateToolbarState = React.useCallback(createUpdateToolbarState(editorRef, setSelectionText, setActiveToolMap), []);
|
|
304
529
|
React.useEffect(() => {
|
|
305
530
|
document.addEventListener("selectionchange", updateToolbarState);
|
|
306
531
|
return () => document.removeEventListener("selectionchange", updateToolbarState);
|
|
307
532
|
}, [updateToolbarState]);
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
533
|
+
|
|
534
|
+
// Initialize editor from `initialHtml` if provided; otherwise (when showDemoText)
|
|
535
|
+
// populate with demo content. Run after `updateToolbarState` is defined.
|
|
536
|
+
React.useEffect(() => {
|
|
537
|
+
if (initialHtml && editorRef.current) {
|
|
538
|
+
editorRef.current.innerHTML = initialHtml;
|
|
539
|
+
setHtml(initialHtml);
|
|
540
|
+
const links = editorRef.current?.querySelectorAll('a') || [];
|
|
541
|
+
links.forEach(link => {
|
|
542
|
+
if (!link.getAttribute('data-key-hint')) {
|
|
543
|
+
link.setAttribute('data-key-hint', 'Ctrl/Shift + Click to follow');
|
|
544
|
+
}
|
|
545
|
+
});
|
|
546
|
+
updateToolbarState();
|
|
547
|
+
try {
|
|
548
|
+
onChange(initialHtml);
|
|
549
|
+
} catch {/* noop */}
|
|
550
|
+
return;
|
|
551
|
+
}
|
|
552
|
+
if (showDemoText && editorRef.current) {
|
|
553
|
+
editorRef.current.innerHTML = DEFAULT_HTML;
|
|
554
|
+
setHtml(editorRef.current.innerHTML);
|
|
555
|
+
const links = editorRef.current?.querySelectorAll('a') || [];
|
|
556
|
+
links.forEach(link => {
|
|
557
|
+
if (!link.getAttribute('data-key-hint')) {
|
|
558
|
+
link.setAttribute('data-key-hint', 'Ctrl/Shift + Click to follow');
|
|
559
|
+
}
|
|
560
|
+
});
|
|
561
|
+
updateToolbarState();
|
|
562
|
+
}
|
|
563
|
+
}, [initialHtml, showDemoText, onChange, updateToolbarState]);
|
|
564
|
+
const exportHtml$1 = async () => {
|
|
565
|
+
await exportHtml(editorRef);
|
|
312
566
|
};
|
|
313
567
|
const activeCommands = React.useMemo(() => COMMANDS.filter(item => tools.includes(item.cmd)), [tools]);
|
|
314
568
|
return /*#__PURE__*/React.createElement("section", {
|
|
315
|
-
className: `editor-root theme-${theme}${showLiveHtml ? " show-preview" : " no-preview"}`,
|
|
569
|
+
className: `editor-root theme-${theme}${showLiveHtml ? " show-preview" : " no-preview"}${isFullscreen ? " fullscreen" : ""}`,
|
|
316
570
|
"data-theme": theme
|
|
317
571
|
}, /*#__PURE__*/React.createElement("div", {
|
|
318
572
|
className: "toolbar"
|
|
@@ -321,13 +575,13 @@ function Editor({
|
|
|
321
575
|
}, /*#__PURE__*/React.createElement("button", {
|
|
322
576
|
type: "button",
|
|
323
577
|
className: "toolbar-btn",
|
|
324
|
-
onClick: () => exec("undo"),
|
|
325
|
-
title: "Undo"
|
|
578
|
+
onClick: () => exec$1("undo"),
|
|
579
|
+
title: translate("Undo")
|
|
326
580
|
}, "\u21B6"), /*#__PURE__*/React.createElement("button", {
|
|
327
581
|
type: "button",
|
|
328
582
|
className: "toolbar-btn",
|
|
329
|
-
onClick: () => exec("redo"),
|
|
330
|
-
title: "Redo"
|
|
583
|
+
onClick: () => exec$1("redo"),
|
|
584
|
+
title: translate("Redo")
|
|
331
585
|
}, "\u21B7")), /*#__PURE__*/React.createElement("span", {
|
|
332
586
|
className: "toolbar-separator"
|
|
333
587
|
}, "|")), activeCommands.length > 0 && /*#__PURE__*/React.createElement(React.Fragment, null, /*#__PURE__*/React.createElement("div", {
|
|
@@ -337,8 +591,8 @@ function Editor({
|
|
|
337
591
|
type: "button",
|
|
338
592
|
className: `toolbar-btn${activeToolMap[item.cmd] ? " active" : ""}`,
|
|
339
593
|
onMouseDown: event => event.preventDefault(),
|
|
340
|
-
onClick: () => exec(item.cmd),
|
|
341
|
-
title: item.label,
|
|
594
|
+
onClick: () => exec$1(item.cmd),
|
|
595
|
+
title: translate(item.label),
|
|
342
596
|
"aria-pressed": activeToolMap[item.cmd] || false
|
|
343
597
|
}, item.icon))), /*#__PURE__*/React.createElement("span", {
|
|
344
598
|
className: "toolbar-separator"
|
|
@@ -346,29 +600,29 @@ function Editor({
|
|
|
346
600
|
className: "toolbar-group"
|
|
347
601
|
}, showHeading && /*#__PURE__*/React.createElement("label", {
|
|
348
602
|
className: "toolbar-label"
|
|
349
|
-
}, "Format", /*#__PURE__*/React.createElement("select", {
|
|
603
|
+
}, translate("Format"), /*#__PURE__*/React.createElement("select", {
|
|
350
604
|
value: heading,
|
|
351
|
-
onChange: event => applyHeading(event.target.value),
|
|
605
|
+
onChange: event => applyHeading$1(event.target.value),
|
|
352
606
|
className: "toolbar-select"
|
|
353
607
|
}, /*#__PURE__*/React.createElement("option", {
|
|
354
608
|
value: "p"
|
|
355
|
-
}, "Paragraph"), /*#__PURE__*/React.createElement("option", {
|
|
609
|
+
}, translate("Paragraph")), /*#__PURE__*/React.createElement("option", {
|
|
356
610
|
value: "h1"
|
|
357
|
-
}, "Heading 1"), /*#__PURE__*/React.createElement("option", {
|
|
611
|
+
}, translate("Heading 1")), /*#__PURE__*/React.createElement("option", {
|
|
358
612
|
value: "h2"
|
|
359
|
-
}, "Heading 2"), /*#__PURE__*/React.createElement("option", {
|
|
613
|
+
}, translate("Heading 2")), /*#__PURE__*/React.createElement("option", {
|
|
360
614
|
value: "h3"
|
|
361
|
-
}, "Heading 3"), /*#__PURE__*/React.createElement("option", {
|
|
615
|
+
}, translate("Heading 3")), /*#__PURE__*/React.createElement("option", {
|
|
362
616
|
value: "h4"
|
|
363
|
-
}, "Heading 4"), /*#__PURE__*/React.createElement("option", {
|
|
617
|
+
}, translate("Heading 4")), /*#__PURE__*/React.createElement("option", {
|
|
364
618
|
value: "blockquote"
|
|
365
|
-
}, "Blockquote"), codeBlock && /*#__PURE__*/React.createElement("option", {
|
|
619
|
+
}, translate("Blockquote")), codeBlock && /*#__PURE__*/React.createElement("option", {
|
|
366
620
|
value: "pre"
|
|
367
|
-
}, "Code Block"))), showFontSize && /*#__PURE__*/React.createElement("label", {
|
|
621
|
+
}, translate("Code Block")))), showFontSize && /*#__PURE__*/React.createElement("label", {
|
|
368
622
|
className: "toolbar-label"
|
|
369
|
-
}, "Size", /*#__PURE__*/React.createElement("select", {
|
|
623
|
+
}, translate("Size"), /*#__PURE__*/React.createElement("select", {
|
|
370
624
|
value: fontSize,
|
|
371
|
-
onChange: event => applyFontSize(event.target.value),
|
|
625
|
+
onChange: event => applyFontSize$1(event.target.value),
|
|
372
626
|
className: "toolbar-select"
|
|
373
627
|
}, /*#__PURE__*/React.createElement("option", {
|
|
374
628
|
value: "10"
|
|
@@ -396,40 +650,40 @@ function Editor({
|
|
|
396
650
|
value: "48"
|
|
397
651
|
}, "48px"), /*#__PURE__*/React.createElement("option", {
|
|
398
652
|
value: "custom"
|
|
399
|
-
}, "Custom"))), showFontSize && fontSize === "custom" && /*#__PURE__*/React.createElement("label", {
|
|
653
|
+
}, translate("Custom")))), showFontSize && fontSize === "custom" && /*#__PURE__*/React.createElement("label", {
|
|
400
654
|
className: "toolbar-label"
|
|
401
655
|
}, /*#__PURE__*/React.createElement("input", {
|
|
402
656
|
type: "number",
|
|
403
657
|
min: "8",
|
|
404
658
|
max: "200",
|
|
405
659
|
value: customSize,
|
|
406
|
-
onChange: event => applyCustomFontSize(event.target.value),
|
|
407
|
-
placeholder: "Size",
|
|
660
|
+
onChange: event => applyCustomFontSize$1(event.target.value),
|
|
661
|
+
placeholder: translate("Size"),
|
|
408
662
|
className: "toolbar-input",
|
|
409
663
|
style: {
|
|
410
664
|
width: "60px"
|
|
411
665
|
}
|
|
412
666
|
}), "px"), showColor && /*#__PURE__*/React.createElement(React.Fragment, null, /*#__PURE__*/React.createElement("label", {
|
|
413
667
|
className: "toolbar-label color-label"
|
|
414
|
-
}, "Font", /*#__PURE__*/React.createElement("input", {
|
|
668
|
+
}, translate("Font"), /*#__PURE__*/React.createElement("input", {
|
|
415
669
|
type: "color",
|
|
416
670
|
className: "toolbar-color",
|
|
417
671
|
value: textColor,
|
|
418
|
-
onChange: event => applyTextColor(event.target.value),
|
|
419
|
-
"aria-label": "Text color"
|
|
672
|
+
onChange: event => applyTextColor$1(event.target.value),
|
|
673
|
+
"aria-label": translate("Text color")
|
|
420
674
|
})), /*#__PURE__*/React.createElement("label", {
|
|
421
675
|
className: "toolbar-label color-label"
|
|
422
|
-
}, "Background", /*#__PURE__*/React.createElement("input", {
|
|
676
|
+
}, translate("Background"), /*#__PURE__*/React.createElement("input", {
|
|
423
677
|
type: "color",
|
|
424
678
|
className: "toolbar-color",
|
|
425
679
|
value: backgroundColor,
|
|
426
|
-
onChange: event => applyBackgroundColor(event.target.value),
|
|
427
|
-
"aria-label": "Background color"
|
|
680
|
+
onChange: event => applyBackgroundColor$1(event.target.value),
|
|
681
|
+
"aria-label": translate("Background color")
|
|
428
682
|
})), /*#__PURE__*/React.createElement("button", {
|
|
429
683
|
type: "button",
|
|
430
684
|
className: "toolbar-btn toolbar-btn-small",
|
|
431
|
-
onClick: resetColors,
|
|
432
|
-
title: "Reset colors"
|
|
685
|
+
onClick: resetColors$1,
|
|
686
|
+
title: translate("Reset colors")
|
|
433
687
|
}, "\u21BA")), codeBlock && /*#__PURE__*/React.createElement("button", {
|
|
434
688
|
type: "button",
|
|
435
689
|
className: "toolbar-btn",
|
|
@@ -437,48 +691,73 @@ function Editor({
|
|
|
437
691
|
setCodeTheme(theme);
|
|
438
692
|
setIsCodeModalOpen(true);
|
|
439
693
|
},
|
|
440
|
-
title: "Insert code block"
|
|
441
|
-
}, "Code Block"), showAlign && /*#__PURE__*/React.createElement("div", {
|
|
694
|
+
title: translate("Insert code block")
|
|
695
|
+
}, translate("Code Block")), showAlign && /*#__PURE__*/React.createElement("div", {
|
|
442
696
|
className: "toolbar-label"
|
|
443
|
-
}, "Align", /*#__PURE__*/React.createElement("div", {
|
|
697
|
+
}, translate("Align"), /*#__PURE__*/React.createElement("div", {
|
|
444
698
|
className: "align-buttons"
|
|
445
699
|
}, /*#__PURE__*/React.createElement("button", {
|
|
446
700
|
type: "button",
|
|
447
701
|
className: "toolbar-btn toolbar-btn-small",
|
|
448
|
-
onClick: () => exec("justifyLeft"),
|
|
449
|
-
title: "Align Left"
|
|
702
|
+
onClick: () => exec$1("justifyLeft"),
|
|
703
|
+
title: translate("Align Left")
|
|
450
704
|
}, "\u27F8"), /*#__PURE__*/React.createElement("button", {
|
|
451
705
|
type: "button",
|
|
452
706
|
className: "toolbar-btn toolbar-btn-small",
|
|
453
|
-
onClick: () => exec("justifyCenter"),
|
|
454
|
-
title: "Align Center"
|
|
707
|
+
onClick: () => exec$1("justifyCenter"),
|
|
708
|
+
title: translate("Align Center")
|
|
455
709
|
}, "\u21D4"), /*#__PURE__*/React.createElement("button", {
|
|
456
710
|
type: "button",
|
|
457
711
|
className: "toolbar-btn toolbar-btn-small",
|
|
458
|
-
onClick: () => exec("justifyRight"),
|
|
459
|
-
title: "Align Right"
|
|
712
|
+
onClick: () => exec$1("justifyRight"),
|
|
713
|
+
title: translate("Align Right")
|
|
460
714
|
}, "\u27F9"), /*#__PURE__*/React.createElement("button", {
|
|
461
715
|
type: "button",
|
|
462
716
|
className: "toolbar-btn toolbar-btn-small",
|
|
463
|
-
onClick: () => exec("justifyFull"),
|
|
464
|
-
title: "Justify"
|
|
717
|
+
onClick: () => exec$1("justifyFull"),
|
|
718
|
+
title: translate("Justify")
|
|
465
719
|
}, "\u21FF")))), /*#__PURE__*/React.createElement("span", {
|
|
466
720
|
className: "toolbar-separator"
|
|
467
|
-
}, "|")), (showLink || showClear) && /*#__PURE__*/React.createElement(React.Fragment, null, /*#__PURE__*/React.createElement("div", {
|
|
721
|
+
}, "|")), (showLink || showTooltip || showAnchor || showHr || showMedia || showClear) && /*#__PURE__*/React.createElement(React.Fragment, null, /*#__PURE__*/React.createElement("div", {
|
|
468
722
|
className: "toolbar-group"
|
|
469
723
|
}, showLink && /*#__PURE__*/React.createElement("button", {
|
|
470
724
|
type: "button",
|
|
471
725
|
className: "toolbar-btn",
|
|
472
|
-
onClick: insertLink
|
|
473
|
-
}, "\uD83D\uDD17"),
|
|
726
|
+
onClick: insertLink$1
|
|
727
|
+
}, "\uD83D\uDD17"), showTooltip && /*#__PURE__*/React.createElement("button", {
|
|
728
|
+
type: "button",
|
|
729
|
+
className: "toolbar-btn",
|
|
730
|
+
onClick: insertTooltip$1,
|
|
731
|
+
title: translate("Add tooltip/note to selected text")
|
|
732
|
+
}, "\uD83D\uDCAC"), showAnchor && /*#__PURE__*/React.createElement("button", {
|
|
733
|
+
type: "button",
|
|
734
|
+
className: "toolbar-btn",
|
|
735
|
+
onClick: insertAnchor$1,
|
|
736
|
+
title: translate("Insert anchor")
|
|
737
|
+
}, "\u2693"), showHr && /*#__PURE__*/React.createElement("button", {
|
|
738
|
+
type: "button",
|
|
739
|
+
className: "toolbar-btn",
|
|
740
|
+
onClick: insertHr$1,
|
|
741
|
+
title: translate("Insert horizontal line")
|
|
742
|
+
}, "\u2500"), showMedia && /*#__PURE__*/React.createElement(React.Fragment, null, /*#__PURE__*/React.createElement("button", {
|
|
743
|
+
type: "button",
|
|
744
|
+
className: "toolbar-btn",
|
|
745
|
+
onClick: insertImage$1,
|
|
746
|
+
title: translate("Insert picture")
|
|
747
|
+
}, "\uD83D\uDDBC\uFE0F"), /*#__PURE__*/React.createElement("button", {
|
|
748
|
+
type: "button",
|
|
749
|
+
className: "toolbar-btn",
|
|
750
|
+
onClick: insertVideo$1,
|
|
751
|
+
title: translate("Insert video")
|
|
752
|
+
}, "\uD83C\uDFAC")), showClear && /*#__PURE__*/React.createElement(React.Fragment, null, /*#__PURE__*/React.createElement("button", {
|
|
474
753
|
type: "button",
|
|
475
754
|
className: "toolbar-btn",
|
|
476
755
|
onClick: removeFormat
|
|
477
|
-
}, "Clear format"), /*#__PURE__*/React.createElement("button", {
|
|
756
|
+
}, translate("Clear format")), /*#__PURE__*/React.createElement("button", {
|
|
478
757
|
type: "button",
|
|
479
758
|
className: "toolbar-btn danger",
|
|
480
|
-
onClick: clearAll
|
|
481
|
-
}, "Clear all"))), /*#__PURE__*/React.createElement("span", {
|
|
759
|
+
onClick: clearAll$1
|
|
760
|
+
}, translate("Clear all")))), /*#__PURE__*/React.createElement("span", {
|
|
482
761
|
className: "toolbar-separator"
|
|
483
762
|
}, "|")), showPlainPaste && /*#__PURE__*/React.createElement("div", {
|
|
484
763
|
className: "toolbar-group toggle"
|
|
@@ -488,14 +767,22 @@ function Editor({
|
|
|
488
767
|
type: "checkbox",
|
|
489
768
|
checked: plainPaste,
|
|
490
769
|
onChange: event => setPlainPaste(event.target.checked)
|
|
491
|
-
}), "Paste as plain text"))), /*#__PURE__*/React.createElement("div", {
|
|
770
|
+
}), translate("Paste as plain text"))), showFullscreen && /*#__PURE__*/React.createElement("div", {
|
|
771
|
+
className: "toolbar-group"
|
|
772
|
+
}, /*#__PURE__*/React.createElement("button", {
|
|
773
|
+
type: "button",
|
|
774
|
+
className: "toolbar-btn",
|
|
775
|
+
onClick: toggleFullscreen,
|
|
776
|
+
title: isFullscreen ? translate("Exit fullscreen") : translate("Enter fullscreen")
|
|
777
|
+
}, isFullscreen ? "⤓" : "⤢"))), /*#__PURE__*/React.createElement("div", {
|
|
492
778
|
className: "editor-area"
|
|
493
779
|
}, /*#__PURE__*/React.createElement("div", {
|
|
494
780
|
ref: editorRef,
|
|
495
781
|
className: "editor-surface",
|
|
496
782
|
contentEditable: true,
|
|
497
|
-
onInput: onInput,
|
|
498
|
-
onPaste: onPaste,
|
|
783
|
+
onInput: onInput$1,
|
|
784
|
+
onPaste: onPaste$1,
|
|
785
|
+
onClick: onEditorClick,
|
|
499
786
|
onKeyUp: updateToolbarState,
|
|
500
787
|
onMouseUp: updateToolbarState,
|
|
501
788
|
suppressContentEditableWarning: true,
|
|
@@ -504,19 +791,19 @@ function Editor({
|
|
|
504
791
|
className: "editor-footer"
|
|
505
792
|
}, showStats && /*#__PURE__*/React.createElement("div", {
|
|
506
793
|
className: "footer-stats"
|
|
507
|
-
}, /*#__PURE__*/React.createElement("span", null, stats.words, " words"), /*#__PURE__*/React.createElement("span", null, stats.chars, " characters"), /*#__PURE__*/React.createElement("span", null, selectionText ? `${selectionText.length} selected` : "No selection")), showCopyHtml && /*#__PURE__*/React.createElement("div", {
|
|
794
|
+
}, /*#__PURE__*/React.createElement("span", null, stats.words, " ", translate("words")), /*#__PURE__*/React.createElement("span", null, stats.chars, " ", translate("characters")), /*#__PURE__*/React.createElement("span", null, selectionText ? `${selectionText.length} ${translate("selected")}` : translate("No selection"))), showCopyHtml && /*#__PURE__*/React.createElement("div", {
|
|
508
795
|
className: "footer-actions"
|
|
509
796
|
}, /*#__PURE__*/React.createElement("button", {
|
|
510
797
|
type: "button",
|
|
511
798
|
className: "toolbar-btn",
|
|
512
|
-
onClick: exportHtml
|
|
513
|
-
}, "Copy HTML"))), showLiveHtml && /*#__PURE__*/React.createElement("aside", {
|
|
799
|
+
onClick: exportHtml$1
|
|
800
|
+
}, translate("Copy HTML")))), showLiveHtml && /*#__PURE__*/React.createElement("aside", {
|
|
514
801
|
className: "editor-preview"
|
|
515
802
|
}, /*#__PURE__*/React.createElement("pre", {
|
|
516
803
|
className: "preview-code"
|
|
517
804
|
}, html), /*#__PURE__*/React.createElement("div", {
|
|
518
805
|
className: "preview-header"
|
|
519
|
-
}, "Live HTML")), codeBlock && isCodeModalOpen && /*#__PURE__*/React.createElement("div", {
|
|
806
|
+
}, translate("Live HTML"))), codeBlock && isCodeModalOpen && /*#__PURE__*/React.createElement("div", {
|
|
520
807
|
className: "modal-backdrop",
|
|
521
808
|
role: "dialog",
|
|
522
809
|
"aria-modal": "true"
|
|
@@ -524,7 +811,7 @@ function Editor({
|
|
|
524
811
|
className: "modal"
|
|
525
812
|
}, /*#__PURE__*/React.createElement("div", {
|
|
526
813
|
className: "modal-header"
|
|
527
|
-
}, "Insert Code Block"), /*#__PURE__*/React.createElement(CodeBlock, {
|
|
814
|
+
}, translate("Insert Code Block")), /*#__PURE__*/React.createElement(CodeBlock, {
|
|
528
815
|
value: codeValue,
|
|
529
816
|
language: codeLanguage,
|
|
530
817
|
theme: codeTheme,
|
|
@@ -532,18 +819,18 @@ function Editor({
|
|
|
532
819
|
onChange: setCodeValue,
|
|
533
820
|
onLanguageChange: setCodeLanguage,
|
|
534
821
|
onThemeChange: setCodeTheme,
|
|
535
|
-
placeholder: "Paste your code here"
|
|
822
|
+
placeholder: translate("Paste your code here")
|
|
536
823
|
}), /*#__PURE__*/React.createElement("div", {
|
|
537
824
|
className: "modal-actions"
|
|
538
825
|
}, /*#__PURE__*/React.createElement("button", {
|
|
539
826
|
type: "button",
|
|
540
827
|
className: "toolbar-btn",
|
|
541
828
|
onClick: () => setIsCodeModalOpen(false)
|
|
542
|
-
}, "Cancel"), /*#__PURE__*/React.createElement("button", {
|
|
829
|
+
}, translate("Cancel")), /*#__PURE__*/React.createElement("button", {
|
|
543
830
|
type: "button",
|
|
544
831
|
className: "toolbar-btn",
|
|
545
|
-
onClick: insertCodeBlock
|
|
546
|
-
}, "Insert")))));
|
|
832
|
+
onClick: insertCodeBlock$1
|
|
833
|
+
}, translate("Insert"))))));
|
|
547
834
|
}
|
|
548
835
|
|
|
549
836
|
// src/index.js - Library entry point
|