@tarviks/lexical-rich-editor 1.0.3 → 1.0.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/README.md +198 -198
- package/dist/index.css +23 -4
- package/dist/index.css.map +1 -1
- package/dist/index.d.mts +55 -8
- package/dist/index.d.ts +55 -8
- package/dist/index.js +570 -311
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +572 -313
- package/dist/index.mjs.map +1 -1
- package/package.json +8 -7
package/dist/index.js
CHANGED
|
@@ -9,6 +9,7 @@ var useLexicalNodeSelection = require('@lexical/react/useLexicalNodeSelection');
|
|
|
9
9
|
var lexical = require('lexical');
|
|
10
10
|
var react = require('@fluentui/react');
|
|
11
11
|
var reactComponents = require('@fluentui/react-components');
|
|
12
|
+
var reactIcons = require('@fluentui/react-icons');
|
|
12
13
|
var code = require('@lexical/code');
|
|
13
14
|
var link = require('@lexical/link');
|
|
14
15
|
var list = require('@lexical/list');
|
|
@@ -26,7 +27,6 @@ var richText = require('@lexical/rich-text');
|
|
|
26
27
|
var table = require('@lexical/table');
|
|
27
28
|
var LexicalBlockWithAlignableContents = require('@lexical/react/LexicalBlockWithAlignableContents');
|
|
28
29
|
var LexicalDecoratorBlockNode = require('@lexical/react/LexicalDecoratorBlockNode');
|
|
29
|
-
var reactIcons = require('@fluentui/react-icons');
|
|
30
30
|
var selection = require('@lexical/selection');
|
|
31
31
|
var reactDom = require('react-dom');
|
|
32
32
|
var html = require('@lexical/html');
|
|
@@ -243,80 +243,107 @@ var init_ImageResizer = __esm({
|
|
|
243
243
|
document.removeEventListener("pointerup", handlePointerUp);
|
|
244
244
|
}
|
|
245
245
|
};
|
|
246
|
-
return
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
onPointerDown: (event) => {
|
|
252
|
-
handlePointerDown(event, Direction.north);
|
|
253
|
-
}
|
|
254
|
-
}
|
|
255
|
-
),
|
|
256
|
-
/* @__PURE__ */ jsxRuntime.jsx(
|
|
257
|
-
"div",
|
|
258
|
-
{
|
|
259
|
-
className: "image-resizer image-resizer-ne",
|
|
260
|
-
onPointerDown: (event) => {
|
|
261
|
-
handlePointerDown(event, Direction.north | Direction.east);
|
|
262
|
-
}
|
|
263
|
-
}
|
|
264
|
-
),
|
|
265
|
-
/* @__PURE__ */ jsxRuntime.jsx(
|
|
266
|
-
"div",
|
|
267
|
-
{
|
|
268
|
-
className: "image-resizer image-resizer-e",
|
|
269
|
-
onPointerDown: (event) => {
|
|
270
|
-
handlePointerDown(event, Direction.east);
|
|
271
|
-
}
|
|
272
|
-
}
|
|
273
|
-
),
|
|
274
|
-
/* @__PURE__ */ jsxRuntime.jsx(
|
|
275
|
-
"div",
|
|
276
|
-
{
|
|
277
|
-
className: "image-resizer image-resizer-se",
|
|
278
|
-
onPointerDown: (event) => {
|
|
279
|
-
handlePointerDown(event, Direction.south | Direction.east);
|
|
280
|
-
}
|
|
281
|
-
}
|
|
282
|
-
),
|
|
283
|
-
/* @__PURE__ */ jsxRuntime.jsx(
|
|
284
|
-
"div",
|
|
285
|
-
{
|
|
286
|
-
className: "image-resizer image-resizer-s",
|
|
287
|
-
onPointerDown: (event) => {
|
|
288
|
-
handlePointerDown(event, Direction.south);
|
|
289
|
-
}
|
|
290
|
-
}
|
|
291
|
-
),
|
|
292
|
-
/* @__PURE__ */ jsxRuntime.jsx(
|
|
293
|
-
"div",
|
|
294
|
-
{
|
|
295
|
-
className: "image-resizer image-resizer-sw",
|
|
296
|
-
onPointerDown: (event) => {
|
|
297
|
-
handlePointerDown(event, Direction.south | Direction.west);
|
|
298
|
-
}
|
|
299
|
-
}
|
|
300
|
-
),
|
|
301
|
-
/* @__PURE__ */ jsxRuntime.jsx(
|
|
302
|
-
"div",
|
|
303
|
-
{
|
|
304
|
-
className: "image-resizer image-resizer-w",
|
|
305
|
-
onPointerDown: (event) => {
|
|
306
|
-
handlePointerDown(event, Direction.west);
|
|
307
|
-
}
|
|
308
|
-
}
|
|
309
|
-
),
|
|
310
|
-
/* @__PURE__ */ jsxRuntime.jsx(
|
|
246
|
+
return (
|
|
247
|
+
// Overlay that exactly covers the image container (position:relative parent).
|
|
248
|
+
// pointer-events:none lets clicks pass through to the image; each handle
|
|
249
|
+
// re-enables pointer-events so drag-resize still works.
|
|
250
|
+
/* @__PURE__ */ jsxRuntime.jsxs(
|
|
311
251
|
"div",
|
|
312
252
|
{
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
253
|
+
ref: controlWrapperRef,
|
|
254
|
+
style: {
|
|
255
|
+
position: "absolute",
|
|
256
|
+
top: 0,
|
|
257
|
+
right: 0,
|
|
258
|
+
bottom: 0,
|
|
259
|
+
left: 0,
|
|
260
|
+
pointerEvents: "none"
|
|
261
|
+
},
|
|
262
|
+
children: [
|
|
263
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
264
|
+
"div",
|
|
265
|
+
{
|
|
266
|
+
className: "image-resizer image-resizer-n",
|
|
267
|
+
style: { pointerEvents: "auto" },
|
|
268
|
+
onPointerDown: (event) => {
|
|
269
|
+
handlePointerDown(event, Direction.north);
|
|
270
|
+
}
|
|
271
|
+
}
|
|
272
|
+
),
|
|
273
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
274
|
+
"div",
|
|
275
|
+
{
|
|
276
|
+
className: "image-resizer image-resizer-ne",
|
|
277
|
+
style: { pointerEvents: "auto" },
|
|
278
|
+
onPointerDown: (event) => {
|
|
279
|
+
handlePointerDown(event, Direction.north | Direction.east);
|
|
280
|
+
}
|
|
281
|
+
}
|
|
282
|
+
),
|
|
283
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
284
|
+
"div",
|
|
285
|
+
{
|
|
286
|
+
className: "image-resizer image-resizer-e",
|
|
287
|
+
style: { pointerEvents: "auto" },
|
|
288
|
+
onPointerDown: (event) => {
|
|
289
|
+
handlePointerDown(event, Direction.east);
|
|
290
|
+
}
|
|
291
|
+
}
|
|
292
|
+
),
|
|
293
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
294
|
+
"div",
|
|
295
|
+
{
|
|
296
|
+
className: "image-resizer image-resizer-se",
|
|
297
|
+
style: { pointerEvents: "auto" },
|
|
298
|
+
onPointerDown: (event) => {
|
|
299
|
+
handlePointerDown(event, Direction.south | Direction.east);
|
|
300
|
+
}
|
|
301
|
+
}
|
|
302
|
+
),
|
|
303
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
304
|
+
"div",
|
|
305
|
+
{
|
|
306
|
+
className: "image-resizer image-resizer-s",
|
|
307
|
+
style: { pointerEvents: "auto" },
|
|
308
|
+
onPointerDown: (event) => {
|
|
309
|
+
handlePointerDown(event, Direction.south);
|
|
310
|
+
}
|
|
311
|
+
}
|
|
312
|
+
),
|
|
313
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
314
|
+
"div",
|
|
315
|
+
{
|
|
316
|
+
className: "image-resizer image-resizer-sw",
|
|
317
|
+
style: { pointerEvents: "auto" },
|
|
318
|
+
onPointerDown: (event) => {
|
|
319
|
+
handlePointerDown(event, Direction.south | Direction.west);
|
|
320
|
+
}
|
|
321
|
+
}
|
|
322
|
+
),
|
|
323
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
324
|
+
"div",
|
|
325
|
+
{
|
|
326
|
+
className: "image-resizer image-resizer-w",
|
|
327
|
+
style: { pointerEvents: "auto" },
|
|
328
|
+
onPointerDown: (event) => {
|
|
329
|
+
handlePointerDown(event, Direction.west);
|
|
330
|
+
}
|
|
331
|
+
}
|
|
332
|
+
),
|
|
333
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
334
|
+
"div",
|
|
335
|
+
{
|
|
336
|
+
className: "image-resizer image-resizer-nw",
|
|
337
|
+
style: { pointerEvents: "auto" },
|
|
338
|
+
onPointerDown: (event) => {
|
|
339
|
+
handlePointerDown(event, Direction.north | Direction.west);
|
|
340
|
+
}
|
|
341
|
+
}
|
|
342
|
+
)
|
|
343
|
+
]
|
|
317
344
|
}
|
|
318
345
|
)
|
|
319
|
-
|
|
346
|
+
);
|
|
320
347
|
};
|
|
321
348
|
ImageResizer_default = ImageResizer;
|
|
322
349
|
}
|
|
@@ -3567,6 +3594,204 @@ function PageBreakPlugin() {
|
|
|
3567
3594
|
}, [editor]);
|
|
3568
3595
|
return null;
|
|
3569
3596
|
}
|
|
3597
|
+
|
|
3598
|
+
// src/Utils/Sanitize.ts
|
|
3599
|
+
var DROP_ENTIRELY = /* @__PURE__ */ new Set([
|
|
3600
|
+
"script",
|
|
3601
|
+
"noscript",
|
|
3602
|
+
"style",
|
|
3603
|
+
"object",
|
|
3604
|
+
"embed",
|
|
3605
|
+
"form",
|
|
3606
|
+
"input",
|
|
3607
|
+
"button",
|
|
3608
|
+
"select",
|
|
3609
|
+
"textarea",
|
|
3610
|
+
"meta",
|
|
3611
|
+
"link",
|
|
3612
|
+
"base"
|
|
3613
|
+
]);
|
|
3614
|
+
var ALLOWED_TAGS = /* @__PURE__ */ new Set([
|
|
3615
|
+
// Block
|
|
3616
|
+
"p",
|
|
3617
|
+
"h1",
|
|
3618
|
+
"h2",
|
|
3619
|
+
"h3",
|
|
3620
|
+
"h4",
|
|
3621
|
+
"h5",
|
|
3622
|
+
"h6",
|
|
3623
|
+
"ul",
|
|
3624
|
+
"ol",
|
|
3625
|
+
"li",
|
|
3626
|
+
"blockquote",
|
|
3627
|
+
"pre",
|
|
3628
|
+
"div",
|
|
3629
|
+
"table",
|
|
3630
|
+
"thead",
|
|
3631
|
+
"tbody",
|
|
3632
|
+
"tfoot",
|
|
3633
|
+
"tr",
|
|
3634
|
+
"td",
|
|
3635
|
+
"th",
|
|
3636
|
+
// Inline
|
|
3637
|
+
"span",
|
|
3638
|
+
"a",
|
|
3639
|
+
"strong",
|
|
3640
|
+
"b",
|
|
3641
|
+
"em",
|
|
3642
|
+
"i",
|
|
3643
|
+
"u",
|
|
3644
|
+
"s",
|
|
3645
|
+
"del",
|
|
3646
|
+
"strike",
|
|
3647
|
+
"sub",
|
|
3648
|
+
"sup",
|
|
3649
|
+
"mark",
|
|
3650
|
+
"code",
|
|
3651
|
+
"br",
|
|
3652
|
+
"hr",
|
|
3653
|
+
// Media / embeds
|
|
3654
|
+
"img",
|
|
3655
|
+
"iframe"
|
|
3656
|
+
]);
|
|
3657
|
+
var ALLOWED_ATTRS = /* @__PURE__ */ new Set([
|
|
3658
|
+
// Presentation
|
|
3659
|
+
"class",
|
|
3660
|
+
"style",
|
|
3661
|
+
"dir",
|
|
3662
|
+
"lang",
|
|
3663
|
+
// Anchors
|
|
3664
|
+
"href",
|
|
3665
|
+
"target",
|
|
3666
|
+
"rel",
|
|
3667
|
+
// Images
|
|
3668
|
+
"src",
|
|
3669
|
+
"alt",
|
|
3670
|
+
"width",
|
|
3671
|
+
"height",
|
|
3672
|
+
// Tables
|
|
3673
|
+
"colspan",
|
|
3674
|
+
"rowspan",
|
|
3675
|
+
// Lists — <ol type="a"> and <ol start="2">
|
|
3676
|
+
"start",
|
|
3677
|
+
"type",
|
|
3678
|
+
// Lexical-internal data markers
|
|
3679
|
+
"data-lex-block",
|
|
3680
|
+
"data-kind",
|
|
3681
|
+
"data-lexical-decorator",
|
|
3682
|
+
// Misc
|
|
3683
|
+
"title",
|
|
3684
|
+
"allowfullscreen"
|
|
3685
|
+
]);
|
|
3686
|
+
var DANGEROUS_URL = /^\s*(javascript|data\s*:|vbscript)/i;
|
|
3687
|
+
function sanitizeElement(el) {
|
|
3688
|
+
for (const child of Array.from(el.children)) {
|
|
3689
|
+
sanitizeElement(child);
|
|
3690
|
+
}
|
|
3691
|
+
const tag = el.tagName.toLowerCase();
|
|
3692
|
+
if (DROP_ENTIRELY.has(tag)) {
|
|
3693
|
+
el.parentNode?.removeChild(el);
|
|
3694
|
+
return;
|
|
3695
|
+
}
|
|
3696
|
+
if (tag === "iframe") {
|
|
3697
|
+
const src = el.getAttribute("src") ?? "";
|
|
3698
|
+
const isYouTube = /^\s*https:\/\/(www\.)?(youtube\.com|youtube-nocookie\.com)\/embed\/[^?&/]+/i.test(src);
|
|
3699
|
+
if (!isYouTube) {
|
|
3700
|
+
el.parentNode?.removeChild(el);
|
|
3701
|
+
return;
|
|
3702
|
+
}
|
|
3703
|
+
}
|
|
3704
|
+
if (!ALLOWED_TAGS.has(tag)) {
|
|
3705
|
+
while (el.firstChild) {
|
|
3706
|
+
el.parentNode?.insertBefore(el.firstChild, el);
|
|
3707
|
+
}
|
|
3708
|
+
el.parentNode?.removeChild(el);
|
|
3709
|
+
return;
|
|
3710
|
+
}
|
|
3711
|
+
for (const { name, value } of Array.from(el.attributes)) {
|
|
3712
|
+
const lname = name.toLowerCase();
|
|
3713
|
+
if (!ALLOWED_ATTRS.has(lname)) {
|
|
3714
|
+
el.removeAttribute(name);
|
|
3715
|
+
continue;
|
|
3716
|
+
}
|
|
3717
|
+
if (lname === "href" || lname === "src") {
|
|
3718
|
+
if (DANGEROUS_URL.test(value)) {
|
|
3719
|
+
el.removeAttribute(name);
|
|
3720
|
+
}
|
|
3721
|
+
}
|
|
3722
|
+
if (lname === "style") {
|
|
3723
|
+
const safe = value.replace(/expression\s*\(/gi, "(").replace(/url\s*\(\s*['"]?\s*javascript:/gi, "url(");
|
|
3724
|
+
el.setAttribute("style", safe);
|
|
3725
|
+
}
|
|
3726
|
+
}
|
|
3727
|
+
if (tag === "a" && (el.getAttribute("target") || "").toLowerCase() === "_blank") {
|
|
3728
|
+
const rel = (el.getAttribute("rel") || "").trim();
|
|
3729
|
+
const tokens = new Set(
|
|
3730
|
+
rel.split(/\s+/).filter(Boolean).map((t) => t.toLowerCase())
|
|
3731
|
+
);
|
|
3732
|
+
tokens.add("noopener");
|
|
3733
|
+
tokens.add("noreferrer");
|
|
3734
|
+
el.setAttribute("rel", Array.from(tokens).join(" "));
|
|
3735
|
+
}
|
|
3736
|
+
}
|
|
3737
|
+
function sanitizeHtml(html) {
|
|
3738
|
+
if (!html || typeof html !== "string") return "";
|
|
3739
|
+
const doc = new DOMParser().parseFromString(html, "text/html");
|
|
3740
|
+
for (const child of Array.from(doc.body.children)) {
|
|
3741
|
+
sanitizeElement(child);
|
|
3742
|
+
}
|
|
3743
|
+
return doc.body.innerHTML;
|
|
3744
|
+
}
|
|
3745
|
+
var BLOCK_TAGS = /* @__PURE__ */ new Set([
|
|
3746
|
+
"p",
|
|
3747
|
+
"h1",
|
|
3748
|
+
"h2",
|
|
3749
|
+
"h3",
|
|
3750
|
+
"h4",
|
|
3751
|
+
"h5",
|
|
3752
|
+
"h6",
|
|
3753
|
+
"div",
|
|
3754
|
+
"ul",
|
|
3755
|
+
"ol",
|
|
3756
|
+
"li",
|
|
3757
|
+
"table",
|
|
3758
|
+
"blockquote",
|
|
3759
|
+
"pre",
|
|
3760
|
+
"hr"
|
|
3761
|
+
]);
|
|
3762
|
+
function normalizeToBlockHtml(html) {
|
|
3763
|
+
if (!html) return "";
|
|
3764
|
+
const doc = new DOMParser().parseFromString(html, "text/html");
|
|
3765
|
+
const body = doc.body;
|
|
3766
|
+
const childNodes = Array.from(body.childNodes);
|
|
3767
|
+
const needsWrap = childNodes.some((node) => {
|
|
3768
|
+
if (node.nodeType === Node.TEXT_NODE) return !!node.nodeValue?.trim();
|
|
3769
|
+
if (node.nodeType === Node.ELEMENT_NODE)
|
|
3770
|
+
return !BLOCK_TAGS.has(node.tagName.toLowerCase());
|
|
3771
|
+
return false;
|
|
3772
|
+
});
|
|
3773
|
+
if (!needsWrap) return html;
|
|
3774
|
+
while (body.firstChild) body.removeChild(body.firstChild);
|
|
3775
|
+
let pendingP = null;
|
|
3776
|
+
for (const node of childNodes) {
|
|
3777
|
+
const isBlock = node.nodeType === Node.ELEMENT_NODE && BLOCK_TAGS.has(node.tagName.toLowerCase());
|
|
3778
|
+
const isWhitespace = node.nodeType === Node.TEXT_NODE && !node.nodeValue?.trim();
|
|
3779
|
+
if (isBlock) {
|
|
3780
|
+
if (pendingP) {
|
|
3781
|
+
body.appendChild(pendingP);
|
|
3782
|
+
pendingP = null;
|
|
3783
|
+
}
|
|
3784
|
+
body.appendChild(node);
|
|
3785
|
+
} else if (!isWhitespace) {
|
|
3786
|
+
if (!pendingP) pendingP = doc.createElement("p");
|
|
3787
|
+
pendingP.appendChild(node);
|
|
3788
|
+
}
|
|
3789
|
+
}
|
|
3790
|
+
if (pendingP) body.appendChild(pendingP);
|
|
3791
|
+
return body.innerHTML;
|
|
3792
|
+
}
|
|
3793
|
+
|
|
3794
|
+
// src/Utils/Helper.ts
|
|
3570
3795
|
function findBlockByKind(kind) {
|
|
3571
3796
|
const root = lexical.$getRoot();
|
|
3572
3797
|
for (const child of root.getChildren()) {
|
|
@@ -3575,8 +3800,9 @@ function findBlockByKind(kind) {
|
|
|
3575
3800
|
return null;
|
|
3576
3801
|
}
|
|
3577
3802
|
function importHtmlIntoBlock(editor, block, html$1) {
|
|
3803
|
+
const safe = normalizeToBlockHtml(sanitizeHtml(html$1));
|
|
3578
3804
|
const parser = new DOMParser();
|
|
3579
|
-
const doc = parser.parseFromString(
|
|
3805
|
+
const doc = parser.parseFromString(safe || "<p></p>", "text/html");
|
|
3580
3806
|
const nodes = html.$generateNodesFromDOM(editor, doc);
|
|
3581
3807
|
block.clear();
|
|
3582
3808
|
block.append(...nodes);
|
|
@@ -3615,7 +3841,8 @@ function hasBlock(editor, kind) {
|
|
|
3615
3841
|
function RefApiPlugin({
|
|
3616
3842
|
forwardedRef,
|
|
3617
3843
|
contentEditableDomRef,
|
|
3618
|
-
focusedRef
|
|
3844
|
+
focusedRef,
|
|
3845
|
+
setRefErrors
|
|
3619
3846
|
}) {
|
|
3620
3847
|
const [editor] = LexicalComposerContext.useLexicalComposerContext();
|
|
3621
3848
|
React6.useImperativeHandle(
|
|
@@ -3654,12 +3881,14 @@ function RefApiPlugin({
|
|
|
3654
3881
|
},
|
|
3655
3882
|
isFocused: () => focusedRef.current,
|
|
3656
3883
|
getEditor: () => editor,
|
|
3884
|
+
setErrors: (messages) => setRefErrors(messages),
|
|
3885
|
+
clearErrors: () => setRefErrors([]),
|
|
3657
3886
|
// Generic blocks (signature, footer, banner, etc.)
|
|
3658
3887
|
upsertBlock: (spec) => upsertBlock(editor, spec),
|
|
3659
3888
|
removeBlock: (kind) => removeBlock(editor, kind),
|
|
3660
3889
|
hasBlock: (kind) => hasBlock(editor, kind)
|
|
3661
3890
|
}),
|
|
3662
|
-
[editor, contentEditableDomRef, focusedRef]
|
|
3891
|
+
[editor, contentEditableDomRef, focusedRef, setRefErrors]
|
|
3663
3892
|
);
|
|
3664
3893
|
return null;
|
|
3665
3894
|
}
|
|
@@ -4299,8 +4528,8 @@ function SpellCheckPlugin({
|
|
|
4299
4528
|
function TableActionMenuPlugin({ disabled = false }) {
|
|
4300
4529
|
const [editor] = LexicalComposerContext.useLexicalComposerContext();
|
|
4301
4530
|
const [isInTable, setIsInTable] = React6__namespace.useState(false);
|
|
4531
|
+
const [anchorRect, setAnchorRect] = React6__namespace.useState(null);
|
|
4302
4532
|
const [open, setOpen] = React6__namespace.useState(false);
|
|
4303
|
-
const [menuPos, setMenuPos] = React6__namespace.useState(null);
|
|
4304
4533
|
const updateFromSelection = React6__namespace.useCallback(() => {
|
|
4305
4534
|
const root = editor.getRootElement();
|
|
4306
4535
|
if (!root) return;
|
|
@@ -4309,21 +4538,34 @@ function TableActionMenuPlugin({ disabled = false }) {
|
|
|
4309
4538
|
if (table.$isTableSelection(selection)) {
|
|
4310
4539
|
const tableNode = selection.getNodes().find((n) => table.$isTableNode(n));
|
|
4311
4540
|
if (tableNode) {
|
|
4312
|
-
|
|
4313
|
-
|
|
4541
|
+
const dom = editor.getElementByKey(tableNode.getKey());
|
|
4542
|
+
if (dom) {
|
|
4543
|
+
setIsInTable(true);
|
|
4544
|
+
setAnchorRect(dom.getBoundingClientRect());
|
|
4545
|
+
return;
|
|
4546
|
+
}
|
|
4314
4547
|
}
|
|
4315
4548
|
}
|
|
4316
4549
|
if (!lexical.$isRangeSelection(selection)) {
|
|
4317
4550
|
setIsInTable(false);
|
|
4551
|
+
setAnchorRect(null);
|
|
4318
4552
|
return;
|
|
4319
4553
|
}
|
|
4320
4554
|
const anchorNode = selection.anchor.getNode();
|
|
4321
4555
|
const cellNode = table.$isTableCellNode(anchorNode) ? anchorNode : lexical.$findMatchingParent(anchorNode, (n) => table.$isTableCellNode(n));
|
|
4322
4556
|
if (!cellNode || !table.$isTableCellNode(cellNode)) {
|
|
4323
4557
|
setIsInTable(false);
|
|
4558
|
+
setAnchorRect(null);
|
|
4559
|
+
return;
|
|
4560
|
+
}
|
|
4561
|
+
const cellDom = editor.getElementByKey(cellNode.getKey());
|
|
4562
|
+
if (!cellDom) {
|
|
4563
|
+
setIsInTable(false);
|
|
4564
|
+
setAnchorRect(null);
|
|
4324
4565
|
return;
|
|
4325
4566
|
}
|
|
4326
4567
|
setIsInTable(true);
|
|
4568
|
+
setAnchorRect(cellDom.getBoundingClientRect());
|
|
4327
4569
|
});
|
|
4328
4570
|
}, [editor]);
|
|
4329
4571
|
React6__namespace.useEffect(() => {
|
|
@@ -4385,33 +4627,18 @@ function TableActionMenuPlugin({ disabled = false }) {
|
|
|
4385
4627
|
React6__namespace.useEffect(() => {
|
|
4386
4628
|
if (!isInTable && open) setOpen(false);
|
|
4387
4629
|
}, [isInTable, open]);
|
|
4388
|
-
|
|
4389
|
-
|
|
4390
|
-
if (!
|
|
4391
|
-
const
|
|
4392
|
-
|
|
4393
|
-
|
|
4394
|
-
|
|
4395
|
-
|
|
4396
|
-
|
|
4397
|
-
|
|
4398
|
-
return;
|
|
4399
|
-
}
|
|
4400
|
-
if (lexical.$isRangeSelection(selection)) {
|
|
4401
|
-
const node = selection.anchor.getNode();
|
|
4402
|
-
const cell = table.$isTableCellNode(node) ? node : lexical.$findMatchingParent(node, (n) => table.$isTableCellNode(n));
|
|
4403
|
-
if (cell) inTable = true;
|
|
4404
|
-
}
|
|
4405
|
-
});
|
|
4406
|
-
if (inTable) {
|
|
4407
|
-
e.preventDefault();
|
|
4408
|
-
setMenuPos({ x: e.clientX, y: e.clientY });
|
|
4409
|
-
setOpen(true);
|
|
4410
|
-
}
|
|
4630
|
+
const canShow = isInTable && !!anchorRect && !disabled;
|
|
4631
|
+
const handleStyle = React6__namespace.useMemo(() => {
|
|
4632
|
+
if (!anchorRect) return void 0;
|
|
4633
|
+
const top = Math.max(8, anchorRect.top + 6);
|
|
4634
|
+
const left = Math.max(8, anchorRect.right - 34);
|
|
4635
|
+
return {
|
|
4636
|
+
position: "fixed",
|
|
4637
|
+
top,
|
|
4638
|
+
left,
|
|
4639
|
+
zIndex: 9999
|
|
4411
4640
|
};
|
|
4412
|
-
|
|
4413
|
-
return () => root.removeEventListener("contextmenu", handleContextMenu);
|
|
4414
|
-
}, [editor, disabled]);
|
|
4641
|
+
}, [anchorRect]);
|
|
4415
4642
|
const dangerStyle = {
|
|
4416
4643
|
color: "var(--colorPaletteRedForeground1)"
|
|
4417
4644
|
};
|
|
@@ -4444,55 +4671,63 @@ function TableActionMenuPlugin({ disabled = false }) {
|
|
|
4444
4671
|
const table$1 = table.$getTableNodeFromLexicalNodeOrThrow(cell);
|
|
4445
4672
|
table$1.remove();
|
|
4446
4673
|
});
|
|
4447
|
-
|
|
4448
|
-
if (!menuPos) return void 0;
|
|
4449
|
-
return {
|
|
4450
|
-
getBoundingClientRect: () => new DOMRect(menuPos.x, menuPos.y, 0, 0)
|
|
4451
|
-
};
|
|
4452
|
-
}, [menuPos]);
|
|
4453
|
-
if (disabled) return null;
|
|
4674
|
+
if (!canShow || !handleStyle) return null;
|
|
4454
4675
|
return reactDom.createPortal(
|
|
4455
|
-
/* @__PURE__ */ jsxRuntime.jsx(
|
|
4456
|
-
/* @__PURE__ */ jsxRuntime.
|
|
4457
|
-
|
|
4458
|
-
|
|
4459
|
-
|
|
4460
|
-
|
|
4461
|
-
|
|
4462
|
-
|
|
4463
|
-
|
|
4464
|
-
|
|
4465
|
-
|
|
4466
|
-
|
|
4467
|
-
|
|
4468
|
-
|
|
4469
|
-
|
|
4470
|
-
/* @__PURE__ */ jsxRuntime.jsx(
|
|
4471
|
-
|
|
4676
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { style: handleStyle, className: "aoTableActionHandleRoot", children: /* @__PURE__ */ jsxRuntime.jsxs(reactComponents.Menu, { open, onOpenChange: (_, data) => setOpen(data.open), children: [
|
|
4677
|
+
/* @__PURE__ */ jsxRuntime.jsx(reactComponents.MenuTrigger, { disableButtonEnhancement: true, children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
4678
|
+
"button",
|
|
4679
|
+
{
|
|
4680
|
+
type: "button",
|
|
4681
|
+
className: "aoTableActionHandleBtn",
|
|
4682
|
+
"aria-label": "Table options",
|
|
4683
|
+
onMouseDown: (e) => {
|
|
4684
|
+
e.preventDefault();
|
|
4685
|
+
},
|
|
4686
|
+
children: /* @__PURE__ */ jsxRuntime.jsx(reactIcons.ChevronDown12Regular, {})
|
|
4687
|
+
}
|
|
4688
|
+
) }),
|
|
4689
|
+
/* @__PURE__ */ jsxRuntime.jsx(reactComponents.MenuPopover, { className: "aoTableActionPopover", children: /* @__PURE__ */ jsxRuntime.jsxs(reactComponents.MenuList, { children: [
|
|
4690
|
+
/* @__PURE__ */ jsxRuntime.jsxs(reactComponents.MenuGroup, { children: [
|
|
4691
|
+
/* @__PURE__ */ jsxRuntime.jsx(reactComponents.MenuGroupHeader, { children: "Insert" }),
|
|
4692
|
+
/* @__PURE__ */ jsxRuntime.jsx(reactComponents.MenuItem, { icon: /* @__PURE__ */ jsxRuntime.jsx(reactIcons.RowTripleRegular, {}), onClick: insertRowAbove, children: /* @__PURE__ */ jsxRuntime.jsxs("span", { className: "aoMenuRow", children: [
|
|
4693
|
+
/* @__PURE__ */ jsxRuntime.jsxs("span", { className: "aoMenuLabel", children: [
|
|
4694
|
+
/* @__PURE__ */ jsxRuntime.jsx(reactIcons.ArrowUpRegular, {}),
|
|
4695
|
+
" Row above"
|
|
4696
|
+
] }),
|
|
4697
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "aoMenuShortcut", children: "Alt \u21E7 \u2191" })
|
|
4698
|
+
] }) }),
|
|
4699
|
+
/* @__PURE__ */ jsxRuntime.jsx(reactComponents.MenuItem, { icon: /* @__PURE__ */ jsxRuntime.jsx(reactIcons.RowTripleRegular, {}), onClick: insertRowBelow, children: /* @__PURE__ */ jsxRuntime.jsxs("span", { className: "aoMenuRow", children: [
|
|
4700
|
+
/* @__PURE__ */ jsxRuntime.jsxs("span", { className: "aoMenuLabel", children: [
|
|
4701
|
+
/* @__PURE__ */ jsxRuntime.jsx(reactIcons.ArrowDownRegular, {}),
|
|
4702
|
+
" Row below"
|
|
4703
|
+
] }),
|
|
4704
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "aoMenuShortcut", children: "Alt \u21E7 \u2193" })
|
|
4705
|
+
] }) }),
|
|
4706
|
+
/* @__PURE__ */ jsxRuntime.jsx(reactComponents.MenuDivider, {}),
|
|
4707
|
+
/* @__PURE__ */ jsxRuntime.jsx(reactComponents.MenuItem, { icon: /* @__PURE__ */ jsxRuntime.jsx(reactIcons.ColumnTripleRegular, {}), onClick: insertColLeft, children: /* @__PURE__ */ jsxRuntime.jsxs("span", { className: "aoMenuRow", children: [
|
|
4708
|
+
/* @__PURE__ */ jsxRuntime.jsxs("span", { className: "aoMenuLabel", children: [
|
|
4709
|
+
/* @__PURE__ */ jsxRuntime.jsx(reactIcons.ArrowLeftRegular, {}),
|
|
4710
|
+
" Column left"
|
|
4711
|
+
] }),
|
|
4712
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "aoMenuShortcut", children: "Alt \u21E7 \u2190" })
|
|
4713
|
+
] }) }),
|
|
4714
|
+
/* @__PURE__ */ jsxRuntime.jsx(reactComponents.MenuItem, { icon: /* @__PURE__ */ jsxRuntime.jsx(reactIcons.ColumnTripleRegular, {}), onClick: insertColRight, children: /* @__PURE__ */ jsxRuntime.jsxs("span", { className: "aoMenuRow", children: [
|
|
4715
|
+
/* @__PURE__ */ jsxRuntime.jsxs("span", { className: "aoMenuLabel", children: [
|
|
4716
|
+
/* @__PURE__ */ jsxRuntime.jsx(reactIcons.ArrowRightRegular, {}),
|
|
4717
|
+
" Column right"
|
|
4718
|
+
] }),
|
|
4719
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "aoMenuShortcut", children: "Alt \u21E7 \u2192" })
|
|
4720
|
+
] }) })
|
|
4721
|
+
] }),
|
|
4472
4722
|
/* @__PURE__ */ jsxRuntime.jsx(reactComponents.MenuDivider, {}),
|
|
4473
|
-
/* @__PURE__ */ jsxRuntime.
|
|
4474
|
-
/* @__PURE__ */ jsxRuntime.
|
|
4475
|
-
|
|
4476
|
-
|
|
4477
|
-
|
|
4478
|
-
|
|
4479
|
-
|
|
4480
|
-
|
|
4481
|
-
/* @__PURE__ */ jsxRuntime.jsxs("span", { className: "aoMenuLabel", children: [
|
|
4482
|
-
/* @__PURE__ */ jsxRuntime.jsx(reactIcons.ArrowRightRegular, {}),
|
|
4483
|
-
" Column right"
|
|
4484
|
-
] }),
|
|
4485
|
-
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "aoMenuShortcut", children: "Alt \u21E7 \u2192" })
|
|
4486
|
-
] }) })
|
|
4487
|
-
] }),
|
|
4488
|
-
/* @__PURE__ */ jsxRuntime.jsx(reactComponents.MenuDivider, {}),
|
|
4489
|
-
/* @__PURE__ */ jsxRuntime.jsxs(reactComponents.MenuGroup, { children: [
|
|
4490
|
-
/* @__PURE__ */ jsxRuntime.jsx(reactComponents.MenuGroupHeader, { children: "Delete" }),
|
|
4491
|
-
/* @__PURE__ */ jsxRuntime.jsx(reactComponents.MenuItem, { icon: /* @__PURE__ */ jsxRuntime.jsx(reactIcons.DeleteRegular, {}), onClick: deleteRow, style: dangerStyle, children: "Delete row" }),
|
|
4492
|
-
/* @__PURE__ */ jsxRuntime.jsx(reactComponents.MenuItem, { icon: /* @__PURE__ */ jsxRuntime.jsx(reactIcons.DeleteRegular, {}), onClick: deleteCol, style: dangerStyle, children: "Delete column" }),
|
|
4493
|
-
/* @__PURE__ */ jsxRuntime.jsx(reactComponents.MenuItem, { icon: /* @__PURE__ */ jsxRuntime.jsx(reactIcons.DeleteRegular, {}), onClick: deleteTable, style: dangerStyle, children: "Delete table" })
|
|
4494
|
-
] })
|
|
4495
|
-
] }) }) }),
|
|
4723
|
+
/* @__PURE__ */ jsxRuntime.jsxs(reactComponents.MenuGroup, { children: [
|
|
4724
|
+
/* @__PURE__ */ jsxRuntime.jsx(reactComponents.MenuGroupHeader, { children: "Delete" }),
|
|
4725
|
+
/* @__PURE__ */ jsxRuntime.jsx(reactComponents.MenuItem, { icon: /* @__PURE__ */ jsxRuntime.jsx(reactIcons.DeleteRegular, {}), onClick: deleteRow, style: dangerStyle, children: "Delete row" }),
|
|
4726
|
+
/* @__PURE__ */ jsxRuntime.jsx(reactComponents.MenuItem, { icon: /* @__PURE__ */ jsxRuntime.jsx(reactIcons.DeleteRegular, {}), onClick: deleteCol, style: dangerStyle, children: "Delete column" }),
|
|
4727
|
+
/* @__PURE__ */ jsxRuntime.jsx(reactComponents.MenuItem, { icon: /* @__PURE__ */ jsxRuntime.jsx(reactIcons.DeleteRegular, {}), onClick: deleteTable, style: dangerStyle, children: "Delete table" })
|
|
4728
|
+
] })
|
|
4729
|
+
] }) })
|
|
4730
|
+
] }) }),
|
|
4496
4731
|
document.body
|
|
4497
4732
|
);
|
|
4498
4733
|
}
|
|
@@ -4796,13 +5031,6 @@ function getToolbarGroupsByLevel(level) {
|
|
|
4796
5031
|
];
|
|
4797
5032
|
}
|
|
4798
5033
|
}
|
|
4799
|
-
var DEFAULT_FONT_SIZE = 15;
|
|
4800
|
-
var formatParagraph = (editor) => {
|
|
4801
|
-
editor.update(() => {
|
|
4802
|
-
const selection$1 = lexical.$getSelection();
|
|
4803
|
-
selection.$setBlocksType(selection$1, () => lexical.$createParagraphNode());
|
|
4804
|
-
});
|
|
4805
|
-
};
|
|
4806
5034
|
var PRESET = [
|
|
4807
5035
|
"#000000",
|
|
4808
5036
|
"#434343",
|
|
@@ -5108,7 +5336,9 @@ var ColorPickerPlugin = ({ disabled }) => {
|
|
|
5108
5336
|
}, [editor]);
|
|
5109
5337
|
const applyStyle = (args) => {
|
|
5110
5338
|
if (disabled) return;
|
|
5111
|
-
editor.
|
|
5339
|
+
const root = editor.getRootElement();
|
|
5340
|
+
const editorIsActive = !!lastRangeSelectionRef.current && !!root && (document.activeElement === root || root.contains(document.activeElement));
|
|
5341
|
+
if (editorIsActive) editor.focus();
|
|
5112
5342
|
editor.update(() => {
|
|
5113
5343
|
const saved = lastRangeSelectionRef.current;
|
|
5114
5344
|
if (saved) {
|
|
@@ -5247,6 +5477,7 @@ var FontFamilyPlugin = ({ disabled = false }) => {
|
|
|
5247
5477
|
"font-family"
|
|
5248
5478
|
);
|
|
5249
5479
|
};
|
|
5480
|
+
var DEFAULT_FONT_SIZE = 15;
|
|
5250
5481
|
var FONT_SIZE_OPTIONS = [
|
|
5251
5482
|
"8",
|
|
5252
5483
|
"9",
|
|
@@ -5547,21 +5778,27 @@ var TableItemPlugin = ({ disabled }) => {
|
|
|
5547
5778
|
reactComponents.Input,
|
|
5548
5779
|
{
|
|
5549
5780
|
autoFocus: !disabled,
|
|
5781
|
+
type: "number",
|
|
5782
|
+
min: 1,
|
|
5550
5783
|
value: rows,
|
|
5551
5784
|
placeholder: "Rows",
|
|
5552
5785
|
appearance: "underline",
|
|
5553
5786
|
disabled,
|
|
5554
|
-
|
|
5787
|
+
input: { style: { textAlign: "left" } },
|
|
5788
|
+
onChange: (_, v) => setRows(v.value.replace(/\D/g, ""))
|
|
5555
5789
|
}
|
|
5556
5790
|
) }),
|
|
5557
5791
|
/* @__PURE__ */ jsxRuntime.jsx(reactComponents.Field, { label: "Columns", orientation: "horizontal", size: "small", children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
5558
5792
|
reactComponents.Input,
|
|
5559
5793
|
{
|
|
5794
|
+
type: "number",
|
|
5795
|
+
min: 1,
|
|
5560
5796
|
value: columns,
|
|
5561
5797
|
placeholder: "Columns",
|
|
5562
5798
|
appearance: "underline",
|
|
5563
5799
|
disabled,
|
|
5564
|
-
|
|
5800
|
+
input: { style: { textAlign: "left" } },
|
|
5801
|
+
onChange: (_, v) => setColumns(v.value.replace(/\D/g, ""))
|
|
5565
5802
|
}
|
|
5566
5803
|
) }),
|
|
5567
5804
|
/* @__PURE__ */ jsxRuntime.jsxs(react.Stack, { horizontal: true, horizontalAlign: "end", tokens: { childrenGap: 6 }, children: [
|
|
@@ -5718,8 +5955,7 @@ var ToolBarPlugins = (props) => {
|
|
|
5718
5955
|
const [isLowercase, setIsLowercase] = React6.useState(false);
|
|
5719
5956
|
const [isCapitalize, setIsCapitalize] = React6.useState(false);
|
|
5720
5957
|
const [alignment, setAlignment] = React6.useState("left");
|
|
5721
|
-
const
|
|
5722
|
-
const [tableNodeKey, setTableNodeKey] = React6.useState(null);
|
|
5958
|
+
const lastSelectionRef = React6__namespace.default.useRef(null);
|
|
5723
5959
|
const presetGroups = getToolbarGroupsByLevel(props.level);
|
|
5724
5960
|
const pluginGroups = React6.useMemo(() => sanitizePluginGroups(presetGroups), [presetGroups]);
|
|
5725
5961
|
const updateToolbarPlugins = () => {
|
|
@@ -5736,8 +5972,6 @@ var ToolBarPlugins = (props) => {
|
|
|
5736
5972
|
setIsLowercase(false);
|
|
5737
5973
|
setIsCapitalize(false);
|
|
5738
5974
|
setSelectNodeType("paragraph");
|
|
5739
|
-
setIsInTable(false);
|
|
5740
|
-
setTableNodeKey(null);
|
|
5741
5975
|
return;
|
|
5742
5976
|
}
|
|
5743
5977
|
setIsBold(selection.hasFormat("bold"));
|
|
@@ -5753,21 +5987,8 @@ var ToolBarPlugins = (props) => {
|
|
|
5753
5987
|
const anchorNode = selection.anchor.getNode();
|
|
5754
5988
|
if (anchorNode.getKey() === "root") {
|
|
5755
5989
|
setSelectNodeType("paragraph");
|
|
5756
|
-
setIsInTable(false);
|
|
5757
|
-
setTableNodeKey(null);
|
|
5758
5990
|
return;
|
|
5759
5991
|
}
|
|
5760
|
-
let tableAncestorKey = null;
|
|
5761
|
-
let cursor = anchorNode.getParent();
|
|
5762
|
-
while (cursor !== null) {
|
|
5763
|
-
if (cursor.getType() === "table") {
|
|
5764
|
-
tableAncestorKey = cursor.getKey();
|
|
5765
|
-
break;
|
|
5766
|
-
}
|
|
5767
|
-
cursor = cursor.getParent();
|
|
5768
|
-
}
|
|
5769
|
-
setIsInTable(tableAncestorKey !== null);
|
|
5770
|
-
setTableNodeKey(tableAncestorKey);
|
|
5771
5992
|
const element = anchorNode.getTopLevelElementOrThrow();
|
|
5772
5993
|
setAlignment(
|
|
5773
5994
|
typeof element.getFormatType === "function" ? element.getFormatType() || "left" : "left"
|
|
@@ -5788,12 +6009,21 @@ var ToolBarPlugins = (props) => {
|
|
|
5788
6009
|
["paragraph", "h1", "h2", "h3", "h4", "h5", "h6", "ul", "ol", "quote", "code"].includes(type) ? type : "paragraph"
|
|
5789
6010
|
);
|
|
5790
6011
|
};
|
|
6012
|
+
const applyToBlock = React6__namespace.default.useCallback(
|
|
6013
|
+
(fn) => {
|
|
6014
|
+
editor.update(() => {
|
|
6015
|
+
const saved = lastSelectionRef.current;
|
|
6016
|
+
if (saved) lexical.$setSelection(saved.clone());
|
|
6017
|
+
const sel = lexical.$getSelection();
|
|
6018
|
+
if (lexical.$isRangeSelection(sel)) fn(sel);
|
|
6019
|
+
});
|
|
6020
|
+
},
|
|
6021
|
+
[editor]
|
|
6022
|
+
);
|
|
5791
6023
|
const formatQuote = () => {
|
|
5792
|
-
|
|
5793
|
-
const selection$1 = lexical.$getSelection();
|
|
5794
|
-
if (!lexical.$isRangeSelection(selection$1)) return;
|
|
6024
|
+
applyToBlock((selection$1) => {
|
|
5795
6025
|
if (selectNodeType === "quote") {
|
|
5796
|
-
|
|
6026
|
+
selection.$setBlocksType(selection$1, () => lexical.$createParagraphNode());
|
|
5797
6027
|
} else {
|
|
5798
6028
|
selection.$setBlocksType(selection$1, () => richText.$createQuoteNode());
|
|
5799
6029
|
}
|
|
@@ -5812,6 +6042,8 @@ var ToolBarPlugins = (props) => {
|
|
|
5812
6042
|
editor.registerCommand(
|
|
5813
6043
|
lexical.SELECTION_CHANGE_COMMAND,
|
|
5814
6044
|
() => {
|
|
6045
|
+
const sel = lexical.$getSelection();
|
|
6046
|
+
if (lexical.$isRangeSelection(sel)) lastSelectionRef.current = sel.clone();
|
|
5815
6047
|
updateToolbarPlugins();
|
|
5816
6048
|
return false;
|
|
5817
6049
|
},
|
|
@@ -5843,16 +6075,52 @@ var ToolBarPlugins = (props) => {
|
|
|
5843
6075
|
editor.dispatchCommand(lexical.FORMAT_TEXT_COMMAND, "highlight");
|
|
5844
6076
|
break;
|
|
5845
6077
|
case "leftAlign" /* LeftAlign */:
|
|
5846
|
-
|
|
6078
|
+
applyToBlock((sel) => {
|
|
6079
|
+
const seen = /* @__PURE__ */ new Set();
|
|
6080
|
+
sel.getNodes().forEach((n) => {
|
|
6081
|
+
const t = n.getTopLevelElementOrThrow();
|
|
6082
|
+
if (!seen.has(t.getKey())) {
|
|
6083
|
+
seen.add(t.getKey());
|
|
6084
|
+
t.setFormat("left");
|
|
6085
|
+
}
|
|
6086
|
+
});
|
|
6087
|
+
});
|
|
5847
6088
|
break;
|
|
5848
6089
|
case "rightAlign" /* RightAlign */:
|
|
5849
|
-
|
|
6090
|
+
applyToBlock((sel) => {
|
|
6091
|
+
const seen = /* @__PURE__ */ new Set();
|
|
6092
|
+
sel.getNodes().forEach((n) => {
|
|
6093
|
+
const t = n.getTopLevelElementOrThrow();
|
|
6094
|
+
if (!seen.has(t.getKey())) {
|
|
6095
|
+
seen.add(t.getKey());
|
|
6096
|
+
t.setFormat("right");
|
|
6097
|
+
}
|
|
6098
|
+
});
|
|
6099
|
+
});
|
|
5850
6100
|
break;
|
|
5851
6101
|
case "centerAlign" /* CenterAlign */:
|
|
5852
|
-
|
|
6102
|
+
applyToBlock((sel) => {
|
|
6103
|
+
const seen = /* @__PURE__ */ new Set();
|
|
6104
|
+
sel.getNodes().forEach((n) => {
|
|
6105
|
+
const t = n.getTopLevelElementOrThrow();
|
|
6106
|
+
if (!seen.has(t.getKey())) {
|
|
6107
|
+
seen.add(t.getKey());
|
|
6108
|
+
t.setFormat("center");
|
|
6109
|
+
}
|
|
6110
|
+
});
|
|
6111
|
+
});
|
|
5853
6112
|
break;
|
|
5854
6113
|
case "justifyAlign" /* JustifyAlign */:
|
|
5855
|
-
|
|
6114
|
+
applyToBlock((sel) => {
|
|
6115
|
+
const seen = /* @__PURE__ */ new Set();
|
|
6116
|
+
sel.getNodes().forEach((n) => {
|
|
6117
|
+
const t = n.getTopLevelElementOrThrow();
|
|
6118
|
+
if (!seen.has(t.getKey())) {
|
|
6119
|
+
seen.add(t.getKey());
|
|
6120
|
+
t.setFormat("justify");
|
|
6121
|
+
}
|
|
6122
|
+
});
|
|
6123
|
+
});
|
|
5856
6124
|
break;
|
|
5857
6125
|
case "undo" /* Undo */:
|
|
5858
6126
|
editor.dispatchCommand(lexical.UNDO_COMMAND, void 0);
|
|
@@ -5872,14 +6140,8 @@ var ToolBarPlugins = (props) => {
|
|
|
5872
6140
|
}
|
|
5873
6141
|
};
|
|
5874
6142
|
const updateHeading = (heading) => {
|
|
5875
|
-
|
|
5876
|
-
|
|
5877
|
-
if (lexical.$isRangeSelection(selection$1)) {
|
|
5878
|
-
selection.$setBlocksType(selection$1, () => richText.$createHeadingNode(heading));
|
|
5879
|
-
}
|
|
5880
|
-
});
|
|
5881
|
-
editor.getEditorState().read(() => {
|
|
5882
|
-
updateToolbarPlugins();
|
|
6143
|
+
applyToBlock((selection$1) => {
|
|
6144
|
+
selection.$setBlocksType(selection$1, () => richText.$createHeadingNode(heading));
|
|
5883
6145
|
});
|
|
5884
6146
|
};
|
|
5885
6147
|
const renderToken = (token, groupIndex, tokenIndex) => {
|
|
@@ -6018,7 +6280,7 @@ var ToolBarPlugins = (props) => {
|
|
|
6018
6280
|
const val = data.optionValue;
|
|
6019
6281
|
if (!val) return;
|
|
6020
6282
|
if (val === "paragraph") {
|
|
6021
|
-
|
|
6283
|
+
applyToBlock((sel) => selection.$setBlocksType(sel, () => lexical.$createParagraphNode()));
|
|
6022
6284
|
setSelectNodeType("paragraph");
|
|
6023
6285
|
} else {
|
|
6024
6286
|
updateHeading(val);
|
|
@@ -6102,16 +6364,10 @@ var ToolBarPlugins = (props) => {
|
|
|
6102
6364
|
onHandleSelectOption("highlight" /* Highlight */);
|
|
6103
6365
|
break;
|
|
6104
6366
|
case "ul-list":
|
|
6105
|
-
editor.dispatchCommand(
|
|
6106
|
-
selectNodeType === "ul" ? list.REMOVE_LIST_COMMAND : list.INSERT_UNORDERED_LIST_COMMAND,
|
|
6107
|
-
void 0
|
|
6108
|
-
);
|
|
6367
|
+
editor.dispatchCommand(selectNodeType === "ul" ? list.REMOVE_LIST_COMMAND : list.INSERT_UNORDERED_LIST_COMMAND, void 0);
|
|
6109
6368
|
break;
|
|
6110
6369
|
case "ol-list":
|
|
6111
|
-
editor.dispatchCommand(
|
|
6112
|
-
selectNodeType === "ol" ? list.REMOVE_LIST_COMMAND : list.INSERT_ORDERED_LIST_COMMAND,
|
|
6113
|
-
void 0
|
|
6114
|
-
);
|
|
6370
|
+
editor.dispatchCommand(selectNodeType === "ol" ? list.REMOVE_LIST_COMMAND : list.INSERT_ORDERED_LIST_COMMAND, void 0);
|
|
6115
6371
|
break;
|
|
6116
6372
|
case "page-break":
|
|
6117
6373
|
editor.dispatchCommand(INSERT_PAGE_BREAK, void 0);
|
|
@@ -6147,12 +6403,7 @@ var ToolBarPlugins = (props) => {
|
|
|
6147
6403
|
"Superscript"
|
|
6148
6404
|
] }),
|
|
6149
6405
|
/* @__PURE__ */ jsxRuntime.jsxs(reactComponents.Option, { value: "highlight", text: "Highlight", children: [
|
|
6150
|
-
/* @__PURE__ */ jsxRuntime.jsx(
|
|
6151
|
-
reactIcons.HighlightAccentFilled,
|
|
6152
|
-
{
|
|
6153
|
-
style: { ...optionIconStyle, color: isEditable ? brand : fgDisabled }
|
|
6154
|
-
}
|
|
6155
|
-
),
|
|
6406
|
+
/* @__PURE__ */ jsxRuntime.jsx(reactIcons.HighlightAccentFilled, { style: { ...optionIconStyle, color: isEditable ? brand : fgDisabled } }),
|
|
6156
6407
|
"Highlight"
|
|
6157
6408
|
] }),
|
|
6158
6409
|
/* @__PURE__ */ jsxRuntime.jsxs(reactComponents.Option, { value: "ul-list", text: "Bullet list", children: [
|
|
@@ -6188,30 +6439,10 @@ var ToolBarPlugins = (props) => {
|
|
|
6188
6439
|
// );
|
|
6189
6440
|
case "Align": {
|
|
6190
6441
|
const ALIGN_OPTIONS = [
|
|
6191
|
-
{
|
|
6192
|
-
|
|
6193
|
-
|
|
6194
|
-
|
|
6195
|
-
action: "leftAlign" /* LeftAlign */
|
|
6196
|
-
},
|
|
6197
|
-
{
|
|
6198
|
-
value: "center",
|
|
6199
|
-
label: "Center Align",
|
|
6200
|
-
icon: /* @__PURE__ */ jsxRuntime.jsx(reactIcons.TextAlignCenterFilled, { style: optionIconStyle }),
|
|
6201
|
-
action: "centerAlign" /* CenterAlign */
|
|
6202
|
-
},
|
|
6203
|
-
{
|
|
6204
|
-
value: "right",
|
|
6205
|
-
label: "Right Align",
|
|
6206
|
-
icon: /* @__PURE__ */ jsxRuntime.jsx(reactIcons.TextAlignRightFilled, { style: optionIconStyle }),
|
|
6207
|
-
action: "rightAlign" /* RightAlign */
|
|
6208
|
-
},
|
|
6209
|
-
{
|
|
6210
|
-
value: "justify",
|
|
6211
|
-
label: "Justify Align",
|
|
6212
|
-
icon: /* @__PURE__ */ jsxRuntime.jsx(reactIcons.TextAlignJustifyFilled, { style: optionIconStyle }),
|
|
6213
|
-
action: "justifyAlign" /* JustifyAlign */
|
|
6214
|
-
}
|
|
6442
|
+
{ value: "left", label: "Left Align", icon: /* @__PURE__ */ jsxRuntime.jsx(reactIcons.TextAlignLeftFilled, { style: optionIconStyle }), action: "leftAlign" /* LeftAlign */ },
|
|
6443
|
+
{ value: "center", label: "Center Align", icon: /* @__PURE__ */ jsxRuntime.jsx(reactIcons.TextAlignCenterFilled, { style: optionIconStyle }), action: "centerAlign" /* CenterAlign */ },
|
|
6444
|
+
{ value: "right", label: "Right Align", icon: /* @__PURE__ */ jsxRuntime.jsx(reactIcons.TextAlignRightFilled, { style: optionIconStyle }), action: "rightAlign" /* RightAlign */ },
|
|
6445
|
+
{ value: "justify", label: "Justify Align", icon: /* @__PURE__ */ jsxRuntime.jsx(reactIcons.TextAlignJustifyFilled, { style: optionIconStyle }), action: "justifyAlign" /* JustifyAlign */ }
|
|
6215
6446
|
];
|
|
6216
6447
|
const alignLabel = ALIGN_OPTIONS.find((o) => o.value === alignment)?.label ?? "Left Align";
|
|
6217
6448
|
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
@@ -6245,69 +6476,29 @@ var ToolBarPlugins = (props) => {
|
|
|
6245
6476
|
if (!pluginGroups || pluginGroups.length === 0) {
|
|
6246
6477
|
return null;
|
|
6247
6478
|
}
|
|
6248
|
-
return /* @__PURE__ */ jsxRuntime.
|
|
6249
|
-
|
|
6250
|
-
|
|
6251
|
-
|
|
6252
|
-
|
|
6253
|
-
|
|
6254
|
-
|
|
6255
|
-
|
|
6256
|
-
|
|
6257
|
-
|
|
6258
|
-
|
|
6259
|
-
|
|
6260
|
-
|
|
6261
|
-
|
|
6262
|
-
|
|
6263
|
-
|
|
6264
|
-
|
|
6265
|
-
|
|
6266
|
-
|
|
6267
|
-
|
|
6268
|
-
|
|
6269
|
-
|
|
6270
|
-
|
|
6271
|
-
),
|
|
6272
|
-
isInTable && /* @__PURE__ */ jsxRuntime.jsxs(
|
|
6273
|
-
"div",
|
|
6274
|
-
{
|
|
6275
|
-
style: {
|
|
6276
|
-
display: "flex",
|
|
6277
|
-
alignItems: "center",
|
|
6278
|
-
gap: 6,
|
|
6279
|
-
padding: "2px 8px",
|
|
6280
|
-
borderBottom: "1px solid #ccced1",
|
|
6281
|
-
background: "#fff8f8"
|
|
6282
|
-
},
|
|
6283
|
-
children: [
|
|
6284
|
-
/* @__PURE__ */ jsxRuntime.jsx("span", { style: { fontSize: 12, color: "#888", userSelect: "none" }, children: "Table" }),
|
|
6285
|
-
/* @__PURE__ */ jsxRuntime.jsx(
|
|
6286
|
-
reactComponents.Button,
|
|
6287
|
-
{
|
|
6288
|
-
size: "small",
|
|
6289
|
-
icon: /* @__PURE__ */ jsxRuntime.jsx(reactIcons.DeleteRegular, { style: { color: "#c4272c" } }),
|
|
6290
|
-
title: "Delete table",
|
|
6291
|
-
style: {
|
|
6292
|
-
background: "transparent",
|
|
6293
|
-
border: "none",
|
|
6294
|
-
color: "#c4272c",
|
|
6295
|
-
fontWeight: 500
|
|
6296
|
-
},
|
|
6297
|
-
onClick: () => {
|
|
6298
|
-
editor.update(() => {
|
|
6299
|
-
if (!tableNodeKey) return;
|
|
6300
|
-
const node = lexical.$getNodeByKey(tableNodeKey);
|
|
6301
|
-
if (node?.getType() === "table") node.remove();
|
|
6302
|
-
});
|
|
6303
|
-
},
|
|
6304
|
-
children: "Delete Table"
|
|
6305
|
-
}
|
|
6306
|
-
)
|
|
6307
|
-
]
|
|
6308
|
-
}
|
|
6309
|
-
)
|
|
6310
|
-
] });
|
|
6479
|
+
return /* @__PURE__ */ jsxRuntime.jsx(react.Stack, { children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
6480
|
+
"div",
|
|
6481
|
+
{
|
|
6482
|
+
role: "toolbar",
|
|
6483
|
+
"aria-label": "Editor toolbar",
|
|
6484
|
+
style: {
|
|
6485
|
+
display: "flex",
|
|
6486
|
+
flexWrap: "wrap",
|
|
6487
|
+
alignItems: "center",
|
|
6488
|
+
borderBottom: "1px solid #ccced1",
|
|
6489
|
+
background: "#ffffff",
|
|
6490
|
+
padding: "0px",
|
|
6491
|
+
minHeight: 36
|
|
6492
|
+
},
|
|
6493
|
+
children: pluginGroups.map((group, groupIndex) => /* @__PURE__ */ jsxRuntime.jsx(React6__namespace.default.Fragment, { children: group.map((token, tokenIndex) => {
|
|
6494
|
+
try {
|
|
6495
|
+
return renderToken(token, groupIndex, tokenIndex);
|
|
6496
|
+
} catch {
|
|
6497
|
+
return null;
|
|
6498
|
+
}
|
|
6499
|
+
}) }, `group-${groupIndex}`))
|
|
6500
|
+
}
|
|
6501
|
+
) });
|
|
6311
6502
|
};
|
|
6312
6503
|
function isYoutubeLikeNode(node) {
|
|
6313
6504
|
try {
|
|
@@ -6460,10 +6651,23 @@ function BrowserSpellCheckPlugin({ enabled }) {
|
|
|
6460
6651
|
function WordCountPlugin({ onCountChange }) {
|
|
6461
6652
|
const [editor] = LexicalComposerContext.useLexicalComposerContext();
|
|
6462
6653
|
React6.useEffect(() => {
|
|
6463
|
-
return editor.registerUpdateListener(() => {
|
|
6464
|
-
|
|
6465
|
-
|
|
6466
|
-
|
|
6654
|
+
return editor.registerUpdateListener(({ editorState }) => {
|
|
6655
|
+
editorState.read(() => {
|
|
6656
|
+
const text = lexical.$getRoot().getTextContent();
|
|
6657
|
+
const words = text.trim() === "" ? 0 : text.trim().split(/\s+/).length;
|
|
6658
|
+
onCountChange(words);
|
|
6659
|
+
});
|
|
6660
|
+
});
|
|
6661
|
+
}, [editor, onCountChange]);
|
|
6662
|
+
return null;
|
|
6663
|
+
}
|
|
6664
|
+
function CharCountPlugin({ onCountChange }) {
|
|
6665
|
+
const [editor] = LexicalComposerContext.useLexicalComposerContext();
|
|
6666
|
+
React6.useEffect(() => {
|
|
6667
|
+
return editor.registerUpdateListener(({ editorState }) => {
|
|
6668
|
+
editorState.read(() => {
|
|
6669
|
+
onCountChange(lexical.$getRoot().getTextContent().length);
|
|
6670
|
+
});
|
|
6467
6671
|
});
|
|
6468
6672
|
}, [editor, onCountChange]);
|
|
6469
6673
|
return null;
|
|
@@ -6613,6 +6817,9 @@ var ContentEditorComponent = React6.forwardRef(
|
|
|
6613
6817
|
const [isLinkEditMode, setIsLinkEditMode] = React6.useState(false);
|
|
6614
6818
|
const [wordCount, setWordCount] = React6.useState(0);
|
|
6615
6819
|
const handleWordCount = React6.useCallback((count) => setWordCount(count), []);
|
|
6820
|
+
const [charCount, setCharCount] = React6.useState(0);
|
|
6821
|
+
const handleCharCount = React6.useCallback((count) => setCharCount(count), []);
|
|
6822
|
+
const [refErrors, setRefErrors] = React6.useState([]);
|
|
6616
6823
|
const contentEditableDomRef = React6.useRef(null);
|
|
6617
6824
|
const previousOverLimitRef = React6.useRef(false);
|
|
6618
6825
|
const focusedRef = React6.useRef(false);
|
|
@@ -6692,7 +6899,41 @@ var ContentEditorComponent = React6.forwardRef(
|
|
|
6692
6899
|
e.stopPropagation();
|
|
6693
6900
|
}
|
|
6694
6901
|
};
|
|
6902
|
+
const [touched, setTouched] = React6.useState(false);
|
|
6695
6903
|
const isOverLimit = props.wordLimit !== void 0 && wordCount > props.wordLimit;
|
|
6904
|
+
const internalErrors = [];
|
|
6905
|
+
if (isOverLimit) {
|
|
6906
|
+
const m = props.errorMessages?.wordLimitExceeded;
|
|
6907
|
+
internalErrors.push(
|
|
6908
|
+
typeof m === "function" ? m(wordCount, props.wordLimit) : m ?? `Word limit exceeded (${wordCount} / ${props.wordLimit} words used)`
|
|
6909
|
+
);
|
|
6910
|
+
}
|
|
6911
|
+
if (props.required && touched && wordCount === 0) {
|
|
6912
|
+
internalErrors.push(
|
|
6913
|
+
props.errorMessages?.required ?? "This field is required"
|
|
6914
|
+
);
|
|
6915
|
+
}
|
|
6916
|
+
if (props.minWords !== void 0 && touched && wordCount < props.minWords) {
|
|
6917
|
+
const m = props.errorMessages?.minWords;
|
|
6918
|
+
internalErrors.push(
|
|
6919
|
+
typeof m === "function" ? m(wordCount, props.minWords) : m ?? `Minimum ${props.minWords} words required (${wordCount} entered)`
|
|
6920
|
+
);
|
|
6921
|
+
}
|
|
6922
|
+
if (props.maxChars !== void 0 && charCount > props.maxChars) {
|
|
6923
|
+
const m = props.errorMessages?.maxCharsExceeded;
|
|
6924
|
+
internalErrors.push(
|
|
6925
|
+
typeof m === "function" ? m(charCount, props.maxChars) : m ?? `Character limit exceeded (${charCount} / ${props.maxChars} characters used)`
|
|
6926
|
+
);
|
|
6927
|
+
}
|
|
6928
|
+
if (props.minChars !== void 0 && touched && charCount < props.minChars && charCount > 0) {
|
|
6929
|
+
const m = props.errorMessages?.minCharsRequired;
|
|
6930
|
+
internalErrors.push(
|
|
6931
|
+
typeof m === "function" ? m(charCount, props.minChars) : m ?? `Minimum ${props.minChars} characters required (${charCount} entered)`
|
|
6932
|
+
);
|
|
6933
|
+
}
|
|
6934
|
+
const allErrors = [...internalErrors, ...props.errors ?? [], ...refErrors];
|
|
6935
|
+
const hasErrors = allErrors.length > 0;
|
|
6936
|
+
const hasRedBorder = hasErrors;
|
|
6696
6937
|
React6.useEffect(() => {
|
|
6697
6938
|
if (props.wordLimit === void 0 || !props.onWordLimitExceeded) return;
|
|
6698
6939
|
const wasOverLimit = previousOverLimitRef.current;
|
|
@@ -6715,7 +6956,7 @@ var ContentEditorComponent = React6.forwardRef(
|
|
|
6715
6956
|
width: props.width ?? "100%",
|
|
6716
6957
|
height: props.height ?? "100%",
|
|
6717
6958
|
margin: props.margin ?? "5px auto",
|
|
6718
|
-
border: `1px solid ${
|
|
6959
|
+
border: `1px solid ${hasRedBorder ? "#c4272c" : "var(--colorNeutralStroke1, #ccced1)"}`,
|
|
6719
6960
|
transition: "border-color 0.2s",
|
|
6720
6961
|
display: "flex",
|
|
6721
6962
|
flexDirection: "column"
|
|
@@ -6745,7 +6986,9 @@ var ContentEditorComponent = React6.forwardRef(
|
|
|
6745
6986
|
position: "relative",
|
|
6746
6987
|
flexGrow: 1,
|
|
6747
6988
|
padding: "15px 0px",
|
|
6748
|
-
overflowY: "scroll"
|
|
6989
|
+
overflowY: "scroll",
|
|
6990
|
+
overflowX: "auto",
|
|
6991
|
+
minWidth: 0
|
|
6749
6992
|
},
|
|
6750
6993
|
onClickCapture: handleReadOnlyClickCapture,
|
|
6751
6994
|
children: [
|
|
@@ -6809,13 +7052,33 @@ var ContentEditorComponent = React6.forwardRef(
|
|
|
6809
7052
|
]
|
|
6810
7053
|
}
|
|
6811
7054
|
),
|
|
7055
|
+
hasErrors && /* @__PURE__ */ jsxRuntime.jsx(
|
|
7056
|
+
"div",
|
|
7057
|
+
{
|
|
7058
|
+
style: {
|
|
7059
|
+
borderTop: "1px solid #fbd5d5",
|
|
7060
|
+
background: "#fff8f8",
|
|
7061
|
+
padding: "6px 12px 8px",
|
|
7062
|
+
display: "flex",
|
|
7063
|
+
flexDirection: "column",
|
|
7064
|
+
gap: 4
|
|
7065
|
+
},
|
|
7066
|
+
children: allErrors.map((err, i) => /* @__PURE__ */ jsxRuntime.jsxs("div", { style: { display: "flex", alignItems: "center", gap: 6 }, children: [
|
|
7067
|
+
/* @__PURE__ */ jsxRuntime.jsx(reactIcons.ErrorCircleRegular, { style: { fontSize: 14, color: "#c4272c", flexShrink: 0 } }),
|
|
7068
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { style: { fontSize: 12, color: "#c4272c" }, children: err })
|
|
7069
|
+
] }, i))
|
|
7070
|
+
}
|
|
7071
|
+
),
|
|
6812
7072
|
/* @__PURE__ */ jsxRuntime.jsx(ReadOnlyPlugin, { readonly: isReadOnly }),
|
|
6813
7073
|
/* @__PURE__ */ jsxRuntime.jsx(BrowserSpellCheckPlugin, { enabled: !resolvedSpellCheck }),
|
|
6814
7074
|
/* @__PURE__ */ jsxRuntime.jsx(
|
|
6815
7075
|
FocusEventsPlugin,
|
|
6816
7076
|
{
|
|
6817
7077
|
onFocus: props.onFocus,
|
|
6818
|
-
onBlur:
|
|
7078
|
+
onBlur: () => {
|
|
7079
|
+
setTouched(true);
|
|
7080
|
+
props.onBlur?.();
|
|
7081
|
+
},
|
|
6819
7082
|
setFocused,
|
|
6820
7083
|
containerRef
|
|
6821
7084
|
}
|
|
@@ -6862,20 +7125,16 @@ var ContentEditorComponent = React6.forwardRef(
|
|
|
6862
7125
|
}
|
|
6863
7126
|
),
|
|
6864
7127
|
!isReadOnly && props.showFloatingToolbar && /* @__PURE__ */ jsxRuntime.jsx(CharacterStylesPopupPlugin, {}),
|
|
6865
|
-
/* @__PURE__ */ jsxRuntime.jsx(
|
|
6866
|
-
|
|
6867
|
-
|
|
6868
|
-
value: props.value,
|
|
6869
|
-
onChange: props.onChange
|
|
6870
|
-
}
|
|
6871
|
-
),
|
|
6872
|
-
props.wordLimit !== void 0 && /* @__PURE__ */ jsxRuntime.jsx(WordCountPlugin, { onCountChange: handleWordCount }),
|
|
7128
|
+
/* @__PURE__ */ jsxRuntime.jsx(CustomOnChangePlugin, { value: props.value, onChange: props.onChange }),
|
|
7129
|
+
(props.wordLimit !== void 0 || props.required || props.minWords !== void 0) && /* @__PURE__ */ jsxRuntime.jsx(WordCountPlugin, { onCountChange: handleWordCount }),
|
|
7130
|
+
(props.maxChars !== void 0 || props.minChars !== void 0) && /* @__PURE__ */ jsxRuntime.jsx(CharCountPlugin, { onCountChange: handleCharCount }),
|
|
6873
7131
|
/* @__PURE__ */ jsxRuntime.jsx(
|
|
6874
7132
|
RefApiPlugin,
|
|
6875
7133
|
{
|
|
6876
7134
|
forwardedRef: ref,
|
|
6877
7135
|
contentEditableDomRef,
|
|
6878
|
-
focusedRef
|
|
7136
|
+
focusedRef,
|
|
7137
|
+
setRefErrors
|
|
6879
7138
|
}
|
|
6880
7139
|
)
|
|
6881
7140
|
]
|