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