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