react-lite-rich-text-editor 1.1.2 → 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/README.md +27 -10
- package/dist/index.cjs.js +885 -1399
- package/dist/index.cjs.js.map +1 -1
- package/dist/index.esm.js +885 -1399
- 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
|
-
__html:
|
|
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,191 +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
|
-
setYoutubeUrl = _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
|
-
|
|
819
|
-
|
|
820
|
-
|
|
821
|
-
|
|
492
|
+
const saveSelection = () => {
|
|
493
|
+
if (typeof window === "undefined") return;
|
|
494
|
+
const sel = window.getSelection();
|
|
495
|
+
if (sel && sel.rangeCount > 0) {
|
|
496
|
+
selectionRangeRef.current = sel.getRangeAt(0).cloneRange();
|
|
497
|
+
}
|
|
822
498
|
};
|
|
823
|
-
|
|
824
|
-
setZoomLevel(
|
|
825
|
-
|
|
826
|
-
|
|
499
|
+
const handleZoomIn = () => {
|
|
500
|
+
setZoomLevel(prevZoom => prevZoom + 0.1);
|
|
501
|
+
};
|
|
502
|
+
const handleZoomOut = () => {
|
|
503
|
+
setZoomLevel(prevZoom => Math.max(0.1, prevZoom - 0.1));
|
|
827
504
|
};
|
|
828
505
|
|
|
829
506
|
// Effect to restore scroll position after modal closes
|
|
830
|
-
React.useEffect(
|
|
507
|
+
React.useEffect(() => {
|
|
831
508
|
if (!imageModalOpen && editorRef.current) {
|
|
832
509
|
editorRef.current.scrollTop = scrollTopRef.current;
|
|
833
510
|
}
|
|
834
511
|
}, [imageModalOpen]);
|
|
835
|
-
React.useEffect(
|
|
512
|
+
React.useEffect(() => {
|
|
836
513
|
if (!imageModalOpen) return;
|
|
837
|
-
|
|
514
|
+
const handleKeyDown = e => {
|
|
838
515
|
if (e.key === 'Escape') {
|
|
839
516
|
closeImageModal();
|
|
840
517
|
}
|
|
841
518
|
};
|
|
842
|
-
|
|
519
|
+
const handleWheel = e => {
|
|
843
520
|
if (e.ctrlKey) {
|
|
844
521
|
e.preventDefault();
|
|
845
522
|
if (e.deltaY < 0) {
|
|
@@ -853,127 +530,99 @@ function RichTextEditor(_ref) {
|
|
|
853
530
|
window.addEventListener('wheel', handleWheel, {
|
|
854
531
|
passive: false
|
|
855
532
|
});
|
|
856
|
-
return
|
|
533
|
+
return () => {
|
|
857
534
|
document.removeEventListener('keydown', handleKeyDown);
|
|
858
535
|
window.removeEventListener('wheel', handleWheel);
|
|
859
536
|
};
|
|
860
537
|
}, [imageModalOpen]);
|
|
861
|
-
React.useEffect(
|
|
862
|
-
|
|
538
|
+
React.useEffect(() => {
|
|
539
|
+
const handleClick = e => {
|
|
863
540
|
// Trigger selection update for toolbar reactivity
|
|
864
|
-
setSelectionVersion(
|
|
865
|
-
|
|
866
|
-
});
|
|
867
|
-
var deleteBtn = e.target.closest('button[title="Remove image"]');
|
|
541
|
+
setSelectionVersion(v => v + 1);
|
|
542
|
+
const deleteBtn = e.target.closest('button[title="Remove image"]');
|
|
868
543
|
if (deleteBtn && editable) {
|
|
869
544
|
e.preventDefault();
|
|
870
545
|
e.stopPropagation();
|
|
871
|
-
|
|
546
|
+
const wrapper = deleteBtn.closest('.image-container');
|
|
872
547
|
if (wrapper && wrapper.parentNode) {
|
|
873
548
|
wrapper.parentNode.removeChild(wrapper);
|
|
874
|
-
triggerChange();
|
|
549
|
+
triggerChange && triggerChange();
|
|
875
550
|
}
|
|
876
551
|
}
|
|
877
552
|
};
|
|
878
|
-
|
|
553
|
+
const editor = editorRef.current;
|
|
879
554
|
if (editor) {
|
|
880
555
|
editor.addEventListener('click', handleClick);
|
|
881
|
-
return
|
|
556
|
+
return () => {
|
|
882
557
|
editor.removeEventListener('click', handleClick);
|
|
883
558
|
};
|
|
884
559
|
}
|
|
885
|
-
|
|
886
|
-
|
|
887
|
-
|
|
888
|
-
|
|
889
|
-
|
|
890
|
-
});
|
|
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));
|
|
891
565
|
}
|
|
892
566
|
}, [value]);
|
|
893
567
|
|
|
894
568
|
// Runs whenever editable changes (toggles delete icon visibility)
|
|
895
|
-
React.useEffect(
|
|
569
|
+
React.useEffect(() => {
|
|
896
570
|
processExistingImages(editorRef.current);
|
|
897
|
-
}, [
|
|
898
|
-
React.useEffect(
|
|
899
|
-
// Only update if value is
|
|
900
|
-
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) {
|
|
901
575
|
try {
|
|
902
|
-
|
|
903
|
-
|
|
904
|
-
|
|
905
|
-
|
|
906
|
-
|
|
907
|
-
editorRef.current.innerHTML = htmlContent;
|
|
908
|
-
}
|
|
576
|
+
let newContent = "";
|
|
577
|
+
|
|
578
|
+
// Check if value is a Draft.js content state
|
|
579
|
+
if (isValidDraftFormat(value)) {
|
|
580
|
+
newContent = draftBlocksToHTML(value);
|
|
909
581
|
} else if (typeof value === 'string') {
|
|
910
|
-
//
|
|
911
|
-
|
|
912
|
-
|
|
913
|
-
|
|
914
|
-
|
|
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;
|
|
915
594
|
}
|
|
595
|
+
updateMetrics();
|
|
916
596
|
}
|
|
917
597
|
} catch (e) {
|
|
918
598
|
console.error('Error processing editor content:', e);
|
|
919
|
-
// Fallback to raw value if parsing fails
|
|
920
|
-
var _unescapedValue = typeof value === 'string' ? unescapeHtml(value) : value;
|
|
921
|
-
setHtml(_unescapedValue);
|
|
922
|
-
if (editorRef.current) {
|
|
923
|
-
editorRef.current.innerHTML = _unescapedValue || '';
|
|
924
|
-
}
|
|
925
599
|
}
|
|
926
|
-
} else {
|
|
600
|
+
} else if (!value && html) {
|
|
927
601
|
setHtml('');
|
|
602
|
+
lastSynchronizedHtmlRef.current = "";
|
|
928
603
|
if (editorRef.current) {
|
|
929
604
|
editorRef.current.innerHTML = '';
|
|
605
|
+
updateMetrics();
|
|
930
606
|
}
|
|
931
607
|
}
|
|
932
|
-
}, [
|
|
608
|
+
}, [value, initialEditable, updateMetrics]);
|
|
933
609
|
|
|
934
|
-
// Call onChange whenever html state updates
|
|
935
|
-
React.useEffect(function () {
|
|
936
|
-
onChange && onChange(html);
|
|
937
|
-
}, [html, onChange]);
|
|
938
610
|
// Trigger change manually
|
|
939
|
-
|
|
940
|
-
|
|
611
|
+
const triggerChange = React.useCallback(() => {
|
|
612
|
+
const next = getCleanHtml();
|
|
941
613
|
setHtml(next);
|
|
942
|
-
|
|
943
|
-
|
|
944
|
-
|
|
945
|
-
var detectListType = function detectListType() {
|
|
946
|
-
var sel = window.getSelection();
|
|
947
|
-
if (!sel || !sel.rangeCount) {
|
|
948
|
-
setCurrentListType(null);
|
|
949
|
-
return;
|
|
950
|
-
}
|
|
951
|
-
var node = sel.anchorNode;
|
|
952
|
-
while (node && node !== editorRef.current) {
|
|
953
|
-
if (node.nodeName === "OL") {
|
|
954
|
-
setCurrentListType("ordered");
|
|
955
|
-
return;
|
|
956
|
-
}
|
|
957
|
-
if (node.nodeName === "UL") {
|
|
958
|
-
setCurrentListType("unordered");
|
|
959
|
-
return;
|
|
960
|
-
}
|
|
961
|
-
node = node.parentNode;
|
|
962
|
-
}
|
|
963
|
-
setCurrentListType(null);
|
|
964
|
-
};
|
|
614
|
+
lastSynchronizedHtmlRef.current = next;
|
|
615
|
+
onChange && onChange(next);
|
|
616
|
+
}, [onChange]);
|
|
965
617
|
|
|
966
618
|
// Helper to walk up DOM to find style tags or CSS style:
|
|
967
|
-
|
|
968
|
-
for (var _len = arguments.length, tagNames = new Array(_len > 1 ? _len - 1 : 0), _key = 1; _key < _len; _key++) {
|
|
969
|
-
tagNames[_key - 1] = arguments[_key];
|
|
970
|
-
}
|
|
619
|
+
const isParentStyle = (node, ...tagNames) => {
|
|
971
620
|
while (node && node !== editorRef.current) {
|
|
972
621
|
if (node.nodeType === 1 && tagNames.includes(node.tagName)) return true;
|
|
973
622
|
|
|
974
623
|
// Also check inline style for bold and italic:
|
|
975
624
|
if (node.nodeType === 1 && node.style) {
|
|
976
|
-
|
|
625
|
+
const style = node.style;
|
|
977
626
|
if (tagNames.includes("bold") && (style.fontWeight === "bold" || Number(style.fontWeight) >= 600)) return true;
|
|
978
627
|
if (tagNames.includes("italic") && style.fontStyle === "italic") return true;
|
|
979
628
|
if (tagNames.includes("underline") && style.textDecoration.includes("underline")) return true;
|
|
@@ -991,100 +640,92 @@ function RichTextEditor(_ref) {
|
|
|
991
640
|
return false;
|
|
992
641
|
};
|
|
993
642
|
|
|
994
|
-
// Update style states based on selection or cursor position
|
|
995
|
-
var updateStyleStates = function updateStyleStates() {
|
|
996
|
-
var sel = window.getSelection();
|
|
997
|
-
if (!sel || !sel.rangeCount) {
|
|
998
|
-
setIsBold(false);
|
|
999
|
-
setIsItalic(false);
|
|
1000
|
-
setIsUnderline(false);
|
|
1001
|
-
setFontColor("#000000"); // default
|
|
1002
|
-
return;
|
|
1003
|
-
}
|
|
1004
|
-
var container = sel.anchorNode.nodeType === 3 ? sel.anchorNode.parentNode : sel.anchorNode;
|
|
1005
|
-
var computedAlign = window.getComputedStyle(container).textAlign;
|
|
1006
|
-
setActiveAlign(computedAlign);
|
|
1007
|
-
var range = sel.getRangeAt(0);
|
|
1008
|
-
if (range.collapsed) {
|
|
1009
|
-
// Cursor only, check parent nodes
|
|
1010
|
-
var _container = sel.anchorNode.nodeType === 3 ? sel.anchorNode.parentNode : sel.anchorNode;
|
|
1011
|
-
window.getComputedStyle(_container);
|
|
1012
|
-
setIsBold(isParentStyle(_container, "B", "STRONG", "bold"));
|
|
1013
|
-
setIsItalic(isParentStyle(_container, "I", "EM", "italic"));
|
|
1014
|
-
setIsUnderline(isParentStyle(_container, "U", "underline"));
|
|
1015
|
-
|
|
1016
|
-
// ✅ Get computed color from container
|
|
1017
|
-
var computedColor = window.getComputedStyle(_container).color;
|
|
1018
|
-
setFontColor(rgbToHex(computedColor));
|
|
1019
|
-
} else {
|
|
1020
|
-
// Text selected, use execCommand state
|
|
1021
|
-
setIsBold(document.queryCommandState("bold"));
|
|
1022
|
-
setIsItalic(document.queryCommandState("italic"));
|
|
1023
|
-
setIsUnderline(document.queryCommandState("underline"));
|
|
1024
|
-
|
|
1025
|
-
// ✅ For selection, get color from selection's start container
|
|
1026
|
-
var _container2 = sel.anchorNode.nodeType === 3 ? sel.anchorNode.parentNode : sel.anchorNode;
|
|
1027
|
-
var _computedColor = window.getComputedStyle(_container2).color;
|
|
1028
|
-
setFontColor(rgbToHex(_computedColor));
|
|
1029
|
-
}
|
|
1030
|
-
};
|
|
1031
|
-
|
|
1032
643
|
// Helper to convert rgb() to hex
|
|
1033
644
|
function rgbToHex(rgb) {
|
|
1034
|
-
|
|
645
|
+
const result = rgb.match(/\d+/g);
|
|
1035
646
|
if (!result) return "#000000";
|
|
1036
|
-
return "#" + result.slice(0, 3).map(
|
|
1037
|
-
|
|
647
|
+
return "#" + result.slice(0, 3).map(x => {
|
|
648
|
+
const hex = parseInt(x, 10).toString(16);
|
|
1038
649
|
return hex.length === 1 ? "0" + hex : hex;
|
|
1039
650
|
}).join("");
|
|
1040
651
|
}
|
|
1041
652
|
|
|
1042
|
-
// Listen for selection changes globally to update styles and list type
|
|
1043
|
-
React.useEffect(
|
|
1044
|
-
|
|
1045
|
-
|
|
1046
|
-
|
|
1047
|
-
|
|
1048
|
-
if (!
|
|
1049
|
-
|
|
1050
|
-
|
|
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"]');
|
|
1051
700
|
if (element) {
|
|
1052
|
-
|
|
1053
|
-
|
|
701
|
+
const fontSize = window.getComputedStyle(element).fontSize;
|
|
702
|
+
const sizeValue = fontSize ? parseInt(fontSize) : 16;
|
|
1054
703
|
setCurrentFontSize(sizeValue.toString());
|
|
1055
704
|
} else {
|
|
1056
|
-
setCurrentFontSize("16");
|
|
705
|
+
setCurrentFontSize("16");
|
|
1057
706
|
}
|
|
1058
707
|
};
|
|
1059
|
-
document.addEventListener(
|
|
1060
|
-
return
|
|
1061
|
-
document.removeEventListener("selectionchange",
|
|
1062
|
-
document.removeEventListener("selectionchange", updateStyleStates);
|
|
1063
|
-
document.removeEventListener('selectionchange', handleSelectionChange);
|
|
708
|
+
document.addEventListener("selectionchange", handleGlobalSelectionSync);
|
|
709
|
+
return () => {
|
|
710
|
+
document.removeEventListener("selectionchange", handleGlobalSelectionSync);
|
|
1064
711
|
};
|
|
1065
712
|
}, []);
|
|
1066
|
-
|
|
1067
|
-
|
|
1068
|
-
};
|
|
1069
|
-
var exec = function exec(command) {
|
|
1070
|
-
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) => {
|
|
1071
715
|
document.execCommand(command, false, value);
|
|
1072
716
|
triggerChange();
|
|
1073
717
|
focus();
|
|
1074
718
|
};
|
|
1075
|
-
|
|
1076
|
-
|
|
1077
|
-
fontColor = _useState50[0],
|
|
1078
|
-
setFontColor = _useState50[1];
|
|
1079
|
-
var handleColorChange = function handleColorChange(color) {
|
|
719
|
+
const [fontColor, setFontColor] = React.useState("#000000");
|
|
720
|
+
const handleColorChange = color => {
|
|
1080
721
|
setFontColor(color);
|
|
1081
722
|
exec("foreColor", color);
|
|
1082
723
|
};
|
|
1083
|
-
|
|
1084
|
-
|
|
724
|
+
const addLink = () => {
|
|
725
|
+
const sel = window.getSelection();
|
|
1085
726
|
if (!sel || sel.rangeCount === 0) return;
|
|
1086
727
|
selectionRangeRef.current = sel.getRangeAt(0).cloneRange();
|
|
1087
|
-
|
|
728
|
+
const selectedText = sel.toString();
|
|
1088
729
|
if (selectedText.length > 0) {
|
|
1089
730
|
setLinkText(selectedText);
|
|
1090
731
|
setLinkUrl("");
|
|
@@ -1095,112 +736,108 @@ function RichTextEditor(_ref) {
|
|
|
1095
736
|
setLinkModalOpen(true);
|
|
1096
737
|
}
|
|
1097
738
|
};
|
|
1098
|
-
|
|
739
|
+
const findParentTag = (node, tagName) => {
|
|
1099
740
|
if (!node) return null;
|
|
1100
|
-
|
|
741
|
+
let curr = node;
|
|
1101
742
|
while (curr && curr !== editorRef.current) {
|
|
1102
743
|
if (curr.tagName === tagName) return curr;
|
|
1103
744
|
curr = curr.parentNode;
|
|
1104
745
|
}
|
|
1105
746
|
return null;
|
|
1106
747
|
};
|
|
1107
|
-
|
|
1108
|
-
|
|
748
|
+
const tableAction = action => {
|
|
749
|
+
const sel = window.getSelection();
|
|
1109
750
|
if (!sel || !sel.rangeCount) return;
|
|
1110
|
-
|
|
751
|
+
const cell = findParentTag(sel.anchorNode, 'TD') || findParentTag(sel.anchorNode, 'TH');
|
|
1111
752
|
if (!cell) return;
|
|
1112
|
-
|
|
1113
|
-
|
|
753
|
+
const row = cell.parentNode;
|
|
754
|
+
const table = row.parentNode.closest('table');
|
|
1114
755
|
switch (action) {
|
|
1115
756
|
case 'addRowAbove':
|
|
1116
|
-
|
|
1117
|
-
for (
|
|
1118
|
-
|
|
757
|
+
const newRowAbove = table.insertRow(row.rowIndex);
|
|
758
|
+
for (let i = 0; i < row.cells.length; i++) {
|
|
759
|
+
const newCell = newRowAbove.insertCell(i);
|
|
1119
760
|
newCell.style.border = "1px solid #e5e7eb";
|
|
1120
761
|
newCell.style.padding = "12px";
|
|
1121
762
|
newCell.innerHTML = " ";
|
|
1122
763
|
}
|
|
1123
764
|
break;
|
|
1124
765
|
case 'addRowBelow':
|
|
1125
|
-
|
|
1126
|
-
for (
|
|
1127
|
-
|
|
1128
|
-
|
|
1129
|
-
|
|
1130
|
-
|
|
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 = " ";
|
|
1131
772
|
}
|
|
1132
773
|
break;
|
|
1133
774
|
case 'addColBefore':
|
|
1134
|
-
|
|
1135
|
-
for (
|
|
1136
|
-
|
|
1137
|
-
|
|
1138
|
-
|
|
1139
|
-
|
|
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 = " ";
|
|
1140
781
|
}
|
|
1141
782
|
break;
|
|
1142
783
|
case 'addColAfter':
|
|
1143
|
-
|
|
1144
|
-
for (
|
|
1145
|
-
|
|
1146
|
-
|
|
1147
|
-
|
|
1148
|
-
|
|
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 = " ";
|
|
1149
790
|
}
|
|
1150
791
|
break;
|
|
1151
792
|
case 'deleteRow':
|
|
1152
793
|
{
|
|
1153
|
-
|
|
1154
|
-
|
|
794
|
+
const rowIndex = row.rowIndex;
|
|
795
|
+
const cellIndex = cell.cellIndex;
|
|
1155
796
|
table.deleteRow(rowIndex);
|
|
1156
797
|
if (table.rows.length === 0) {
|
|
1157
798
|
table.remove();
|
|
1158
799
|
} else {
|
|
1159
|
-
|
|
1160
|
-
|
|
1161
|
-
|
|
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)];
|
|
1162
803
|
if (targetCell) {
|
|
1163
|
-
|
|
804
|
+
const range = document.createRange();
|
|
1164
805
|
range.selectNodeContents(targetCell);
|
|
1165
806
|
range.collapse(true);
|
|
1166
807
|
sel.removeAllRanges();
|
|
1167
808
|
sel.addRange(range);
|
|
1168
|
-
setSelectionVersion(
|
|
1169
|
-
return v + 1;
|
|
1170
|
-
});
|
|
809
|
+
setSelectionVersion(v => v + 1);
|
|
1171
810
|
}
|
|
1172
811
|
}
|
|
1173
812
|
break;
|
|
1174
813
|
}
|
|
1175
814
|
case 'deleteCol':
|
|
1176
815
|
{
|
|
1177
|
-
|
|
1178
|
-
|
|
1179
|
-
for (
|
|
1180
|
-
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);
|
|
1181
820
|
}
|
|
1182
821
|
if (table.rows[0].cells.length === 0) {
|
|
1183
822
|
table.remove();
|
|
1184
823
|
} else {
|
|
1185
|
-
var _table$rows$
|
|
1186
|
-
|
|
1187
|
-
|
|
1188
|
-
if (
|
|
1189
|
-
|
|
1190
|
-
|
|
1191
|
-
|
|
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);
|
|
1192
831
|
sel.removeAllRanges();
|
|
1193
|
-
sel.addRange(
|
|
1194
|
-
setSelectionVersion(
|
|
1195
|
-
return v + 1;
|
|
1196
|
-
});
|
|
832
|
+
sel.addRange(range);
|
|
833
|
+
setSelectionVersion(v => v + 1);
|
|
1197
834
|
}
|
|
1198
835
|
}
|
|
1199
836
|
break;
|
|
1200
837
|
}
|
|
1201
838
|
case 'mergeRight':
|
|
1202
839
|
if (cell.nextElementSibling) {
|
|
1203
|
-
|
|
840
|
+
const nextCell = cell.nextElementSibling;
|
|
1204
841
|
cell.colSpan = (cell.colSpan || 1) + (nextCell.colSpan || 1);
|
|
1205
842
|
nextCell.remove();
|
|
1206
843
|
}
|
|
@@ -1211,20 +848,20 @@ function RichTextEditor(_ref) {
|
|
|
1211
848
|
}
|
|
1212
849
|
triggerChange && triggerChange();
|
|
1213
850
|
};
|
|
1214
|
-
|
|
1215
|
-
|
|
1216
|
-
|
|
1217
|
-
|
|
1218
|
-
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++) {
|
|
1219
856
|
tableHtml += '<tr>';
|
|
1220
|
-
for (
|
|
857
|
+
for (let j = 0; j < cols; j++) {
|
|
1221
858
|
tableHtml += '<td style="border: 1px solid #e5e7eb; padding: 12px; min-height: 20px;"> </td>';
|
|
1222
859
|
}
|
|
1223
860
|
tableHtml += '</tr>';
|
|
1224
861
|
}
|
|
1225
862
|
tableHtml += '</tbody></table><p> </p>';
|
|
1226
863
|
if (selectionRangeRef.current) {
|
|
1227
|
-
|
|
864
|
+
const sel = window.getSelection();
|
|
1228
865
|
sel.removeAllRanges();
|
|
1229
866
|
sel.addRange(selectionRangeRef.current);
|
|
1230
867
|
}
|
|
@@ -1232,51 +869,85 @@ function RichTextEditor(_ref) {
|
|
|
1232
869
|
setTableModalOpen(false);
|
|
1233
870
|
triggerChange && triggerChange();
|
|
1234
871
|
};
|
|
1235
|
-
|
|
1236
|
-
|
|
1237
|
-
|
|
1238
|
-
|
|
1239
|
-
|
|
1240
|
-
|
|
1241
|
-
|
|
872
|
+
const parseVideoUrl = url => {
|
|
873
|
+
url = url.trim();
|
|
874
|
+
if (!url) return null;
|
|
875
|
+
|
|
876
|
+
// YouTube
|
|
877
|
+
const ytRegExp = /^.*(youtu.be\/|v\/|u\/\w\/|embed\/|watch\?v=|\&v=|watch\?vi=|\&vi=)([^#\&\?]*).*/;
|
|
878
|
+
const ytMatch = url.match(ytRegExp);
|
|
879
|
+
if (ytMatch && ytMatch[2].length === 11) {
|
|
880
|
+
return `https://www.youtube.com/embed/${ytMatch[2]}`;
|
|
881
|
+
}
|
|
882
|
+
|
|
883
|
+
// Vimeo
|
|
884
|
+
const vimeoRegExp = /vimeo\.com\/(?:channels\/(?:\w+\/)?|groups\/([^\/]*)\/videos\/|album\/(\d+)\/video\/|video\/|)(\d+)(?:$|\/|\?)/;
|
|
885
|
+
const vimeoMatch = url.match(vimeoRegExp);
|
|
886
|
+
if (vimeoMatch && vimeoMatch[3]) {
|
|
887
|
+
return `https://player.vimeo.com/video/${vimeoMatch[3]}`;
|
|
888
|
+
}
|
|
889
|
+
|
|
890
|
+
// DailyMotion
|
|
891
|
+
const dmRegExp = /dailymotion\.com\/video\/([a-zA-Z0-9]+)/;
|
|
892
|
+
const dmMatch = url.match(dmRegExp);
|
|
893
|
+
if (dmMatch && dmMatch[1]) {
|
|
894
|
+
return `https://www.dailymotion.com/embed/video/${dmMatch[1]}`;
|
|
895
|
+
}
|
|
896
|
+
return null;
|
|
897
|
+
};
|
|
898
|
+
const insertVideo = () => {
|
|
899
|
+
const embedUrl = parseVideoUrl(videoUrl);
|
|
900
|
+
if (embedUrl) {
|
|
1242
901
|
if (editorRef.current) {
|
|
1243
902
|
editorRef.current.focus();
|
|
1244
903
|
}
|
|
1245
904
|
if (selectionRangeRef.current) {
|
|
1246
|
-
|
|
905
|
+
const sel = window.getSelection();
|
|
1247
906
|
sel.removeAllRanges();
|
|
1248
907
|
sel.addRange(selectionRangeRef.current);
|
|
1249
908
|
}
|
|
1250
|
-
|
|
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>`;
|
|
1251
917
|
try {
|
|
1252
918
|
document.execCommand("insertHTML", false, embedHtml);
|
|
1253
919
|
} catch (err) {
|
|
1254
|
-
console.error("Failed to insert
|
|
1255
|
-
// Fallback: append to the end of the editor
|
|
920
|
+
console.error("Failed to insert Video HTML:", err);
|
|
1256
921
|
if (editorRef.current) {
|
|
1257
|
-
|
|
922
|
+
const div = document.createElement('div');
|
|
1258
923
|
div.innerHTML = embedHtml;
|
|
1259
924
|
editorRef.current.appendChild(div);
|
|
1260
925
|
}
|
|
1261
926
|
}
|
|
927
|
+
setVideoModalOpen(false);
|
|
928
|
+
setVideoUrl("");
|
|
929
|
+
triggerChange && triggerChange();
|
|
1262
930
|
} else {
|
|
1263
|
-
console.warn("Invalid
|
|
931
|
+
console.warn("Invalid Video URL or Platform not supported");
|
|
1264
932
|
}
|
|
1265
|
-
setYoutubeModalOpen(false);
|
|
1266
|
-
setYoutubeUrl("");
|
|
1267
|
-
triggerChange && triggerChange();
|
|
1268
933
|
};
|
|
1269
|
-
|
|
934
|
+
const processExistingImages = container => {
|
|
1270
935
|
if (!container) return;
|
|
1271
|
-
container.querySelectorAll("img").forEach(
|
|
1272
|
-
//
|
|
1273
|
-
|
|
1274
|
-
if (
|
|
1275
|
-
|
|
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;
|
|
1276
947
|
}
|
|
1277
|
-
|
|
1278
|
-
|
|
1279
|
-
wrapper.className =
|
|
948
|
+
const wrapper = document.createElement("div");
|
|
949
|
+
const align = img.getAttribute('data-align') || 'center';
|
|
950
|
+
wrapper.className = `image-container image-align-${align}`;
|
|
1280
951
|
wrapper.style.cursor = editable ? 'pointer' : 'default';
|
|
1281
952
|
img.className = "rte-image";
|
|
1282
953
|
img.style.cssText = ""; // Reset inline styles
|
|
@@ -1284,26 +955,26 @@ function RichTextEditor(_ref) {
|
|
|
1284
955
|
img.dataset.hasDeleteButton = "true";
|
|
1285
956
|
|
|
1286
957
|
// Add click listener to open modal
|
|
1287
|
-
img.addEventListener("click",
|
|
1288
|
-
|
|
1289
|
-
});
|
|
1290
|
-
var deleteBtn = document.createElement("button");
|
|
958
|
+
img.addEventListener("click", () => openImageModal(img.src));
|
|
959
|
+
const deleteBtn = document.createElement("button");
|
|
1291
960
|
deleteBtn.innerHTML = "×";
|
|
1292
961
|
deleteBtn.className = "image-delete-button";
|
|
1293
962
|
deleteBtn.style.display = editable ? 'flex' : 'none';
|
|
1294
963
|
deleteBtn.style.pointerEvents = editable ? 'auto' : 'none';
|
|
1295
964
|
deleteBtn.title = "Remove image";
|
|
1296
|
-
deleteBtn.onclick =
|
|
965
|
+
deleteBtn.onclick = e => {
|
|
1297
966
|
e.preventDefault();
|
|
1298
967
|
e.stopPropagation();
|
|
1299
|
-
|
|
968
|
+
const wrapper = e.currentTarget.closest(".image-container");
|
|
1300
969
|
if (wrapper && wrapper.parentNode) {
|
|
1301
970
|
wrapper.parentNode.removeChild(wrapper);
|
|
1302
971
|
triggerChange && triggerChange();
|
|
1303
972
|
}
|
|
1304
973
|
};
|
|
1305
|
-
|
|
1306
|
-
|
|
974
|
+
const {
|
|
975
|
+
parentNode,
|
|
976
|
+
nextSibling
|
|
977
|
+
} = img;
|
|
1307
978
|
if (parentNode) {
|
|
1308
979
|
parentNode.removeChild(img);
|
|
1309
980
|
wrapper.appendChild(img);
|
|
@@ -1316,111 +987,86 @@ function RichTextEditor(_ref) {
|
|
|
1316
987
|
}
|
|
1317
988
|
});
|
|
1318
989
|
};
|
|
1319
|
-
React.useEffect(
|
|
990
|
+
React.useEffect(() => {
|
|
1320
991
|
if (editorRef.current && value) {
|
|
1321
|
-
requestAnimationFrame(
|
|
1322
|
-
return processExistingImages(editorRef.current);
|
|
1323
|
-
});
|
|
992
|
+
requestAnimationFrame(() => processExistingImages(editorRef.current));
|
|
1324
993
|
}
|
|
1325
994
|
}, [value]);
|
|
1326
|
-
var insertImage = /*#__PURE__*/function () {
|
|
1327
|
-
var _ref2 = _asyncToGenerator(/*#__PURE__*/_regenerator().m(function _callee(dataUrl, fileName) {
|
|
1328
|
-
var container, img;
|
|
1329
|
-
return _regenerator().w(function (_context) {
|
|
1330
|
-
while (1) switch (_context.n) {
|
|
1331
|
-
case 0:
|
|
1332
|
-
try {
|
|
1333
|
-
if (editable) {
|
|
1334
|
-
// Create container for the image
|
|
1335
|
-
container = document.createElement('div');
|
|
1336
|
-
container.className = 'image-container';
|
|
1337
995
|
|
|
1338
|
-
|
|
1339
|
-
|
|
1340
|
-
|
|
1341
|
-
|
|
1342
|
-
|
|
1343
|
-
|
|
1344
|
-
|
|
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';
|
|
1345
1006
|
|
|
1346
|
-
|
|
1347
|
-
|
|
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));
|
|
1348
1012
|
|
|
1349
|
-
|
|
1350
|
-
|
|
1351
|
-
triggerChange();
|
|
1013
|
+
// Add elements to container
|
|
1014
|
+
container.appendChild(img);
|
|
1352
1015
|
|
|
1353
|
-
|
|
1354
|
-
|
|
1355
|
-
|
|
1356
|
-
|
|
1357
|
-
|
|
1358
|
-
|
|
1359
|
-
|
|
1360
|
-
|
|
1361
|
-
|
|
1362
|
-
|
|
1363
|
-
|
|
1364
|
-
|
|
1365
|
-
}));
|
|
1366
|
-
return function insertImage(_x, _x2) {
|
|
1367
|
-
return _ref2.apply(this, arguments);
|
|
1368
|
-
};
|
|
1369
|
-
}();
|
|
1370
|
-
var readFileAsDataURL = function readFileAsDataURL(file) {
|
|
1371
|
-
return new Promise(function (res, rej) {
|
|
1372
|
-
var reader = new FileReader();
|
|
1373
|
-
reader.onload = function (ev) {
|
|
1374
|
-
return res(ev.target.result);
|
|
1375
|
-
};
|
|
1376
|
-
reader.onerror = rej;
|
|
1377
|
-
reader.readAsDataURL(file);
|
|
1378
|
-
});
|
|
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
|
+
}
|
|
1379
1028
|
};
|
|
1380
|
-
|
|
1381
|
-
|
|
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;
|
|
1382
1037
|
if (!clipboardData) return;
|
|
1383
1038
|
|
|
1384
1039
|
// Check for image in clipboard
|
|
1385
|
-
|
|
1386
|
-
|
|
1387
|
-
|
|
1388
|
-
|
|
1389
|
-
|
|
1390
|
-
|
|
1391
|
-
|
|
1392
|
-
|
|
1393
|
-
|
|
1394
|
-
|
|
1395
|
-
|
|
1396
|
-
|
|
1397
|
-
|
|
1398
|
-
|
|
1399
|
-
|
|
1400
|
-
|
|
1401
|
-
|
|
1402
|
-
|
|
1403
|
-
|
|
1404
|
-
|
|
1405
|
-
}
|
|
1406
|
-
return {
|
|
1407
|
-
v: void 0
|
|
1408
|
-
};
|
|
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
|
+
});
|
|
1409
1060
|
}
|
|
1410
|
-
|
|
1411
|
-
|
|
1412
|
-
for (var i = 0; i < items.length; i++) {
|
|
1413
|
-
_ret = _loop();
|
|
1414
|
-
if (_ret) return _ret.v;
|
|
1061
|
+
return;
|
|
1062
|
+
}
|
|
1415
1063
|
}
|
|
1416
|
-
|
|
1064
|
+
const htmlData = clipboardData.getData('text/html');
|
|
1417
1065
|
if (htmlData && htmlData.trim()) {
|
|
1418
1066
|
e.preventDefault();
|
|
1419
|
-
|
|
1067
|
+
const tempDiv = document.createElement('div');
|
|
1420
1068
|
tempDiv.innerHTML = htmlData;
|
|
1421
|
-
tempDiv.querySelectorAll('script, meta, link').forEach(
|
|
1422
|
-
return el.remove();
|
|
1423
|
-
});
|
|
1069
|
+
tempDiv.querySelectorAll('script, meta, link').forEach(el => el.remove());
|
|
1424
1070
|
document.execCommand('styleWithCSS', false, true);
|
|
1425
1071
|
document.execCommand('insertHTML', false, tempDiv.innerHTML);
|
|
1426
1072
|
document.execCommand('styleWithCSS', false, false);
|
|
@@ -1428,13 +1074,13 @@ function RichTextEditor(_ref) {
|
|
|
1428
1074
|
focus();
|
|
1429
1075
|
return;
|
|
1430
1076
|
}
|
|
1431
|
-
|
|
1077
|
+
const plainText = clipboardData.getData('text/plain');
|
|
1432
1078
|
if (plainText) {
|
|
1433
1079
|
e.preventDefault();
|
|
1434
|
-
|
|
1435
|
-
htmlToInsert = htmlToInsert.replace(URL_REGEX,
|
|
1436
|
-
|
|
1437
|
-
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>`;
|
|
1438
1084
|
});
|
|
1439
1085
|
htmlToInsert = htmlToInsert.replace(/\n/g, '<br>');
|
|
1440
1086
|
document.execCommand('insertHTML', false, htmlToInsert);
|
|
@@ -1442,94 +1088,37 @@ function RichTextEditor(_ref) {
|
|
|
1442
1088
|
focus();
|
|
1443
1089
|
}
|
|
1444
1090
|
}, [insertImage, triggerChange]);
|
|
1445
|
-
|
|
1446
|
-
|
|
1447
|
-
|
|
1448
|
-
|
|
1449
|
-
|
|
1450
|
-
|
|
1451
|
-
|
|
1452
|
-
|
|
1453
|
-
|
|
1454
|
-
|
|
1455
|
-
|
|
1456
|
-
|
|
1457
|
-
|
|
1458
|
-
|
|
1459
|
-
|
|
1460
|
-
|
|
1461
|
-
|
|
1462
|
-
|
|
1463
|
-
|
|
1464
|
-
|
|
1465
|
-
|
|
1466
|
-
|
|
1467
|
-
|
|
1468
|
-
|
|
1469
|
-
|
|
1470
|
-
|
|
1471
|
-
|
|
1472
|
-
|
|
1473
|
-
return _regenerator().w(function (_context2) {
|
|
1474
|
-
while (1) switch (_context2.n) {
|
|
1475
|
-
case 0:
|
|
1476
|
-
file = _step.value;
|
|
1477
|
-
try {
|
|
1478
|
-
setIsUploading(true);
|
|
1479
|
-
uploadPromise = onImageUpload ? onImageUpload(file) : readFileAsDataURL(file);
|
|
1480
|
-
uploadPromise.then(function (url) {
|
|
1481
|
-
if (url) {
|
|
1482
|
-
var finalUrl = _typeof(url) === 'object' && url !== null && url.mediaUrl ? url.mediaUrl : url;
|
|
1483
|
-
insertImage(finalUrl, file.name);
|
|
1484
|
-
}
|
|
1485
|
-
setIsUploading(false);
|
|
1486
|
-
})["catch"](function (error) {
|
|
1487
|
-
console.error('Error processing image:', error);
|
|
1488
|
-
setIsUploading(false);
|
|
1489
|
-
});
|
|
1490
|
-
} catch (error) {
|
|
1491
|
-
console.error('Error processing image:', error);
|
|
1492
|
-
setIsUploading(false);
|
|
1493
|
-
}
|
|
1494
|
-
case 1:
|
|
1495
|
-
return _context2.a(2);
|
|
1496
|
-
}
|
|
1497
|
-
}, _loop2);
|
|
1498
|
-
});
|
|
1499
|
-
_iterator.s();
|
|
1500
|
-
case 4:
|
|
1501
|
-
if ((_step = _iterator.n()).done) {
|
|
1502
|
-
_context3.n = 6;
|
|
1503
|
-
break;
|
|
1504
|
-
}
|
|
1505
|
-
return _context3.d(_regeneratorValues(_loop2()), 5);
|
|
1506
|
-
case 5:
|
|
1507
|
-
_context3.n = 4;
|
|
1508
|
-
break;
|
|
1509
|
-
case 6:
|
|
1510
|
-
_context3.n = 8;
|
|
1511
|
-
break;
|
|
1512
|
-
case 7:
|
|
1513
|
-
_context3.p = 7;
|
|
1514
|
-
_t = _context3.v;
|
|
1515
|
-
_iterator.e(_t);
|
|
1516
|
-
case 8:
|
|
1517
|
-
_context3.p = 8;
|
|
1518
|
-
_iterator.f();
|
|
1519
|
-
return _context3.f(8);
|
|
1520
|
-
case 9:
|
|
1521
|
-
return _context3.a(2);
|
|
1522
|
-
}
|
|
1523
|
-
}, _callee2, null, [[3, 7, 8, 9]]);
|
|
1524
|
-
}));
|
|
1525
|
-
return function handleDrop(_x3) {
|
|
1526
|
-
return _ref3.apply(this, arguments);
|
|
1527
|
-
};
|
|
1528
|
-
}();
|
|
1529
|
-
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 => {
|
|
1530
1119
|
try {
|
|
1531
|
-
|
|
1532
|
-
|
|
1120
|
+
const sel = window.getSelection();
|
|
1121
|
+
let range;
|
|
1533
1122
|
if (!sel || sel.rangeCount === 0 || !editorRef.current.contains(sel.anchorNode)) {
|
|
1534
1123
|
editorRef.current.focus();
|
|
1535
1124
|
|
|
@@ -1544,7 +1133,7 @@ function RichTextEditor(_ref) {
|
|
|
1544
1133
|
}
|
|
1545
1134
|
range.deleteContents();
|
|
1546
1135
|
range.insertNode(node);
|
|
1547
|
-
|
|
1136
|
+
const space = document.createTextNode("\u00A0");
|
|
1548
1137
|
if (node.parentNode) {
|
|
1549
1138
|
node.parentNode.insertBefore(space, node.nextSibling);
|
|
1550
1139
|
}
|
|
@@ -1559,36 +1148,36 @@ function RichTextEditor(_ref) {
|
|
|
1559
1148
|
}
|
|
1560
1149
|
}
|
|
1561
1150
|
};
|
|
1562
|
-
|
|
1151
|
+
const getCleanHtml = () => {
|
|
1563
1152
|
if (!editorRef.current) return "";
|
|
1564
1153
|
return editorRef.current.innerHTML;
|
|
1565
1154
|
};
|
|
1566
1155
|
|
|
1567
1156
|
// Helper function to unescape HTML entities
|
|
1568
|
-
|
|
1157
|
+
const unescapeHtml = html => {
|
|
1569
1158
|
if (!html) return '';
|
|
1570
|
-
|
|
1159
|
+
const txt = document.createElement("textarea");
|
|
1571
1160
|
txt.innerHTML = html;
|
|
1572
1161
|
return txt.value;
|
|
1573
1162
|
};
|
|
1574
|
-
|
|
1163
|
+
const handleKeyDown = React.useCallback(e => {
|
|
1575
1164
|
// Handle Enter key
|
|
1576
1165
|
if (e.key === 'Enter') {
|
|
1577
1166
|
e.preventDefault();
|
|
1578
|
-
|
|
1167
|
+
const selection = window.getSelection();
|
|
1579
1168
|
if (!selection.rangeCount) return;
|
|
1580
|
-
|
|
1581
|
-
|
|
1582
|
-
|
|
1169
|
+
const range = selection.getRangeAt(0);
|
|
1170
|
+
const node = range.startContainer;
|
|
1171
|
+
const parent = node.nodeType === 3 ? node.parentNode : node;
|
|
1583
1172
|
|
|
1584
1173
|
// Check if we're in a list item
|
|
1585
|
-
|
|
1174
|
+
const listItem = parent.closest('li');
|
|
1586
1175
|
if (listItem) {
|
|
1587
|
-
|
|
1176
|
+
const list = listItem.parentNode;
|
|
1588
1177
|
list.tagName === 'OL';
|
|
1589
1178
|
|
|
1590
1179
|
// Create a new list item
|
|
1591
|
-
|
|
1180
|
+
const newItem = document.createElement('li');
|
|
1592
1181
|
|
|
1593
1182
|
// If we're at the end of a list item, add a new one
|
|
1594
1183
|
if (range.collapsed && range.endOffset === node.length) {
|
|
@@ -1596,12 +1185,12 @@ function RichTextEditor(_ref) {
|
|
|
1596
1185
|
if (listItem.textContent.trim() === '') {
|
|
1597
1186
|
document.execCommand('insertHTML', false, '<div><br></div>');
|
|
1598
1187
|
// Move the cursor to the new line
|
|
1599
|
-
|
|
1600
|
-
|
|
1601
|
-
|
|
1602
|
-
|
|
1188
|
+
const newRange = document.createRange();
|
|
1189
|
+
const newDiv = editorRef.current.lastElementChild;
|
|
1190
|
+
newRange.setStart(newDiv, 0);
|
|
1191
|
+
newRange.collapse(true);
|
|
1603
1192
|
selection.removeAllRanges();
|
|
1604
|
-
selection.addRange(
|
|
1193
|
+
selection.addRange(newRange);
|
|
1605
1194
|
return;
|
|
1606
1195
|
}
|
|
1607
1196
|
|
|
@@ -1613,15 +1202,15 @@ function RichTextEditor(_ref) {
|
|
|
1613
1202
|
}
|
|
1614
1203
|
|
|
1615
1204
|
// Move cursor to the new list item
|
|
1616
|
-
|
|
1205
|
+
const newRange = document.createRange();
|
|
1617
1206
|
newRange.setStart(newItem, 0);
|
|
1618
1207
|
newRange.collapse(true);
|
|
1619
1208
|
selection.removeAllRanges();
|
|
1620
1209
|
selection.addRange(newRange);
|
|
1621
1210
|
} else {
|
|
1622
1211
|
// If we're in the middle of text, split the list item
|
|
1623
|
-
|
|
1624
|
-
|
|
1212
|
+
const textBefore = node.textContent.substring(0, range.startOffset);
|
|
1213
|
+
const textAfter = node.textContent.substring(range.startOffset);
|
|
1625
1214
|
|
|
1626
1215
|
// Update current item
|
|
1627
1216
|
node.textContent = textBefore;
|
|
@@ -1635,11 +1224,11 @@ function RichTextEditor(_ref) {
|
|
|
1635
1224
|
}
|
|
1636
1225
|
|
|
1637
1226
|
// Move cursor to the new list item
|
|
1638
|
-
|
|
1639
|
-
|
|
1640
|
-
|
|
1227
|
+
const newRange = document.createRange();
|
|
1228
|
+
newRange.setStart(newItem.firstChild || newItem, 0);
|
|
1229
|
+
newRange.collapse(true);
|
|
1641
1230
|
selection.removeAllRanges();
|
|
1642
|
-
selection.addRange(
|
|
1231
|
+
selection.addRange(newRange);
|
|
1643
1232
|
}
|
|
1644
1233
|
} else {
|
|
1645
1234
|
// Regular text, insert a new paragraph
|
|
@@ -1661,54 +1250,54 @@ function RichTextEditor(_ref) {
|
|
|
1661
1250
|
exec("underline");
|
|
1662
1251
|
}
|
|
1663
1252
|
}, [exec, triggerChange]);
|
|
1664
|
-
|
|
1253
|
+
const confirmLink = () => {
|
|
1665
1254
|
// Add protocol if missing
|
|
1666
|
-
|
|
1255
|
+
let url = linkUrl.trim();
|
|
1667
1256
|
if (url && !/^(https?:\/\/|mailto:|tel:)/i.test(url)) {
|
|
1668
|
-
url =
|
|
1257
|
+
url = `https://${url}`;
|
|
1669
1258
|
}
|
|
1670
|
-
|
|
1671
|
-
|
|
1672
|
-
|
|
1259
|
+
const safeUrl = escapeAttr(url);
|
|
1260
|
+
const safeText = escapeHtml(linkText || linkUrl);
|
|
1261
|
+
const sel = window.getSelection();
|
|
1673
1262
|
sel.removeAllRanges();
|
|
1674
1263
|
if (selectionRangeRef.current) {
|
|
1675
1264
|
sel.addRange(selectionRangeRef.current);
|
|
1676
1265
|
}
|
|
1677
|
-
|
|
1266
|
+
const linkHtml = `<a href="${safeUrl}" target="_blank" rel="noopener noreferrer" style="color: blue;">${safeText}</a>`;
|
|
1678
1267
|
document.execCommand("insertHTML", false, linkHtml);
|
|
1679
1268
|
setLinkModalOpen(false);
|
|
1680
1269
|
triggerChange();
|
|
1681
1270
|
focus();
|
|
1682
1271
|
selectionRangeRef.current = null;
|
|
1683
1272
|
};
|
|
1684
|
-
|
|
1273
|
+
const cancelLink = () => {
|
|
1685
1274
|
setLinkModalOpen(false);
|
|
1686
1275
|
selectionRangeRef.current = null;
|
|
1687
1276
|
};
|
|
1688
|
-
|
|
1277
|
+
const handleSelect = type => {
|
|
1689
1278
|
exec(type === "unordered" ? "insertUnorderedList" : "insertOrderedList");
|
|
1690
1279
|
};
|
|
1691
|
-
|
|
1280
|
+
const onLineHeightChange = value => {
|
|
1692
1281
|
if (!value) return;
|
|
1693
|
-
|
|
1282
|
+
const sel = window.getSelection();
|
|
1694
1283
|
if (!sel || !sel.rangeCount) return;
|
|
1695
|
-
|
|
1696
|
-
|
|
1284
|
+
const range = sel.getRangeAt(0);
|
|
1285
|
+
const editor = editorRef.current;
|
|
1697
1286
|
if (!editor) return;
|
|
1698
|
-
|
|
1699
|
-
acceptNode:
|
|
1287
|
+
const walker = document.createTreeWalker(editor, NodeFilter.SHOW_ELEMENT | NodeFilter.SHOW_TEXT, {
|
|
1288
|
+
acceptNode: node => {
|
|
1700
1289
|
return range.intersectsNode(node) ? NodeFilter.FILTER_ACCEPT : NodeFilter.FILTER_REJECT;
|
|
1701
1290
|
}
|
|
1702
1291
|
}, false);
|
|
1703
|
-
|
|
1704
|
-
|
|
1705
|
-
|
|
1706
|
-
|
|
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();
|
|
1707
1296
|
while (node = walker.nextNode()) {
|
|
1708
1297
|
if (node.nodeType === 1 && blockTags.includes(node.tagName)) {
|
|
1709
1298
|
blocksToStyle.add(node);
|
|
1710
1299
|
} else if (node.nodeType === 3) {
|
|
1711
|
-
|
|
1300
|
+
let parent = node.parentNode;
|
|
1712
1301
|
while (parent && parent !== editor && !blockTags.includes(parent.tagName)) {
|
|
1713
1302
|
parent = parent.parentNode;
|
|
1714
1303
|
}
|
|
@@ -1718,11 +1307,11 @@ function RichTextEditor(_ref) {
|
|
|
1718
1307
|
}
|
|
1719
1308
|
}
|
|
1720
1309
|
if (blocksToStyle.size > 0) {
|
|
1721
|
-
blocksToStyle.forEach(
|
|
1310
|
+
blocksToStyle.forEach(block => {
|
|
1722
1311
|
block.style.lineHeight = value;
|
|
1723
1312
|
});
|
|
1724
1313
|
} else {
|
|
1725
|
-
|
|
1314
|
+
let common = range.commonAncestorContainer;
|
|
1726
1315
|
if (common.nodeType === 3) common = common.parentNode;
|
|
1727
1316
|
while (common && common !== editor && !blockTags.includes(common.tagName)) {
|
|
1728
1317
|
common = common.parentNode;
|
|
@@ -1731,7 +1320,7 @@ function RichTextEditor(_ref) {
|
|
|
1731
1320
|
common.style.lineHeight = value;
|
|
1732
1321
|
} else if (editor) {
|
|
1733
1322
|
document.execCommand('formatBlock', false, 'div');
|
|
1734
|
-
|
|
1323
|
+
let newCommon = window.getSelection().getRangeAt(0).commonAncestorContainer;
|
|
1735
1324
|
if (newCommon.nodeType === 3) newCommon = newCommon.parentNode;
|
|
1736
1325
|
if (newCommon && newCommon !== editor) {
|
|
1737
1326
|
newCommon.style.lineHeight = value;
|
|
@@ -1746,19 +1335,19 @@ function RichTextEditor(_ref) {
|
|
|
1746
1335
|
triggerChange();
|
|
1747
1336
|
focus();
|
|
1748
1337
|
};
|
|
1749
|
-
|
|
1750
|
-
|
|
1338
|
+
const applyFontSize = size => {
|
|
1339
|
+
const sel = window.getSelection();
|
|
1751
1340
|
if (!sel || !sel.rangeCount) return;
|
|
1752
|
-
|
|
1753
|
-
|
|
1341
|
+
const range = sel.getRangeAt(0);
|
|
1342
|
+
const sizePx = `${size}px`;
|
|
1754
1343
|
|
|
1755
1344
|
// Collapsed selection (cursor only): insert a styled zero-width span
|
|
1756
1345
|
if (range.collapsed) {
|
|
1757
|
-
|
|
1346
|
+
const span = document.createElement("span");
|
|
1758
1347
|
span.style.fontSize = sizePx;
|
|
1759
1348
|
span.appendChild(document.createTextNode("\u200B"));
|
|
1760
1349
|
range.insertNode(span);
|
|
1761
|
-
|
|
1350
|
+
const newRange = document.createRange();
|
|
1762
1351
|
newRange.setStart(span.firstChild, 1);
|
|
1763
1352
|
newRange.collapse(true);
|
|
1764
1353
|
sel.removeAllRanges();
|
|
@@ -1770,42 +1359,41 @@ function RichTextEditor(_ref) {
|
|
|
1770
1359
|
|
|
1771
1360
|
// Extended selection (highlighted text)
|
|
1772
1361
|
try {
|
|
1773
|
-
|
|
1362
|
+
const editor = editorRef.current;
|
|
1774
1363
|
if (!editor) return;
|
|
1775
1364
|
|
|
1776
1365
|
// We will iterate through all the text nodes in the selection
|
|
1777
|
-
|
|
1778
|
-
acceptNode:
|
|
1366
|
+
const walker = document.createTreeWalker(editor, NodeFilter.SHOW_TEXT, {
|
|
1367
|
+
acceptNode: node => {
|
|
1779
1368
|
return range.intersectsNode(node) ? NodeFilter.FILTER_ACCEPT : NodeFilter.FILTER_REJECT;
|
|
1780
1369
|
}
|
|
1781
1370
|
}, false);
|
|
1782
|
-
|
|
1783
|
-
|
|
1371
|
+
let node;
|
|
1372
|
+
const nodesToStyle = [];
|
|
1784
1373
|
while (node = walker.nextNode()) {
|
|
1785
1374
|
nodesToStyle.push(node);
|
|
1786
1375
|
}
|
|
1787
|
-
|
|
1788
|
-
|
|
1376
|
+
const savedRange = range.cloneRange();
|
|
1377
|
+
let lastInsertedNode = null;
|
|
1789
1378
|
|
|
1790
1379
|
// Iterate through the selected text nodes and wrap them in spans
|
|
1791
|
-
for (
|
|
1792
|
-
|
|
1793
|
-
var parent = textNode.parentNode;
|
|
1380
|
+
for (const textNode of nodesToStyle) {
|
|
1381
|
+
const parent = textNode.parentNode;
|
|
1794
1382
|
|
|
1795
1383
|
// This is important: check if the parent is a block-level element
|
|
1796
1384
|
// like a list item or paragraph. If so, we want to style the block
|
|
1797
1385
|
// itself to avoid breaking its structure.
|
|
1798
|
-
|
|
1386
|
+
const isBlockLevel = ['P', 'H1', 'H2', 'H3', 'H4', 'H5', 'H6', 'LI', 'BLOCKQUOTE'].includes(parent.tagName);
|
|
1799
1387
|
if (isBlockLevel) {
|
|
1800
1388
|
parent.style.fontSize = sizePx;
|
|
1801
1389
|
} else {
|
|
1802
1390
|
// For inline text, wrap the selected portion in a new span
|
|
1803
|
-
|
|
1804
|
-
|
|
1805
|
-
|
|
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");
|
|
1806
1394
|
newSpan.style.fontSize = sizePx;
|
|
1807
1395
|
newSpan.textContent = textNode.textContent.substring(startOffset, endOffset);
|
|
1808
|
-
|
|
1396
|
+
const tempRange = document.createRange();
|
|
1809
1397
|
tempRange.setStart(textNode, startOffset);
|
|
1810
1398
|
tempRange.setEnd(textNode, endOffset);
|
|
1811
1399
|
tempRange.deleteContents();
|
|
@@ -1816,11 +1404,11 @@ function RichTextEditor(_ref) {
|
|
|
1816
1404
|
|
|
1817
1405
|
// After styling, we need to correctly position the cursor
|
|
1818
1406
|
if (lastInsertedNode) {
|
|
1819
|
-
|
|
1820
|
-
|
|
1821
|
-
|
|
1407
|
+
const newRange = document.createRange();
|
|
1408
|
+
newRange.setStartAfter(lastInsertedNode);
|
|
1409
|
+
newRange.collapse(true);
|
|
1822
1410
|
sel.removeAllRanges();
|
|
1823
|
-
sel.addRange(
|
|
1411
|
+
sel.addRange(newRange);
|
|
1824
1412
|
} else {
|
|
1825
1413
|
// If no nodes were wrapped (e.g., we styled a block), restore the original selection
|
|
1826
1414
|
sel.removeAllRanges();
|
|
@@ -1832,65 +1420,47 @@ function RichTextEditor(_ref) {
|
|
|
1832
1420
|
triggerChange();
|
|
1833
1421
|
focus();
|
|
1834
1422
|
};
|
|
1835
|
-
|
|
1836
|
-
if (
|
|
1837
|
-
|
|
1838
|
-
setHtml(
|
|
1839
|
-
|
|
1840
|
-
|
|
1841
|
-
|
|
1842
|
-
|
|
1843
|
-
|
|
1844
|
-
|
|
1845
|
-
|
|
1846
|
-
|
|
1847
|
-
|
|
1848
|
-
|
|
1849
|
-
|
|
1850
|
-
|
|
1851
|
-
|
|
1852
|
-
|
|
1853
|
-
|
|
1854
|
-
case 1:
|
|
1855
|
-
try {
|
|
1856
|
-
setIsUploading(true);
|
|
1857
|
-
uploadPromise = onImageUpload ? onImageUpload(file) : readFileAsDataURL(file);
|
|
1858
|
-
uploadPromise.then(function (url) {
|
|
1859
|
-
if (url) {
|
|
1860
|
-
var finalUrl = _typeof(url) === 'object' && url !== null && url.mediaUrl ? url.mediaUrl : url;
|
|
1861
|
-
insertImage(finalUrl, file.name);
|
|
1862
|
-
}
|
|
1863
|
-
setIsUploading(false);
|
|
1864
|
-
e.target.value = null;
|
|
1865
|
-
})["catch"](function (error) {
|
|
1866
|
-
console.error('Error uploading image:', error);
|
|
1867
|
-
setIsUploading(false);
|
|
1868
|
-
});
|
|
1869
|
-
} catch (error) {
|
|
1870
|
-
console.error('Error uploading image:', error);
|
|
1871
|
-
setIsUploading(false);
|
|
1872
|
-
}
|
|
1873
|
-
case 2:
|
|
1874
|
-
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);
|
|
1875
1442
|
}
|
|
1876
|
-
|
|
1877
|
-
|
|
1878
|
-
|
|
1879
|
-
|
|
1880
|
-
|
|
1881
|
-
|
|
1882
|
-
|
|
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(() => {
|
|
1883
1455
|
// If disabled is explicitly false, make sure the editor is not editable
|
|
1884
1456
|
if (disabled === true) {
|
|
1885
1457
|
setEditable(false);
|
|
1886
1458
|
}
|
|
1887
1459
|
}, [disabled]);
|
|
1888
|
-
|
|
1889
|
-
setSelectionVersion(
|
|
1890
|
-
return v + 1;
|
|
1891
|
-
});
|
|
1460
|
+
const handleEditorClick = React.useCallback(e => {
|
|
1461
|
+
setSelectionVersion(v => v + 1);
|
|
1892
1462
|
// Check if the click is on a link
|
|
1893
|
-
|
|
1463
|
+
const clickedLink = e.target.closest('a');
|
|
1894
1464
|
if (clickedLink) {
|
|
1895
1465
|
e.preventDefault();
|
|
1896
1466
|
e.stopPropagation();
|
|
@@ -1899,11 +1469,10 @@ function RichTextEditor(_ref) {
|
|
|
1899
1469
|
}
|
|
1900
1470
|
|
|
1901
1471
|
// NEW: Check if click is on an image for resizing
|
|
1902
|
-
|
|
1472
|
+
const clickedImg = e.target.closest('img');
|
|
1903
1473
|
if (clickedImg && !clickedImg.closest('.rte-modal')) {
|
|
1904
1474
|
setSelectedImage(clickedImg);
|
|
1905
|
-
|
|
1906
|
-
} else if (!e.target.closest('.resize-handle')) {
|
|
1475
|
+
} else if (!e.target.closest('.rte-image-toolbar')) {
|
|
1907
1476
|
setSelectedImage(null);
|
|
1908
1477
|
}
|
|
1909
1478
|
|
|
@@ -1916,119 +1485,81 @@ function RichTextEditor(_ref) {
|
|
|
1916
1485
|
// Only allow setting editable to true if not disabled
|
|
1917
1486
|
if (!editable && disabled !== true) {
|
|
1918
1487
|
setEditable(true);
|
|
1919
|
-
setTimeout(
|
|
1488
|
+
setTimeout(() => {
|
|
1920
1489
|
if (editorRef.current) {
|
|
1921
1490
|
editorRef.current.focus();
|
|
1922
1491
|
}
|
|
1923
1492
|
}, 0);
|
|
1924
1493
|
}
|
|
1925
1494
|
}, [editable, disabled]);
|
|
1926
|
-
|
|
1927
|
-
|
|
1928
|
-
|
|
1929
|
-
|
|
1930
|
-
|
|
1931
|
-
|
|
1932
|
-
|
|
1933
|
-
|
|
1934
|
-
|
|
1935
|
-
|
|
1936
|
-
|
|
1937
|
-
|
|
1938
|
-
|
|
1939
|
-
|
|
1940
|
-
|
|
1941
|
-
|
|
1942
|
-
img.style.height = "".concat(newHeight, "px");
|
|
1943
|
-
setResizeData({}); // Force re-render of handles
|
|
1944
|
-
};
|
|
1945
|
-
var _onMouseUp = function onMouseUp() {
|
|
1946
|
-
document.removeEventListener('mousemove', onMouseMove);
|
|
1947
|
-
document.removeEventListener('mouseup', _onMouseUp);
|
|
1948
|
-
triggerChange();
|
|
1949
|
-
};
|
|
1950
|
-
document.addEventListener('mousemove', onMouseMove);
|
|
1951
|
-
document.addEventListener('mouseup', _onMouseUp);
|
|
1952
|
-
};
|
|
1953
|
-
var renderResizeHandles = function renderResizeHandles() {
|
|
1954
|
-
if (!selectedImage || !editorRef.current) return null;
|
|
1955
|
-
var editorRect = editorRef.current.getBoundingClientRect();
|
|
1956
|
-
var imgRect = selectedImage.getBoundingClientRect();
|
|
1957
|
-
|
|
1958
|
-
// Relative position within editorRef using the more robust BoundingClientRect
|
|
1959
|
-
var top = imgRect.top - editorRect.top + editorRef.current.scrollTop;
|
|
1960
|
-
var left = imgRect.left - editorRect.left + editorRef.current.scrollLeft;
|
|
1961
|
-
var width = imgRect.width;
|
|
1962
|
-
var height = imgRect.height;
|
|
1963
|
-
var handleStyles = {
|
|
1964
|
-
position: 'absolute',
|
|
1965
|
-
width: '10px',
|
|
1966
|
-
height: '10px',
|
|
1967
|
-
background: '#3b82f6',
|
|
1968
|
-
border: '2px solid white',
|
|
1969
|
-
borderRadius: '50%',
|
|
1970
|
-
zIndex: 100
|
|
1971
|
-
};
|
|
1972
|
-
var handles = [{
|
|
1973
|
-
id: 'nw',
|
|
1974
|
-
style: {
|
|
1975
|
-
top: top - 5,
|
|
1976
|
-
left: left - 5,
|
|
1977
|
-
cursor: 'nw-resize'
|
|
1978
|
-
}
|
|
1979
|
-
}, {
|
|
1980
|
-
id: 'ne',
|
|
1981
|
-
style: {
|
|
1982
|
-
top: top - 5,
|
|
1983
|
-
left: left + width - 5,
|
|
1984
|
-
cursor: 'ne-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();
|
|
1985
1511
|
}
|
|
1986
|
-
}
|
|
1987
|
-
|
|
1988
|
-
|
|
1989
|
-
|
|
1990
|
-
|
|
1991
|
-
|
|
1512
|
+
};
|
|
1513
|
+
const removeImage = () => {
|
|
1514
|
+
const wrapper = selectedImage.closest('.image-container');
|
|
1515
|
+
if (wrapper) {
|
|
1516
|
+
wrapper.remove();
|
|
1517
|
+
setSelectedImage(null);
|
|
1518
|
+
triggerChange();
|
|
1992
1519
|
}
|
|
1993
|
-
}
|
|
1994
|
-
|
|
1995
|
-
|
|
1996
|
-
|
|
1997
|
-
|
|
1998
|
-
|
|
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();
|
|
1999
1531
|
}
|
|
2000
|
-
}
|
|
1532
|
+
};
|
|
2001
1533
|
return /*#__PURE__*/React.createElement("div", {
|
|
1534
|
+
className: "rte-image-toolbar",
|
|
2002
1535
|
style: {
|
|
2003
1536
|
position: 'absolute',
|
|
2004
|
-
top: 0,
|
|
2005
|
-
left: 0,
|
|
2006
|
-
|
|
2007
|
-
height: '100%',
|
|
2008
|
-
pointerEvents: 'none'
|
|
2009
|
-
}
|
|
2010
|
-
}, /*#__PURE__*/React.createElement("div", {
|
|
2011
|
-
style: {
|
|
2012
|
-
position: 'absolute',
|
|
2013
|
-
top: top,
|
|
2014
|
-
left: left,
|
|
2015
|
-
width: width,
|
|
2016
|
-
height: height,
|
|
2017
|
-
border: '2px solid #3b82f6',
|
|
2018
|
-
pointerEvents: 'none'
|
|
1537
|
+
top: Math.max(0, top - 45),
|
|
1538
|
+
left: Math.max(0, left + width / 2 - 80),
|
|
1539
|
+
zIndex: 1000
|
|
2019
1540
|
}
|
|
2020
|
-
}
|
|
2021
|
-
|
|
2022
|
-
|
|
2023
|
-
|
|
2024
|
-
|
|
2025
|
-
|
|
2026
|
-
|
|
2027
|
-
|
|
2028
|
-
|
|
2029
|
-
|
|
2030
|
-
|
|
2031
|
-
|
|
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"));
|
|
2032
1563
|
};
|
|
2033
1564
|
return /*#__PURE__*/React.createElement("div", {
|
|
2034
1565
|
className: "rte-main-wrapper",
|
|
@@ -2042,21 +1573,21 @@ function RichTextEditor(_ref) {
|
|
|
2042
1573
|
},
|
|
2043
1574
|
className: !showBorder ? "" : "rte-container",
|
|
2044
1575
|
onClick: handleEditorClick,
|
|
2045
|
-
onMouseOver:
|
|
2046
|
-
|
|
1576
|
+
onMouseOver: e => {
|
|
1577
|
+
const table = e.target.closest('table');
|
|
2047
1578
|
if (table && editorRef.current.contains(table)) {
|
|
2048
1579
|
setHoveredTable(table);
|
|
2049
1580
|
}
|
|
2050
1581
|
},
|
|
2051
|
-
onMouseOut:
|
|
2052
|
-
|
|
2053
|
-
|
|
1582
|
+
onMouseOut: e => {
|
|
1583
|
+
const table = e.target.closest('table');
|
|
1584
|
+
const related = e.relatedTarget;
|
|
2054
1585
|
if (table && (!related || !table.contains(related)) && !(related !== null && related !== void 0 && related.closest('.rte-table-delete-hover'))) {
|
|
2055
1586
|
setHoveredTable(null);
|
|
2056
1587
|
}
|
|
2057
1588
|
},
|
|
2058
1589
|
onDrop: handleDrop,
|
|
2059
|
-
onDragOver:
|
|
1590
|
+
onDragOver: e => {
|
|
2060
1591
|
e.preventDefault();
|
|
2061
1592
|
e.stopPropagation();
|
|
2062
1593
|
}
|
|
@@ -2065,40 +1596,40 @@ function RichTextEditor(_ref) {
|
|
|
2065
1596
|
}, /*#__PURE__*/React.createElement("button", {
|
|
2066
1597
|
type: "button",
|
|
2067
1598
|
title: "Bold",
|
|
2068
|
-
onClick:
|
|
1599
|
+
onClick: e => {
|
|
2069
1600
|
e.preventDefault();
|
|
2070
1601
|
e.stopPropagation();
|
|
2071
1602
|
document.execCommand("bold");
|
|
2072
1603
|
handleInput();
|
|
2073
1604
|
focus();
|
|
2074
1605
|
},
|
|
2075
|
-
className:
|
|
1606
|
+
className: `rte-toolbar-button ${isBold ? "active" : ""}`
|
|
2076
1607
|
}, /*#__PURE__*/React.createElement(FaBold, {
|
|
2077
1608
|
size: 14
|
|
2078
1609
|
})), /*#__PURE__*/React.createElement("button", {
|
|
2079
1610
|
type: "button",
|
|
2080
1611
|
title: "Italic",
|
|
2081
|
-
onClick:
|
|
1612
|
+
onClick: e => {
|
|
2082
1613
|
e.preventDefault();
|
|
2083
1614
|
e.stopPropagation();
|
|
2084
1615
|
document.execCommand("italic");
|
|
2085
1616
|
handleInput();
|
|
2086
1617
|
focus();
|
|
2087
1618
|
},
|
|
2088
|
-
className:
|
|
1619
|
+
className: `rte-toolbar-button ${isItalic ? "active" : ""}`
|
|
2089
1620
|
}, /*#__PURE__*/React.createElement(FaItalic, {
|
|
2090
1621
|
size: 14
|
|
2091
1622
|
})), /*#__PURE__*/React.createElement("button", {
|
|
2092
1623
|
type: "button",
|
|
2093
1624
|
title: "Underline",
|
|
2094
|
-
onClick:
|
|
1625
|
+
onClick: e => {
|
|
2095
1626
|
e.preventDefault();
|
|
2096
1627
|
e.stopPropagation();
|
|
2097
1628
|
document.execCommand("underline");
|
|
2098
1629
|
handleInput();
|
|
2099
1630
|
focus();
|
|
2100
1631
|
},
|
|
2101
|
-
className:
|
|
1632
|
+
className: `rte-toolbar-button ${isUnderline ? "active" : ""}`
|
|
2102
1633
|
}, /*#__PURE__*/React.createElement(FaUnderline, {
|
|
2103
1634
|
size: 14
|
|
2104
1635
|
})), /*#__PURE__*/React.createElement("div", {
|
|
@@ -2110,13 +1641,11 @@ function RichTextEditor(_ref) {
|
|
|
2110
1641
|
}
|
|
2111
1642
|
}), /*#__PURE__*/React.createElement("select", {
|
|
2112
1643
|
value: currentFontSize,
|
|
2113
|
-
onMouseDown:
|
|
2114
|
-
|
|
2115
|
-
},
|
|
2116
|
-
onChange: function onChange(e) {
|
|
1644
|
+
onMouseDown: e => e.stopPropagation(),
|
|
1645
|
+
onChange: e => {
|
|
2117
1646
|
e.preventDefault();
|
|
2118
1647
|
e.stopPropagation();
|
|
2119
|
-
|
|
1648
|
+
const size = e.target.value;
|
|
2120
1649
|
if (!size) return;
|
|
2121
1650
|
applyFontSize(size);
|
|
2122
1651
|
setCurrentFontSize(size);
|
|
@@ -2126,12 +1655,10 @@ function RichTextEditor(_ref) {
|
|
|
2126
1655
|
style: {
|
|
2127
1656
|
width: '70px'
|
|
2128
1657
|
}
|
|
2129
|
-
}, [8, 10, 12, 14, 16, 18, 20, 24, 28, 32, 36, 40, 48].map(
|
|
2130
|
-
|
|
2131
|
-
|
|
2132
|
-
|
|
2133
|
-
}, s, "px");
|
|
2134
|
-
})), /*#__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", {
|
|
2135
1662
|
title: "Font Color",
|
|
2136
1663
|
className: "rte-color-picker-label"
|
|
2137
1664
|
}, /*#__PURE__*/React.createElement(FaFont, {
|
|
@@ -2142,11 +1669,11 @@ function RichTextEditor(_ref) {
|
|
|
2142
1669
|
}), /*#__PURE__*/React.createElement("input", {
|
|
2143
1670
|
type: "color",
|
|
2144
1671
|
value: fontColor,
|
|
2145
|
-
onMouseDown:
|
|
1672
|
+
onMouseDown: e => {
|
|
2146
1673
|
e.preventDefault();
|
|
2147
1674
|
e.stopPropagation();
|
|
2148
1675
|
},
|
|
2149
|
-
onChange:
|
|
1676
|
+
onChange: e => {
|
|
2150
1677
|
e.stopPropagation();
|
|
2151
1678
|
handleColorChange(e.target.value);
|
|
2152
1679
|
},
|
|
@@ -2161,8 +1688,8 @@ function RichTextEditor(_ref) {
|
|
|
2161
1688
|
}), /*#__PURE__*/React.createElement("button", {
|
|
2162
1689
|
type: "button",
|
|
2163
1690
|
title: "Align Left",
|
|
2164
|
-
className:
|
|
2165
|
-
onMouseDown:
|
|
1691
|
+
className: `rte-toolbar-button ${activeAlign === "left" ? "active" : ""}`,
|
|
1692
|
+
onMouseDown: e => {
|
|
2166
1693
|
e.preventDefault();
|
|
2167
1694
|
exec("justifyLeft");
|
|
2168
1695
|
setActiveAlign("left");
|
|
@@ -2172,8 +1699,8 @@ function RichTextEditor(_ref) {
|
|
|
2172
1699
|
})), /*#__PURE__*/React.createElement("button", {
|
|
2173
1700
|
type: "button",
|
|
2174
1701
|
title: "Align Center",
|
|
2175
|
-
className:
|
|
2176
|
-
onMouseDown:
|
|
1702
|
+
className: `rte-toolbar-button ${activeAlign === "center" ? "active" : ""}`,
|
|
1703
|
+
onMouseDown: e => {
|
|
2177
1704
|
e.preventDefault();
|
|
2178
1705
|
exec("justifyCenter");
|
|
2179
1706
|
setActiveAlign("center");
|
|
@@ -2183,8 +1710,8 @@ function RichTextEditor(_ref) {
|
|
|
2183
1710
|
})), /*#__PURE__*/React.createElement("button", {
|
|
2184
1711
|
type: "button",
|
|
2185
1712
|
title: "Align Right",
|
|
2186
|
-
className:
|
|
2187
|
-
onMouseDown:
|
|
1713
|
+
className: `rte-toolbar-button ${activeAlign === "right" ? "active" : ""}`,
|
|
1714
|
+
onMouseDown: e => {
|
|
2188
1715
|
e.preventDefault();
|
|
2189
1716
|
exec("justifyRight");
|
|
2190
1717
|
setActiveAlign("right");
|
|
@@ -2201,21 +1728,21 @@ function RichTextEditor(_ref) {
|
|
|
2201
1728
|
}), /*#__PURE__*/React.createElement("button", {
|
|
2202
1729
|
type: "button",
|
|
2203
1730
|
title: "Unordered List",
|
|
2204
|
-
onMouseDown:
|
|
1731
|
+
onMouseDown: e => {
|
|
2205
1732
|
e.preventDefault();
|
|
2206
1733
|
handleSelect("unordered");
|
|
2207
1734
|
},
|
|
2208
|
-
className:
|
|
1735
|
+
className: `rte-toolbar-button ${currentListType === "unordered" ? "active" : ""}`
|
|
2209
1736
|
}, /*#__PURE__*/React.createElement(FaListUl, {
|
|
2210
1737
|
size: 14
|
|
2211
1738
|
})), /*#__PURE__*/React.createElement("button", {
|
|
2212
1739
|
type: "button",
|
|
2213
1740
|
title: "Ordered List",
|
|
2214
|
-
onMouseDown:
|
|
1741
|
+
onMouseDown: e => {
|
|
2215
1742
|
e.preventDefault();
|
|
2216
1743
|
handleSelect("ordered");
|
|
2217
1744
|
},
|
|
2218
|
-
className:
|
|
1745
|
+
className: `rte-toolbar-button ${currentListType === "ordered" ? "active" : ""}`
|
|
2219
1746
|
}, /*#__PURE__*/React.createElement(FaListOl, {
|
|
2220
1747
|
size: 14
|
|
2221
1748
|
})), /*#__PURE__*/React.createElement("div", {
|
|
@@ -2226,12 +1753,10 @@ function RichTextEditor(_ref) {
|
|
|
2226
1753
|
}
|
|
2227
1754
|
}, /*#__PURE__*/React.createElement("select", {
|
|
2228
1755
|
value: currentLineHeight,
|
|
2229
|
-
onMouseDown:
|
|
2230
|
-
|
|
2231
|
-
},
|
|
2232
|
-
onChange: function onChange(e) {
|
|
1756
|
+
onMouseDown: e => e.stopPropagation(),
|
|
1757
|
+
onChange: e => {
|
|
2233
1758
|
e.preventDefault();
|
|
2234
|
-
|
|
1759
|
+
const height = e.target.value;
|
|
2235
1760
|
if (height) {
|
|
2236
1761
|
onLineHeightChange(height);
|
|
2237
1762
|
setCurrentLineHeight(height);
|
|
@@ -2246,12 +1771,10 @@ function RichTextEditor(_ref) {
|
|
|
2246
1771
|
}, /*#__PURE__*/React.createElement("option", {
|
|
2247
1772
|
value: "",
|
|
2248
1773
|
disabled: true
|
|
2249
|
-
}, "\u2195"), ['1', '1.15', '1.5', '2'].map(
|
|
2250
|
-
|
|
2251
|
-
|
|
2252
|
-
|
|
2253
|
-
}, h);
|
|
2254
|
-
})), /*#__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", {
|
|
2255
1778
|
style: {
|
|
2256
1779
|
position: 'absolute',
|
|
2257
1780
|
left: '6px',
|
|
@@ -2278,7 +1801,7 @@ function RichTextEditor(_ref) {
|
|
|
2278
1801
|
type: "button",
|
|
2279
1802
|
title: "Add Link",
|
|
2280
1803
|
className: "rte-toolbar-button",
|
|
2281
|
-
onMouseDown:
|
|
1804
|
+
onMouseDown: e => {
|
|
2282
1805
|
e.preventDefault();
|
|
2283
1806
|
addLink();
|
|
2284
1807
|
}
|
|
@@ -2298,7 +1821,7 @@ function RichTextEditor(_ref) {
|
|
|
2298
1821
|
}), /*#__PURE__*/React.createElement("button", {
|
|
2299
1822
|
type: "button",
|
|
2300
1823
|
className: "rte-toolbar-button",
|
|
2301
|
-
onMouseDown:
|
|
1824
|
+
onMouseDown: e => {
|
|
2302
1825
|
var _fileInputRef$current;
|
|
2303
1826
|
e.preventDefault();
|
|
2304
1827
|
if (!isUploading) (_fileInputRef$current = fileInputRef.current) === null || _fileInputRef$current === void 0 || _fileInputRef$current.click();
|
|
@@ -2325,9 +1848,9 @@ function RichTextEditor(_ref) {
|
|
|
2325
1848
|
type: "button",
|
|
2326
1849
|
title: "Insert Table",
|
|
2327
1850
|
className: "rte-toolbar-button",
|
|
2328
|
-
onMouseDown:
|
|
1851
|
+
onMouseDown: e => {
|
|
2329
1852
|
e.preventDefault();
|
|
2330
|
-
|
|
1853
|
+
const sel = window.getSelection();
|
|
2331
1854
|
if (sel && sel.rangeCount > 0) {
|
|
2332
1855
|
selectionRangeRef.current = sel.getRangeAt(0).cloneRange();
|
|
2333
1856
|
}
|
|
@@ -2337,24 +1860,21 @@ function RichTextEditor(_ref) {
|
|
|
2337
1860
|
size: 14
|
|
2338
1861
|
})), /*#__PURE__*/React.createElement("button", {
|
|
2339
1862
|
type: "button",
|
|
2340
|
-
title: "Embed YouTube
|
|
2341
|
-
className:
|
|
2342
|
-
onMouseDown:
|
|
1863
|
+
title: "Embed Video (YouTube, Vimeo, etc.)",
|
|
1864
|
+
className: `rte-toolbar-button ${videoModalOpen ? 'active' : ''}`,
|
|
1865
|
+
onMouseDown: e => {
|
|
2343
1866
|
e.preventDefault();
|
|
2344
|
-
|
|
2345
|
-
|
|
2346
|
-
selectionRangeRef.current = sel.getRangeAt(0).cloneRange();
|
|
2347
|
-
}
|
|
2348
|
-
setYoutubeModalOpen(true);
|
|
1867
|
+
saveSelection();
|
|
1868
|
+
setVideoModalOpen(true);
|
|
2349
1869
|
}
|
|
2350
|
-
}, /*#__PURE__*/React.createElement(
|
|
1870
|
+
}, /*#__PURE__*/React.createElement(FaVideo, {
|
|
2351
1871
|
size: 14
|
|
2352
|
-
})),
|
|
1872
|
+
})), (() => {
|
|
2353
1873
|
if (typeof window === "undefined") return null;
|
|
2354
|
-
|
|
1874
|
+
const sel = window.getSelection();
|
|
2355
1875
|
// Robust check: inside cell OR the table itself is selected
|
|
2356
|
-
|
|
2357
|
-
|
|
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');
|
|
2358
1878
|
if (isCell || isTable) {
|
|
2359
1879
|
return /*#__PURE__*/React.createElement(React.Fragment, null, /*#__PURE__*/React.createElement("div", {
|
|
2360
1880
|
style: {
|
|
@@ -2367,7 +1887,7 @@ function RichTextEditor(_ref) {
|
|
|
2367
1887
|
type: "button",
|
|
2368
1888
|
title: "Add Row Above",
|
|
2369
1889
|
className: "rte-toolbar-button",
|
|
2370
|
-
onMouseDown:
|
|
1890
|
+
onMouseDown: e => {
|
|
2371
1891
|
e.preventDefault();
|
|
2372
1892
|
tableAction('addRowAbove');
|
|
2373
1893
|
}
|
|
@@ -2375,7 +1895,7 @@ function RichTextEditor(_ref) {
|
|
|
2375
1895
|
type: "button",
|
|
2376
1896
|
title: "Add Row Below",
|
|
2377
1897
|
className: "rte-toolbar-button",
|
|
2378
|
-
onMouseDown:
|
|
1898
|
+
onMouseDown: e => {
|
|
2379
1899
|
e.preventDefault();
|
|
2380
1900
|
tableAction('addRowBelow');
|
|
2381
1901
|
}
|
|
@@ -2383,7 +1903,7 @@ function RichTextEditor(_ref) {
|
|
|
2383
1903
|
type: "button",
|
|
2384
1904
|
title: "Add Col Before",
|
|
2385
1905
|
className: "rte-toolbar-button",
|
|
2386
|
-
onMouseDown:
|
|
1906
|
+
onMouseDown: e => {
|
|
2387
1907
|
e.preventDefault();
|
|
2388
1908
|
tableAction('addColBefore');
|
|
2389
1909
|
}
|
|
@@ -2391,38 +1911,36 @@ function RichTextEditor(_ref) {
|
|
|
2391
1911
|
type: "button",
|
|
2392
1912
|
title: "Add Col After",
|
|
2393
1913
|
className: "rte-toolbar-button",
|
|
2394
|
-
onMouseDown:
|
|
1914
|
+
onMouseDown: e => {
|
|
2395
1915
|
e.preventDefault();
|
|
2396
1916
|
tableAction('addColAfter');
|
|
2397
1917
|
}
|
|
2398
|
-
}, "+C\u2192"), /*#__PURE__*/React.createElement("
|
|
2399
|
-
style: {
|
|
2400
|
-
width: '1px',
|
|
2401
|
-
height: '20px',
|
|
2402
|
-
backgroundColor: '#f3f4f6',
|
|
2403
|
-
margin: '0 4px'
|
|
2404
|
-
}
|
|
2405
|
-
}), /*#__PURE__*/React.createElement("button", {
|
|
1918
|
+
}, "+C\u2192"), /*#__PURE__*/React.createElement("button", {
|
|
2406
1919
|
type: "button",
|
|
2407
1920
|
title: "Merge Cells (Right)",
|
|
2408
1921
|
className: "rte-toolbar-button",
|
|
2409
|
-
onMouseDown:
|
|
1922
|
+
onMouseDown: e => {
|
|
2410
1923
|
e.preventDefault();
|
|
2411
1924
|
tableAction('mergeRight');
|
|
2412
1925
|
}
|
|
2413
1926
|
}, /*#__PURE__*/React.createElement(FaObjectGroup, {
|
|
2414
1927
|
size: 14
|
|
2415
|
-
})), /*#__PURE__*/React.createElement("
|
|
1928
|
+
})), /*#__PURE__*/React.createElement("div", {
|
|
1929
|
+
style: {
|
|
1930
|
+
display: 'flex',
|
|
1931
|
+
gap: '10px'
|
|
1932
|
+
}
|
|
1933
|
+
}, /*#__PURE__*/React.createElement("button", {
|
|
2416
1934
|
type: "button",
|
|
2417
1935
|
title: "Delete Row",
|
|
2418
|
-
className: "rte-toolbar-button rte-toolbar-button-danger
|
|
2419
|
-
onMouseDown:
|
|
1936
|
+
className: "rte-toolbar-button rte-toolbar-button-danger",
|
|
1937
|
+
onMouseDown: e => {
|
|
2420
1938
|
e.preventDefault();
|
|
2421
1939
|
tableAction('deleteRow');
|
|
2422
1940
|
}
|
|
2423
1941
|
}, /*#__PURE__*/React.createElement(FaTrash, {
|
|
2424
1942
|
size: 12
|
|
2425
|
-
}),
|
|
1943
|
+
}), /*#__PURE__*/React.createElement("span", {
|
|
2426
1944
|
style: {
|
|
2427
1945
|
fontSize: '10px'
|
|
2428
1946
|
}
|
|
@@ -2430,47 +1948,42 @@ function RichTextEditor(_ref) {
|
|
|
2430
1948
|
type: "button",
|
|
2431
1949
|
title: "Delete Column",
|
|
2432
1950
|
className: "rte-toolbar-button rte-toolbar-button-danger",
|
|
2433
|
-
onMouseDown:
|
|
1951
|
+
onMouseDown: e => {
|
|
2434
1952
|
e.preventDefault();
|
|
2435
1953
|
tableAction('deleteCol');
|
|
2436
1954
|
}
|
|
2437
1955
|
}, /*#__PURE__*/React.createElement(FaTrash, {
|
|
2438
1956
|
size: 12
|
|
2439
|
-
}),
|
|
1957
|
+
}), /*#__PURE__*/React.createElement("span", {
|
|
2440
1958
|
style: {
|
|
2441
|
-
fontSize: '10px'
|
|
2442
|
-
marginRight: "5px"
|
|
1959
|
+
fontSize: '10px'
|
|
2443
1960
|
}
|
|
2444
1961
|
}, "Col")), /*#__PURE__*/React.createElement("button", {
|
|
2445
1962
|
type: "button",
|
|
2446
1963
|
title: "Delete Table",
|
|
2447
1964
|
className: "rte-toolbar-button rte-toolbar-button-danger",
|
|
2448
|
-
onMouseDown:
|
|
1965
|
+
onMouseDown: e => {
|
|
2449
1966
|
e.preventDefault();
|
|
2450
1967
|
tableAction('deleteTable');
|
|
2451
1968
|
}
|
|
2452
1969
|
}, /*#__PURE__*/React.createElement(FaTrash, {
|
|
2453
|
-
size:
|
|
2454
|
-
}),
|
|
1970
|
+
size: 12
|
|
1971
|
+
}), /*#__PURE__*/React.createElement("span", {
|
|
2455
1972
|
style: {
|
|
2456
|
-
|
|
1973
|
+
fontSize: '10px'
|
|
2457
1974
|
}
|
|
2458
|
-
}, "Table")));
|
|
1975
|
+
}, "Table"))));
|
|
2459
1976
|
}
|
|
2460
1977
|
return null;
|
|
2461
|
-
}()), /*#__PURE__*/React.createElement("div", {
|
|
1978
|
+
})()), /*#__PURE__*/React.createElement("div", {
|
|
2462
1979
|
ref: editorRef,
|
|
2463
1980
|
contentEditable: editable && disabled !== true,
|
|
2464
1981
|
suppressContentEditableWarning: true,
|
|
2465
1982
|
onInput: handleInput,
|
|
2466
1983
|
onPaste: handlePaste,
|
|
2467
1984
|
onDrop: handleDrop,
|
|
2468
|
-
onDragStart:
|
|
2469
|
-
|
|
2470
|
-
},
|
|
2471
|
-
onDragOver: function onDragOver(e) {
|
|
2472
|
-
return e.preventDefault();
|
|
2473
|
-
},
|
|
1985
|
+
onDragStart: e => e.preventDefault(),
|
|
1986
|
+
onDragOver: e => e.preventDefault(),
|
|
2474
1987
|
onKeyDown: handleKeyDown,
|
|
2475
1988
|
onClick: handleEditorClick,
|
|
2476
1989
|
style: {
|
|
@@ -2479,30 +1992,22 @@ function RichTextEditor(_ref) {
|
|
|
2479
1992
|
paddingLeft: paddingLeft || '12px'
|
|
2480
1993
|
},
|
|
2481
1994
|
className: "rte-content"
|
|
2482
|
-
}),
|
|
1995
|
+
}), renderImageToolbar(), /*#__PURE__*/React.createElement("div", {
|
|
2483
1996
|
className: "rte-footer"
|
|
2484
|
-
},
|
|
2485
|
-
|
|
2486
|
-
|
|
2487
|
-
|
|
2488
|
-
|
|
2489
|
-
|
|
2490
|
-
|
|
2491
|
-
|
|
2492
|
-
|
|
2493
|
-
}, /*#__PURE__*/React.createElement("b", null, words), " words"), /*#__PURE__*/React.createElement("span", {
|
|
2494
|
-
className: "rte-footer-separator"
|
|
2495
|
-
}, "\u2022"), /*#__PURE__*/React.createElement("span", {
|
|
2496
|
-
className: "rte-footer-item"
|
|
2497
|
-
}, /*#__PURE__*/React.createElement("b", null, chars), " characters"));
|
|
2498
|
-
}()), 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", {
|
|
2499
2006
|
className: "rte-modal-overlay",
|
|
2500
2007
|
onClick: cancelLink
|
|
2501
2008
|
}, /*#__PURE__*/React.createElement("div", {
|
|
2502
2009
|
className: "rte-modal",
|
|
2503
|
-
onClick:
|
|
2504
|
-
return e.stopPropagation();
|
|
2505
|
-
}
|
|
2010
|
+
onClick: e => e.stopPropagation()
|
|
2506
2011
|
}, /*#__PURE__*/React.createElement("h3", {
|
|
2507
2012
|
className: "rte-modal-title"
|
|
2508
2013
|
}, "Insert Link"), /*#__PURE__*/React.createElement("div", {
|
|
@@ -2518,9 +2023,7 @@ function RichTextEditor(_ref) {
|
|
|
2518
2023
|
className: "rte-input",
|
|
2519
2024
|
placeholder: "e.g. Google",
|
|
2520
2025
|
value: linkText,
|
|
2521
|
-
onChange:
|
|
2522
|
-
return setLinkText(e.target.value);
|
|
2523
|
-
}
|
|
2026
|
+
onChange: e => setLinkText(e.target.value)
|
|
2524
2027
|
})), /*#__PURE__*/React.createElement("div", {
|
|
2525
2028
|
className: "rte-form-group"
|
|
2526
2029
|
}, /*#__PURE__*/React.createElement("label", {
|
|
@@ -2530,12 +2033,8 @@ function RichTextEditor(_ref) {
|
|
|
2530
2033
|
className: "rte-input",
|
|
2531
2034
|
placeholder: "https://example.com",
|
|
2532
2035
|
value: linkUrl,
|
|
2533
|
-
onChange:
|
|
2534
|
-
|
|
2535
|
-
},
|
|
2536
|
-
onKeyDown: function onKeyDown(e) {
|
|
2537
|
-
return e.key === 'Enter' && confirmLink();
|
|
2538
|
-
},
|
|
2036
|
+
onChange: e => setLinkUrl(e.target.value),
|
|
2037
|
+
onKeyDown: e => e.key === 'Enter' && confirmLink(),
|
|
2539
2038
|
autoFocus: true
|
|
2540
2039
|
}))), /*#__PURE__*/React.createElement("div", {
|
|
2541
2040
|
className: "rte-modal-divider",
|
|
@@ -2555,14 +2054,10 @@ function RichTextEditor(_ref) {
|
|
|
2555
2054
|
disabled: !linkUrl
|
|
2556
2055
|
}, "Insert")))), tableModalOpen && /*#__PURE__*/React.createElement("div", {
|
|
2557
2056
|
className: "rte-modal-overlay",
|
|
2558
|
-
onClick:
|
|
2559
|
-
return setTableModalOpen(false);
|
|
2560
|
-
}
|
|
2057
|
+
onClick: () => setTableModalOpen(false)
|
|
2561
2058
|
}, /*#__PURE__*/React.createElement("div", {
|
|
2562
2059
|
className: "rte-modal",
|
|
2563
|
-
onClick:
|
|
2564
|
-
return e.stopPropagation();
|
|
2565
|
-
}
|
|
2060
|
+
onClick: e => e.stopPropagation()
|
|
2566
2061
|
}, /*#__PURE__*/React.createElement("h3", {
|
|
2567
2062
|
className: "rte-modal-title"
|
|
2568
2063
|
}, "Insert Table"), /*#__PURE__*/React.createElement("div", {
|
|
@@ -2573,9 +2068,7 @@ function RichTextEditor(_ref) {
|
|
|
2573
2068
|
type: "number",
|
|
2574
2069
|
className: "rte-input",
|
|
2575
2070
|
value: tableRows,
|
|
2576
|
-
onChange:
|
|
2577
|
-
return setTableRows(e.target.value);
|
|
2578
|
-
},
|
|
2071
|
+
onChange: e => setTableRows(e.target.value),
|
|
2579
2072
|
min: "1",
|
|
2580
2073
|
max: "10"
|
|
2581
2074
|
})), /*#__PURE__*/React.createElement("div", {
|
|
@@ -2586,9 +2079,7 @@ function RichTextEditor(_ref) {
|
|
|
2586
2079
|
type: "number",
|
|
2587
2080
|
className: "rte-input",
|
|
2588
2081
|
value: tableCols,
|
|
2589
|
-
onChange:
|
|
2590
|
-
return setTableCols(e.target.value);
|
|
2591
|
-
},
|
|
2082
|
+
onChange: e => setTableCols(e.target.value),
|
|
2592
2083
|
min: "1",
|
|
2593
2084
|
max: "10"
|
|
2594
2085
|
})), /*#__PURE__*/React.createElement("div", {
|
|
@@ -2596,56 +2087,55 @@ function RichTextEditor(_ref) {
|
|
|
2596
2087
|
}, /*#__PURE__*/React.createElement("button", {
|
|
2597
2088
|
type: "button",
|
|
2598
2089
|
className: "rte-button rte-button-secondary",
|
|
2599
|
-
onClick:
|
|
2600
|
-
return setTableModalOpen(false);
|
|
2601
|
-
}
|
|
2090
|
+
onClick: () => setTableModalOpen(false)
|
|
2602
2091
|
}, "Cancel"), /*#__PURE__*/React.createElement("button", {
|
|
2603
2092
|
type: "button",
|
|
2604
2093
|
className: "rte-button rte-button-primary",
|
|
2605
2094
|
onClick: insertTable
|
|
2606
|
-
}, "Insert")))),
|
|
2095
|
+
}, "Insert")))), videoModalOpen && /*#__PURE__*/React.createElement("div", {
|
|
2607
2096
|
className: "rte-modal-overlay",
|
|
2608
|
-
onClick:
|
|
2609
|
-
return setYoutubeModalOpen(false);
|
|
2610
|
-
}
|
|
2097
|
+
onClick: () => setVideoModalOpen(false)
|
|
2611
2098
|
}, /*#__PURE__*/React.createElement("div", {
|
|
2612
2099
|
className: "rte-modal",
|
|
2613
|
-
onClick:
|
|
2614
|
-
return e.stopPropagation();
|
|
2615
|
-
}
|
|
2100
|
+
onClick: e => e.stopPropagation()
|
|
2616
2101
|
}, /*#__PURE__*/React.createElement("div", {
|
|
2617
2102
|
className: "rte-modal-header"
|
|
2618
2103
|
}, /*#__PURE__*/React.createElement("h3", {
|
|
2619
2104
|
className: "rte-modal-title"
|
|
2620
|
-
}, "Embed
|
|
2105
|
+
}, "Embed Video")), /*#__PURE__*/React.createElement("div", {
|
|
2621
2106
|
className: "rte-form-group"
|
|
2622
2107
|
}, /*#__PURE__*/React.createElement("label", {
|
|
2623
2108
|
className: "rte-label"
|
|
2624
|
-
}, "Paste YouTube
|
|
2109
|
+
}, "Paste Video URL (YouTube, Vimeo...) ", /*#__PURE__*/React.createElement("span", {
|
|
2110
|
+
style: {
|
|
2111
|
+
color: '#ef4444'
|
|
2112
|
+
}
|
|
2113
|
+
}, "*")), /*#__PURE__*/React.createElement("input", {
|
|
2625
2114
|
type: "text",
|
|
2626
2115
|
className: "rte-input",
|
|
2627
|
-
value:
|
|
2628
|
-
onChange:
|
|
2629
|
-
|
|
2630
|
-
},
|
|
2631
|
-
placeholder: "https://www.youtube.com/watch?v=...",
|
|
2116
|
+
value: videoUrl,
|
|
2117
|
+
onChange: e => setVideoUrl(e.target.value),
|
|
2118
|
+
placeholder: "Paste URL here...",
|
|
2632
2119
|
autoFocus: true,
|
|
2633
|
-
onKeyDown:
|
|
2634
|
-
if (e.key === 'Enter')
|
|
2635
|
-
if (e.key === 'Escape')
|
|
2120
|
+
onKeyDown: e => {
|
|
2121
|
+
if (e.key === 'Enter' && videoUrl.trim()) insertVideo();
|
|
2122
|
+
if (e.key === 'Escape') setVideoModalOpen(false);
|
|
2636
2123
|
}
|
|
2637
2124
|
})), /*#__PURE__*/React.createElement("div", {
|
|
2638
2125
|
className: "rte-modal-actions"
|
|
2639
2126
|
}, /*#__PURE__*/React.createElement("button", {
|
|
2640
2127
|
type: "button",
|
|
2641
2128
|
className: "rte-button rte-button-secondary",
|
|
2642
|
-
onClick:
|
|
2643
|
-
return setYoutubeModalOpen(false);
|
|
2644
|
-
}
|
|
2129
|
+
onClick: () => setVideoModalOpen(false)
|
|
2645
2130
|
}, "Cancel"), /*#__PURE__*/React.createElement("button", {
|
|
2646
2131
|
type: "button",
|
|
2647
2132
|
className: "rte-button rte-button-primary",
|
|
2648
|
-
onClick:
|
|
2133
|
+
onClick: () => {
|
|
2134
|
+
if (videoUrl.trim()) {
|
|
2135
|
+
insertVideo();
|
|
2136
|
+
}
|
|
2137
|
+
},
|
|
2138
|
+
disabled: !videoUrl.trim()
|
|
2649
2139
|
}, "Embed Video")))), imageModalOpen && /*#__PURE__*/React.createElement("div", {
|
|
2650
2140
|
className: "rte-modal-overlay",
|
|
2651
2141
|
onClick: closeImageModal
|
|
@@ -2655,16 +2145,14 @@ function RichTextEditor(_ref) {
|
|
|
2655
2145
|
maxWidth: "90%",
|
|
2656
2146
|
maxHeight: "90%"
|
|
2657
2147
|
},
|
|
2658
|
-
onClick:
|
|
2659
|
-
return e.stopPropagation();
|
|
2660
|
-
}
|
|
2148
|
+
onClick: e => e.stopPropagation()
|
|
2661
2149
|
}, /*#__PURE__*/React.createElement("img", {
|
|
2662
2150
|
src: selectedImageUrl,
|
|
2663
2151
|
style: {
|
|
2664
2152
|
width: "100%",
|
|
2665
2153
|
maxHeight: "90vh",
|
|
2666
2154
|
borderRadius: '12px',
|
|
2667
|
-
transform:
|
|
2155
|
+
transform: `scale(${zoomLevel})`,
|
|
2668
2156
|
transition: "transform 0.2s ease",
|
|
2669
2157
|
boxShadow: '0 25px 50px -12px rgba(0,0,0,0.5)'
|
|
2670
2158
|
},
|
|
@@ -2679,13 +2167,11 @@ function RichTextEditor(_ref) {
|
|
|
2679
2167
|
}, /*#__PURE__*/React.createElement("button", {
|
|
2680
2168
|
type: "button",
|
|
2681
2169
|
className: "rte-button rte-button-secondary",
|
|
2682
|
-
onClick:
|
|
2683
|
-
return setEditable(false);
|
|
2684
|
-
}
|
|
2170
|
+
onClick: () => setEditable(false)
|
|
2685
2171
|
}, "Cancel"), /*#__PURE__*/React.createElement("button", {
|
|
2686
2172
|
type: "button",
|
|
2687
2173
|
className: "rte-button rte-button-primary",
|
|
2688
|
-
onClick:
|
|
2174
|
+
onClick: () => {
|
|
2689
2175
|
onChange && onChange(html);
|
|
2690
2176
|
setEditable(false);
|
|
2691
2177
|
}
|