react-lite-rich-text-editor 1.1.3 → 1.1.4
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.js +825 -1370
- package/dist/index.cjs.js.map +1 -1
- package/dist/index.esm.js +822 -1367
- package/dist/index.esm.js.map +1 -1
- package/package.json +1 -1
package/dist/index.esm.js
CHANGED
|
@@ -1,593 +1,329 @@
|
|
|
1
1
|
import React, { useRef, useState, useEffect, useCallback } from 'react';
|
|
2
2
|
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
if (Array.isArray(r)) return r;
|
|
10
|
-
}
|
|
11
|
-
function asyncGeneratorStep(n, t, e, r, o, a, c) {
|
|
12
|
-
try {
|
|
13
|
-
var i = n[a](c),
|
|
14
|
-
u = i.value;
|
|
15
|
-
} catch (n) {
|
|
16
|
-
return void e(n);
|
|
17
|
-
}
|
|
18
|
-
i.done ? t(u) : Promise.resolve(u).then(r, o);
|
|
19
|
-
}
|
|
20
|
-
function _asyncToGenerator(n) {
|
|
21
|
-
return function () {
|
|
22
|
-
var t = this,
|
|
23
|
-
e = arguments;
|
|
24
|
-
return new Promise(function (r, o) {
|
|
25
|
-
var a = n.apply(t, e);
|
|
26
|
-
function _next(n) {
|
|
27
|
-
asyncGeneratorStep(a, r, o, _next, _throw, "next", n);
|
|
28
|
-
}
|
|
29
|
-
function _throw(n) {
|
|
30
|
-
asyncGeneratorStep(a, r, o, _next, _throw, "throw", n);
|
|
31
|
-
}
|
|
32
|
-
_next(void 0);
|
|
33
|
-
});
|
|
34
|
-
};
|
|
35
|
-
}
|
|
36
|
-
function _createForOfIteratorHelper(r, e) {
|
|
37
|
-
var t = "undefined" != typeof Symbol && r[Symbol.iterator] || r["@@iterator"];
|
|
38
|
-
if (!t) {
|
|
39
|
-
if (Array.isArray(r) || (t = _unsupportedIterableToArray(r)) || e) {
|
|
40
|
-
t && (r = t);
|
|
41
|
-
var n = 0,
|
|
42
|
-
F = function () {};
|
|
43
|
-
return {
|
|
44
|
-
s: F,
|
|
45
|
-
n: function () {
|
|
46
|
-
return n >= r.length ? {
|
|
47
|
-
done: true
|
|
48
|
-
} : {
|
|
49
|
-
done: false,
|
|
50
|
-
value: r[n++]
|
|
51
|
-
};
|
|
52
|
-
},
|
|
53
|
-
e: function (r) {
|
|
54
|
-
throw r;
|
|
55
|
-
},
|
|
56
|
-
f: F
|
|
57
|
-
};
|
|
58
|
-
}
|
|
59
|
-
throw new TypeError("Invalid attempt to iterate non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.");
|
|
60
|
-
}
|
|
61
|
-
var o,
|
|
62
|
-
a = true,
|
|
63
|
-
u = false;
|
|
64
|
-
return {
|
|
65
|
-
s: function () {
|
|
66
|
-
t = t.call(r);
|
|
67
|
-
},
|
|
68
|
-
n: function () {
|
|
69
|
-
var r = t.next();
|
|
70
|
-
return a = r.done, r;
|
|
71
|
-
},
|
|
72
|
-
e: function (r) {
|
|
73
|
-
u = true, o = r;
|
|
74
|
-
},
|
|
75
|
-
f: function () {
|
|
76
|
-
try {
|
|
77
|
-
a || null == t.return || t.return();
|
|
78
|
-
} finally {
|
|
79
|
-
if (u) throw o;
|
|
80
|
-
}
|
|
81
|
-
}
|
|
82
|
-
};
|
|
83
|
-
}
|
|
84
|
-
function _defineProperty(e, r, t) {
|
|
85
|
-
return (r = _toPropertyKey(r)) in e ? Object.defineProperty(e, r, {
|
|
86
|
-
value: t,
|
|
87
|
-
enumerable: true,
|
|
88
|
-
configurable: true,
|
|
89
|
-
writable: true
|
|
90
|
-
}) : e[r] = t, e;
|
|
91
|
-
}
|
|
92
|
-
function _iterableToArrayLimit(r, l) {
|
|
93
|
-
var t = null == r ? null : "undefined" != typeof Symbol && r[Symbol.iterator] || r["@@iterator"];
|
|
94
|
-
if (null != t) {
|
|
95
|
-
var e,
|
|
96
|
-
n,
|
|
97
|
-
i,
|
|
98
|
-
u,
|
|
99
|
-
a = [],
|
|
100
|
-
f = true,
|
|
101
|
-
o = false;
|
|
102
|
-
try {
|
|
103
|
-
if (i = (t = t.call(r)).next, 0 === l) ; else for (; !(f = (e = i.call(t)).done) && (a.push(e.value), a.length !== l); f = !0);
|
|
104
|
-
} catch (r) {
|
|
105
|
-
o = true, n = r;
|
|
106
|
-
} finally {
|
|
107
|
-
try {
|
|
108
|
-
if (!f && null != t.return && (u = t.return(), Object(u) !== u)) return;
|
|
109
|
-
} finally {
|
|
110
|
-
if (o) throw n;
|
|
111
|
-
}
|
|
112
|
-
}
|
|
113
|
-
return a;
|
|
114
|
-
}
|
|
115
|
-
}
|
|
116
|
-
function _nonIterableRest() {
|
|
117
|
-
throw new TypeError("Invalid attempt to destructure non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.");
|
|
118
|
-
}
|
|
119
|
-
function ownKeys(e, r) {
|
|
120
|
-
var t = Object.keys(e);
|
|
121
|
-
if (Object.getOwnPropertySymbols) {
|
|
122
|
-
var o = Object.getOwnPropertySymbols(e);
|
|
123
|
-
r && (o = o.filter(function (r) {
|
|
124
|
-
return Object.getOwnPropertyDescriptor(e, r).enumerable;
|
|
125
|
-
})), t.push.apply(t, o);
|
|
126
|
-
}
|
|
127
|
-
return t;
|
|
128
|
-
}
|
|
129
|
-
function _objectSpread2(e) {
|
|
130
|
-
for (var r = 1; r < arguments.length; r++) {
|
|
131
|
-
var t = null != arguments[r] ? arguments[r] : {};
|
|
132
|
-
r % 2 ? ownKeys(Object(t), true).forEach(function (r) {
|
|
133
|
-
_defineProperty(e, r, t[r]);
|
|
134
|
-
}) : Object.getOwnPropertyDescriptors ? Object.defineProperties(e, Object.getOwnPropertyDescriptors(t)) : ownKeys(Object(t)).forEach(function (r) {
|
|
135
|
-
Object.defineProperty(e, r, Object.getOwnPropertyDescriptor(t, r));
|
|
136
|
-
});
|
|
137
|
-
}
|
|
138
|
-
return e;
|
|
139
|
-
}
|
|
140
|
-
function _regenerator() {
|
|
141
|
-
/*! regenerator-runtime -- Copyright (c) 2014-present, Facebook, Inc. -- license (MIT): https://github.com/babel/babel/blob/main/packages/babel-helpers/LICENSE */
|
|
142
|
-
var e,
|
|
143
|
-
t,
|
|
144
|
-
r = "function" == typeof Symbol ? Symbol : {},
|
|
145
|
-
n = r.iterator || "@@iterator",
|
|
146
|
-
o = r.toStringTag || "@@toStringTag";
|
|
147
|
-
function i(r, n, o, i) {
|
|
148
|
-
var c = n && n.prototype instanceof Generator ? n : Generator,
|
|
149
|
-
u = Object.create(c.prototype);
|
|
150
|
-
return _regeneratorDefine(u, "_invoke", function (r, n, o) {
|
|
151
|
-
var i,
|
|
152
|
-
c,
|
|
153
|
-
u,
|
|
154
|
-
f = 0,
|
|
155
|
-
p = o || [],
|
|
156
|
-
y = false,
|
|
157
|
-
G = {
|
|
158
|
-
p: 0,
|
|
159
|
-
n: 0,
|
|
160
|
-
v: e,
|
|
161
|
-
a: d,
|
|
162
|
-
f: d.bind(e, 4),
|
|
163
|
-
d: function (t, r) {
|
|
164
|
-
return i = t, c = 0, u = e, G.n = r, a;
|
|
165
|
-
}
|
|
166
|
-
};
|
|
167
|
-
function d(r, n) {
|
|
168
|
-
for (c = r, u = n, t = 0; !y && f && !o && t < p.length; t++) {
|
|
169
|
-
var o,
|
|
170
|
-
i = p[t],
|
|
171
|
-
d = G.p,
|
|
172
|
-
l = i[2];
|
|
173
|
-
r > 3 ? (o = l === n) && (u = i[(c = i[4]) ? 5 : (c = 3, 3)], i[4] = i[5] = e) : i[0] <= d && ((o = r < 2 && d < i[1]) ? (c = 0, G.v = n, G.n = i[1]) : d < l && (o = r < 3 || i[0] > n || n > l) && (i[4] = r, i[5] = n, G.n = l, c = 0));
|
|
174
|
-
}
|
|
175
|
-
if (o || r > 1) return a;
|
|
176
|
-
throw y = true, n;
|
|
177
|
-
}
|
|
178
|
-
return function (o, p, l) {
|
|
179
|
-
if (f > 1) throw TypeError("Generator is already running");
|
|
180
|
-
for (y && 1 === p && d(p, l), c = p, u = l; (t = c < 2 ? e : u) || !y;) {
|
|
181
|
-
i || (c ? c < 3 ? (c > 1 && (G.n = -1), d(c, u)) : G.n = u : G.v = u);
|
|
182
|
-
try {
|
|
183
|
-
if (f = 2, i) {
|
|
184
|
-
if (c || (o = "next"), t = i[o]) {
|
|
185
|
-
if (!(t = t.call(i, u))) throw TypeError("iterator result is not an object");
|
|
186
|
-
if (!t.done) return t;
|
|
187
|
-
u = t.value, c < 2 && (c = 0);
|
|
188
|
-
} else 1 === c && (t = i.return) && t.call(i), c < 2 && (u = TypeError("The iterator does not provide a '" + o + "' method"), c = 1);
|
|
189
|
-
i = e;
|
|
190
|
-
} else if ((t = (y = G.n < 0) ? u : r.call(n, G)) !== a) break;
|
|
191
|
-
} catch (t) {
|
|
192
|
-
i = e, c = 1, u = t;
|
|
193
|
-
} finally {
|
|
194
|
-
f = 1;
|
|
195
|
-
}
|
|
196
|
-
}
|
|
197
|
-
return {
|
|
198
|
-
value: t,
|
|
199
|
-
done: y
|
|
200
|
-
};
|
|
201
|
-
};
|
|
202
|
-
}(r, o, i), true), u;
|
|
203
|
-
}
|
|
204
|
-
var a = {};
|
|
205
|
-
function Generator() {}
|
|
206
|
-
function GeneratorFunction() {}
|
|
207
|
-
function GeneratorFunctionPrototype() {}
|
|
208
|
-
t = Object.getPrototypeOf;
|
|
209
|
-
var c = [][n] ? t(t([][n]())) : (_regeneratorDefine(t = {}, n, function () {
|
|
210
|
-
return this;
|
|
211
|
-
}), t),
|
|
212
|
-
u = GeneratorFunctionPrototype.prototype = Generator.prototype = Object.create(c);
|
|
213
|
-
function f(e) {
|
|
214
|
-
return Object.setPrototypeOf ? Object.setPrototypeOf(e, GeneratorFunctionPrototype) : (e.__proto__ = GeneratorFunctionPrototype, _regeneratorDefine(e, o, "GeneratorFunction")), e.prototype = Object.create(u), e;
|
|
215
|
-
}
|
|
216
|
-
return GeneratorFunction.prototype = GeneratorFunctionPrototype, _regeneratorDefine(u, "constructor", GeneratorFunctionPrototype), _regeneratorDefine(GeneratorFunctionPrototype, "constructor", GeneratorFunction), GeneratorFunction.displayName = "GeneratorFunction", _regeneratorDefine(GeneratorFunctionPrototype, o, "GeneratorFunction"), _regeneratorDefine(u), _regeneratorDefine(u, o, "Generator"), _regeneratorDefine(u, n, function () {
|
|
217
|
-
return this;
|
|
218
|
-
}), _regeneratorDefine(u, "toString", function () {
|
|
219
|
-
return "[object Generator]";
|
|
220
|
-
}), (_regenerator = function () {
|
|
221
|
-
return {
|
|
222
|
-
w: i,
|
|
223
|
-
m: f
|
|
224
|
-
};
|
|
225
|
-
})();
|
|
226
|
-
}
|
|
227
|
-
function _regeneratorDefine(e, r, n, t) {
|
|
228
|
-
var i = Object.defineProperty;
|
|
229
|
-
try {
|
|
230
|
-
i({}, "", {});
|
|
231
|
-
} catch (e) {
|
|
232
|
-
i = 0;
|
|
233
|
-
}
|
|
234
|
-
_regeneratorDefine = function (e, r, n, t) {
|
|
235
|
-
function o(r, n) {
|
|
236
|
-
_regeneratorDefine(e, r, function (e) {
|
|
237
|
-
return this._invoke(r, n, e);
|
|
238
|
-
});
|
|
239
|
-
}
|
|
240
|
-
r ? i ? i(e, r, {
|
|
241
|
-
value: n,
|
|
242
|
-
enumerable: !t,
|
|
243
|
-
configurable: !t,
|
|
244
|
-
writable: !t
|
|
245
|
-
}) : e[r] = n : (o("next", 0), o("throw", 1), o("return", 2));
|
|
246
|
-
}, _regeneratorDefine(e, r, n, t);
|
|
247
|
-
}
|
|
248
|
-
function _regeneratorValues(e) {
|
|
249
|
-
if (null != e) {
|
|
250
|
-
var t = e["function" == typeof Symbol && Symbol.iterator || "@@iterator"],
|
|
251
|
-
r = 0;
|
|
252
|
-
if (t) return t.call(e);
|
|
253
|
-
if ("function" == typeof e.next) return e;
|
|
254
|
-
if (!isNaN(e.length)) return {
|
|
255
|
-
next: function () {
|
|
256
|
-
return e && r >= e.length && (e = void 0), {
|
|
257
|
-
value: e && e[r++],
|
|
258
|
-
done: !e
|
|
259
|
-
};
|
|
260
|
-
}
|
|
261
|
-
};
|
|
262
|
-
}
|
|
263
|
-
throw new TypeError(typeof e + " is not iterable");
|
|
264
|
-
}
|
|
265
|
-
function _slicedToArray(r, e) {
|
|
266
|
-
return _arrayWithHoles(r) || _iterableToArrayLimit(r, e) || _unsupportedIterableToArray(r, e) || _nonIterableRest();
|
|
267
|
-
}
|
|
268
|
-
function _toPrimitive(t, r) {
|
|
269
|
-
if ("object" != typeof t || !t) return t;
|
|
270
|
-
var e = t[Symbol.toPrimitive];
|
|
271
|
-
if (void 0 !== e) {
|
|
272
|
-
var i = e.call(t, r);
|
|
273
|
-
if ("object" != typeof i) return i;
|
|
274
|
-
throw new TypeError("@@toPrimitive must return a primitive value.");
|
|
275
|
-
}
|
|
276
|
-
return ("string" === r ? String : Number)(t);
|
|
277
|
-
}
|
|
278
|
-
function _toPropertyKey(t) {
|
|
279
|
-
var i = _toPrimitive(t, "string");
|
|
280
|
-
return "symbol" == typeof i ? i : i + "";
|
|
281
|
-
}
|
|
282
|
-
function _typeof(o) {
|
|
283
|
-
"@babel/helpers - typeof";
|
|
284
|
-
|
|
285
|
-
return _typeof = "function" == typeof Symbol && "symbol" == typeof Symbol.iterator ? function (o) {
|
|
286
|
-
return typeof o;
|
|
287
|
-
} : function (o) {
|
|
288
|
-
return o && "function" == typeof Symbol && o.constructor === Symbol && o !== Symbol.prototype ? "symbol" : typeof o;
|
|
289
|
-
}, _typeof(o);
|
|
290
|
-
}
|
|
291
|
-
function _unsupportedIterableToArray(r, a) {
|
|
292
|
-
if (r) {
|
|
293
|
-
if ("string" == typeof r) return _arrayLikeToArray(r, a);
|
|
294
|
-
var t = {}.toString.call(r).slice(8, -1);
|
|
295
|
-
return "Object" === t && r.constructor && (t = r.constructor.name), "Map" === t || "Set" === t ? Array.from(r) : "Arguments" === t || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(t) ? _arrayLikeToArray(r, a) : void 0;
|
|
296
|
-
}
|
|
297
|
-
}
|
|
298
|
-
|
|
299
|
-
var FaImage = function FaImage(_ref) {
|
|
300
|
-
var className = _ref.className,
|
|
301
|
-
size = _ref.size,
|
|
302
|
-
color = _ref.color,
|
|
303
|
-
style = _ref.style;
|
|
3
|
+
const FaImage = ({
|
|
4
|
+
className,
|
|
5
|
+
size,
|
|
6
|
+
color,
|
|
7
|
+
style
|
|
8
|
+
}) => {
|
|
304
9
|
return /*#__PURE__*/React.createElement("span", {
|
|
305
10
|
className: className,
|
|
306
|
-
style:
|
|
11
|
+
style: {
|
|
307
12
|
display: 'inline-flex',
|
|
308
13
|
alignItems: 'center',
|
|
309
14
|
justifyContent: 'center',
|
|
310
15
|
fontSize: size || '1em',
|
|
311
|
-
color: color || 'inherit'
|
|
312
|
-
|
|
16
|
+
color: color || 'inherit',
|
|
17
|
+
...style
|
|
18
|
+
},
|
|
313
19
|
dangerouslySetInnerHTML: {
|
|
314
|
-
__html:
|
|
20
|
+
__html: `<svg stroke="currentColor" fill="currentColor" stroke-width="0" viewBox="0 0 512 512" height="1em" width="1em" xmlns="http://www.w3.org/2000/svg"><path d="M464 448H48c-26.51 0-48-21.49-48-48V112c0-26.51 21.49-48 48-48h416c26.51 0 48 21.49 48 48v288c0 26.51-21.49 48-48 48zM112 120c-30.928 0-56 25.072-56 56s25.072 56 56 56 56-25.072 56-56-25.072-56-56-56zM64 384h384V272l-87.515-87.515c-4.686-4.686-12.284-4.686-16.971 0L208 320l-55.515-55.515c-4.686-4.686-12.284-4.686-16.971 0L64 336v48z"></path></svg>`
|
|
315
21
|
}
|
|
316
22
|
});
|
|
317
23
|
};
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
24
|
+
const FaBold = ({
|
|
25
|
+
className,
|
|
26
|
+
size,
|
|
27
|
+
color,
|
|
28
|
+
style
|
|
29
|
+
}) => {
|
|
323
30
|
return /*#__PURE__*/React.createElement("span", {
|
|
324
31
|
className: className,
|
|
325
|
-
style:
|
|
32
|
+
style: {
|
|
326
33
|
display: 'inline-flex',
|
|
327
34
|
alignItems: 'center',
|
|
328
35
|
justifyContent: 'center',
|
|
329
36
|
fontSize: size || '1em',
|
|
330
|
-
color: color || 'inherit'
|
|
331
|
-
|
|
37
|
+
color: color || 'inherit',
|
|
38
|
+
...style
|
|
39
|
+
},
|
|
332
40
|
dangerouslySetInnerHTML: {
|
|
333
|
-
__html:
|
|
41
|
+
__html: `<svg stroke="currentColor" fill="currentColor" stroke-width="0" viewBox="0 0 384 512" height="1em" width="1em" xmlns="http://www.w3.org/2000/svg"><path d="M333.49 238a122 122 0 0 0 27-65.21C367.87 96.49 308 32 233.42 32H34a16 16 0 0 0-16 16v48a16 16 0 0 0 16 16h31.87v288H34a16 16 0 0 0-16 16v48a16 16 0 0 0 16 16h209.32c70.8 0 134.14-51.75 141-122.4 4.74-48.45-16.39-92.06-50.83-119.6zM145.66 112h87.76a48 48 0 0 1 0 96h-87.76zm87.76 288h-87.76V288h87.76a56 56 0 0 1 0 112z"></path></svg>`
|
|
334
42
|
}
|
|
335
43
|
});
|
|
336
44
|
};
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
45
|
+
const FaItalic = ({
|
|
46
|
+
className,
|
|
47
|
+
size,
|
|
48
|
+
color,
|
|
49
|
+
style
|
|
50
|
+
}) => {
|
|
342
51
|
return /*#__PURE__*/React.createElement("span", {
|
|
343
52
|
className: className,
|
|
344
|
-
style:
|
|
53
|
+
style: {
|
|
345
54
|
display: 'inline-flex',
|
|
346
55
|
alignItems: 'center',
|
|
347
56
|
justifyContent: 'center',
|
|
348
57
|
fontSize: size || '1em',
|
|
349
|
-
color: color || 'inherit'
|
|
350
|
-
|
|
58
|
+
color: color || 'inherit',
|
|
59
|
+
...style
|
|
60
|
+
},
|
|
351
61
|
dangerouslySetInnerHTML: {
|
|
352
|
-
__html:
|
|
62
|
+
__html: `<svg stroke="currentColor" fill="currentColor" stroke-width="0" viewBox="0 0 320 512" height="1em" width="1em" xmlns="http://www.w3.org/2000/svg"><path d="M320 48v32a16 16 0 0 1-16 16h-62.76l-80 320H208a16 16 0 0 1 16 16v32a16 16 0 0 1-16 16H16a16 16 0 0 1-16-16v-32a16 16 0 0 1 16-16h62.76l80-320H112a16 16 0 0 1-16-16V48a16 16 0 0 1 16-16h192a16 16 0 0 1 16 16z"></path></svg>`
|
|
353
63
|
}
|
|
354
64
|
});
|
|
355
65
|
};
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
|
|
66
|
+
const FaUnderline = ({
|
|
67
|
+
className,
|
|
68
|
+
size,
|
|
69
|
+
color,
|
|
70
|
+
style
|
|
71
|
+
}) => {
|
|
361
72
|
return /*#__PURE__*/React.createElement("span", {
|
|
362
73
|
className: className,
|
|
363
|
-
style:
|
|
74
|
+
style: {
|
|
364
75
|
display: 'inline-flex',
|
|
365
76
|
alignItems: 'center',
|
|
366
77
|
justifyContent: 'center',
|
|
367
78
|
fontSize: size || '1em',
|
|
368
|
-
color: color || 'inherit'
|
|
369
|
-
|
|
79
|
+
color: color || 'inherit',
|
|
80
|
+
...style
|
|
81
|
+
},
|
|
370
82
|
dangerouslySetInnerHTML: {
|
|
371
|
-
__html:
|
|
83
|
+
__html: `<svg stroke="currentColor" fill="currentColor" stroke-width="0" viewBox="0 0 448 512" height="1em" width="1em" xmlns="http://www.w3.org/2000/svg"><path d="M32 64h32v160c0 88.22 71.78 160 160 160s160-71.78 160-160V64h32a16 16 0 0 0 16-16V16a16 16 0 0 0-16-16H272a16 16 0 0 0-16 16v32a16 16 0 0 0 16 16h32v160a80 80 0 0 1-160 0V64h32a16 16 0 0 0 16-16V16a16 16 0 0 0-16-16H32a16 16 0 0 0-16 16v32a16 16 0 0 0 16 16zm400 384H16a16 16 0 0 0-16 16v32a16 16 0 0 0 16 16h416a16 16 0 0 0 16-16v-32a16 16 0 0 0-16-16z"></path></svg>`
|
|
372
84
|
}
|
|
373
85
|
});
|
|
374
86
|
};
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
|
|
379
|
-
|
|
87
|
+
const FaTextHeight = ({
|
|
88
|
+
className,
|
|
89
|
+
size,
|
|
90
|
+
color,
|
|
91
|
+
style
|
|
92
|
+
}) => {
|
|
380
93
|
return /*#__PURE__*/React.createElement("span", {
|
|
381
94
|
className: className,
|
|
382
|
-
style:
|
|
95
|
+
style: {
|
|
383
96
|
display: 'inline-flex',
|
|
384
97
|
alignItems: 'center',
|
|
385
98
|
justifyContent: 'center',
|
|
386
99
|
fontSize: size || '1em',
|
|
387
|
-
color: color || 'inherit'
|
|
388
|
-
|
|
100
|
+
color: color || 'inherit',
|
|
101
|
+
...style
|
|
102
|
+
},
|
|
389
103
|
dangerouslySetInnerHTML: {
|
|
390
|
-
__html:
|
|
104
|
+
__html: `<svg stroke="currentColor" fill="currentColor" stroke-width="0" viewBox="0 0 576 512" height="1em" width="1em" xmlns="http://www.w3.org/2000/svg"><path d="M304 32H16A16 16 0 0 0 0 48v96a16 16 0 0 0 16 16h32a16 16 0 0 0 16-16v-32h56v304H80a16 16 0 0 0-16 16v32a16 16 0 0 0 16 16h160a16 16 0 0 0 16-16v-32a16 16 0 0 0-16-16h-40V112h56v32a16 16 0 0 0 16 16h32a16 16 0 0 0 16-16V48a16 16 0 0 0-16-16zm256 336h-48V144h48c14.31 0 21.33-17.31 11.31-27.31l-80-80a16 16 0 0 0-22.62 0l-80 80C379.36 126 384.36 144 400 144h48v224h-48c-14.31 0-21.32 17.31-11.31 27.31l80 80a16 16 0 0 0 22.62 0l80-80C580.64 386 575.64 368 560 368z"></path></svg>`
|
|
391
105
|
}
|
|
392
106
|
});
|
|
393
107
|
};
|
|
394
|
-
|
|
395
|
-
|
|
396
|
-
|
|
397
|
-
|
|
398
|
-
|
|
108
|
+
const FaAlignCenter = ({
|
|
109
|
+
className,
|
|
110
|
+
size,
|
|
111
|
+
color,
|
|
112
|
+
style
|
|
113
|
+
}) => {
|
|
399
114
|
return /*#__PURE__*/React.createElement("span", {
|
|
400
115
|
className: className,
|
|
401
|
-
style:
|
|
116
|
+
style: {
|
|
402
117
|
display: 'inline-flex',
|
|
403
118
|
alignItems: 'center',
|
|
404
119
|
justifyContent: 'center',
|
|
405
120
|
fontSize: size || '1em',
|
|
406
|
-
color: color || 'inherit'
|
|
407
|
-
|
|
121
|
+
color: color || 'inherit',
|
|
122
|
+
...style
|
|
123
|
+
},
|
|
408
124
|
dangerouslySetInnerHTML: {
|
|
409
|
-
__html:
|
|
125
|
+
__html: `<svg stroke="currentColor" fill="currentColor" stroke-width="0" viewBox="0 0 448 512" height="1em" width="1em" xmlns="http://www.w3.org/2000/svg"><path d="M432 160H16a16 16 0 0 0-16 16v32a16 16 0 0 0 16 16h416a16 16 0 0 0 16-16v-32a16 16 0 0 0-16-16zm0 256H16a16 16 0 0 0-16 16v32a16 16 0 0 0 16 16h416a16 16 0 0 0 16-16v-32a16 16 0 0 0-16-16zM108.1 96h231.81A12.09 12.09 0 0 0 352 83.9V44.09A12.09 12.09 0 0 0 339.91 32H108.1A12.09 12.09 0 0 0 96 44.09V83.9A12.1 12.1 0 0 0 108.1 96zm231.81 256A12.09 12.09 0 0 0 352 339.9v-39.81A12.09 12.09 0 0 0 339.91 288H108.1A12.09 12.09 0 0 0 96 300.09v39.81a12.1 12.1 0 0 0 12.1 12.1z"></path></svg>`
|
|
410
126
|
}
|
|
411
127
|
});
|
|
412
128
|
};
|
|
413
|
-
|
|
414
|
-
|
|
415
|
-
|
|
416
|
-
|
|
417
|
-
|
|
129
|
+
const FaAlignRight = ({
|
|
130
|
+
className,
|
|
131
|
+
size,
|
|
132
|
+
color,
|
|
133
|
+
style
|
|
134
|
+
}) => {
|
|
418
135
|
return /*#__PURE__*/React.createElement("span", {
|
|
419
136
|
className: className,
|
|
420
|
-
style:
|
|
137
|
+
style: {
|
|
421
138
|
display: 'inline-flex',
|
|
422
139
|
alignItems: 'center',
|
|
423
140
|
justifyContent: 'center',
|
|
424
141
|
fontSize: size || '1em',
|
|
425
|
-
color: color || 'inherit'
|
|
426
|
-
|
|
142
|
+
color: color || 'inherit',
|
|
143
|
+
...style
|
|
144
|
+
},
|
|
427
145
|
dangerouslySetInnerHTML: {
|
|
428
|
-
__html:
|
|
146
|
+
__html: `<svg stroke="currentColor" fill="currentColor" stroke-width="0" viewBox="0 0 448 512" height="1em" width="1em" xmlns="http://www.w3.org/2000/svg"><path d="M16 224h416a16 16 0 0 0 16-16v-32a16 16 0 0 0-16-16H16a16 16 0 0 0-16 16v32a16 16 0 0 0 16 16zm416 192H16a16 16 0 0 0-16 16v32a16 16 0 0 0 16 16h416a16 16 0 0 0 16-16v-32a16 16 0 0 0-16-16zm3.17-384H172.83A12.82 12.82 0 0 0 160 44.83v38.34A12.82 12.82 0 0 0 172.83 96h262.34A12.82 12.82 0 0 0 448 83.17V44.83A12.82 12.82 0 0 0 435.17 32zm0 256H172.83A12.82 12.82 0 0 0 160 300.83v38.34A12.82 12.82 0 0 0 172.83 352h262.34A12.82 12.82 0 0 0 448 339.17v-38.34A12.82 12.82 0 0 0 435.17 288z"></path></svg>`
|
|
429
147
|
}
|
|
430
148
|
});
|
|
431
149
|
};
|
|
432
|
-
|
|
433
|
-
|
|
434
|
-
|
|
435
|
-
|
|
436
|
-
|
|
150
|
+
const FaAlignLeft = ({
|
|
151
|
+
className,
|
|
152
|
+
size,
|
|
153
|
+
color,
|
|
154
|
+
style
|
|
155
|
+
}) => {
|
|
437
156
|
return /*#__PURE__*/React.createElement("span", {
|
|
438
157
|
className: className,
|
|
439
|
-
style:
|
|
158
|
+
style: {
|
|
440
159
|
display: 'inline-flex',
|
|
441
160
|
alignItems: 'center',
|
|
442
161
|
justifyContent: 'center',
|
|
443
162
|
fontSize: size || '1em',
|
|
444
|
-
color: color || 'inherit'
|
|
445
|
-
|
|
163
|
+
color: color || 'inherit',
|
|
164
|
+
...style
|
|
165
|
+
},
|
|
446
166
|
dangerouslySetInnerHTML: {
|
|
447
|
-
__html:
|
|
167
|
+
__html: `<svg stroke="currentColor" fill="currentColor" stroke-width="0" viewBox="0 0 448 512" height="1em" width="1em" xmlns="http://www.w3.org/2000/svg"><path d="M12.83 352h262.34A12.82 12.82 0 0 0 288 339.17v-38.34A12.82 12.82 0 0 0 275.17 288H12.83A12.82 12.82 0 0 0 0 300.83v38.34A12.82 12.82 0 0 0 12.83 352zm0-256h262.34A12.82 12.82 0 0 0 288 83.17V44.83A12.82 12.82 0 0 0 275.17 32H12.83A12.82 12.82 0 0 0 0 44.83v38.34A12.82 12.82 0 0 0 12.83 96zM432 160H16a16 16 0 0 0-16 16v32a16 16 0 0 0 16 16h416a16 16 0 0 0 16-16v-32a16 16 0 0 0-16-16zm0 256H16a16 16 0 0 0-16 16v32a16 16 0 0 0 16 16h416a16 16 0 0 0 16-16v-32a16 16 0 0 0-16-16z"></path></svg>`
|
|
448
168
|
}
|
|
449
169
|
});
|
|
450
170
|
};
|
|
451
|
-
|
|
452
|
-
|
|
453
|
-
|
|
454
|
-
|
|
455
|
-
|
|
171
|
+
const FaListOl = ({
|
|
172
|
+
className,
|
|
173
|
+
size,
|
|
174
|
+
color,
|
|
175
|
+
style
|
|
176
|
+
}) => {
|
|
456
177
|
return /*#__PURE__*/React.createElement("span", {
|
|
457
178
|
className: className,
|
|
458
|
-
style:
|
|
179
|
+
style: {
|
|
459
180
|
display: 'inline-flex',
|
|
460
181
|
alignItems: 'center',
|
|
461
182
|
justifyContent: 'center',
|
|
462
183
|
fontSize: size || '1em',
|
|
463
|
-
color: color || 'inherit'
|
|
464
|
-
|
|
184
|
+
color: color || 'inherit',
|
|
185
|
+
...style
|
|
186
|
+
},
|
|
465
187
|
dangerouslySetInnerHTML: {
|
|
466
|
-
__html:
|
|
188
|
+
__html: `<svg stroke="currentColor" fill="currentColor" stroke-width="0" viewBox="0 0 512 512" height="1em" width="1em" xmlns="http://www.w3.org/2000/svg"><path d="M61.77 401l17.5-20.15a19.92 19.92 0 0 0 5.07-14.19v-3.31C84.34 356 80.5 352 73 352H16a8 8 0 0 0-8 8v16a8 8 0 0 0 8 8h22.83a157.41 157.41 0 0 0-11 12.31l-5.61 7c-4 5.07-5.25 10.13-2.8 14.88l1.05 1.93c3 5.76 6.29 7.88 12.25 7.88h4.73c10.33 0 15.94 2.44 15.94 9.09 0 4.72-4.2 8.22-14.36 8.22a41.54 41.54 0 0 1-15.47-3.12c-6.49-3.88-11.74-3.5-15.6 3.12l-5.59 9.31c-3.72 6.13-3.19 11.72 2.63 15.94 7.71 4.69 20.38 9.44 37 9.44 34.16 0 48.5-22.75 48.5-44.12-.03-14.38-9.12-29.76-28.73-34.88zM496 224H176a16 16 0 0 0-16 16v32a16 16 0 0 0 16 16h320a16 16 0 0 0 16-16v-32a16 16 0 0 0-16-16zm0-160H176a16 16 0 0 0-16 16v32a16 16 0 0 0 16 16h320a16 16 0 0 0 16-16V80a16 16 0 0 0-16-16zm0 320H176a16 16 0 0 0-16 16v32a16 16 0 0 0 16 16h320a16 16 0 0 0 16-16v-32a16 16 0 0 0-16-16zM16 160h64a8 8 0 0 0 8-8v-16a8 8 0 0 0-8-8H64V40a8 8 0 0 0-8-8H32a8 8 0 0 0-7.14 4.42l-8 16A8 8 0 0 0 24 64h8v64H16a8 8 0 0 0-8 8v16a8 8 0 0 0 8 8zm-3.91 160H80a8 8 0 0 0 8-8v-16a8 8 0 0 0-8-8H41.32c3.29-10.29 48.34-18.68 48.34-56.44 0-29.06-25-39.56-44.47-39.56-21.36 0-33.8 10-40.46 18.75-4.37 5.59-3 10.84 2.8 15.37l8.58 6.88c5.61 4.56 11 2.47 16.12-2.44a13.44 13.44 0 0 1 9.46-3.84c3.33 0 9.28 1.56 9.28 8.75C51 248.19 0 257.31 0 304.59v4C0 316 5.08 320 12.09 320z"></path></svg>`
|
|
467
189
|
}
|
|
468
190
|
});
|
|
469
191
|
};
|
|
470
|
-
|
|
471
|
-
|
|
472
|
-
|
|
473
|
-
|
|
474
|
-
|
|
192
|
+
const FaListUl = ({
|
|
193
|
+
className,
|
|
194
|
+
size,
|
|
195
|
+
color,
|
|
196
|
+
style
|
|
197
|
+
}) => {
|
|
475
198
|
return /*#__PURE__*/React.createElement("span", {
|
|
476
199
|
className: className,
|
|
477
|
-
style:
|
|
200
|
+
style: {
|
|
478
201
|
display: 'inline-flex',
|
|
479
202
|
alignItems: 'center',
|
|
480
203
|
justifyContent: 'center',
|
|
481
204
|
fontSize: size || '1em',
|
|
482
|
-
color: color || 'inherit'
|
|
483
|
-
|
|
205
|
+
color: color || 'inherit',
|
|
206
|
+
...style
|
|
207
|
+
},
|
|
484
208
|
dangerouslySetInnerHTML: {
|
|
485
|
-
__html:
|
|
209
|
+
__html: `<svg stroke="currentColor" fill="currentColor" stroke-width="0" viewBox="0 0 512 512" height="1em" width="1em" xmlns="http://www.w3.org/2000/svg"><path d="M48 48a48 48 0 1 0 48 48 48 48 0 0 0-48-48zm0 160a48 48 0 1 0 48 48 48 48 0 0 0-48-48zm0 160a48 48 0 1 0 48 48 48 48 0 0 0-48-48zm448 16H176a16 16 0 0 0-16 16v32a16 16 0 0 0 16 16h320a16 16 0 0 0 16-16v-32a16 16 0 0 0-16-16zm0-320H176a16 16 0 0 0-16 16v32a16 16 0 0 0 16 16h320a16 16 0 0 0 16-16V80a16 16 0 0 0-16-16zm0 160H176a16 16 0 0 0-16 16v32a16 16 0 0 0 16 16h320a16 16 0 0 0 16-16v-32a16 16 0 0 0-16-16z"></path></svg>`
|
|
486
210
|
}
|
|
487
211
|
});
|
|
488
212
|
};
|
|
489
|
-
|
|
490
|
-
|
|
491
|
-
|
|
492
|
-
|
|
493
|
-
|
|
213
|
+
const FaFont = ({
|
|
214
|
+
className,
|
|
215
|
+
size,
|
|
216
|
+
color,
|
|
217
|
+
style
|
|
218
|
+
}) => {
|
|
494
219
|
return /*#__PURE__*/React.createElement("span", {
|
|
495
220
|
className: className,
|
|
496
|
-
style:
|
|
221
|
+
style: {
|
|
497
222
|
display: 'inline-flex',
|
|
498
223
|
alignItems: 'center',
|
|
499
224
|
justifyContent: 'center',
|
|
500
225
|
fontSize: size || '1em',
|
|
501
|
-
color: color || 'inherit'
|
|
502
|
-
|
|
226
|
+
color: color || 'inherit',
|
|
227
|
+
...style
|
|
228
|
+
},
|
|
503
229
|
dangerouslySetInnerHTML: {
|
|
504
|
-
__html:
|
|
230
|
+
__html: `<svg stroke="currentColor" fill="currentColor" stroke-width="0" viewBox="0 0 448 512" height="1em" width="1em" xmlns="http://www.w3.org/2000/svg"><path d="M432 416h-23.41L277.88 53.69A32 32 0 0 0 247.58 32h-47.16a32 32 0 0 0-30.3 21.69L39.41 416H16a16 16 0 0 0-16 16v32a16 16 0 0 0 16 16h128a16 16 0 0 0 16-16v-32a16 16 0 0 0-16-16h-19.58l23.3-64h152.56l23.3 64H304a16 16 0 0 0-16 16v32a16 16 0 0 0 16 16h128a16 16 0 0 0 16-16v-32a16 16 0 0 0-16-16zM176.85 272L224 142.51 271.15 272z"></path></svg>`
|
|
505
231
|
}
|
|
506
232
|
});
|
|
507
233
|
};
|
|
508
|
-
|
|
509
|
-
|
|
510
|
-
|
|
511
|
-
|
|
512
|
-
|
|
234
|
+
const FaTable = ({
|
|
235
|
+
className,
|
|
236
|
+
size,
|
|
237
|
+
color,
|
|
238
|
+
style
|
|
239
|
+
}) => {
|
|
513
240
|
return /*#__PURE__*/React.createElement("span", {
|
|
514
241
|
className: className,
|
|
515
|
-
style:
|
|
242
|
+
style: {
|
|
516
243
|
display: 'inline-flex',
|
|
517
244
|
alignItems: 'center',
|
|
518
245
|
justifyContent: 'center',
|
|
519
246
|
fontSize: size || '1em',
|
|
520
|
-
color: color || 'inherit'
|
|
521
|
-
|
|
247
|
+
color: color || 'inherit',
|
|
248
|
+
...style
|
|
249
|
+
},
|
|
522
250
|
dangerouslySetInnerHTML: {
|
|
523
|
-
__html:
|
|
251
|
+
__html: `<svg stroke="currentColor" fill="currentColor" stroke-width="0" viewBox="0 0 512 512" height="1em" width="1em" xmlns="http://www.w3.org/2000/svg"><path d="M64 448c-35.3 0-64-28.7-64-64V128c0-35.3 28.7-64 64-64H448c35.3 0 64 28.7 64 64V384c0 35.3-28.7 64-64 64H64zm96-288H64v64h96v-64zm0 96H64v64h96v-64zm0 96H64c0 17.7 14.3 32 32 32h64v-32zm128-192h-96v64h96v-64zm0 96h-96v64h96v-64zm0 96h-96v96h96v-96zm160-192h-96v64h96v-64zm0 96h-96v64h96v-64zm0 96h-96v64h64c17.7 0 32-14.3 32-32v-32z"></path></svg>`
|
|
524
252
|
}
|
|
525
253
|
});
|
|
526
254
|
};
|
|
527
|
-
|
|
528
|
-
|
|
529
|
-
|
|
530
|
-
|
|
531
|
-
|
|
255
|
+
const FaObjectGroup = ({
|
|
256
|
+
className,
|
|
257
|
+
size,
|
|
258
|
+
color,
|
|
259
|
+
style
|
|
260
|
+
}) => {
|
|
532
261
|
return /*#__PURE__*/React.createElement("span", {
|
|
533
262
|
className: className,
|
|
534
|
-
style:
|
|
263
|
+
style: {
|
|
535
264
|
display: 'inline-flex',
|
|
536
265
|
alignItems: 'center',
|
|
537
266
|
justifyContent: 'center',
|
|
538
267
|
fontSize: size || '1em',
|
|
539
|
-
color: color || 'inherit'
|
|
540
|
-
|
|
268
|
+
color: color || 'inherit',
|
|
269
|
+
...style
|
|
270
|
+
},
|
|
541
271
|
dangerouslySetInnerHTML: {
|
|
542
|
-
__html:
|
|
272
|
+
__html: `<svg stroke="currentColor" fill="currentColor" stroke-width="0" viewBox="0 0 512 512" height="1em" width="1em" xmlns="http://www.w3.org/2000/svg"><path d="M480 320h-48v48c0 17.7-14.3 32-32 32h-48v32c0 26.5-21.5 48-48 48H48c-26.5 0-48-21.5-48-48V160c0-26.5 21.5-48 48-48h32v-48c0-17.7 14.3-32 32-32h48V0h32c26.5 0 48 21.5 48 48v48h48c17.7 0 32 14.3 32 32v48h32c26.5 0 48 21.5 48 48v128c0 26.5-21.5 48-48 48z"></path></svg>`
|
|
543
273
|
}
|
|
544
274
|
});
|
|
545
275
|
};
|
|
546
|
-
|
|
547
|
-
|
|
548
|
-
|
|
549
|
-
|
|
550
|
-
|
|
276
|
+
const FaTrash = ({
|
|
277
|
+
className,
|
|
278
|
+
size,
|
|
279
|
+
color,
|
|
280
|
+
style
|
|
281
|
+
}) => {
|
|
551
282
|
return /*#__PURE__*/React.createElement("span", {
|
|
552
283
|
className: className,
|
|
553
|
-
style:
|
|
284
|
+
style: {
|
|
554
285
|
display: 'inline-flex',
|
|
555
286
|
alignItems: 'center',
|
|
556
287
|
justifyContent: 'center',
|
|
557
288
|
fontSize: size || '1em',
|
|
558
|
-
color: color || 'inherit'
|
|
559
|
-
|
|
289
|
+
color: color || 'inherit',
|
|
290
|
+
...style
|
|
291
|
+
},
|
|
560
292
|
dangerouslySetInnerHTML: {
|
|
561
|
-
__html:
|
|
293
|
+
__html: `<svg stroke="currentColor" fill="currentColor" stroke-width="0" viewBox="0 0 448 512" height="1em" width="1em" xmlns="http://www.w3.org/2000/svg"><path d="M432 32H312l-9.4-18.7A24 24 0 0 0 281.1 0H166.8a23.72 23.72 0 0 0-21.4 13.3L136 32H16A16 16 0 0 0 0 48v32a16 16 0 0 0 16 16h416a16 16 0 0 0 16-16V48a16 16 0 0 0-16-16zM53.2 467a48 48 0 0 0 47.9 45h245.8a48 48 0 0 0 47.9-45L416 128H32z"></path></svg>`
|
|
562
294
|
}
|
|
563
295
|
});
|
|
564
296
|
};
|
|
565
|
-
|
|
566
|
-
|
|
567
|
-
|
|
568
|
-
|
|
569
|
-
|
|
297
|
+
const FaVideo = ({
|
|
298
|
+
className,
|
|
299
|
+
size,
|
|
300
|
+
color,
|
|
301
|
+
style
|
|
302
|
+
}) => {
|
|
570
303
|
return /*#__PURE__*/React.createElement("span", {
|
|
571
304
|
className: className,
|
|
572
|
-
style:
|
|
305
|
+
style: {
|
|
573
306
|
display: 'inline-flex',
|
|
574
307
|
alignItems: 'center',
|
|
575
308
|
justifyContent: 'center',
|
|
576
309
|
fontSize: size || '1em',
|
|
577
|
-
color: color || 'inherit'
|
|
578
|
-
|
|
310
|
+
color: color || 'inherit',
|
|
311
|
+
...style
|
|
312
|
+
},
|
|
579
313
|
dangerouslySetInnerHTML: {
|
|
580
314
|
__html: '<svg stroke=\"currentColor\" fill=\"currentColor\" stroke-width=\"0\" viewBox=\"0 0 576 512\" height=\"1em\" width=\"1em\" xmlns=\"http://www.w3.org/2000/svg\"><path d=\"M0 128C0 92.7 28.7 64 64 64H320c35.3 0 64 28.7 64 64V384c0 35.3-28.7 64-64 64H64c-35.3 0-64-28.7-64-64V128zM559.1 99.8c10.4 5.6 16.9 16.3 16.9 28.2V384c0 11.9-6.5 22.6-16.9 28.2s-23 5-32.9-1.6l-96-64L416 337.1V174.9l14.2-9.5 96-64c9.9-6.6 22.6-7.1 32.9-1.6z\"></path></svg>'
|
|
581
315
|
}
|
|
582
316
|
});
|
|
583
317
|
};
|
|
584
318
|
|
|
319
|
+
// Basic ID generator
|
|
320
|
+
|
|
585
321
|
// DraftJS helper stubs
|
|
586
322
|
// Since we are removing specific DraftJS dependencies for this package,
|
|
587
323
|
// these serve as placeholders or basic HTML verifiers.
|
|
588
324
|
|
|
589
|
-
|
|
590
|
-
if (
|
|
325
|
+
const isValidDraftFormat = content => {
|
|
326
|
+
if (typeof content !== "object" || content === null) return false;
|
|
591
327
|
return !!(content.blocks && content.entityMap);
|
|
592
328
|
};
|
|
593
329
|
|
|
@@ -595,18 +331,16 @@ var isValidDraftFormat = function isValidDraftFormat(content) {
|
|
|
595
331
|
// Dealing with full DraftJS->HTML conversion without the library is complex.
|
|
596
332
|
// We assume for this package that if the legacy DraftJS format is passed,
|
|
597
333
|
// the user might need to handle it or we expect HTML primarily.
|
|
598
|
-
|
|
334
|
+
const draftBlocksToHTML = content => {
|
|
599
335
|
console.warn("draftBlocksToHTML: DraftJS object detected but full conversion is simplified in this package.");
|
|
600
336
|
// Return empty or try to extract text as a fallback
|
|
601
337
|
if (content && content.blocks) {
|
|
602
|
-
return content.blocks.map(
|
|
603
|
-
return "<p>".concat(b.text, "</p>");
|
|
604
|
-
}).join("");
|
|
338
|
+
return content.blocks.map(b => `<p>${b.text}</p>`).join("");
|
|
605
339
|
}
|
|
606
340
|
return "";
|
|
607
341
|
};
|
|
608
342
|
|
|
609
|
-
|
|
343
|
+
const Spinner = () => {
|
|
610
344
|
return /*#__PURE__*/React.createElement("div", {
|
|
611
345
|
className: "rte-spinner-container"
|
|
612
346
|
}, /*#__PURE__*/React.createElement("div", {
|
|
@@ -614,8 +348,9 @@ var Spinner = function Spinner() {
|
|
|
614
348
|
}));
|
|
615
349
|
};
|
|
616
350
|
|
|
617
|
-
|
|
618
|
-
|
|
351
|
+
const LabelComponent = ({
|
|
352
|
+
children
|
|
353
|
+
}) => {
|
|
619
354
|
if (!children) return null;
|
|
620
355
|
return /*#__PURE__*/React.createElement("label", {
|
|
621
356
|
className: "rte-label",
|
|
@@ -653,198 +388,133 @@ function styleInject(css, ref) {
|
|
|
653
388
|
}
|
|
654
389
|
}
|
|
655
390
|
|
|
656
|
-
var css_248z = ".rte-container{background-color:#fff;border:1px solid #e5e7eb;border-radius:12px;box-shadow:0 1px 3px rgba(0,0,0,.05);overflow:hidden;transition:all .2s cubic-bezier(.4,0,.2,1)}.rte-container:focus-within{border-color:#3b82f6;box-shadow:0 0 0 3px rgba(59,130,246,.1)}.rte-toolbar{align-items:center;background-color:#f9fafb;border-bottom:1px solid #f3f4f6;display:flex;flex-wrap:wrap;gap:4px;padding:8px}.rte-toolbar-button{align-items:center;background:transparent;border:none;border-radius:6px;color:#4b5563;cursor:pointer;display:flex;height:32px;justify-content:center;padding:0;transition:all .15s ease;width:32px}.rte-toolbar-button:hover{background-color:#f3f4f6;color:#111827}.rte-toolbar-button.active{background-color:#eff6ff;color:#2563eb}.rte-toolbar-button:disabled{cursor:not-allowed;opacity:.5}.rte-toolbar-button-danger:hover{background-color:#fef2f2!important;color:#dc2626!important}.rte-toolbar-select{background-color:#fff;border:1px solid #e5e7eb;border-radius:6px;color:#374151;cursor:pointer;font-size:14px;height:32px;outline:none;padding:0 8px;transition:border-color .15s ease}.rte-toolbar-select:hover{border-color:#d1d5db}.rte-toolbar-select:focus{border-color:#3b82f6}.rte-color-picker-label{align-items:center;border-radius:6px;cursor:pointer;display:flex;height:32px;justify-content:center;position:relative;transition:background-color .15s ease;width:32px}.rte-color-picker-label:hover{background-color:#f3f4f6}.rte-color-input{cursor:pointer;height:100%;inset:0;opacity:0;position:absolute;width:100%}.rte-content{color:#1f2937;font-family:inherit;font-size:16px;line-height:1.6;min-height:150px;outline:none;overflow-y:auto;padding:12px;word-break:break-word}.rte-content ul{list-style-type:disc;margin-left:1.5rem}.rte-content ol{list-style-type:decimal;margin-left:1.5rem}.rte-content img{border-radius:8px;display:block;height:auto;max-width:100%}.rte-content table{border-collapse:collapse;margin:16px 0;width:100%}.rte-content td,.rte-content th{border:1px solid #e5e7eb;min-width:40px;padding:12px;word-break:break-word}.video-container{border-radius:12px;box-shadow:0 4px 6px -1px rgba(0,0,0,.1);height:0;margin:16px 0;overflow:hidden;padding-bottom:56.25%;position:relative}.video-container iframe{height:100%;left:0;position:absolute;top:0;width:100%}.rte-modal-overlay{align-items:center;animation:rte-fade-in .2s ease-out;backdrop-filter:blur(4px);background-color:rgba(0,0,0,.5);display:flex;inset:0;justify-content:center;position:fixed;z-index:9999}.rte-modal{animation:rte-zoom-in .2s ease-out;background-color:#fff;border:1px solid #f3f4f6;border-radius:16px;box-shadow:0 20px 25px -5px rgba(0,0,0,.1),0 10px 10px -5px rgba(0,0,0,.04);display:flex;flex-direction:column;gap:16px;max-width:400px;padding:0;width:100%}.rte-modal-title{color:#111827;flex:1;font-size:18px;font-weight:600;margin:0;text-align:center}.rte-modal-header{align-items:center;border-bottom:1px solid #f3f4f6;display:flex;justify-content:space-between;padding:20px 24px 16px}.rte-form-group{display:flex;flex-direction:column;gap:8px;padding:16px 24px}.rte-label{color:#374151;font-size:14px;font-weight:600}.rte-input{border:1px solid #d1d5db;border-radius:8px;outline:none;padding:8px 12px;transition:all .15s ease;width:93%}.rte-input:focus{border-color:#3b82f6;box-shadow:0 0 0 3px rgba(59,130,246,.1)}.rte-modal-actions{border-top:1px solid #f3f4f6;display:flex;gap:12px;justify-content:flex-end;padding:16px 24px 20px}.rte-button{border:none;border-radius:8px;cursor:pointer;font-weight:500;padding:8px 16px;transition:all .15s ease}.rte-button-secondary{background-color:#f3f4f6;color:#4b5563}.rte-button-secondary:hover{background-color:#e5e7eb}.rte-button-primary{background-color:#2563eb;box-shadow:0 1px 2px rgba(0,0,0,.05);color:#fff}.rte-button-primary:hover{background-color:#1d4ed8}.rte-button-primary:disabled{cursor:not-allowed;opacity:.5}.rte-spinner-container{align-items:center;display:flex;justify-content:center;padding:16px}.rte-spinner{animation:rte-spin .8s linear infinite;border:3px solid #eff6ff;border-radius:50%;border-top-color:#3b82f6;height:32px;width:32px}@keyframes rte-spin{to{transform:rotate(1turn)}}@keyframes rte-fade-in{0%{opacity:0}to{opacity:1}}@keyframes rte-zoom-in{0%{opacity:0;transform:scale(.95)}to{opacity:1;transform:scale(1)}}.image-container{
|
|
391
|
+
var css_248z = ".rte-container{background-color:#fff;border:1px solid #e5e7eb;border-radius:12px;box-shadow:0 1px 3px rgba(0,0,0,.05);overflow:hidden;transition:all .2s cubic-bezier(.4,0,.2,1)}.rte-container:focus-within{border-color:#3b82f6;box-shadow:0 0 0 3px rgba(59,130,246,.1)}.rte-toolbar{align-items:center;background-color:#f9fafb;border-bottom:1px solid #f3f4f6;display:flex;flex-wrap:wrap;gap:4px;padding:8px}.rte-toolbar-button{align-items:center;background:transparent;border:none;border-radius:6px;color:#4b5563;cursor:pointer;display:flex;height:32px;justify-content:center;padding:0;transition:all .15s ease;width:32px}.rte-toolbar-button:hover{background-color:#f3f4f6;color:#111827}.rte-toolbar-button.active{background-color:#eff6ff;color:#2563eb}.rte-toolbar-button:disabled{cursor:not-allowed;opacity:.5}.rte-toolbar-button-danger:hover{background-color:#fef2f2!important;color:#dc2626!important}.rte-toolbar-select{background-color:#fff;border:1px solid #e5e7eb;border-radius:6px;color:#374151;cursor:pointer;font-size:14px;height:32px;outline:none;padding:0 8px;transition:border-color .15s ease}.rte-toolbar-select:hover{border-color:#d1d5db}.rte-toolbar-select:focus{border-color:#3b82f6}.rte-color-picker-label{align-items:center;border-radius:6px;cursor:pointer;display:flex;height:32px;justify-content:center;position:relative;transition:background-color .15s ease;width:32px}.rte-color-picker-label:hover{background-color:#f3f4f6}.rte-color-input{cursor:pointer;height:100%;inset:0;opacity:0;position:absolute;width:100%}.rte-content{color:#1f2937;font-family:inherit;font-size:16px;line-height:1.6;min-height:150px;outline:none;overflow-y:auto;padding:12px;word-break:break-word}.rte-content ul{list-style-type:disc;margin-left:1.5rem}.rte-content ol{list-style-type:decimal;margin-left:1.5rem}.rte-content img{border-radius:8px;display:block;height:auto;max-width:100%}.rte-content table{border-collapse:collapse;margin:16px 0;width:100%}.rte-content td,.rte-content th{border:1px solid #e5e7eb;min-width:40px;padding:12px;word-break:break-word}.video-container{border-radius:12px;box-shadow:0 4px 6px -1px rgba(0,0,0,.1);height:0;margin:16px 0;overflow:hidden;padding-bottom:56.25%;position:relative}.video-container iframe{height:100%;left:0;position:absolute;top:0;width:100%}.rte-modal-overlay{align-items:center;animation:rte-fade-in .2s ease-out;backdrop-filter:blur(4px);background-color:rgba(0,0,0,.5);display:flex;inset:0;justify-content:center;position:fixed;z-index:9999}.rte-modal{animation:rte-zoom-in .2s ease-out;background-color:#fff;border:1px solid #f3f4f6;border-radius:16px;box-shadow:0 20px 25px -5px rgba(0,0,0,.1),0 10px 10px -5px rgba(0,0,0,.04);display:flex;flex-direction:column;gap:16px;max-width:400px;padding:0;width:100%}.rte-modal-title{color:#111827;flex:1;font-size:18px;font-weight:600;margin:0;text-align:center}.rte-modal-header{align-items:center;border-bottom:1px solid #f3f4f6;display:flex;justify-content:space-between;padding:20px 24px 16px}.rte-form-group{display:flex;flex-direction:column;gap:8px;padding:16px 24px}.rte-label{color:#374151;font-size:14px;font-weight:600}.rte-input{border:1px solid #d1d5db;border-radius:8px;outline:none;padding:8px 12px;transition:all .15s ease;width:93%}.rte-input:focus{border-color:#3b82f6;box-shadow:0 0 0 3px rgba(59,130,246,.1)}.rte-modal-actions{border-top:1px solid #f3f4f6;display:flex;gap:12px;justify-content:flex-end;padding:16px 24px 20px}.rte-button{border:none;border-radius:8px;cursor:pointer;font-weight:500;padding:8px 16px;transition:all .15s ease}.rte-button-secondary{background-color:#f3f4f6;color:#4b5563}.rte-button-secondary:hover{background-color:#e5e7eb}.rte-button-primary{background-color:#2563eb;box-shadow:0 1px 2px rgba(0,0,0,.05);color:#fff}.rte-button-primary:hover{background-color:#1d4ed8}.rte-button-primary:disabled{cursor:not-allowed;opacity:.5}.rte-spinner-container{align-items:center;display:flex;justify-content:center;padding:16px}.rte-spinner{animation:rte-spin .8s linear infinite;border:3px solid #eff6ff;border-radius:50%;border-top-color:#3b82f6;height:32px;width:32px}@keyframes rte-spin{to{transform:rotate(1turn)}}@keyframes rte-fade-in{0%{opacity:0}to{opacity:1}}@keyframes rte-zoom-in{0%{opacity:0;transform:scale(.95)}to{opacity:1;transform:scale(1)}}.image-container{display:inline-block;line-height:0;margin:15px;max-width:100%;position:relative}.image-container.image-align-center{display:block;margin:24px auto;text-align:center}.image-container.image-align-left,.image-container.image-align-right{display:block}.image-container.image-align-left,.image-container.image-align-right{margin:15px 0}.image-container.image-align-left img{margin-left:0!important;margin-right:auto!important}.image-container.image-align-center img{margin-left:auto!important;margin-right:auto!important}.image-container.image-align-right img{margin-left:auto!important;margin-right:0!important}.image-container img{border-radius:12px;display:block;height:auto;margin:0;max-width:100%;width:auto}.image-container.image-small img{width:50%!important}.image-delete-button{align-items:center;background:#ef4444;border:3px solid #fff;border-radius:9999px;box-shadow:0 4px 6px -1px rgba(0,0,0,.1),0 2px 4px -1px rgba(0,0,0,.06);color:#fff;cursor:pointer;display:flex;font-size:18px;font-weight:700;height:26px;justify-content:center;line-height:1;padding:0;position:absolute;right:0;top:0;transform:translate(50%,-50%);transition:all .2s cubic-bezier(.4,0,.2,1);width:26px;z-index:50}.image-delete-button:hover{background:#b91c1c;box-shadow:0 10px 15px -3px rgba(0,0,0,.1);transform:translate(50%,-50%) scale(1.1)}.rte-table-delete-btn,.rte-table-delete-hover{align-items:center;display:flex;justify-content:center}.rte-table-delete-btn{background:#fff;border:1px solid #ef4444;border-radius:6px;box-shadow:0 4px 6px -1px rgba(0,0,0,.1),0 2px 4px -1px rgba(0,0,0,.06);color:#ef4444;cursor:pointer;height:28px;padding:0;transition:all .2s ease;width:28px}.rte-table-delete-btn:hover{background:#ef4444;color:#fff;transform:scale(1.1)}.rte-table-delete-btn:active{transform:scale(.95)}.rte-image-toolbar{background:#fff!important;border:1px solid #e5e7eb!important;border-radius:8px!important;box-shadow:0 4px 6px -1px rgba(0,0,0,.1),0 2px 4px -1px rgba(0,0,0,.06)!important;display:flex;gap:4px!important;padding:4px!important;pointer-events:auto!important}.rte-image-toolbar button{align-items:center;background:transparent;border:none;border-radius:4px;color:#4b5563;cursor:pointer;display:flex;font-size:11px;font-weight:600;height:28px;justify-content:center;min-width:32px;padding:0 4px;transition:all .15s ease}.rte-image-toolbar button:hover{background-color:#f3f4f6;color:#111827}.rte-image-toolbar button.danger{color:#ef4444!important}.rte-image-toolbar button.danger:hover{background-color:#fef2f2!important}.image-container:after{clear:both;content:\"\";display:table}.rte-footer{background-color:#fcfcfd;border-top:1px solid #f3f4f6;display:flex;justify-content:flex-end;padding:6px 16px;user-select:none}.rte-footer-content{align-items:center;color:#9ca3af;display:flex;font-size:11px;gap:10px;letter-spacing:.025em}.rte-footer-separator{color:#e5e7eb;font-size:14px;line-height:1}.rte-footer-item b{color:#6b7280;font-weight:600}";
|
|
657
392
|
styleInject(css_248z);
|
|
658
393
|
|
|
659
394
|
// Helper functions for HTML escaping
|
|
660
|
-
|
|
395
|
+
const escapeHtml = str => {
|
|
661
396
|
if (!str) return "";
|
|
662
397
|
return String(str).replace(/&/g, "&").replace(/</g, "<").replace(/>/g, ">").replace(/\"/g, """).replace(/'/g, "'");
|
|
663
398
|
};
|
|
664
|
-
|
|
665
|
-
return escapeHtml(str).replace(/"/g, """);
|
|
666
|
-
};
|
|
399
|
+
const escapeAttr = str => escapeHtml(str).replace(/"/g, """);
|
|
667
400
|
|
|
668
401
|
// URL detection regex
|
|
669
|
-
|
|
670
|
-
function RichTextEditor(
|
|
671
|
-
|
|
672
|
-
|
|
673
|
-
|
|
674
|
-
|
|
675
|
-
|
|
676
|
-
|
|
677
|
-
|
|
678
|
-
|
|
679
|
-
|
|
680
|
-
|
|
681
|
-
|
|
682
|
-
|
|
683
|
-
|
|
684
|
-
|
|
685
|
-
|
|
686
|
-
minHeight = _ref.minHeight,
|
|
687
|
-
maxHeight = _ref.maxHeight,
|
|
688
|
-
onImageUpload = _ref.onImageUpload;
|
|
402
|
+
const URL_REGEX = /(https?:\/\/[^\s]+)/g;
|
|
403
|
+
function RichTextEditor({
|
|
404
|
+
onChange,
|
|
405
|
+
showEditButton,
|
|
406
|
+
onBlur,
|
|
407
|
+
disabled = false,
|
|
408
|
+
editable: initialEditable = false,
|
|
409
|
+
value,
|
|
410
|
+
isLoading,
|
|
411
|
+
isList = false,
|
|
412
|
+
label,
|
|
413
|
+
showBorder = true,
|
|
414
|
+
paddingLeft,
|
|
415
|
+
minHeight,
|
|
416
|
+
maxHeight,
|
|
417
|
+
onImageUpload
|
|
418
|
+
}) {
|
|
689
419
|
if (isLoading) {
|
|
690
420
|
return /*#__PURE__*/React.createElement(Spinner, null);
|
|
691
421
|
}
|
|
692
|
-
|
|
693
|
-
|
|
694
|
-
|
|
695
|
-
|
|
696
|
-
|
|
697
|
-
|
|
698
|
-
|
|
699
|
-
|
|
700
|
-
|
|
701
|
-
|
|
702
|
-
|
|
703
|
-
|
|
704
|
-
|
|
705
|
-
linkUrl = _useState6[0],
|
|
706
|
-
setLinkUrl = _useState6[1];
|
|
707
|
-
var _useState7 = useState(""),
|
|
708
|
-
_useState8 = _slicedToArray(_useState7, 2),
|
|
709
|
-
linkText = _useState8[0],
|
|
710
|
-
setLinkText = _useState8[1];
|
|
711
|
-
var selectionRangeRef = useRef(null);
|
|
712
|
-
var _useState9 = useState(defaultEditable),
|
|
713
|
-
_useState0 = _slicedToArray(_useState9, 2),
|
|
714
|
-
editable = _useState0[0],
|
|
715
|
-
setEditable = _useState0[1];
|
|
422
|
+
const editorRef = useRef(null);
|
|
423
|
+
const fileInputRef = useRef(null);
|
|
424
|
+
const scrollTopRef = useRef(0);
|
|
425
|
+
const [html, setHtml] = useState("");
|
|
426
|
+
const [linkModalOpen, setLinkModalOpen] = useState(false);
|
|
427
|
+
const [linkUrl, setLinkUrl] = useState("");
|
|
428
|
+
const [linkText, setLinkText] = useState("");
|
|
429
|
+
const selectionRangeRef = useRef(null);
|
|
430
|
+
const [editable, setEditable] = useState(initialEditable);
|
|
431
|
+
const lastSynchronizedHtmlRef = useRef("");
|
|
432
|
+
useEffect(() => {
|
|
433
|
+
setEditable(initialEditable);
|
|
434
|
+
}, [initialEditable]);
|
|
716
435
|
|
|
717
436
|
// NEW: Track current list type for dropdown
|
|
718
|
-
|
|
719
|
-
_useState10 = _slicedToArray(_useState1, 2),
|
|
720
|
-
currentListType = _useState10[0],
|
|
721
|
-
setCurrentListType = _useState10[1];
|
|
437
|
+
const [currentListType, setCurrentListType] = useState(null);
|
|
722
438
|
|
|
723
439
|
// NEW: Track active styles for toolbar buttons
|
|
724
|
-
|
|
725
|
-
|
|
726
|
-
|
|
727
|
-
setIsBold = _useState12[1];
|
|
728
|
-
var _useState13 = useState(false),
|
|
729
|
-
_useState14 = _slicedToArray(_useState13, 2),
|
|
730
|
-
isItalic = _useState14[0],
|
|
731
|
-
setIsItalic = _useState14[1];
|
|
732
|
-
var _useState15 = useState(false),
|
|
733
|
-
_useState16 = _slicedToArray(_useState15, 2),
|
|
734
|
-
isUnderline = _useState16[0],
|
|
735
|
-
setIsUnderline = _useState16[1];
|
|
440
|
+
const [isBold, setIsBold] = useState(false);
|
|
441
|
+
const [isItalic, setIsItalic] = useState(false);
|
|
442
|
+
const [isUnderline, setIsUnderline] = useState(false);
|
|
736
443
|
|
|
737
444
|
// NEW: Track current font size
|
|
738
|
-
|
|
739
|
-
_useState18 = _slicedToArray(_useState17, 2),
|
|
740
|
-
currentFontSize = _useState18[0],
|
|
741
|
-
setCurrentFontSize = _useState18[1];
|
|
445
|
+
const [currentFontSize, setCurrentFontSize] = useState("16");
|
|
742
446
|
|
|
743
447
|
// NEW: Track current line height
|
|
744
|
-
|
|
745
|
-
|
|
746
|
-
|
|
747
|
-
|
|
748
|
-
|
|
749
|
-
|
|
750
|
-
|
|
751
|
-
|
|
752
|
-
|
|
753
|
-
|
|
754
|
-
|
|
755
|
-
|
|
756
|
-
|
|
757
|
-
|
|
758
|
-
|
|
759
|
-
|
|
760
|
-
|
|
761
|
-
|
|
762
|
-
|
|
763
|
-
|
|
764
|
-
|
|
765
|
-
|
|
766
|
-
|
|
767
|
-
|
|
768
|
-
|
|
769
|
-
|
|
770
|
-
|
|
771
|
-
|
|
772
|
-
|
|
773
|
-
|
|
774
|
-
|
|
775
|
-
setVideoUrl = _useState34[1];
|
|
776
|
-
var _useState35 = useState(false),
|
|
777
|
-
_useState36 = _slicedToArray(_useState35, 2),
|
|
778
|
-
tableModalOpen = _useState36[0],
|
|
779
|
-
setTableModalOpen = _useState36[1];
|
|
780
|
-
var _useState37 = useState(null),
|
|
781
|
-
_useState38 = _slicedToArray(_useState37, 2);
|
|
782
|
-
_useState38[0];
|
|
783
|
-
var setHoveredTable = _useState38[1];
|
|
784
|
-
var _useState39 = useState(3),
|
|
785
|
-
_useState40 = _slicedToArray(_useState39, 2),
|
|
786
|
-
tableRows = _useState40[0],
|
|
787
|
-
setTableRows = _useState40[1];
|
|
788
|
-
var _useState41 = useState(3),
|
|
789
|
-
_useState42 = _slicedToArray(_useState41, 2),
|
|
790
|
-
tableCols = _useState42[0],
|
|
791
|
-
setTableCols = _useState42[1];
|
|
792
|
-
var _useState43 = useState(0),
|
|
793
|
-
_useState44 = _slicedToArray(_useState43, 2);
|
|
794
|
-
_useState44[0];
|
|
795
|
-
var setSelectionVersion = _useState44[1];
|
|
796
|
-
var _useState45 = useState(null),
|
|
797
|
-
_useState46 = _slicedToArray(_useState45, 2),
|
|
798
|
-
selectedImage = _useState46[0],
|
|
799
|
-
setSelectedImage = _useState46[1];
|
|
800
|
-
var _useState47 = useState(null),
|
|
801
|
-
_useState48 = _slicedToArray(_useState47, 2);
|
|
802
|
-
_useState48[0];
|
|
803
|
-
var setResizeData = _useState48[1];
|
|
804
|
-
var openImageModal = function openImageModal(url) {
|
|
448
|
+
const [currentLineHeight, setCurrentLineHeight] = useState("");
|
|
449
|
+
const [activeAlign, setActiveAlign] = useState(null);
|
|
450
|
+
const [imageModalOpen, setImageModalOpen] = useState(false);
|
|
451
|
+
const [selectedImageUrl, setSelectedImageUrl] = useState("");
|
|
452
|
+
const [zoomLevel, setZoomLevel] = useState(1);
|
|
453
|
+
const [isUploading, setIsUploading] = useState(false);
|
|
454
|
+
const [videoModalOpen, setVideoModalOpen] = useState(false);
|
|
455
|
+
const [videoUrl, setVideoUrl] = useState("");
|
|
456
|
+
const [tableModalOpen, setTableModalOpen] = useState(false);
|
|
457
|
+
const [hoveredTable, setHoveredTable] = useState(null);
|
|
458
|
+
const [tableRows, setTableRows] = useState(3);
|
|
459
|
+
const [tableCols, setTableCols] = useState(3);
|
|
460
|
+
const [selectionVersion, setSelectionVersion] = useState(0);
|
|
461
|
+
const [selectedImage, setSelectedImage] = useState(null);
|
|
462
|
+
const [metrics, setMetrics] = useState({
|
|
463
|
+
words: 0,
|
|
464
|
+
chars: 0
|
|
465
|
+
});
|
|
466
|
+
const updateMetrics = useCallback(() => {
|
|
467
|
+
if (!editorRef.current) return;
|
|
468
|
+
// Calculate metrics immediately but outside of render path
|
|
469
|
+
const text = editorRef.current.innerText || "";
|
|
470
|
+
const cleanText = text.replace(/[\n\r]/g, ' ').trim();
|
|
471
|
+
const words = cleanText ? cleanText.split(/\s+/).length : 0;
|
|
472
|
+
const chars = text.length;
|
|
473
|
+
setMetrics({
|
|
474
|
+
words,
|
|
475
|
+
chars
|
|
476
|
+
});
|
|
477
|
+
}, []);
|
|
478
|
+
const openImageModal = url => {
|
|
805
479
|
if (editorRef.current) {
|
|
806
480
|
scrollTopRef.current = editorRef.current.scrollTop;
|
|
807
481
|
}
|
|
808
482
|
setSelectedImageUrl(url);
|
|
809
483
|
setImageModalOpen(true);
|
|
810
484
|
};
|
|
811
|
-
|
|
485
|
+
const closeImageModal = () => {
|
|
812
486
|
setImageModalOpen(false);
|
|
813
487
|
setSelectedImageUrl("");
|
|
814
488
|
setZoomLevel(1);
|
|
815
489
|
};
|
|
816
|
-
|
|
490
|
+
const saveSelection = () => {
|
|
817
491
|
if (typeof window === "undefined") return;
|
|
818
|
-
|
|
492
|
+
const sel = window.getSelection();
|
|
819
493
|
if (sel && sel.rangeCount > 0) {
|
|
820
494
|
selectionRangeRef.current = sel.getRangeAt(0).cloneRange();
|
|
821
495
|
}
|
|
822
496
|
};
|
|
823
|
-
|
|
824
|
-
setZoomLevel(
|
|
825
|
-
return prevZoom + 0.1;
|
|
826
|
-
});
|
|
497
|
+
const handleZoomIn = () => {
|
|
498
|
+
setZoomLevel(prevZoom => prevZoom + 0.1);
|
|
827
499
|
};
|
|
828
|
-
|
|
829
|
-
setZoomLevel(
|
|
830
|
-
return Math.max(0.1, prevZoom - 0.1);
|
|
831
|
-
});
|
|
500
|
+
const handleZoomOut = () => {
|
|
501
|
+
setZoomLevel(prevZoom => Math.max(0.1, prevZoom - 0.1));
|
|
832
502
|
};
|
|
833
503
|
|
|
834
504
|
// Effect to restore scroll position after modal closes
|
|
835
|
-
useEffect(
|
|
505
|
+
useEffect(() => {
|
|
836
506
|
if (!imageModalOpen && editorRef.current) {
|
|
837
507
|
editorRef.current.scrollTop = scrollTopRef.current;
|
|
838
508
|
}
|
|
839
509
|
}, [imageModalOpen]);
|
|
840
|
-
useEffect(
|
|
510
|
+
useEffect(() => {
|
|
841
511
|
if (!imageModalOpen) return;
|
|
842
|
-
|
|
512
|
+
const handleKeyDown = e => {
|
|
843
513
|
if (e.key === 'Escape') {
|
|
844
514
|
closeImageModal();
|
|
845
515
|
}
|
|
846
516
|
};
|
|
847
|
-
|
|
517
|
+
const handleWheel = e => {
|
|
848
518
|
if (e.ctrlKey) {
|
|
849
519
|
e.preventDefault();
|
|
850
520
|
if (e.deltaY < 0) {
|
|
@@ -858,127 +528,99 @@ function RichTextEditor(_ref) {
|
|
|
858
528
|
window.addEventListener('wheel', handleWheel, {
|
|
859
529
|
passive: false
|
|
860
530
|
});
|
|
861
|
-
return
|
|
531
|
+
return () => {
|
|
862
532
|
document.removeEventListener('keydown', handleKeyDown);
|
|
863
533
|
window.removeEventListener('wheel', handleWheel);
|
|
864
534
|
};
|
|
865
535
|
}, [imageModalOpen]);
|
|
866
|
-
useEffect(
|
|
867
|
-
|
|
536
|
+
useEffect(() => {
|
|
537
|
+
const handleClick = e => {
|
|
868
538
|
// Trigger selection update for toolbar reactivity
|
|
869
|
-
setSelectionVersion(
|
|
870
|
-
|
|
871
|
-
});
|
|
872
|
-
var deleteBtn = e.target.closest('button[title="Remove image"]');
|
|
539
|
+
setSelectionVersion(v => v + 1);
|
|
540
|
+
const deleteBtn = e.target.closest('button[title="Remove image"]');
|
|
873
541
|
if (deleteBtn && editable) {
|
|
874
542
|
e.preventDefault();
|
|
875
543
|
e.stopPropagation();
|
|
876
|
-
|
|
544
|
+
const wrapper = deleteBtn.closest('.image-container');
|
|
877
545
|
if (wrapper && wrapper.parentNode) {
|
|
878
546
|
wrapper.parentNode.removeChild(wrapper);
|
|
879
|
-
triggerChange();
|
|
547
|
+
triggerChange && triggerChange();
|
|
880
548
|
}
|
|
881
549
|
}
|
|
882
550
|
};
|
|
883
|
-
|
|
551
|
+
const editor = editorRef.current;
|
|
884
552
|
if (editor) {
|
|
885
553
|
editor.addEventListener('click', handleClick);
|
|
886
|
-
return
|
|
554
|
+
return () => {
|
|
887
555
|
editor.removeEventListener('click', handleClick);
|
|
888
556
|
};
|
|
889
557
|
}
|
|
890
|
-
|
|
891
|
-
|
|
892
|
-
|
|
893
|
-
|
|
894
|
-
|
|
895
|
-
});
|
|
558
|
+
// Removed dependency on editable to minimize listener churn
|
|
559
|
+
}, []);
|
|
560
|
+
useEffect(() => {
|
|
561
|
+
if (editorRef.current && value && value !== lastSynchronizedHtmlRef.current) {
|
|
562
|
+
requestAnimationFrame(() => processExistingImages(editorRef.current));
|
|
896
563
|
}
|
|
897
564
|
}, [value]);
|
|
898
565
|
|
|
899
566
|
// Runs whenever editable changes (toggles delete icon visibility)
|
|
900
|
-
useEffect(
|
|
567
|
+
useEffect(() => {
|
|
901
568
|
processExistingImages(editorRef.current);
|
|
902
|
-
}, [
|
|
903
|
-
useEffect(
|
|
904
|
-
// Only update if value is
|
|
905
|
-
if (value) {
|
|
569
|
+
}, [editable]);
|
|
570
|
+
useEffect(() => {
|
|
571
|
+
// Only update if value is different from our last known synced state
|
|
572
|
+
if (value && value !== lastSynchronizedHtmlRef.current) {
|
|
906
573
|
try {
|
|
907
|
-
|
|
908
|
-
|
|
909
|
-
|
|
910
|
-
|
|
911
|
-
|
|
912
|
-
editorRef.current.innerHTML = htmlContent;
|
|
913
|
-
}
|
|
574
|
+
let newContent = "";
|
|
575
|
+
|
|
576
|
+
// Check if value is a Draft.js content state
|
|
577
|
+
if (isValidDraftFormat(value)) {
|
|
578
|
+
newContent = draftBlocksToHTML(value);
|
|
914
579
|
} else if (typeof value === 'string') {
|
|
915
|
-
//
|
|
916
|
-
|
|
917
|
-
|
|
918
|
-
|
|
919
|
-
|
|
580
|
+
// If value is already what we have in HTML state, skip unescaping
|
|
581
|
+
if (value === html) {
|
|
582
|
+
lastSynchronizedHtmlRef.current = value;
|
|
583
|
+
return;
|
|
584
|
+
}
|
|
585
|
+
newContent = unescapeHtml(value);
|
|
586
|
+
}
|
|
587
|
+
if (newContent && newContent !== html) {
|
|
588
|
+
lastSynchronizedHtmlRef.current = value;
|
|
589
|
+
setHtml(newContent);
|
|
590
|
+
if (editorRef.current && editorRef.current.innerHTML !== newContent) {
|
|
591
|
+
editorRef.current.innerHTML = newContent;
|
|
920
592
|
}
|
|
593
|
+
updateMetrics();
|
|
921
594
|
}
|
|
922
595
|
} catch (e) {
|
|
923
596
|
console.error('Error processing editor content:', e);
|
|
924
|
-
// Fallback to raw value if parsing fails
|
|
925
|
-
var _unescapedValue = typeof value === 'string' ? unescapeHtml(value) : value;
|
|
926
|
-
setHtml(_unescapedValue);
|
|
927
|
-
if (editorRef.current) {
|
|
928
|
-
editorRef.current.innerHTML = _unescapedValue || '';
|
|
929
|
-
}
|
|
930
597
|
}
|
|
931
|
-
} else {
|
|
598
|
+
} else if (!value && html) {
|
|
932
599
|
setHtml('');
|
|
600
|
+
lastSynchronizedHtmlRef.current = "";
|
|
933
601
|
if (editorRef.current) {
|
|
934
602
|
editorRef.current.innerHTML = '';
|
|
603
|
+
updateMetrics();
|
|
935
604
|
}
|
|
936
605
|
}
|
|
937
|
-
}, [
|
|
606
|
+
}, [value, initialEditable, updateMetrics]);
|
|
938
607
|
|
|
939
|
-
// Call onChange whenever html state updates
|
|
940
|
-
useEffect(function () {
|
|
941
|
-
onChange && onChange(html);
|
|
942
|
-
}, [html, onChange]);
|
|
943
608
|
// Trigger change manually
|
|
944
|
-
|
|
945
|
-
|
|
609
|
+
const triggerChange = useCallback(() => {
|
|
610
|
+
const next = getCleanHtml();
|
|
946
611
|
setHtml(next);
|
|
947
|
-
|
|
948
|
-
|
|
949
|
-
|
|
950
|
-
var detectListType = function detectListType() {
|
|
951
|
-
var sel = window.getSelection();
|
|
952
|
-
if (!sel || !sel.rangeCount) {
|
|
953
|
-
setCurrentListType(null);
|
|
954
|
-
return;
|
|
955
|
-
}
|
|
956
|
-
var node = sel.anchorNode;
|
|
957
|
-
while (node && node !== editorRef.current) {
|
|
958
|
-
if (node.nodeName === "OL") {
|
|
959
|
-
setCurrentListType("ordered");
|
|
960
|
-
return;
|
|
961
|
-
}
|
|
962
|
-
if (node.nodeName === "UL") {
|
|
963
|
-
setCurrentListType("unordered");
|
|
964
|
-
return;
|
|
965
|
-
}
|
|
966
|
-
node = node.parentNode;
|
|
967
|
-
}
|
|
968
|
-
setCurrentListType(null);
|
|
969
|
-
};
|
|
612
|
+
lastSynchronizedHtmlRef.current = next;
|
|
613
|
+
onChange && onChange(next);
|
|
614
|
+
}, [onChange]);
|
|
970
615
|
|
|
971
616
|
// Helper to walk up DOM to find style tags or CSS style:
|
|
972
|
-
|
|
973
|
-
for (var _len = arguments.length, tagNames = new Array(_len > 1 ? _len - 1 : 0), _key = 1; _key < _len; _key++) {
|
|
974
|
-
tagNames[_key - 1] = arguments[_key];
|
|
975
|
-
}
|
|
617
|
+
const isParentStyle = (node, ...tagNames) => {
|
|
976
618
|
while (node && node !== editorRef.current) {
|
|
977
619
|
if (node.nodeType === 1 && tagNames.includes(node.tagName)) return true;
|
|
978
620
|
|
|
979
621
|
// Also check inline style for bold and italic:
|
|
980
622
|
if (node.nodeType === 1 && node.style) {
|
|
981
|
-
|
|
623
|
+
const style = node.style;
|
|
982
624
|
if (tagNames.includes("bold") && (style.fontWeight === "bold" || Number(style.fontWeight) >= 600)) return true;
|
|
983
625
|
if (tagNames.includes("italic") && style.fontStyle === "italic") return true;
|
|
984
626
|
if (tagNames.includes("underline") && style.textDecoration.includes("underline")) return true;
|
|
@@ -996,100 +638,92 @@ function RichTextEditor(_ref) {
|
|
|
996
638
|
return false;
|
|
997
639
|
};
|
|
998
640
|
|
|
999
|
-
// Update style states based on selection or cursor position
|
|
1000
|
-
var updateStyleStates = function updateStyleStates() {
|
|
1001
|
-
var sel = window.getSelection();
|
|
1002
|
-
if (!sel || !sel.rangeCount) {
|
|
1003
|
-
setIsBold(false);
|
|
1004
|
-
setIsItalic(false);
|
|
1005
|
-
setIsUnderline(false);
|
|
1006
|
-
setFontColor("#000000"); // default
|
|
1007
|
-
return;
|
|
1008
|
-
}
|
|
1009
|
-
var container = sel.anchorNode.nodeType === 3 ? sel.anchorNode.parentNode : sel.anchorNode;
|
|
1010
|
-
var computedAlign = window.getComputedStyle(container).textAlign;
|
|
1011
|
-
setActiveAlign(computedAlign);
|
|
1012
|
-
var range = sel.getRangeAt(0);
|
|
1013
|
-
if (range.collapsed) {
|
|
1014
|
-
// Cursor only, check parent nodes
|
|
1015
|
-
var _container = sel.anchorNode.nodeType === 3 ? sel.anchorNode.parentNode : sel.anchorNode;
|
|
1016
|
-
window.getComputedStyle(_container);
|
|
1017
|
-
setIsBold(isParentStyle(_container, "B", "STRONG", "bold"));
|
|
1018
|
-
setIsItalic(isParentStyle(_container, "I", "EM", "italic"));
|
|
1019
|
-
setIsUnderline(isParentStyle(_container, "U", "underline"));
|
|
1020
|
-
|
|
1021
|
-
// ✅ Get computed color from container
|
|
1022
|
-
var computedColor = window.getComputedStyle(_container).color;
|
|
1023
|
-
setFontColor(rgbToHex(computedColor));
|
|
1024
|
-
} else {
|
|
1025
|
-
// Text selected, use execCommand state
|
|
1026
|
-
setIsBold(document.queryCommandState("bold"));
|
|
1027
|
-
setIsItalic(document.queryCommandState("italic"));
|
|
1028
|
-
setIsUnderline(document.queryCommandState("underline"));
|
|
1029
|
-
|
|
1030
|
-
// ✅ For selection, get color from selection's start container
|
|
1031
|
-
var _container2 = sel.anchorNode.nodeType === 3 ? sel.anchorNode.parentNode : sel.anchorNode;
|
|
1032
|
-
var _computedColor = window.getComputedStyle(_container2).color;
|
|
1033
|
-
setFontColor(rgbToHex(_computedColor));
|
|
1034
|
-
}
|
|
1035
|
-
};
|
|
1036
|
-
|
|
1037
641
|
// Helper to convert rgb() to hex
|
|
1038
642
|
function rgbToHex(rgb) {
|
|
1039
|
-
|
|
643
|
+
const result = rgb.match(/\d+/g);
|
|
1040
644
|
if (!result) return "#000000";
|
|
1041
|
-
return "#" + result.slice(0, 3).map(
|
|
1042
|
-
|
|
645
|
+
return "#" + result.slice(0, 3).map(x => {
|
|
646
|
+
const hex = parseInt(x, 10).toString(16);
|
|
1043
647
|
return hex.length === 1 ? "0" + hex : hex;
|
|
1044
648
|
}).join("");
|
|
1045
649
|
}
|
|
1046
650
|
|
|
1047
|
-
// Listen for selection changes globally to update styles and list type
|
|
1048
|
-
useEffect(
|
|
1049
|
-
|
|
1050
|
-
|
|
1051
|
-
|
|
1052
|
-
|
|
1053
|
-
if (!
|
|
1054
|
-
|
|
1055
|
-
|
|
651
|
+
// Listen for selection changes globally to update styles and list type in one pass
|
|
652
|
+
useEffect(() => {
|
|
653
|
+
const handleGlobalSelectionSync = () => {
|
|
654
|
+
var _editorRef$current;
|
|
655
|
+
// Only sync if the editor has focus
|
|
656
|
+
const sel = window.getSelection();
|
|
657
|
+
if (!sel || !sel.rangeCount || !((_editorRef$current = editorRef.current) !== null && _editorRef$current !== void 0 && _editorRef$current.contains(sel.anchorNode))) {
|
|
658
|
+
return;
|
|
659
|
+
}
|
|
660
|
+
|
|
661
|
+
// 1. Detect List Type
|
|
662
|
+
let node = sel.anchorNode;
|
|
663
|
+
let listFound = null;
|
|
664
|
+
while (node && node !== editorRef.current) {
|
|
665
|
+
if (node.nodeName === "OL") {
|
|
666
|
+
listFound = "ordered";
|
|
667
|
+
break;
|
|
668
|
+
}
|
|
669
|
+
if (node.nodeName === "UL") {
|
|
670
|
+
listFound = "unordered";
|
|
671
|
+
break;
|
|
672
|
+
}
|
|
673
|
+
node = node.parentNode;
|
|
674
|
+
}
|
|
675
|
+
setCurrentListType(listFound);
|
|
676
|
+
|
|
677
|
+
// 2. Update Style States
|
|
678
|
+
const container = sel.anchorNode.nodeType === 3 ? sel.anchorNode.parentNode : sel.anchorNode;
|
|
679
|
+
const computedAlign = window.getComputedStyle(container).textAlign;
|
|
680
|
+
setActiveAlign(computedAlign);
|
|
681
|
+
const range = sel.getRangeAt(0);
|
|
682
|
+
if (range.collapsed) {
|
|
683
|
+
setIsBold(isParentStyle(container, "B", "STRONG", "bold"));
|
|
684
|
+
setIsItalic(isParentStyle(container, "I", "EM", "italic"));
|
|
685
|
+
setIsUnderline(isParentStyle(container, "U", "underline"));
|
|
686
|
+
const computedColor = window.getComputedStyle(container).color;
|
|
687
|
+
setFontColor(rgbToHex(computedColor));
|
|
688
|
+
} else {
|
|
689
|
+
setIsBold(document.queryCommandState("bold"));
|
|
690
|
+
setIsItalic(document.queryCommandState("italic"));
|
|
691
|
+
setIsUnderline(document.queryCommandState("underline"));
|
|
692
|
+
const computedColor = window.getComputedStyle(container).color;
|
|
693
|
+
setFontColor(rgbToHex(computedColor));
|
|
694
|
+
}
|
|
695
|
+
|
|
696
|
+
// 3. Current Font Size
|
|
697
|
+
const element = range.startContainer.parentElement.closest('[style*="font-size"]');
|
|
1056
698
|
if (element) {
|
|
1057
|
-
|
|
1058
|
-
|
|
699
|
+
const fontSize = window.getComputedStyle(element).fontSize;
|
|
700
|
+
const sizeValue = fontSize ? parseInt(fontSize) : 16;
|
|
1059
701
|
setCurrentFontSize(sizeValue.toString());
|
|
1060
702
|
} else {
|
|
1061
|
-
setCurrentFontSize("16");
|
|
703
|
+
setCurrentFontSize("16");
|
|
1062
704
|
}
|
|
1063
705
|
};
|
|
1064
|
-
document.addEventListener(
|
|
1065
|
-
return
|
|
1066
|
-
document.removeEventListener("selectionchange",
|
|
1067
|
-
document.removeEventListener("selectionchange", updateStyleStates);
|
|
1068
|
-
document.removeEventListener('selectionchange', handleSelectionChange);
|
|
706
|
+
document.addEventListener("selectionchange", handleGlobalSelectionSync);
|
|
707
|
+
return () => {
|
|
708
|
+
document.removeEventListener("selectionchange", handleGlobalSelectionSync);
|
|
1069
709
|
};
|
|
1070
710
|
}, []);
|
|
1071
|
-
|
|
1072
|
-
|
|
1073
|
-
};
|
|
1074
|
-
var exec = function exec(command) {
|
|
1075
|
-
var value = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : null;
|
|
711
|
+
const focus = () => editorRef.current && editorRef.current.focus();
|
|
712
|
+
const exec = (command, value = null) => {
|
|
1076
713
|
document.execCommand(command, false, value);
|
|
1077
714
|
triggerChange();
|
|
1078
715
|
focus();
|
|
1079
716
|
};
|
|
1080
|
-
|
|
1081
|
-
|
|
1082
|
-
fontColor = _useState50[0],
|
|
1083
|
-
setFontColor = _useState50[1];
|
|
1084
|
-
var handleColorChange = function handleColorChange(color) {
|
|
717
|
+
const [fontColor, setFontColor] = useState("#000000");
|
|
718
|
+
const handleColorChange = color => {
|
|
1085
719
|
setFontColor(color);
|
|
1086
720
|
exec("foreColor", color);
|
|
1087
721
|
};
|
|
1088
|
-
|
|
1089
|
-
|
|
722
|
+
const addLink = () => {
|
|
723
|
+
const sel = window.getSelection();
|
|
1090
724
|
if (!sel || sel.rangeCount === 0) return;
|
|
1091
725
|
selectionRangeRef.current = sel.getRangeAt(0).cloneRange();
|
|
1092
|
-
|
|
726
|
+
const selectedText = sel.toString();
|
|
1093
727
|
if (selectedText.length > 0) {
|
|
1094
728
|
setLinkText(selectedText);
|
|
1095
729
|
setLinkUrl("");
|
|
@@ -1100,112 +734,108 @@ function RichTextEditor(_ref) {
|
|
|
1100
734
|
setLinkModalOpen(true);
|
|
1101
735
|
}
|
|
1102
736
|
};
|
|
1103
|
-
|
|
737
|
+
const findParentTag = (node, tagName) => {
|
|
1104
738
|
if (!node) return null;
|
|
1105
|
-
|
|
739
|
+
let curr = node;
|
|
1106
740
|
while (curr && curr !== editorRef.current) {
|
|
1107
741
|
if (curr.tagName === tagName) return curr;
|
|
1108
742
|
curr = curr.parentNode;
|
|
1109
743
|
}
|
|
1110
744
|
return null;
|
|
1111
745
|
};
|
|
1112
|
-
|
|
1113
|
-
|
|
746
|
+
const tableAction = action => {
|
|
747
|
+
const sel = window.getSelection();
|
|
1114
748
|
if (!sel || !sel.rangeCount) return;
|
|
1115
|
-
|
|
749
|
+
const cell = findParentTag(sel.anchorNode, 'TD') || findParentTag(sel.anchorNode, 'TH');
|
|
1116
750
|
if (!cell) return;
|
|
1117
|
-
|
|
1118
|
-
|
|
751
|
+
const row = cell.parentNode;
|
|
752
|
+
const table = row.parentNode.closest('table');
|
|
1119
753
|
switch (action) {
|
|
1120
754
|
case 'addRowAbove':
|
|
1121
|
-
|
|
1122
|
-
for (
|
|
1123
|
-
|
|
755
|
+
const newRowAbove = table.insertRow(row.rowIndex);
|
|
756
|
+
for (let i = 0; i < row.cells.length; i++) {
|
|
757
|
+
const newCell = newRowAbove.insertCell(i);
|
|
1124
758
|
newCell.style.border = "1px solid #e5e7eb";
|
|
1125
759
|
newCell.style.padding = "12px";
|
|
1126
760
|
newCell.innerHTML = " ";
|
|
1127
761
|
}
|
|
1128
762
|
break;
|
|
1129
763
|
case 'addRowBelow':
|
|
1130
|
-
|
|
1131
|
-
for (
|
|
1132
|
-
|
|
1133
|
-
|
|
1134
|
-
|
|
1135
|
-
|
|
764
|
+
const newRowBelow = table.insertRow(row.rowIndex + 1);
|
|
765
|
+
for (let i = 0; i < row.cells.length; i++) {
|
|
766
|
+
const newCell = newRowBelow.insertCell(i);
|
|
767
|
+
newCell.style.border = "1px solid #e5e7eb";
|
|
768
|
+
newCell.style.padding = "12px";
|
|
769
|
+
newCell.innerHTML = " ";
|
|
1136
770
|
}
|
|
1137
771
|
break;
|
|
1138
772
|
case 'addColBefore':
|
|
1139
|
-
|
|
1140
|
-
for (
|
|
1141
|
-
|
|
1142
|
-
|
|
1143
|
-
|
|
1144
|
-
|
|
773
|
+
const cellIndex = cell.cellIndex;
|
|
774
|
+
for (let i = 0; i < table.rows.length; i++) {
|
|
775
|
+
const newCell = table.rows[i].insertCell(cellIndex);
|
|
776
|
+
newCell.style.border = "1px solid #e5e7eb";
|
|
777
|
+
newCell.style.padding = "12px";
|
|
778
|
+
newCell.innerHTML = " ";
|
|
1145
779
|
}
|
|
1146
780
|
break;
|
|
1147
781
|
case 'addColAfter':
|
|
1148
|
-
|
|
1149
|
-
for (
|
|
1150
|
-
|
|
1151
|
-
|
|
1152
|
-
|
|
1153
|
-
|
|
782
|
+
const cellIndexAfter = cell.cellIndex + 1;
|
|
783
|
+
for (let i = 0; i < table.rows.length; i++) {
|
|
784
|
+
const newCell = table.rows[i].insertCell(cellIndexAfter);
|
|
785
|
+
newCell.style.border = "1px solid #e5e7eb";
|
|
786
|
+
newCell.style.padding = "12px";
|
|
787
|
+
newCell.innerHTML = " ";
|
|
1154
788
|
}
|
|
1155
789
|
break;
|
|
1156
790
|
case 'deleteRow':
|
|
1157
791
|
{
|
|
1158
|
-
|
|
1159
|
-
|
|
792
|
+
const rowIndex = row.rowIndex;
|
|
793
|
+
const cellIndex = cell.cellIndex;
|
|
1160
794
|
table.deleteRow(rowIndex);
|
|
1161
795
|
if (table.rows.length === 0) {
|
|
1162
796
|
table.remove();
|
|
1163
797
|
} else {
|
|
1164
|
-
|
|
1165
|
-
|
|
1166
|
-
|
|
798
|
+
const targetRowIndex = Math.min(rowIndex, table.rows.length - 1);
|
|
799
|
+
const targetRow = table.rows[targetRowIndex];
|
|
800
|
+
const targetCell = targetRow.cells[Math.min(cellIndex, targetRow.cells.length - 1)];
|
|
1167
801
|
if (targetCell) {
|
|
1168
|
-
|
|
802
|
+
const range = document.createRange();
|
|
1169
803
|
range.selectNodeContents(targetCell);
|
|
1170
804
|
range.collapse(true);
|
|
1171
805
|
sel.removeAllRanges();
|
|
1172
806
|
sel.addRange(range);
|
|
1173
|
-
setSelectionVersion(
|
|
1174
|
-
return v + 1;
|
|
1175
|
-
});
|
|
807
|
+
setSelectionVersion(v => v + 1);
|
|
1176
808
|
}
|
|
1177
809
|
}
|
|
1178
810
|
break;
|
|
1179
811
|
}
|
|
1180
812
|
case 'deleteCol':
|
|
1181
813
|
{
|
|
1182
|
-
|
|
1183
|
-
|
|
1184
|
-
for (
|
|
1185
|
-
table.rows[
|
|
814
|
+
const idx = cell.cellIndex;
|
|
815
|
+
const rowIndex = row.rowIndex;
|
|
816
|
+
for (let i = 0; i < table.rows.length; i++) {
|
|
817
|
+
table.rows[i].deleteCell(idx);
|
|
1186
818
|
}
|
|
1187
819
|
if (table.rows[0].cells.length === 0) {
|
|
1188
820
|
table.remove();
|
|
1189
821
|
} else {
|
|
1190
|
-
var _table$rows$
|
|
1191
|
-
|
|
1192
|
-
|
|
1193
|
-
if (
|
|
1194
|
-
|
|
1195
|
-
|
|
1196
|
-
|
|
822
|
+
var _table$rows$rowIndex;
|
|
823
|
+
const targetColIndex = Math.min(idx, table.rows[0].cells.length - 1);
|
|
824
|
+
const targetCell = ((_table$rows$rowIndex = table.rows[rowIndex]) === null || _table$rows$rowIndex === void 0 ? void 0 : _table$rows$rowIndex.cells[targetColIndex]) || table.rows[0].cells[targetColIndex];
|
|
825
|
+
if (targetCell) {
|
|
826
|
+
const range = document.createRange();
|
|
827
|
+
range.selectNodeContents(targetCell);
|
|
828
|
+
range.collapse(true);
|
|
1197
829
|
sel.removeAllRanges();
|
|
1198
|
-
sel.addRange(
|
|
1199
|
-
setSelectionVersion(
|
|
1200
|
-
return v + 1;
|
|
1201
|
-
});
|
|
830
|
+
sel.addRange(range);
|
|
831
|
+
setSelectionVersion(v => v + 1);
|
|
1202
832
|
}
|
|
1203
833
|
}
|
|
1204
834
|
break;
|
|
1205
835
|
}
|
|
1206
836
|
case 'mergeRight':
|
|
1207
837
|
if (cell.nextElementSibling) {
|
|
1208
|
-
|
|
838
|
+
const nextCell = cell.nextElementSibling;
|
|
1209
839
|
cell.colSpan = (cell.colSpan || 1) + (nextCell.colSpan || 1);
|
|
1210
840
|
nextCell.remove();
|
|
1211
841
|
}
|
|
@@ -1216,20 +846,20 @@ function RichTextEditor(_ref) {
|
|
|
1216
846
|
}
|
|
1217
847
|
triggerChange && triggerChange();
|
|
1218
848
|
};
|
|
1219
|
-
|
|
1220
|
-
|
|
1221
|
-
|
|
1222
|
-
|
|
1223
|
-
for (
|
|
849
|
+
const insertTable = () => {
|
|
850
|
+
const rows = parseInt(tableRows) || 3;
|
|
851
|
+
const cols = parseInt(tableCols) || 3;
|
|
852
|
+
let tableHtml = '<table style="width: 100%; border-collapse: collapse; border: 1px solid #e5e7eb; margin: 16px 0;"><tbody>';
|
|
853
|
+
for (let i = 0; i < rows; i++) {
|
|
1224
854
|
tableHtml += '<tr>';
|
|
1225
|
-
for (
|
|
855
|
+
for (let j = 0; j < cols; j++) {
|
|
1226
856
|
tableHtml += '<td style="border: 1px solid #e5e7eb; padding: 12px; min-height: 20px;"> </td>';
|
|
1227
857
|
}
|
|
1228
858
|
tableHtml += '</tr>';
|
|
1229
859
|
}
|
|
1230
860
|
tableHtml += '</tbody></table><p> </p>';
|
|
1231
861
|
if (selectionRangeRef.current) {
|
|
1232
|
-
|
|
862
|
+
const sel = window.getSelection();
|
|
1233
863
|
sel.removeAllRanges();
|
|
1234
864
|
sel.addRange(selectionRangeRef.current);
|
|
1235
865
|
}
|
|
@@ -1237,50 +867,57 @@ function RichTextEditor(_ref) {
|
|
|
1237
867
|
setTableModalOpen(false);
|
|
1238
868
|
triggerChange && triggerChange();
|
|
1239
869
|
};
|
|
1240
|
-
|
|
870
|
+
const parseVideoUrl = url => {
|
|
1241
871
|
url = url.trim();
|
|
1242
872
|
if (!url) return null;
|
|
1243
873
|
|
|
1244
874
|
// YouTube
|
|
1245
|
-
|
|
1246
|
-
|
|
875
|
+
const ytRegExp = /^.*(youtu.be\/|v\/|u\/\w\/|embed\/|watch\?v=|\&v=|watch\?vi=|\&vi=)([^#\&\?]*).*/;
|
|
876
|
+
const ytMatch = url.match(ytRegExp);
|
|
1247
877
|
if (ytMatch && ytMatch[2].length === 11) {
|
|
1248
|
-
return
|
|
878
|
+
return `https://www.youtube.com/embed/${ytMatch[2]}`;
|
|
1249
879
|
}
|
|
1250
880
|
|
|
1251
881
|
// Vimeo
|
|
1252
|
-
|
|
1253
|
-
|
|
882
|
+
const vimeoRegExp = /vimeo\.com\/(?:channels\/(?:\w+\/)?|groups\/([^\/]*)\/videos\/|album\/(\d+)\/video\/|video\/|)(\d+)(?:$|\/|\?)/;
|
|
883
|
+
const vimeoMatch = url.match(vimeoRegExp);
|
|
1254
884
|
if (vimeoMatch && vimeoMatch[3]) {
|
|
1255
|
-
return
|
|
885
|
+
return `https://player.vimeo.com/video/${vimeoMatch[3]}`;
|
|
1256
886
|
}
|
|
1257
887
|
|
|
1258
888
|
// DailyMotion
|
|
1259
|
-
|
|
1260
|
-
|
|
889
|
+
const dmRegExp = /dailymotion\.com\/video\/([a-zA-Z0-9]+)/;
|
|
890
|
+
const dmMatch = url.match(dmRegExp);
|
|
1261
891
|
if (dmMatch && dmMatch[1]) {
|
|
1262
|
-
return
|
|
892
|
+
return `https://www.dailymotion.com/embed/video/${dmMatch[1]}`;
|
|
1263
893
|
}
|
|
1264
894
|
return null;
|
|
1265
895
|
};
|
|
1266
|
-
|
|
1267
|
-
|
|
896
|
+
const insertVideo = () => {
|
|
897
|
+
const embedUrl = parseVideoUrl(videoUrl);
|
|
1268
898
|
if (embedUrl) {
|
|
1269
899
|
if (editorRef.current) {
|
|
1270
900
|
editorRef.current.focus();
|
|
1271
901
|
}
|
|
1272
902
|
if (selectionRangeRef.current) {
|
|
1273
|
-
|
|
903
|
+
const sel = window.getSelection();
|
|
1274
904
|
sel.removeAllRanges();
|
|
1275
905
|
sel.addRange(selectionRangeRef.current);
|
|
1276
906
|
}
|
|
1277
|
-
|
|
907
|
+
const embedHtml = `<div class="video-container">
|
|
908
|
+
<iframe
|
|
909
|
+
src="${embedUrl}"
|
|
910
|
+
frameborder="0"
|
|
911
|
+
allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture"
|
|
912
|
+
allowfullscreen
|
|
913
|
+
></iframe>
|
|
914
|
+
</div><p> </p>`;
|
|
1278
915
|
try {
|
|
1279
916
|
document.execCommand("insertHTML", false, embedHtml);
|
|
1280
917
|
} catch (err) {
|
|
1281
918
|
console.error("Failed to insert Video HTML:", err);
|
|
1282
919
|
if (editorRef.current) {
|
|
1283
|
-
|
|
920
|
+
const div = document.createElement('div');
|
|
1284
921
|
div.innerHTML = embedHtml;
|
|
1285
922
|
editorRef.current.appendChild(div);
|
|
1286
923
|
}
|
|
@@ -1292,17 +929,23 @@ function RichTextEditor(_ref) {
|
|
|
1292
929
|
console.warn("Invalid Video URL or Platform not supported");
|
|
1293
930
|
}
|
|
1294
931
|
};
|
|
1295
|
-
|
|
932
|
+
const processExistingImages = container => {
|
|
1296
933
|
if (!container) return;
|
|
1297
|
-
container.querySelectorAll("img").forEach(
|
|
1298
|
-
//
|
|
1299
|
-
|
|
1300
|
-
if (
|
|
1301
|
-
|
|
934
|
+
container.querySelectorAll("img").forEach(img => {
|
|
935
|
+
// ONLY wrap if it's not already inside a wrapper
|
|
936
|
+
const existingWrapper = img.closest(".image-container");
|
|
937
|
+
if (existingWrapper) {
|
|
938
|
+
// Just update existing wrapper state if needed
|
|
939
|
+
existingWrapper.style.cursor = editable ? 'pointer' : 'default';
|
|
940
|
+
const deleteBtn = existingWrapper.querySelector('.image-delete-button');
|
|
941
|
+
if (deleteBtn) {
|
|
942
|
+
deleteBtn.style.display = editable ? 'flex' : 'none';
|
|
943
|
+
}
|
|
944
|
+
return;
|
|
1302
945
|
}
|
|
1303
|
-
|
|
1304
|
-
|
|
1305
|
-
wrapper.className =
|
|
946
|
+
const wrapper = document.createElement("div");
|
|
947
|
+
const align = img.getAttribute('data-align') || 'center';
|
|
948
|
+
wrapper.className = `image-container image-align-${align}`;
|
|
1306
949
|
wrapper.style.cursor = editable ? 'pointer' : 'default';
|
|
1307
950
|
img.className = "rte-image";
|
|
1308
951
|
img.style.cssText = ""; // Reset inline styles
|
|
@@ -1310,26 +953,26 @@ function RichTextEditor(_ref) {
|
|
|
1310
953
|
img.dataset.hasDeleteButton = "true";
|
|
1311
954
|
|
|
1312
955
|
// Add click listener to open modal
|
|
1313
|
-
img.addEventListener("click",
|
|
1314
|
-
|
|
1315
|
-
});
|
|
1316
|
-
var deleteBtn = document.createElement("button");
|
|
956
|
+
img.addEventListener("click", () => openImageModal(img.src));
|
|
957
|
+
const deleteBtn = document.createElement("button");
|
|
1317
958
|
deleteBtn.innerHTML = "×";
|
|
1318
959
|
deleteBtn.className = "image-delete-button";
|
|
1319
960
|
deleteBtn.style.display = editable ? 'flex' : 'none';
|
|
1320
961
|
deleteBtn.style.pointerEvents = editable ? 'auto' : 'none';
|
|
1321
962
|
deleteBtn.title = "Remove image";
|
|
1322
|
-
deleteBtn.onclick =
|
|
963
|
+
deleteBtn.onclick = e => {
|
|
1323
964
|
e.preventDefault();
|
|
1324
965
|
e.stopPropagation();
|
|
1325
|
-
|
|
966
|
+
const wrapper = e.currentTarget.closest(".image-container");
|
|
1326
967
|
if (wrapper && wrapper.parentNode) {
|
|
1327
968
|
wrapper.parentNode.removeChild(wrapper);
|
|
1328
969
|
triggerChange && triggerChange();
|
|
1329
970
|
}
|
|
1330
971
|
};
|
|
1331
|
-
|
|
1332
|
-
|
|
972
|
+
const {
|
|
973
|
+
parentNode,
|
|
974
|
+
nextSibling
|
|
975
|
+
} = img;
|
|
1333
976
|
if (parentNode) {
|
|
1334
977
|
parentNode.removeChild(img);
|
|
1335
978
|
wrapper.appendChild(img);
|
|
@@ -1342,111 +985,86 @@ function RichTextEditor(_ref) {
|
|
|
1342
985
|
}
|
|
1343
986
|
});
|
|
1344
987
|
};
|
|
1345
|
-
useEffect(
|
|
988
|
+
useEffect(() => {
|
|
1346
989
|
if (editorRef.current && value) {
|
|
1347
|
-
requestAnimationFrame(
|
|
1348
|
-
return processExistingImages(editorRef.current);
|
|
1349
|
-
});
|
|
990
|
+
requestAnimationFrame(() => processExistingImages(editorRef.current));
|
|
1350
991
|
}
|
|
1351
992
|
}, [value]);
|
|
1352
|
-
var insertImage = /*#__PURE__*/function () {
|
|
1353
|
-
var _ref2 = _asyncToGenerator(/*#__PURE__*/_regenerator().m(function _callee(dataUrl, fileName) {
|
|
1354
|
-
var container, img;
|
|
1355
|
-
return _regenerator().w(function (_context) {
|
|
1356
|
-
while (1) switch (_context.n) {
|
|
1357
|
-
case 0:
|
|
1358
|
-
try {
|
|
1359
|
-
if (editable) {
|
|
1360
|
-
// Create container for the image
|
|
1361
|
-
container = document.createElement('div');
|
|
1362
|
-
container.className = 'image-container';
|
|
1363
993
|
|
|
1364
|
-
|
|
1365
|
-
|
|
1366
|
-
|
|
1367
|
-
|
|
1368
|
-
|
|
1369
|
-
|
|
1370
|
-
|
|
994
|
+
/*
|
|
995
|
+
Advanced Tip: Use the 'onImageUpload' prop to handle file uploads to a server
|
|
996
|
+
instead of using base64. If 'onImageUpload' is provided, it should return a URL string.
|
|
997
|
+
*/
|
|
998
|
+
const insertImage = async (dataUrl, fileName) => {
|
|
999
|
+
try {
|
|
1000
|
+
if (editable) {
|
|
1001
|
+
// Create container for the image
|
|
1002
|
+
const container = document.createElement('div');
|
|
1003
|
+
container.className = 'image-container';
|
|
1371
1004
|
|
|
1372
|
-
|
|
1373
|
-
|
|
1005
|
+
// Create image element
|
|
1006
|
+
const img = document.createElement('img');
|
|
1007
|
+
img.src = dataUrl;
|
|
1008
|
+
img.alt = fileName || "image";
|
|
1009
|
+
img.addEventListener("click", () => openImageModal(dataUrl));
|
|
1374
1010
|
|
|
1375
|
-
|
|
1376
|
-
|
|
1377
|
-
triggerChange();
|
|
1011
|
+
// Add elements to container
|
|
1012
|
+
container.appendChild(img);
|
|
1378
1013
|
|
|
1379
|
-
|
|
1380
|
-
|
|
1381
|
-
|
|
1382
|
-
|
|
1383
|
-
|
|
1384
|
-
|
|
1385
|
-
|
|
1386
|
-
|
|
1387
|
-
|
|
1388
|
-
|
|
1389
|
-
|
|
1390
|
-
|
|
1391
|
-
}));
|
|
1392
|
-
return function insertImage(_x, _x2) {
|
|
1393
|
-
return _ref2.apply(this, arguments);
|
|
1394
|
-
};
|
|
1395
|
-
}();
|
|
1396
|
-
var readFileAsDataURL = function readFileAsDataURL(file) {
|
|
1397
|
-
return new Promise(function (res, rej) {
|
|
1398
|
-
var reader = new FileReader();
|
|
1399
|
-
reader.onload = function (ev) {
|
|
1400
|
-
return res(ev.target.result);
|
|
1401
|
-
};
|
|
1402
|
-
reader.onerror = rej;
|
|
1403
|
-
reader.readAsDataURL(file);
|
|
1404
|
-
});
|
|
1014
|
+
// Insert at cursor position
|
|
1015
|
+
insertNodeAtCursor(container);
|
|
1016
|
+
triggerChange();
|
|
1017
|
+
|
|
1018
|
+
// Immediately process newly inserted image so delete button appears
|
|
1019
|
+
requestAnimationFrame(() => {
|
|
1020
|
+
processExistingImages(editorRef.current);
|
|
1021
|
+
});
|
|
1022
|
+
}
|
|
1023
|
+
} catch (err) {
|
|
1024
|
+
console.error('Error inserting image:', err);
|
|
1025
|
+
}
|
|
1405
1026
|
};
|
|
1406
|
-
|
|
1407
|
-
|
|
1027
|
+
const readFileAsDataURL = file => new Promise((res, rej) => {
|
|
1028
|
+
const reader = new FileReader();
|
|
1029
|
+
reader.onload = ev => res(ev.target.result);
|
|
1030
|
+
reader.onerror = rej;
|
|
1031
|
+
reader.readAsDataURL(file);
|
|
1032
|
+
});
|
|
1033
|
+
const handlePaste = useCallback(e => {
|
|
1034
|
+
const clipboardData = e.clipboardData || window.clipboardData;
|
|
1408
1035
|
if (!clipboardData) return;
|
|
1409
1036
|
|
|
1410
1037
|
// Check for image in clipboard
|
|
1411
|
-
|
|
1412
|
-
|
|
1413
|
-
|
|
1414
|
-
|
|
1415
|
-
|
|
1416
|
-
|
|
1417
|
-
|
|
1418
|
-
|
|
1419
|
-
|
|
1420
|
-
|
|
1421
|
-
|
|
1422
|
-
|
|
1423
|
-
|
|
1424
|
-
|
|
1425
|
-
|
|
1426
|
-
|
|
1427
|
-
|
|
1428
|
-
|
|
1429
|
-
|
|
1430
|
-
|
|
1431
|
-
}
|
|
1432
|
-
return {
|
|
1433
|
-
v: void 0
|
|
1434
|
-
};
|
|
1038
|
+
const items = clipboardData.items || [];
|
|
1039
|
+
for (let i = 0; i < items.length; i++) {
|
|
1040
|
+
const item = items[i];
|
|
1041
|
+
if (item.kind === 'file' && item.type.indexOf('image/') !== -1) {
|
|
1042
|
+
e.preventDefault();
|
|
1043
|
+
const file = item.getAsFile();
|
|
1044
|
+
if (file) {
|
|
1045
|
+
setIsUploading(true);
|
|
1046
|
+
const uploadPromise = onImageUpload ? onImageUpload(file) : readFileAsDataURL(file);
|
|
1047
|
+
uploadPromise.then(url => {
|
|
1048
|
+
if (url) {
|
|
1049
|
+
// if the user's onImageUpload resolves to `{ mediaUrl: '...' }` like the previous MediaUpload, handle it
|
|
1050
|
+
const finalUrl = typeof url === 'object' && url !== null && url.mediaUrl ? url.mediaUrl : url;
|
|
1051
|
+
insertImage(finalUrl, file.name || 'pasted-image');
|
|
1052
|
+
}
|
|
1053
|
+
setIsUploading(false);
|
|
1054
|
+
}).catch(error => {
|
|
1055
|
+
console.error('Error uploading pasted image:', error);
|
|
1056
|
+
setIsUploading(false);
|
|
1057
|
+
});
|
|
1435
1058
|
}
|
|
1436
|
-
|
|
1437
|
-
|
|
1438
|
-
for (var i = 0; i < items.length; i++) {
|
|
1439
|
-
_ret = _loop();
|
|
1440
|
-
if (_ret) return _ret.v;
|
|
1059
|
+
return;
|
|
1060
|
+
}
|
|
1441
1061
|
}
|
|
1442
|
-
|
|
1062
|
+
const htmlData = clipboardData.getData('text/html');
|
|
1443
1063
|
if (htmlData && htmlData.trim()) {
|
|
1444
1064
|
e.preventDefault();
|
|
1445
|
-
|
|
1065
|
+
const tempDiv = document.createElement('div');
|
|
1446
1066
|
tempDiv.innerHTML = htmlData;
|
|
1447
|
-
tempDiv.querySelectorAll('script, meta, link').forEach(
|
|
1448
|
-
return el.remove();
|
|
1449
|
-
});
|
|
1067
|
+
tempDiv.querySelectorAll('script, meta, link').forEach(el => el.remove());
|
|
1450
1068
|
document.execCommand('styleWithCSS', false, true);
|
|
1451
1069
|
document.execCommand('insertHTML', false, tempDiv.innerHTML);
|
|
1452
1070
|
document.execCommand('styleWithCSS', false, false);
|
|
@@ -1454,13 +1072,13 @@ function RichTextEditor(_ref) {
|
|
|
1454
1072
|
focus();
|
|
1455
1073
|
return;
|
|
1456
1074
|
}
|
|
1457
|
-
|
|
1075
|
+
const plainText = clipboardData.getData('text/plain');
|
|
1458
1076
|
if (plainText) {
|
|
1459
1077
|
e.preventDefault();
|
|
1460
|
-
|
|
1461
|
-
htmlToInsert = htmlToInsert.replace(URL_REGEX,
|
|
1462
|
-
|
|
1463
|
-
return
|
|
1078
|
+
let htmlToInsert = escapeHtml(plainText);
|
|
1079
|
+
htmlToInsert = htmlToInsert.replace(URL_REGEX, url => {
|
|
1080
|
+
const safeUrl = escapeAttr(url.trim());
|
|
1081
|
+
return `<a href="${safeUrl}" target="_blank" rel="noopener noreferrer" style="color: blue; text-decoration: underline;">${escapeHtml(url)}</a>`;
|
|
1464
1082
|
});
|
|
1465
1083
|
htmlToInsert = htmlToInsert.replace(/\n/g, '<br>');
|
|
1466
1084
|
document.execCommand('insertHTML', false, htmlToInsert);
|
|
@@ -1468,94 +1086,37 @@ function RichTextEditor(_ref) {
|
|
|
1468
1086
|
focus();
|
|
1469
1087
|
}
|
|
1470
1088
|
}, [insertImage, triggerChange]);
|
|
1471
|
-
|
|
1472
|
-
|
|
1473
|
-
|
|
1474
|
-
|
|
1475
|
-
|
|
1476
|
-
|
|
1477
|
-
|
|
1478
|
-
|
|
1479
|
-
|
|
1480
|
-
|
|
1481
|
-
|
|
1482
|
-
|
|
1483
|
-
|
|
1484
|
-
|
|
1485
|
-
|
|
1486
|
-
|
|
1487
|
-
|
|
1488
|
-
|
|
1489
|
-
|
|
1490
|
-
|
|
1491
|
-
|
|
1492
|
-
|
|
1493
|
-
|
|
1494
|
-
|
|
1495
|
-
|
|
1496
|
-
|
|
1497
|
-
|
|
1498
|
-
|
|
1499
|
-
return _regenerator().w(function (_context2) {
|
|
1500
|
-
while (1) switch (_context2.n) {
|
|
1501
|
-
case 0:
|
|
1502
|
-
file = _step.value;
|
|
1503
|
-
try {
|
|
1504
|
-
setIsUploading(true);
|
|
1505
|
-
uploadPromise = onImageUpload ? onImageUpload(file) : readFileAsDataURL(file);
|
|
1506
|
-
uploadPromise.then(function (url) {
|
|
1507
|
-
if (url) {
|
|
1508
|
-
var finalUrl = _typeof(url) === 'object' && url !== null && url.mediaUrl ? url.mediaUrl : url;
|
|
1509
|
-
insertImage(finalUrl, file.name);
|
|
1510
|
-
}
|
|
1511
|
-
setIsUploading(false);
|
|
1512
|
-
})["catch"](function (error) {
|
|
1513
|
-
console.error('Error processing image:', error);
|
|
1514
|
-
setIsUploading(false);
|
|
1515
|
-
});
|
|
1516
|
-
} catch (error) {
|
|
1517
|
-
console.error('Error processing image:', error);
|
|
1518
|
-
setIsUploading(false);
|
|
1519
|
-
}
|
|
1520
|
-
case 1:
|
|
1521
|
-
return _context2.a(2);
|
|
1522
|
-
}
|
|
1523
|
-
}, _loop2);
|
|
1524
|
-
});
|
|
1525
|
-
_iterator.s();
|
|
1526
|
-
case 4:
|
|
1527
|
-
if ((_step = _iterator.n()).done) {
|
|
1528
|
-
_context3.n = 6;
|
|
1529
|
-
break;
|
|
1530
|
-
}
|
|
1531
|
-
return _context3.d(_regeneratorValues(_loop2()), 5);
|
|
1532
|
-
case 5:
|
|
1533
|
-
_context3.n = 4;
|
|
1534
|
-
break;
|
|
1535
|
-
case 6:
|
|
1536
|
-
_context3.n = 8;
|
|
1537
|
-
break;
|
|
1538
|
-
case 7:
|
|
1539
|
-
_context3.p = 7;
|
|
1540
|
-
_t = _context3.v;
|
|
1541
|
-
_iterator.e(_t);
|
|
1542
|
-
case 8:
|
|
1543
|
-
_context3.p = 8;
|
|
1544
|
-
_iterator.f();
|
|
1545
|
-
return _context3.f(8);
|
|
1546
|
-
case 9:
|
|
1547
|
-
return _context3.a(2);
|
|
1548
|
-
}
|
|
1549
|
-
}, _callee2, null, [[3, 7, 8, 9]]);
|
|
1550
|
-
}));
|
|
1551
|
-
return function handleDrop(_x3) {
|
|
1552
|
-
return _ref3.apply(this, arguments);
|
|
1553
|
-
};
|
|
1554
|
-
}();
|
|
1555
|
-
var insertNodeAtCursor = function insertNodeAtCursor(node) {
|
|
1089
|
+
const handleDrop = async e => {
|
|
1090
|
+
if (!editable) return;
|
|
1091
|
+
e.preventDefault();
|
|
1092
|
+
e.stopPropagation();
|
|
1093
|
+
const files = e.dataTransfer.files;
|
|
1094
|
+
if (!files || files.length === 0) return;
|
|
1095
|
+
const imageFiles = Array.from(files).filter(file => file.type.startsWith("image/"));
|
|
1096
|
+
for (const file of imageFiles) {
|
|
1097
|
+
try {
|
|
1098
|
+
setIsUploading(true);
|
|
1099
|
+
const uploadPromise = onImageUpload ? onImageUpload(file) : readFileAsDataURL(file);
|
|
1100
|
+
uploadPromise.then(url => {
|
|
1101
|
+
if (url) {
|
|
1102
|
+
const finalUrl = typeof url === 'object' && url !== null && url.mediaUrl ? url.mediaUrl : url;
|
|
1103
|
+
insertImage(finalUrl, file.name);
|
|
1104
|
+
}
|
|
1105
|
+
setIsUploading(false);
|
|
1106
|
+
}).catch(error => {
|
|
1107
|
+
console.error('Error processing image:', error);
|
|
1108
|
+
setIsUploading(false);
|
|
1109
|
+
});
|
|
1110
|
+
} catch (error) {
|
|
1111
|
+
console.error('Error processing image:', error);
|
|
1112
|
+
setIsUploading(false);
|
|
1113
|
+
}
|
|
1114
|
+
}
|
|
1115
|
+
};
|
|
1116
|
+
const insertNodeAtCursor = node => {
|
|
1556
1117
|
try {
|
|
1557
|
-
|
|
1558
|
-
|
|
1118
|
+
const sel = window.getSelection();
|
|
1119
|
+
let range;
|
|
1559
1120
|
if (!sel || sel.rangeCount === 0 || !editorRef.current.contains(sel.anchorNode)) {
|
|
1560
1121
|
editorRef.current.focus();
|
|
1561
1122
|
|
|
@@ -1570,7 +1131,7 @@ function RichTextEditor(_ref) {
|
|
|
1570
1131
|
}
|
|
1571
1132
|
range.deleteContents();
|
|
1572
1133
|
range.insertNode(node);
|
|
1573
|
-
|
|
1134
|
+
const space = document.createTextNode("\u00A0");
|
|
1574
1135
|
if (node.parentNode) {
|
|
1575
1136
|
node.parentNode.insertBefore(space, node.nextSibling);
|
|
1576
1137
|
}
|
|
@@ -1585,36 +1146,36 @@ function RichTextEditor(_ref) {
|
|
|
1585
1146
|
}
|
|
1586
1147
|
}
|
|
1587
1148
|
};
|
|
1588
|
-
|
|
1149
|
+
const getCleanHtml = () => {
|
|
1589
1150
|
if (!editorRef.current) return "";
|
|
1590
1151
|
return editorRef.current.innerHTML;
|
|
1591
1152
|
};
|
|
1592
1153
|
|
|
1593
1154
|
// Helper function to unescape HTML entities
|
|
1594
|
-
|
|
1155
|
+
const unescapeHtml = html => {
|
|
1595
1156
|
if (!html) return '';
|
|
1596
|
-
|
|
1157
|
+
const txt = document.createElement("textarea");
|
|
1597
1158
|
txt.innerHTML = html;
|
|
1598
1159
|
return txt.value;
|
|
1599
1160
|
};
|
|
1600
|
-
|
|
1161
|
+
const handleKeyDown = useCallback(e => {
|
|
1601
1162
|
// Handle Enter key
|
|
1602
1163
|
if (e.key === 'Enter') {
|
|
1603
1164
|
e.preventDefault();
|
|
1604
|
-
|
|
1165
|
+
const selection = window.getSelection();
|
|
1605
1166
|
if (!selection.rangeCount) return;
|
|
1606
|
-
|
|
1607
|
-
|
|
1608
|
-
|
|
1167
|
+
const range = selection.getRangeAt(0);
|
|
1168
|
+
const node = range.startContainer;
|
|
1169
|
+
const parent = node.nodeType === 3 ? node.parentNode : node;
|
|
1609
1170
|
|
|
1610
1171
|
// Check if we're in a list item
|
|
1611
|
-
|
|
1172
|
+
const listItem = parent.closest('li');
|
|
1612
1173
|
if (listItem) {
|
|
1613
|
-
|
|
1174
|
+
const list = listItem.parentNode;
|
|
1614
1175
|
list.tagName === 'OL';
|
|
1615
1176
|
|
|
1616
1177
|
// Create a new list item
|
|
1617
|
-
|
|
1178
|
+
const newItem = document.createElement('li');
|
|
1618
1179
|
|
|
1619
1180
|
// If we're at the end of a list item, add a new one
|
|
1620
1181
|
if (range.collapsed && range.endOffset === node.length) {
|
|
@@ -1622,12 +1183,12 @@ function RichTextEditor(_ref) {
|
|
|
1622
1183
|
if (listItem.textContent.trim() === '') {
|
|
1623
1184
|
document.execCommand('insertHTML', false, '<div><br></div>');
|
|
1624
1185
|
// Move the cursor to the new line
|
|
1625
|
-
|
|
1626
|
-
|
|
1627
|
-
|
|
1628
|
-
|
|
1186
|
+
const newRange = document.createRange();
|
|
1187
|
+
const newDiv = editorRef.current.lastElementChild;
|
|
1188
|
+
newRange.setStart(newDiv, 0);
|
|
1189
|
+
newRange.collapse(true);
|
|
1629
1190
|
selection.removeAllRanges();
|
|
1630
|
-
selection.addRange(
|
|
1191
|
+
selection.addRange(newRange);
|
|
1631
1192
|
return;
|
|
1632
1193
|
}
|
|
1633
1194
|
|
|
@@ -1639,15 +1200,15 @@ function RichTextEditor(_ref) {
|
|
|
1639
1200
|
}
|
|
1640
1201
|
|
|
1641
1202
|
// Move cursor to the new list item
|
|
1642
|
-
|
|
1203
|
+
const newRange = document.createRange();
|
|
1643
1204
|
newRange.setStart(newItem, 0);
|
|
1644
1205
|
newRange.collapse(true);
|
|
1645
1206
|
selection.removeAllRanges();
|
|
1646
1207
|
selection.addRange(newRange);
|
|
1647
1208
|
} else {
|
|
1648
1209
|
// If we're in the middle of text, split the list item
|
|
1649
|
-
|
|
1650
|
-
|
|
1210
|
+
const textBefore = node.textContent.substring(0, range.startOffset);
|
|
1211
|
+
const textAfter = node.textContent.substring(range.startOffset);
|
|
1651
1212
|
|
|
1652
1213
|
// Update current item
|
|
1653
1214
|
node.textContent = textBefore;
|
|
@@ -1661,11 +1222,11 @@ function RichTextEditor(_ref) {
|
|
|
1661
1222
|
}
|
|
1662
1223
|
|
|
1663
1224
|
// Move cursor to the new list item
|
|
1664
|
-
|
|
1665
|
-
|
|
1666
|
-
|
|
1225
|
+
const newRange = document.createRange();
|
|
1226
|
+
newRange.setStart(newItem.firstChild || newItem, 0);
|
|
1227
|
+
newRange.collapse(true);
|
|
1667
1228
|
selection.removeAllRanges();
|
|
1668
|
-
selection.addRange(
|
|
1229
|
+
selection.addRange(newRange);
|
|
1669
1230
|
}
|
|
1670
1231
|
} else {
|
|
1671
1232
|
// Regular text, insert a new paragraph
|
|
@@ -1687,54 +1248,54 @@ function RichTextEditor(_ref) {
|
|
|
1687
1248
|
exec("underline");
|
|
1688
1249
|
}
|
|
1689
1250
|
}, [exec, triggerChange]);
|
|
1690
|
-
|
|
1251
|
+
const confirmLink = () => {
|
|
1691
1252
|
// Add protocol if missing
|
|
1692
|
-
|
|
1253
|
+
let url = linkUrl.trim();
|
|
1693
1254
|
if (url && !/^(https?:\/\/|mailto:|tel:)/i.test(url)) {
|
|
1694
|
-
url =
|
|
1255
|
+
url = `https://${url}`;
|
|
1695
1256
|
}
|
|
1696
|
-
|
|
1697
|
-
|
|
1698
|
-
|
|
1257
|
+
const safeUrl = escapeAttr(url);
|
|
1258
|
+
const safeText = escapeHtml(linkText || linkUrl);
|
|
1259
|
+
const sel = window.getSelection();
|
|
1699
1260
|
sel.removeAllRanges();
|
|
1700
1261
|
if (selectionRangeRef.current) {
|
|
1701
1262
|
sel.addRange(selectionRangeRef.current);
|
|
1702
1263
|
}
|
|
1703
|
-
|
|
1264
|
+
const linkHtml = `<a href="${safeUrl}" target="_blank" rel="noopener noreferrer" style="color: blue;">${safeText}</a>`;
|
|
1704
1265
|
document.execCommand("insertHTML", false, linkHtml);
|
|
1705
1266
|
setLinkModalOpen(false);
|
|
1706
1267
|
triggerChange();
|
|
1707
1268
|
focus();
|
|
1708
1269
|
selectionRangeRef.current = null;
|
|
1709
1270
|
};
|
|
1710
|
-
|
|
1271
|
+
const cancelLink = () => {
|
|
1711
1272
|
setLinkModalOpen(false);
|
|
1712
1273
|
selectionRangeRef.current = null;
|
|
1713
1274
|
};
|
|
1714
|
-
|
|
1275
|
+
const handleSelect = type => {
|
|
1715
1276
|
exec(type === "unordered" ? "insertUnorderedList" : "insertOrderedList");
|
|
1716
1277
|
};
|
|
1717
|
-
|
|
1278
|
+
const onLineHeightChange = value => {
|
|
1718
1279
|
if (!value) return;
|
|
1719
|
-
|
|
1280
|
+
const sel = window.getSelection();
|
|
1720
1281
|
if (!sel || !sel.rangeCount) return;
|
|
1721
|
-
|
|
1722
|
-
|
|
1282
|
+
const range = sel.getRangeAt(0);
|
|
1283
|
+
const editor = editorRef.current;
|
|
1723
1284
|
if (!editor) return;
|
|
1724
|
-
|
|
1725
|
-
acceptNode:
|
|
1285
|
+
const walker = document.createTreeWalker(editor, NodeFilter.SHOW_ELEMENT | NodeFilter.SHOW_TEXT, {
|
|
1286
|
+
acceptNode: node => {
|
|
1726
1287
|
return range.intersectsNode(node) ? NodeFilter.FILTER_ACCEPT : NodeFilter.FILTER_REJECT;
|
|
1727
1288
|
}
|
|
1728
1289
|
}, false);
|
|
1729
|
-
|
|
1730
|
-
|
|
1731
|
-
|
|
1732
|
-
|
|
1290
|
+
let node;
|
|
1291
|
+
const blocksToStyle = new Set();
|
|
1292
|
+
const blockTags = ['P', 'DIV', 'H1', 'H2', 'H3', 'H4', 'H5', 'H6', 'LI', 'BLOCKQUOTE'];
|
|
1293
|
+
const tempRange = range.cloneRange();
|
|
1733
1294
|
while (node = walker.nextNode()) {
|
|
1734
1295
|
if (node.nodeType === 1 && blockTags.includes(node.tagName)) {
|
|
1735
1296
|
blocksToStyle.add(node);
|
|
1736
1297
|
} else if (node.nodeType === 3) {
|
|
1737
|
-
|
|
1298
|
+
let parent = node.parentNode;
|
|
1738
1299
|
while (parent && parent !== editor && !blockTags.includes(parent.tagName)) {
|
|
1739
1300
|
parent = parent.parentNode;
|
|
1740
1301
|
}
|
|
@@ -1744,11 +1305,11 @@ function RichTextEditor(_ref) {
|
|
|
1744
1305
|
}
|
|
1745
1306
|
}
|
|
1746
1307
|
if (blocksToStyle.size > 0) {
|
|
1747
|
-
blocksToStyle.forEach(
|
|
1308
|
+
blocksToStyle.forEach(block => {
|
|
1748
1309
|
block.style.lineHeight = value;
|
|
1749
1310
|
});
|
|
1750
1311
|
} else {
|
|
1751
|
-
|
|
1312
|
+
let common = range.commonAncestorContainer;
|
|
1752
1313
|
if (common.nodeType === 3) common = common.parentNode;
|
|
1753
1314
|
while (common && common !== editor && !blockTags.includes(common.tagName)) {
|
|
1754
1315
|
common = common.parentNode;
|
|
@@ -1757,7 +1318,7 @@ function RichTextEditor(_ref) {
|
|
|
1757
1318
|
common.style.lineHeight = value;
|
|
1758
1319
|
} else if (editor) {
|
|
1759
1320
|
document.execCommand('formatBlock', false, 'div');
|
|
1760
|
-
|
|
1321
|
+
let newCommon = window.getSelection().getRangeAt(0).commonAncestorContainer;
|
|
1761
1322
|
if (newCommon.nodeType === 3) newCommon = newCommon.parentNode;
|
|
1762
1323
|
if (newCommon && newCommon !== editor) {
|
|
1763
1324
|
newCommon.style.lineHeight = value;
|
|
@@ -1772,19 +1333,19 @@ function RichTextEditor(_ref) {
|
|
|
1772
1333
|
triggerChange();
|
|
1773
1334
|
focus();
|
|
1774
1335
|
};
|
|
1775
|
-
|
|
1776
|
-
|
|
1336
|
+
const applyFontSize = size => {
|
|
1337
|
+
const sel = window.getSelection();
|
|
1777
1338
|
if (!sel || !sel.rangeCount) return;
|
|
1778
|
-
|
|
1779
|
-
|
|
1339
|
+
const range = sel.getRangeAt(0);
|
|
1340
|
+
const sizePx = `${size}px`;
|
|
1780
1341
|
|
|
1781
1342
|
// Collapsed selection (cursor only): insert a styled zero-width span
|
|
1782
1343
|
if (range.collapsed) {
|
|
1783
|
-
|
|
1344
|
+
const span = document.createElement("span");
|
|
1784
1345
|
span.style.fontSize = sizePx;
|
|
1785
1346
|
span.appendChild(document.createTextNode("\u200B"));
|
|
1786
1347
|
range.insertNode(span);
|
|
1787
|
-
|
|
1348
|
+
const newRange = document.createRange();
|
|
1788
1349
|
newRange.setStart(span.firstChild, 1);
|
|
1789
1350
|
newRange.collapse(true);
|
|
1790
1351
|
sel.removeAllRanges();
|
|
@@ -1796,42 +1357,41 @@ function RichTextEditor(_ref) {
|
|
|
1796
1357
|
|
|
1797
1358
|
// Extended selection (highlighted text)
|
|
1798
1359
|
try {
|
|
1799
|
-
|
|
1360
|
+
const editor = editorRef.current;
|
|
1800
1361
|
if (!editor) return;
|
|
1801
1362
|
|
|
1802
1363
|
// We will iterate through all the text nodes in the selection
|
|
1803
|
-
|
|
1804
|
-
acceptNode:
|
|
1364
|
+
const walker = document.createTreeWalker(editor, NodeFilter.SHOW_TEXT, {
|
|
1365
|
+
acceptNode: node => {
|
|
1805
1366
|
return range.intersectsNode(node) ? NodeFilter.FILTER_ACCEPT : NodeFilter.FILTER_REJECT;
|
|
1806
1367
|
}
|
|
1807
1368
|
}, false);
|
|
1808
|
-
|
|
1809
|
-
|
|
1369
|
+
let node;
|
|
1370
|
+
const nodesToStyle = [];
|
|
1810
1371
|
while (node = walker.nextNode()) {
|
|
1811
1372
|
nodesToStyle.push(node);
|
|
1812
1373
|
}
|
|
1813
|
-
|
|
1814
|
-
|
|
1374
|
+
const savedRange = range.cloneRange();
|
|
1375
|
+
let lastInsertedNode = null;
|
|
1815
1376
|
|
|
1816
1377
|
// Iterate through the selected text nodes and wrap them in spans
|
|
1817
|
-
for (
|
|
1818
|
-
|
|
1819
|
-
var parent = textNode.parentNode;
|
|
1378
|
+
for (const textNode of nodesToStyle) {
|
|
1379
|
+
const parent = textNode.parentNode;
|
|
1820
1380
|
|
|
1821
1381
|
// This is important: check if the parent is a block-level element
|
|
1822
1382
|
// like a list item or paragraph. If so, we want to style the block
|
|
1823
1383
|
// itself to avoid breaking its structure.
|
|
1824
|
-
|
|
1384
|
+
const isBlockLevel = ['P', 'H1', 'H2', 'H3', 'H4', 'H5', 'H6', 'LI', 'BLOCKQUOTE'].includes(parent.tagName);
|
|
1825
1385
|
if (isBlockLevel) {
|
|
1826
1386
|
parent.style.fontSize = sizePx;
|
|
1827
1387
|
} else {
|
|
1828
1388
|
// For inline text, wrap the selected portion in a new span
|
|
1829
|
-
|
|
1830
|
-
|
|
1831
|
-
|
|
1389
|
+
const startOffset = textNode === savedRange.startContainer ? savedRange.startOffset : 0;
|
|
1390
|
+
const endOffset = textNode === savedRange.endContainer ? savedRange.endOffset : textNode.length;
|
|
1391
|
+
const newSpan = document.createElement("span");
|
|
1832
1392
|
newSpan.style.fontSize = sizePx;
|
|
1833
1393
|
newSpan.textContent = textNode.textContent.substring(startOffset, endOffset);
|
|
1834
|
-
|
|
1394
|
+
const tempRange = document.createRange();
|
|
1835
1395
|
tempRange.setStart(textNode, startOffset);
|
|
1836
1396
|
tempRange.setEnd(textNode, endOffset);
|
|
1837
1397
|
tempRange.deleteContents();
|
|
@@ -1842,11 +1402,11 @@ function RichTextEditor(_ref) {
|
|
|
1842
1402
|
|
|
1843
1403
|
// After styling, we need to correctly position the cursor
|
|
1844
1404
|
if (lastInsertedNode) {
|
|
1845
|
-
|
|
1846
|
-
|
|
1847
|
-
|
|
1405
|
+
const newRange = document.createRange();
|
|
1406
|
+
newRange.setStartAfter(lastInsertedNode);
|
|
1407
|
+
newRange.collapse(true);
|
|
1848
1408
|
sel.removeAllRanges();
|
|
1849
|
-
sel.addRange(
|
|
1409
|
+
sel.addRange(newRange);
|
|
1850
1410
|
} else {
|
|
1851
1411
|
// If no nodes were wrapped (e.g., we styled a block), restore the original selection
|
|
1852
1412
|
sel.removeAllRanges();
|
|
@@ -1858,65 +1418,47 @@ function RichTextEditor(_ref) {
|
|
|
1858
1418
|
triggerChange();
|
|
1859
1419
|
focus();
|
|
1860
1420
|
};
|
|
1861
|
-
|
|
1862
|
-
if (
|
|
1863
|
-
|
|
1864
|
-
setHtml(
|
|
1865
|
-
|
|
1866
|
-
|
|
1867
|
-
|
|
1868
|
-
|
|
1869
|
-
|
|
1870
|
-
|
|
1871
|
-
|
|
1872
|
-
|
|
1873
|
-
|
|
1874
|
-
|
|
1875
|
-
|
|
1876
|
-
|
|
1877
|
-
|
|
1878
|
-
|
|
1879
|
-
|
|
1880
|
-
case 1:
|
|
1881
|
-
try {
|
|
1882
|
-
setIsUploading(true);
|
|
1883
|
-
uploadPromise = onImageUpload ? onImageUpload(file) : readFileAsDataURL(file);
|
|
1884
|
-
uploadPromise.then(function (url) {
|
|
1885
|
-
if (url) {
|
|
1886
|
-
var finalUrl = _typeof(url) === 'object' && url !== null && url.mediaUrl ? url.mediaUrl : url;
|
|
1887
|
-
insertImage(finalUrl, file.name);
|
|
1888
|
-
}
|
|
1889
|
-
setIsUploading(false);
|
|
1890
|
-
e.target.value = null;
|
|
1891
|
-
})["catch"](function (error) {
|
|
1892
|
-
console.error('Error uploading image:', error);
|
|
1893
|
-
setIsUploading(false);
|
|
1894
|
-
});
|
|
1895
|
-
} catch (error) {
|
|
1896
|
-
console.error('Error uploading image:', error);
|
|
1897
|
-
setIsUploading(false);
|
|
1898
|
-
}
|
|
1899
|
-
case 2:
|
|
1900
|
-
return _context4.a(2);
|
|
1421
|
+
const handleInput = useCallback(() => {
|
|
1422
|
+
if (editorRef.current) {
|
|
1423
|
+
const next = editorRef.current.innerHTML;
|
|
1424
|
+
setHtml(next);
|
|
1425
|
+
lastSynchronizedHtmlRef.current = next;
|
|
1426
|
+
onChange && onChange(next);
|
|
1427
|
+
updateMetrics();
|
|
1428
|
+
}
|
|
1429
|
+
}, [onChange, updateMetrics]);
|
|
1430
|
+
const handleImageUpload = async e => {
|
|
1431
|
+
const file = e.target.files[0];
|
|
1432
|
+
if (!file) return;
|
|
1433
|
+
try {
|
|
1434
|
+
setIsUploading(true);
|
|
1435
|
+
const uploadPromise = onImageUpload ? onImageUpload(file) : readFileAsDataURL(file);
|
|
1436
|
+
uploadPromise.then(url => {
|
|
1437
|
+
if (url) {
|
|
1438
|
+
const finalUrl = typeof url === 'object' && url !== null && url.mediaUrl ? url.mediaUrl : url;
|
|
1439
|
+
insertImage(finalUrl, file.name);
|
|
1901
1440
|
}
|
|
1902
|
-
|
|
1903
|
-
|
|
1904
|
-
|
|
1905
|
-
|
|
1906
|
-
|
|
1907
|
-
|
|
1908
|
-
|
|
1441
|
+
setIsUploading(false);
|
|
1442
|
+
e.target.value = null;
|
|
1443
|
+
}).catch(error => {
|
|
1444
|
+
console.error('Error uploading image:', error);
|
|
1445
|
+
setIsUploading(false);
|
|
1446
|
+
});
|
|
1447
|
+
} catch (error) {
|
|
1448
|
+
console.error('Error uploading image:', error);
|
|
1449
|
+
setIsUploading(false);
|
|
1450
|
+
}
|
|
1451
|
+
};
|
|
1452
|
+
useEffect(() => {
|
|
1909
1453
|
// If disabled is explicitly false, make sure the editor is not editable
|
|
1910
1454
|
if (disabled === true) {
|
|
1911
1455
|
setEditable(false);
|
|
1912
1456
|
}
|
|
1913
1457
|
}, [disabled]);
|
|
1914
|
-
|
|
1915
|
-
setSelectionVersion(
|
|
1916
|
-
return v + 1;
|
|
1917
|
-
});
|
|
1458
|
+
const handleEditorClick = useCallback(e => {
|
|
1459
|
+
setSelectionVersion(v => v + 1);
|
|
1918
1460
|
// Check if the click is on a link
|
|
1919
|
-
|
|
1461
|
+
const clickedLink = e.target.closest('a');
|
|
1920
1462
|
if (clickedLink) {
|
|
1921
1463
|
e.preventDefault();
|
|
1922
1464
|
e.stopPropagation();
|
|
@@ -1925,11 +1467,10 @@ function RichTextEditor(_ref) {
|
|
|
1925
1467
|
}
|
|
1926
1468
|
|
|
1927
1469
|
// NEW: Check if click is on an image for resizing
|
|
1928
|
-
|
|
1470
|
+
const clickedImg = e.target.closest('img');
|
|
1929
1471
|
if (clickedImg && !clickedImg.closest('.rte-modal')) {
|
|
1930
1472
|
setSelectedImage(clickedImg);
|
|
1931
|
-
|
|
1932
|
-
} else if (!e.target.closest('.resize-handle')) {
|
|
1473
|
+
} else if (!e.target.closest('.rte-image-toolbar')) {
|
|
1933
1474
|
setSelectedImage(null);
|
|
1934
1475
|
}
|
|
1935
1476
|
|
|
@@ -1942,119 +1483,81 @@ function RichTextEditor(_ref) {
|
|
|
1942
1483
|
// Only allow setting editable to true if not disabled
|
|
1943
1484
|
if (!editable && disabled !== true) {
|
|
1944
1485
|
setEditable(true);
|
|
1945
|
-
setTimeout(
|
|
1486
|
+
setTimeout(() => {
|
|
1946
1487
|
if (editorRef.current) {
|
|
1947
1488
|
editorRef.current.focus();
|
|
1948
1489
|
}
|
|
1949
1490
|
}, 0);
|
|
1950
1491
|
}
|
|
1951
1492
|
}, [editable, disabled]);
|
|
1952
|
-
|
|
1953
|
-
|
|
1954
|
-
|
|
1955
|
-
|
|
1956
|
-
|
|
1957
|
-
|
|
1958
|
-
|
|
1959
|
-
|
|
1960
|
-
|
|
1961
|
-
|
|
1962
|
-
|
|
1963
|
-
|
|
1964
|
-
|
|
1965
|
-
|
|
1966
|
-
|
|
1967
|
-
|
|
1968
|
-
img.style.height = "".concat(newHeight, "px");
|
|
1969
|
-
setResizeData({}); // Force re-render of handles
|
|
1970
|
-
};
|
|
1971
|
-
var _onMouseUp = function onMouseUp() {
|
|
1972
|
-
document.removeEventListener('mousemove', onMouseMove);
|
|
1973
|
-
document.removeEventListener('mouseup', _onMouseUp);
|
|
1974
|
-
triggerChange();
|
|
1975
|
-
};
|
|
1976
|
-
document.addEventListener('mousemove', onMouseMove);
|
|
1977
|
-
document.addEventListener('mouseup', _onMouseUp);
|
|
1978
|
-
};
|
|
1979
|
-
var renderResizeHandles = function renderResizeHandles() {
|
|
1980
|
-
if (!selectedImage || !editorRef.current) return null;
|
|
1981
|
-
var editorRect = editorRef.current.getBoundingClientRect();
|
|
1982
|
-
var imgRect = selectedImage.getBoundingClientRect();
|
|
1983
|
-
|
|
1984
|
-
// Relative position within editorRef using the more robust BoundingClientRect
|
|
1985
|
-
var top = imgRect.top - editorRect.top + editorRef.current.scrollTop;
|
|
1986
|
-
var left = imgRect.left - editorRect.left + editorRef.current.scrollLeft;
|
|
1987
|
-
var width = imgRect.width;
|
|
1988
|
-
var height = imgRect.height;
|
|
1989
|
-
var handleStyles = {
|
|
1990
|
-
position: 'absolute',
|
|
1991
|
-
width: '10px',
|
|
1992
|
-
height: '10px',
|
|
1993
|
-
background: '#3b82f6',
|
|
1994
|
-
border: '2px solid white',
|
|
1995
|
-
borderRadius: '50%',
|
|
1996
|
-
zIndex: 100
|
|
1997
|
-
};
|
|
1998
|
-
var handles = [{
|
|
1999
|
-
id: 'nw',
|
|
2000
|
-
style: {
|
|
2001
|
-
top: top - 5,
|
|
2002
|
-
left: left - 5,
|
|
2003
|
-
cursor: 'nw-resize'
|
|
1493
|
+
const renderImageToolbar = () => {
|
|
1494
|
+
if (!selectedImage || !editorRef.current || !editable) return null;
|
|
1495
|
+
const editorRect = editorRef.current.getBoundingClientRect();
|
|
1496
|
+
const imgRect = selectedImage.getBoundingClientRect();
|
|
1497
|
+
const top = imgRect.top - editorRect.top + editorRef.current.scrollTop;
|
|
1498
|
+
const left = imgRect.left - editorRect.left + editorRef.current.scrollLeft;
|
|
1499
|
+
const width = imgRect.width;
|
|
1500
|
+
const handleAlignment = align => {
|
|
1501
|
+
const wrapper = selectedImage.closest('.image-container');
|
|
1502
|
+
if (wrapper) {
|
|
1503
|
+
// Remove all alignment classes first
|
|
1504
|
+
wrapper.classList.remove('image-align-left', 'image-align-center', 'image-align-right');
|
|
1505
|
+
// Add the new alignment class
|
|
1506
|
+
wrapper.classList.add(`image-align-${align}`);
|
|
1507
|
+
selectedImage.setAttribute('data-align', align);
|
|
1508
|
+
triggerChange();
|
|
2004
1509
|
}
|
|
2005
|
-
}
|
|
2006
|
-
|
|
2007
|
-
|
|
2008
|
-
|
|
2009
|
-
|
|
2010
|
-
|
|
2011
|
-
|
|
2012
|
-
}, {
|
|
2013
|
-
id: 'sw',
|
|
2014
|
-
style: {
|
|
2015
|
-
top: top + height - 5,
|
|
2016
|
-
left: left - 5,
|
|
2017
|
-
cursor: 'sw-resize'
|
|
1510
|
+
};
|
|
1511
|
+
const removeImage = () => {
|
|
1512
|
+
const wrapper = selectedImage.closest('.image-container');
|
|
1513
|
+
if (wrapper) {
|
|
1514
|
+
wrapper.remove();
|
|
1515
|
+
setSelectedImage(null);
|
|
1516
|
+
triggerChange();
|
|
2018
1517
|
}
|
|
2019
|
-
}
|
|
2020
|
-
|
|
2021
|
-
|
|
2022
|
-
|
|
2023
|
-
|
|
2024
|
-
|
|
1518
|
+
};
|
|
1519
|
+
const toggleSize = () => {
|
|
1520
|
+
const wrapper = selectedImage.closest('.image-container');
|
|
1521
|
+
if (wrapper) {
|
|
1522
|
+
const isSmall = wrapper.classList.contains('image-small');
|
|
1523
|
+
if (isSmall) {
|
|
1524
|
+
wrapper.classList.remove('image-small');
|
|
1525
|
+
} else {
|
|
1526
|
+
wrapper.classList.add('image-small');
|
|
1527
|
+
}
|
|
1528
|
+
triggerChange();
|
|
2025
1529
|
}
|
|
2026
|
-
}
|
|
1530
|
+
};
|
|
2027
1531
|
return /*#__PURE__*/React.createElement("div", {
|
|
1532
|
+
className: "rte-image-toolbar",
|
|
2028
1533
|
style: {
|
|
2029
1534
|
position: 'absolute',
|
|
2030
|
-
top: 0,
|
|
2031
|
-
left: 0,
|
|
2032
|
-
|
|
2033
|
-
height: '100%',
|
|
2034
|
-
pointerEvents: 'none'
|
|
2035
|
-
}
|
|
2036
|
-
}, /*#__PURE__*/React.createElement("div", {
|
|
2037
|
-
style: {
|
|
2038
|
-
position: 'absolute',
|
|
2039
|
-
top: top,
|
|
2040
|
-
left: left,
|
|
2041
|
-
width: width,
|
|
2042
|
-
height: height,
|
|
2043
|
-
border: '2px solid #3b82f6',
|
|
2044
|
-
pointerEvents: 'none'
|
|
1535
|
+
top: Math.max(0, top - 45),
|
|
1536
|
+
left: Math.max(0, left + width / 2 - 80),
|
|
1537
|
+
zIndex: 1000
|
|
2045
1538
|
}
|
|
2046
|
-
}
|
|
2047
|
-
|
|
2048
|
-
|
|
2049
|
-
|
|
2050
|
-
|
|
2051
|
-
|
|
2052
|
-
|
|
2053
|
-
|
|
2054
|
-
|
|
2055
|
-
|
|
2056
|
-
|
|
2057
|
-
|
|
1539
|
+
}, /*#__PURE__*/React.createElement("button", {
|
|
1540
|
+
type: "button",
|
|
1541
|
+
onClick: () => handleAlignment('left'),
|
|
1542
|
+
title: "Align Left"
|
|
1543
|
+
}, "L"), /*#__PURE__*/React.createElement("button", {
|
|
1544
|
+
type: "button",
|
|
1545
|
+
onClick: () => handleAlignment('center'),
|
|
1546
|
+
title: "Align Center"
|
|
1547
|
+
}, "C"), /*#__PURE__*/React.createElement("button", {
|
|
1548
|
+
type: "button",
|
|
1549
|
+
onClick: () => handleAlignment('right'),
|
|
1550
|
+
title: "Align Right"
|
|
1551
|
+
}, "R"), /*#__PURE__*/React.createElement("button", {
|
|
1552
|
+
type: "button",
|
|
1553
|
+
onClick: toggleSize,
|
|
1554
|
+
title: "Toggle 50% Width"
|
|
1555
|
+
}, "50%"), /*#__PURE__*/React.createElement("button", {
|
|
1556
|
+
type: "button",
|
|
1557
|
+
onClick: removeImage,
|
|
1558
|
+
className: "danger",
|
|
1559
|
+
title: "Remove Image"
|
|
1560
|
+
}, "\xD7"));
|
|
2058
1561
|
};
|
|
2059
1562
|
return /*#__PURE__*/React.createElement("div", {
|
|
2060
1563
|
className: "rte-main-wrapper",
|
|
@@ -2068,21 +1571,21 @@ function RichTextEditor(_ref) {
|
|
|
2068
1571
|
},
|
|
2069
1572
|
className: !showBorder ? "" : "rte-container",
|
|
2070
1573
|
onClick: handleEditorClick,
|
|
2071
|
-
onMouseOver:
|
|
2072
|
-
|
|
1574
|
+
onMouseOver: e => {
|
|
1575
|
+
const table = e.target.closest('table');
|
|
2073
1576
|
if (table && editorRef.current.contains(table)) {
|
|
2074
1577
|
setHoveredTable(table);
|
|
2075
1578
|
}
|
|
2076
1579
|
},
|
|
2077
|
-
onMouseOut:
|
|
2078
|
-
|
|
2079
|
-
|
|
1580
|
+
onMouseOut: e => {
|
|
1581
|
+
const table = e.target.closest('table');
|
|
1582
|
+
const related = e.relatedTarget;
|
|
2080
1583
|
if (table && (!related || !table.contains(related)) && !(related !== null && related !== void 0 && related.closest('.rte-table-delete-hover'))) {
|
|
2081
1584
|
setHoveredTable(null);
|
|
2082
1585
|
}
|
|
2083
1586
|
},
|
|
2084
1587
|
onDrop: handleDrop,
|
|
2085
|
-
onDragOver:
|
|
1588
|
+
onDragOver: e => {
|
|
2086
1589
|
e.preventDefault();
|
|
2087
1590
|
e.stopPropagation();
|
|
2088
1591
|
}
|
|
@@ -2091,40 +1594,40 @@ function RichTextEditor(_ref) {
|
|
|
2091
1594
|
}, /*#__PURE__*/React.createElement("button", {
|
|
2092
1595
|
type: "button",
|
|
2093
1596
|
title: "Bold",
|
|
2094
|
-
onClick:
|
|
1597
|
+
onClick: e => {
|
|
2095
1598
|
e.preventDefault();
|
|
2096
1599
|
e.stopPropagation();
|
|
2097
1600
|
document.execCommand("bold");
|
|
2098
1601
|
handleInput();
|
|
2099
1602
|
focus();
|
|
2100
1603
|
},
|
|
2101
|
-
className:
|
|
1604
|
+
className: `rte-toolbar-button ${isBold ? "active" : ""}`
|
|
2102
1605
|
}, /*#__PURE__*/React.createElement(FaBold, {
|
|
2103
1606
|
size: 14
|
|
2104
1607
|
})), /*#__PURE__*/React.createElement("button", {
|
|
2105
1608
|
type: "button",
|
|
2106
1609
|
title: "Italic",
|
|
2107
|
-
onClick:
|
|
1610
|
+
onClick: e => {
|
|
2108
1611
|
e.preventDefault();
|
|
2109
1612
|
e.stopPropagation();
|
|
2110
1613
|
document.execCommand("italic");
|
|
2111
1614
|
handleInput();
|
|
2112
1615
|
focus();
|
|
2113
1616
|
},
|
|
2114
|
-
className:
|
|
1617
|
+
className: `rte-toolbar-button ${isItalic ? "active" : ""}`
|
|
2115
1618
|
}, /*#__PURE__*/React.createElement(FaItalic, {
|
|
2116
1619
|
size: 14
|
|
2117
1620
|
})), /*#__PURE__*/React.createElement("button", {
|
|
2118
1621
|
type: "button",
|
|
2119
1622
|
title: "Underline",
|
|
2120
|
-
onClick:
|
|
1623
|
+
onClick: e => {
|
|
2121
1624
|
e.preventDefault();
|
|
2122
1625
|
e.stopPropagation();
|
|
2123
1626
|
document.execCommand("underline");
|
|
2124
1627
|
handleInput();
|
|
2125
1628
|
focus();
|
|
2126
1629
|
},
|
|
2127
|
-
className:
|
|
1630
|
+
className: `rte-toolbar-button ${isUnderline ? "active" : ""}`
|
|
2128
1631
|
}, /*#__PURE__*/React.createElement(FaUnderline, {
|
|
2129
1632
|
size: 14
|
|
2130
1633
|
})), /*#__PURE__*/React.createElement("div", {
|
|
@@ -2136,13 +1639,11 @@ function RichTextEditor(_ref) {
|
|
|
2136
1639
|
}
|
|
2137
1640
|
}), /*#__PURE__*/React.createElement("select", {
|
|
2138
1641
|
value: currentFontSize,
|
|
2139
|
-
onMouseDown:
|
|
2140
|
-
|
|
2141
|
-
},
|
|
2142
|
-
onChange: function onChange(e) {
|
|
1642
|
+
onMouseDown: e => e.stopPropagation(),
|
|
1643
|
+
onChange: e => {
|
|
2143
1644
|
e.preventDefault();
|
|
2144
1645
|
e.stopPropagation();
|
|
2145
|
-
|
|
1646
|
+
const size = e.target.value;
|
|
2146
1647
|
if (!size) return;
|
|
2147
1648
|
applyFontSize(size);
|
|
2148
1649
|
setCurrentFontSize(size);
|
|
@@ -2152,12 +1653,10 @@ function RichTextEditor(_ref) {
|
|
|
2152
1653
|
style: {
|
|
2153
1654
|
width: '70px'
|
|
2154
1655
|
}
|
|
2155
|
-
}, [8, 10, 12, 14, 16, 18, 20, 24, 28, 32, 36, 40, 48].map(
|
|
2156
|
-
|
|
2157
|
-
|
|
2158
|
-
|
|
2159
|
-
}, s, "px");
|
|
2160
|
-
})), /*#__PURE__*/React.createElement("label", {
|
|
1656
|
+
}, [8, 10, 12, 14, 16, 18, 20, 24, 28, 32, 36, 40, 48].map(s => /*#__PURE__*/React.createElement("option", {
|
|
1657
|
+
key: s,
|
|
1658
|
+
value: s
|
|
1659
|
+
}, s, "px"))), /*#__PURE__*/React.createElement("label", {
|
|
2161
1660
|
title: "Font Color",
|
|
2162
1661
|
className: "rte-color-picker-label"
|
|
2163
1662
|
}, /*#__PURE__*/React.createElement(FaFont, {
|
|
@@ -2168,11 +1667,11 @@ function RichTextEditor(_ref) {
|
|
|
2168
1667
|
}), /*#__PURE__*/React.createElement("input", {
|
|
2169
1668
|
type: "color",
|
|
2170
1669
|
value: fontColor,
|
|
2171
|
-
onMouseDown:
|
|
1670
|
+
onMouseDown: e => {
|
|
2172
1671
|
e.preventDefault();
|
|
2173
1672
|
e.stopPropagation();
|
|
2174
1673
|
},
|
|
2175
|
-
onChange:
|
|
1674
|
+
onChange: e => {
|
|
2176
1675
|
e.stopPropagation();
|
|
2177
1676
|
handleColorChange(e.target.value);
|
|
2178
1677
|
},
|
|
@@ -2187,8 +1686,8 @@ function RichTextEditor(_ref) {
|
|
|
2187
1686
|
}), /*#__PURE__*/React.createElement("button", {
|
|
2188
1687
|
type: "button",
|
|
2189
1688
|
title: "Align Left",
|
|
2190
|
-
className:
|
|
2191
|
-
onMouseDown:
|
|
1689
|
+
className: `rte-toolbar-button ${activeAlign === "left" ? "active" : ""}`,
|
|
1690
|
+
onMouseDown: e => {
|
|
2192
1691
|
e.preventDefault();
|
|
2193
1692
|
exec("justifyLeft");
|
|
2194
1693
|
setActiveAlign("left");
|
|
@@ -2198,8 +1697,8 @@ function RichTextEditor(_ref) {
|
|
|
2198
1697
|
})), /*#__PURE__*/React.createElement("button", {
|
|
2199
1698
|
type: "button",
|
|
2200
1699
|
title: "Align Center",
|
|
2201
|
-
className:
|
|
2202
|
-
onMouseDown:
|
|
1700
|
+
className: `rte-toolbar-button ${activeAlign === "center" ? "active" : ""}`,
|
|
1701
|
+
onMouseDown: e => {
|
|
2203
1702
|
e.preventDefault();
|
|
2204
1703
|
exec("justifyCenter");
|
|
2205
1704
|
setActiveAlign("center");
|
|
@@ -2209,8 +1708,8 @@ function RichTextEditor(_ref) {
|
|
|
2209
1708
|
})), /*#__PURE__*/React.createElement("button", {
|
|
2210
1709
|
type: "button",
|
|
2211
1710
|
title: "Align Right",
|
|
2212
|
-
className:
|
|
2213
|
-
onMouseDown:
|
|
1711
|
+
className: `rte-toolbar-button ${activeAlign === "right" ? "active" : ""}`,
|
|
1712
|
+
onMouseDown: e => {
|
|
2214
1713
|
e.preventDefault();
|
|
2215
1714
|
exec("justifyRight");
|
|
2216
1715
|
setActiveAlign("right");
|
|
@@ -2227,21 +1726,21 @@ function RichTextEditor(_ref) {
|
|
|
2227
1726
|
}), /*#__PURE__*/React.createElement("button", {
|
|
2228
1727
|
type: "button",
|
|
2229
1728
|
title: "Unordered List",
|
|
2230
|
-
onMouseDown:
|
|
1729
|
+
onMouseDown: e => {
|
|
2231
1730
|
e.preventDefault();
|
|
2232
1731
|
handleSelect("unordered");
|
|
2233
1732
|
},
|
|
2234
|
-
className:
|
|
1733
|
+
className: `rte-toolbar-button ${currentListType === "unordered" ? "active" : ""}`
|
|
2235
1734
|
}, /*#__PURE__*/React.createElement(FaListUl, {
|
|
2236
1735
|
size: 14
|
|
2237
1736
|
})), /*#__PURE__*/React.createElement("button", {
|
|
2238
1737
|
type: "button",
|
|
2239
1738
|
title: "Ordered List",
|
|
2240
|
-
onMouseDown:
|
|
1739
|
+
onMouseDown: e => {
|
|
2241
1740
|
e.preventDefault();
|
|
2242
1741
|
handleSelect("ordered");
|
|
2243
1742
|
},
|
|
2244
|
-
className:
|
|
1743
|
+
className: `rte-toolbar-button ${currentListType === "ordered" ? "active" : ""}`
|
|
2245
1744
|
}, /*#__PURE__*/React.createElement(FaListOl, {
|
|
2246
1745
|
size: 14
|
|
2247
1746
|
})), /*#__PURE__*/React.createElement("div", {
|
|
@@ -2252,12 +1751,10 @@ function RichTextEditor(_ref) {
|
|
|
2252
1751
|
}
|
|
2253
1752
|
}, /*#__PURE__*/React.createElement("select", {
|
|
2254
1753
|
value: currentLineHeight,
|
|
2255
|
-
onMouseDown:
|
|
2256
|
-
|
|
2257
|
-
},
|
|
2258
|
-
onChange: function onChange(e) {
|
|
1754
|
+
onMouseDown: e => e.stopPropagation(),
|
|
1755
|
+
onChange: e => {
|
|
2259
1756
|
e.preventDefault();
|
|
2260
|
-
|
|
1757
|
+
const height = e.target.value;
|
|
2261
1758
|
if (height) {
|
|
2262
1759
|
onLineHeightChange(height);
|
|
2263
1760
|
setCurrentLineHeight(height);
|
|
@@ -2272,12 +1769,10 @@ function RichTextEditor(_ref) {
|
|
|
2272
1769
|
}, /*#__PURE__*/React.createElement("option", {
|
|
2273
1770
|
value: "",
|
|
2274
1771
|
disabled: true
|
|
2275
|
-
}, "\u2195"), ['1', '1.15', '1.5', '2'].map(
|
|
2276
|
-
|
|
2277
|
-
|
|
2278
|
-
|
|
2279
|
-
}, h);
|
|
2280
|
-
})), /*#__PURE__*/React.createElement("div", {
|
|
1772
|
+
}, "\u2195"), ['1', '1.15', '1.5', '2'].map(h => /*#__PURE__*/React.createElement("option", {
|
|
1773
|
+
key: h,
|
|
1774
|
+
value: h
|
|
1775
|
+
}, h))), /*#__PURE__*/React.createElement("div", {
|
|
2281
1776
|
style: {
|
|
2282
1777
|
position: 'absolute',
|
|
2283
1778
|
left: '6px',
|
|
@@ -2304,7 +1799,7 @@ function RichTextEditor(_ref) {
|
|
|
2304
1799
|
type: "button",
|
|
2305
1800
|
title: "Add Link",
|
|
2306
1801
|
className: "rte-toolbar-button",
|
|
2307
|
-
onMouseDown:
|
|
1802
|
+
onMouseDown: e => {
|
|
2308
1803
|
e.preventDefault();
|
|
2309
1804
|
addLink();
|
|
2310
1805
|
}
|
|
@@ -2324,7 +1819,7 @@ function RichTextEditor(_ref) {
|
|
|
2324
1819
|
}), /*#__PURE__*/React.createElement("button", {
|
|
2325
1820
|
type: "button",
|
|
2326
1821
|
className: "rte-toolbar-button",
|
|
2327
|
-
onMouseDown:
|
|
1822
|
+
onMouseDown: e => {
|
|
2328
1823
|
var _fileInputRef$current;
|
|
2329
1824
|
e.preventDefault();
|
|
2330
1825
|
if (!isUploading) (_fileInputRef$current = fileInputRef.current) === null || _fileInputRef$current === void 0 || _fileInputRef$current.click();
|
|
@@ -2351,9 +1846,9 @@ function RichTextEditor(_ref) {
|
|
|
2351
1846
|
type: "button",
|
|
2352
1847
|
title: "Insert Table",
|
|
2353
1848
|
className: "rte-toolbar-button",
|
|
2354
|
-
onMouseDown:
|
|
1849
|
+
onMouseDown: e => {
|
|
2355
1850
|
e.preventDefault();
|
|
2356
|
-
|
|
1851
|
+
const sel = window.getSelection();
|
|
2357
1852
|
if (sel && sel.rangeCount > 0) {
|
|
2358
1853
|
selectionRangeRef.current = sel.getRangeAt(0).cloneRange();
|
|
2359
1854
|
}
|
|
@@ -2364,20 +1859,20 @@ function RichTextEditor(_ref) {
|
|
|
2364
1859
|
})), /*#__PURE__*/React.createElement("button", {
|
|
2365
1860
|
type: "button",
|
|
2366
1861
|
title: "Embed Video (YouTube, Vimeo, etc.)",
|
|
2367
|
-
className:
|
|
2368
|
-
onMouseDown:
|
|
1862
|
+
className: `rte-toolbar-button ${videoModalOpen ? 'active' : ''}`,
|
|
1863
|
+
onMouseDown: e => {
|
|
2369
1864
|
e.preventDefault();
|
|
2370
1865
|
saveSelection();
|
|
2371
1866
|
setVideoModalOpen(true);
|
|
2372
1867
|
}
|
|
2373
1868
|
}, /*#__PURE__*/React.createElement(FaVideo, {
|
|
2374
1869
|
size: 14
|
|
2375
|
-
})),
|
|
1870
|
+
})), (() => {
|
|
2376
1871
|
if (typeof window === "undefined") return null;
|
|
2377
|
-
|
|
1872
|
+
const sel = window.getSelection();
|
|
2378
1873
|
// Robust check: inside cell OR the table itself is selected
|
|
2379
|
-
|
|
2380
|
-
|
|
1874
|
+
const isCell = sel && sel.rangeCount > 0 && sel.anchorNode && (findParentTag(sel.anchorNode, 'TD') || findParentTag(sel.anchorNode, 'TH'));
|
|
1875
|
+
const isTable = sel && sel.rangeCount > 0 && sel.anchorNode && findParentTag(sel.anchorNode, 'TABLE');
|
|
2381
1876
|
if (isCell || isTable) {
|
|
2382
1877
|
return /*#__PURE__*/React.createElement(React.Fragment, null, /*#__PURE__*/React.createElement("div", {
|
|
2383
1878
|
style: {
|
|
@@ -2390,7 +1885,7 @@ function RichTextEditor(_ref) {
|
|
|
2390
1885
|
type: "button",
|
|
2391
1886
|
title: "Add Row Above",
|
|
2392
1887
|
className: "rte-toolbar-button",
|
|
2393
|
-
onMouseDown:
|
|
1888
|
+
onMouseDown: e => {
|
|
2394
1889
|
e.preventDefault();
|
|
2395
1890
|
tableAction('addRowAbove');
|
|
2396
1891
|
}
|
|
@@ -2398,7 +1893,7 @@ function RichTextEditor(_ref) {
|
|
|
2398
1893
|
type: "button",
|
|
2399
1894
|
title: "Add Row Below",
|
|
2400
1895
|
className: "rte-toolbar-button",
|
|
2401
|
-
onMouseDown:
|
|
1896
|
+
onMouseDown: e => {
|
|
2402
1897
|
e.preventDefault();
|
|
2403
1898
|
tableAction('addRowBelow');
|
|
2404
1899
|
}
|
|
@@ -2406,7 +1901,7 @@ function RichTextEditor(_ref) {
|
|
|
2406
1901
|
type: "button",
|
|
2407
1902
|
title: "Add Col Before",
|
|
2408
1903
|
className: "rte-toolbar-button",
|
|
2409
|
-
onMouseDown:
|
|
1904
|
+
onMouseDown: e => {
|
|
2410
1905
|
e.preventDefault();
|
|
2411
1906
|
tableAction('addColBefore');
|
|
2412
1907
|
}
|
|
@@ -2414,7 +1909,7 @@ function RichTextEditor(_ref) {
|
|
|
2414
1909
|
type: "button",
|
|
2415
1910
|
title: "Add Col After",
|
|
2416
1911
|
className: "rte-toolbar-button",
|
|
2417
|
-
onMouseDown:
|
|
1912
|
+
onMouseDown: e => {
|
|
2418
1913
|
e.preventDefault();
|
|
2419
1914
|
tableAction('addColAfter');
|
|
2420
1915
|
}
|
|
@@ -2422,7 +1917,7 @@ function RichTextEditor(_ref) {
|
|
|
2422
1917
|
type: "button",
|
|
2423
1918
|
title: "Merge Cells (Right)",
|
|
2424
1919
|
className: "rte-toolbar-button",
|
|
2425
|
-
onMouseDown:
|
|
1920
|
+
onMouseDown: e => {
|
|
2426
1921
|
e.preventDefault();
|
|
2427
1922
|
tableAction('mergeRight');
|
|
2428
1923
|
}
|
|
@@ -2437,7 +1932,7 @@ function RichTextEditor(_ref) {
|
|
|
2437
1932
|
type: "button",
|
|
2438
1933
|
title: "Delete Row",
|
|
2439
1934
|
className: "rte-toolbar-button rte-toolbar-button-danger",
|
|
2440
|
-
onMouseDown:
|
|
1935
|
+
onMouseDown: e => {
|
|
2441
1936
|
e.preventDefault();
|
|
2442
1937
|
tableAction('deleteRow');
|
|
2443
1938
|
}
|
|
@@ -2451,7 +1946,7 @@ function RichTextEditor(_ref) {
|
|
|
2451
1946
|
type: "button",
|
|
2452
1947
|
title: "Delete Column",
|
|
2453
1948
|
className: "rte-toolbar-button rte-toolbar-button-danger",
|
|
2454
|
-
onMouseDown:
|
|
1949
|
+
onMouseDown: e => {
|
|
2455
1950
|
e.preventDefault();
|
|
2456
1951
|
tableAction('deleteCol');
|
|
2457
1952
|
}
|
|
@@ -2465,7 +1960,7 @@ function RichTextEditor(_ref) {
|
|
|
2465
1960
|
type: "button",
|
|
2466
1961
|
title: "Delete Table",
|
|
2467
1962
|
className: "rte-toolbar-button rte-toolbar-button-danger",
|
|
2468
|
-
onMouseDown:
|
|
1963
|
+
onMouseDown: e => {
|
|
2469
1964
|
e.preventDefault();
|
|
2470
1965
|
tableAction('deleteTable');
|
|
2471
1966
|
}
|
|
@@ -2478,19 +1973,15 @@ function RichTextEditor(_ref) {
|
|
|
2478
1973
|
}, "Table"))));
|
|
2479
1974
|
}
|
|
2480
1975
|
return null;
|
|
2481
|
-
}()), /*#__PURE__*/React.createElement("div", {
|
|
1976
|
+
})()), /*#__PURE__*/React.createElement("div", {
|
|
2482
1977
|
ref: editorRef,
|
|
2483
1978
|
contentEditable: editable && disabled !== true,
|
|
2484
1979
|
suppressContentEditableWarning: true,
|
|
2485
1980
|
onInput: handleInput,
|
|
2486
1981
|
onPaste: handlePaste,
|
|
2487
1982
|
onDrop: handleDrop,
|
|
2488
|
-
onDragStart:
|
|
2489
|
-
|
|
2490
|
-
},
|
|
2491
|
-
onDragOver: function onDragOver(e) {
|
|
2492
|
-
return e.preventDefault();
|
|
2493
|
-
},
|
|
1983
|
+
onDragStart: e => e.preventDefault(),
|
|
1984
|
+
onDragOver: e => e.preventDefault(),
|
|
2494
1985
|
onKeyDown: handleKeyDown,
|
|
2495
1986
|
onClick: handleEditorClick,
|
|
2496
1987
|
style: {
|
|
@@ -2499,30 +1990,22 @@ function RichTextEditor(_ref) {
|
|
|
2499
1990
|
paddingLeft: paddingLeft || '12px'
|
|
2500
1991
|
},
|
|
2501
1992
|
className: "rte-content"
|
|
2502
|
-
}),
|
|
1993
|
+
}), renderImageToolbar(), /*#__PURE__*/React.createElement("div", {
|
|
2503
1994
|
className: "rte-footer"
|
|
2504
|
-
},
|
|
2505
|
-
|
|
2506
|
-
|
|
2507
|
-
|
|
2508
|
-
|
|
2509
|
-
|
|
2510
|
-
|
|
2511
|
-
|
|
2512
|
-
|
|
2513
|
-
}, /*#__PURE__*/React.createElement("b", null, words), " words"), /*#__PURE__*/React.createElement("span", {
|
|
2514
|
-
className: "rte-footer-separator"
|
|
2515
|
-
}, "\u2022"), /*#__PURE__*/React.createElement("span", {
|
|
2516
|
-
className: "rte-footer-item"
|
|
2517
|
-
}, /*#__PURE__*/React.createElement("b", null, chars), " characters"));
|
|
2518
|
-
}()), linkModalOpen && /*#__PURE__*/React.createElement("div", {
|
|
1995
|
+
}, /*#__PURE__*/React.createElement("div", {
|
|
1996
|
+
className: "rte-footer-content"
|
|
1997
|
+
}, /*#__PURE__*/React.createElement("span", {
|
|
1998
|
+
className: "rte-footer-item"
|
|
1999
|
+
}, /*#__PURE__*/React.createElement("b", null, metrics.words), " words"), /*#__PURE__*/React.createElement("span", {
|
|
2000
|
+
className: "rte-footer-separator"
|
|
2001
|
+
}, "\u2022"), /*#__PURE__*/React.createElement("span", {
|
|
2002
|
+
className: "rte-footer-item"
|
|
2003
|
+
}, /*#__PURE__*/React.createElement("b", null, metrics.chars), " characters"))), linkModalOpen && /*#__PURE__*/React.createElement("div", {
|
|
2519
2004
|
className: "rte-modal-overlay",
|
|
2520
2005
|
onClick: cancelLink
|
|
2521
2006
|
}, /*#__PURE__*/React.createElement("div", {
|
|
2522
2007
|
className: "rte-modal",
|
|
2523
|
-
onClick:
|
|
2524
|
-
return e.stopPropagation();
|
|
2525
|
-
}
|
|
2008
|
+
onClick: e => e.stopPropagation()
|
|
2526
2009
|
}, /*#__PURE__*/React.createElement("h3", {
|
|
2527
2010
|
className: "rte-modal-title"
|
|
2528
2011
|
}, "Insert Link"), /*#__PURE__*/React.createElement("div", {
|
|
@@ -2538,9 +2021,7 @@ function RichTextEditor(_ref) {
|
|
|
2538
2021
|
className: "rte-input",
|
|
2539
2022
|
placeholder: "e.g. Google",
|
|
2540
2023
|
value: linkText,
|
|
2541
|
-
onChange:
|
|
2542
|
-
return setLinkText(e.target.value);
|
|
2543
|
-
}
|
|
2024
|
+
onChange: e => setLinkText(e.target.value)
|
|
2544
2025
|
})), /*#__PURE__*/React.createElement("div", {
|
|
2545
2026
|
className: "rte-form-group"
|
|
2546
2027
|
}, /*#__PURE__*/React.createElement("label", {
|
|
@@ -2550,12 +2031,8 @@ function RichTextEditor(_ref) {
|
|
|
2550
2031
|
className: "rte-input",
|
|
2551
2032
|
placeholder: "https://example.com",
|
|
2552
2033
|
value: linkUrl,
|
|
2553
|
-
onChange:
|
|
2554
|
-
|
|
2555
|
-
},
|
|
2556
|
-
onKeyDown: function onKeyDown(e) {
|
|
2557
|
-
return e.key === 'Enter' && confirmLink();
|
|
2558
|
-
},
|
|
2034
|
+
onChange: e => setLinkUrl(e.target.value),
|
|
2035
|
+
onKeyDown: e => e.key === 'Enter' && confirmLink(),
|
|
2559
2036
|
autoFocus: true
|
|
2560
2037
|
}))), /*#__PURE__*/React.createElement("div", {
|
|
2561
2038
|
className: "rte-modal-divider",
|
|
@@ -2575,14 +2052,10 @@ function RichTextEditor(_ref) {
|
|
|
2575
2052
|
disabled: !linkUrl
|
|
2576
2053
|
}, "Insert")))), tableModalOpen && /*#__PURE__*/React.createElement("div", {
|
|
2577
2054
|
className: "rte-modal-overlay",
|
|
2578
|
-
onClick:
|
|
2579
|
-
return setTableModalOpen(false);
|
|
2580
|
-
}
|
|
2055
|
+
onClick: () => setTableModalOpen(false)
|
|
2581
2056
|
}, /*#__PURE__*/React.createElement("div", {
|
|
2582
2057
|
className: "rte-modal",
|
|
2583
|
-
onClick:
|
|
2584
|
-
return e.stopPropagation();
|
|
2585
|
-
}
|
|
2058
|
+
onClick: e => e.stopPropagation()
|
|
2586
2059
|
}, /*#__PURE__*/React.createElement("h3", {
|
|
2587
2060
|
className: "rte-modal-title"
|
|
2588
2061
|
}, "Insert Table"), /*#__PURE__*/React.createElement("div", {
|
|
@@ -2593,9 +2066,7 @@ function RichTextEditor(_ref) {
|
|
|
2593
2066
|
type: "number",
|
|
2594
2067
|
className: "rte-input",
|
|
2595
2068
|
value: tableRows,
|
|
2596
|
-
onChange:
|
|
2597
|
-
return setTableRows(e.target.value);
|
|
2598
|
-
},
|
|
2069
|
+
onChange: e => setTableRows(e.target.value),
|
|
2599
2070
|
min: "1",
|
|
2600
2071
|
max: "10"
|
|
2601
2072
|
})), /*#__PURE__*/React.createElement("div", {
|
|
@@ -2606,9 +2077,7 @@ function RichTextEditor(_ref) {
|
|
|
2606
2077
|
type: "number",
|
|
2607
2078
|
className: "rte-input",
|
|
2608
2079
|
value: tableCols,
|
|
2609
|
-
onChange:
|
|
2610
|
-
return setTableCols(e.target.value);
|
|
2611
|
-
},
|
|
2080
|
+
onChange: e => setTableCols(e.target.value),
|
|
2612
2081
|
min: "1",
|
|
2613
2082
|
max: "10"
|
|
2614
2083
|
})), /*#__PURE__*/React.createElement("div", {
|
|
@@ -2616,23 +2085,17 @@ function RichTextEditor(_ref) {
|
|
|
2616
2085
|
}, /*#__PURE__*/React.createElement("button", {
|
|
2617
2086
|
type: "button",
|
|
2618
2087
|
className: "rte-button rte-button-secondary",
|
|
2619
|
-
onClick:
|
|
2620
|
-
return setTableModalOpen(false);
|
|
2621
|
-
}
|
|
2088
|
+
onClick: () => setTableModalOpen(false)
|
|
2622
2089
|
}, "Cancel"), /*#__PURE__*/React.createElement("button", {
|
|
2623
2090
|
type: "button",
|
|
2624
2091
|
className: "rte-button rte-button-primary",
|
|
2625
2092
|
onClick: insertTable
|
|
2626
2093
|
}, "Insert")))), videoModalOpen && /*#__PURE__*/React.createElement("div", {
|
|
2627
2094
|
className: "rte-modal-overlay",
|
|
2628
|
-
onClick:
|
|
2629
|
-
return setVideoModalOpen(false);
|
|
2630
|
-
}
|
|
2095
|
+
onClick: () => setVideoModalOpen(false)
|
|
2631
2096
|
}, /*#__PURE__*/React.createElement("div", {
|
|
2632
2097
|
className: "rte-modal",
|
|
2633
|
-
onClick:
|
|
2634
|
-
return e.stopPropagation();
|
|
2635
|
-
}
|
|
2098
|
+
onClick: e => e.stopPropagation()
|
|
2636
2099
|
}, /*#__PURE__*/React.createElement("div", {
|
|
2637
2100
|
className: "rte-modal-header"
|
|
2638
2101
|
}, /*#__PURE__*/React.createElement("h3", {
|
|
@@ -2649,12 +2112,10 @@ function RichTextEditor(_ref) {
|
|
|
2649
2112
|
type: "text",
|
|
2650
2113
|
className: "rte-input",
|
|
2651
2114
|
value: videoUrl,
|
|
2652
|
-
onChange:
|
|
2653
|
-
return setVideoUrl(e.target.value);
|
|
2654
|
-
},
|
|
2115
|
+
onChange: e => setVideoUrl(e.target.value),
|
|
2655
2116
|
placeholder: "Paste URL here...",
|
|
2656
2117
|
autoFocus: true,
|
|
2657
|
-
onKeyDown:
|
|
2118
|
+
onKeyDown: e => {
|
|
2658
2119
|
if (e.key === 'Enter' && videoUrl.trim()) insertVideo();
|
|
2659
2120
|
if (e.key === 'Escape') setVideoModalOpen(false);
|
|
2660
2121
|
}
|
|
@@ -2663,13 +2124,11 @@ function RichTextEditor(_ref) {
|
|
|
2663
2124
|
}, /*#__PURE__*/React.createElement("button", {
|
|
2664
2125
|
type: "button",
|
|
2665
2126
|
className: "rte-button rte-button-secondary",
|
|
2666
|
-
onClick:
|
|
2667
|
-
return setVideoModalOpen(false);
|
|
2668
|
-
}
|
|
2127
|
+
onClick: () => setVideoModalOpen(false)
|
|
2669
2128
|
}, "Cancel"), /*#__PURE__*/React.createElement("button", {
|
|
2670
2129
|
type: "button",
|
|
2671
2130
|
className: "rte-button rte-button-primary",
|
|
2672
|
-
onClick:
|
|
2131
|
+
onClick: () => {
|
|
2673
2132
|
if (videoUrl.trim()) {
|
|
2674
2133
|
insertVideo();
|
|
2675
2134
|
}
|
|
@@ -2684,16 +2143,14 @@ function RichTextEditor(_ref) {
|
|
|
2684
2143
|
maxWidth: "90%",
|
|
2685
2144
|
maxHeight: "90%"
|
|
2686
2145
|
},
|
|
2687
|
-
onClick:
|
|
2688
|
-
return e.stopPropagation();
|
|
2689
|
-
}
|
|
2146
|
+
onClick: e => e.stopPropagation()
|
|
2690
2147
|
}, /*#__PURE__*/React.createElement("img", {
|
|
2691
2148
|
src: selectedImageUrl,
|
|
2692
2149
|
style: {
|
|
2693
2150
|
width: "100%",
|
|
2694
2151
|
maxHeight: "90vh",
|
|
2695
2152
|
borderRadius: '12px',
|
|
2696
|
-
transform:
|
|
2153
|
+
transform: `scale(${zoomLevel})`,
|
|
2697
2154
|
transition: "transform 0.2s ease",
|
|
2698
2155
|
boxShadow: '0 25px 50px -12px rgba(0,0,0,0.5)'
|
|
2699
2156
|
},
|
|
@@ -2708,13 +2165,11 @@ function RichTextEditor(_ref) {
|
|
|
2708
2165
|
}, /*#__PURE__*/React.createElement("button", {
|
|
2709
2166
|
type: "button",
|
|
2710
2167
|
className: "rte-button rte-button-secondary",
|
|
2711
|
-
onClick:
|
|
2712
|
-
return setEditable(false);
|
|
2713
|
-
}
|
|
2168
|
+
onClick: () => setEditable(false)
|
|
2714
2169
|
}, "Cancel"), /*#__PURE__*/React.createElement("button", {
|
|
2715
2170
|
type: "button",
|
|
2716
2171
|
className: "rte-button rte-button-primary",
|
|
2717
|
-
onClick:
|
|
2172
|
+
onClick: () => {
|
|
2718
2173
|
onChange && onChange(html);
|
|
2719
2174
|
setEditable(false);
|
|
2720
2175
|
}
|