pdeditor 1.0.0

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.
@@ -0,0 +1,9 @@
1
+ import * as react_jsx_runtime from 'react/jsx-runtime';
2
+
3
+ type EditorProps = {
4
+ value?: string;
5
+ onChange?: (v: string) => void;
6
+ };
7
+ declare const CustomEditor: ({ value, onChange }: EditorProps) => react_jsx_runtime.JSX.Element;
8
+
9
+ export { CustomEditor };
package/dist/index.js ADDED
@@ -0,0 +1,534 @@
1
+ var __defProp = Object.defineProperty;
2
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
3
+ var __getOwnPropNames = Object.getOwnPropertyNames;
4
+ var __getOwnPropSymbols = Object.getOwnPropertySymbols;
5
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
6
+ var __propIsEnum = Object.prototype.propertyIsEnumerable;
7
+ var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
8
+ var __spreadValues = (a, b) => {
9
+ for (var prop in b || (b = {}))
10
+ if (__hasOwnProp.call(b, prop))
11
+ __defNormalProp(a, prop, b[prop]);
12
+ if (__getOwnPropSymbols)
13
+ for (var prop of __getOwnPropSymbols(b)) {
14
+ if (__propIsEnum.call(b, prop))
15
+ __defNormalProp(a, prop, b[prop]);
16
+ }
17
+ return a;
18
+ };
19
+ var __export = (target, all) => {
20
+ for (var name in all)
21
+ __defProp(target, name, { get: all[name], enumerable: true });
22
+ };
23
+ var __copyProps = (to, from, except, desc) => {
24
+ if (from && typeof from === "object" || typeof from === "function") {
25
+ for (let key of __getOwnPropNames(from))
26
+ if (!__hasOwnProp.call(to, key) && key !== except)
27
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
28
+ }
29
+ return to;
30
+ };
31
+ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
32
+
33
+ // src/index.tsx
34
+ var index_exports = {};
35
+ __export(index_exports, {
36
+ CustomEditor: () => CustomEditor
37
+ });
38
+ module.exports = __toCommonJS(index_exports);
39
+ var import_react = require("react");
40
+ var import_jsx_runtime = require("react/jsx-runtime");
41
+ var SpecialCharModal = ({ onClose, onInsert }) => {
42
+ const chars = [
43
+ "!",
44
+ '"',
45
+ "#",
46
+ "$",
47
+ "%",
48
+ "&",
49
+ "'",
50
+ "(",
51
+ ")",
52
+ "*",
53
+ "+",
54
+ "-",
55
+ ".",
56
+ "/",
57
+ "0",
58
+ "1",
59
+ "2",
60
+ "3",
61
+ "4",
62
+ "5",
63
+ "6",
64
+ "7",
65
+ "8",
66
+ "9",
67
+ "A",
68
+ "B",
69
+ "C",
70
+ "D",
71
+ "E",
72
+ "F",
73
+ "G",
74
+ "H",
75
+ "I",
76
+ "J",
77
+ "K",
78
+ "L",
79
+ "M",
80
+ "N",
81
+ "O",
82
+ "P",
83
+ "Q",
84
+ "R",
85
+ "S",
86
+ "T",
87
+ "U",
88
+ "V",
89
+ "W",
90
+ "X",
91
+ "Y",
92
+ "Z",
93
+ "a",
94
+ "b",
95
+ "c",
96
+ "d",
97
+ "e",
98
+ "f",
99
+ "g",
100
+ "h",
101
+ "i",
102
+ "j",
103
+ "k",
104
+ "l",
105
+ "m",
106
+ "n",
107
+ "o",
108
+ "p",
109
+ "q",
110
+ "r",
111
+ "s",
112
+ "t",
113
+ "u",
114
+ "v",
115
+ "w",
116
+ "x",
117
+ "y",
118
+ "z",
119
+ "\u20AC",
120
+ "\xA3",
121
+ "\xA5",
122
+ "\xA9",
123
+ "\xAE",
124
+ "\xB5",
125
+ "\u03C0",
126
+ "\u2192",
127
+ "\u21D4",
128
+ "\xB1",
129
+ "\xD7",
130
+ "\xF7",
131
+ "\u2260",
132
+ "\u2264",
133
+ "\u2265",
134
+ "\u03B1",
135
+ "\u03B2",
136
+ "\u03B3",
137
+ "\u03B4",
138
+ "\u03B5",
139
+ "\u03B8",
140
+ "\u03BB",
141
+ "\u03C3",
142
+ "\u03C9",
143
+ "\u2211",
144
+ "\u222B",
145
+ "\u221E",
146
+ "\u221A",
147
+ "\u2202"
148
+ ];
149
+ return /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { style: { position: "fixed", top: 0, left: 0, right: 0, bottom: 0, background: "rgba(0,0,0,0.5)", display: "flex", alignItems: "center", justifyContent: "center", zIndex: 1e3 }, children: /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { style: { background: "white", padding: 20, borderRadius: 8, maxWidth: 500, maxHeight: "80vh", overflow: "auto" }, children: [
150
+ /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { style: { display: "flex", justifyContent: "space-between", marginBottom: 15 }, children: [
151
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("h3", { style: { margin: 0 }, children: "Special Characters" }),
152
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("button", { onClick: onClose, style: { border: "none", background: "none", fontSize: 20, cursor: "pointer" }, children: "\xD7" })
153
+ ] }),
154
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { style: { display: "grid", gridTemplateColumns: "repeat(10, 1fr)", gap: 5 }, children: chars.map((char, i) => /* @__PURE__ */ (0, import_jsx_runtime.jsx)("button", { onClick: () => {
155
+ onInsert(char);
156
+ onClose();
157
+ }, style: { padding: 10, cursor: "pointer", border: "1px solid #ddd", background: "white", fontSize: 16 }, children: char }, i)) })
158
+ ] }) });
159
+ };
160
+ var FindReplaceModal = ({ onClose, editorRef }) => {
161
+ const [findText, setFindText] = (0, import_react.useState)("");
162
+ const [replaceText, setReplaceText] = (0, import_react.useState)("");
163
+ const [matchCase, setMatchCase] = (0, import_react.useState)(false);
164
+ const [matchWholeWord, setMatchWholeWord] = (0, import_react.useState)(false);
165
+ const [matchCyclic, setMatchCyclic] = (0, import_react.useState)(false);
166
+ const highlightMatches = () => {
167
+ if (!editorRef.current || !findText) return;
168
+ const content = editorRef.current.innerHTML;
169
+ const flags = matchCase ? "g" : "gi";
170
+ const pattern = matchWholeWord ? `\\b${findText}\\b` : findText;
171
+ const regex = new RegExp(pattern, flags);
172
+ const highlighted = content.replace(regex, (match) => `<mark>${match}</mark>`);
173
+ editorRef.current.innerHTML = highlighted;
174
+ };
175
+ const replace = () => {
176
+ if (!editorRef.current || !findText) return;
177
+ const content = editorRef.current.innerHTML.replace(/<mark>/g, "").replace(/<\/mark>/g, "");
178
+ const flags = matchCase ? "" : "i";
179
+ const pattern = matchWholeWord ? `\\b${findText}\\b` : findText;
180
+ const regex = new RegExp(pattern, flags);
181
+ editorRef.current.innerHTML = content.replace(regex, replaceText);
182
+ };
183
+ const replaceAll = () => {
184
+ if (!editorRef.current || !findText) return;
185
+ const content = editorRef.current.innerHTML.replace(/<mark>/g, "").replace(/<\/mark>/g, "");
186
+ const flags = matchCase ? "g" : "gi";
187
+ const pattern = matchWholeWord ? `\\b${findText}\\b` : findText;
188
+ const regex = new RegExp(pattern, flags);
189
+ editorRef.current.innerHTML = content.replace(regex, replaceText);
190
+ };
191
+ return /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { style: { position: "fixed", top: 0, left: 0, right: 0, bottom: 0, background: "rgba(0,0,0,0.5)", display: "flex", alignItems: "center", justifyContent: "center", zIndex: 1e3 }, children: /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { style: { background: "white", padding: 20, borderRadius: 8, minWidth: 400 }, children: [
192
+ /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { style: { display: "flex", justifyContent: "space-between", marginBottom: 15 }, children: [
193
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("h3", { style: { margin: 0 }, children: "Find & Replace" }),
194
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("button", { onClick: onClose, style: { border: "none", background: "none", fontSize: 20, cursor: "pointer" }, children: "\xD7" })
195
+ ] }),
196
+ /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { style: { marginBottom: 10 }, children: [
197
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("input", { type: "text", placeholder: "Find", value: findText, onChange: (e) => setFindText(e.target.value), style: { width: "100%", padding: 8, marginBottom: 10 } }),
198
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("input", { type: "text", placeholder: "Replace", value: replaceText, onChange: (e) => setReplaceText(e.target.value), style: { width: "100%", padding: 8 } })
199
+ ] }),
200
+ /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { style: { marginBottom: 15 }, children: [
201
+ /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("label", { style: { display: "block", marginBottom: 5 }, children: [
202
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("input", { type: "checkbox", checked: matchCase, onChange: (e) => setMatchCase(e.target.checked) }),
203
+ " Match case"
204
+ ] }),
205
+ /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("label", { style: { display: "block", marginBottom: 5 }, children: [
206
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("input", { type: "checkbox", checked: matchWholeWord, onChange: (e) => setMatchWholeWord(e.target.checked) }),
207
+ " Match whole word"
208
+ ] }),
209
+ /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("label", { style: { display: "block" }, children: [
210
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("input", { type: "checkbox", checked: matchCyclic, onChange: (e) => setMatchCyclic(e.target.checked) }),
211
+ " Match cyclic"
212
+ ] })
213
+ ] }),
214
+ /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { style: { display: "flex", gap: 10 }, children: [
215
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("button", { onClick: highlightMatches, style: { padding: "8px 16px", cursor: "pointer" }, children: "Find" }),
216
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("button", { onClick: replace, style: { padding: "8px 16px", cursor: "pointer" }, children: "Replace" }),
217
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("button", { onClick: replaceAll, style: { padding: "8px 16px", cursor: "pointer" }, children: "Replace All" })
218
+ ] })
219
+ ] }) });
220
+ };
221
+ var ColorPicker = ({ onClose, onSelect, type }) => {
222
+ const colors = [
223
+ "#000000",
224
+ "#434343",
225
+ "#666666",
226
+ "#999999",
227
+ "#B7B7B7",
228
+ "#CCCCCC",
229
+ "#D9D9D9",
230
+ "#EFEFEF",
231
+ "#F3F3F3",
232
+ "#FFFFFF",
233
+ "#980000",
234
+ "#FF0000",
235
+ "#FF9900",
236
+ "#FFFF00",
237
+ "#00FF00",
238
+ "#00FFFF",
239
+ "#4A86E8",
240
+ "#0000FF",
241
+ "#9900FF",
242
+ "#FF00FF",
243
+ "#E6B8AF",
244
+ "#F4CCCC",
245
+ "#FCE5CD",
246
+ "#FFF2CC",
247
+ "#D9EAD3",
248
+ "#D0E0E3",
249
+ "#C9DAF8",
250
+ "#CFE2F3",
251
+ "#D9D2E9",
252
+ "#EAD1DC",
253
+ "#DD7E6B",
254
+ "#EA9999",
255
+ "#F9CB9C",
256
+ "#FFE599",
257
+ "#B6D7A8",
258
+ "#A2C4C9",
259
+ "#A4C2F4",
260
+ "#9FC5E8",
261
+ "#B4A7D6",
262
+ "#D5A6BD",
263
+ "#CC4125",
264
+ "#E06666",
265
+ "#F6B26B",
266
+ "#FFD966",
267
+ "#93C47D",
268
+ "#76A5AF",
269
+ "#6D9EEB",
270
+ "#6FA8DC",
271
+ "#8E7CC3",
272
+ "#C27BA0",
273
+ "#A61C00",
274
+ "#CC0000",
275
+ "#E69138",
276
+ "#F1C232",
277
+ "#6AA84F",
278
+ "#45818E",
279
+ "#3C78D8",
280
+ "#3D85C6",
281
+ "#674EA7",
282
+ "#A64D79",
283
+ "#85200C",
284
+ "#990000",
285
+ "#B45F06",
286
+ "#BF9000",
287
+ "#38761D",
288
+ "#134F5C",
289
+ "#1155CC",
290
+ "#0B5394",
291
+ "#351C75",
292
+ "#741B47",
293
+ "#5B0F00",
294
+ "#660000",
295
+ "#783F04",
296
+ "#7F6000",
297
+ "#274E13",
298
+ "#0C343D",
299
+ "#1C4587",
300
+ "#073763",
301
+ "#20124D",
302
+ "#4C1130"
303
+ ];
304
+ return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { style: { position: "absolute", background: "white", border: "1px solid #ccc", padding: 10, borderRadius: 4, boxShadow: "0 2px 8px rgba(0,0,0,0.15)", zIndex: 100 }, children: [
305
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { style: { marginBottom: 10, fontWeight: "bold" }, children: type === "text" ? "Text Color" : "Background Color" }),
306
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { style: { display: "grid", gridTemplateColumns: "repeat(10, 1fr)", gap: 3, marginBottom: 10 }, children: colors.map((color, i) => /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { onClick: () => {
307
+ onSelect(color);
308
+ onClose();
309
+ }, style: { width: 20, height: 20, background: color, cursor: "pointer", border: "1px solid #ddd" } }, i)) }),
310
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("button", { onClick: onClose, style: { width: "100%", padding: 5, cursor: "pointer" }, children: "Close" })
311
+ ] });
312
+ };
313
+ var TableInsertPopup = ({ onClose, onInsert }) => {
314
+ const [rows, setRows] = (0, import_react.useState)(3);
315
+ const [cols, setCols] = (0, import_react.useState)(3);
316
+ return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { style: { position: "absolute", background: "white", border: "1px solid #ccc", padding: 15, borderRadius: 4, boxShadow: "0 2px 8px rgba(0,0,0,0.15)", zIndex: 100 }, children: [
317
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { style: { marginBottom: 10, fontWeight: "bold" }, children: "Insert Table" }),
318
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { style: { display: "grid", gridTemplateColumns: "repeat(10, 1fr)", gap: 2, marginBottom: 10 }, children: Array.from({ length: 100 }, (_, i) => {
319
+ const r = Math.floor(i / 10) + 1;
320
+ const c = i % 10 + 1;
321
+ const isSelected = r <= rows && c <= cols;
322
+ return /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { onMouseEnter: () => {
323
+ setRows(r);
324
+ setCols(c);
325
+ }, onClick: () => {
326
+ onInsert(rows, cols);
327
+ onClose();
328
+ }, style: { width: 15, height: 15, border: "1px solid #ddd", background: isSelected ? "#4A86E8" : "white", cursor: "pointer" } }, i);
329
+ }) }),
330
+ /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { style: { textAlign: "center", marginBottom: 10 }, children: [
331
+ rows,
332
+ " \xD7 ",
333
+ cols
334
+ ] }),
335
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("button", { onClick: onClose, style: { width: "100%", padding: 5, cursor: "pointer" }, children: "Cancel" })
336
+ ] });
337
+ };
338
+ var CustomEditor = ({ value, onChange }) => {
339
+ const [isSourceMode, setIsSourceMode] = (0, import_react.useState)(false);
340
+ const [sourceValue, setSourceValue] = (0, import_react.useState)("");
341
+ const [showSpecialChar, setShowSpecialChar] = (0, import_react.useState)(false);
342
+ const [showFindReplace, setShowFindReplace] = (0, import_react.useState)(false);
343
+ const [showTextColor, setShowTextColor] = (0, import_react.useState)(false);
344
+ const [showBgColor, setShowBgColor] = (0, import_react.useState)(false);
345
+ const [showTablePopup, setShowTablePopup] = (0, import_react.useState)(false);
346
+ const [isFullscreen, setIsFullscreen] = (0, import_react.useState)(false);
347
+ const editorRef = (0, import_react.useRef)(null);
348
+ const containerRef = (0, import_react.useRef)(null);
349
+ (0, import_react.useEffect)(() => {
350
+ if (editorRef.current && value !== void 0 && !isSourceMode) {
351
+ editorRef.current.innerHTML = value;
352
+ }
353
+ }, [value]);
354
+ (0, import_react.useEffect)(() => {
355
+ const handleFullscreenChange = () => {
356
+ setIsFullscreen(!!document.fullscreenElement);
357
+ };
358
+ document.addEventListener("fullscreenchange", handleFullscreenChange);
359
+ return () => document.removeEventListener("fullscreenchange", handleFullscreenChange);
360
+ }, []);
361
+ const handleInput = () => {
362
+ if (editorRef.current && onChange) {
363
+ onChange(editorRef.current.innerHTML);
364
+ }
365
+ };
366
+ const execCmd = (cmd, val) => {
367
+ var _a;
368
+ document.execCommand(cmd, false, val);
369
+ (_a = editorRef.current) == null ? void 0 : _a.focus();
370
+ };
371
+ const toggleSourceMode = () => {
372
+ var _a;
373
+ if (isSourceMode) {
374
+ if (editorRef.current) {
375
+ editorRef.current.innerHTML = sourceValue;
376
+ onChange == null ? void 0 : onChange(sourceValue);
377
+ }
378
+ } else {
379
+ setSourceValue(((_a = editorRef.current) == null ? void 0 : _a.innerHTML) || "");
380
+ }
381
+ setIsSourceMode(!isSourceMode);
382
+ };
383
+ const insertSpecialChar = (char) => {
384
+ if (editorRef.current) {
385
+ editorRef.current.focus();
386
+ document.execCommand("insertText", false, char);
387
+ handleInput();
388
+ }
389
+ };
390
+ const insertTable = (rows, cols) => {
391
+ let html = '<table border="1" style="border-collapse: collapse; width: 100%;">';
392
+ for (let r = 0; r < rows; r++) {
393
+ html += "<tr>";
394
+ for (let c = 0; c < cols; c++) {
395
+ html += '<td style="padding: 8px; border: 1px solid #ddd;">&nbsp;</td>';
396
+ }
397
+ html += "</tr>";
398
+ }
399
+ html += "</table>";
400
+ document.execCommand("insertHTML", false, html);
401
+ handleInput();
402
+ };
403
+ const toggleFullscreen = async () => {
404
+ var _a;
405
+ if (!document.fullscreenElement) {
406
+ await ((_a = containerRef.current) == null ? void 0 : _a.requestFullscreen());
407
+ } else {
408
+ await document.exitFullscreen();
409
+ }
410
+ };
411
+ const handleCopy = () => {
412
+ document.execCommand("copy");
413
+ };
414
+ const handlePaste = () => {
415
+ document.execCommand("paste");
416
+ };
417
+ const handlePastePlain = async () => {
418
+ try {
419
+ const text = await navigator.clipboard.readText();
420
+ document.execCommand("insertText", false, text);
421
+ } catch (e) {
422
+ console.error("Paste failed", e);
423
+ }
424
+ };
425
+ const toolbarStyle = {
426
+ display: "flex",
427
+ flexWrap: "wrap",
428
+ gap: 5,
429
+ padding: 10,
430
+ background: "#f5f5f5",
431
+ borderBottom: "1px solid #ccc",
432
+ alignItems: "center"
433
+ };
434
+ const btnStyle = {
435
+ padding: "6px 10px",
436
+ cursor: "pointer",
437
+ border: "1px solid #ccc",
438
+ background: "white",
439
+ borderRadius: 3,
440
+ fontSize: 14
441
+ };
442
+ const selectStyle = {
443
+ padding: "6px 10px",
444
+ cursor: "pointer",
445
+ border: "1px solid #ccc",
446
+ background: "white",
447
+ borderRadius: 3,
448
+ fontSize: 14
449
+ };
450
+ return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { ref: containerRef, style: __spreadValues({ border: "1px solid #ccc", background: "white" }, isFullscreen ? { position: "fixed", top: 0, left: 0, right: 0, bottom: 0, zIndex: 9999 } : {}), children: [
451
+ /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { style: toolbarStyle, children: [
452
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("button", { onClick: toggleSourceMode, style: btnStyle, title: "Source Mode", children: "Source" }),
453
+ /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("select", { onChange: (e) => execCmd("formatBlock", e.target.value), style: selectStyle, defaultValue: "", children: [
454
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("option", { value: "", children: "Style" }),
455
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("option", { value: "p", children: "Paragraph" }),
456
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("option", { value: "h1", children: "Heading 1" }),
457
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("option", { value: "h2", children: "Heading 2" }),
458
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("option", { value: "h3", children: "Heading 3" }),
459
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("option", { value: "h4", children: "Heading 4" }),
460
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("option", { value: "h5", children: "Heading 5" }),
461
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("option", { value: "h6", children: "Heading 6" }),
462
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("option", { value: "pre", children: "Pre" })
463
+ ] }),
464
+ /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("select", { onChange: (e) => execCmd("formatBlock", e.target.value), style: selectStyle, defaultValue: "", children: [
465
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("option", { value: "", children: "Format" }),
466
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("option", { value: "p", children: "Normal" }),
467
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("option", { value: "address", children: "Address" }),
468
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("option", { value: "blockquote", children: "Quote" })
469
+ ] }),
470
+ /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("select", { onChange: (e) => execCmd("fontSize", e.target.value), style: selectStyle, defaultValue: "", children: [
471
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("option", { value: "", children: "Size" }),
472
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("option", { value: "1", children: "Small" }),
473
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("option", { value: "3", children: "Normal" }),
474
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("option", { value: "5", children: "Large" }),
475
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("option", { value: "7", children: "Huge" })
476
+ ] }),
477
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("button", { onClick: () => execCmd("bold"), style: btnStyle, title: "Bold", children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)("b", { children: "B" }) }),
478
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("button", { onClick: () => execCmd("italic"), style: btnStyle, title: "Italic", children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)("i", { children: "I" }) }),
479
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("button", { onClick: () => execCmd("underline"), style: btnStyle, title: "Underline", children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)("u", { children: "U" }) }),
480
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("button", { onClick: () => execCmd("strikeThrough"), style: btnStyle, title: "Strikethrough", children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)("s", { children: "S" }) }),
481
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("button", { onClick: () => execCmd("subscript"), style: btnStyle, title: "Subscript", children: "x\u2082" }),
482
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("button", { onClick: () => execCmd("superscript"), style: btnStyle, title: "Superscript", children: "x\xB2" }),
483
+ /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { style: { position: "relative" }, children: [
484
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("button", { onClick: () => setShowTextColor(!showTextColor), style: btnStyle, title: "Text Color", children: "A" }),
485
+ showTextColor && /* @__PURE__ */ (0, import_jsx_runtime.jsx)(ColorPicker, { onClose: () => setShowTextColor(false), onSelect: (c) => execCmd("foreColor", c), type: "text" })
486
+ ] }),
487
+ /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { style: { position: "relative" }, children: [
488
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("button", { onClick: () => setShowBgColor(!showBgColor), style: btnStyle, title: "Background Color", children: "\u25FC" }),
489
+ showBgColor && /* @__PURE__ */ (0, import_jsx_runtime.jsx)(ColorPicker, { onClose: () => setShowBgColor(false), onSelect: (c) => execCmd("backColor", c), type: "background" })
490
+ ] }),
491
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("button", { onClick: () => execCmd("justifyLeft"), style: btnStyle, title: "Align Left", children: "\u2261" }),
492
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("button", { onClick: () => execCmd("justifyCenter"), style: btnStyle, title: "Align Center", children: "\u2261" }),
493
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("button", { onClick: () => execCmd("justifyRight"), style: btnStyle, title: "Align Right", children: "\u2261" }),
494
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("button", { onClick: () => execCmd("justifyFull"), style: btnStyle, title: "Justify", children: "\u2261" }),
495
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("button", { onClick: () => execCmd("insertUnorderedList"), style: btnStyle, title: "Bullet List", children: "\u2022 List" }),
496
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("button", { onClick: () => execCmd("insertOrderedList"), style: btnStyle, title: "Numbered List", children: "1. List" }),
497
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("button", { onClick: () => execCmd("indent"), style: btnStyle, title: "Indent", children: "\u2192" }),
498
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("button", { onClick: () => execCmd("outdent"), style: btnStyle, title: "Outdent", children: "\u2190" }),
499
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("button", { onClick: () => execCmd("formatBlock", "blockquote"), style: btnStyle, title: "Blockquote", children: '"' }),
500
+ /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { style: { position: "relative" }, children: [
501
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("button", { onClick: () => setShowTablePopup(!showTablePopup), style: btnStyle, title: "Insert Table", children: "Table" }),
502
+ showTablePopup && /* @__PURE__ */ (0, import_jsx_runtime.jsx)(TableInsertPopup, { onClose: () => setShowTablePopup(false), onInsert: insertTable })
503
+ ] }),
504
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("button", { onClick: () => setShowSpecialChar(true), style: btnStyle, title: "Special Characters", children: "\u03A9" }),
505
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("button", { onClick: () => setShowFindReplace(true), style: btnStyle, title: "Find & Replace", children: "\u{1F50D}" }),
506
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("button", { onClick: handleCopy, style: btnStyle, title: "Copy", children: "Copy" }),
507
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("button", { onClick: handlePaste, style: btnStyle, title: "Paste", children: "Paste" }),
508
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("button", { onClick: handlePastePlain, style: btnStyle, title: "Paste Plain", children: "Paste Plain" }),
509
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("button", { onClick: toggleFullscreen, style: btnStyle, title: "Fullscreen", children: isFullscreen ? "\u2297" : "\u2295" })
510
+ ] }),
511
+ isSourceMode ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
512
+ "textarea",
513
+ {
514
+ value: sourceValue,
515
+ onChange: (e) => setSourceValue(e.target.value),
516
+ style: { width: "100%", minHeight: 400, padding: 10, border: "none", fontFamily: "monospace", resize: "vertical" }
517
+ }
518
+ ) : /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
519
+ "div",
520
+ {
521
+ ref: editorRef,
522
+ contentEditable: true,
523
+ onInput: handleInput,
524
+ style: { minHeight: 400, padding: 10, outline: "none" }
525
+ }
526
+ ),
527
+ showSpecialChar && /* @__PURE__ */ (0, import_jsx_runtime.jsx)(SpecialCharModal, { onClose: () => setShowSpecialChar(false), onInsert: insertSpecialChar }),
528
+ showFindReplace && /* @__PURE__ */ (0, import_jsx_runtime.jsx)(FindReplaceModal, { onClose: () => setShowFindReplace(false), editorRef })
529
+ ] });
530
+ };
531
+ // Annotate the CommonJS export names for ESM import in node:
532
+ 0 && (module.exports = {
533
+ CustomEditor
534
+ });
package/package.json ADDED
@@ -0,0 +1,28 @@
1
+ {
2
+ "name": "pdeditor",
3
+ "version": "1.0.0",
4
+ "main": "index.js",
5
+ "scripts": {
6
+ "build": "tsup src/index.tsx --dts"
7
+ },
8
+ "keywords": [],
9
+ "author": "",
10
+ "license": "ISC",
11
+ "type": "commonjs",
12
+ "files": ["dist"],
13
+ "description": "",
14
+ "devDependencies": {
15
+ "@types/react": "^19.2.13",
16
+ "@types/react-dom": "^19.2.3",
17
+ "tsup": "^8.5.1",
18
+ "typescript": "^5.9.3"
19
+ },
20
+ "peerDependencies": {
21
+ "react": ">=17",
22
+ "react-dom": ">=17"
23
+ },
24
+ "dependencies": {
25
+ "react": "^19.2.4",
26
+ "react-dom": "^19.2.4"
27
+ }
28
+ }