react-lite-rich-text-editor 1.1.3 → 1.1.5
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 +1141 -1436
- package/dist/index.cjs.js.map +1 -1
- package/dist/index.esm.js +1139 -1434
- package/dist/index.esm.js.map +1 -1
- package/package.json +8 -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,131 @@ 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;max-width:100%;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:block;line-height:0;margin:16px 0;max-width:100%;width:fit-content}.image-container.image-align-center{margin-left:auto;margin-right:auto}.image-container.image-align-left{margin-left:0;margin-right:auto}.image-container.image-align-right{margin-left:auto;margin-right:0}.image-media-frame{display:block;line-height:0;max-width:100%;position:relative;width:fit-content}.image-media-frame img{border-radius:12px;display:block;height:auto;margin:0;max-width:100%;width:auto}.image-media-frame[style*=width] img{width:100%}.image-media-frame[data-explicit-height=true] img,.image-media-frame[style*=height] img{height:100%;object-fit:contain}.image-container.image-small .image-media-frame 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:none;font-size:18px;font-weight:700;height:26px;justify-content:center;line-height:1;padding:0;pointer-events:none;position:absolute;right:0;top:0;transform:translate(50%,-50%);transition:all .2s cubic-bezier(.4,0,.2,1);width:26px;z-index:50}.rte-content.rte-is-editable.rte-is-focused .image-delete-button,.rte-content.rte-is-editable.rte-is-focused .video-delete-button{display:flex;pointer-events:auto}.image-delete-button:hover{background:#b91c1c;box-shadow:0 10px 15px -3px rgba(0,0,0,.1);transform:translate(50%,-50%) scale(1.1)}.media-resize-handles{inset:0;pointer-events:none;position:absolute;z-index:55}.media-resize-handle{background:#dbeafe;border:2px solid #fff;border-radius:4px;box-shadow:0 1px 3px rgba(15,23,42,.12);pointer-events:auto;position:absolute;z-index:60}.media-resize-handle:hover{background:#bfdbfe}.media-resize-handle-left,.media-resize-handle-right{cursor:ew-resize;height:28px;top:50%;transform:translateY(-50%);width:10px}.media-resize-handle-right{right:-5px}.media-resize-handle-left{left:-5px}.media-resize-handle-bottom,.media-resize-handle-top{cursor:ns-resize;height:10px;left:50%;transform:translateX(-50%);width:28px}.media-resize-handle-top{top:-5px}.media-resize-handle-bottom{bottom:-5px}.video-container .media-resize-handle-right{right:4px}.video-container .media-resize-handle-left{left:4px}.video-container .media-resize-handle-top{top:4px}.video-container .media-resize-handle-bottom{bottom:4px}.video-container .video-delete-button{z-index:70}.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
|
-
|
|
687
|
-
|
|
688
|
-
|
|
689
|
-
|
|
690
|
-
|
|
691
|
-
|
|
692
|
-
|
|
693
|
-
|
|
694
|
-
|
|
695
|
-
|
|
696
|
-
|
|
697
|
-
|
|
698
|
-
|
|
699
|
-
|
|
700
|
-
_useState4 = _slicedToArray(_useState3, 2),
|
|
701
|
-
linkModalOpen = _useState4[0],
|
|
702
|
-
setLinkModalOpen = _useState4[1];
|
|
703
|
-
var _useState5 = useState(""),
|
|
704
|
-
_useState6 = _slicedToArray(_useState5, 2),
|
|
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];
|
|
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
|
+
}) {
|
|
419
|
+
const editorRef = useRef(null);
|
|
420
|
+
const fileInputRef = useRef(null);
|
|
421
|
+
const scrollTopRef = useRef(0);
|
|
422
|
+
const [html, setHtml] = useState("");
|
|
423
|
+
const [linkModalOpen, setLinkModalOpen] = useState(false);
|
|
424
|
+
const [linkUrl, setLinkUrl] = useState("");
|
|
425
|
+
const [linkText, setLinkText] = useState("");
|
|
426
|
+
const selectionRangeRef = useRef(null);
|
|
427
|
+
const [editable, setEditable] = useState(initialEditable);
|
|
428
|
+
const [editorFocused, setEditorFocused] = useState(false);
|
|
429
|
+
const lastSynchronizedHtmlRef = useRef("");
|
|
430
|
+
useEffect(() => {
|
|
431
|
+
setEditable(initialEditable);
|
|
432
|
+
}, [initialEditable]);
|
|
716
433
|
|
|
717
434
|
// NEW: Track current list type for dropdown
|
|
718
|
-
|
|
719
|
-
_useState10 = _slicedToArray(_useState1, 2),
|
|
720
|
-
currentListType = _useState10[0],
|
|
721
|
-
setCurrentListType = _useState10[1];
|
|
435
|
+
const [currentListType, setCurrentListType] = useState(null);
|
|
722
436
|
|
|
723
437
|
// 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];
|
|
438
|
+
const [isBold, setIsBold] = useState(false);
|
|
439
|
+
const [isItalic, setIsItalic] = useState(false);
|
|
440
|
+
const [isUnderline, setIsUnderline] = useState(false);
|
|
736
441
|
|
|
737
442
|
// NEW: Track current font size
|
|
738
|
-
|
|
739
|
-
_useState18 = _slicedToArray(_useState17, 2),
|
|
740
|
-
currentFontSize = _useState18[0],
|
|
741
|
-
setCurrentFontSize = _useState18[1];
|
|
443
|
+
const [currentFontSize, setCurrentFontSize] = useState("16");
|
|
742
444
|
|
|
743
445
|
// 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) {
|
|
446
|
+
const [currentLineHeight, setCurrentLineHeight] = useState("");
|
|
447
|
+
const [activeAlign, setActiveAlign] = useState(null);
|
|
448
|
+
const [imageModalOpen, setImageModalOpen] = useState(false);
|
|
449
|
+
const [selectedImageUrl, setSelectedImageUrl] = useState("");
|
|
450
|
+
const [zoomLevel, setZoomLevel] = useState(1);
|
|
451
|
+
const [isUploading, setIsUploading] = useState(false);
|
|
452
|
+
const [videoModalOpen, setVideoModalOpen] = useState(false);
|
|
453
|
+
const [videoUrl, setVideoUrl] = useState("");
|
|
454
|
+
const [tableModalOpen, setTableModalOpen] = useState(false);
|
|
455
|
+
const [hoveredTable, setHoveredTable] = useState(null);
|
|
456
|
+
const [tableRows, setTableRows] = useState(3);
|
|
457
|
+
const [tableCols, setTableCols] = useState(3);
|
|
458
|
+
const [selectionVersion, setSelectionVersion] = useState(0);
|
|
459
|
+
const [selectedImage, setSelectedImage] = useState(null);
|
|
460
|
+
const [metrics, setMetrics] = useState({
|
|
461
|
+
words: 0,
|
|
462
|
+
chars: 0
|
|
463
|
+
});
|
|
464
|
+
const updateMetrics = useCallback(() => {
|
|
465
|
+
if (!editorRef.current) return;
|
|
466
|
+
// Calculate metrics immediately but outside of render path
|
|
467
|
+
const text = editorRef.current.innerText || "";
|
|
468
|
+
const cleanText = text.replace(/[\n\r]/g, ' ').trim();
|
|
469
|
+
const words = cleanText ? cleanText.split(/\s+/).length : 0;
|
|
470
|
+
const chars = text.length;
|
|
471
|
+
setMetrics({
|
|
472
|
+
words,
|
|
473
|
+
chars
|
|
474
|
+
});
|
|
475
|
+
}, []);
|
|
476
|
+
const openImageModal = url => {
|
|
805
477
|
if (editorRef.current) {
|
|
806
478
|
scrollTopRef.current = editorRef.current.scrollTop;
|
|
807
479
|
}
|
|
808
480
|
setSelectedImageUrl(url);
|
|
809
481
|
setImageModalOpen(true);
|
|
810
482
|
};
|
|
811
|
-
|
|
483
|
+
const closeImageModal = () => {
|
|
812
484
|
setImageModalOpen(false);
|
|
813
485
|
setSelectedImageUrl("");
|
|
814
486
|
setZoomLevel(1);
|
|
815
487
|
};
|
|
816
|
-
|
|
488
|
+
const saveSelection = () => {
|
|
817
489
|
if (typeof window === "undefined") return;
|
|
818
|
-
|
|
490
|
+
const sel = window.getSelection();
|
|
819
491
|
if (sel && sel.rangeCount > 0) {
|
|
820
492
|
selectionRangeRef.current = sel.getRangeAt(0).cloneRange();
|
|
821
493
|
}
|
|
822
494
|
};
|
|
823
|
-
|
|
824
|
-
setZoomLevel(
|
|
825
|
-
return prevZoom + 0.1;
|
|
826
|
-
});
|
|
495
|
+
const handleZoomIn = () => {
|
|
496
|
+
setZoomLevel(prevZoom => prevZoom + 0.1);
|
|
827
497
|
};
|
|
828
|
-
|
|
829
|
-
setZoomLevel(
|
|
830
|
-
return Math.max(0.1, prevZoom - 0.1);
|
|
831
|
-
});
|
|
498
|
+
const handleZoomOut = () => {
|
|
499
|
+
setZoomLevel(prevZoom => Math.max(0.1, prevZoom - 0.1));
|
|
832
500
|
};
|
|
833
501
|
|
|
834
502
|
// Effect to restore scroll position after modal closes
|
|
835
|
-
useEffect(
|
|
503
|
+
useEffect(() => {
|
|
836
504
|
if (!imageModalOpen && editorRef.current) {
|
|
837
505
|
editorRef.current.scrollTop = scrollTopRef.current;
|
|
838
506
|
}
|
|
839
507
|
}, [imageModalOpen]);
|
|
840
|
-
useEffect(
|
|
508
|
+
useEffect(() => {
|
|
841
509
|
if (!imageModalOpen) return;
|
|
842
|
-
|
|
510
|
+
const handleKeyDown = e => {
|
|
843
511
|
if (e.key === 'Escape') {
|
|
844
512
|
closeImageModal();
|
|
845
513
|
}
|
|
846
514
|
};
|
|
847
|
-
|
|
515
|
+
const handleWheel = e => {
|
|
848
516
|
if (e.ctrlKey) {
|
|
849
517
|
e.preventDefault();
|
|
850
518
|
if (e.deltaY < 0) {
|
|
@@ -858,127 +526,96 @@ function RichTextEditor(_ref) {
|
|
|
858
526
|
window.addEventListener('wheel', handleWheel, {
|
|
859
527
|
passive: false
|
|
860
528
|
});
|
|
861
|
-
return
|
|
529
|
+
return () => {
|
|
862
530
|
document.removeEventListener('keydown', handleKeyDown);
|
|
863
531
|
window.removeEventListener('wheel', handleWheel);
|
|
864
532
|
};
|
|
865
533
|
}, [imageModalOpen]);
|
|
866
|
-
useEffect(
|
|
867
|
-
|
|
868
|
-
|
|
869
|
-
setSelectionVersion(function (v) {
|
|
870
|
-
return v + 1;
|
|
871
|
-
});
|
|
872
|
-
var deleteBtn = e.target.closest('button[title="Remove image"]');
|
|
873
|
-
if (deleteBtn && editable) {
|
|
874
|
-
e.preventDefault();
|
|
875
|
-
e.stopPropagation();
|
|
876
|
-
var wrapper = deleteBtn.closest('.image-container');
|
|
877
|
-
if (wrapper && wrapper.parentNode) {
|
|
878
|
-
wrapper.parentNode.removeChild(wrapper);
|
|
879
|
-
triggerChange();
|
|
880
|
-
}
|
|
881
|
-
}
|
|
882
|
-
};
|
|
883
|
-
var editor = editorRef.current;
|
|
884
|
-
if (editor) {
|
|
885
|
-
editor.addEventListener('click', handleClick);
|
|
886
|
-
return function () {
|
|
887
|
-
editor.removeEventListener('click', handleClick);
|
|
888
|
-
};
|
|
889
|
-
}
|
|
890
|
-
}, [editable]);
|
|
891
|
-
useEffect(function () {
|
|
892
|
-
if (editorRef.current && value) {
|
|
893
|
-
requestAnimationFrame(function () {
|
|
894
|
-
return processExistingImages(editorRef.current);
|
|
895
|
-
});
|
|
534
|
+
useEffect(() => {
|
|
535
|
+
if (editorRef.current && value && value !== lastSynchronizedHtmlRef.current) {
|
|
536
|
+
requestAnimationFrame(() => processExistingMedia(editorRef.current));
|
|
896
537
|
}
|
|
897
538
|
}, [value]);
|
|
898
539
|
|
|
899
540
|
// Runs whenever editable changes (toggles delete icon visibility)
|
|
900
|
-
useEffect(
|
|
901
|
-
|
|
902
|
-
|
|
903
|
-
|
|
904
|
-
|
|
905
|
-
|
|
541
|
+
useEffect(() => {
|
|
542
|
+
if (!editable) {
|
|
543
|
+
setEditorFocused(false);
|
|
544
|
+
}
|
|
545
|
+
processExistingMedia(editorRef.current);
|
|
546
|
+
}, [editable]);
|
|
547
|
+
useEffect(() => {
|
|
548
|
+
if (!editorRef.current) return;
|
|
549
|
+
editorRef.current.querySelectorAll(".image-container, .video-container").forEach(container => {
|
|
550
|
+
updateMediaControlVisibility(container);
|
|
551
|
+
});
|
|
552
|
+
}, [editorFocused, editable]);
|
|
553
|
+
useEffect(() => {
|
|
554
|
+
// Only update if value is different from our last known synced state
|
|
555
|
+
if (value && value !== lastSynchronizedHtmlRef.current) {
|
|
906
556
|
try {
|
|
907
|
-
|
|
908
|
-
|
|
909
|
-
|
|
910
|
-
|
|
911
|
-
|
|
912
|
-
editorRef.current.innerHTML = htmlContent;
|
|
913
|
-
}
|
|
557
|
+
let newContent = "";
|
|
558
|
+
|
|
559
|
+
// Check if value is a Draft.js content state
|
|
560
|
+
if (isValidDraftFormat(value)) {
|
|
561
|
+
newContent = draftBlocksToHTML(value);
|
|
914
562
|
} else if (typeof value === 'string') {
|
|
915
|
-
//
|
|
916
|
-
|
|
917
|
-
|
|
918
|
-
|
|
919
|
-
|
|
563
|
+
// If value is already what we have in HTML state, skip unescaping
|
|
564
|
+
if (value === html) {
|
|
565
|
+
lastSynchronizedHtmlRef.current = value;
|
|
566
|
+
return;
|
|
567
|
+
}
|
|
568
|
+
newContent = unescapeHtml(value);
|
|
569
|
+
}
|
|
570
|
+
if (newContent && newContent !== html) {
|
|
571
|
+
lastSynchronizedHtmlRef.current = value;
|
|
572
|
+
setHtml(newContent);
|
|
573
|
+
if (editorRef.current && editorRef.current.innerHTML !== newContent) {
|
|
574
|
+
editorRef.current.innerHTML = newContent;
|
|
920
575
|
}
|
|
576
|
+
requestAnimationFrame(() => processExistingMedia(editorRef.current));
|
|
577
|
+
updateMetrics();
|
|
921
578
|
}
|
|
922
579
|
} catch (e) {
|
|
923
580
|
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
581
|
}
|
|
931
|
-
} else {
|
|
582
|
+
} else if (!value && html) {
|
|
932
583
|
setHtml('');
|
|
584
|
+
lastSynchronizedHtmlRef.current = "";
|
|
933
585
|
if (editorRef.current) {
|
|
934
586
|
editorRef.current.innerHTML = '';
|
|
587
|
+
updateMetrics();
|
|
935
588
|
}
|
|
936
589
|
}
|
|
937
|
-
}, [
|
|
590
|
+
}, [value, initialEditable, updateMetrics]);
|
|
591
|
+
const processExistingMedia = container => {
|
|
592
|
+
if (!container) return;
|
|
593
|
+
processExistingImages(container);
|
|
594
|
+
processExistingVideos(container);
|
|
595
|
+
};
|
|
596
|
+
const getCleanHtml = () => {
|
|
597
|
+
if (!editorRef.current) return "";
|
|
598
|
+
const clone = editorRef.current.cloneNode(true);
|
|
599
|
+
stripEditorChrome(clone);
|
|
600
|
+
return clone.innerHTML;
|
|
601
|
+
};
|
|
938
602
|
|
|
939
|
-
// Call onChange whenever html state updates
|
|
940
|
-
useEffect(function () {
|
|
941
|
-
onChange && onChange(html);
|
|
942
|
-
}, [html, onChange]);
|
|
943
603
|
// Trigger change manually
|
|
944
|
-
|
|
945
|
-
|
|
604
|
+
const triggerChange = useCallback(() => {
|
|
605
|
+
const next = getCleanHtml();
|
|
946
606
|
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
|
-
};
|
|
607
|
+
lastSynchronizedHtmlRef.current = next;
|
|
608
|
+
onChange && onChange(next);
|
|
609
|
+
}, [onChange]);
|
|
970
610
|
|
|
971
611
|
// 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
|
-
}
|
|
612
|
+
const isParentStyle = (node, ...tagNames) => {
|
|
976
613
|
while (node && node !== editorRef.current) {
|
|
977
614
|
if (node.nodeType === 1 && tagNames.includes(node.tagName)) return true;
|
|
978
615
|
|
|
979
616
|
// Also check inline style for bold and italic:
|
|
980
617
|
if (node.nodeType === 1 && node.style) {
|
|
981
|
-
|
|
618
|
+
const style = node.style;
|
|
982
619
|
if (tagNames.includes("bold") && (style.fontWeight === "bold" || Number(style.fontWeight) >= 600)) return true;
|
|
983
620
|
if (tagNames.includes("italic") && style.fontStyle === "italic") return true;
|
|
984
621
|
if (tagNames.includes("underline") && style.textDecoration.includes("underline")) return true;
|
|
@@ -996,100 +633,299 @@ function RichTextEditor(_ref) {
|
|
|
996
633
|
return false;
|
|
997
634
|
};
|
|
998
635
|
|
|
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
636
|
// Helper to convert rgb() to hex
|
|
1038
637
|
function rgbToHex(rgb) {
|
|
1039
|
-
|
|
638
|
+
const result = rgb.match(/\d+/g);
|
|
1040
639
|
if (!result) return "#000000";
|
|
1041
|
-
return "#" + result.slice(0, 3).map(
|
|
1042
|
-
|
|
640
|
+
return "#" + result.slice(0, 3).map(x => {
|
|
641
|
+
const hex = parseInt(x, 10).toString(16);
|
|
1043
642
|
return hex.length === 1 ? "0" + hex : hex;
|
|
1044
643
|
}).join("");
|
|
1045
644
|
}
|
|
645
|
+
const getColorAtCursor = () => {
|
|
646
|
+
const sel = window.getSelection();
|
|
647
|
+
if (!sel || !sel.rangeCount || !editorRef.current) return null;
|
|
648
|
+
let node = sel.anchorNode;
|
|
649
|
+
if (node.nodeType === 3) node = node.parentNode;
|
|
650
|
+
while (node && node !== editorRef.current) {
|
|
651
|
+
if (node.nodeType === 1) {
|
|
652
|
+
if (node.style && node.style.color) {
|
|
653
|
+
return rgbToHex(node.style.color);
|
|
654
|
+
}
|
|
655
|
+
if (node.tagName === "FONT" && node.getAttribute("color")) {
|
|
656
|
+
return node.getAttribute("color");
|
|
657
|
+
}
|
|
658
|
+
}
|
|
659
|
+
node = node.parentNode;
|
|
660
|
+
}
|
|
661
|
+
const computedColor = window.getComputedStyle(sel.anchorNode.nodeType === 3 ? sel.anchorNode.parentNode : sel.anchorNode).color;
|
|
662
|
+
return rgbToHex(computedColor);
|
|
663
|
+
};
|
|
664
|
+
const stripEditorChrome = root => {
|
|
665
|
+
root.querySelectorAll(".image-delete-button, .video-delete-button, .video-edit-overlay, .media-resize-handles, .media-resize-handle").forEach(element => element.remove());
|
|
666
|
+
return root;
|
|
667
|
+
};
|
|
668
|
+
const getMediaSizeLimits = () => {
|
|
669
|
+
const maxWidth = editorRef.current ? editorRef.current.getBoundingClientRect().width - 24 : 800;
|
|
670
|
+
return {
|
|
671
|
+
minWidth: 120,
|
|
672
|
+
minHeight: 80,
|
|
673
|
+
maxWidth,
|
|
674
|
+
maxHeight: 720
|
|
675
|
+
};
|
|
676
|
+
};
|
|
677
|
+
const ensureImageMediaFrame = imageContainer => {
|
|
678
|
+
if (!imageContainer) return null;
|
|
679
|
+
let frame = imageContainer.querySelector(":scope > .image-media-frame");
|
|
680
|
+
if (frame) return frame;
|
|
681
|
+
frame = document.createElement("div");
|
|
682
|
+
frame.className = "image-media-frame";
|
|
683
|
+
["width", "height", "marginLeft", "marginTop", "maxWidth"].forEach(prop => {
|
|
684
|
+
if (imageContainer.style[prop]) {
|
|
685
|
+
frame.style[prop] = imageContainer.style[prop];
|
|
686
|
+
imageContainer.style[prop] = "";
|
|
687
|
+
}
|
|
688
|
+
});
|
|
689
|
+
if (imageContainer.dataset.explicitHeight) {
|
|
690
|
+
frame.dataset.explicitHeight = imageContainer.dataset.explicitHeight;
|
|
691
|
+
delete imageContainer.dataset.explicitHeight;
|
|
692
|
+
}
|
|
693
|
+
const children = Array.from(imageContainer.children);
|
|
694
|
+
imageContainer.appendChild(frame);
|
|
695
|
+
children.forEach(child => frame.appendChild(child));
|
|
696
|
+
return frame;
|
|
697
|
+
};
|
|
698
|
+
const getImageMediaTarget = imageContainer => ensureImageMediaFrame(imageContainer) || imageContainer;
|
|
699
|
+
const applyImageMediaSize = (frame, width, height, edge) => {
|
|
700
|
+
const img = frame.querySelector("img");
|
|
701
|
+
const isVertical = edge === "top" || edge === "bottom";
|
|
702
|
+
frame.style.width = `${Math.round(width)}px`;
|
|
703
|
+
frame.style.maxWidth = "100%";
|
|
704
|
+
if (isVertical) {
|
|
705
|
+
frame.style.height = `${Math.round(height)}px`;
|
|
706
|
+
frame.dataset.explicitHeight = "true";
|
|
707
|
+
if (img) {
|
|
708
|
+
img.style.width = "100%";
|
|
709
|
+
img.style.height = "100%";
|
|
710
|
+
img.style.objectFit = "contain";
|
|
711
|
+
}
|
|
712
|
+
return;
|
|
713
|
+
}
|
|
714
|
+
if (!frame.dataset.explicitHeight) {
|
|
715
|
+
frame.style.height = "";
|
|
716
|
+
}
|
|
717
|
+
if (img) {
|
|
718
|
+
img.style.width = "100%";
|
|
719
|
+
if (frame.dataset.explicitHeight) {
|
|
720
|
+
img.style.height = "100%";
|
|
721
|
+
img.style.objectFit = "contain";
|
|
722
|
+
} else {
|
|
723
|
+
img.style.height = "auto";
|
|
724
|
+
img.style.objectFit = "";
|
|
725
|
+
}
|
|
726
|
+
}
|
|
727
|
+
};
|
|
728
|
+
const applyVideoMediaSize = (container, width, height) => {
|
|
729
|
+
container.style.paddingBottom = "0";
|
|
730
|
+
container.style.width = `${Math.round(width)}px`;
|
|
731
|
+
container.style.maxWidth = "100%";
|
|
732
|
+
container.style.height = `${Math.round(height)}px`;
|
|
733
|
+
};
|
|
734
|
+
const attachMediaResizeHandle = container => {
|
|
735
|
+
if (!container || container.querySelector(".media-resize-handles")) return;
|
|
736
|
+
const isVideo = container.classList.contains("video-container");
|
|
737
|
+
const resizeTarget = isVideo ? container : getImageMediaTarget(container);
|
|
738
|
+
if (!resizeTarget) return;
|
|
739
|
+
const handlesWrapper = document.createElement("div");
|
|
740
|
+
handlesWrapper.className = "media-resize-handles";
|
|
741
|
+
handlesWrapper.setAttribute("contenteditable", "false");
|
|
742
|
+
const edges = [{
|
|
743
|
+
edge: "left",
|
|
744
|
+
title: "Drag to resize width"
|
|
745
|
+
}, {
|
|
746
|
+
edge: "right",
|
|
747
|
+
title: "Drag to resize width"
|
|
748
|
+
}, {
|
|
749
|
+
edge: "top",
|
|
750
|
+
title: "Drag to resize height"
|
|
751
|
+
}, {
|
|
752
|
+
edge: "bottom",
|
|
753
|
+
title: "Drag to resize height"
|
|
754
|
+
}];
|
|
755
|
+
edges.forEach(({
|
|
756
|
+
edge,
|
|
757
|
+
title
|
|
758
|
+
}) => {
|
|
759
|
+
const handle = document.createElement("div");
|
|
760
|
+
handle.className = `media-resize-handle media-resize-handle-${edge}`;
|
|
761
|
+
handle.title = title;
|
|
762
|
+
handle.setAttribute("contenteditable", "false");
|
|
763
|
+
handle.dataset.edge = edge;
|
|
764
|
+
handle.addEventListener("mousedown", event => {
|
|
765
|
+
if (!editable) return;
|
|
766
|
+
event.preventDefault();
|
|
767
|
+
event.stopPropagation();
|
|
768
|
+
const limits = getMediaSizeLimits();
|
|
769
|
+
const rect = resizeTarget.getBoundingClientRect();
|
|
770
|
+
const startX = event.clientX;
|
|
771
|
+
const startY = event.clientY;
|
|
772
|
+
const startWidth = rect.width;
|
|
773
|
+
const startHeight = rect.height;
|
|
774
|
+
const startMarginLeft = Number.parseFloat(resizeTarget.style.marginLeft) || 0;
|
|
775
|
+
const startMarginTop = Number.parseFloat(resizeTarget.style.marginTop) || 0;
|
|
776
|
+
if (isVideo) {
|
|
777
|
+
resizeTarget.style.paddingBottom = "0";
|
|
778
|
+
}
|
|
779
|
+
const onMouseMove = moveEvent => {
|
|
780
|
+
const deltaX = moveEvent.clientX - startX;
|
|
781
|
+
const deltaY = moveEvent.clientY - startY;
|
|
782
|
+
let nextWidth = startWidth;
|
|
783
|
+
let nextHeight = startHeight;
|
|
784
|
+
if (edge === "right") {
|
|
785
|
+
nextWidth = startWidth + deltaX;
|
|
786
|
+
} else if (edge === "left") {
|
|
787
|
+
nextWidth = startWidth - deltaX;
|
|
788
|
+
} else if (edge === "bottom") {
|
|
789
|
+
nextHeight = startHeight + deltaY;
|
|
790
|
+
} else if (edge === "top") {
|
|
791
|
+
nextHeight = startHeight - deltaY;
|
|
792
|
+
}
|
|
793
|
+
nextWidth = Math.max(limits.minWidth, Math.min(nextWidth, limits.maxWidth));
|
|
794
|
+
nextHeight = Math.max(limits.minHeight, Math.min(nextHeight, limits.maxHeight));
|
|
795
|
+
if (edge === "left") {
|
|
796
|
+
resizeTarget.style.marginLeft = `${Math.round(startMarginLeft + (startWidth - nextWidth))}px`;
|
|
797
|
+
}
|
|
798
|
+
if (edge === "top") {
|
|
799
|
+
resizeTarget.style.marginTop = `${Math.round(startMarginTop + (startHeight - nextHeight))}px`;
|
|
800
|
+
}
|
|
801
|
+
if (isVideo) {
|
|
802
|
+
applyVideoMediaSize(resizeTarget, nextWidth, nextHeight);
|
|
803
|
+
} else {
|
|
804
|
+
applyImageMediaSize(resizeTarget, nextWidth, nextHeight, edge);
|
|
805
|
+
}
|
|
806
|
+
};
|
|
807
|
+
const onMouseUp = () => {
|
|
808
|
+
document.removeEventListener("mousemove", onMouseMove);
|
|
809
|
+
document.removeEventListener("mouseup", onMouseUp);
|
|
810
|
+
triggerChange();
|
|
811
|
+
};
|
|
812
|
+
document.addEventListener("mousemove", onMouseMove);
|
|
813
|
+
document.addEventListener("mouseup", onMouseUp);
|
|
814
|
+
});
|
|
815
|
+
handlesWrapper.appendChild(handle);
|
|
816
|
+
});
|
|
817
|
+
resizeTarget.appendChild(handlesWrapper);
|
|
818
|
+
};
|
|
819
|
+
const handleEditorFocus = () => {
|
|
820
|
+
setEditorFocused(true);
|
|
821
|
+
};
|
|
822
|
+
const handleEditorBlur = () => {
|
|
823
|
+
requestAnimationFrame(() => {
|
|
824
|
+
var _editorRef$current;
|
|
825
|
+
if (!((_editorRef$current = editorRef.current) !== null && _editorRef$current !== void 0 && _editorRef$current.contains(document.activeElement))) {
|
|
826
|
+
setEditorFocused(false);
|
|
827
|
+
}
|
|
828
|
+
});
|
|
829
|
+
};
|
|
830
|
+
const updateMediaControlVisibility = container => {
|
|
831
|
+
const handles = container.querySelector(".media-resize-handles");
|
|
832
|
+
if (handles instanceof HTMLElement) {
|
|
833
|
+
handles.style.display = editable ? "block" : "none";
|
|
834
|
+
handles.style.pointerEvents = editable ? "auto" : "none";
|
|
835
|
+
}
|
|
836
|
+
};
|
|
837
|
+
const createMediaDeleteButton = (title, className, onRemove) => {
|
|
838
|
+
const deleteBtn = document.createElement("button");
|
|
839
|
+
deleteBtn.type = "button";
|
|
840
|
+
deleteBtn.innerHTML = "×";
|
|
841
|
+
deleteBtn.className = className;
|
|
842
|
+
deleteBtn.title = title;
|
|
843
|
+
deleteBtn.setAttribute("contenteditable", "false");
|
|
844
|
+
deleteBtn.onclick = event => {
|
|
845
|
+
event.preventDefault();
|
|
846
|
+
event.stopPropagation();
|
|
847
|
+
onRemove();
|
|
848
|
+
};
|
|
849
|
+
return deleteBtn;
|
|
850
|
+
};
|
|
1046
851
|
|
|
1047
|
-
// Listen for selection changes globally to update styles and list type
|
|
1048
|
-
useEffect(
|
|
1049
|
-
|
|
1050
|
-
|
|
1051
|
-
|
|
1052
|
-
|
|
1053
|
-
if (!
|
|
1054
|
-
|
|
1055
|
-
|
|
852
|
+
// Listen for selection changes globally to update styles and list type in one pass
|
|
853
|
+
useEffect(() => {
|
|
854
|
+
const handleGlobalSelectionSync = () => {
|
|
855
|
+
var _editorRef$current2;
|
|
856
|
+
// Only sync if the editor has focus
|
|
857
|
+
const sel = window.getSelection();
|
|
858
|
+
if (!sel || !sel.rangeCount || !((_editorRef$current2 = editorRef.current) !== null && _editorRef$current2 !== void 0 && _editorRef$current2.contains(sel.anchorNode))) {
|
|
859
|
+
return;
|
|
860
|
+
}
|
|
861
|
+
|
|
862
|
+
// 1. Detect List Type
|
|
863
|
+
let node = sel.anchorNode;
|
|
864
|
+
let listFound = null;
|
|
865
|
+
while (node && node !== editorRef.current) {
|
|
866
|
+
if (node.nodeName === "OL") {
|
|
867
|
+
listFound = "ordered";
|
|
868
|
+
break;
|
|
869
|
+
}
|
|
870
|
+
if (node.nodeName === "UL") {
|
|
871
|
+
listFound = "unordered";
|
|
872
|
+
break;
|
|
873
|
+
}
|
|
874
|
+
node = node.parentNode;
|
|
875
|
+
}
|
|
876
|
+
setCurrentListType(listFound);
|
|
877
|
+
|
|
878
|
+
// 2. Update Style States
|
|
879
|
+
const container = sel.anchorNode.nodeType === 3 ? sel.anchorNode.parentNode : sel.anchorNode;
|
|
880
|
+
const computedAlign = window.getComputedStyle(container).textAlign;
|
|
881
|
+
setActiveAlign(computedAlign);
|
|
882
|
+
const range = sel.getRangeAt(0);
|
|
883
|
+
if (range.collapsed) {
|
|
884
|
+
setIsBold(isParentStyle(container, "B", "STRONG", "bold"));
|
|
885
|
+
setIsItalic(isParentStyle(container, "I", "EM", "italic"));
|
|
886
|
+
setIsUnderline(isParentStyle(container, "U", "underline"));
|
|
887
|
+
const computedColor = window.getComputedStyle(container).color;
|
|
888
|
+
setFontColor(rgbToHex(computedColor));
|
|
889
|
+
} else {
|
|
890
|
+
setIsBold(document.queryCommandState("bold"));
|
|
891
|
+
setIsItalic(document.queryCommandState("italic"));
|
|
892
|
+
setIsUnderline(document.queryCommandState("underline"));
|
|
893
|
+
const computedColor = window.getComputedStyle(container).color;
|
|
894
|
+
setFontColor(rgbToHex(computedColor));
|
|
895
|
+
}
|
|
896
|
+
|
|
897
|
+
// 3. Current Font Size
|
|
898
|
+
const element = range.startContainer.parentElement.closest('[style*="font-size"]');
|
|
1056
899
|
if (element) {
|
|
1057
|
-
|
|
1058
|
-
|
|
900
|
+
const fontSize = window.getComputedStyle(element).fontSize;
|
|
901
|
+
const sizeValue = fontSize ? parseInt(fontSize) : 16;
|
|
1059
902
|
setCurrentFontSize(sizeValue.toString());
|
|
1060
903
|
} else {
|
|
1061
|
-
setCurrentFontSize("16");
|
|
904
|
+
setCurrentFontSize("16");
|
|
1062
905
|
}
|
|
1063
906
|
};
|
|
1064
|
-
document.addEventListener(
|
|
1065
|
-
return
|
|
1066
|
-
document.removeEventListener("selectionchange",
|
|
1067
|
-
document.removeEventListener("selectionchange", updateStyleStates);
|
|
1068
|
-
document.removeEventListener('selectionchange', handleSelectionChange);
|
|
907
|
+
document.addEventListener("selectionchange", handleGlobalSelectionSync);
|
|
908
|
+
return () => {
|
|
909
|
+
document.removeEventListener("selectionchange", handleGlobalSelectionSync);
|
|
1069
910
|
};
|
|
1070
911
|
}, []);
|
|
1071
|
-
|
|
1072
|
-
|
|
1073
|
-
};
|
|
1074
|
-
var exec = function exec(command) {
|
|
1075
|
-
var value = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : null;
|
|
912
|
+
const focus = () => editorRef.current && editorRef.current.focus();
|
|
913
|
+
const exec = (command, value = null) => {
|
|
1076
914
|
document.execCommand(command, false, value);
|
|
1077
915
|
triggerChange();
|
|
1078
916
|
focus();
|
|
1079
917
|
};
|
|
1080
|
-
|
|
1081
|
-
|
|
1082
|
-
|
|
1083
|
-
setFontColor = _useState50[1];
|
|
1084
|
-
var handleColorChange = function handleColorChange(color) {
|
|
918
|
+
const [fontColor, setFontColor] = useState("#000000");
|
|
919
|
+
const getActiveTextColor = () => getColorAtCursor() || fontColor;
|
|
920
|
+
const handleColorChange = color => {
|
|
1085
921
|
setFontColor(color);
|
|
1086
922
|
exec("foreColor", color);
|
|
1087
923
|
};
|
|
1088
|
-
|
|
1089
|
-
|
|
924
|
+
const addLink = () => {
|
|
925
|
+
const sel = window.getSelection();
|
|
1090
926
|
if (!sel || sel.rangeCount === 0) return;
|
|
1091
927
|
selectionRangeRef.current = sel.getRangeAt(0).cloneRange();
|
|
1092
|
-
|
|
928
|
+
const selectedText = sel.toString();
|
|
1093
929
|
if (selectedText.length > 0) {
|
|
1094
930
|
setLinkText(selectedText);
|
|
1095
931
|
setLinkUrl("");
|
|
@@ -1100,112 +936,108 @@ function RichTextEditor(_ref) {
|
|
|
1100
936
|
setLinkModalOpen(true);
|
|
1101
937
|
}
|
|
1102
938
|
};
|
|
1103
|
-
|
|
939
|
+
const findParentTag = (node, tagName) => {
|
|
1104
940
|
if (!node) return null;
|
|
1105
|
-
|
|
941
|
+
let curr = node;
|
|
1106
942
|
while (curr && curr !== editorRef.current) {
|
|
1107
943
|
if (curr.tagName === tagName) return curr;
|
|
1108
944
|
curr = curr.parentNode;
|
|
1109
945
|
}
|
|
1110
946
|
return null;
|
|
1111
947
|
};
|
|
1112
|
-
|
|
1113
|
-
|
|
948
|
+
const tableAction = action => {
|
|
949
|
+
const sel = window.getSelection();
|
|
1114
950
|
if (!sel || !sel.rangeCount) return;
|
|
1115
|
-
|
|
951
|
+
const cell = findParentTag(sel.anchorNode, 'TD') || findParentTag(sel.anchorNode, 'TH');
|
|
1116
952
|
if (!cell) return;
|
|
1117
|
-
|
|
1118
|
-
|
|
953
|
+
const row = cell.parentNode;
|
|
954
|
+
const table = row.parentNode.closest('table');
|
|
1119
955
|
switch (action) {
|
|
1120
956
|
case 'addRowAbove':
|
|
1121
|
-
|
|
1122
|
-
for (
|
|
1123
|
-
|
|
957
|
+
const newRowAbove = table.insertRow(row.rowIndex);
|
|
958
|
+
for (let i = 0; i < row.cells.length; i++) {
|
|
959
|
+
const newCell = newRowAbove.insertCell(i);
|
|
1124
960
|
newCell.style.border = "1px solid #e5e7eb";
|
|
1125
961
|
newCell.style.padding = "12px";
|
|
1126
962
|
newCell.innerHTML = " ";
|
|
1127
963
|
}
|
|
1128
964
|
break;
|
|
1129
965
|
case 'addRowBelow':
|
|
1130
|
-
|
|
1131
|
-
for (
|
|
1132
|
-
|
|
1133
|
-
|
|
1134
|
-
|
|
1135
|
-
|
|
966
|
+
const newRowBelow = table.insertRow(row.rowIndex + 1);
|
|
967
|
+
for (let i = 0; i < row.cells.length; i++) {
|
|
968
|
+
const newCell = newRowBelow.insertCell(i);
|
|
969
|
+
newCell.style.border = "1px solid #e5e7eb";
|
|
970
|
+
newCell.style.padding = "12px";
|
|
971
|
+
newCell.innerHTML = " ";
|
|
1136
972
|
}
|
|
1137
973
|
break;
|
|
1138
974
|
case 'addColBefore':
|
|
1139
|
-
|
|
1140
|
-
for (
|
|
1141
|
-
|
|
1142
|
-
|
|
1143
|
-
|
|
1144
|
-
|
|
975
|
+
const cellIndex = cell.cellIndex;
|
|
976
|
+
for (let i = 0; i < table.rows.length; i++) {
|
|
977
|
+
const newCell = table.rows[i].insertCell(cellIndex);
|
|
978
|
+
newCell.style.border = "1px solid #e5e7eb";
|
|
979
|
+
newCell.style.padding = "12px";
|
|
980
|
+
newCell.innerHTML = " ";
|
|
1145
981
|
}
|
|
1146
982
|
break;
|
|
1147
983
|
case 'addColAfter':
|
|
1148
|
-
|
|
1149
|
-
for (
|
|
1150
|
-
|
|
1151
|
-
|
|
1152
|
-
|
|
1153
|
-
|
|
984
|
+
const cellIndexAfter = cell.cellIndex + 1;
|
|
985
|
+
for (let i = 0; i < table.rows.length; i++) {
|
|
986
|
+
const newCell = table.rows[i].insertCell(cellIndexAfter);
|
|
987
|
+
newCell.style.border = "1px solid #e5e7eb";
|
|
988
|
+
newCell.style.padding = "12px";
|
|
989
|
+
newCell.innerHTML = " ";
|
|
1154
990
|
}
|
|
1155
991
|
break;
|
|
1156
992
|
case 'deleteRow':
|
|
1157
993
|
{
|
|
1158
|
-
|
|
1159
|
-
|
|
994
|
+
const rowIndex = row.rowIndex;
|
|
995
|
+
const cellIndex = cell.cellIndex;
|
|
1160
996
|
table.deleteRow(rowIndex);
|
|
1161
997
|
if (table.rows.length === 0) {
|
|
1162
998
|
table.remove();
|
|
1163
999
|
} else {
|
|
1164
|
-
|
|
1165
|
-
|
|
1166
|
-
|
|
1000
|
+
const targetRowIndex = Math.min(rowIndex, table.rows.length - 1);
|
|
1001
|
+
const targetRow = table.rows[targetRowIndex];
|
|
1002
|
+
const targetCell = targetRow.cells[Math.min(cellIndex, targetRow.cells.length - 1)];
|
|
1167
1003
|
if (targetCell) {
|
|
1168
|
-
|
|
1004
|
+
const range = document.createRange();
|
|
1169
1005
|
range.selectNodeContents(targetCell);
|
|
1170
1006
|
range.collapse(true);
|
|
1171
1007
|
sel.removeAllRanges();
|
|
1172
1008
|
sel.addRange(range);
|
|
1173
|
-
setSelectionVersion(
|
|
1174
|
-
return v + 1;
|
|
1175
|
-
});
|
|
1009
|
+
setSelectionVersion(v => v + 1);
|
|
1176
1010
|
}
|
|
1177
1011
|
}
|
|
1178
1012
|
break;
|
|
1179
1013
|
}
|
|
1180
1014
|
case 'deleteCol':
|
|
1181
1015
|
{
|
|
1182
|
-
|
|
1183
|
-
|
|
1184
|
-
for (
|
|
1185
|
-
table.rows[
|
|
1016
|
+
const idx = cell.cellIndex;
|
|
1017
|
+
const rowIndex = row.rowIndex;
|
|
1018
|
+
for (let i = 0; i < table.rows.length; i++) {
|
|
1019
|
+
table.rows[i].deleteCell(idx);
|
|
1186
1020
|
}
|
|
1187
1021
|
if (table.rows[0].cells.length === 0) {
|
|
1188
1022
|
table.remove();
|
|
1189
1023
|
} else {
|
|
1190
|
-
var _table$rows$
|
|
1191
|
-
|
|
1192
|
-
|
|
1193
|
-
if (
|
|
1194
|
-
|
|
1195
|
-
|
|
1196
|
-
|
|
1024
|
+
var _table$rows$rowIndex;
|
|
1025
|
+
const targetColIndex = Math.min(idx, table.rows[0].cells.length - 1);
|
|
1026
|
+
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];
|
|
1027
|
+
if (targetCell) {
|
|
1028
|
+
const range = document.createRange();
|
|
1029
|
+
range.selectNodeContents(targetCell);
|
|
1030
|
+
range.collapse(true);
|
|
1197
1031
|
sel.removeAllRanges();
|
|
1198
|
-
sel.addRange(
|
|
1199
|
-
setSelectionVersion(
|
|
1200
|
-
return v + 1;
|
|
1201
|
-
});
|
|
1032
|
+
sel.addRange(range);
|
|
1033
|
+
setSelectionVersion(v => v + 1);
|
|
1202
1034
|
}
|
|
1203
1035
|
}
|
|
1204
1036
|
break;
|
|
1205
1037
|
}
|
|
1206
1038
|
case 'mergeRight':
|
|
1207
1039
|
if (cell.nextElementSibling) {
|
|
1208
|
-
|
|
1040
|
+
const nextCell = cell.nextElementSibling;
|
|
1209
1041
|
cell.colSpan = (cell.colSpan || 1) + (nextCell.colSpan || 1);
|
|
1210
1042
|
nextCell.remove();
|
|
1211
1043
|
}
|
|
@@ -1216,20 +1048,20 @@ function RichTextEditor(_ref) {
|
|
|
1216
1048
|
}
|
|
1217
1049
|
triggerChange && triggerChange();
|
|
1218
1050
|
};
|
|
1219
|
-
|
|
1220
|
-
|
|
1221
|
-
|
|
1222
|
-
|
|
1223
|
-
for (
|
|
1051
|
+
const insertTable = () => {
|
|
1052
|
+
const rows = parseInt(tableRows) || 3;
|
|
1053
|
+
const cols = parseInt(tableCols) || 3;
|
|
1054
|
+
let tableHtml = '<table style="width: 100%; border-collapse: collapse; border: 1px solid #e5e7eb; margin: 16px 0;"><tbody>';
|
|
1055
|
+
for (let i = 0; i < rows; i++) {
|
|
1224
1056
|
tableHtml += '<tr>';
|
|
1225
|
-
for (
|
|
1057
|
+
for (let j = 0; j < cols; j++) {
|
|
1226
1058
|
tableHtml += '<td style="border: 1px solid #e5e7eb; padding: 12px; min-height: 20px;"> </td>';
|
|
1227
1059
|
}
|
|
1228
1060
|
tableHtml += '</tr>';
|
|
1229
1061
|
}
|
|
1230
1062
|
tableHtml += '</tbody></table><p> </p>';
|
|
1231
1063
|
if (selectionRangeRef.current) {
|
|
1232
|
-
|
|
1064
|
+
const sel = window.getSelection();
|
|
1233
1065
|
sel.removeAllRanges();
|
|
1234
1066
|
sel.addRange(selectionRangeRef.current);
|
|
1235
1067
|
}
|
|
@@ -1237,50 +1069,57 @@ function RichTextEditor(_ref) {
|
|
|
1237
1069
|
setTableModalOpen(false);
|
|
1238
1070
|
triggerChange && triggerChange();
|
|
1239
1071
|
};
|
|
1240
|
-
|
|
1072
|
+
const parseVideoUrl = url => {
|
|
1241
1073
|
url = url.trim();
|
|
1242
1074
|
if (!url) return null;
|
|
1243
1075
|
|
|
1244
1076
|
// YouTube
|
|
1245
|
-
|
|
1246
|
-
|
|
1077
|
+
const ytRegExp = /^.*(youtu.be\/|v\/|u\/\w\/|embed\/|watch\?v=|\&v=|watch\?vi=|\&vi=)([^#\&\?]*).*/;
|
|
1078
|
+
const ytMatch = url.match(ytRegExp);
|
|
1247
1079
|
if (ytMatch && ytMatch[2].length === 11) {
|
|
1248
|
-
return
|
|
1080
|
+
return `https://www.youtube.com/embed/${ytMatch[2]}`;
|
|
1249
1081
|
}
|
|
1250
1082
|
|
|
1251
1083
|
// Vimeo
|
|
1252
|
-
|
|
1253
|
-
|
|
1084
|
+
const vimeoRegExp = /vimeo\.com\/(?:channels\/(?:\w+\/)?|groups\/([^\/]*)\/videos\/|album\/(\d+)\/video\/|video\/|)(\d+)(?:$|\/|\?)/;
|
|
1085
|
+
const vimeoMatch = url.match(vimeoRegExp);
|
|
1254
1086
|
if (vimeoMatch && vimeoMatch[3]) {
|
|
1255
|
-
return
|
|
1087
|
+
return `https://player.vimeo.com/video/${vimeoMatch[3]}`;
|
|
1256
1088
|
}
|
|
1257
1089
|
|
|
1258
1090
|
// DailyMotion
|
|
1259
|
-
|
|
1260
|
-
|
|
1091
|
+
const dmRegExp = /dailymotion\.com\/video\/([a-zA-Z0-9]+)/;
|
|
1092
|
+
const dmMatch = url.match(dmRegExp);
|
|
1261
1093
|
if (dmMatch && dmMatch[1]) {
|
|
1262
|
-
return
|
|
1094
|
+
return `https://www.dailymotion.com/embed/video/${dmMatch[1]}`;
|
|
1263
1095
|
}
|
|
1264
1096
|
return null;
|
|
1265
1097
|
};
|
|
1266
|
-
|
|
1267
|
-
|
|
1098
|
+
const insertVideo = () => {
|
|
1099
|
+
const embedUrl = parseVideoUrl(videoUrl);
|
|
1268
1100
|
if (embedUrl) {
|
|
1269
1101
|
if (editorRef.current) {
|
|
1270
1102
|
editorRef.current.focus();
|
|
1271
1103
|
}
|
|
1272
1104
|
if (selectionRangeRef.current) {
|
|
1273
|
-
|
|
1105
|
+
const sel = window.getSelection();
|
|
1274
1106
|
sel.removeAllRanges();
|
|
1275
1107
|
sel.addRange(selectionRangeRef.current);
|
|
1276
1108
|
}
|
|
1277
|
-
|
|
1109
|
+
const embedHtml = `<div class="video-container">
|
|
1110
|
+
<iframe
|
|
1111
|
+
src="${embedUrl}"
|
|
1112
|
+
frameborder="0"
|
|
1113
|
+
allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture"
|
|
1114
|
+
allowfullscreen
|
|
1115
|
+
></iframe>
|
|
1116
|
+
</div><p> </p>`;
|
|
1278
1117
|
try {
|
|
1279
1118
|
document.execCommand("insertHTML", false, embedHtml);
|
|
1280
1119
|
} catch (err) {
|
|
1281
1120
|
console.error("Failed to insert Video HTML:", err);
|
|
1282
1121
|
if (editorRef.current) {
|
|
1283
|
-
|
|
1122
|
+
const div = document.createElement('div');
|
|
1284
1123
|
div.innerHTML = embedHtml;
|
|
1285
1124
|
editorRef.current.appendChild(div);
|
|
1286
1125
|
}
|
|
@@ -1288,52 +1127,82 @@ function RichTextEditor(_ref) {
|
|
|
1288
1127
|
setVideoModalOpen(false);
|
|
1289
1128
|
setVideoUrl("");
|
|
1290
1129
|
triggerChange && triggerChange();
|
|
1130
|
+
requestAnimationFrame(() => processExistingMedia(editorRef.current));
|
|
1291
1131
|
} else {
|
|
1292
1132
|
console.warn("Invalid Video URL or Platform not supported");
|
|
1293
1133
|
}
|
|
1294
1134
|
};
|
|
1295
|
-
|
|
1135
|
+
const processExistingVideos = container => {
|
|
1296
1136
|
if (!container) return;
|
|
1297
|
-
container.querySelectorAll("
|
|
1298
|
-
|
|
1299
|
-
|
|
1300
|
-
|
|
1301
|
-
oldWrapper.replaceWith(img); // unwrap
|
|
1302
|
-
}
|
|
1303
|
-
var wrapper = document.createElement("div");
|
|
1304
|
-
var align = img.getAttribute('data-align') || 'center';
|
|
1305
|
-
wrapper.className = "image-container image-align-".concat(align);
|
|
1306
|
-
wrapper.style.cursor = editable ? 'pointer' : 'default';
|
|
1307
|
-
img.className = "rte-image";
|
|
1308
|
-
img.style.cssText = ""; // Reset inline styles
|
|
1309
|
-
img.setAttribute('data-align', align);
|
|
1310
|
-
img.dataset.hasDeleteButton = "true";
|
|
1311
|
-
|
|
1312
|
-
// Add click listener to open modal
|
|
1313
|
-
img.addEventListener("click", function () {
|
|
1314
|
-
return openImageModal(img.src);
|
|
1315
|
-
});
|
|
1316
|
-
var deleteBtn = document.createElement("button");
|
|
1317
|
-
deleteBtn.innerHTML = "×";
|
|
1318
|
-
deleteBtn.className = "image-delete-button";
|
|
1319
|
-
deleteBtn.style.display = editable ? 'flex' : 'none';
|
|
1320
|
-
deleteBtn.style.pointerEvents = editable ? 'auto' : 'none';
|
|
1321
|
-
deleteBtn.title = "Remove image";
|
|
1322
|
-
deleteBtn.onclick = function (e) {
|
|
1323
|
-
e.preventDefault();
|
|
1324
|
-
e.stopPropagation();
|
|
1325
|
-
var wrapper = e.currentTarget.closest(".image-container");
|
|
1326
|
-
if (wrapper && wrapper.parentNode) {
|
|
1327
|
-
wrapper.parentNode.removeChild(wrapper);
|
|
1137
|
+
container.querySelectorAll(".video-container").forEach(videoContainer => {
|
|
1138
|
+
if (!videoContainer.querySelector(".video-delete-button")) {
|
|
1139
|
+
const deleteBtn = createMediaDeleteButton("Remove video", "video-delete-button image-delete-button", () => {
|
|
1140
|
+
videoContainer.remove();
|
|
1328
1141
|
triggerChange && triggerChange();
|
|
1142
|
+
});
|
|
1143
|
+
videoContainer.appendChild(deleteBtn);
|
|
1144
|
+
}
|
|
1145
|
+
attachMediaResizeHandle(videoContainer);
|
|
1146
|
+
updateMediaControlVisibility(videoContainer);
|
|
1147
|
+
});
|
|
1148
|
+
};
|
|
1149
|
+
const processExistingImages = container => {
|
|
1150
|
+
if (!container) return;
|
|
1151
|
+
container.querySelectorAll("img").forEach(img => {
|
|
1152
|
+
var _img$closest;
|
|
1153
|
+
if (img.closest(".rte-modal")) return;
|
|
1154
|
+
const existingWrapper = img.closest(".image-container");
|
|
1155
|
+
if (existingWrapper) {
|
|
1156
|
+
existingWrapper.style.cursor = editable ? "pointer" : "default";
|
|
1157
|
+
const frame = ensureImageMediaFrame(existingWrapper);
|
|
1158
|
+
if (frame && !frame.querySelector(".image-delete-button")) {
|
|
1159
|
+
frame.appendChild(createMediaDeleteButton("Remove image", "image-delete-button", () => {
|
|
1160
|
+
existingWrapper.remove();
|
|
1161
|
+
triggerChange && triggerChange();
|
|
1162
|
+
}));
|
|
1329
1163
|
}
|
|
1330
|
-
|
|
1331
|
-
|
|
1332
|
-
|
|
1164
|
+
attachMediaResizeHandle(existingWrapper);
|
|
1165
|
+
updateMediaControlVisibility(existingWrapper);
|
|
1166
|
+
return;
|
|
1167
|
+
}
|
|
1168
|
+
const wrapper = document.createElement("div");
|
|
1169
|
+
const align = img.getAttribute("data-align") || ((_img$closest = img.closest("[data-align]")) === null || _img$closest === void 0 ? void 0 : _img$closest.getAttribute("data-align")) || "left";
|
|
1170
|
+
wrapper.className = `image-container image-align-${align}`;
|
|
1171
|
+
wrapper.style.cursor = editable ? "pointer" : "default";
|
|
1172
|
+
const frame = document.createElement("div");
|
|
1173
|
+
frame.className = "image-media-frame";
|
|
1174
|
+
if (img.getAttribute("width") && !frame.style.width) {
|
|
1175
|
+
frame.style.width = `${img.getAttribute("width")}px`;
|
|
1176
|
+
} else if (img.style.width && img.style.width.endsWith("px")) {
|
|
1177
|
+
frame.style.width = img.style.width;
|
|
1178
|
+
}
|
|
1179
|
+
img.classList.add("rte-image");
|
|
1180
|
+
img.setAttribute("data-align", align);
|
|
1181
|
+
if (frame.style.width) {
|
|
1182
|
+
img.style.width = "100%";
|
|
1183
|
+
img.style.height = frame.dataset.explicitHeight ? "100%" : "auto";
|
|
1184
|
+
} else {
|
|
1185
|
+
img.style.width = "";
|
|
1186
|
+
img.style.height = "auto";
|
|
1187
|
+
}
|
|
1188
|
+
img.addEventListener("click", event => {
|
|
1189
|
+
if (event.target.closest(".image-delete-button, .media-resize-handle")) return;
|
|
1190
|
+
openImageModal(img.src);
|
|
1191
|
+
});
|
|
1192
|
+
const deleteBtn = createMediaDeleteButton("Remove image", "image-delete-button", () => {
|
|
1193
|
+
wrapper.remove();
|
|
1194
|
+
triggerChange && triggerChange();
|
|
1195
|
+
});
|
|
1196
|
+
const {
|
|
1197
|
+
parentNode,
|
|
1198
|
+
nextSibling
|
|
1199
|
+
} = img;
|
|
1333
1200
|
if (parentNode) {
|
|
1334
1201
|
parentNode.removeChild(img);
|
|
1335
|
-
|
|
1336
|
-
|
|
1202
|
+
frame.appendChild(img);
|
|
1203
|
+
frame.appendChild(deleteBtn);
|
|
1204
|
+
wrapper.appendChild(frame);
|
|
1205
|
+
attachMediaResizeHandle(wrapper);
|
|
1337
1206
|
if (nextSibling) {
|
|
1338
1207
|
parentNode.insertBefore(wrapper, nextSibling);
|
|
1339
1208
|
} else {
|
|
@@ -1342,111 +1211,80 @@ function RichTextEditor(_ref) {
|
|
|
1342
1211
|
}
|
|
1343
1212
|
});
|
|
1344
1213
|
};
|
|
1345
|
-
useEffect(function () {
|
|
1346
|
-
if (editorRef.current && value) {
|
|
1347
|
-
requestAnimationFrame(function () {
|
|
1348
|
-
return processExistingImages(editorRef.current);
|
|
1349
|
-
});
|
|
1350
|
-
}
|
|
1351
|
-
}, [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
|
-
|
|
1364
|
-
// Create image element
|
|
1365
|
-
img = document.createElement('img');
|
|
1366
|
-
img.src = dataUrl;
|
|
1367
|
-
img.alt = fileName || "image";
|
|
1368
|
-
img.addEventListener("click", function () {
|
|
1369
|
-
return openImageModal(dataUrl);
|
|
1370
|
-
});
|
|
1371
1214
|
|
|
1372
|
-
|
|
1373
|
-
|
|
1215
|
+
/*
|
|
1216
|
+
Advanced Tip: Use the 'onImageUpload' prop to handle file uploads to a server
|
|
1217
|
+
instead of using base64. If 'onImageUpload' is provided, it should return a URL string.
|
|
1218
|
+
*/
|
|
1219
|
+
const insertImage = async (dataUrl, fileName) => {
|
|
1220
|
+
try {
|
|
1221
|
+
if (editable) {
|
|
1222
|
+
// Create container for the image
|
|
1223
|
+
const container = document.createElement('div');
|
|
1224
|
+
container.className = 'image-container image-align-left';
|
|
1225
|
+
const frame = document.createElement('div');
|
|
1226
|
+
frame.className = 'image-media-frame';
|
|
1374
1227
|
|
|
1375
|
-
|
|
1376
|
-
|
|
1377
|
-
|
|
1228
|
+
// Create image element
|
|
1229
|
+
const img = document.createElement('img');
|
|
1230
|
+
img.src = dataUrl;
|
|
1231
|
+
img.alt = fileName || "image";
|
|
1232
|
+
img.addEventListener("click", () => openImageModal(dataUrl));
|
|
1233
|
+
frame.appendChild(img);
|
|
1234
|
+
container.appendChild(frame);
|
|
1378
1235
|
|
|
1379
|
-
|
|
1380
|
-
|
|
1381
|
-
|
|
1382
|
-
|
|
1383
|
-
|
|
1384
|
-
|
|
1385
|
-
|
|
1386
|
-
|
|
1387
|
-
|
|
1388
|
-
|
|
1389
|
-
}
|
|
1390
|
-
}, _callee);
|
|
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
|
-
});
|
|
1236
|
+
// Insert at cursor position
|
|
1237
|
+
insertNodeAtCursor(container);
|
|
1238
|
+
requestAnimationFrame(() => {
|
|
1239
|
+
processExistingMedia(editorRef.current);
|
|
1240
|
+
triggerChange();
|
|
1241
|
+
});
|
|
1242
|
+
}
|
|
1243
|
+
} catch (err) {
|
|
1244
|
+
console.error('Error inserting image:', err);
|
|
1245
|
+
}
|
|
1405
1246
|
};
|
|
1406
|
-
|
|
1407
|
-
|
|
1247
|
+
const readFileAsDataURL = file => new Promise((res, rej) => {
|
|
1248
|
+
const reader = new FileReader();
|
|
1249
|
+
reader.onload = ev => res(ev.target.result);
|
|
1250
|
+
reader.onerror = rej;
|
|
1251
|
+
reader.readAsDataURL(file);
|
|
1252
|
+
});
|
|
1253
|
+
const handlePaste = useCallback(e => {
|
|
1254
|
+
const clipboardData = e.clipboardData || window.clipboardData;
|
|
1408
1255
|
if (!clipboardData) return;
|
|
1409
1256
|
|
|
1410
1257
|
// 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
|
-
};
|
|
1258
|
+
const items = clipboardData.items || [];
|
|
1259
|
+
for (let i = 0; i < items.length; i++) {
|
|
1260
|
+
const item = items[i];
|
|
1261
|
+
if (item.kind === 'file' && item.type.indexOf('image/') !== -1) {
|
|
1262
|
+
e.preventDefault();
|
|
1263
|
+
const file = item.getAsFile();
|
|
1264
|
+
if (file) {
|
|
1265
|
+
setIsUploading(true);
|
|
1266
|
+
const uploadPromise = onImageUpload ? onImageUpload(file) : readFileAsDataURL(file);
|
|
1267
|
+
uploadPromise.then(url => {
|
|
1268
|
+
if (url) {
|
|
1269
|
+
// if the user's onImageUpload resolves to `{ mediaUrl: '...' }` like the previous MediaUpload, handle it
|
|
1270
|
+
const finalUrl = typeof url === 'object' && url !== null && url.mediaUrl ? url.mediaUrl : url;
|
|
1271
|
+
insertImage(finalUrl, file.name || 'pasted-image');
|
|
1272
|
+
}
|
|
1273
|
+
setIsUploading(false);
|
|
1274
|
+
}).catch(error => {
|
|
1275
|
+
console.error('Error uploading pasted image:', error);
|
|
1276
|
+
setIsUploading(false);
|
|
1277
|
+
});
|
|
1435
1278
|
}
|
|
1436
|
-
|
|
1437
|
-
|
|
1438
|
-
for (var i = 0; i < items.length; i++) {
|
|
1439
|
-
_ret = _loop();
|
|
1440
|
-
if (_ret) return _ret.v;
|
|
1279
|
+
return;
|
|
1280
|
+
}
|
|
1441
1281
|
}
|
|
1442
|
-
|
|
1282
|
+
const htmlData = clipboardData.getData('text/html');
|
|
1443
1283
|
if (htmlData && htmlData.trim()) {
|
|
1444
1284
|
e.preventDefault();
|
|
1445
|
-
|
|
1285
|
+
const tempDiv = document.createElement('div');
|
|
1446
1286
|
tempDiv.innerHTML = htmlData;
|
|
1447
|
-
tempDiv.querySelectorAll('script, meta, link').forEach(
|
|
1448
|
-
return el.remove();
|
|
1449
|
-
});
|
|
1287
|
+
tempDiv.querySelectorAll('script, meta, link').forEach(el => el.remove());
|
|
1450
1288
|
document.execCommand('styleWithCSS', false, true);
|
|
1451
1289
|
document.execCommand('insertHTML', false, tempDiv.innerHTML);
|
|
1452
1290
|
document.execCommand('styleWithCSS', false, false);
|
|
@@ -1454,13 +1292,13 @@ function RichTextEditor(_ref) {
|
|
|
1454
1292
|
focus();
|
|
1455
1293
|
return;
|
|
1456
1294
|
}
|
|
1457
|
-
|
|
1295
|
+
const plainText = clipboardData.getData('text/plain');
|
|
1458
1296
|
if (plainText) {
|
|
1459
1297
|
e.preventDefault();
|
|
1460
|
-
|
|
1461
|
-
htmlToInsert = htmlToInsert.replace(URL_REGEX,
|
|
1462
|
-
|
|
1463
|
-
return
|
|
1298
|
+
let htmlToInsert = escapeHtml(plainText);
|
|
1299
|
+
htmlToInsert = htmlToInsert.replace(URL_REGEX, url => {
|
|
1300
|
+
const safeUrl = escapeAttr(url.trim());
|
|
1301
|
+
return `<a href="${safeUrl}" target="_blank" rel="noopener noreferrer" style="color: blue; text-decoration: underline;">${escapeHtml(url)}</a>`;
|
|
1464
1302
|
});
|
|
1465
1303
|
htmlToInsert = htmlToInsert.replace(/\n/g, '<br>');
|
|
1466
1304
|
document.execCommand('insertHTML', false, htmlToInsert);
|
|
@@ -1468,94 +1306,37 @@ function RichTextEditor(_ref) {
|
|
|
1468
1306
|
focus();
|
|
1469
1307
|
}
|
|
1470
1308
|
}, [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) {
|
|
1309
|
+
const handleDrop = async e => {
|
|
1310
|
+
if (!editable) return;
|
|
1311
|
+
e.preventDefault();
|
|
1312
|
+
e.stopPropagation();
|
|
1313
|
+
const files = e.dataTransfer.files;
|
|
1314
|
+
if (!files || files.length === 0) return;
|
|
1315
|
+
const imageFiles = Array.from(files).filter(file => file.type.startsWith("image/"));
|
|
1316
|
+
for (const file of imageFiles) {
|
|
1317
|
+
try {
|
|
1318
|
+
setIsUploading(true);
|
|
1319
|
+
const uploadPromise = onImageUpload ? onImageUpload(file) : readFileAsDataURL(file);
|
|
1320
|
+
uploadPromise.then(url => {
|
|
1321
|
+
if (url) {
|
|
1322
|
+
const finalUrl = typeof url === 'object' && url !== null && url.mediaUrl ? url.mediaUrl : url;
|
|
1323
|
+
insertImage(finalUrl, file.name);
|
|
1324
|
+
}
|
|
1325
|
+
setIsUploading(false);
|
|
1326
|
+
}).catch(error => {
|
|
1327
|
+
console.error('Error processing image:', error);
|
|
1328
|
+
setIsUploading(false);
|
|
1329
|
+
});
|
|
1330
|
+
} catch (error) {
|
|
1331
|
+
console.error('Error processing image:', error);
|
|
1332
|
+
setIsUploading(false);
|
|
1333
|
+
}
|
|
1334
|
+
}
|
|
1335
|
+
};
|
|
1336
|
+
const insertNodeAtCursor = node => {
|
|
1556
1337
|
try {
|
|
1557
|
-
|
|
1558
|
-
|
|
1338
|
+
const sel = window.getSelection();
|
|
1339
|
+
let range;
|
|
1559
1340
|
if (!sel || sel.rangeCount === 0 || !editorRef.current.contains(sel.anchorNode)) {
|
|
1560
1341
|
editorRef.current.focus();
|
|
1561
1342
|
|
|
@@ -1570,7 +1351,7 @@ function RichTextEditor(_ref) {
|
|
|
1570
1351
|
}
|
|
1571
1352
|
range.deleteContents();
|
|
1572
1353
|
range.insertNode(node);
|
|
1573
|
-
|
|
1354
|
+
const space = document.createTextNode("\u00A0");
|
|
1574
1355
|
if (node.parentNode) {
|
|
1575
1356
|
node.parentNode.insertBefore(space, node.nextSibling);
|
|
1576
1357
|
}
|
|
@@ -1585,49 +1366,68 @@ function RichTextEditor(_ref) {
|
|
|
1585
1366
|
}
|
|
1586
1367
|
}
|
|
1587
1368
|
};
|
|
1588
|
-
var getCleanHtml = function getCleanHtml() {
|
|
1589
|
-
if (!editorRef.current) return "";
|
|
1590
|
-
return editorRef.current.innerHTML;
|
|
1591
|
-
};
|
|
1592
1369
|
|
|
1593
1370
|
// Helper function to unescape HTML entities
|
|
1594
|
-
|
|
1371
|
+
const unescapeHtml = html => {
|
|
1595
1372
|
if (!html) return '';
|
|
1596
|
-
|
|
1373
|
+
const txt = document.createElement("textarea");
|
|
1597
1374
|
txt.innerHTML = html;
|
|
1598
1375
|
return txt.value;
|
|
1599
1376
|
};
|
|
1600
|
-
|
|
1377
|
+
const isCursorAtEndOfListItem = (range, listItem) => {
|
|
1378
|
+
const suffixRange = document.createRange();
|
|
1379
|
+
suffixRange.setStart(range.startContainer, range.startOffset);
|
|
1380
|
+
suffixRange.setEnd(listItem, listItem.childNodes.length);
|
|
1381
|
+
return suffixRange.toString().replace(/\u200B/g, "").length === 0;
|
|
1382
|
+
};
|
|
1383
|
+
const prepareListItemForTyping = (listItem, selection) => {
|
|
1384
|
+
const activeColor = getActiveTextColor();
|
|
1385
|
+
const newRange = document.createRange();
|
|
1386
|
+
if (activeColor && activeColor.toLowerCase() !== "#000000") {
|
|
1387
|
+
const span = document.createElement("span");
|
|
1388
|
+
span.style.color = activeColor;
|
|
1389
|
+
span.appendChild(document.createTextNode("\u200B"));
|
|
1390
|
+
listItem.appendChild(span);
|
|
1391
|
+
newRange.setStart(span.firstChild, 1);
|
|
1392
|
+
} else {
|
|
1393
|
+
listItem.appendChild(document.createTextNode("\u200B"));
|
|
1394
|
+
newRange.setStart(listItem.firstChild, 1);
|
|
1395
|
+
}
|
|
1396
|
+
newRange.collapse(true);
|
|
1397
|
+
selection.removeAllRanges();
|
|
1398
|
+
selection.addRange(newRange);
|
|
1399
|
+
};
|
|
1400
|
+
const handleKeyDown = useCallback(e => {
|
|
1601
1401
|
// Handle Enter key
|
|
1602
1402
|
if (e.key === 'Enter') {
|
|
1603
1403
|
e.preventDefault();
|
|
1604
|
-
|
|
1404
|
+
const selection = window.getSelection();
|
|
1605
1405
|
if (!selection.rangeCount) return;
|
|
1606
|
-
|
|
1607
|
-
|
|
1608
|
-
|
|
1406
|
+
const range = selection.getRangeAt(0);
|
|
1407
|
+
const node = range.startContainer;
|
|
1408
|
+
const parent = node.nodeType === 3 ? node.parentNode : node;
|
|
1609
1409
|
|
|
1610
1410
|
// Check if we're in a list item
|
|
1611
|
-
|
|
1411
|
+
const listItem = parent.closest('li');
|
|
1612
1412
|
if (listItem) {
|
|
1613
|
-
|
|
1614
|
-
list.tagName === 'OL';
|
|
1413
|
+
const list = listItem.parentNode;
|
|
1615
1414
|
|
|
1616
1415
|
// Create a new list item
|
|
1617
|
-
|
|
1416
|
+
const newItem = document.createElement('li');
|
|
1618
1417
|
|
|
1619
1418
|
// If we're at the end of a list item, add a new one
|
|
1620
|
-
if (range.collapsed && range
|
|
1419
|
+
if (range.collapsed && isCursorAtEndOfListItem(range, listItem)) {
|
|
1621
1420
|
// If it's empty, create a regular paragraph instead
|
|
1622
|
-
if (listItem.textContent.trim() === '') {
|
|
1421
|
+
if (listItem.textContent.replace(/\u200B/g, '').trim() === '') {
|
|
1623
1422
|
document.execCommand('insertHTML', false, '<div><br></div>');
|
|
1624
1423
|
// Move the cursor to the new line
|
|
1625
|
-
|
|
1626
|
-
|
|
1627
|
-
|
|
1628
|
-
|
|
1424
|
+
const newRange = document.createRange();
|
|
1425
|
+
const newDiv = editorRef.current.lastElementChild;
|
|
1426
|
+
newRange.setStart(newDiv, 0);
|
|
1427
|
+
newRange.collapse(true);
|
|
1629
1428
|
selection.removeAllRanges();
|
|
1630
|
-
selection.addRange(
|
|
1429
|
+
selection.addRange(newRange);
|
|
1430
|
+
triggerChange();
|
|
1631
1431
|
return;
|
|
1632
1432
|
}
|
|
1633
1433
|
|
|
@@ -1637,35 +1437,29 @@ function RichTextEditor(_ref) {
|
|
|
1637
1437
|
} else {
|
|
1638
1438
|
list.appendChild(newItem);
|
|
1639
1439
|
}
|
|
1640
|
-
|
|
1641
|
-
// Move cursor to the new list item
|
|
1642
|
-
var newRange = document.createRange();
|
|
1643
|
-
newRange.setStart(newItem, 0);
|
|
1644
|
-
newRange.collapse(true);
|
|
1645
|
-
selection.removeAllRanges();
|
|
1646
|
-
selection.addRange(newRange);
|
|
1440
|
+
prepareListItemForTyping(newItem, selection);
|
|
1647
1441
|
} else {
|
|
1648
|
-
// If we're in the middle of text, split the list item
|
|
1649
|
-
|
|
1650
|
-
|
|
1651
|
-
|
|
1652
|
-
|
|
1653
|
-
|
|
1654
|
-
|
|
1655
|
-
// Insert new item after current one
|
|
1656
|
-
newItem.textContent = textAfter;
|
|
1442
|
+
// If we're in the middle of text, split the list item while preserving formatting
|
|
1443
|
+
const afterRange = document.createRange();
|
|
1444
|
+
afterRange.setStart(range.startContainer, range.startOffset);
|
|
1445
|
+
afterRange.setEnd(listItem, listItem.childNodes.length);
|
|
1446
|
+
const movedFragment = afterRange.extractContents();
|
|
1447
|
+
newItem.appendChild(movedFragment);
|
|
1657
1448
|
if (listItem.nextSibling) {
|
|
1658
1449
|
list.insertBefore(newItem, listItem.nextSibling);
|
|
1659
1450
|
} else {
|
|
1660
1451
|
list.appendChild(newItem);
|
|
1661
1452
|
}
|
|
1662
|
-
|
|
1663
|
-
|
|
1664
|
-
|
|
1665
|
-
|
|
1666
|
-
|
|
1667
|
-
|
|
1668
|
-
|
|
1453
|
+
if (!newItem.textContent.replace(/\u200B/g, '').trim()) {
|
|
1454
|
+
newItem.textContent = "";
|
|
1455
|
+
prepareListItemForTyping(newItem, selection);
|
|
1456
|
+
} else {
|
|
1457
|
+
const newRange = document.createRange();
|
|
1458
|
+
newRange.setStart(newItem, 0);
|
|
1459
|
+
newRange.collapse(true);
|
|
1460
|
+
selection.removeAllRanges();
|
|
1461
|
+
selection.addRange(newRange);
|
|
1462
|
+
}
|
|
1669
1463
|
}
|
|
1670
1464
|
} else {
|
|
1671
1465
|
// Regular text, insert a new paragraph
|
|
@@ -1686,55 +1480,55 @@ function RichTextEditor(_ref) {
|
|
|
1686
1480
|
e.preventDefault();
|
|
1687
1481
|
exec("underline");
|
|
1688
1482
|
}
|
|
1689
|
-
}, [exec, triggerChange]);
|
|
1690
|
-
|
|
1483
|
+
}, [exec, triggerChange, fontColor]);
|
|
1484
|
+
const confirmLink = () => {
|
|
1691
1485
|
// Add protocol if missing
|
|
1692
|
-
|
|
1486
|
+
let url = linkUrl.trim();
|
|
1693
1487
|
if (url && !/^(https?:\/\/|mailto:|tel:)/i.test(url)) {
|
|
1694
|
-
url =
|
|
1488
|
+
url = `https://${url}`;
|
|
1695
1489
|
}
|
|
1696
|
-
|
|
1697
|
-
|
|
1698
|
-
|
|
1490
|
+
const safeUrl = escapeAttr(url);
|
|
1491
|
+
const safeText = escapeHtml(linkText || linkUrl);
|
|
1492
|
+
const sel = window.getSelection();
|
|
1699
1493
|
sel.removeAllRanges();
|
|
1700
1494
|
if (selectionRangeRef.current) {
|
|
1701
1495
|
sel.addRange(selectionRangeRef.current);
|
|
1702
1496
|
}
|
|
1703
|
-
|
|
1497
|
+
const linkHtml = `<a href="${safeUrl}" target="_blank" rel="noopener noreferrer" style="color: blue;">${safeText}</a>`;
|
|
1704
1498
|
document.execCommand("insertHTML", false, linkHtml);
|
|
1705
1499
|
setLinkModalOpen(false);
|
|
1706
1500
|
triggerChange();
|
|
1707
1501
|
focus();
|
|
1708
1502
|
selectionRangeRef.current = null;
|
|
1709
1503
|
};
|
|
1710
|
-
|
|
1504
|
+
const cancelLink = () => {
|
|
1711
1505
|
setLinkModalOpen(false);
|
|
1712
1506
|
selectionRangeRef.current = null;
|
|
1713
1507
|
};
|
|
1714
|
-
|
|
1508
|
+
const handleSelect = type => {
|
|
1715
1509
|
exec(type === "unordered" ? "insertUnorderedList" : "insertOrderedList");
|
|
1716
1510
|
};
|
|
1717
|
-
|
|
1511
|
+
const onLineHeightChange = value => {
|
|
1718
1512
|
if (!value) return;
|
|
1719
|
-
|
|
1513
|
+
const sel = window.getSelection();
|
|
1720
1514
|
if (!sel || !sel.rangeCount) return;
|
|
1721
|
-
|
|
1722
|
-
|
|
1515
|
+
const range = sel.getRangeAt(0);
|
|
1516
|
+
const editor = editorRef.current;
|
|
1723
1517
|
if (!editor) return;
|
|
1724
|
-
|
|
1725
|
-
acceptNode:
|
|
1518
|
+
const walker = document.createTreeWalker(editor, NodeFilter.SHOW_ELEMENT | NodeFilter.SHOW_TEXT, {
|
|
1519
|
+
acceptNode: node => {
|
|
1726
1520
|
return range.intersectsNode(node) ? NodeFilter.FILTER_ACCEPT : NodeFilter.FILTER_REJECT;
|
|
1727
1521
|
}
|
|
1728
1522
|
}, false);
|
|
1729
|
-
|
|
1730
|
-
|
|
1731
|
-
|
|
1732
|
-
|
|
1523
|
+
let node;
|
|
1524
|
+
const blocksToStyle = new Set();
|
|
1525
|
+
const blockTags = ['P', 'DIV', 'H1', 'H2', 'H3', 'H4', 'H5', 'H6', 'LI', 'BLOCKQUOTE'];
|
|
1526
|
+
const tempRange = range.cloneRange();
|
|
1733
1527
|
while (node = walker.nextNode()) {
|
|
1734
1528
|
if (node.nodeType === 1 && blockTags.includes(node.tagName)) {
|
|
1735
1529
|
blocksToStyle.add(node);
|
|
1736
1530
|
} else if (node.nodeType === 3) {
|
|
1737
|
-
|
|
1531
|
+
let parent = node.parentNode;
|
|
1738
1532
|
while (parent && parent !== editor && !blockTags.includes(parent.tagName)) {
|
|
1739
1533
|
parent = parent.parentNode;
|
|
1740
1534
|
}
|
|
@@ -1744,11 +1538,11 @@ function RichTextEditor(_ref) {
|
|
|
1744
1538
|
}
|
|
1745
1539
|
}
|
|
1746
1540
|
if (blocksToStyle.size > 0) {
|
|
1747
|
-
blocksToStyle.forEach(
|
|
1541
|
+
blocksToStyle.forEach(block => {
|
|
1748
1542
|
block.style.lineHeight = value;
|
|
1749
1543
|
});
|
|
1750
1544
|
} else {
|
|
1751
|
-
|
|
1545
|
+
let common = range.commonAncestorContainer;
|
|
1752
1546
|
if (common.nodeType === 3) common = common.parentNode;
|
|
1753
1547
|
while (common && common !== editor && !blockTags.includes(common.tagName)) {
|
|
1754
1548
|
common = common.parentNode;
|
|
@@ -1757,7 +1551,7 @@ function RichTextEditor(_ref) {
|
|
|
1757
1551
|
common.style.lineHeight = value;
|
|
1758
1552
|
} else if (editor) {
|
|
1759
1553
|
document.execCommand('formatBlock', false, 'div');
|
|
1760
|
-
|
|
1554
|
+
let newCommon = window.getSelection().getRangeAt(0).commonAncestorContainer;
|
|
1761
1555
|
if (newCommon.nodeType === 3) newCommon = newCommon.parentNode;
|
|
1762
1556
|
if (newCommon && newCommon !== editor) {
|
|
1763
1557
|
newCommon.style.lineHeight = value;
|
|
@@ -1772,19 +1566,19 @@ function RichTextEditor(_ref) {
|
|
|
1772
1566
|
triggerChange();
|
|
1773
1567
|
focus();
|
|
1774
1568
|
};
|
|
1775
|
-
|
|
1776
|
-
|
|
1569
|
+
const applyFontSize = size => {
|
|
1570
|
+
const sel = window.getSelection();
|
|
1777
1571
|
if (!sel || !sel.rangeCount) return;
|
|
1778
|
-
|
|
1779
|
-
|
|
1572
|
+
const range = sel.getRangeAt(0);
|
|
1573
|
+
const sizePx = `${size}px`;
|
|
1780
1574
|
|
|
1781
1575
|
// Collapsed selection (cursor only): insert a styled zero-width span
|
|
1782
1576
|
if (range.collapsed) {
|
|
1783
|
-
|
|
1577
|
+
const span = document.createElement("span");
|
|
1784
1578
|
span.style.fontSize = sizePx;
|
|
1785
1579
|
span.appendChild(document.createTextNode("\u200B"));
|
|
1786
1580
|
range.insertNode(span);
|
|
1787
|
-
|
|
1581
|
+
const newRange = document.createRange();
|
|
1788
1582
|
newRange.setStart(span.firstChild, 1);
|
|
1789
1583
|
newRange.collapse(true);
|
|
1790
1584
|
sel.removeAllRanges();
|
|
@@ -1796,42 +1590,41 @@ function RichTextEditor(_ref) {
|
|
|
1796
1590
|
|
|
1797
1591
|
// Extended selection (highlighted text)
|
|
1798
1592
|
try {
|
|
1799
|
-
|
|
1593
|
+
const editor = editorRef.current;
|
|
1800
1594
|
if (!editor) return;
|
|
1801
1595
|
|
|
1802
1596
|
// We will iterate through all the text nodes in the selection
|
|
1803
|
-
|
|
1804
|
-
acceptNode:
|
|
1597
|
+
const walker = document.createTreeWalker(editor, NodeFilter.SHOW_TEXT, {
|
|
1598
|
+
acceptNode: node => {
|
|
1805
1599
|
return range.intersectsNode(node) ? NodeFilter.FILTER_ACCEPT : NodeFilter.FILTER_REJECT;
|
|
1806
1600
|
}
|
|
1807
1601
|
}, false);
|
|
1808
|
-
|
|
1809
|
-
|
|
1602
|
+
let node;
|
|
1603
|
+
const nodesToStyle = [];
|
|
1810
1604
|
while (node = walker.nextNode()) {
|
|
1811
1605
|
nodesToStyle.push(node);
|
|
1812
1606
|
}
|
|
1813
|
-
|
|
1814
|
-
|
|
1607
|
+
const savedRange = range.cloneRange();
|
|
1608
|
+
let lastInsertedNode = null;
|
|
1815
1609
|
|
|
1816
1610
|
// Iterate through the selected text nodes and wrap them in spans
|
|
1817
|
-
for (
|
|
1818
|
-
|
|
1819
|
-
var parent = textNode.parentNode;
|
|
1611
|
+
for (const textNode of nodesToStyle) {
|
|
1612
|
+
const parent = textNode.parentNode;
|
|
1820
1613
|
|
|
1821
1614
|
// This is important: check if the parent is a block-level element
|
|
1822
1615
|
// like a list item or paragraph. If so, we want to style the block
|
|
1823
1616
|
// itself to avoid breaking its structure.
|
|
1824
|
-
|
|
1617
|
+
const isBlockLevel = ['P', 'H1', 'H2', 'H3', 'H4', 'H5', 'H6', 'LI', 'BLOCKQUOTE'].includes(parent.tagName);
|
|
1825
1618
|
if (isBlockLevel) {
|
|
1826
1619
|
parent.style.fontSize = sizePx;
|
|
1827
1620
|
} else {
|
|
1828
1621
|
// For inline text, wrap the selected portion in a new span
|
|
1829
|
-
|
|
1830
|
-
|
|
1831
|
-
|
|
1622
|
+
const startOffset = textNode === savedRange.startContainer ? savedRange.startOffset : 0;
|
|
1623
|
+
const endOffset = textNode === savedRange.endContainer ? savedRange.endOffset : textNode.length;
|
|
1624
|
+
const newSpan = document.createElement("span");
|
|
1832
1625
|
newSpan.style.fontSize = sizePx;
|
|
1833
1626
|
newSpan.textContent = textNode.textContent.substring(startOffset, endOffset);
|
|
1834
|
-
|
|
1627
|
+
const tempRange = document.createRange();
|
|
1835
1628
|
tempRange.setStart(textNode, startOffset);
|
|
1836
1629
|
tempRange.setEnd(textNode, endOffset);
|
|
1837
1630
|
tempRange.deleteContents();
|
|
@@ -1842,11 +1635,11 @@ function RichTextEditor(_ref) {
|
|
|
1842
1635
|
|
|
1843
1636
|
// After styling, we need to correctly position the cursor
|
|
1844
1637
|
if (lastInsertedNode) {
|
|
1845
|
-
|
|
1846
|
-
|
|
1847
|
-
|
|
1638
|
+
const newRange = document.createRange();
|
|
1639
|
+
newRange.setStartAfter(lastInsertedNode);
|
|
1640
|
+
newRange.collapse(true);
|
|
1848
1641
|
sel.removeAllRanges();
|
|
1849
|
-
sel.addRange(
|
|
1642
|
+
sel.addRange(newRange);
|
|
1850
1643
|
} else {
|
|
1851
1644
|
// If no nodes were wrapped (e.g., we styled a block), restore the original selection
|
|
1852
1645
|
sel.removeAllRanges();
|
|
@@ -1858,65 +1651,59 @@ function RichTextEditor(_ref) {
|
|
|
1858
1651
|
triggerChange();
|
|
1859
1652
|
focus();
|
|
1860
1653
|
};
|
|
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);
|
|
1654
|
+
const handleInput = useCallback(() => {
|
|
1655
|
+
if (editorRef.current) {
|
|
1656
|
+
const next = getCleanHtml();
|
|
1657
|
+
setHtml(next);
|
|
1658
|
+
lastSynchronizedHtmlRef.current = next;
|
|
1659
|
+
onChange && onChange(next);
|
|
1660
|
+
updateMetrics();
|
|
1661
|
+
}
|
|
1662
|
+
}, [onChange, updateMetrics]);
|
|
1663
|
+
const handleImageUpload = async e => {
|
|
1664
|
+
const file = e.target.files[0];
|
|
1665
|
+
if (!file) return;
|
|
1666
|
+
try {
|
|
1667
|
+
setIsUploading(true);
|
|
1668
|
+
const uploadPromise = onImageUpload ? onImageUpload(file) : readFileAsDataURL(file);
|
|
1669
|
+
uploadPromise.then(url => {
|
|
1670
|
+
if (url) {
|
|
1671
|
+
const finalUrl = typeof url === 'object' && url !== null && url.mediaUrl ? url.mediaUrl : url;
|
|
1672
|
+
insertImage(finalUrl, file.name);
|
|
1901
1673
|
}
|
|
1902
|
-
|
|
1903
|
-
|
|
1904
|
-
|
|
1905
|
-
|
|
1906
|
-
|
|
1907
|
-
|
|
1908
|
-
|
|
1674
|
+
setIsUploading(false);
|
|
1675
|
+
e.target.value = null;
|
|
1676
|
+
}).catch(error => {
|
|
1677
|
+
console.error('Error uploading image:', error);
|
|
1678
|
+
setIsUploading(false);
|
|
1679
|
+
});
|
|
1680
|
+
} catch (error) {
|
|
1681
|
+
console.error('Error uploading image:', error);
|
|
1682
|
+
setIsUploading(false);
|
|
1683
|
+
}
|
|
1684
|
+
};
|
|
1685
|
+
useEffect(() => {
|
|
1909
1686
|
// If disabled is explicitly false, make sure the editor is not editable
|
|
1910
1687
|
if (disabled === true) {
|
|
1911
1688
|
setEditable(false);
|
|
1912
1689
|
}
|
|
1913
1690
|
}, [disabled]);
|
|
1914
|
-
|
|
1915
|
-
setSelectionVersion(
|
|
1916
|
-
|
|
1917
|
-
|
|
1691
|
+
const handleEditorClick = useCallback(e => {
|
|
1692
|
+
setSelectionVersion(v => v + 1);
|
|
1693
|
+
const deleteBtn = e.target.closest('button[title="Remove image"], button[title="Remove video"]');
|
|
1694
|
+
if (deleteBtn && editable && editorFocused) {
|
|
1695
|
+
e.preventDefault();
|
|
1696
|
+
e.stopPropagation();
|
|
1697
|
+
const wrapper = deleteBtn.closest('.image-container, .video-container');
|
|
1698
|
+
if (wrapper) {
|
|
1699
|
+
wrapper.remove();
|
|
1700
|
+
triggerChange();
|
|
1701
|
+
}
|
|
1702
|
+
return;
|
|
1703
|
+
}
|
|
1704
|
+
|
|
1918
1705
|
// Check if the click is on a link
|
|
1919
|
-
|
|
1706
|
+
const clickedLink = e.target.closest('a');
|
|
1920
1707
|
if (clickedLink) {
|
|
1921
1708
|
e.preventDefault();
|
|
1922
1709
|
e.stopPropagation();
|
|
@@ -1925,11 +1712,10 @@ function RichTextEditor(_ref) {
|
|
|
1925
1712
|
}
|
|
1926
1713
|
|
|
1927
1714
|
// NEW: Check if click is on an image for resizing
|
|
1928
|
-
|
|
1715
|
+
const clickedImg = e.target.closest('img');
|
|
1929
1716
|
if (clickedImg && !clickedImg.closest('.rte-modal')) {
|
|
1930
1717
|
setSelectedImage(clickedImg);
|
|
1931
|
-
|
|
1932
|
-
} else if (!e.target.closest('.resize-handle')) {
|
|
1718
|
+
} else if (!e.target.closest('.rte-image-toolbar')) {
|
|
1933
1719
|
setSelectedImage(null);
|
|
1934
1720
|
}
|
|
1935
1721
|
|
|
@@ -1942,120 +1728,85 @@ function RichTextEditor(_ref) {
|
|
|
1942
1728
|
// Only allow setting editable to true if not disabled
|
|
1943
1729
|
if (!editable && disabled !== true) {
|
|
1944
1730
|
setEditable(true);
|
|
1945
|
-
setTimeout(
|
|
1731
|
+
setTimeout(() => {
|
|
1946
1732
|
if (editorRef.current) {
|
|
1947
1733
|
editorRef.current.focus();
|
|
1948
1734
|
}
|
|
1949
1735
|
}, 0);
|
|
1950
1736
|
}
|
|
1951
|
-
}, [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'
|
|
2004
|
-
}
|
|
2005
|
-
}, {
|
|
2006
|
-
id: 'ne',
|
|
2007
|
-
style: {
|
|
2008
|
-
top: top - 5,
|
|
2009
|
-
left: left + width - 5,
|
|
2010
|
-
cursor: 'ne-resize'
|
|
1737
|
+
}, [editable, disabled, editorFocused, triggerChange]);
|
|
1738
|
+
const renderImageToolbar = () => {
|
|
1739
|
+
if (!selectedImage || !editorRef.current || !editable) return null;
|
|
1740
|
+
const editorRect = editorRef.current.getBoundingClientRect();
|
|
1741
|
+
const imgRect = selectedImage.getBoundingClientRect();
|
|
1742
|
+
const top = imgRect.top - editorRect.top + editorRef.current.scrollTop;
|
|
1743
|
+
const left = imgRect.left - editorRect.left + editorRef.current.scrollLeft;
|
|
1744
|
+
const width = imgRect.width;
|
|
1745
|
+
const handleAlignment = align => {
|
|
1746
|
+
const wrapper = selectedImage.closest('.image-container');
|
|
1747
|
+
if (wrapper) {
|
|
1748
|
+
// Remove all alignment classes first
|
|
1749
|
+
wrapper.classList.remove('image-align-left', 'image-align-center', 'image-align-right');
|
|
1750
|
+
// Add the new alignment class
|
|
1751
|
+
wrapper.classList.add(`image-align-${align}`);
|
|
1752
|
+
selectedImage.setAttribute('data-align', align);
|
|
1753
|
+
triggerChange();
|
|
2011
1754
|
}
|
|
2012
|
-
}
|
|
2013
|
-
|
|
2014
|
-
|
|
2015
|
-
|
|
2016
|
-
|
|
2017
|
-
|
|
1755
|
+
};
|
|
1756
|
+
const removeImage = () => {
|
|
1757
|
+
const wrapper = selectedImage.closest('.image-container');
|
|
1758
|
+
if (wrapper) {
|
|
1759
|
+
wrapper.remove();
|
|
1760
|
+
setSelectedImage(null);
|
|
1761
|
+
triggerChange();
|
|
2018
1762
|
}
|
|
2019
|
-
}
|
|
2020
|
-
|
|
2021
|
-
|
|
2022
|
-
|
|
2023
|
-
|
|
2024
|
-
|
|
1763
|
+
};
|
|
1764
|
+
const toggleSize = () => {
|
|
1765
|
+
const wrapper = selectedImage.closest('.image-container');
|
|
1766
|
+
if (wrapper) {
|
|
1767
|
+
const isSmall = wrapper.classList.contains('image-small');
|
|
1768
|
+
if (isSmall) {
|
|
1769
|
+
wrapper.classList.remove('image-small');
|
|
1770
|
+
} else {
|
|
1771
|
+
wrapper.classList.add('image-small');
|
|
1772
|
+
}
|
|
1773
|
+
triggerChange();
|
|
2025
1774
|
}
|
|
2026
|
-
}
|
|
1775
|
+
};
|
|
2027
1776
|
return /*#__PURE__*/React.createElement("div", {
|
|
1777
|
+
className: "rte-image-toolbar",
|
|
2028
1778
|
style: {
|
|
2029
1779
|
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'
|
|
1780
|
+
top: Math.max(0, top - 45),
|
|
1781
|
+
left: Math.max(0, left + width / 2 - 80),
|
|
1782
|
+
zIndex: 1000
|
|
2045
1783
|
}
|
|
2046
|
-
}
|
|
2047
|
-
|
|
2048
|
-
|
|
2049
|
-
|
|
2050
|
-
|
|
2051
|
-
|
|
2052
|
-
|
|
2053
|
-
|
|
2054
|
-
|
|
2055
|
-
|
|
2056
|
-
|
|
2057
|
-
|
|
1784
|
+
}, /*#__PURE__*/React.createElement("button", {
|
|
1785
|
+
type: "button",
|
|
1786
|
+
onClick: () => handleAlignment('left'),
|
|
1787
|
+
title: "Align Left"
|
|
1788
|
+
}, "L"), /*#__PURE__*/React.createElement("button", {
|
|
1789
|
+
type: "button",
|
|
1790
|
+
onClick: () => handleAlignment('center'),
|
|
1791
|
+
title: "Align Center"
|
|
1792
|
+
}, "C"), /*#__PURE__*/React.createElement("button", {
|
|
1793
|
+
type: "button",
|
|
1794
|
+
onClick: () => handleAlignment('right'),
|
|
1795
|
+
title: "Align Right"
|
|
1796
|
+
}, "R"), /*#__PURE__*/React.createElement("button", {
|
|
1797
|
+
type: "button",
|
|
1798
|
+
onClick: toggleSize,
|
|
1799
|
+
title: "Toggle 50% Width"
|
|
1800
|
+
}, "50%"), /*#__PURE__*/React.createElement("button", {
|
|
1801
|
+
type: "button",
|
|
1802
|
+
onClick: removeImage,
|
|
1803
|
+
className: "danger",
|
|
1804
|
+
title: "Remove Image"
|
|
1805
|
+
}, "\xD7"));
|
|
2058
1806
|
};
|
|
1807
|
+
if (isLoading) {
|
|
1808
|
+
return /*#__PURE__*/React.createElement(Spinner, null);
|
|
1809
|
+
}
|
|
2059
1810
|
return /*#__PURE__*/React.createElement("div", {
|
|
2060
1811
|
className: "rte-main-wrapper",
|
|
2061
1812
|
style: {
|
|
@@ -2068,21 +1819,21 @@ function RichTextEditor(_ref) {
|
|
|
2068
1819
|
},
|
|
2069
1820
|
className: !showBorder ? "" : "rte-container",
|
|
2070
1821
|
onClick: handleEditorClick,
|
|
2071
|
-
onMouseOver:
|
|
2072
|
-
|
|
1822
|
+
onMouseOver: e => {
|
|
1823
|
+
const table = e.target.closest('table');
|
|
2073
1824
|
if (table && editorRef.current.contains(table)) {
|
|
2074
1825
|
setHoveredTable(table);
|
|
2075
1826
|
}
|
|
2076
1827
|
},
|
|
2077
|
-
onMouseOut:
|
|
2078
|
-
|
|
2079
|
-
|
|
1828
|
+
onMouseOut: e => {
|
|
1829
|
+
const table = e.target.closest('table');
|
|
1830
|
+
const related = e.relatedTarget;
|
|
2080
1831
|
if (table && (!related || !table.contains(related)) && !(related !== null && related !== void 0 && related.closest('.rte-table-delete-hover'))) {
|
|
2081
1832
|
setHoveredTable(null);
|
|
2082
1833
|
}
|
|
2083
1834
|
},
|
|
2084
1835
|
onDrop: handleDrop,
|
|
2085
|
-
onDragOver:
|
|
1836
|
+
onDragOver: e => {
|
|
2086
1837
|
e.preventDefault();
|
|
2087
1838
|
e.stopPropagation();
|
|
2088
1839
|
}
|
|
@@ -2091,40 +1842,40 @@ function RichTextEditor(_ref) {
|
|
|
2091
1842
|
}, /*#__PURE__*/React.createElement("button", {
|
|
2092
1843
|
type: "button",
|
|
2093
1844
|
title: "Bold",
|
|
2094
|
-
onClick:
|
|
1845
|
+
onClick: e => {
|
|
2095
1846
|
e.preventDefault();
|
|
2096
1847
|
e.stopPropagation();
|
|
2097
1848
|
document.execCommand("bold");
|
|
2098
1849
|
handleInput();
|
|
2099
1850
|
focus();
|
|
2100
1851
|
},
|
|
2101
|
-
className:
|
|
1852
|
+
className: `rte-toolbar-button ${isBold ? "active" : ""}`
|
|
2102
1853
|
}, /*#__PURE__*/React.createElement(FaBold, {
|
|
2103
1854
|
size: 14
|
|
2104
1855
|
})), /*#__PURE__*/React.createElement("button", {
|
|
2105
1856
|
type: "button",
|
|
2106
1857
|
title: "Italic",
|
|
2107
|
-
onClick:
|
|
1858
|
+
onClick: e => {
|
|
2108
1859
|
e.preventDefault();
|
|
2109
1860
|
e.stopPropagation();
|
|
2110
1861
|
document.execCommand("italic");
|
|
2111
1862
|
handleInput();
|
|
2112
1863
|
focus();
|
|
2113
1864
|
},
|
|
2114
|
-
className:
|
|
1865
|
+
className: `rte-toolbar-button ${isItalic ? "active" : ""}`
|
|
2115
1866
|
}, /*#__PURE__*/React.createElement(FaItalic, {
|
|
2116
1867
|
size: 14
|
|
2117
1868
|
})), /*#__PURE__*/React.createElement("button", {
|
|
2118
1869
|
type: "button",
|
|
2119
1870
|
title: "Underline",
|
|
2120
|
-
onClick:
|
|
1871
|
+
onClick: e => {
|
|
2121
1872
|
e.preventDefault();
|
|
2122
1873
|
e.stopPropagation();
|
|
2123
1874
|
document.execCommand("underline");
|
|
2124
1875
|
handleInput();
|
|
2125
1876
|
focus();
|
|
2126
1877
|
},
|
|
2127
|
-
className:
|
|
1878
|
+
className: `rte-toolbar-button ${isUnderline ? "active" : ""}`
|
|
2128
1879
|
}, /*#__PURE__*/React.createElement(FaUnderline, {
|
|
2129
1880
|
size: 14
|
|
2130
1881
|
})), /*#__PURE__*/React.createElement("div", {
|
|
@@ -2136,13 +1887,11 @@ function RichTextEditor(_ref) {
|
|
|
2136
1887
|
}
|
|
2137
1888
|
}), /*#__PURE__*/React.createElement("select", {
|
|
2138
1889
|
value: currentFontSize,
|
|
2139
|
-
onMouseDown:
|
|
2140
|
-
|
|
2141
|
-
},
|
|
2142
|
-
onChange: function onChange(e) {
|
|
1890
|
+
onMouseDown: e => e.stopPropagation(),
|
|
1891
|
+
onChange: e => {
|
|
2143
1892
|
e.preventDefault();
|
|
2144
1893
|
e.stopPropagation();
|
|
2145
|
-
|
|
1894
|
+
const size = e.target.value;
|
|
2146
1895
|
if (!size) return;
|
|
2147
1896
|
applyFontSize(size);
|
|
2148
1897
|
setCurrentFontSize(size);
|
|
@@ -2152,12 +1901,10 @@ function RichTextEditor(_ref) {
|
|
|
2152
1901
|
style: {
|
|
2153
1902
|
width: '70px'
|
|
2154
1903
|
}
|
|
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", {
|
|
1904
|
+
}, [8, 10, 12, 14, 16, 18, 20, 24, 28, 32, 36, 40, 48].map(s => /*#__PURE__*/React.createElement("option", {
|
|
1905
|
+
key: s,
|
|
1906
|
+
value: s
|
|
1907
|
+
}, s, "px"))), /*#__PURE__*/React.createElement("label", {
|
|
2161
1908
|
title: "Font Color",
|
|
2162
1909
|
className: "rte-color-picker-label"
|
|
2163
1910
|
}, /*#__PURE__*/React.createElement(FaFont, {
|
|
@@ -2168,11 +1915,11 @@ function RichTextEditor(_ref) {
|
|
|
2168
1915
|
}), /*#__PURE__*/React.createElement("input", {
|
|
2169
1916
|
type: "color",
|
|
2170
1917
|
value: fontColor,
|
|
2171
|
-
onMouseDown:
|
|
1918
|
+
onMouseDown: e => {
|
|
2172
1919
|
e.preventDefault();
|
|
2173
1920
|
e.stopPropagation();
|
|
2174
1921
|
},
|
|
2175
|
-
onChange:
|
|
1922
|
+
onChange: e => {
|
|
2176
1923
|
e.stopPropagation();
|
|
2177
1924
|
handleColorChange(e.target.value);
|
|
2178
1925
|
},
|
|
@@ -2187,8 +1934,8 @@ function RichTextEditor(_ref) {
|
|
|
2187
1934
|
}), /*#__PURE__*/React.createElement("button", {
|
|
2188
1935
|
type: "button",
|
|
2189
1936
|
title: "Align Left",
|
|
2190
|
-
className:
|
|
2191
|
-
onMouseDown:
|
|
1937
|
+
className: `rte-toolbar-button ${activeAlign === "left" ? "active" : ""}`,
|
|
1938
|
+
onMouseDown: e => {
|
|
2192
1939
|
e.preventDefault();
|
|
2193
1940
|
exec("justifyLeft");
|
|
2194
1941
|
setActiveAlign("left");
|
|
@@ -2198,8 +1945,8 @@ function RichTextEditor(_ref) {
|
|
|
2198
1945
|
})), /*#__PURE__*/React.createElement("button", {
|
|
2199
1946
|
type: "button",
|
|
2200
1947
|
title: "Align Center",
|
|
2201
|
-
className:
|
|
2202
|
-
onMouseDown:
|
|
1948
|
+
className: `rte-toolbar-button ${activeAlign === "center" ? "active" : ""}`,
|
|
1949
|
+
onMouseDown: e => {
|
|
2203
1950
|
e.preventDefault();
|
|
2204
1951
|
exec("justifyCenter");
|
|
2205
1952
|
setActiveAlign("center");
|
|
@@ -2209,8 +1956,8 @@ function RichTextEditor(_ref) {
|
|
|
2209
1956
|
})), /*#__PURE__*/React.createElement("button", {
|
|
2210
1957
|
type: "button",
|
|
2211
1958
|
title: "Align Right",
|
|
2212
|
-
className:
|
|
2213
|
-
onMouseDown:
|
|
1959
|
+
className: `rte-toolbar-button ${activeAlign === "right" ? "active" : ""}`,
|
|
1960
|
+
onMouseDown: e => {
|
|
2214
1961
|
e.preventDefault();
|
|
2215
1962
|
exec("justifyRight");
|
|
2216
1963
|
setActiveAlign("right");
|
|
@@ -2227,21 +1974,21 @@ function RichTextEditor(_ref) {
|
|
|
2227
1974
|
}), /*#__PURE__*/React.createElement("button", {
|
|
2228
1975
|
type: "button",
|
|
2229
1976
|
title: "Unordered List",
|
|
2230
|
-
onMouseDown:
|
|
1977
|
+
onMouseDown: e => {
|
|
2231
1978
|
e.preventDefault();
|
|
2232
1979
|
handleSelect("unordered");
|
|
2233
1980
|
},
|
|
2234
|
-
className:
|
|
1981
|
+
className: `rte-toolbar-button ${currentListType === "unordered" ? "active" : ""}`
|
|
2235
1982
|
}, /*#__PURE__*/React.createElement(FaListUl, {
|
|
2236
1983
|
size: 14
|
|
2237
1984
|
})), /*#__PURE__*/React.createElement("button", {
|
|
2238
1985
|
type: "button",
|
|
2239
1986
|
title: "Ordered List",
|
|
2240
|
-
onMouseDown:
|
|
1987
|
+
onMouseDown: e => {
|
|
2241
1988
|
e.preventDefault();
|
|
2242
1989
|
handleSelect("ordered");
|
|
2243
1990
|
},
|
|
2244
|
-
className:
|
|
1991
|
+
className: `rte-toolbar-button ${currentListType === "ordered" ? "active" : ""}`
|
|
2245
1992
|
}, /*#__PURE__*/React.createElement(FaListOl, {
|
|
2246
1993
|
size: 14
|
|
2247
1994
|
})), /*#__PURE__*/React.createElement("div", {
|
|
@@ -2252,12 +1999,10 @@ function RichTextEditor(_ref) {
|
|
|
2252
1999
|
}
|
|
2253
2000
|
}, /*#__PURE__*/React.createElement("select", {
|
|
2254
2001
|
value: currentLineHeight,
|
|
2255
|
-
onMouseDown:
|
|
2256
|
-
|
|
2257
|
-
},
|
|
2258
|
-
onChange: function onChange(e) {
|
|
2002
|
+
onMouseDown: e => e.stopPropagation(),
|
|
2003
|
+
onChange: e => {
|
|
2259
2004
|
e.preventDefault();
|
|
2260
|
-
|
|
2005
|
+
const height = e.target.value;
|
|
2261
2006
|
if (height) {
|
|
2262
2007
|
onLineHeightChange(height);
|
|
2263
2008
|
setCurrentLineHeight(height);
|
|
@@ -2272,12 +2017,10 @@ function RichTextEditor(_ref) {
|
|
|
2272
2017
|
}, /*#__PURE__*/React.createElement("option", {
|
|
2273
2018
|
value: "",
|
|
2274
2019
|
disabled: true
|
|
2275
|
-
}, "\u2195"), ['1', '1.15', '1.5', '2'].map(
|
|
2276
|
-
|
|
2277
|
-
|
|
2278
|
-
|
|
2279
|
-
}, h);
|
|
2280
|
-
})), /*#__PURE__*/React.createElement("div", {
|
|
2020
|
+
}, "\u2195"), ['1', '1.15', '1.5', '2'].map(h => /*#__PURE__*/React.createElement("option", {
|
|
2021
|
+
key: h,
|
|
2022
|
+
value: h
|
|
2023
|
+
}, h))), /*#__PURE__*/React.createElement("div", {
|
|
2281
2024
|
style: {
|
|
2282
2025
|
position: 'absolute',
|
|
2283
2026
|
left: '6px',
|
|
@@ -2304,7 +2047,7 @@ function RichTextEditor(_ref) {
|
|
|
2304
2047
|
type: "button",
|
|
2305
2048
|
title: "Add Link",
|
|
2306
2049
|
className: "rte-toolbar-button",
|
|
2307
|
-
onMouseDown:
|
|
2050
|
+
onMouseDown: e => {
|
|
2308
2051
|
e.preventDefault();
|
|
2309
2052
|
addLink();
|
|
2310
2053
|
}
|
|
@@ -2324,7 +2067,7 @@ function RichTextEditor(_ref) {
|
|
|
2324
2067
|
}), /*#__PURE__*/React.createElement("button", {
|
|
2325
2068
|
type: "button",
|
|
2326
2069
|
className: "rte-toolbar-button",
|
|
2327
|
-
onMouseDown:
|
|
2070
|
+
onMouseDown: e => {
|
|
2328
2071
|
var _fileInputRef$current;
|
|
2329
2072
|
e.preventDefault();
|
|
2330
2073
|
if (!isUploading) (_fileInputRef$current = fileInputRef.current) === null || _fileInputRef$current === void 0 || _fileInputRef$current.click();
|
|
@@ -2351,9 +2094,9 @@ function RichTextEditor(_ref) {
|
|
|
2351
2094
|
type: "button",
|
|
2352
2095
|
title: "Insert Table",
|
|
2353
2096
|
className: "rte-toolbar-button",
|
|
2354
|
-
onMouseDown:
|
|
2097
|
+
onMouseDown: e => {
|
|
2355
2098
|
e.preventDefault();
|
|
2356
|
-
|
|
2099
|
+
const sel = window.getSelection();
|
|
2357
2100
|
if (sel && sel.rangeCount > 0) {
|
|
2358
2101
|
selectionRangeRef.current = sel.getRangeAt(0).cloneRange();
|
|
2359
2102
|
}
|
|
@@ -2364,20 +2107,20 @@ function RichTextEditor(_ref) {
|
|
|
2364
2107
|
})), /*#__PURE__*/React.createElement("button", {
|
|
2365
2108
|
type: "button",
|
|
2366
2109
|
title: "Embed Video (YouTube, Vimeo, etc.)",
|
|
2367
|
-
className:
|
|
2368
|
-
onMouseDown:
|
|
2110
|
+
className: `rte-toolbar-button ${videoModalOpen ? 'active' : ''}`,
|
|
2111
|
+
onMouseDown: e => {
|
|
2369
2112
|
e.preventDefault();
|
|
2370
2113
|
saveSelection();
|
|
2371
2114
|
setVideoModalOpen(true);
|
|
2372
2115
|
}
|
|
2373
2116
|
}, /*#__PURE__*/React.createElement(FaVideo, {
|
|
2374
2117
|
size: 14
|
|
2375
|
-
})),
|
|
2118
|
+
})), (() => {
|
|
2376
2119
|
if (typeof window === "undefined") return null;
|
|
2377
|
-
|
|
2120
|
+
const sel = window.getSelection();
|
|
2378
2121
|
// Robust check: inside cell OR the table itself is selected
|
|
2379
|
-
|
|
2380
|
-
|
|
2122
|
+
const isCell = sel && sel.rangeCount > 0 && sel.anchorNode && (findParentTag(sel.anchorNode, 'TD') || findParentTag(sel.anchorNode, 'TH'));
|
|
2123
|
+
const isTable = sel && sel.rangeCount > 0 && sel.anchorNode && findParentTag(sel.anchorNode, 'TABLE');
|
|
2381
2124
|
if (isCell || isTable) {
|
|
2382
2125
|
return /*#__PURE__*/React.createElement(React.Fragment, null, /*#__PURE__*/React.createElement("div", {
|
|
2383
2126
|
style: {
|
|
@@ -2390,7 +2133,7 @@ function RichTextEditor(_ref) {
|
|
|
2390
2133
|
type: "button",
|
|
2391
2134
|
title: "Add Row Above",
|
|
2392
2135
|
className: "rte-toolbar-button",
|
|
2393
|
-
onMouseDown:
|
|
2136
|
+
onMouseDown: e => {
|
|
2394
2137
|
e.preventDefault();
|
|
2395
2138
|
tableAction('addRowAbove');
|
|
2396
2139
|
}
|
|
@@ -2398,7 +2141,7 @@ function RichTextEditor(_ref) {
|
|
|
2398
2141
|
type: "button",
|
|
2399
2142
|
title: "Add Row Below",
|
|
2400
2143
|
className: "rte-toolbar-button",
|
|
2401
|
-
onMouseDown:
|
|
2144
|
+
onMouseDown: e => {
|
|
2402
2145
|
e.preventDefault();
|
|
2403
2146
|
tableAction('addRowBelow');
|
|
2404
2147
|
}
|
|
@@ -2406,7 +2149,7 @@ function RichTextEditor(_ref) {
|
|
|
2406
2149
|
type: "button",
|
|
2407
2150
|
title: "Add Col Before",
|
|
2408
2151
|
className: "rte-toolbar-button",
|
|
2409
|
-
onMouseDown:
|
|
2152
|
+
onMouseDown: e => {
|
|
2410
2153
|
e.preventDefault();
|
|
2411
2154
|
tableAction('addColBefore');
|
|
2412
2155
|
}
|
|
@@ -2414,7 +2157,7 @@ function RichTextEditor(_ref) {
|
|
|
2414
2157
|
type: "button",
|
|
2415
2158
|
title: "Add Col After",
|
|
2416
2159
|
className: "rte-toolbar-button",
|
|
2417
|
-
onMouseDown:
|
|
2160
|
+
onMouseDown: e => {
|
|
2418
2161
|
e.preventDefault();
|
|
2419
2162
|
tableAction('addColAfter');
|
|
2420
2163
|
}
|
|
@@ -2422,7 +2165,7 @@ function RichTextEditor(_ref) {
|
|
|
2422
2165
|
type: "button",
|
|
2423
2166
|
title: "Merge Cells (Right)",
|
|
2424
2167
|
className: "rte-toolbar-button",
|
|
2425
|
-
onMouseDown:
|
|
2168
|
+
onMouseDown: e => {
|
|
2426
2169
|
e.preventDefault();
|
|
2427
2170
|
tableAction('mergeRight');
|
|
2428
2171
|
}
|
|
@@ -2437,7 +2180,7 @@ function RichTextEditor(_ref) {
|
|
|
2437
2180
|
type: "button",
|
|
2438
2181
|
title: "Delete Row",
|
|
2439
2182
|
className: "rte-toolbar-button rte-toolbar-button-danger",
|
|
2440
|
-
onMouseDown:
|
|
2183
|
+
onMouseDown: e => {
|
|
2441
2184
|
e.preventDefault();
|
|
2442
2185
|
tableAction('deleteRow');
|
|
2443
2186
|
}
|
|
@@ -2451,7 +2194,7 @@ function RichTextEditor(_ref) {
|
|
|
2451
2194
|
type: "button",
|
|
2452
2195
|
title: "Delete Column",
|
|
2453
2196
|
className: "rte-toolbar-button rte-toolbar-button-danger",
|
|
2454
|
-
onMouseDown:
|
|
2197
|
+
onMouseDown: e => {
|
|
2455
2198
|
e.preventDefault();
|
|
2456
2199
|
tableAction('deleteCol');
|
|
2457
2200
|
}
|
|
@@ -2465,7 +2208,7 @@ function RichTextEditor(_ref) {
|
|
|
2465
2208
|
type: "button",
|
|
2466
2209
|
title: "Delete Table",
|
|
2467
2210
|
className: "rte-toolbar-button rte-toolbar-button-danger",
|
|
2468
|
-
onMouseDown:
|
|
2211
|
+
onMouseDown: e => {
|
|
2469
2212
|
e.preventDefault();
|
|
2470
2213
|
tableAction('deleteTable');
|
|
2471
2214
|
}
|
|
@@ -2478,51 +2221,41 @@ function RichTextEditor(_ref) {
|
|
|
2478
2221
|
}, "Table"))));
|
|
2479
2222
|
}
|
|
2480
2223
|
return null;
|
|
2481
|
-
}()), /*#__PURE__*/React.createElement("div", {
|
|
2224
|
+
})()), /*#__PURE__*/React.createElement("div", {
|
|
2482
2225
|
ref: editorRef,
|
|
2483
2226
|
contentEditable: editable && disabled !== true,
|
|
2484
2227
|
suppressContentEditableWarning: true,
|
|
2485
2228
|
onInput: handleInput,
|
|
2486
2229
|
onPaste: handlePaste,
|
|
2487
2230
|
onDrop: handleDrop,
|
|
2488
|
-
onDragStart:
|
|
2489
|
-
|
|
2490
|
-
},
|
|
2491
|
-
onDragOver: function onDragOver(e) {
|
|
2492
|
-
return e.preventDefault();
|
|
2493
|
-
},
|
|
2231
|
+
onDragStart: e => e.preventDefault(),
|
|
2232
|
+
onDragOver: e => e.preventDefault(),
|
|
2494
2233
|
onKeyDown: handleKeyDown,
|
|
2495
2234
|
onClick: handleEditorClick,
|
|
2235
|
+
onFocus: handleEditorFocus,
|
|
2236
|
+
onBlur: handleEditorBlur,
|
|
2496
2237
|
style: {
|
|
2497
2238
|
minHeight: minHeight || '150px',
|
|
2498
2239
|
maxHeight: maxHeight || '500px',
|
|
2499
2240
|
paddingLeft: paddingLeft || '12px'
|
|
2500
2241
|
},
|
|
2501
|
-
className:
|
|
2502
|
-
}),
|
|
2242
|
+
className: `rte-content${editable ? " rte-is-editable" : ""}${editorFocused ? " rte-is-focused" : ""}`
|
|
2243
|
+
}), renderImageToolbar(), /*#__PURE__*/React.createElement("div", {
|
|
2503
2244
|
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", {
|
|
2245
|
+
}, /*#__PURE__*/React.createElement("div", {
|
|
2246
|
+
className: "rte-footer-content"
|
|
2247
|
+
}, /*#__PURE__*/React.createElement("span", {
|
|
2248
|
+
className: "rte-footer-item"
|
|
2249
|
+
}, /*#__PURE__*/React.createElement("b", null, metrics.words), " words"), /*#__PURE__*/React.createElement("span", {
|
|
2250
|
+
className: "rte-footer-separator"
|
|
2251
|
+
}, "\u2022"), /*#__PURE__*/React.createElement("span", {
|
|
2252
|
+
className: "rte-footer-item"
|
|
2253
|
+
}, /*#__PURE__*/React.createElement("b", null, metrics.chars), " characters"))), linkModalOpen && /*#__PURE__*/React.createElement("div", {
|
|
2519
2254
|
className: "rte-modal-overlay",
|
|
2520
2255
|
onClick: cancelLink
|
|
2521
2256
|
}, /*#__PURE__*/React.createElement("div", {
|
|
2522
2257
|
className: "rte-modal",
|
|
2523
|
-
onClick:
|
|
2524
|
-
return e.stopPropagation();
|
|
2525
|
-
}
|
|
2258
|
+
onClick: e => e.stopPropagation()
|
|
2526
2259
|
}, /*#__PURE__*/React.createElement("h3", {
|
|
2527
2260
|
className: "rte-modal-title"
|
|
2528
2261
|
}, "Insert Link"), /*#__PURE__*/React.createElement("div", {
|
|
@@ -2538,9 +2271,7 @@ function RichTextEditor(_ref) {
|
|
|
2538
2271
|
className: "rte-input",
|
|
2539
2272
|
placeholder: "e.g. Google",
|
|
2540
2273
|
value: linkText,
|
|
2541
|
-
onChange:
|
|
2542
|
-
return setLinkText(e.target.value);
|
|
2543
|
-
}
|
|
2274
|
+
onChange: e => setLinkText(e.target.value)
|
|
2544
2275
|
})), /*#__PURE__*/React.createElement("div", {
|
|
2545
2276
|
className: "rte-form-group"
|
|
2546
2277
|
}, /*#__PURE__*/React.createElement("label", {
|
|
@@ -2550,12 +2281,8 @@ function RichTextEditor(_ref) {
|
|
|
2550
2281
|
className: "rte-input",
|
|
2551
2282
|
placeholder: "https://example.com",
|
|
2552
2283
|
value: linkUrl,
|
|
2553
|
-
onChange:
|
|
2554
|
-
|
|
2555
|
-
},
|
|
2556
|
-
onKeyDown: function onKeyDown(e) {
|
|
2557
|
-
return e.key === 'Enter' && confirmLink();
|
|
2558
|
-
},
|
|
2284
|
+
onChange: e => setLinkUrl(e.target.value),
|
|
2285
|
+
onKeyDown: e => e.key === 'Enter' && confirmLink(),
|
|
2559
2286
|
autoFocus: true
|
|
2560
2287
|
}))), /*#__PURE__*/React.createElement("div", {
|
|
2561
2288
|
className: "rte-modal-divider",
|
|
@@ -2575,14 +2302,10 @@ function RichTextEditor(_ref) {
|
|
|
2575
2302
|
disabled: !linkUrl
|
|
2576
2303
|
}, "Insert")))), tableModalOpen && /*#__PURE__*/React.createElement("div", {
|
|
2577
2304
|
className: "rte-modal-overlay",
|
|
2578
|
-
onClick:
|
|
2579
|
-
return setTableModalOpen(false);
|
|
2580
|
-
}
|
|
2305
|
+
onClick: () => setTableModalOpen(false)
|
|
2581
2306
|
}, /*#__PURE__*/React.createElement("div", {
|
|
2582
2307
|
className: "rte-modal",
|
|
2583
|
-
onClick:
|
|
2584
|
-
return e.stopPropagation();
|
|
2585
|
-
}
|
|
2308
|
+
onClick: e => e.stopPropagation()
|
|
2586
2309
|
}, /*#__PURE__*/React.createElement("h3", {
|
|
2587
2310
|
className: "rte-modal-title"
|
|
2588
2311
|
}, "Insert Table"), /*#__PURE__*/React.createElement("div", {
|
|
@@ -2593,9 +2316,7 @@ function RichTextEditor(_ref) {
|
|
|
2593
2316
|
type: "number",
|
|
2594
2317
|
className: "rte-input",
|
|
2595
2318
|
value: tableRows,
|
|
2596
|
-
onChange:
|
|
2597
|
-
return setTableRows(e.target.value);
|
|
2598
|
-
},
|
|
2319
|
+
onChange: e => setTableRows(e.target.value),
|
|
2599
2320
|
min: "1",
|
|
2600
2321
|
max: "10"
|
|
2601
2322
|
})), /*#__PURE__*/React.createElement("div", {
|
|
@@ -2606,9 +2327,7 @@ function RichTextEditor(_ref) {
|
|
|
2606
2327
|
type: "number",
|
|
2607
2328
|
className: "rte-input",
|
|
2608
2329
|
value: tableCols,
|
|
2609
|
-
onChange:
|
|
2610
|
-
return setTableCols(e.target.value);
|
|
2611
|
-
},
|
|
2330
|
+
onChange: e => setTableCols(e.target.value),
|
|
2612
2331
|
min: "1",
|
|
2613
2332
|
max: "10"
|
|
2614
2333
|
})), /*#__PURE__*/React.createElement("div", {
|
|
@@ -2616,23 +2335,17 @@ function RichTextEditor(_ref) {
|
|
|
2616
2335
|
}, /*#__PURE__*/React.createElement("button", {
|
|
2617
2336
|
type: "button",
|
|
2618
2337
|
className: "rte-button rte-button-secondary",
|
|
2619
|
-
onClick:
|
|
2620
|
-
return setTableModalOpen(false);
|
|
2621
|
-
}
|
|
2338
|
+
onClick: () => setTableModalOpen(false)
|
|
2622
2339
|
}, "Cancel"), /*#__PURE__*/React.createElement("button", {
|
|
2623
2340
|
type: "button",
|
|
2624
2341
|
className: "rte-button rte-button-primary",
|
|
2625
2342
|
onClick: insertTable
|
|
2626
2343
|
}, "Insert")))), videoModalOpen && /*#__PURE__*/React.createElement("div", {
|
|
2627
2344
|
className: "rte-modal-overlay",
|
|
2628
|
-
onClick:
|
|
2629
|
-
return setVideoModalOpen(false);
|
|
2630
|
-
}
|
|
2345
|
+
onClick: () => setVideoModalOpen(false)
|
|
2631
2346
|
}, /*#__PURE__*/React.createElement("div", {
|
|
2632
2347
|
className: "rte-modal",
|
|
2633
|
-
onClick:
|
|
2634
|
-
return e.stopPropagation();
|
|
2635
|
-
}
|
|
2348
|
+
onClick: e => e.stopPropagation()
|
|
2636
2349
|
}, /*#__PURE__*/React.createElement("div", {
|
|
2637
2350
|
className: "rte-modal-header"
|
|
2638
2351
|
}, /*#__PURE__*/React.createElement("h3", {
|
|
@@ -2649,12 +2362,10 @@ function RichTextEditor(_ref) {
|
|
|
2649
2362
|
type: "text",
|
|
2650
2363
|
className: "rte-input",
|
|
2651
2364
|
value: videoUrl,
|
|
2652
|
-
onChange:
|
|
2653
|
-
return setVideoUrl(e.target.value);
|
|
2654
|
-
},
|
|
2365
|
+
onChange: e => setVideoUrl(e.target.value),
|
|
2655
2366
|
placeholder: "Paste URL here...",
|
|
2656
2367
|
autoFocus: true,
|
|
2657
|
-
onKeyDown:
|
|
2368
|
+
onKeyDown: e => {
|
|
2658
2369
|
if (e.key === 'Enter' && videoUrl.trim()) insertVideo();
|
|
2659
2370
|
if (e.key === 'Escape') setVideoModalOpen(false);
|
|
2660
2371
|
}
|
|
@@ -2663,13 +2374,11 @@ function RichTextEditor(_ref) {
|
|
|
2663
2374
|
}, /*#__PURE__*/React.createElement("button", {
|
|
2664
2375
|
type: "button",
|
|
2665
2376
|
className: "rte-button rte-button-secondary",
|
|
2666
|
-
onClick:
|
|
2667
|
-
return setVideoModalOpen(false);
|
|
2668
|
-
}
|
|
2377
|
+
onClick: () => setVideoModalOpen(false)
|
|
2669
2378
|
}, "Cancel"), /*#__PURE__*/React.createElement("button", {
|
|
2670
2379
|
type: "button",
|
|
2671
2380
|
className: "rte-button rte-button-primary",
|
|
2672
|
-
onClick:
|
|
2381
|
+
onClick: () => {
|
|
2673
2382
|
if (videoUrl.trim()) {
|
|
2674
2383
|
insertVideo();
|
|
2675
2384
|
}
|
|
@@ -2684,16 +2393,14 @@ function RichTextEditor(_ref) {
|
|
|
2684
2393
|
maxWidth: "90%",
|
|
2685
2394
|
maxHeight: "90%"
|
|
2686
2395
|
},
|
|
2687
|
-
onClick:
|
|
2688
|
-
return e.stopPropagation();
|
|
2689
|
-
}
|
|
2396
|
+
onClick: e => e.stopPropagation()
|
|
2690
2397
|
}, /*#__PURE__*/React.createElement("img", {
|
|
2691
2398
|
src: selectedImageUrl,
|
|
2692
2399
|
style: {
|
|
2693
2400
|
width: "100%",
|
|
2694
2401
|
maxHeight: "90vh",
|
|
2695
2402
|
borderRadius: '12px',
|
|
2696
|
-
transform:
|
|
2403
|
+
transform: `scale(${zoomLevel})`,
|
|
2697
2404
|
transition: "transform 0.2s ease",
|
|
2698
2405
|
boxShadow: '0 25px 50px -12px rgba(0,0,0,0.5)'
|
|
2699
2406
|
},
|
|
@@ -2708,13 +2415,11 @@ function RichTextEditor(_ref) {
|
|
|
2708
2415
|
}, /*#__PURE__*/React.createElement("button", {
|
|
2709
2416
|
type: "button",
|
|
2710
2417
|
className: "rte-button rte-button-secondary",
|
|
2711
|
-
onClick:
|
|
2712
|
-
return setEditable(false);
|
|
2713
|
-
}
|
|
2418
|
+
onClick: () => setEditable(false)
|
|
2714
2419
|
}, "Cancel"), /*#__PURE__*/React.createElement("button", {
|
|
2715
2420
|
type: "button",
|
|
2716
2421
|
className: "rte-button rte-button-primary",
|
|
2717
|
-
onClick:
|
|
2422
|
+
onClick: () => {
|
|
2718
2423
|
onChange && onChange(html);
|
|
2719
2424
|
setEditable(false);
|
|
2720
2425
|
}
|