@tarviks/lexical-rich-editor 1.2.1 → 1.3.0
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.css +126 -84
- package/dist/index.css.map +1 -1
- package/dist/index.d.mts +362 -62
- package/dist/index.d.ts +362 -62
- package/dist/index.js +2181 -1381
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +2189 -1390
- package/dist/index.mjs.map +1 -1
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -9,7 +9,6 @@ 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');
|
|
13
12
|
var code = require('@lexical/code');
|
|
14
13
|
var link = require('@lexical/link');
|
|
15
14
|
var list = require('@lexical/list');
|
|
@@ -25,8 +24,8 @@ var LexicalRichTextPlugin = require('@lexical/react/LexicalRichTextPlugin');
|
|
|
25
24
|
var LexicalTablePlugin = require('@lexical/react/LexicalTablePlugin');
|
|
26
25
|
var richText = require('@lexical/rich-text');
|
|
27
26
|
var table = require('@lexical/table');
|
|
28
|
-
var LexicalBlockWithAlignableContents = require('@lexical/react/LexicalBlockWithAlignableContents');
|
|
29
27
|
var LexicalDecoratorBlockNode = require('@lexical/react/LexicalDecoratorBlockNode');
|
|
28
|
+
var reactIcons = require('@fluentui/react-icons');
|
|
30
29
|
var selection = require('@lexical/selection');
|
|
31
30
|
var reactDom = require('react-dom');
|
|
32
31
|
var html = require('@lexical/html');
|
|
@@ -544,17 +543,6 @@ var init_ImageComponent = __esm({
|
|
|
544
543
|
onClick,
|
|
545
544
|
lexical.COMMAND_PRIORITY_LOW
|
|
546
545
|
),
|
|
547
|
-
editor.registerCommand(
|
|
548
|
-
lexical.DRAGSTART_COMMAND,
|
|
549
|
-
(event) => {
|
|
550
|
-
if (event.target === imageRef.current) {
|
|
551
|
-
event.preventDefault();
|
|
552
|
-
return true;
|
|
553
|
-
}
|
|
554
|
-
return false;
|
|
555
|
-
},
|
|
556
|
-
lexical.COMMAND_PRIORITY_LOW
|
|
557
|
-
),
|
|
558
546
|
editor.registerCommand(
|
|
559
547
|
lexical.KEY_DELETE_COMMAND,
|
|
560
548
|
$onDelete,
|
|
@@ -612,36 +600,44 @@ var init_ImageComponent = __esm({
|
|
|
612
600
|
const onResizeStart = () => {
|
|
613
601
|
setIsResizing(true);
|
|
614
602
|
};
|
|
615
|
-
const draggable =
|
|
603
|
+
const draggable = !isResizing;
|
|
616
604
|
const isFocused = (isSelected || isResizing) && isEditable;
|
|
617
|
-
return /* @__PURE__ */ jsxRuntime.jsx(React9.Suspense, { fallback: null, children: /* @__PURE__ */ jsxRuntime.jsxs(
|
|
618
|
-
|
|
619
|
-
|
|
620
|
-
|
|
621
|
-
|
|
622
|
-
|
|
623
|
-
|
|
624
|
-
|
|
625
|
-
|
|
626
|
-
|
|
627
|
-
|
|
628
|
-
|
|
629
|
-
|
|
630
|
-
|
|
631
|
-
|
|
632
|
-
|
|
633
|
-
|
|
634
|
-
|
|
635
|
-
|
|
636
|
-
|
|
637
|
-
|
|
638
|
-
|
|
639
|
-
|
|
640
|
-
|
|
641
|
-
|
|
642
|
-
|
|
643
|
-
|
|
644
|
-
|
|
605
|
+
return /* @__PURE__ */ jsxRuntime.jsx(React9.Suspense, { fallback: null, children: /* @__PURE__ */ jsxRuntime.jsxs(
|
|
606
|
+
"div",
|
|
607
|
+
{
|
|
608
|
+
draggable,
|
|
609
|
+
style: { position: "relative", display: "inline-block" },
|
|
610
|
+
children: [
|
|
611
|
+
isLoadError ? /* @__PURE__ */ jsxRuntime.jsx(BrokenImage, {}) : /* @__PURE__ */ jsxRuntime.jsx(
|
|
612
|
+
LazyImage,
|
|
613
|
+
{
|
|
614
|
+
className: isFocused ? `focused ${lexical.$isNodeSelection(selection) ? "draggable" : ""}` : null,
|
|
615
|
+
src,
|
|
616
|
+
altText,
|
|
617
|
+
imageRef,
|
|
618
|
+
width,
|
|
619
|
+
height,
|
|
620
|
+
maxWidth,
|
|
621
|
+
onError: () => setIsLoadError(true)
|
|
622
|
+
}
|
|
623
|
+
),
|
|
624
|
+
resizable && lexical.$isNodeSelection(selection) && isFocused && /* @__PURE__ */ jsxRuntime.jsx(
|
|
625
|
+
ImageResizer_default,
|
|
626
|
+
{
|
|
627
|
+
showCaption,
|
|
628
|
+
setShowCaption,
|
|
629
|
+
editor,
|
|
630
|
+
buttonRef,
|
|
631
|
+
imageRef,
|
|
632
|
+
maxWidth,
|
|
633
|
+
onResizeStart,
|
|
634
|
+
onResizeEnd,
|
|
635
|
+
captionsEnabled: !isLoadError && captionsEnabled
|
|
636
|
+
}
|
|
637
|
+
)
|
|
638
|
+
]
|
|
639
|
+
}
|
|
640
|
+
) });
|
|
645
641
|
};
|
|
646
642
|
ImageComponent_default = ImageComponent;
|
|
647
643
|
}
|
|
@@ -786,9 +782,6 @@ var init_ImageNode = __esm({
|
|
|
786
782
|
const writable = this.getWritable();
|
|
787
783
|
writable.__width = width;
|
|
788
784
|
writable.__height = height;
|
|
789
|
-
if (typeof width === "number" && width > writable.__maxWidth) {
|
|
790
|
-
writable.__maxWidth = width;
|
|
791
|
-
}
|
|
792
785
|
}
|
|
793
786
|
setShowCaption(showCaption) {
|
|
794
787
|
const writable = this.getWritable();
|
|
@@ -915,35 +908,13 @@ var init_InlineImageComponent = __esm({
|
|
|
915
908
|
};
|
|
916
909
|
InlineImageComponent = ({ src, altText, nodeKey, width, height, showCaption, caption, position }) => {
|
|
917
910
|
const [isSelected, setSelected, clearSelection] = useLexicalNodeSelection.useLexicalNodeSelection(nodeKey);
|
|
911
|
+
const [isResizing, setIsResizing] = React9.useState(false);
|
|
918
912
|
const [selection, setSelection] = React9.useState(null);
|
|
919
913
|
const activeEditorRef = React9.useRef(null);
|
|
920
914
|
const imageRef = React9.useRef(null);
|
|
921
915
|
const buttonRef = React9.useRef(null);
|
|
922
916
|
const [editor] = LexicalComposerContext.useLexicalComposerContext();
|
|
923
917
|
const isEditable = useLexicalEditable.useLexicalEditable();
|
|
924
|
-
const [isResizing, setIsResizing] = React9.useState(false);
|
|
925
|
-
const onResizeEnd = (nextWidth, nextHeight) => {
|
|
926
|
-
setTimeout(() => {
|
|
927
|
-
setIsResizing(false);
|
|
928
|
-
}, 200);
|
|
929
|
-
editor.update(() => {
|
|
930
|
-
const node = lexical.$getNodeByKey(nodeKey);
|
|
931
|
-
if ($isInlineImageNode(node)) {
|
|
932
|
-
node.setWidthAndHeight(nextWidth, nextHeight);
|
|
933
|
-
}
|
|
934
|
-
});
|
|
935
|
-
};
|
|
936
|
-
const onResizeStart = () => {
|
|
937
|
-
setIsResizing(true);
|
|
938
|
-
};
|
|
939
|
-
const setShowCaption = (show) => {
|
|
940
|
-
editor.update(() => {
|
|
941
|
-
const node = lexical.$getNodeByKey(nodeKey);
|
|
942
|
-
if ($isInlineImageNode(node)) {
|
|
943
|
-
node.setShowCaption(show);
|
|
944
|
-
}
|
|
945
|
-
});
|
|
946
|
-
};
|
|
947
918
|
const $onDelete = React9.useCallback(
|
|
948
919
|
(payload) => {
|
|
949
920
|
const deleteSelection = lexical.$getSelection();
|
|
@@ -999,6 +970,25 @@ var init_InlineImageComponent = __esm({
|
|
|
999
970
|
},
|
|
1000
971
|
[caption, editor, setSelected]
|
|
1001
972
|
);
|
|
973
|
+
const onClick = React9.useCallback(
|
|
974
|
+
(payload) => {
|
|
975
|
+
const event = payload;
|
|
976
|
+
if (isResizing) {
|
|
977
|
+
return true;
|
|
978
|
+
}
|
|
979
|
+
if (event.target === imageRef.current) {
|
|
980
|
+
if (event.shiftKey) {
|
|
981
|
+
setSelected(!isSelected);
|
|
982
|
+
} else {
|
|
983
|
+
clearSelection();
|
|
984
|
+
setSelected(true);
|
|
985
|
+
}
|
|
986
|
+
return true;
|
|
987
|
+
}
|
|
988
|
+
return false;
|
|
989
|
+
},
|
|
990
|
+
[isResizing, isSelected, setSelected, clearSelection]
|
|
991
|
+
);
|
|
1002
992
|
React9.useEffect(() => {
|
|
1003
993
|
let isMounted = true;
|
|
1004
994
|
const unregister = utils.mergeRegister(
|
|
@@ -1017,51 +1007,13 @@ var init_InlineImageComponent = __esm({
|
|
|
1017
1007
|
),
|
|
1018
1008
|
editor.registerCommand(
|
|
1019
1009
|
lexical.CLICK_COMMAND,
|
|
1020
|
-
|
|
1021
|
-
const event = payload;
|
|
1022
|
-
if (isResizing) {
|
|
1023
|
-
return true;
|
|
1024
|
-
}
|
|
1025
|
-
if (event.target === imageRef.current) {
|
|
1026
|
-
if (event.shiftKey) {
|
|
1027
|
-
setSelected(!isSelected);
|
|
1028
|
-
} else {
|
|
1029
|
-
clearSelection();
|
|
1030
|
-
setSelected(true);
|
|
1031
|
-
}
|
|
1032
|
-
return true;
|
|
1033
|
-
}
|
|
1034
|
-
return false;
|
|
1035
|
-
},
|
|
1036
|
-
lexical.COMMAND_PRIORITY_LOW
|
|
1037
|
-
),
|
|
1038
|
-
editor.registerCommand(
|
|
1039
|
-
lexical.DRAGSTART_COMMAND,
|
|
1040
|
-
(event) => {
|
|
1041
|
-
if (event.target === imageRef.current) {
|
|
1042
|
-
event.preventDefault();
|
|
1043
|
-
return true;
|
|
1044
|
-
}
|
|
1045
|
-
return false;
|
|
1046
|
-
},
|
|
1047
|
-
lexical.COMMAND_PRIORITY_LOW
|
|
1048
|
-
),
|
|
1049
|
-
editor.registerCommand(
|
|
1050
|
-
lexical.KEY_DELETE_COMMAND,
|
|
1051
|
-
$onDelete,
|
|
1052
|
-
lexical.COMMAND_PRIORITY_LOW
|
|
1053
|
-
),
|
|
1054
|
-
editor.registerCommand(
|
|
1055
|
-
lexical.KEY_BACKSPACE_COMMAND,
|
|
1056
|
-
$onDelete,
|
|
1010
|
+
onClick,
|
|
1057
1011
|
lexical.COMMAND_PRIORITY_LOW
|
|
1058
1012
|
),
|
|
1013
|
+
editor.registerCommand(lexical.KEY_DELETE_COMMAND, $onDelete, lexical.COMMAND_PRIORITY_LOW),
|
|
1014
|
+
editor.registerCommand(lexical.KEY_BACKSPACE_COMMAND, $onDelete, lexical.COMMAND_PRIORITY_LOW),
|
|
1059
1015
|
editor.registerCommand(lexical.KEY_ENTER_COMMAND, $onEnter, lexical.COMMAND_PRIORITY_LOW),
|
|
1060
|
-
editor.registerCommand(
|
|
1061
|
-
lexical.KEY_ESCAPE_COMMAND,
|
|
1062
|
-
$onEscape,
|
|
1063
|
-
lexical.COMMAND_PRIORITY_LOW
|
|
1064
|
-
)
|
|
1016
|
+
editor.registerCommand(lexical.KEY_ESCAPE_COMMAND, $onEscape, lexical.COMMAND_PRIORITY_LOW)
|
|
1065
1017
|
);
|
|
1066
1018
|
return () => {
|
|
1067
1019
|
isMounted = false;
|
|
@@ -1076,12 +1028,27 @@ var init_InlineImageComponent = __esm({
|
|
|
1076
1028
|
$onDelete,
|
|
1077
1029
|
$onEnter,
|
|
1078
1030
|
$onEscape,
|
|
1031
|
+
onClick,
|
|
1079
1032
|
setSelected
|
|
1080
1033
|
]);
|
|
1081
|
-
const
|
|
1034
|
+
const onResizeStart = () => {
|
|
1035
|
+
setIsResizing(true);
|
|
1036
|
+
};
|
|
1037
|
+
const onResizeEnd = (nextWidth, nextHeight) => {
|
|
1038
|
+
setTimeout(() => {
|
|
1039
|
+
setIsResizing(false);
|
|
1040
|
+
}, 200);
|
|
1041
|
+
editor.update(() => {
|
|
1042
|
+
const node = lexical.$getNodeByKey(nodeKey);
|
|
1043
|
+
if ($isInlineImageNode(node)) {
|
|
1044
|
+
node.setWidthAndHeight(nextWidth, nextHeight);
|
|
1045
|
+
}
|
|
1046
|
+
});
|
|
1047
|
+
};
|
|
1048
|
+
const draggable = !isResizing;
|
|
1082
1049
|
const isFocused = (isSelected || isResizing) && isEditable;
|
|
1083
|
-
return /* @__PURE__ */ jsxRuntime.jsx(React9.Suspense, { fallback: null, children: /* @__PURE__ */ jsxRuntime.jsxs(
|
|
1084
|
-
/* @__PURE__ */ jsxRuntime.jsx(
|
|
1050
|
+
return /* @__PURE__ */ jsxRuntime.jsx(React9.Suspense, { fallback: null, children: /* @__PURE__ */ jsxRuntime.jsxs("span", { draggable, style: { position: "relative", display: "inline-block" }, children: [
|
|
1051
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
1085
1052
|
LazyImage2,
|
|
1086
1053
|
{
|
|
1087
1054
|
className: isFocused ? `focused ${lexical.$isNodeSelection(selection) ? "draggable" : ""}` : null,
|
|
@@ -1092,18 +1059,19 @@ var init_InlineImageComponent = __esm({
|
|
|
1092
1059
|
height,
|
|
1093
1060
|
position
|
|
1094
1061
|
}
|
|
1095
|
-
)
|
|
1096
|
-
|
|
1062
|
+
),
|
|
1063
|
+
lexical.$isNodeSelection(selection) && isFocused && /* @__PURE__ */ jsxRuntime.jsx(
|
|
1097
1064
|
ImageResizer_default,
|
|
1098
1065
|
{
|
|
1099
|
-
showCaption,
|
|
1100
|
-
setShowCaption
|
|
1066
|
+
showCaption: false,
|
|
1067
|
+
setShowCaption: () => {
|
|
1068
|
+
},
|
|
1069
|
+
captionsEnabled: false,
|
|
1101
1070
|
editor,
|
|
1102
1071
|
buttonRef,
|
|
1103
1072
|
imageRef,
|
|
1104
1073
|
onResizeStart,
|
|
1105
|
-
onResizeEnd
|
|
1106
|
-
captionsEnabled: false
|
|
1074
|
+
onResizeEnd
|
|
1107
1075
|
}
|
|
1108
1076
|
)
|
|
1109
1077
|
] }) });
|
|
@@ -1294,6 +1262,19 @@ var ContentEditorLevel = /* @__PURE__ */ ((ContentEditorLevel2) => {
|
|
|
1294
1262
|
ContentEditorLevel2["Pro"] = "pro";
|
|
1295
1263
|
return ContentEditorLevel2;
|
|
1296
1264
|
})(ContentEditorLevel || {});
|
|
1265
|
+
var DEFAULT_VALIDATION_MESSAGES = {
|
|
1266
|
+
required: "This field is required.",
|
|
1267
|
+
minWords: (current, min) => `Minimum ${min} word${min === 1 ? "" : "s"} required (${current} entered).`,
|
|
1268
|
+
maxWords: (current, max) => `Word limit exceeded: ${current} / ${max} words.`,
|
|
1269
|
+
minChars: (current, min) => `Minimum ${min} character${min === 1 ? "" : "s"} required (${current} entered).`,
|
|
1270
|
+
maxChars: (current, max) => `Character limit exceeded: ${current} / ${max} characters.`,
|
|
1271
|
+
noImages: "Images are not allowed in this field.",
|
|
1272
|
+
maxImages: (current, max) => `Too many images: ${current} / ${max} allowed.`,
|
|
1273
|
+
noLinks: "Hyperlinks are not allowed in this field.",
|
|
1274
|
+
maxLinks: (current, max) => `Too many links: ${current} / ${max} allowed.`,
|
|
1275
|
+
noTables: "Tables are not allowed in this field.",
|
|
1276
|
+
imageTooLarge: (fileMB, maxMB) => `Image size (${fileMB.toFixed(1)} MB) exceeds the ${maxMB} MB limit.`
|
|
1277
|
+
};
|
|
1297
1278
|
|
|
1298
1279
|
// src/Types/PageSetup.ts
|
|
1299
1280
|
var DEFAULT_PAGE_SETUP = {
|
|
@@ -1334,6 +1315,106 @@ function resolvePageCanvasMetrics(value) {
|
|
|
1334
1315
|
paddingPx: Math.round(margin.valueIn * CSS_PX_PER_INCH)
|
|
1335
1316
|
};
|
|
1336
1317
|
}
|
|
1318
|
+
lexical.createCommand(
|
|
1319
|
+
"INSERT_ALPHA_LIST_COMMAND"
|
|
1320
|
+
);
|
|
1321
|
+
var AlphaListNode = class _AlphaListNode extends list.ListNode {
|
|
1322
|
+
static getType() {
|
|
1323
|
+
return "alpha-list";
|
|
1324
|
+
}
|
|
1325
|
+
static clone(node) {
|
|
1326
|
+
return new _AlphaListNode(node.getStart(), node.__key);
|
|
1327
|
+
}
|
|
1328
|
+
constructor(start = 1, key) {
|
|
1329
|
+
super("number", start, key);
|
|
1330
|
+
this.__listType = "lower-alpha";
|
|
1331
|
+
}
|
|
1332
|
+
createDOM(config, _editor) {
|
|
1333
|
+
const element = document.createElement("ol");
|
|
1334
|
+
element.setAttribute("type", "a");
|
|
1335
|
+
if (this.getStart() !== 1) element.setAttribute("start", String(this.getStart()));
|
|
1336
|
+
element.style.listStyleType = "lower-alpha";
|
|
1337
|
+
const olClass = config.theme?.list?.ol;
|
|
1338
|
+
if (olClass) element.className = olClass;
|
|
1339
|
+
return element;
|
|
1340
|
+
}
|
|
1341
|
+
updateDOM() {
|
|
1342
|
+
return false;
|
|
1343
|
+
}
|
|
1344
|
+
exportDOM(_editor) {
|
|
1345
|
+
const element = document.createElement("ol");
|
|
1346
|
+
element.setAttribute("type", "a");
|
|
1347
|
+
if (this.getStart() !== 1) element.setAttribute("start", String(this.getStart()));
|
|
1348
|
+
element.style.listStyleType = "lower-alpha";
|
|
1349
|
+
return { element };
|
|
1350
|
+
}
|
|
1351
|
+
static importDOM() {
|
|
1352
|
+
return {
|
|
1353
|
+
ol: (domNode) => {
|
|
1354
|
+
if (domNode instanceof HTMLOListElement && (domNode.getAttribute("type") === "a" || domNode.style.listStyleType === "lower-alpha")) {
|
|
1355
|
+
return { conversion: convertAlphaOL, priority: 1 };
|
|
1356
|
+
}
|
|
1357
|
+
return null;
|
|
1358
|
+
}
|
|
1359
|
+
};
|
|
1360
|
+
}
|
|
1361
|
+
exportJSON() {
|
|
1362
|
+
const base = super.exportJSON();
|
|
1363
|
+
return {
|
|
1364
|
+
...base,
|
|
1365
|
+
type: "alpha-list",
|
|
1366
|
+
listType: "lower-alpha",
|
|
1367
|
+
tag: "ol",
|
|
1368
|
+
version: 1,
|
|
1369
|
+
start: this.getStart()
|
|
1370
|
+
};
|
|
1371
|
+
}
|
|
1372
|
+
static importJSON(serialized) {
|
|
1373
|
+
return new _AlphaListNode(serialized.start ?? 1);
|
|
1374
|
+
}
|
|
1375
|
+
};
|
|
1376
|
+
function convertAlphaOL(domNode) {
|
|
1377
|
+
const start = domNode instanceof HTMLOListElement ? parseInt(domNode.getAttribute("start") || "1", 10) || 1 : 1;
|
|
1378
|
+
return { node: $createAlphaListNode(start) };
|
|
1379
|
+
}
|
|
1380
|
+
function $createAlphaListNode(start = 1) {
|
|
1381
|
+
return new AlphaListNode(start);
|
|
1382
|
+
}
|
|
1383
|
+
function $isAlphaListNode(node) {
|
|
1384
|
+
return node instanceof AlphaListNode;
|
|
1385
|
+
}
|
|
1386
|
+
function $toggleAlphaList() {
|
|
1387
|
+
const selection = lexical.$getSelection();
|
|
1388
|
+
if (!lexical.$isRangeSelection(selection)) return;
|
|
1389
|
+
const anchor = selection.anchor.getNode();
|
|
1390
|
+
const currentList = utils.$findMatchingParent(anchor, list.$isListNode);
|
|
1391
|
+
if ($isAlphaListNode(currentList)) {
|
|
1392
|
+
list.$removeList();
|
|
1393
|
+
return;
|
|
1394
|
+
}
|
|
1395
|
+
list.$insertList("number");
|
|
1396
|
+
const sel2 = lexical.$getSelection();
|
|
1397
|
+
if (!lexical.$isRangeSelection(sel2)) return;
|
|
1398
|
+
const newAnchor = sel2.anchor.getNode();
|
|
1399
|
+
const newList = utils.$findMatchingParent(newAnchor, (n) => list.$isListNode(n) && !$isAlphaListNode(n));
|
|
1400
|
+
if (!newList || !list.$isListNode(newList)) return;
|
|
1401
|
+
const start = newList.getStart();
|
|
1402
|
+
const formatType = typeof newList.getFormatType === "function" ? newList.getFormatType() : void 0;
|
|
1403
|
+
const alpha = $createAlphaListNode(start);
|
|
1404
|
+
for (const child of newList.getChildren()) {
|
|
1405
|
+
alpha.append(child);
|
|
1406
|
+
}
|
|
1407
|
+
newList.replace(alpha);
|
|
1408
|
+
if (formatType && typeof alpha.setFormat === "function") {
|
|
1409
|
+
alpha.setFormat(formatType);
|
|
1410
|
+
}
|
|
1411
|
+
const firstItem = alpha.getFirstChild();
|
|
1412
|
+
if (list.$isListItemNode(firstItem)) {
|
|
1413
|
+
firstItem.selectStart();
|
|
1414
|
+
} else {
|
|
1415
|
+
alpha.select();
|
|
1416
|
+
}
|
|
1417
|
+
}
|
|
1337
1418
|
var AutocompleteNode = class _AutocompleteNode extends lexical.TextNode {
|
|
1338
1419
|
static getType() {
|
|
1339
1420
|
return "autocomplete";
|
|
@@ -1344,6 +1425,13 @@ var AutocompleteNode = class _AutocompleteNode extends lexical.TextNode {
|
|
|
1344
1425
|
static importJSON(serializedNode) {
|
|
1345
1426
|
return new _AutocompleteNode(serializedNode.text, serializedNode.uuid);
|
|
1346
1427
|
}
|
|
1428
|
+
// AutocompleteNode is excluded from copy via excludeFromCopy(), so it is
|
|
1429
|
+
// never placed on the clipboard and never needs to be reconstructed from
|
|
1430
|
+
// HTML. Returning null here satisfies Lexical's exportDOM/importDOM
|
|
1431
|
+
// contract check and silences the console warning.
|
|
1432
|
+
static importDOM() {
|
|
1433
|
+
return null;
|
|
1434
|
+
}
|
|
1347
1435
|
exportJSON() {
|
|
1348
1436
|
return { ...super.exportJSON(), uuid: this.__uuid };
|
|
1349
1437
|
}
|
|
@@ -1658,13 +1746,20 @@ function VideoResizer({
|
|
|
1658
1746
|
const dy = ev.clientY - rs.startY;
|
|
1659
1747
|
let newW = rs.startW;
|
|
1660
1748
|
let newH = rs.startH;
|
|
1661
|
-
if (dir === "se") {
|
|
1749
|
+
if (dir === "se" || dir === "ne") {
|
|
1662
1750
|
newW = Math.max(MIN_WIDTH, rs.startW + dx);
|
|
1663
1751
|
newH = newW / rs.ratio;
|
|
1752
|
+
} else if (dir === "nw" || dir === "sw") {
|
|
1753
|
+
newW = Math.max(MIN_WIDTH, rs.startW - dx);
|
|
1754
|
+
newH = newW / rs.ratio;
|
|
1664
1755
|
} else if (dir === "e") {
|
|
1665
1756
|
newW = Math.max(MIN_WIDTH, rs.startW + dx);
|
|
1757
|
+
} else if (dir === "w") {
|
|
1758
|
+
newW = Math.max(MIN_WIDTH, rs.startW - dx);
|
|
1666
1759
|
} else if (dir === "s") {
|
|
1667
1760
|
newH = Math.max(MIN_HEIGHT, rs.startH + dy);
|
|
1761
|
+
} else if (dir === "n") {
|
|
1762
|
+
newH = Math.max(MIN_HEIGHT, rs.startH - dy);
|
|
1668
1763
|
}
|
|
1669
1764
|
container.style.width = `${newW}px`;
|
|
1670
1765
|
container.style.height = `${newH}px`;
|
|
@@ -1684,13 +1779,23 @@ function VideoResizer({
|
|
|
1684
1779
|
/* @__PURE__ */ jsxRuntime.jsx(
|
|
1685
1780
|
"div",
|
|
1686
1781
|
{
|
|
1687
|
-
style: {
|
|
1688
|
-
|
|
1689
|
-
|
|
1690
|
-
|
|
1691
|
-
|
|
1692
|
-
|
|
1693
|
-
|
|
1782
|
+
style: { ...handleBase, top: -5, left: "50%", transform: "translateX(-50%)", cursor: "n-resize" },
|
|
1783
|
+
onPointerDown: (e) => startResize(e, "n"),
|
|
1784
|
+
title: "Resize height"
|
|
1785
|
+
}
|
|
1786
|
+
),
|
|
1787
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
1788
|
+
"div",
|
|
1789
|
+
{
|
|
1790
|
+
style: { ...handleBase, top: -5, right: -5, cursor: "ne-resize" },
|
|
1791
|
+
onPointerDown: (e) => startResize(e, "ne"),
|
|
1792
|
+
title: "Resize (proportional)"
|
|
1793
|
+
}
|
|
1794
|
+
),
|
|
1795
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
1796
|
+
"div",
|
|
1797
|
+
{
|
|
1798
|
+
style: { ...handleBase, top: "50%", right: -5, transform: "translateY(-50%)", cursor: "ew-resize" },
|
|
1694
1799
|
onPointerDown: (e) => startResize(e, "e"),
|
|
1695
1800
|
title: "Resize width"
|
|
1696
1801
|
}
|
|
@@ -1698,13 +1803,15 @@ function VideoResizer({
|
|
|
1698
1803
|
/* @__PURE__ */ jsxRuntime.jsx(
|
|
1699
1804
|
"div",
|
|
1700
1805
|
{
|
|
1701
|
-
style: {
|
|
1702
|
-
|
|
1703
|
-
|
|
1704
|
-
|
|
1705
|
-
|
|
1706
|
-
|
|
1707
|
-
|
|
1806
|
+
style: { ...handleBase, bottom: -5, right: -5, cursor: "se-resize" },
|
|
1807
|
+
onPointerDown: (e) => startResize(e, "se"),
|
|
1808
|
+
title: "Resize (proportional)"
|
|
1809
|
+
}
|
|
1810
|
+
),
|
|
1811
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
1812
|
+
"div",
|
|
1813
|
+
{
|
|
1814
|
+
style: { ...handleBase, bottom: -5, left: "50%", transform: "translateX(-50%)", cursor: "s-resize" },
|
|
1708
1815
|
onPointerDown: (e) => startResize(e, "s"),
|
|
1709
1816
|
title: "Resize height"
|
|
1710
1817
|
}
|
|
@@ -1712,15 +1819,30 @@ function VideoResizer({
|
|
|
1712
1819
|
/* @__PURE__ */ jsxRuntime.jsx(
|
|
1713
1820
|
"div",
|
|
1714
1821
|
{
|
|
1715
|
-
style: { ...handleBase, bottom: -5,
|
|
1716
|
-
onPointerDown: (e) => startResize(e, "
|
|
1822
|
+
style: { ...handleBase, bottom: -5, left: -5, cursor: "sw-resize" },
|
|
1823
|
+
onPointerDown: (e) => startResize(e, "sw"),
|
|
1824
|
+
title: "Resize (proportional)"
|
|
1825
|
+
}
|
|
1826
|
+
),
|
|
1827
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
1828
|
+
"div",
|
|
1829
|
+
{
|
|
1830
|
+
style: { ...handleBase, top: "50%", left: -5, transform: "translateY(-50%)", cursor: "ew-resize" },
|
|
1831
|
+
onPointerDown: (e) => startResize(e, "w"),
|
|
1832
|
+
title: "Resize width"
|
|
1833
|
+
}
|
|
1834
|
+
),
|
|
1835
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
1836
|
+
"div",
|
|
1837
|
+
{
|
|
1838
|
+
style: { ...handleBase, top: -5, left: -5, cursor: "nw-resize" },
|
|
1839
|
+
onPointerDown: (e) => startResize(e, "nw"),
|
|
1717
1840
|
title: "Resize (proportional)"
|
|
1718
1841
|
}
|
|
1719
1842
|
)
|
|
1720
1843
|
] });
|
|
1721
1844
|
}
|
|
1722
1845
|
function YouTubeComponent({
|
|
1723
|
-
className,
|
|
1724
1846
|
format,
|
|
1725
1847
|
nodeKey,
|
|
1726
1848
|
videoID,
|
|
@@ -1728,9 +1850,48 @@ function YouTubeComponent({
|
|
|
1728
1850
|
height,
|
|
1729
1851
|
editor
|
|
1730
1852
|
}) {
|
|
1853
|
+
const wrapperRef = React9__namespace.useRef(null);
|
|
1731
1854
|
const containerRef = React9__namespace.useRef(null);
|
|
1855
|
+
const iframeRef = React9__namespace.useRef(null);
|
|
1856
|
+
const isResizingRef = React9__namespace.useRef(false);
|
|
1857
|
+
const [isNodeSelected, setNodeSelected, clearNodeSelection] = useLexicalNodeSelection.useLexicalNodeSelection(nodeKey);
|
|
1732
1858
|
const [isHovered, setIsHovered] = React9__namespace.useState(false);
|
|
1733
1859
|
const [isResizing, setIsResizing] = React9__namespace.useState(false);
|
|
1860
|
+
const [isPlaying, setIsPlaying] = React9__namespace.useState(false);
|
|
1861
|
+
React9__namespace.useEffect(() => {
|
|
1862
|
+
return utils.mergeRegister(
|
|
1863
|
+
editor.registerCommand(
|
|
1864
|
+
lexical.FORMAT_ELEMENT_COMMAND,
|
|
1865
|
+
(formatType) => {
|
|
1866
|
+
if (isNodeSelected) {
|
|
1867
|
+
editor.update(() => {
|
|
1868
|
+
const node = lexical.$getNodeByKey(nodeKey);
|
|
1869
|
+
if ($isYouTubeNode(node)) node.setFormat(formatType);
|
|
1870
|
+
});
|
|
1871
|
+
return true;
|
|
1872
|
+
}
|
|
1873
|
+
return false;
|
|
1874
|
+
},
|
|
1875
|
+
lexical.COMMAND_PRIORITY_LOW
|
|
1876
|
+
),
|
|
1877
|
+
// Select this node on click. When the thumbnail is shown the <img> is
|
|
1878
|
+
// in the parent DOM so CLICK_COMMAND fires naturally. When the iframe is
|
|
1879
|
+
// live, clicks land in the iframe's browsing context — the node stays
|
|
1880
|
+
// selected via wrapperRef boundary detection on the wrapper div.
|
|
1881
|
+
editor.registerCommand(
|
|
1882
|
+
lexical.CLICK_COMMAND,
|
|
1883
|
+
(event) => {
|
|
1884
|
+
if (wrapperRef.current?.contains(event.target)) {
|
|
1885
|
+
if (!event.shiftKey) clearNodeSelection();
|
|
1886
|
+
setNodeSelected(true);
|
|
1887
|
+
return true;
|
|
1888
|
+
}
|
|
1889
|
+
return false;
|
|
1890
|
+
},
|
|
1891
|
+
lexical.COMMAND_PRIORITY_LOW
|
|
1892
|
+
)
|
|
1893
|
+
);
|
|
1894
|
+
}, [editor, isNodeSelected, nodeKey, clearNodeSelection, setNodeSelected]);
|
|
1734
1895
|
const handleDelete = (e) => {
|
|
1735
1896
|
e.preventDefault();
|
|
1736
1897
|
e.stopPropagation();
|
|
@@ -1739,72 +1900,173 @@ function YouTubeComponent({
|
|
|
1739
1900
|
node?.remove();
|
|
1740
1901
|
});
|
|
1741
1902
|
};
|
|
1903
|
+
const handleResizeStart = () => {
|
|
1904
|
+
isResizingRef.current = true;
|
|
1905
|
+
setIsResizing(true);
|
|
1906
|
+
if (iframeRef.current) iframeRef.current.style.pointerEvents = "none";
|
|
1907
|
+
};
|
|
1742
1908
|
const handleResizeEnd = (w, h) => {
|
|
1909
|
+
isResizingRef.current = false;
|
|
1743
1910
|
setIsResizing(false);
|
|
1911
|
+
if (iframeRef.current) iframeRef.current.style.pointerEvents = "";
|
|
1912
|
+
setIsHovered(true);
|
|
1744
1913
|
editor.update(() => {
|
|
1745
1914
|
const node = lexical.$getNodeByKey(nodeKey);
|
|
1746
|
-
if ($isYouTubeNode(node))
|
|
1747
|
-
node.setSize(Math.round(w), Math.round(h));
|
|
1748
|
-
}
|
|
1915
|
+
if ($isYouTubeNode(node)) node.setSize(Math.round(w), Math.round(h));
|
|
1749
1916
|
});
|
|
1750
1917
|
};
|
|
1751
|
-
|
|
1918
|
+
const actionBtnStyle = (side) => ({
|
|
1919
|
+
position: "absolute",
|
|
1920
|
+
top: 8,
|
|
1921
|
+
[side]: 8,
|
|
1922
|
+
width: 28,
|
|
1923
|
+
height: 28,
|
|
1924
|
+
borderRadius: "50%",
|
|
1925
|
+
background: "rgba(0,0,0,0.65)",
|
|
1926
|
+
color: "#fff",
|
|
1927
|
+
border: "none",
|
|
1928
|
+
cursor: "pointer",
|
|
1929
|
+
fontSize: side === "right" ? 18 : 14,
|
|
1930
|
+
lineHeight: 1,
|
|
1931
|
+
padding: 0,
|
|
1932
|
+
zIndex: 10,
|
|
1933
|
+
display: "flex",
|
|
1934
|
+
alignItems: "center",
|
|
1935
|
+
justifyContent: "center"
|
|
1936
|
+
});
|
|
1937
|
+
return /* @__PURE__ */ jsxRuntime.jsx("div", { ref: wrapperRef, style: { display: "block", textAlign: format || void 0 }, children: /* @__PURE__ */ jsxRuntime.jsxs(
|
|
1752
1938
|
"div",
|
|
1753
1939
|
{
|
|
1754
1940
|
ref: containerRef,
|
|
1755
|
-
style: {
|
|
1941
|
+
style: {
|
|
1942
|
+
position: "relative",
|
|
1943
|
+
display: "inline-block",
|
|
1944
|
+
width,
|
|
1945
|
+
height,
|
|
1946
|
+
lineHeight: 0,
|
|
1947
|
+
outline: isNodeSelected ? "2px solid #0078d4" : void 0,
|
|
1948
|
+
outlineOffset: 2
|
|
1949
|
+
},
|
|
1756
1950
|
onMouseEnter: () => setIsHovered(true),
|
|
1757
1951
|
onMouseLeave: () => {
|
|
1758
|
-
if (!
|
|
1952
|
+
if (!isResizingRef.current) setIsHovered(false);
|
|
1759
1953
|
},
|
|
1760
1954
|
children: [
|
|
1761
|
-
|
|
1762
|
-
|
|
1763
|
-
|
|
1764
|
-
|
|
1765
|
-
|
|
1766
|
-
|
|
1767
|
-
allow: "accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture",
|
|
1768
|
-
allowFullScreen: true,
|
|
1769
|
-
title: "YouTube video",
|
|
1770
|
-
style: { display: "block", border: "none", pointerEvents: isResizing ? "none" : "auto" }
|
|
1771
|
-
}
|
|
1772
|
-
),
|
|
1773
|
-
isHovered && /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
|
|
1774
|
-
/* @__PURE__ */ jsxRuntime.jsx(
|
|
1775
|
-
"button",
|
|
1776
|
-
{
|
|
1777
|
-
type: "button",
|
|
1778
|
-
onClick: handleDelete,
|
|
1779
|
-
title: "Remove video",
|
|
1780
|
-
style: {
|
|
1781
|
-
position: "absolute",
|
|
1782
|
-
top: 8,
|
|
1783
|
-
right: 8,
|
|
1784
|
-
width: 28,
|
|
1785
|
-
height: 28,
|
|
1786
|
-
borderRadius: "50%",
|
|
1787
|
-
background: "rgba(0,0,0,0.65)",
|
|
1788
|
-
color: "#fff",
|
|
1789
|
-
border: "none",
|
|
1790
|
-
cursor: "pointer",
|
|
1791
|
-
fontSize: 18,
|
|
1792
|
-
lineHeight: 1,
|
|
1793
|
-
padding: 0,
|
|
1794
|
-
zIndex: 10,
|
|
1795
|
-
display: "flex",
|
|
1796
|
-
alignItems: "center",
|
|
1797
|
-
justifyContent: "center"
|
|
1798
|
-
},
|
|
1799
|
-
children: "\xD7"
|
|
1800
|
-
}
|
|
1801
|
-
),
|
|
1955
|
+
isPlaying ? (
|
|
1956
|
+
/* ── Playing state ─────────────────────────────────────────────────
|
|
1957
|
+
* Show the real YouTube iframe in-place at the same dimensions.
|
|
1958
|
+
* autoplay=1 starts playback immediately.
|
|
1959
|
+
* pointer-events are set to 'none' during resize (handleResizeStart)
|
|
1960
|
+
* so drag events are not lost to the iframe's browsing context. */
|
|
1802
1961
|
/* @__PURE__ */ jsxRuntime.jsx(
|
|
1803
|
-
|
|
1962
|
+
"iframe",
|
|
1804
1963
|
{
|
|
1805
|
-
|
|
1806
|
-
|
|
1807
|
-
|
|
1964
|
+
ref: iframeRef,
|
|
1965
|
+
width: "100%",
|
|
1966
|
+
height: "100%",
|
|
1967
|
+
src: `https://www.youtube.com/embed/${videoID}?autoplay=1`,
|
|
1968
|
+
sandbox: "allow-same-origin allow-scripts allow-popups allow-presentation",
|
|
1969
|
+
allow: "accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture",
|
|
1970
|
+
allowFullScreen: true,
|
|
1971
|
+
title: "YouTube video",
|
|
1972
|
+
style: { display: "block", border: "none" }
|
|
1973
|
+
}
|
|
1974
|
+
)
|
|
1975
|
+
) : (
|
|
1976
|
+
/* ── Thumbnail state ───────────────────────────────────────────────
|
|
1977
|
+
* Static <img> keeps all clicks in the parent DOM so Lexical's
|
|
1978
|
+
* CLICK_COMMAND fires correctly and the node can be selected.
|
|
1979
|
+
* Clicking the red ▶ badge switches to playing state. */
|
|
1980
|
+
/* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
|
|
1981
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
1982
|
+
"img",
|
|
1983
|
+
{
|
|
1984
|
+
src: `https://img.youtube.com/vi/${videoID}/hqdefault.jpg`,
|
|
1985
|
+
alt: "YouTube video",
|
|
1986
|
+
draggable: false,
|
|
1987
|
+
style: {
|
|
1988
|
+
width: "100%",
|
|
1989
|
+
height: "100%",
|
|
1990
|
+
objectFit: "cover",
|
|
1991
|
+
display: "block",
|
|
1992
|
+
userSelect: "none",
|
|
1993
|
+
cursor: "pointer"
|
|
1994
|
+
}
|
|
1995
|
+
}
|
|
1996
|
+
),
|
|
1997
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
1998
|
+
"div",
|
|
1999
|
+
{
|
|
2000
|
+
role: "button",
|
|
2001
|
+
"aria-label": "Play video",
|
|
2002
|
+
onClick: () => setIsPlaying(true),
|
|
2003
|
+
style: {
|
|
2004
|
+
position: "absolute",
|
|
2005
|
+
top: "50%",
|
|
2006
|
+
left: "50%",
|
|
2007
|
+
transform: "translate(-50%, -50%)",
|
|
2008
|
+
width: 56,
|
|
2009
|
+
height: 56,
|
|
2010
|
+
background: "rgba(255, 0, 0, 0.85)",
|
|
2011
|
+
borderRadius: "50%",
|
|
2012
|
+
display: "flex",
|
|
2013
|
+
alignItems: "center",
|
|
2014
|
+
justifyContent: "center",
|
|
2015
|
+
cursor: "pointer"
|
|
2016
|
+
},
|
|
2017
|
+
children: /* @__PURE__ */ jsxRuntime.jsx("span", { style: { color: "#fff", fontSize: 20, lineHeight: 1, marginLeft: 5 }, children: "\u25B6" })
|
|
2018
|
+
}
|
|
2019
|
+
)
|
|
2020
|
+
] })
|
|
2021
|
+
),
|
|
2022
|
+
(isHovered || isResizing) && /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
|
|
2023
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
2024
|
+
"button",
|
|
2025
|
+
{
|
|
2026
|
+
type: "button",
|
|
2027
|
+
onClick: handleDelete,
|
|
2028
|
+
title: "Remove video",
|
|
2029
|
+
style: actionBtnStyle("right"),
|
|
2030
|
+
children: "\xD7"
|
|
2031
|
+
}
|
|
2032
|
+
),
|
|
2033
|
+
isPlaying && /* @__PURE__ */ jsxRuntime.jsx(
|
|
2034
|
+
"button",
|
|
2035
|
+
{
|
|
2036
|
+
type: "button",
|
|
2037
|
+
onClick: (e) => {
|
|
2038
|
+
e.stopPropagation();
|
|
2039
|
+
setIsPlaying(false);
|
|
2040
|
+
},
|
|
2041
|
+
title: "Stop video",
|
|
2042
|
+
style: actionBtnStyle("left"),
|
|
2043
|
+
children: "\u23F9"
|
|
2044
|
+
}
|
|
2045
|
+
),
|
|
2046
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
2047
|
+
"button",
|
|
2048
|
+
{
|
|
2049
|
+
type: "button",
|
|
2050
|
+
onClick: (e) => {
|
|
2051
|
+
e.stopPropagation();
|
|
2052
|
+
window.open(`https://www.youtube.com/watch?v=${videoID}`, "_blank", "noopener,noreferrer");
|
|
2053
|
+
},
|
|
2054
|
+
title: "Open in browser",
|
|
2055
|
+
style: {
|
|
2056
|
+
...actionBtnStyle("left"),
|
|
2057
|
+
top: isPlaying ? 44 : 8,
|
|
2058
|
+
// stack below stop button when playing
|
|
2059
|
+
fontSize: 13
|
|
2060
|
+
},
|
|
2061
|
+
children: "\u2197"
|
|
2062
|
+
}
|
|
2063
|
+
),
|
|
2064
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
2065
|
+
VideoResizer,
|
|
2066
|
+
{
|
|
2067
|
+
containerRef,
|
|
2068
|
+
onResizeStart: handleResizeStart,
|
|
2069
|
+
onResizeEnd: handleResizeEnd
|
|
1808
2070
|
}
|
|
1809
2071
|
)
|
|
1810
2072
|
] })
|
|
@@ -1864,6 +2126,7 @@ var YouTubeNode = class _YouTubeNode extends LexicalDecoratorBlockNode.Decorator
|
|
|
1864
2126
|
iframe.setAttribute("width", String(this.__width));
|
|
1865
2127
|
iframe.setAttribute("height", String(this.__height));
|
|
1866
2128
|
iframe.style.border = "none";
|
|
2129
|
+
iframe.setAttribute("sandbox", "allow-same-origin allow-scripts allow-popups allow-presentation");
|
|
1867
2130
|
iframe.setAttribute(
|
|
1868
2131
|
"allow",
|
|
1869
2132
|
"accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture"
|
|
@@ -1891,16 +2154,10 @@ var YouTubeNode = class _YouTubeNode extends LexicalDecoratorBlockNode.Decorator
|
|
|
1891
2154
|
writable.__width = width;
|
|
1892
2155
|
writable.__height = height;
|
|
1893
2156
|
}
|
|
1894
|
-
decorate(_editor,
|
|
1895
|
-
const embedBlockTheme = config.theme.embedBlock || {};
|
|
1896
|
-
const className = {
|
|
1897
|
-
base: embedBlockTheme.base || "",
|
|
1898
|
-
focus: embedBlockTheme.focus || ""
|
|
1899
|
-
};
|
|
2157
|
+
decorate(_editor, _config) {
|
|
1900
2158
|
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
1901
2159
|
YouTubeComponent,
|
|
1902
2160
|
{
|
|
1903
|
-
className,
|
|
1904
2161
|
format: this.__format,
|
|
1905
2162
|
nodeKey: this.getKey(),
|
|
1906
2163
|
videoID: this.__id,
|
|
@@ -2266,12 +2523,12 @@ function useFloatingPortalContainer(editor) {
|
|
|
2266
2523
|
}, [editor]);
|
|
2267
2524
|
return container;
|
|
2268
2525
|
}
|
|
2269
|
-
function setPopupPositionFixed(popupEl, rect) {
|
|
2526
|
+
function setPopupPositionFixed(popupEl, rect, topBoundary) {
|
|
2270
2527
|
const GAP = 8;
|
|
2271
2528
|
const MARGIN = 8;
|
|
2272
2529
|
let top = rect.top - popupEl.offsetHeight - GAP;
|
|
2273
|
-
let left = rect.left
|
|
2274
|
-
if (top <
|
|
2530
|
+
let left = rect.left;
|
|
2531
|
+
if (top < topBoundary) top = rect.bottom + GAP;
|
|
2275
2532
|
left = clamp2(left, MARGIN, window.innerWidth - popupEl.offsetWidth - MARGIN);
|
|
2276
2533
|
popupEl.style.top = `${top}px`;
|
|
2277
2534
|
popupEl.style.left = `${left}px`;
|
|
@@ -2313,10 +2570,22 @@ function FloatingCharacterStylesEditor({
|
|
|
2313
2570
|
popupEl.classList.remove("is-open");
|
|
2314
2571
|
return;
|
|
2315
2572
|
}
|
|
2316
|
-
|
|
2317
|
-
|
|
2573
|
+
let rect;
|
|
2574
|
+
try {
|
|
2575
|
+
const focusRange = document.createRange();
|
|
2576
|
+
focusRange.setStart(sel.focusNode, sel.focusOffset);
|
|
2577
|
+
focusRange.setEnd(sel.focusNode, sel.focusOffset);
|
|
2578
|
+
rect = focusRange.getBoundingClientRect();
|
|
2579
|
+
if (rect.width === 0 && rect.height === 0 && rect.top === 0 && rect.left === 0) {
|
|
2580
|
+
throw new Error("empty focus rect");
|
|
2581
|
+
}
|
|
2582
|
+
} catch {
|
|
2583
|
+
rect = sel.getRangeAt(0).getBoundingClientRect();
|
|
2584
|
+
}
|
|
2585
|
+
const toolbarEl = root?.closest(".lexical-rich-editor-root")?.querySelector(".editor-toolbar-root");
|
|
2586
|
+
const topBoundary = toolbarEl ? toolbarEl.getBoundingClientRect().bottom + 8 : 8;
|
|
2318
2587
|
if (!mouseDownRef.current) {
|
|
2319
|
-
setPopupPositionFixed(popupEl, rect);
|
|
2588
|
+
setPopupPositionFixed(popupEl, rect, topBoundary);
|
|
2320
2589
|
}
|
|
2321
2590
|
popupEl.classList.add("is-open");
|
|
2322
2591
|
}, [editor]);
|
|
@@ -2524,6 +2793,11 @@ function useCharacterStylesPopup(editor, opts) {
|
|
|
2524
2793
|
setIsText(false);
|
|
2525
2794
|
return;
|
|
2526
2795
|
}
|
|
2796
|
+
const activeElement = document.activeElement;
|
|
2797
|
+
if (activeElement && activeElement !== document.body && rootElement && !rootElement.contains(activeElement)) {
|
|
2798
|
+
setIsText(false);
|
|
2799
|
+
return;
|
|
2800
|
+
}
|
|
2527
2801
|
if (!lexical.$isRangeSelection(selection)) return;
|
|
2528
2802
|
const node = getSelectedNode(selection);
|
|
2529
2803
|
setIsBold(selection.hasFormat("bold"));
|
|
@@ -2544,7 +2818,11 @@ function useCharacterStylesPopup(editor, opts) {
|
|
|
2544
2818
|
}, [editor]);
|
|
2545
2819
|
React9.useEffect(() => {
|
|
2546
2820
|
document.addEventListener("selectionchange", updatePopupState);
|
|
2547
|
-
|
|
2821
|
+
document.addEventListener("focusin", updatePopupState);
|
|
2822
|
+
return () => {
|
|
2823
|
+
document.removeEventListener("selectionchange", updatePopupState);
|
|
2824
|
+
document.removeEventListener("focusin", updatePopupState);
|
|
2825
|
+
};
|
|
2548
2826
|
}, [updatePopupState]);
|
|
2549
2827
|
React9.useEffect(() => editor.registerUpdateListener(updatePopupState), [editor, updatePopupState]);
|
|
2550
2828
|
if (!portalContainer || !isText || isLink) return null;
|
|
@@ -2802,34 +3080,57 @@ function normalizeToBlockHtml(html) {
|
|
|
2802
3080
|
if (pendingP) body.appendChild(pendingP);
|
|
2803
3081
|
return body.innerHTML;
|
|
2804
3082
|
}
|
|
3083
|
+
function splitHeadingsAtBrSequences(html) {
|
|
3084
|
+
const doc = new DOMParser().parseFromString(html, "text/html");
|
|
3085
|
+
const headings = Array.from(doc.querySelectorAll("h1, h2, h3, h4, h5, h6"));
|
|
3086
|
+
headings.forEach((el) => {
|
|
3087
|
+
const inner = el.innerHTML;
|
|
3088
|
+
const SEP = /<br\s*\/?>\s*(?:<br\s*\/?>)+/gi;
|
|
3089
|
+
if (!SEP.test(inner)) return;
|
|
3090
|
+
SEP.lastIndex = 0;
|
|
3091
|
+
const parts = inner.split(SEP).map((p) => p.trim()).filter(Boolean);
|
|
3092
|
+
if (parts.length <= 1) return;
|
|
3093
|
+
const parent = el.parentNode;
|
|
3094
|
+
if (!parent) return;
|
|
3095
|
+
const tagName = el.tagName.toLowerCase();
|
|
3096
|
+
const attrs = Array.from(el.attributes);
|
|
3097
|
+
const fragment = doc.createDocumentFragment();
|
|
3098
|
+
parts.forEach((part) => {
|
|
3099
|
+
const newEl = doc.createElement(tagName);
|
|
3100
|
+
attrs.forEach((a) => newEl.setAttribute(a.name, a.value));
|
|
3101
|
+
newEl.innerHTML = part;
|
|
3102
|
+
fragment.appendChild(newEl);
|
|
3103
|
+
});
|
|
3104
|
+
parent.replaceChild(fragment, el);
|
|
3105
|
+
});
|
|
3106
|
+
return doc.body.innerHTML;
|
|
3107
|
+
}
|
|
2805
3108
|
var CustomOnChangePlugin = ({ value, onChange }) => {
|
|
2806
3109
|
const [editor] = LexicalComposerContext.useLexicalComposerContext();
|
|
2807
3110
|
const initializedRef = React9.useRef(false);
|
|
2808
|
-
const onChangeRef = React9.useRef(onChange);
|
|
2809
|
-
onChangeRef.current = onChange;
|
|
2810
3111
|
React9.useEffect(() => {
|
|
2811
3112
|
if (!value || initializedRef.current) return;
|
|
2812
3113
|
initializedRef.current = true;
|
|
2813
3114
|
editor.update(() => {
|
|
2814
3115
|
const root = lexical.$getRoot();
|
|
2815
3116
|
root.clear();
|
|
3117
|
+
const safe = sanitizeHtml(value);
|
|
3118
|
+
const cleaned = normalizeToBlockHtml(splitHeadingsAtBrSequences(safe));
|
|
2816
3119
|
const parser = new DOMParser();
|
|
2817
|
-
const dom = parser.parseFromString(
|
|
3120
|
+
const dom = parser.parseFromString(cleaned, "text/html");
|
|
2818
3121
|
const nodes = html.$generateNodesFromDOM(editor, dom);
|
|
2819
3122
|
root.append(...nodes);
|
|
2820
|
-
lexical.$setSelection(null);
|
|
2821
3123
|
});
|
|
2822
3124
|
}, [editor, value]);
|
|
2823
|
-
const handleChange = React9.useCallback((editorState) => {
|
|
2824
|
-
editorState.read(() => {
|
|
2825
|
-
onChangeRef.current(postProcessOutput(html.$generateHtmlFromNodes(editor)));
|
|
2826
|
-
});
|
|
2827
|
-
}, [editor]);
|
|
2828
3125
|
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
2829
3126
|
LexicalOnChangePlugin.OnChangePlugin,
|
|
2830
3127
|
{
|
|
2831
|
-
onChange:
|
|
2832
|
-
|
|
3128
|
+
onChange: (editorState) => {
|
|
3129
|
+
editorState.read(() => {
|
|
3130
|
+
const raw = html.$generateHtmlFromNodes(editor);
|
|
3131
|
+
onChange(postProcessOutput(splitHeadingsAtBrSequences(raw)));
|
|
3132
|
+
});
|
|
3133
|
+
}
|
|
2833
3134
|
}
|
|
2834
3135
|
);
|
|
2835
3136
|
};
|
|
@@ -2939,7 +3240,7 @@ var FloatingLinkEditor = ({ editor, isLink, setIsLink, anchorElem, isLinkEditMod
|
|
|
2939
3240
|
setLinkUrl("");
|
|
2940
3241
|
}
|
|
2941
3242
|
return true;
|
|
2942
|
-
}, [anchorElem, editor,
|
|
3243
|
+
}, [anchorElem, editor, setIsLinkEditMode, isLinkEditMode, isLink, linkUrl]);
|
|
2943
3244
|
React9.useEffect(() => {
|
|
2944
3245
|
const scrollerElem = anchorElem.parentElement;
|
|
2945
3246
|
const update = () => {
|
|
@@ -3037,7 +3338,6 @@ var FloatingLinkEditor = ({ editor, isLink, setIsLink, anchorElem, isLinkEditMod
|
|
|
3037
3338
|
{
|
|
3038
3339
|
ref: inputRef,
|
|
3039
3340
|
className: "link-input",
|
|
3040
|
-
placeholder: "https://",
|
|
3041
3341
|
value: editedLinkUrl,
|
|
3042
3342
|
onChange: (event) => {
|
|
3043
3343
|
setEditedLinkUrl(event.target.value);
|
|
@@ -3047,31 +3347,33 @@ var FloatingLinkEditor = ({ editor, isLink, setIsLink, anchorElem, isLinkEditMod
|
|
|
3047
3347
|
}
|
|
3048
3348
|
}
|
|
3049
3349
|
),
|
|
3050
|
-
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "link-actions", children: [
|
|
3350
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "link-input-actions", children: [
|
|
3051
3351
|
/* @__PURE__ */ jsxRuntime.jsx(
|
|
3052
|
-
"
|
|
3352
|
+
"div",
|
|
3053
3353
|
{
|
|
3054
|
-
|
|
3055
|
-
|
|
3354
|
+
className: "link-cancel",
|
|
3355
|
+
role: "button",
|
|
3356
|
+
tabIndex: 0,
|
|
3056
3357
|
title: "Cancel",
|
|
3057
3358
|
"aria-label": "Cancel",
|
|
3058
3359
|
onMouseDown: preventDefault,
|
|
3059
3360
|
onClick: () => {
|
|
3060
3361
|
setIsLinkEditMode(false);
|
|
3061
3362
|
},
|
|
3062
|
-
children: /* @__PURE__ */ jsxRuntime.jsx(reactIcons.
|
|
3363
|
+
children: /* @__PURE__ */ jsxRuntime.jsx(reactIcons.DismissRegular, { fontSize: 16 })
|
|
3063
3364
|
}
|
|
3064
3365
|
),
|
|
3065
3366
|
/* @__PURE__ */ jsxRuntime.jsx(
|
|
3066
|
-
"
|
|
3367
|
+
"div",
|
|
3067
3368
|
{
|
|
3068
|
-
|
|
3069
|
-
|
|
3369
|
+
className: "link-confirm",
|
|
3370
|
+
role: "button",
|
|
3371
|
+
tabIndex: 0,
|
|
3070
3372
|
title: "Confirm",
|
|
3071
3373
|
"aria-label": "Confirm",
|
|
3072
3374
|
onMouseDown: preventDefault,
|
|
3073
3375
|
onClick: handleLinkSubmission,
|
|
3074
|
-
children: /* @__PURE__ */ jsxRuntime.jsx(reactIcons.
|
|
3376
|
+
children: /* @__PURE__ */ jsxRuntime.jsx(reactIcons.CheckmarkRegular, { fontSize: 16 })
|
|
3075
3377
|
}
|
|
3076
3378
|
)
|
|
3077
3379
|
] })
|
|
@@ -3085,38 +3387,38 @@ var FloatingLinkEditor = ({ editor, isLink, setIsLink, anchorElem, isLinkEditMod
|
|
|
3085
3387
|
children: linkUrl
|
|
3086
3388
|
}
|
|
3087
3389
|
),
|
|
3088
|
-
/* @__PURE__ */ jsxRuntime.
|
|
3089
|
-
|
|
3090
|
-
|
|
3091
|
-
|
|
3092
|
-
|
|
3093
|
-
|
|
3094
|
-
|
|
3095
|
-
|
|
3096
|
-
|
|
3097
|
-
|
|
3098
|
-
|
|
3099
|
-
|
|
3100
|
-
|
|
3101
|
-
|
|
3102
|
-
|
|
3103
|
-
|
|
3104
|
-
|
|
3105
|
-
|
|
3106
|
-
|
|
3107
|
-
|
|
3108
|
-
|
|
3109
|
-
|
|
3110
|
-
|
|
3111
|
-
|
|
3112
|
-
|
|
3113
|
-
|
|
3114
|
-
|
|
3115
|
-
|
|
3116
|
-
|
|
3117
|
-
}
|
|
3118
|
-
|
|
3119
|
-
|
|
3390
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
3391
|
+
"div",
|
|
3392
|
+
{
|
|
3393
|
+
className: "link-edit",
|
|
3394
|
+
role: "button",
|
|
3395
|
+
tabIndex: 0,
|
|
3396
|
+
title: "Edit link",
|
|
3397
|
+
"aria-label": "Edit link",
|
|
3398
|
+
onMouseDown: preventDefault,
|
|
3399
|
+
onClick: (event) => {
|
|
3400
|
+
event.preventDefault();
|
|
3401
|
+
setEditedLinkUrl(linkUrl);
|
|
3402
|
+
setIsLinkEditMode(true);
|
|
3403
|
+
},
|
|
3404
|
+
children: /* @__PURE__ */ jsxRuntime.jsx(reactIcons.EditRegular, { fontSize: 16 })
|
|
3405
|
+
}
|
|
3406
|
+
),
|
|
3407
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
3408
|
+
"div",
|
|
3409
|
+
{
|
|
3410
|
+
className: "link-trash",
|
|
3411
|
+
role: "button",
|
|
3412
|
+
tabIndex: 0,
|
|
3413
|
+
title: "Remove link",
|
|
3414
|
+
"aria-label": "Remove link",
|
|
3415
|
+
onMouseDown: preventDefault,
|
|
3416
|
+
onClick: () => {
|
|
3417
|
+
editor.dispatchCommand(link.TOGGLE_LINK_COMMAND, null);
|
|
3418
|
+
},
|
|
3419
|
+
children: /* @__PURE__ */ jsxRuntime.jsx(reactIcons.DeleteRegular, { fontSize: 16 })
|
|
3420
|
+
}
|
|
3421
|
+
)
|
|
3120
3422
|
] }) });
|
|
3121
3423
|
};
|
|
3122
3424
|
var useFloatingLinkEditorToolbar = (editor, anchorElem, isLinkEditMode, setIsLinkEditMode) => {
|
|
@@ -3197,8 +3499,6 @@ var FloatingLinkEditorPlugin = ({ anchorElem, isLinkEditMode, setIsLinkEditMode
|
|
|
3197
3499
|
setIsLinkEditMode
|
|
3198
3500
|
);
|
|
3199
3501
|
};
|
|
3200
|
-
|
|
3201
|
-
// src/Plugins/ImagePlugin.tsx
|
|
3202
3502
|
init_ImageNode();
|
|
3203
3503
|
var INSERT_IMAGE_COMMAND = lexical.createCommand("INSERT_IMAGE_COMMAND");
|
|
3204
3504
|
var readClipboardImageAsDataURL = async (event) => {
|
|
@@ -3217,28 +3517,77 @@ var readClipboardImageAsDataURL = async (event) => {
|
|
|
3217
3517
|
}
|
|
3218
3518
|
return null;
|
|
3219
3519
|
};
|
|
3520
|
+
var InsertImageByURL = ({
|
|
3521
|
+
setIsOpen,
|
|
3522
|
+
onClick,
|
|
3523
|
+
disabled
|
|
3524
|
+
}) => {
|
|
3525
|
+
const [altText, setAltText] = React9.useState("");
|
|
3526
|
+
const [src, setSrc] = React9.useState("");
|
|
3527
|
+
const isDisabled = disabled || src === "";
|
|
3528
|
+
return /* @__PURE__ */ jsxRuntime.jsxs(react.Stack, { tokens: { childrenGap: 6, padding: "10px 0px 0px 0px" }, children: [
|
|
3529
|
+
/* @__PURE__ */ jsxRuntime.jsx(reactComponents.Field, { label: "Enter URL", size: "small", children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
3530
|
+
reactComponents.Input,
|
|
3531
|
+
{
|
|
3532
|
+
autoFocus: !disabled,
|
|
3533
|
+
appearance: "underline",
|
|
3534
|
+
placeholder: "Add URL",
|
|
3535
|
+
disabled,
|
|
3536
|
+
onChange: (_, v) => setSrc(v.value),
|
|
3537
|
+
value: src
|
|
3538
|
+
}
|
|
3539
|
+
) }),
|
|
3540
|
+
/* @__PURE__ */ jsxRuntime.jsx(reactComponents.Field, { label: "Alt Text", size: "small", children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
3541
|
+
reactComponents.Input,
|
|
3542
|
+
{
|
|
3543
|
+
placeholder: "Alt text",
|
|
3544
|
+
disabled,
|
|
3545
|
+
onChange: (_, v) => setAltText(v.value),
|
|
3546
|
+
value: altText
|
|
3547
|
+
},
|
|
3548
|
+
"alt-text-url"
|
|
3549
|
+
) }),
|
|
3550
|
+
/* @__PURE__ */ jsxRuntime.jsxs(react.Stack, { horizontal: true, horizontalAlign: "end", tokens: { childrenGap: 6 }, children: [
|
|
3551
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
3552
|
+
reactComponents.Button,
|
|
3553
|
+
{
|
|
3554
|
+
style: { width: "150px" },
|
|
3555
|
+
onClick: () => !disabled && onClick({ altText, src }),
|
|
3556
|
+
disabled: isDisabled,
|
|
3557
|
+
size: "small",
|
|
3558
|
+
children: "Confirm"
|
|
3559
|
+
},
|
|
3560
|
+
"url-confirm-btn"
|
|
3561
|
+
),
|
|
3562
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
3563
|
+
reactComponents.Button,
|
|
3564
|
+
{
|
|
3565
|
+
style: { width: "150px" },
|
|
3566
|
+
onClick: () => setIsOpen(false),
|
|
3567
|
+
disabled,
|
|
3568
|
+
size: "small",
|
|
3569
|
+
children: "Cancel"
|
|
3570
|
+
},
|
|
3571
|
+
"file-url-cancel"
|
|
3572
|
+
)
|
|
3573
|
+
] })
|
|
3574
|
+
] });
|
|
3575
|
+
};
|
|
3220
3576
|
var InsertImageDialog = ({
|
|
3221
3577
|
activeEditor,
|
|
3222
3578
|
disabled,
|
|
3223
|
-
|
|
3224
|
-
|
|
3579
|
+
maxImageSizeMB,
|
|
3580
|
+
validationMessages
|
|
3225
3581
|
}) => {
|
|
3226
3582
|
const [src, setSrc] = React9.useState("");
|
|
3227
3583
|
const [altText, setAltText] = React9.useState("");
|
|
3228
|
-
const [
|
|
3584
|
+
const [isOpen, setIsOpen] = React9.useState(false);
|
|
3585
|
+
const [selectedValue, setSelectedValue] = React9.useState("Upload");
|
|
3229
3586
|
const [fileName, setFileName] = React9.useState("");
|
|
3587
|
+
const [fileSizeError, setFileSizeError] = React9.useState(null);
|
|
3230
3588
|
const hasModifier = React9.useRef(false);
|
|
3231
3589
|
const iconColor = disabled ? "var(--colorNeutralForegroundDisabled, #A6A6A6)" : "#333333";
|
|
3232
|
-
const
|
|
3233
|
-
const isOpen = isControlled ? !!externalOpen && !disabled : internalOpen && !disabled;
|
|
3234
|
-
const isAddDisabled = disabled || src === "";
|
|
3235
|
-
const handleClose = () => {
|
|
3236
|
-
setSrc("");
|
|
3237
|
-
setAltText("");
|
|
3238
|
-
setFileName("");
|
|
3239
|
-
if (isControlled) onClose?.();
|
|
3240
|
-
else setInternalOpen(false);
|
|
3241
|
-
};
|
|
3590
|
+
const isDisabled = disabled || src === "" || !!fileSizeError;
|
|
3242
3591
|
React9.useEffect(() => {
|
|
3243
3592
|
hasModifier.current = false;
|
|
3244
3593
|
const handler = (e) => {
|
|
@@ -3250,57 +3599,75 @@ var InsertImageDialog = ({
|
|
|
3250
3599
|
const onClick = (payload) => {
|
|
3251
3600
|
if (disabled) return;
|
|
3252
3601
|
activeEditor.dispatchCommand(INSERT_IMAGE_COMMAND, payload);
|
|
3253
|
-
|
|
3602
|
+
setIsOpen(false);
|
|
3603
|
+
setAltText("");
|
|
3604
|
+
setSrc("");
|
|
3605
|
+
setFileName("");
|
|
3606
|
+
setFileSizeError(null);
|
|
3254
3607
|
};
|
|
3255
3608
|
const loadImage = (event) => {
|
|
3256
3609
|
if (disabled) return;
|
|
3257
3610
|
const files = event.target.files;
|
|
3258
3611
|
if (!files || files.length === 0) return;
|
|
3612
|
+
const file = files[0];
|
|
3613
|
+
if (maxImageSizeMB !== void 0) {
|
|
3614
|
+
const fileMB = file.size / (1024 * 1024);
|
|
3615
|
+
if (fileMB > maxImageSizeMB) {
|
|
3616
|
+
const override = validationMessages?.imageTooLarge;
|
|
3617
|
+
const msg = override !== void 0 ? typeof override === "function" ? override(fileMB, maxImageSizeMB) : override : DEFAULT_VALIDATION_MESSAGES.imageTooLarge(fileMB, maxImageSizeMB);
|
|
3618
|
+
setFileSizeError(msg);
|
|
3619
|
+
setSrc("");
|
|
3620
|
+
setFileName("");
|
|
3621
|
+
event.target.value = "";
|
|
3622
|
+
return;
|
|
3623
|
+
}
|
|
3624
|
+
}
|
|
3625
|
+
setFileSizeError(null);
|
|
3259
3626
|
const reader = new FileReader();
|
|
3260
3627
|
reader.onload = () => {
|
|
3261
3628
|
if (typeof reader.result === "string") {
|
|
3262
3629
|
setSrc(reader.result);
|
|
3263
|
-
setFileName(
|
|
3630
|
+
setFileName(file.name);
|
|
3264
3631
|
}
|
|
3265
3632
|
};
|
|
3266
|
-
reader.readAsDataURL(
|
|
3633
|
+
reader.readAsDataURL(file);
|
|
3267
3634
|
};
|
|
3268
|
-
return /* @__PURE__ */ jsxRuntime.jsxs(
|
|
3269
|
-
|
|
3270
|
-
|
|
3271
|
-
|
|
3272
|
-
|
|
3273
|
-
|
|
3274
|
-
disabled,
|
|
3275
|
-
icon: /* @__PURE__ */ jsxRuntime.jsx(reactIcons.ImageAddRegular, { style: { color: iconColor } }),
|
|
3276
|
-
style: {
|
|
3277
|
-
background: isOpen && !disabled ? "#ebebeb" : "none",
|
|
3278
|
-
border: "none",
|
|
3279
|
-
margin: 2,
|
|
3280
|
-
opacity: disabled ? 0.55 : 1,
|
|
3281
|
-
cursor: disabled ? "not-allowed" : "pointer"
|
|
3282
|
-
},
|
|
3283
|
-
onClick: () => {
|
|
3284
|
-
if (disabled) return;
|
|
3285
|
-
setSrc("");
|
|
3286
|
-
setAltText("");
|
|
3287
|
-
setFileName("");
|
|
3288
|
-
setInternalOpen(true);
|
|
3289
|
-
}
|
|
3635
|
+
return /* @__PURE__ */ jsxRuntime.jsxs(
|
|
3636
|
+
reactComponents.Dialog,
|
|
3637
|
+
{
|
|
3638
|
+
open: disabled ? false : isOpen,
|
|
3639
|
+
onOpenChange: (_, data) => {
|
|
3640
|
+
if (!disabled) setIsOpen(data.open);
|
|
3290
3641
|
},
|
|
3291
|
-
|
|
3292
|
-
|
|
3293
|
-
|
|
3294
|
-
|
|
3295
|
-
|
|
3296
|
-
|
|
3297
|
-
|
|
3298
|
-
|
|
3299
|
-
|
|
3300
|
-
|
|
3301
|
-
|
|
3302
|
-
|
|
3303
|
-
|
|
3642
|
+
children: [
|
|
3643
|
+
/* @__PURE__ */ jsxRuntime.jsx(reactComponents.DialogTrigger, { disableButtonEnhancement: true, children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
3644
|
+
reactComponents.Button,
|
|
3645
|
+
{
|
|
3646
|
+
size: "small",
|
|
3647
|
+
title: "Add Image",
|
|
3648
|
+
disabled,
|
|
3649
|
+
icon: /* @__PURE__ */ jsxRuntime.jsx(reactIcons.ImageAddRegular, { style: { color: iconColor } }),
|
|
3650
|
+
style: {
|
|
3651
|
+
background: isOpen && !disabled ? "#ebebeb" : "none",
|
|
3652
|
+
border: "none",
|
|
3653
|
+
margin: 2,
|
|
3654
|
+
opacity: disabled ? 0.55 : 1,
|
|
3655
|
+
cursor: disabled ? "not-allowed" : "pointer"
|
|
3656
|
+
},
|
|
3657
|
+
onClick: () => {
|
|
3658
|
+
if (disabled) return;
|
|
3659
|
+
setIsOpen((prev) => !prev);
|
|
3660
|
+
setSrc("");
|
|
3661
|
+
setAltText("");
|
|
3662
|
+
setFileName("");
|
|
3663
|
+
}
|
|
3664
|
+
},
|
|
3665
|
+
"upload-image"
|
|
3666
|
+
) }),
|
|
3667
|
+
/* @__PURE__ */ jsxRuntime.jsx(reactComponents.DialogSurface, { style: { maxWidth: 340 }, children: /* @__PURE__ */ jsxRuntime.jsxs(reactComponents.DialogBody, { children: [
|
|
3668
|
+
/* @__PURE__ */ jsxRuntime.jsx(reactComponents.DialogTitle, { children: "Insert image" }),
|
|
3669
|
+
/* @__PURE__ */ jsxRuntime.jsx(reactComponents.DialogContent, { children: /* @__PURE__ */ jsxRuntime.jsxs(react.Stack, { tokens: { childrenGap: 8 }, children: [
|
|
3670
|
+
/* @__PURE__ */ jsxRuntime.jsx(reactComponents.Field, { label: "Upload", size: "small", children: /* @__PURE__ */ jsxRuntime.jsxs(
|
|
3304
3671
|
"label",
|
|
3305
3672
|
{
|
|
3306
3673
|
style: {
|
|
@@ -3339,7 +3706,8 @@ var InsertImageDialog = ({
|
|
|
3339
3706
|
]
|
|
3340
3707
|
}
|
|
3341
3708
|
) }),
|
|
3342
|
-
/* @__PURE__ */ jsxRuntime.jsx(reactComponents.
|
|
3709
|
+
fileSizeError && /* @__PURE__ */ jsxRuntime.jsx(reactComponents.MessageBar, { intent: "error", style: { marginTop: 4 }, children: /* @__PURE__ */ jsxRuntime.jsx(reactComponents.MessageBarBody, { children: fileSizeError }) }),
|
|
3710
|
+
/* @__PURE__ */ jsxRuntime.jsx(reactComponents.Field, { label: "Alt Text", size: "small", children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
3343
3711
|
reactComponents.Input,
|
|
3344
3712
|
{
|
|
3345
3713
|
placeholder: "Alt text",
|
|
@@ -3348,25 +3716,24 @@ var InsertImageDialog = ({
|
|
|
3348
3716
|
onChange: (_, d) => setAltText(d.value),
|
|
3349
3717
|
value: altText
|
|
3350
3718
|
}
|
|
3351
|
-
) })
|
|
3352
|
-
|
|
3353
|
-
|
|
3354
|
-
/* @__PURE__ */ jsxRuntime.jsx(
|
|
3355
|
-
reactComponents.Button,
|
|
3719
|
+
) }),
|
|
3720
|
+
selectedValue === "URL" && /* @__PURE__ */ jsxRuntime.jsx(
|
|
3721
|
+
InsertImageByURL,
|
|
3356
3722
|
{
|
|
3357
|
-
|
|
3358
|
-
|
|
3359
|
-
|
|
3360
|
-
onClick: () => onClick({ altText, src }),
|
|
3361
|
-
children: "Add"
|
|
3723
|
+
disabled,
|
|
3724
|
+
setIsOpen: (open) => setIsOpen(open),
|
|
3725
|
+
onClick: (payload) => onClick(payload)
|
|
3362
3726
|
}
|
|
3363
|
-
)
|
|
3364
|
-
|
|
3727
|
+
)
|
|
3728
|
+
] }) }),
|
|
3729
|
+
/* @__PURE__ */ jsxRuntime.jsxs(reactComponents.DialogActions, { children: [
|
|
3730
|
+
/* @__PURE__ */ jsxRuntime.jsx(reactComponents.Button, { size: "small", disabled: isDisabled, onClick: () => onClick({ altText, src }), children: "Add" }),
|
|
3731
|
+
/* @__PURE__ */ jsxRuntime.jsx(reactComponents.Button, { size: "small", disabled, onClick: () => setIsOpen(false), children: "Cancel" })
|
|
3365
3732
|
] })
|
|
3366
3733
|
] }) })
|
|
3367
|
-
|
|
3368
|
-
|
|
3369
|
-
|
|
3734
|
+
]
|
|
3735
|
+
}
|
|
3736
|
+
);
|
|
3370
3737
|
};
|
|
3371
3738
|
var ImagesPlugin = ({ captionsEnabled }) => {
|
|
3372
3739
|
const [editor] = LexicalComposerContext.useLexicalComposerContext();
|
|
@@ -3379,9 +3746,21 @@ var ImagesPlugin = ({ captionsEnabled }) => {
|
|
|
3379
3746
|
INSERT_IMAGE_COMMAND,
|
|
3380
3747
|
(payload) => {
|
|
3381
3748
|
const imageNode = $createImageNode(payload);
|
|
3382
|
-
lexical.$
|
|
3383
|
-
if (lexical.$
|
|
3384
|
-
|
|
3749
|
+
const selection = lexical.$getSelection();
|
|
3750
|
+
if (lexical.$isRangeSelection(selection)) {
|
|
3751
|
+
const anchorNode = selection.anchor.getNode();
|
|
3752
|
+
const topLevel = anchorNode.getTopLevelElementOrThrow();
|
|
3753
|
+
const imageParagraph = lexical.$createParagraphNode();
|
|
3754
|
+
imageParagraph.append(imageNode);
|
|
3755
|
+
topLevel.insertAfter(imageParagraph);
|
|
3756
|
+
const tail = lexical.$createParagraphNode();
|
|
3757
|
+
imageParagraph.insertAfter(tail);
|
|
3758
|
+
tail.select();
|
|
3759
|
+
} else {
|
|
3760
|
+
lexical.$insertNodes([imageNode]);
|
|
3761
|
+
if (lexical.$isRootOrShadowRoot(imageNode.getParentOrThrow())) {
|
|
3762
|
+
utils.$wrapNodeInElement(imageNode, lexical.$createParagraphNode).selectEnd();
|
|
3763
|
+
}
|
|
3385
3764
|
}
|
|
3386
3765
|
return true;
|
|
3387
3766
|
},
|
|
@@ -3432,12 +3811,25 @@ var TRANSPARENT_IMAGE = "data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAA
|
|
|
3432
3811
|
var img = document.createElement("img");
|
|
3433
3812
|
img.src = TRANSPARENT_IMAGE;
|
|
3434
3813
|
var $onDragStart = (event) => {
|
|
3435
|
-
|
|
3814
|
+
let node = $getImageNodeInSelection();
|
|
3815
|
+
if (!node) {
|
|
3816
|
+
const target = event.target;
|
|
3817
|
+
if (!target) return false;
|
|
3818
|
+
const lexicalNode = lexical.$getNearestNodeFromDOMNode(target);
|
|
3819
|
+
if ($isImageNode(lexicalNode)) {
|
|
3820
|
+
node = lexicalNode;
|
|
3821
|
+
}
|
|
3822
|
+
}
|
|
3436
3823
|
if (!node) return false;
|
|
3437
3824
|
const dataTransfer = event.dataTransfer;
|
|
3438
3825
|
if (!dataTransfer) return false;
|
|
3826
|
+
const imgEl = event.target?.closest?.("span.editor-image")?.querySelector?.("img") ?? event.target;
|
|
3827
|
+
if (imgEl instanceof HTMLElement) {
|
|
3828
|
+
dataTransfer.setDragImage(imgEl, 20, 20);
|
|
3829
|
+
} else {
|
|
3830
|
+
dataTransfer.setDragImage(img, 0, 0);
|
|
3831
|
+
}
|
|
3439
3832
|
dataTransfer.setData("text/plain", "_");
|
|
3440
|
-
dataTransfer.setDragImage(img, 0, 0);
|
|
3441
3833
|
dataTransfer.setData(
|
|
3442
3834
|
"application/x-lexical-drag",
|
|
3443
3835
|
JSON.stringify({
|
|
@@ -3465,20 +3857,23 @@ var $onDragover = (event) => {
|
|
|
3465
3857
|
return true;
|
|
3466
3858
|
};
|
|
3467
3859
|
var $onDrop = (event, editor) => {
|
|
3468
|
-
const node = $getImageNodeInSelection();
|
|
3469
|
-
if (!node) return false;
|
|
3470
3860
|
const data = getDragImageData(event);
|
|
3471
3861
|
if (!data) return false;
|
|
3472
3862
|
event.preventDefault();
|
|
3473
3863
|
if (canDropImage(event)) {
|
|
3864
|
+
const sourceKey = data.key;
|
|
3865
|
+
if (sourceKey) {
|
|
3866
|
+
const sourceNode = lexical.$getNodeByKey(sourceKey);
|
|
3867
|
+
if (sourceNode) sourceNode.remove();
|
|
3868
|
+
}
|
|
3474
3869
|
const range = getDragSelection(event);
|
|
3475
|
-
node.remove();
|
|
3476
3870
|
const rangeSelection = lexical.$createRangeSelection();
|
|
3477
3871
|
if (range !== null && range !== void 0) {
|
|
3478
3872
|
rangeSelection.applyDOMRange(range);
|
|
3479
3873
|
}
|
|
3480
3874
|
lexical.$setSelection(rangeSelection);
|
|
3481
|
-
|
|
3875
|
+
const { key: _key, ...insertPayload } = data;
|
|
3876
|
+
editor.dispatchCommand(INSERT_IMAGE_COMMAND, insertPayload);
|
|
3482
3877
|
}
|
|
3483
3878
|
return true;
|
|
3484
3879
|
};
|
|
@@ -3498,7 +3893,7 @@ var getDragImageData = (event) => {
|
|
|
3498
3893
|
};
|
|
3499
3894
|
var canDropImage = (event) => {
|
|
3500
3895
|
const target = event.target;
|
|
3501
|
-
return !!(lexical.isHTMLElement(target) && !target.closest("code, span.editor-image") &&
|
|
3896
|
+
return !!(lexical.isHTMLElement(target) && !target.closest("code, span.editor-image") && target.closest('[contenteditable="true"]'));
|
|
3502
3897
|
};
|
|
3503
3898
|
var getDragSelection = (event) => {
|
|
3504
3899
|
let range;
|
|
@@ -3513,8 +3908,6 @@ var getDragSelection = (event) => {
|
|
|
3513
3908
|
}
|
|
3514
3909
|
return range;
|
|
3515
3910
|
};
|
|
3516
|
-
|
|
3517
|
-
// src/Plugins/InlineImage.tsx
|
|
3518
3911
|
init_InlineImage();
|
|
3519
3912
|
init_InlineImageNode();
|
|
3520
3913
|
var INSERT_INLINE_IMAGE_COMMAND = lexical.createCommand(
|
|
@@ -3533,39 +3926,45 @@ var useStyles = reactComponents.makeStyles({
|
|
|
3533
3926
|
var InsertInlineImageDialog = ({
|
|
3534
3927
|
disabled,
|
|
3535
3928
|
activeEditor,
|
|
3536
|
-
|
|
3537
|
-
|
|
3929
|
+
maxImageSizeMB,
|
|
3930
|
+
validationMessages
|
|
3538
3931
|
}) => {
|
|
3539
3932
|
const hasModifier = React9.useRef(false);
|
|
3540
3933
|
const [src, setSrc] = React9.useState("");
|
|
3541
|
-
const [
|
|
3934
|
+
const [isOpen, setIsOpen] = React9.useState(false);
|
|
3542
3935
|
const [altText, setAltText] = React9.useState("");
|
|
3543
3936
|
const [fileName, setFileName] = React9.useState("");
|
|
3544
3937
|
const [position, setPosition] = React9.useState("left");
|
|
3938
|
+
const [fileSizeError, setFileSizeError] = React9.useState(null);
|
|
3545
3939
|
const styles = useStyles();
|
|
3546
3940
|
const iconColor = disabled ? "var(--colorNeutralForegroundDisabled, #A6A6A6)" : "#333333";
|
|
3547
|
-
const
|
|
3548
|
-
const isOpen = isControlled ? !!externalOpen && !disabled : internalOpen && !disabled;
|
|
3549
|
-
const isAddDisabled = disabled || src === "";
|
|
3550
|
-
const handleClose = () => {
|
|
3551
|
-
setSrc("");
|
|
3552
|
-
setAltText("");
|
|
3553
|
-
setFileName("");
|
|
3554
|
-
if (isControlled) onClose?.();
|
|
3555
|
-
else setInternalOpen(false);
|
|
3556
|
-
};
|
|
3941
|
+
const isDisabled = disabled || src === "" || !!fileSizeError;
|
|
3557
3942
|
const loadImage = (event) => {
|
|
3558
3943
|
if (disabled) return;
|
|
3559
3944
|
const files = event.target.files;
|
|
3560
3945
|
if (!files || files.length === 0) return;
|
|
3946
|
+
const file = files[0];
|
|
3947
|
+
if (maxImageSizeMB !== void 0) {
|
|
3948
|
+
const fileMB = file.size / (1024 * 1024);
|
|
3949
|
+
if (fileMB > maxImageSizeMB) {
|
|
3950
|
+
const override = validationMessages?.imageTooLarge;
|
|
3951
|
+
const msg = override !== void 0 ? typeof override === "function" ? override(fileMB, maxImageSizeMB) : override : DEFAULT_VALIDATION_MESSAGES.imageTooLarge(fileMB, maxImageSizeMB);
|
|
3952
|
+
setFileSizeError(msg);
|
|
3953
|
+
setSrc("");
|
|
3954
|
+
setFileName("");
|
|
3955
|
+
event.target.value = "";
|
|
3956
|
+
return;
|
|
3957
|
+
}
|
|
3958
|
+
}
|
|
3959
|
+
setFileSizeError(null);
|
|
3561
3960
|
const reader = new FileReader();
|
|
3562
3961
|
reader.onload = () => {
|
|
3563
3962
|
if (typeof reader.result === "string") {
|
|
3564
3963
|
setSrc(reader.result);
|
|
3565
|
-
setFileName(
|
|
3964
|
+
setFileName(file.name);
|
|
3566
3965
|
}
|
|
3567
3966
|
};
|
|
3568
|
-
reader.readAsDataURL(
|
|
3967
|
+
reader.readAsDataURL(file);
|
|
3569
3968
|
};
|
|
3570
3969
|
React9.useEffect(() => {
|
|
3571
3970
|
const handler = (e) => {
|
|
@@ -3578,44 +3977,48 @@ var InsertInlineImageDialog = ({
|
|
|
3578
3977
|
if (disabled) return;
|
|
3579
3978
|
const payload = { altText, position, src };
|
|
3580
3979
|
activeEditor.dispatchCommand(INSERT_INLINE_IMAGE_COMMAND, payload);
|
|
3581
|
-
|
|
3980
|
+
setIsOpen(false);
|
|
3981
|
+
setAltText("");
|
|
3982
|
+
setSrc("");
|
|
3983
|
+
setFileName("");
|
|
3984
|
+
setFileSizeError(null);
|
|
3582
3985
|
};
|
|
3583
|
-
return /* @__PURE__ */ jsxRuntime.jsxs(
|
|
3584
|
-
|
|
3585
|
-
|
|
3586
|
-
|
|
3587
|
-
|
|
3588
|
-
|
|
3589
|
-
disabled,
|
|
3590
|
-
icon: /* @__PURE__ */ jsxRuntime.jsx(reactIcons.ImageEditRegular, { style: { color: iconColor } }),
|
|
3591
|
-
style: {
|
|
3592
|
-
background: isOpen && !disabled ? "#ebebeb" : "none",
|
|
3593
|
-
border: "none",
|
|
3594
|
-
margin: 2,
|
|
3595
|
-
opacity: disabled ? 0.55 : 1,
|
|
3596
|
-
cursor: disabled ? "not-allowed" : "pointer"
|
|
3597
|
-
},
|
|
3598
|
-
onClick: () => {
|
|
3599
|
-
if (disabled) return;
|
|
3600
|
-
setSrc("");
|
|
3601
|
-
setAltText("");
|
|
3602
|
-
setFileName("");
|
|
3603
|
-
setInternalOpen(true);
|
|
3604
|
-
}
|
|
3986
|
+
return /* @__PURE__ */ jsxRuntime.jsxs(
|
|
3987
|
+
reactComponents.Dialog,
|
|
3988
|
+
{
|
|
3989
|
+
open: disabled ? false : isOpen,
|
|
3990
|
+
onOpenChange: (_, data) => {
|
|
3991
|
+
if (!disabled) setIsOpen(data.open);
|
|
3605
3992
|
},
|
|
3606
|
-
|
|
3607
|
-
|
|
3608
|
-
|
|
3609
|
-
|
|
3610
|
-
|
|
3611
|
-
|
|
3612
|
-
|
|
3613
|
-
|
|
3614
|
-
|
|
3615
|
-
|
|
3616
|
-
|
|
3617
|
-
|
|
3618
|
-
|
|
3993
|
+
children: [
|
|
3994
|
+
/* @__PURE__ */ jsxRuntime.jsx(reactComponents.DialogTrigger, { disableButtonEnhancement: true, children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
3995
|
+
reactComponents.Button,
|
|
3996
|
+
{
|
|
3997
|
+
size: "small",
|
|
3998
|
+
title: "Add Inline Image",
|
|
3999
|
+
disabled,
|
|
4000
|
+
icon: /* @__PURE__ */ jsxRuntime.jsx(reactIcons.ImageEditRegular, { style: { color: iconColor } }),
|
|
4001
|
+
style: {
|
|
4002
|
+
background: isOpen && !disabled ? "#ebebeb" : "none",
|
|
4003
|
+
border: "none",
|
|
4004
|
+
margin: 2,
|
|
4005
|
+
opacity: disabled ? 0.55 : 1,
|
|
4006
|
+
cursor: disabled ? "not-allowed" : "pointer"
|
|
4007
|
+
},
|
|
4008
|
+
onClick: () => {
|
|
4009
|
+
if (disabled) return;
|
|
4010
|
+
setIsOpen((prev) => !prev);
|
|
4011
|
+
setAltText("");
|
|
4012
|
+
setSrc("");
|
|
4013
|
+
setFileName("");
|
|
4014
|
+
}
|
|
4015
|
+
},
|
|
4016
|
+
"upload-inline-image"
|
|
4017
|
+
) }),
|
|
4018
|
+
/* @__PURE__ */ jsxRuntime.jsx(reactComponents.DialogSurface, { style: { maxWidth: 360 }, children: /* @__PURE__ */ jsxRuntime.jsxs(reactComponents.DialogBody, { children: [
|
|
4019
|
+
/* @__PURE__ */ jsxRuntime.jsx(reactComponents.DialogTitle, { children: "Insert inline image" }),
|
|
4020
|
+
/* @__PURE__ */ jsxRuntime.jsx(reactComponents.DialogContent, { children: /* @__PURE__ */ jsxRuntime.jsxs(react.Stack, { tokens: { childrenGap: 8 }, children: [
|
|
4021
|
+
/* @__PURE__ */ jsxRuntime.jsx(reactComponents.Field, { label: "Upload", size: "small", children: /* @__PURE__ */ jsxRuntime.jsxs(
|
|
3619
4022
|
"label",
|
|
3620
4023
|
{
|
|
3621
4024
|
style: {
|
|
@@ -3654,22 +4057,25 @@ var InsertInlineImageDialog = ({
|
|
|
3654
4057
|
]
|
|
3655
4058
|
}
|
|
3656
4059
|
) }),
|
|
3657
|
-
/* @__PURE__ */ jsxRuntime.jsx(reactComponents.Field, { label: "Position",
|
|
4060
|
+
/* @__PURE__ */ jsxRuntime.jsx(reactComponents.Field, { label: "Position", size: "small", children: /* @__PURE__ */ jsxRuntime.jsxs(
|
|
3658
4061
|
reactComponents.Dropdown,
|
|
3659
4062
|
{
|
|
3660
|
-
placeholder: "Left Align",
|
|
3661
4063
|
className: styles.alignDropdown,
|
|
3662
4064
|
disabled,
|
|
4065
|
+
value: position === "full" ? "Full" : position === "right" ? "Right" : "Left",
|
|
4066
|
+
selectedOptions: [position ?? "left"],
|
|
3663
4067
|
listbox: { style: { width: "120px" } },
|
|
3664
4068
|
root: { style: { borderBottom: "1px solid black" } },
|
|
4069
|
+
onOptionSelect: (_, data) => setPosition(data.optionValue),
|
|
3665
4070
|
children: [
|
|
3666
|
-
/* @__PURE__ */ jsxRuntime.jsx(reactComponents.Option, {
|
|
3667
|
-
/* @__PURE__ */ jsxRuntime.jsx(reactComponents.Option, {
|
|
3668
|
-
/* @__PURE__ */ jsxRuntime.jsx(reactComponents.Option, {
|
|
4071
|
+
/* @__PURE__ */ jsxRuntime.jsx(reactComponents.Option, { value: "left", children: "Left" }, "left"),
|
|
4072
|
+
/* @__PURE__ */ jsxRuntime.jsx(reactComponents.Option, { value: "right", children: "Right" }, "right"),
|
|
4073
|
+
/* @__PURE__ */ jsxRuntime.jsx(reactComponents.Option, { value: "full", children: "Full" }, "full")
|
|
3669
4074
|
]
|
|
3670
4075
|
}
|
|
3671
4076
|
) }),
|
|
3672
|
-
/* @__PURE__ */ jsxRuntime.jsx(reactComponents.
|
|
4077
|
+
fileSizeError && /* @__PURE__ */ jsxRuntime.jsx(reactComponents.MessageBar, { intent: "error", style: { marginTop: 4 }, children: /* @__PURE__ */ jsxRuntime.jsx(reactComponents.MessageBarBody, { children: fileSizeError }) }),
|
|
4078
|
+
/* @__PURE__ */ jsxRuntime.jsx(reactComponents.Field, { label: "Alt Text", size: "small", children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
3673
4079
|
reactComponents.Input,
|
|
3674
4080
|
{
|
|
3675
4081
|
placeholder: "Alt text",
|
|
@@ -3684,9 +4090,8 @@ var InsertInlineImageDialog = ({
|
|
|
3684
4090
|
/* @__PURE__ */ jsxRuntime.jsx(
|
|
3685
4091
|
reactComponents.Button,
|
|
3686
4092
|
{
|
|
3687
|
-
appearance: "primary",
|
|
3688
4093
|
size: "small",
|
|
3689
|
-
disabled:
|
|
4094
|
+
disabled: isDisabled,
|
|
3690
4095
|
onClick: handleOnClick,
|
|
3691
4096
|
children: "Add"
|
|
3692
4097
|
},
|
|
@@ -3697,16 +4102,16 @@ var InsertInlineImageDialog = ({
|
|
|
3697
4102
|
{
|
|
3698
4103
|
size: "small",
|
|
3699
4104
|
disabled,
|
|
3700
|
-
onClick:
|
|
4105
|
+
onClick: () => setIsOpen(false),
|
|
3701
4106
|
children: "Cancel"
|
|
3702
4107
|
},
|
|
3703
4108
|
"file-inline-upload-cancel"
|
|
3704
4109
|
)
|
|
3705
4110
|
] })
|
|
3706
4111
|
] }) })
|
|
3707
|
-
|
|
3708
|
-
|
|
3709
|
-
|
|
4112
|
+
]
|
|
4113
|
+
}
|
|
4114
|
+
);
|
|
3710
4115
|
};
|
|
3711
4116
|
var InlineImagePlugin = () => {
|
|
3712
4117
|
const [editor] = LexicalComposerContext.useLexicalComposerContext();
|
|
@@ -3723,6 +4128,11 @@ var InlineImagePlugin = () => {
|
|
|
3723
4128
|
if (lexical.$isRootOrShadowRoot(imageNode.getParentOrThrow())) {
|
|
3724
4129
|
utils.$wrapNodeInElement(imageNode, lexical.$createParagraphNode).selectEnd();
|
|
3725
4130
|
}
|
|
4131
|
+
const parent = imageNode.getParent();
|
|
4132
|
+
if (parent && typeof parent.setFormat === "function") {
|
|
4133
|
+
const fmt = payload.position === "right" ? "right" : payload.position === "full" ? "center" : "left";
|
|
4134
|
+
parent.setFormat(fmt);
|
|
4135
|
+
}
|
|
3726
4136
|
return true;
|
|
3727
4137
|
},
|
|
3728
4138
|
lexical.COMMAND_PRIORITY_EDITOR
|
|
@@ -3751,12 +4161,23 @@ var TRANSPARENT_IMAGE2 = "data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEA
|
|
|
3751
4161
|
var img2 = document.createElement("img");
|
|
3752
4162
|
img2.src = TRANSPARENT_IMAGE2;
|
|
3753
4163
|
function $onDragStart2(event) {
|
|
3754
|
-
|
|
4164
|
+
let node = $getImageNodeInSelection2();
|
|
4165
|
+
if (!node) {
|
|
4166
|
+
const target = event.target;
|
|
4167
|
+
if (!target) return false;
|
|
4168
|
+
const lexicalNode = lexical.$getNearestNodeFromDOMNode(target);
|
|
4169
|
+
if ($isInlineImageNode(lexicalNode)) node = lexicalNode;
|
|
4170
|
+
}
|
|
3755
4171
|
if (!node) return false;
|
|
3756
4172
|
const dataTransfer = event.dataTransfer;
|
|
3757
4173
|
if (!dataTransfer) return false;
|
|
4174
|
+
const imgEl = event.target?.closest?.(".inline-editor-image")?.querySelector?.("img") ?? event.target;
|
|
4175
|
+
if (imgEl instanceof HTMLElement) {
|
|
4176
|
+
dataTransfer.setDragImage(imgEl, 20, 20);
|
|
4177
|
+
} else {
|
|
4178
|
+
dataTransfer.setDragImage(img2, 0, 0);
|
|
4179
|
+
}
|
|
3758
4180
|
dataTransfer.setData("text/plain", "_");
|
|
3759
|
-
dataTransfer.setDragImage(img2, 0, 0);
|
|
3760
4181
|
dataTransfer.setData(
|
|
3761
4182
|
"application/x-lexical-drag",
|
|
3762
4183
|
JSON.stringify({
|
|
@@ -3775,28 +4196,31 @@ function $onDragStart2(event) {
|
|
|
3775
4196
|
return true;
|
|
3776
4197
|
}
|
|
3777
4198
|
var $onDragover2 = (event) => {
|
|
3778
|
-
const
|
|
3779
|
-
if (!
|
|
4199
|
+
const hasDragData = !!event.dataTransfer?.types.includes("application/x-lexical-drag");
|
|
4200
|
+
if (!hasDragData) return false;
|
|
3780
4201
|
if (!canDropImage2(event)) {
|
|
3781
4202
|
event.preventDefault();
|
|
3782
4203
|
}
|
|
3783
4204
|
return true;
|
|
3784
4205
|
};
|
|
3785
4206
|
var $onDrop2 = (event, editor) => {
|
|
3786
|
-
const node = $getImageNodeInSelection2();
|
|
3787
|
-
if (!node) return false;
|
|
3788
4207
|
const data = getDragImageData2(event);
|
|
3789
4208
|
if (!data) return false;
|
|
3790
4209
|
event.preventDefault();
|
|
3791
4210
|
if (canDropImage2(event)) {
|
|
4211
|
+
const sourceKey = data.key;
|
|
4212
|
+
if (sourceKey) {
|
|
4213
|
+
const sourceNode = lexical.$getNodeByKey(sourceKey);
|
|
4214
|
+
if (sourceNode) sourceNode.remove();
|
|
4215
|
+
}
|
|
3792
4216
|
const range = getDragSelection2(event);
|
|
3793
|
-
node.remove();
|
|
3794
4217
|
const rangeSelection = lexical.$createRangeSelection();
|
|
3795
4218
|
if (range !== null && range !== void 0) {
|
|
3796
4219
|
rangeSelection.applyDOMRange(range);
|
|
3797
4220
|
}
|
|
3798
4221
|
lexical.$setSelection(rangeSelection);
|
|
3799
|
-
|
|
4222
|
+
const { key: _key, ...insertPayload } = data;
|
|
4223
|
+
editor.dispatchCommand(INSERT_INLINE_IMAGE_COMMAND, insertPayload);
|
|
3800
4224
|
}
|
|
3801
4225
|
return true;
|
|
3802
4226
|
};
|
|
@@ -3816,7 +4240,7 @@ var getDragImageData2 = (event) => {
|
|
|
3816
4240
|
};
|
|
3817
4241
|
var canDropImage2 = (event) => {
|
|
3818
4242
|
const target = event.target;
|
|
3819
|
-
return !!(lexical.isHTMLElement(target) && !target.closest("code, span.editor-image
|
|
4243
|
+
return !!(lexical.isHTMLElement(target) && !target.closest("code, span.editor-image, .inline-editor-image") && target.closest('[contenteditable="true"]'));
|
|
3820
4244
|
};
|
|
3821
4245
|
var getDragSelection2 = (event) => {
|
|
3822
4246
|
let range;
|
|
@@ -3907,20 +4331,79 @@ function hasBlock(editor, kind) {
|
|
|
3907
4331
|
}
|
|
3908
4332
|
|
|
3909
4333
|
// src/Plugins/RefApiPlugin.tsx
|
|
4334
|
+
function getUserContentSignature(editor) {
|
|
4335
|
+
const parts = [];
|
|
4336
|
+
editor.getEditorState().read(() => {
|
|
4337
|
+
const root = lexical.$getRoot();
|
|
4338
|
+
const collectNode = (node) => {
|
|
4339
|
+
if ($isHtmlBlockNode(node)) return;
|
|
4340
|
+
if (lexical.$isDecoratorNode(node)) {
|
|
4341
|
+
parts.push(`D:${node.getKey()}`);
|
|
4342
|
+
return;
|
|
4343
|
+
}
|
|
4344
|
+
if (lexical.$isLineBreakNode(node)) {
|
|
4345
|
+
parts.push("BR");
|
|
4346
|
+
return;
|
|
4347
|
+
}
|
|
4348
|
+
if (lexical.$isTextNode(node)) {
|
|
4349
|
+
parts.push(`T${node.getFormat()}:${node.getStyle()}:${node.getTextContent()}`);
|
|
4350
|
+
return;
|
|
4351
|
+
}
|
|
4352
|
+
if (lexical.$isElementNode(node)) {
|
|
4353
|
+
const type = node.getType();
|
|
4354
|
+
const tag = typeof node.getTag === "function" ? node.getTag() : "";
|
|
4355
|
+
const list = typeof node.getListType === "function" ? node.getListType() : "";
|
|
4356
|
+
const fmt = typeof node.getFormat === "function" ? node.getFormat() : "";
|
|
4357
|
+
parts.push(`[${type}:${tag}:${list}:${fmt}]`);
|
|
4358
|
+
for (const child of node.getChildren()) {
|
|
4359
|
+
collectNode(child);
|
|
4360
|
+
}
|
|
4361
|
+
parts.push("[/]");
|
|
4362
|
+
}
|
|
4363
|
+
};
|
|
4364
|
+
for (const child of root.getChildren()) {
|
|
4365
|
+
if ($isHtmlBlockNode(child)) continue;
|
|
4366
|
+
collectNode(child);
|
|
4367
|
+
}
|
|
4368
|
+
});
|
|
4369
|
+
return JSON.stringify(parts);
|
|
4370
|
+
}
|
|
3910
4371
|
function RefApiPlugin({
|
|
3911
4372
|
forwardedRef,
|
|
3912
4373
|
contentEditableDomRef,
|
|
3913
|
-
focusedRef
|
|
3914
|
-
setRefErrors
|
|
4374
|
+
focusedRef
|
|
3915
4375
|
}) {
|
|
3916
4376
|
const [editor] = LexicalComposerContext.useLexicalComposerContext();
|
|
4377
|
+
const cleanBaselineRef = React9__namespace.default.useRef(null);
|
|
4378
|
+
React9__namespace.default.useEffect(() => {
|
|
4379
|
+
const capture = () => {
|
|
4380
|
+
if (cleanBaselineRef.current === null) {
|
|
4381
|
+
cleanBaselineRef.current = getUserContentSignature(editor);
|
|
4382
|
+
}
|
|
4383
|
+
};
|
|
4384
|
+
const unregister = editor.registerUpdateListener(({ dirtyElements, dirtyLeaves }) => {
|
|
4385
|
+
if (cleanBaselineRef.current !== null) {
|
|
4386
|
+
unregister();
|
|
4387
|
+
return;
|
|
4388
|
+
}
|
|
4389
|
+
if (dirtyElements.size === 0 && dirtyLeaves.size === 0) return;
|
|
4390
|
+
capture();
|
|
4391
|
+
unregister();
|
|
4392
|
+
});
|
|
4393
|
+
const timerId = setTimeout(capture, 0);
|
|
4394
|
+
return () => {
|
|
4395
|
+
clearTimeout(timerId);
|
|
4396
|
+
unregister();
|
|
4397
|
+
};
|
|
4398
|
+
}, [editor]);
|
|
3917
4399
|
React9.useImperativeHandle(
|
|
3918
4400
|
forwardedRef,
|
|
3919
4401
|
() => ({
|
|
3920
4402
|
setValue: (html$1) => {
|
|
3921
4403
|
editor.update(() => {
|
|
4404
|
+
const safe = normalizeToBlockHtml(sanitizeHtml(html$1 || ""));
|
|
3922
4405
|
const parser = new DOMParser();
|
|
3923
|
-
const dom = parser.parseFromString(
|
|
4406
|
+
const dom = parser.parseFromString(safe || "<p></p>", "text/html");
|
|
3924
4407
|
const nodes = html.$generateNodesFromDOM(editor, dom);
|
|
3925
4408
|
const root = lexical.$getRoot();
|
|
3926
4409
|
root.clear();
|
|
@@ -3930,9 +4413,9 @@ function RefApiPlugin({
|
|
|
3930
4413
|
getValue: () => {
|
|
3931
4414
|
let html$1 = "";
|
|
3932
4415
|
editor.getEditorState().read(() => {
|
|
3933
|
-
html$1 = html.$generateHtmlFromNodes(editor, null);
|
|
4416
|
+
html$1 = postProcessOutput(splitHeadingsAtBrSequences(html.$generateHtmlFromNodes(editor, null)));
|
|
3934
4417
|
});
|
|
3935
|
-
return
|
|
4418
|
+
return html$1;
|
|
3936
4419
|
},
|
|
3937
4420
|
clear: () => {
|
|
3938
4421
|
editor.update(() => {
|
|
@@ -3950,14 +4433,20 @@ function RefApiPlugin({
|
|
|
3950
4433
|
},
|
|
3951
4434
|
isFocused: () => focusedRef.current,
|
|
3952
4435
|
getEditor: () => editor,
|
|
3953
|
-
setErrors: (messages) => setRefErrors(messages),
|
|
3954
|
-
clearErrors: () => setRefErrors([]),
|
|
3955
4436
|
// Generic blocks (signature, footer, banner, etc.)
|
|
3956
4437
|
upsertBlock: (spec) => upsertBlock(editor, spec),
|
|
3957
4438
|
removeBlock: (kind) => removeBlock(editor, kind),
|
|
3958
|
-
hasBlock: (kind) => hasBlock(editor, kind)
|
|
4439
|
+
hasBlock: (kind) => hasBlock(editor, kind),
|
|
4440
|
+
checkDirty: () => {
|
|
4441
|
+
if (cleanBaselineRef.current === null) return false;
|
|
4442
|
+
const current = getUserContentSignature(editor);
|
|
4443
|
+
return current !== cleanBaselineRef.current;
|
|
4444
|
+
},
|
|
4445
|
+
markClean: () => {
|
|
4446
|
+
cleanBaselineRef.current = getUserContentSignature(editor);
|
|
4447
|
+
}
|
|
3959
4448
|
}),
|
|
3960
|
-
[editor, contentEditableDomRef, focusedRef
|
|
4449
|
+
[editor, contentEditableDomRef, focusedRef]
|
|
3961
4450
|
);
|
|
3962
4451
|
return null;
|
|
3963
4452
|
}
|
|
@@ -4598,8 +5087,22 @@ function TableActionMenuPlugin({ disabled = false }) {
|
|
|
4598
5087
|
const [editor] = LexicalComposerContext.useLexicalComposerContext();
|
|
4599
5088
|
const [isInTable, setIsInTable] = React9__namespace.useState(false);
|
|
4600
5089
|
const [anchorRect, setAnchorRect] = React9__namespace.useState(null);
|
|
5090
|
+
const [contentRight, setContentRight] = React9__namespace.useState(null);
|
|
4601
5091
|
const [open, setOpen] = React9__namespace.useState(false);
|
|
5092
|
+
const openRef = React9__namespace.useRef(false);
|
|
5093
|
+
const savedAnchorRef = React9__namespace.useRef(null);
|
|
5094
|
+
const measureContentRight = React9__namespace.useCallback((cellDom) => {
|
|
5095
|
+
try {
|
|
5096
|
+
const range = document.createRange();
|
|
5097
|
+
range.selectNodeContents(cellDom);
|
|
5098
|
+
const cr = range.getBoundingClientRect();
|
|
5099
|
+
return cr.width > 2 ? cr.right : null;
|
|
5100
|
+
} catch {
|
|
5101
|
+
return null;
|
|
5102
|
+
}
|
|
5103
|
+
}, []);
|
|
4602
5104
|
const updateFromSelection = React9__namespace.useCallback(() => {
|
|
5105
|
+
if (openRef.current) return;
|
|
4603
5106
|
const root = editor.getRootElement();
|
|
4604
5107
|
if (!root) return;
|
|
4605
5108
|
editor.getEditorState().read(() => {
|
|
@@ -4611,6 +5114,7 @@ function TableActionMenuPlugin({ disabled = false }) {
|
|
|
4611
5114
|
if (dom) {
|
|
4612
5115
|
setIsInTable(true);
|
|
4613
5116
|
setAnchorRect(dom.getBoundingClientRect());
|
|
5117
|
+
setContentRight(null);
|
|
4614
5118
|
return;
|
|
4615
5119
|
}
|
|
4616
5120
|
}
|
|
@@ -4618,6 +5122,7 @@ function TableActionMenuPlugin({ disabled = false }) {
|
|
|
4618
5122
|
if (!lexical.$isRangeSelection(selection)) {
|
|
4619
5123
|
setIsInTable(false);
|
|
4620
5124
|
setAnchorRect(null);
|
|
5125
|
+
setContentRight(null);
|
|
4621
5126
|
return;
|
|
4622
5127
|
}
|
|
4623
5128
|
const anchorNode = selection.anchor.getNode();
|
|
@@ -4625,18 +5130,28 @@ function TableActionMenuPlugin({ disabled = false }) {
|
|
|
4625
5130
|
if (!cellNode || !table.$isTableCellNode(cellNode)) {
|
|
4626
5131
|
setIsInTable(false);
|
|
4627
5132
|
setAnchorRect(null);
|
|
5133
|
+
setContentRight(null);
|
|
4628
5134
|
return;
|
|
4629
5135
|
}
|
|
4630
5136
|
const cellDom = editor.getElementByKey(cellNode.getKey());
|
|
4631
5137
|
if (!cellDom) {
|
|
4632
5138
|
setIsInTable(false);
|
|
4633
5139
|
setAnchorRect(null);
|
|
5140
|
+
setContentRight(null);
|
|
4634
5141
|
return;
|
|
4635
5142
|
}
|
|
4636
5143
|
setIsInTable(true);
|
|
4637
5144
|
setAnchorRect(cellDom.getBoundingClientRect());
|
|
5145
|
+
setContentRight(measureContentRight(cellDom));
|
|
5146
|
+
if (lexical.$isRangeSelection(selection)) {
|
|
5147
|
+
savedAnchorRef.current = {
|
|
5148
|
+
key: selection.anchor.key,
|
|
5149
|
+
offset: selection.anchor.offset,
|
|
5150
|
+
type: selection.anchor.type
|
|
5151
|
+
};
|
|
5152
|
+
}
|
|
4638
5153
|
});
|
|
4639
|
-
}, [editor]);
|
|
5154
|
+
}, [editor, measureContentRight]);
|
|
4640
5155
|
React9__namespace.useEffect(() => {
|
|
4641
5156
|
return utils.mergeRegister(
|
|
4642
5157
|
editor.registerCommand(
|
|
@@ -4693,30 +5208,37 @@ function TableActionMenuPlugin({ disabled = false }) {
|
|
|
4693
5208
|
lexical.COMMAND_PRIORITY_HIGH
|
|
4694
5209
|
);
|
|
4695
5210
|
}, [editor, disabled]);
|
|
4696
|
-
React9__namespace.useEffect(() => {
|
|
4697
|
-
if (!isInTable && open) setOpen(false);
|
|
4698
|
-
}, [isInTable, open]);
|
|
4699
5211
|
const canShow = isInTable && !!anchorRect && !disabled;
|
|
4700
5212
|
const handleStyle = React9__namespace.useMemo(() => {
|
|
4701
5213
|
if (!anchorRect) return void 0;
|
|
4702
5214
|
const top = Math.max(8, anchorRect.top + 6);
|
|
4703
|
-
const
|
|
5215
|
+
const clampedCellRight = Math.min(anchorRect.right, window.innerWidth - 8);
|
|
5216
|
+
const left = contentRight !== null ? Math.max(anchorRect.left + 4, Math.min(contentRight + 4, clampedCellRight - 32)) : Math.max(8, anchorRect.left + 8);
|
|
4704
5217
|
return {
|
|
4705
5218
|
position: "fixed",
|
|
4706
5219
|
top,
|
|
4707
5220
|
left,
|
|
4708
5221
|
zIndex: 9999
|
|
4709
5222
|
};
|
|
4710
|
-
}, [anchorRect]);
|
|
5223
|
+
}, [anchorRect, contentRight]);
|
|
4711
5224
|
const dangerStyle = {
|
|
4712
5225
|
color: "var(--colorPaletteRedForeground1)"
|
|
4713
5226
|
};
|
|
4714
5227
|
const run = React9__namespace.useCallback(
|
|
4715
5228
|
(fn) => {
|
|
4716
5229
|
if (disabled) return;
|
|
4717
|
-
|
|
4718
|
-
editor.update(() => fn());
|
|
5230
|
+
openRef.current = false;
|
|
4719
5231
|
setOpen(false);
|
|
5232
|
+
editor.update(() => {
|
|
5233
|
+
const saved = savedAnchorRef.current;
|
|
5234
|
+
if (saved && lexical.$getNodeByKey(saved.key)) {
|
|
5235
|
+
const sel = lexical.$createRangeSelection();
|
|
5236
|
+
sel.anchor.set(saved.key, saved.offset, saved.type);
|
|
5237
|
+
sel.focus.set(saved.key, saved.offset, saved.type);
|
|
5238
|
+
lexical.$setSelection(sel);
|
|
5239
|
+
}
|
|
5240
|
+
fn();
|
|
5241
|
+
});
|
|
4720
5242
|
},
|
|
4721
5243
|
[disabled, editor]
|
|
4722
5244
|
);
|
|
@@ -4726,32 +5248,31 @@ function TableActionMenuPlugin({ disabled = false }) {
|
|
|
4726
5248
|
const insertColLeft = () => run(() => table.$insertTableColumnAtSelection(false));
|
|
4727
5249
|
const deleteRow = () => run(() => table.$deleteTableRowAtSelection());
|
|
4728
5250
|
const deleteCol = () => run(() => table.$deleteTableColumnAtSelection());
|
|
4729
|
-
const deleteTable = () =>
|
|
4730
|
-
|
|
4731
|
-
|
|
4732
|
-
|
|
5251
|
+
const deleteTable = () => {
|
|
5252
|
+
if (disabled) return;
|
|
5253
|
+
openRef.current = false;
|
|
5254
|
+
setOpen(false);
|
|
5255
|
+
editor.update(() => {
|
|
5256
|
+
const saved = savedAnchorRef.current;
|
|
5257
|
+
if (!saved) return;
|
|
5258
|
+
const anchorNode = lexical.$getNodeByKey(saved.key);
|
|
5259
|
+
if (!anchorNode) return;
|
|
5260
|
+
const tableNode = lexical.$findMatchingParent(anchorNode, (n) => table.$isTableNode(n));
|
|
4733
5261
|
if (tableNode) tableNode.remove();
|
|
4734
|
-
|
|
4735
|
-
|
|
4736
|
-
if (!lexical.$isRangeSelection(selection)) return;
|
|
4737
|
-
const node = selection.anchor.getNode();
|
|
4738
|
-
const cell = lexical.$findMatchingParent(node, (n) => table.$isTableCellNode(n)) ?? (table.$isTableCellNode(node) ? node : null);
|
|
4739
|
-
if (!cell) return;
|
|
4740
|
-
const table$1 = table.$getTableNodeFromLexicalNodeOrThrow(cell);
|
|
4741
|
-
table$1.remove();
|
|
4742
|
-
});
|
|
5262
|
+
});
|
|
5263
|
+
};
|
|
4743
5264
|
if (!canShow || !handleStyle) return null;
|
|
4744
5265
|
return reactDom.createPortal(
|
|
4745
|
-
/* @__PURE__ */ jsxRuntime.jsx("div", { style: handleStyle, className: "aoTableActionHandleRoot", children: /* @__PURE__ */ jsxRuntime.jsxs(reactComponents.Menu, { open, onOpenChange: (_, data) =>
|
|
5266
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { style: handleStyle, className: "aoTableActionHandleRoot", "data-lexical-editor-portal": "true", children: /* @__PURE__ */ jsxRuntime.jsxs(reactComponents.Menu, { open, onOpenChange: (_, data) => {
|
|
5267
|
+
openRef.current = data.open;
|
|
5268
|
+
setOpen(data.open);
|
|
5269
|
+
}, children: [
|
|
4746
5270
|
/* @__PURE__ */ jsxRuntime.jsx(reactComponents.MenuTrigger, { disableButtonEnhancement: true, children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
4747
5271
|
"button",
|
|
4748
5272
|
{
|
|
4749
5273
|
type: "button",
|
|
4750
5274
|
className: "aoTableActionHandleBtn",
|
|
4751
5275
|
"aria-label": "Table options",
|
|
4752
|
-
onMouseDown: (e) => {
|
|
4753
|
-
e.preventDefault();
|
|
4754
|
-
},
|
|
4755
5276
|
children: /* @__PURE__ */ jsxRuntime.jsx(reactIcons.ChevronDown12Regular, {})
|
|
4756
5277
|
}
|
|
4757
5278
|
) }),
|
|
@@ -5075,8 +5596,8 @@ function getToolbarGroupsByLevel(level) {
|
|
|
5075
5596
|
// ['undo', 'redo', '|'],
|
|
5076
5597
|
["Bold", "Italic", "Underline", "|"],
|
|
5077
5598
|
["ColorPicker", "|"],
|
|
5078
|
-
["Link", "|"],
|
|
5079
|
-
[
|
|
5599
|
+
["Link", "Table", "|"],
|
|
5600
|
+
// ['Image', 'Youtube', 'InlineImage', '|'],
|
|
5080
5601
|
["Heading", "|"],
|
|
5081
5602
|
["FontFamily", "|"],
|
|
5082
5603
|
["FontSize", "|"],
|
|
@@ -5090,8 +5611,9 @@ function getToolbarGroupsByLevel(level) {
|
|
|
5090
5611
|
// ['undo', 'redo', '|'],
|
|
5091
5612
|
["Bold", "Italic", "Underline", "|"],
|
|
5092
5613
|
["ColorPicker", "|"],
|
|
5093
|
-
["Link", "|"],
|
|
5094
|
-
[
|
|
5614
|
+
["Link", "Table", "|"],
|
|
5615
|
+
// ['CodeBlock', '|'],
|
|
5616
|
+
["Image", "Youtube", "InlineImage", "|"],
|
|
5095
5617
|
["Heading", "|"],
|
|
5096
5618
|
["FontFamily", "|"],
|
|
5097
5619
|
["FontSize", "|"],
|
|
@@ -5101,6 +5623,85 @@ function getToolbarGroupsByLevel(level) {
|
|
|
5101
5623
|
];
|
|
5102
5624
|
}
|
|
5103
5625
|
}
|
|
5626
|
+
var DEFAULT_FONT_SIZE = 15;
|
|
5627
|
+
function $splitBlocksAtLineBreaks(selection) {
|
|
5628
|
+
const blocksToSplit = /* @__PURE__ */ new Set();
|
|
5629
|
+
for (const node of selection.getNodes()) {
|
|
5630
|
+
const block = node.getTopLevelElement();
|
|
5631
|
+
if (block && lexical.$isElementNode(block)) {
|
|
5632
|
+
const children = block.getChildren();
|
|
5633
|
+
if (children.some(lexical.$isLineBreakNode)) {
|
|
5634
|
+
blocksToSplit.add(block);
|
|
5635
|
+
}
|
|
5636
|
+
}
|
|
5637
|
+
}
|
|
5638
|
+
for (const block of blocksToSplit) {
|
|
5639
|
+
const children = [...block.getChildren()];
|
|
5640
|
+
const groups = [[]];
|
|
5641
|
+
for (const child of children) {
|
|
5642
|
+
if (lexical.$isLineBreakNode(child)) {
|
|
5643
|
+
groups.push([]);
|
|
5644
|
+
} else {
|
|
5645
|
+
groups[groups.length - 1].push(child);
|
|
5646
|
+
}
|
|
5647
|
+
}
|
|
5648
|
+
const nonEmptyCount = groups.filter((g) => g.length > 0).length;
|
|
5649
|
+
if (nonEmptyCount <= 1) continue;
|
|
5650
|
+
for (let i = groups.length - 1; i >= 1; i--) {
|
|
5651
|
+
const group = groups[i];
|
|
5652
|
+
const newBlock = group.length === 0 ? lexical.$createParagraphNode() : richText.$isHeadingNode(block) ? richText.$createHeadingNode(block.getTag()) : lexical.$createParagraphNode();
|
|
5653
|
+
group.forEach((child) => newBlock.append(child));
|
|
5654
|
+
block.insertAfter(newBlock);
|
|
5655
|
+
}
|
|
5656
|
+
[...block.getChildren()].filter(lexical.$isLineBreakNode).forEach((br) => br.remove());
|
|
5657
|
+
}
|
|
5658
|
+
}
|
|
5659
|
+
function $splitBlockAtPartialSelection(selection) {
|
|
5660
|
+
if (selection.isCollapsed()) return false;
|
|
5661
|
+
const anchorBlock = selection.anchor.getNode().getTopLevelElement();
|
|
5662
|
+
const focusBlock = selection.focus.getNode().getTopLevelElement();
|
|
5663
|
+
if (!anchorBlock || !focusBlock || !anchorBlock.is(focusBlock)) return false;
|
|
5664
|
+
if (!lexical.$isElementNode(anchorBlock)) return false;
|
|
5665
|
+
const block = anchorBlock;
|
|
5666
|
+
const extractedNodes = selection.extract();
|
|
5667
|
+
if (!extractedNodes.length) return false;
|
|
5668
|
+
const allDirect = extractedNodes.every((n) => {
|
|
5669
|
+
const parent = n.getParent();
|
|
5670
|
+
return parent !== null && parent.is(block);
|
|
5671
|
+
});
|
|
5672
|
+
if (!allDirect) return false;
|
|
5673
|
+
const allChildren = [...block.getChildren()];
|
|
5674
|
+
const firstSelected = extractedNodes[0];
|
|
5675
|
+
const lastSelected = extractedNodes[extractedNodes.length - 1];
|
|
5676
|
+
const firstIdx = allChildren.findIndex((n) => n.is(firstSelected));
|
|
5677
|
+
const lastIdx = allChildren.findIndex((n) => n.is(lastSelected));
|
|
5678
|
+
if (firstIdx === -1 || lastIdx === -1) return false;
|
|
5679
|
+
if (firstIdx === 0 && lastIdx === allChildren.length - 1) return false;
|
|
5680
|
+
const selectedNodes = allChildren.slice(firstIdx, lastIdx + 1);
|
|
5681
|
+
const afterNodes = allChildren.slice(lastIdx + 1);
|
|
5682
|
+
if (afterNodes.length > 0) {
|
|
5683
|
+
const afterBlock = richText.$isHeadingNode(block) ? richText.$createHeadingNode(block.getTag()) : lexical.$createParagraphNode();
|
|
5684
|
+
afterNodes.forEach((n) => afterBlock.append(n));
|
|
5685
|
+
block.insertAfter(afterBlock);
|
|
5686
|
+
}
|
|
5687
|
+
const selectedBlock = lexical.$createParagraphNode();
|
|
5688
|
+
selectedNodes.forEach((n) => selectedBlock.append(n));
|
|
5689
|
+
block.insertAfter(selectedBlock);
|
|
5690
|
+
if (block.getChildrenSize() === 0) {
|
|
5691
|
+
block.remove();
|
|
5692
|
+
}
|
|
5693
|
+
selectedBlock.select();
|
|
5694
|
+
return true;
|
|
5695
|
+
}
|
|
5696
|
+
var formatParagraph = (editor) => {
|
|
5697
|
+
editor.update(() => {
|
|
5698
|
+
const selection$1 = lexical.$getSelection();
|
|
5699
|
+
if (lexical.$isRangeSelection(selection$1)) {
|
|
5700
|
+
$splitBlocksAtLineBreaks(selection$1);
|
|
5701
|
+
}
|
|
5702
|
+
selection.$setBlocksType(lexical.$getSelection(), () => lexical.$createParagraphNode());
|
|
5703
|
+
});
|
|
5704
|
+
};
|
|
5104
5705
|
var PRESET = [
|
|
5105
5706
|
"#000000",
|
|
5106
5707
|
"#434343",
|
|
@@ -5384,7 +5985,7 @@ var ColorPickerControl = ({ value, title, disabled, onChange, icon, onOpenChange
|
|
|
5384
5985
|
directionalHint: 4,
|
|
5385
5986
|
className: "aoColorCallout",
|
|
5386
5987
|
preventDismissOnEvent,
|
|
5387
|
-
children: /* @__PURE__ */ jsxRuntime.jsxs(react.Stack, { tokens: { childrenGap: 14 }, styles: { root: { padding: "14px 16px 16px", width:
|
|
5988
|
+
children: /* @__PURE__ */ jsxRuntime.jsxs(react.Stack, { tokens: { childrenGap: 14 }, styles: { root: { padding: "14px 16px 16px", width: 250 } }, children: [
|
|
5388
5989
|
/* @__PURE__ */ jsxRuntime.jsxs("div", { style: { display: "flex", alignItems: "center", justifyContent: "space-between" }, children: [
|
|
5389
5990
|
/* @__PURE__ */ jsxRuntime.jsx("div", { style: { fontSize: 13, fontWeight: 600, color: "#242424", letterSpacing: 0.1 }, children: title }),
|
|
5390
5991
|
/* @__PURE__ */ jsxRuntime.jsx(
|
|
@@ -5397,8 +5998,8 @@ var ColorPickerControl = ({ value, title, disabled, onChange, icon, onOpenChange
|
|
|
5397
5998
|
display: "flex",
|
|
5398
5999
|
alignItems: "center",
|
|
5399
6000
|
justifyContent: "center",
|
|
5400
|
-
width:
|
|
5401
|
-
height:
|
|
6001
|
+
width: 18,
|
|
6002
|
+
height: 18,
|
|
5402
6003
|
padding: 0,
|
|
5403
6004
|
border: "none",
|
|
5404
6005
|
borderRadius: 4,
|
|
@@ -5421,7 +6022,7 @@ var ColorPickerControl = ({ value, title, disabled, onChange, icon, onOpenChange
|
|
|
5421
6022
|
style: {
|
|
5422
6023
|
position: "relative",
|
|
5423
6024
|
width: "100%",
|
|
5424
|
-
height:
|
|
6025
|
+
height: 125,
|
|
5425
6026
|
borderRadius: 8,
|
|
5426
6027
|
overflow: "hidden",
|
|
5427
6028
|
cursor: "crosshair",
|
|
@@ -5510,8 +6111,8 @@ var ColorPickerControl = ({ value, title, disabled, onChange, icon, onOpenChange
|
|
|
5510
6111
|
"div",
|
|
5511
6112
|
{
|
|
5512
6113
|
style: {
|
|
5513
|
-
width:
|
|
5514
|
-
height:
|
|
6114
|
+
width: 20,
|
|
6115
|
+
height: 20,
|
|
5515
6116
|
borderRadius: 6,
|
|
5516
6117
|
flexShrink: 0,
|
|
5517
6118
|
background: hex,
|
|
@@ -5552,10 +6153,10 @@ var ColorPickerControl = ({ value, title, disabled, onChange, icon, onOpenChange
|
|
|
5552
6153
|
title: c,
|
|
5553
6154
|
"aria-label": c,
|
|
5554
6155
|
style: {
|
|
5555
|
-
width:
|
|
5556
|
-
height:
|
|
6156
|
+
width: 18,
|
|
6157
|
+
height: 18,
|
|
5557
6158
|
padding: 0,
|
|
5558
|
-
borderRadius:
|
|
6159
|
+
borderRadius: 4,
|
|
5559
6160
|
background: c,
|
|
5560
6161
|
cursor: "pointer",
|
|
5561
6162
|
boxShadow: isSelected ? "0 0 0 2px #fff, 0 0 0 3px #4a86e8" : "inset 0 0 0 1px rgba(0,0,0,0.15)",
|
|
@@ -5765,7 +6366,6 @@ var FontFamilyPlugin = ({ disabled = false }) => {
|
|
|
5765
6366
|
"font-family"
|
|
5766
6367
|
);
|
|
5767
6368
|
};
|
|
5768
|
-
var DEFAULT_FONT_SIZE = 15;
|
|
5769
6369
|
var FONT_SIZE_OPTIONS = [
|
|
5770
6370
|
"8",
|
|
5771
6371
|
"9",
|
|
@@ -5901,135 +6501,43 @@ var FontSizePlugin = ({ disabled }) => {
|
|
|
5901
6501
|
"fontsize"
|
|
5902
6502
|
) });
|
|
5903
6503
|
};
|
|
5904
|
-
var VERBATIM_LINK_RE = /^https?:\/\/|^mailto:|^tel:|^#|^\//i;
|
|
5905
|
-
function getLinkValidationMessage(raw) {
|
|
5906
|
-
const trimmed = raw.trim();
|
|
5907
|
-
if (!trimmed) return void 0;
|
|
5908
|
-
if (/\s/.test(trimmed)) return "URL cannot contain spaces";
|
|
5909
|
-
if (!VERBATIM_LINK_RE.test(trimmed) && !trimmed.includes(".")) {
|
|
5910
|
-
return "Enter a valid URL (e.g. example.com)";
|
|
5911
|
-
}
|
|
5912
|
-
return void 0;
|
|
5913
|
-
}
|
|
5914
6504
|
var InsertLinkPlugin = ({
|
|
5915
6505
|
disabled,
|
|
5916
|
-
|
|
5917
|
-
onClose
|
|
6506
|
+
setIsLinkEditMode
|
|
5918
6507
|
}) => {
|
|
5919
6508
|
const [editor] = LexicalComposerContext.useLexicalComposerContext();
|
|
5920
|
-
const [internalOpen, setInternalOpen] = React9.useState(false);
|
|
5921
|
-
const [text, setText] = React9.useState("");
|
|
5922
|
-
const [link$1, setLink] = React9.useState("");
|
|
5923
6509
|
const iconColor = disabled ? "var(--colorNeutralForegroundDisabled, #A6A6A6)" : "#333333";
|
|
5924
|
-
const
|
|
5925
|
-
const isOpen = isControlled ? !!externalOpen && !disabled : internalOpen && !disabled;
|
|
5926
|
-
const linkError = getLinkValidationMessage(link$1);
|
|
5927
|
-
const handleClose = () => {
|
|
5928
|
-
setText("");
|
|
5929
|
-
setLink("");
|
|
5930
|
-
if (isControlled) onClose?.();
|
|
5931
|
-
else setInternalOpen(false);
|
|
5932
|
-
};
|
|
5933
|
-
const insertLink = (text2, link2) => {
|
|
6510
|
+
const insertLink = () => {
|
|
5934
6511
|
if (disabled) return;
|
|
5935
|
-
if (getLinkValidationMessage(link2)) return;
|
|
5936
|
-
const trimmedLink = link2.trim();
|
|
5937
|
-
const href = VERBATIM_LINK_RE.test(trimmedLink) ? trimmedLink : `https://${trimmedLink}`;
|
|
5938
6512
|
editor.update(() => {
|
|
5939
6513
|
const selection = lexical.$getSelection();
|
|
5940
|
-
if (lexical.$isRangeSelection(selection))
|
|
5941
|
-
|
|
5942
|
-
|
|
5943
|
-
|
|
5944
|
-
|
|
6514
|
+
if (!lexical.$isRangeSelection(selection)) return;
|
|
6515
|
+
const node = getSelectedNode2(selection);
|
|
6516
|
+
const linkParent = utils.$findMatchingParent(node, link.$isLinkNode);
|
|
6517
|
+
if (!linkParent && !link.$isLinkNode(node)) {
|
|
6518
|
+
editor.dispatchCommand(link.TOGGLE_LINK_COMMAND, "https://");
|
|
5945
6519
|
}
|
|
5946
6520
|
});
|
|
5947
|
-
|
|
6521
|
+
setIsLinkEditMode(true);
|
|
5948
6522
|
};
|
|
5949
|
-
return /* @__PURE__ */ jsxRuntime.
|
|
5950
|
-
|
|
5951
|
-
|
|
5952
|
-
|
|
5953
|
-
|
|
5954
|
-
|
|
5955
|
-
|
|
5956
|
-
|
|
5957
|
-
|
|
5958
|
-
|
|
5959
|
-
|
|
5960
|
-
|
|
5961
|
-
|
|
5962
|
-
cursor: disabled ? "not-allowed" : "pointer"
|
|
5963
|
-
},
|
|
5964
|
-
onClick: () => {
|
|
5965
|
-
if (disabled) return;
|
|
5966
|
-
setInternalOpen((prev) => !prev);
|
|
5967
|
-
}
|
|
6523
|
+
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
6524
|
+
reactComponents.Button,
|
|
6525
|
+
{
|
|
6526
|
+
size: "small",
|
|
6527
|
+
title: "Add link",
|
|
6528
|
+
disabled,
|
|
6529
|
+
icon: /* @__PURE__ */ jsxRuntime.jsx(reactIcons.LinkAddRegular, { style: { color: iconColor } }),
|
|
6530
|
+
style: {
|
|
6531
|
+
background: "none",
|
|
6532
|
+
border: "none",
|
|
6533
|
+
margin: 2,
|
|
6534
|
+
opacity: disabled ? 0.55 : 1,
|
|
6535
|
+
cursor: disabled ? "not-allowed" : "pointer"
|
|
5968
6536
|
},
|
|
5969
|
-
|
|
5970
|
-
|
|
5971
|
-
|
|
5972
|
-
|
|
5973
|
-
{
|
|
5974
|
-
open: isOpen,
|
|
5975
|
-
onOpenChange: (_, data) => {
|
|
5976
|
-
if (!data.open) handleClose();
|
|
5977
|
-
},
|
|
5978
|
-
children: /* @__PURE__ */ jsxRuntime.jsx(reactComponents.DialogSurface, { style: { maxWidth: "380px" }, children: /* @__PURE__ */ jsxRuntime.jsxs(reactComponents.DialogBody, { children: [
|
|
5979
|
-
/* @__PURE__ */ jsxRuntime.jsx(reactComponents.DialogTitle, { children: "Insert Link" }),
|
|
5980
|
-
/* @__PURE__ */ jsxRuntime.jsx(reactComponents.DialogContent, { children: /* @__PURE__ */ jsxRuntime.jsxs(react.Stack, { tokens: { childrenGap: 10 }, style: { paddingTop: 8 }, children: [
|
|
5981
|
-
/* @__PURE__ */ jsxRuntime.jsx(reactComponents.Field, { label: "Text", orientation: "horizontal", size: "small", children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
5982
|
-
reactComponents.Input,
|
|
5983
|
-
{
|
|
5984
|
-
autoFocus: !disabled,
|
|
5985
|
-
value: text,
|
|
5986
|
-
appearance: "underline",
|
|
5987
|
-
placeholder: "Text",
|
|
5988
|
-
disabled,
|
|
5989
|
-
onChange: (_, v) => setText(v.value)
|
|
5990
|
-
}
|
|
5991
|
-
) }),
|
|
5992
|
-
/* @__PURE__ */ jsxRuntime.jsx(
|
|
5993
|
-
reactComponents.Field,
|
|
5994
|
-
{
|
|
5995
|
-
label: "Link",
|
|
5996
|
-
orientation: "horizontal",
|
|
5997
|
-
size: "small",
|
|
5998
|
-
validationState: linkError ? "error" : "none",
|
|
5999
|
-
validationMessage: linkError,
|
|
6000
|
-
children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
6001
|
-
reactComponents.Input,
|
|
6002
|
-
{
|
|
6003
|
-
value: link$1,
|
|
6004
|
-
appearance: "underline",
|
|
6005
|
-
placeholder: "Link",
|
|
6006
|
-
disabled,
|
|
6007
|
-
onChange: (_, v) => setLink(v.value),
|
|
6008
|
-
onKeyDown: (e) => {
|
|
6009
|
-
if (e.key === "Enter" && text && link$1 && !linkError) insertLink(text, link$1);
|
|
6010
|
-
}
|
|
6011
|
-
}
|
|
6012
|
-
)
|
|
6013
|
-
}
|
|
6014
|
-
)
|
|
6015
|
-
] }) }),
|
|
6016
|
-
/* @__PURE__ */ jsxRuntime.jsxs(reactComponents.DialogActions, { children: [
|
|
6017
|
-
/* @__PURE__ */ jsxRuntime.jsx(
|
|
6018
|
-
reactComponents.Button,
|
|
6019
|
-
{
|
|
6020
|
-
appearance: "primary",
|
|
6021
|
-
size: "small",
|
|
6022
|
-
disabled: disabled || !text || !link$1 || !!linkError,
|
|
6023
|
-
onClick: () => insertLink(text, link$1),
|
|
6024
|
-
children: "Add"
|
|
6025
|
-
}
|
|
6026
|
-
),
|
|
6027
|
-
/* @__PURE__ */ jsxRuntime.jsx(reactComponents.Button, { size: "small", disabled, onClick: handleClose, children: "Cancel" })
|
|
6028
|
-
] })
|
|
6029
|
-
] }) })
|
|
6030
|
-
}
|
|
6031
|
-
)
|
|
6032
|
-
] });
|
|
6537
|
+
onClick: insertLink
|
|
6538
|
+
},
|
|
6539
|
+
"insert-link"
|
|
6540
|
+
);
|
|
6033
6541
|
};
|
|
6034
6542
|
function PageSetupPlugin({ disabled, value, onChange }) {
|
|
6035
6543
|
const sizeLabel = value.size === "pageless" ? "Pageless" : PAGE_SIZE_OPTIONS.find((o) => o.key === value.size)?.label ?? "Pageless";
|
|
@@ -6085,281 +6593,177 @@ function PageSetupPlugin({ disabled, value, onChange }) {
|
|
|
6085
6593
|
}
|
|
6086
6594
|
);
|
|
6087
6595
|
}
|
|
6088
|
-
var
|
|
6089
|
-
var MAX_COLS = 50;
|
|
6090
|
-
var TableItemPlugin = ({
|
|
6091
|
-
disabled,
|
|
6092
|
-
open: externalOpen,
|
|
6093
|
-
onClose
|
|
6094
|
-
}) => {
|
|
6596
|
+
var TableItemPlugin = ({ disabled }) => {
|
|
6095
6597
|
const [editor] = LexicalComposerContext.useLexicalComposerContext();
|
|
6096
6598
|
const [columns, setColumns] = React9.useState("");
|
|
6097
6599
|
const [rows, setRows] = React9.useState("");
|
|
6098
|
-
const [
|
|
6099
|
-
const [rowError, setRowError] = React9.useState("");
|
|
6100
|
-
const [colError, setColError] = React9.useState("");
|
|
6101
|
-
const isControlled = externalOpen !== void 0;
|
|
6102
|
-
const isOpen = isControlled ? !!externalOpen && !disabled : internalOpen && !disabled;
|
|
6600
|
+
const [isOpen, setIsOpen] = React9.useState(false);
|
|
6103
6601
|
const iconColor = disabled ? "var(--colorNeutralForegroundDisabled, #A6A6A6)" : "#333333";
|
|
6104
|
-
const handleClose = () => {
|
|
6105
|
-
setRows("");
|
|
6106
|
-
setColumns("");
|
|
6107
|
-
setRowError("");
|
|
6108
|
-
setColError("");
|
|
6109
|
-
if (isControlled) onClose?.();
|
|
6110
|
-
else setInternalOpen(false);
|
|
6111
|
-
};
|
|
6112
|
-
const onRowsChange = (val) => {
|
|
6113
|
-
const clean = val.replace(/\D/g, "");
|
|
6114
|
-
setRows(clean);
|
|
6115
|
-
const n = Number(clean);
|
|
6116
|
-
if (clean && n > MAX_ROWS) setRowError(`Maximum ${MAX_ROWS} rows allowed`);
|
|
6117
|
-
else setRowError("");
|
|
6118
|
-
};
|
|
6119
|
-
const onColsChange = (val) => {
|
|
6120
|
-
const clean = val.replace(/\D/g, "");
|
|
6121
|
-
setColumns(clean);
|
|
6122
|
-
const n = Number(clean);
|
|
6123
|
-
if (clean && n > MAX_COLS) setColError(`Maximum ${MAX_COLS} columns allowed`);
|
|
6124
|
-
else setColError("");
|
|
6125
|
-
};
|
|
6126
6602
|
const onAddTable = () => {
|
|
6127
6603
|
if (disabled) return;
|
|
6128
6604
|
const row = Number(rows);
|
|
6129
6605
|
const col = Number(columns);
|
|
6130
6606
|
if (!row || !col) return;
|
|
6131
|
-
if (row > MAX_ROWS || col > MAX_COLS) return;
|
|
6132
6607
|
editor.update(() => {
|
|
6133
6608
|
const tableNode = table.$createTableNodeWithDimensions(row, col, true);
|
|
6134
6609
|
utils.$insertNodeToNearestRoot(tableNode);
|
|
6135
6610
|
});
|
|
6136
|
-
|
|
6611
|
+
setRows("");
|
|
6612
|
+
setColumns("");
|
|
6613
|
+
setIsOpen(false);
|
|
6137
6614
|
};
|
|
6138
|
-
|
|
6139
|
-
|
|
6140
|
-
|
|
6141
|
-
|
|
6142
|
-
{
|
|
6143
|
-
|
|
6144
|
-
title: "Add table",
|
|
6145
|
-
disabled,
|
|
6146
|
-
icon: /* @__PURE__ */ jsxRuntime.jsx(reactIcons.TableAddRegular, { style: { color: iconColor } }),
|
|
6147
|
-
style: {
|
|
6148
|
-
background: isOpen && !disabled ? "#ebebeb" : "none",
|
|
6149
|
-
border: "none",
|
|
6150
|
-
margin: 2,
|
|
6151
|
-
opacity: disabled ? 0.55 : 1,
|
|
6152
|
-
cursor: disabled ? "not-allowed" : "pointer"
|
|
6153
|
-
},
|
|
6154
|
-
onClick: () => {
|
|
6155
|
-
if (disabled) return;
|
|
6156
|
-
setRows("");
|
|
6157
|
-
setColumns("");
|
|
6158
|
-
setRowError("");
|
|
6159
|
-
setColError("");
|
|
6160
|
-
setInternalOpen(true);
|
|
6161
|
-
}
|
|
6615
|
+
return /* @__PURE__ */ jsxRuntime.jsxs(
|
|
6616
|
+
reactComponents.Dialog,
|
|
6617
|
+
{
|
|
6618
|
+
open: disabled ? false : isOpen,
|
|
6619
|
+
onOpenChange: (_, data) => {
|
|
6620
|
+
if (!disabled) setIsOpen(data.open);
|
|
6162
6621
|
},
|
|
6163
|
-
|
|
6164
|
-
|
|
6165
|
-
|
|
6166
|
-
|
|
6167
|
-
|
|
6168
|
-
|
|
6169
|
-
|
|
6170
|
-
|
|
6171
|
-
|
|
6172
|
-
|
|
6173
|
-
|
|
6174
|
-
|
|
6175
|
-
|
|
6176
|
-
|
|
6622
|
+
children: [
|
|
6623
|
+
/* @__PURE__ */ jsxRuntime.jsx(reactComponents.DialogTrigger, { disableButtonEnhancement: true, children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
6624
|
+
reactComponents.Button,
|
|
6625
|
+
{
|
|
6626
|
+
size: "small",
|
|
6627
|
+
title: "Add table",
|
|
6628
|
+
disabled,
|
|
6629
|
+
icon: /* @__PURE__ */ jsxRuntime.jsx(reactIcons.TableAddRegular, { style: { color: iconColor } }),
|
|
6630
|
+
style: {
|
|
6631
|
+
background: isOpen && !disabled ? "#ebebeb" : "none",
|
|
6632
|
+
border: "none",
|
|
6633
|
+
margin: 2,
|
|
6634
|
+
opacity: disabled ? 0.55 : 1,
|
|
6635
|
+
cursor: disabled ? "not-allowed" : "pointer"
|
|
6636
|
+
},
|
|
6637
|
+
onClick: () => {
|
|
6638
|
+
if (disabled) return;
|
|
6639
|
+
setIsOpen((prev) => !prev);
|
|
6640
|
+
setRows("");
|
|
6641
|
+
setColumns("");
|
|
6642
|
+
}
|
|
6643
|
+
},
|
|
6644
|
+
"insert-table-nodes"
|
|
6645
|
+
) }),
|
|
6646
|
+
/* @__PURE__ */ jsxRuntime.jsx(reactComponents.DialogSurface, { style: { maxWidth: 300 }, children: /* @__PURE__ */ jsxRuntime.jsxs(reactComponents.DialogBody, { children: [
|
|
6647
|
+
/* @__PURE__ */ jsxRuntime.jsx(reactComponents.DialogTitle, { children: "Insert table" }),
|
|
6648
|
+
/* @__PURE__ */ jsxRuntime.jsx(reactComponents.DialogContent, { children: /* @__PURE__ */ jsxRuntime.jsxs(react.Stack, { tokens: { childrenGap: 8 }, children: [
|
|
6649
|
+
/* @__PURE__ */ jsxRuntime.jsx(reactComponents.Field, { label: "Rows", size: "small", children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
6650
|
+
reactComponents.Input,
|
|
6177
6651
|
{
|
|
6178
|
-
|
|
6179
|
-
|
|
6180
|
-
|
|
6181
|
-
|
|
6182
|
-
|
|
6183
|
-
|
|
6184
|
-
reactComponents.Input,
|
|
6185
|
-
{
|
|
6186
|
-
autoFocus: !disabled,
|
|
6187
|
-
type: "number",
|
|
6188
|
-
min: 1,
|
|
6189
|
-
max: MAX_ROWS,
|
|
6190
|
-
value: rows,
|
|
6191
|
-
placeholder: "Rows",
|
|
6192
|
-
appearance: "underline",
|
|
6193
|
-
disabled,
|
|
6194
|
-
input: { style: { textAlign: "left" } },
|
|
6195
|
-
onChange: (_, v) => onRowsChange(v.value)
|
|
6196
|
-
}
|
|
6197
|
-
)
|
|
6652
|
+
autoFocus: !disabled,
|
|
6653
|
+
value: rows,
|
|
6654
|
+
placeholder: "Rows",
|
|
6655
|
+
appearance: "underline",
|
|
6656
|
+
disabled,
|
|
6657
|
+
onChange: (_, v) => setRows(v.value)
|
|
6198
6658
|
}
|
|
6199
|
-
),
|
|
6200
|
-
/* @__PURE__ */ jsxRuntime.jsx(
|
|
6201
|
-
reactComponents.
|
|
6659
|
+
) }),
|
|
6660
|
+
/* @__PURE__ */ jsxRuntime.jsx(reactComponents.Field, { label: "Columns", size: "small", children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
6661
|
+
reactComponents.Input,
|
|
6202
6662
|
{
|
|
6203
|
-
|
|
6204
|
-
|
|
6205
|
-
|
|
6206
|
-
|
|
6207
|
-
|
|
6208
|
-
children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
6209
|
-
reactComponents.Input,
|
|
6210
|
-
{
|
|
6211
|
-
type: "number",
|
|
6212
|
-
min: 1,
|
|
6213
|
-
max: MAX_COLS,
|
|
6214
|
-
value: columns,
|
|
6215
|
-
placeholder: "Columns",
|
|
6216
|
-
appearance: "underline",
|
|
6217
|
-
disabled,
|
|
6218
|
-
input: { style: { textAlign: "left" } },
|
|
6219
|
-
onChange: (_, v) => onColsChange(v.value)
|
|
6220
|
-
}
|
|
6221
|
-
)
|
|
6663
|
+
value: columns,
|
|
6664
|
+
placeholder: "Columns",
|
|
6665
|
+
appearance: "underline",
|
|
6666
|
+
disabled,
|
|
6667
|
+
onChange: (_, v) => setColumns(v.value)
|
|
6222
6668
|
}
|
|
6223
|
-
)
|
|
6669
|
+
) })
|
|
6224
6670
|
] }) }),
|
|
6225
6671
|
/* @__PURE__ */ jsxRuntime.jsxs(reactComponents.DialogActions, { children: [
|
|
6226
6672
|
/* @__PURE__ */ jsxRuntime.jsx(
|
|
6227
6673
|
reactComponents.Button,
|
|
6228
6674
|
{
|
|
6229
|
-
appearance: "primary",
|
|
6230
6675
|
size: "small",
|
|
6231
|
-
|
|
6676
|
+
appearance: "primary",
|
|
6677
|
+
disabled: disabled || !rows || !columns,
|
|
6232
6678
|
onClick: onAddTable,
|
|
6233
6679
|
children: "Add"
|
|
6234
6680
|
}
|
|
6235
6681
|
),
|
|
6236
|
-
/* @__PURE__ */ jsxRuntime.jsx(reactComponents.Button, { size: "small", disabled, onClick:
|
|
6682
|
+
/* @__PURE__ */ jsxRuntime.jsx(reactComponents.Button, { size: "small", disabled, onClick: () => setIsOpen(false), children: "Cancel" })
|
|
6237
6683
|
] })
|
|
6238
6684
|
] }) })
|
|
6239
|
-
|
|
6240
|
-
|
|
6241
|
-
|
|
6685
|
+
]
|
|
6686
|
+
}
|
|
6687
|
+
);
|
|
6242
6688
|
};
|
|
6243
|
-
|
|
6244
|
-
const trimmed = url.trim();
|
|
6245
|
-
if (/^[\w-]{11}$/.test(trimmed)) return trimmed;
|
|
6246
|
-
const match = /(?:youtu\.be\/|youtube\.com\/(?:watch\?v=|embed\/|v\/|shorts\/|live\/|u\/\w\/))([^#&?]{11})/.exec(trimmed);
|
|
6247
|
-
return match ? match[1] : null;
|
|
6248
|
-
}
|
|
6249
|
-
var YoutubeUploadPlugin = ({
|
|
6250
|
-
disabled,
|
|
6251
|
-
open: externalOpen,
|
|
6252
|
-
onClose
|
|
6253
|
-
}) => {
|
|
6689
|
+
var YoutubeUploadPlugin = ({ disabled }) => {
|
|
6254
6690
|
const [url, setURL] = React9.useState("");
|
|
6255
|
-
const [
|
|
6256
|
-
const [internalOpen, setInternalOpen] = React9.useState(false);
|
|
6691
|
+
const [isOpen, setIsOpen] = React9.useState(false);
|
|
6257
6692
|
const [editor] = LexicalComposerContext.useLexicalComposerContext();
|
|
6258
6693
|
const iconColor = disabled ? "var(--colorNeutralForegroundDisabled, #A6A6A6)" : "#424242";
|
|
6259
|
-
const isControlled = externalOpen !== void 0;
|
|
6260
|
-
const isOpen = isControlled ? !!externalOpen && !disabled : internalOpen && !disabled;
|
|
6261
|
-
const handleClose = () => {
|
|
6262
|
-
setURL("");
|
|
6263
|
-
setUrlError("");
|
|
6264
|
-
if (isControlled) onClose?.();
|
|
6265
|
-
else setInternalOpen(false);
|
|
6266
|
-
};
|
|
6267
6694
|
const onHandleEmbeded = () => {
|
|
6268
6695
|
if (disabled) return;
|
|
6269
6696
|
if (!url) return;
|
|
6270
|
-
const
|
|
6271
|
-
|
|
6272
|
-
|
|
6273
|
-
return;
|
|
6274
|
-
}
|
|
6275
|
-
setUrlError("");
|
|
6697
|
+
const match = /^.*(youtu\.be\/|v\/|u\/\w\/|embed\/|watch\?v=|&v=)([^#&?]*).*/.exec(url);
|
|
6698
|
+
const id = match && match[2]?.length === 11 ? match[2] : null;
|
|
6699
|
+
if (!id) return;
|
|
6276
6700
|
editor.update(() => {
|
|
6277
6701
|
const node = $createYouTubeNode(id);
|
|
6278
6702
|
lexical.$insertNodes([node]);
|
|
6279
6703
|
});
|
|
6280
|
-
|
|
6704
|
+
setURL("");
|
|
6705
|
+
setIsOpen(false);
|
|
6281
6706
|
};
|
|
6282
|
-
return /* @__PURE__ */ jsxRuntime.jsxs(
|
|
6283
|
-
|
|
6284
|
-
|
|
6285
|
-
|
|
6286
|
-
|
|
6287
|
-
|
|
6288
|
-
disabled,
|
|
6289
|
-
icon: /* @__PURE__ */ jsxRuntime.jsx(reactIcons.VideoClipRegular, { style: { color: iconColor } }),
|
|
6290
|
-
style: {
|
|
6291
|
-
background: isOpen && !disabled ? "#ebebeb" : "none",
|
|
6292
|
-
border: "none",
|
|
6293
|
-
margin: 2,
|
|
6294
|
-
opacity: disabled ? 0.55 : 1,
|
|
6295
|
-
cursor: disabled ? "not-allowed" : "pointer"
|
|
6296
|
-
},
|
|
6297
|
-
onClick: () => {
|
|
6298
|
-
if (disabled) return;
|
|
6299
|
-
setURL("");
|
|
6300
|
-
setUrlError("");
|
|
6301
|
-
setInternalOpen(true);
|
|
6302
|
-
}
|
|
6707
|
+
return /* @__PURE__ */ jsxRuntime.jsxs(
|
|
6708
|
+
reactComponents.Dialog,
|
|
6709
|
+
{
|
|
6710
|
+
open: disabled ? false : isOpen,
|
|
6711
|
+
onOpenChange: (_, data) => {
|
|
6712
|
+
if (!disabled) setIsOpen(data.open);
|
|
6303
6713
|
},
|
|
6304
|
-
|
|
6305
|
-
|
|
6306
|
-
|
|
6307
|
-
|
|
6308
|
-
|
|
6309
|
-
|
|
6310
|
-
|
|
6311
|
-
|
|
6312
|
-
|
|
6313
|
-
|
|
6314
|
-
|
|
6315
|
-
|
|
6316
|
-
|
|
6317
|
-
|
|
6318
|
-
|
|
6319
|
-
|
|
6320
|
-
|
|
6321
|
-
|
|
6322
|
-
|
|
6323
|
-
|
|
6324
|
-
|
|
6325
|
-
|
|
6326
|
-
|
|
6327
|
-
|
|
6328
|
-
|
|
6329
|
-
|
|
6330
|
-
|
|
6331
|
-
|
|
6332
|
-
|
|
6333
|
-
|
|
6334
|
-
|
|
6335
|
-
|
|
6336
|
-
|
|
6337
|
-
|
|
6338
|
-
|
|
6339
|
-
|
|
6340
|
-
)
|
|
6341
|
-
}
|
|
6342
|
-
),
|
|
6343
|
-
/* @__PURE__ */ jsxRuntime.jsx("div", { style: { fontSize: 11, color: "#94a3b8", lineHeight: 1.5 }, children: "Supports: youtube.com/watch?v=\u2026, youtu.be/\u2026, /shorts/\u2026, /live/\u2026" })
|
|
6344
|
-
] }) }),
|
|
6714
|
+
children: [
|
|
6715
|
+
/* @__PURE__ */ jsxRuntime.jsx(reactComponents.DialogTrigger, { disableButtonEnhancement: true, children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
6716
|
+
reactComponents.Button,
|
|
6717
|
+
{
|
|
6718
|
+
title: "Add youtube URL",
|
|
6719
|
+
size: "small",
|
|
6720
|
+
disabled,
|
|
6721
|
+
icon: /* @__PURE__ */ jsxRuntime.jsx(reactIcons.VideoClipRegular, { style: { color: iconColor } }),
|
|
6722
|
+
style: {
|
|
6723
|
+
background: isOpen && !disabled ? "#ebebeb" : "none",
|
|
6724
|
+
border: "none",
|
|
6725
|
+
margin: 2,
|
|
6726
|
+
opacity: disabled ? 0.55 : 1,
|
|
6727
|
+
cursor: disabled ? "not-allowed" : "pointer"
|
|
6728
|
+
},
|
|
6729
|
+
onClick: () => {
|
|
6730
|
+
if (disabled) return;
|
|
6731
|
+
setIsOpen((prev) => !prev);
|
|
6732
|
+
setURL("");
|
|
6733
|
+
}
|
|
6734
|
+
},
|
|
6735
|
+
"upload-video"
|
|
6736
|
+
) }),
|
|
6737
|
+
/* @__PURE__ */ jsxRuntime.jsx(reactComponents.DialogSurface, { style: { maxWidth: 320 }, children: /* @__PURE__ */ jsxRuntime.jsxs(reactComponents.DialogBody, { children: [
|
|
6738
|
+
/* @__PURE__ */ jsxRuntime.jsx(reactComponents.DialogTitle, { children: "Embed YouTube video" }),
|
|
6739
|
+
/* @__PURE__ */ jsxRuntime.jsx(reactComponents.DialogContent, { children: /* @__PURE__ */ jsxRuntime.jsx(react.Stack, { tokens: { childrenGap: 8 }, children: /* @__PURE__ */ jsxRuntime.jsx(reactComponents.Field, { label: "URL", size: "small", children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
6740
|
+
reactComponents.Input,
|
|
6741
|
+
{
|
|
6742
|
+
autoFocus: !disabled,
|
|
6743
|
+
disabled,
|
|
6744
|
+
value: url,
|
|
6745
|
+
appearance: "underline",
|
|
6746
|
+
placeholder: "Add Youtube video URL",
|
|
6747
|
+
onChange: (_, v) => setURL(v.value)
|
|
6748
|
+
}
|
|
6749
|
+
) }) }) }),
|
|
6345
6750
|
/* @__PURE__ */ jsxRuntime.jsxs(reactComponents.DialogActions, { children: [
|
|
6346
|
-
/* @__PURE__ */ jsxRuntime.jsx(
|
|
6347
|
-
|
|
6348
|
-
{
|
|
6349
|
-
appearance: "primary",
|
|
6350
|
-
size: "small",
|
|
6351
|
-
disabled: disabled || !url,
|
|
6352
|
-
onClick: onHandleEmbeded,
|
|
6353
|
-
children: "Add"
|
|
6354
|
-
}
|
|
6355
|
-
),
|
|
6356
|
-
/* @__PURE__ */ jsxRuntime.jsx(reactComponents.Button, { size: "small", disabled, onClick: handleClose, children: "Cancel" })
|
|
6751
|
+
/* @__PURE__ */ jsxRuntime.jsx(reactComponents.Button, { size: "small", disabled: disabled || !url, onClick: onHandleEmbeded, children: "Add" }),
|
|
6752
|
+
/* @__PURE__ */ jsxRuntime.jsx(reactComponents.Button, { size: "small", disabled, onClick: () => setIsOpen(false), children: "Cancel" })
|
|
6357
6753
|
] })
|
|
6358
6754
|
] }) })
|
|
6359
|
-
|
|
6360
|
-
|
|
6361
|
-
|
|
6755
|
+
]
|
|
6756
|
+
}
|
|
6757
|
+
);
|
|
6362
6758
|
};
|
|
6759
|
+
var TextAlphaListLtrFilled = ({ style }) => /* @__PURE__ */ jsxRuntime.jsxs("svg", { width: "1em", height: "1em", viewBox: "0 0 20 20", fill: "currentColor", "aria-hidden": "true", style, children: [
|
|
6760
|
+
/* @__PURE__ */ jsxRuntime.jsx("path", { d: "M8.75 4a.75.75 0 1 0 0 1.5h7.5a.75.75 0 0 0 0-1.5h-7.5Z" }),
|
|
6761
|
+
/* @__PURE__ */ jsxRuntime.jsx("path", { d: "M8.75 9a.75.75 0 1 0 0 1.5h7.5a.75.75 0 0 0 0-1.5h-7.5Z" }),
|
|
6762
|
+
/* @__PURE__ */ jsxRuntime.jsx("path", { d: "M8 14.75c0-.41.34-.75.75-.75h7.5a.75.75 0 0 1 0 1.5h-7.5a.75.75 0 0 1-.75-.75Z" }),
|
|
6763
|
+
/* @__PURE__ */ jsxRuntime.jsx("text", { x: "3.5", y: "6", fontSize: "5.5", fontWeight: "bold", textAnchor: "middle", children: "a" }),
|
|
6764
|
+
/* @__PURE__ */ jsxRuntime.jsx("text", { x: "3.5", y: "11", fontSize: "5.5", fontWeight: "bold", textAnchor: "middle", children: "b" }),
|
|
6765
|
+
/* @__PURE__ */ jsxRuntime.jsx("text", { x: "3.5", y: "16", fontSize: "5.5", fontWeight: "bold", textAnchor: "middle", children: "c" })
|
|
6766
|
+
] });
|
|
6363
6767
|
var useStyles4 = reactComponents.makeStyles({
|
|
6364
6768
|
dropdown: {
|
|
6365
6769
|
minInlineSize: "90px",
|
|
@@ -6377,25 +6781,42 @@ var ALLOWED_TOKENS = {
|
|
|
6377
6781
|
Bold: true,
|
|
6378
6782
|
Italic: true,
|
|
6379
6783
|
Underline: true,
|
|
6784
|
+
Strikethrough: true,
|
|
6785
|
+
Subscript: true,
|
|
6786
|
+
Superscript: true,
|
|
6787
|
+
Highlight: true,
|
|
6788
|
+
Uppercase: true,
|
|
6789
|
+
Lowercase: true,
|
|
6790
|
+
Capitalize: true,
|
|
6791
|
+
BulletList: true,
|
|
6792
|
+
NumberList: true,
|
|
6793
|
+
AlphabeticalList: true,
|
|
6794
|
+
Quote: true,
|
|
6795
|
+
PageBreak: true,
|
|
6796
|
+
H1: true,
|
|
6797
|
+
H2: true,
|
|
6798
|
+
H3: true,
|
|
6799
|
+
H4: true,
|
|
6800
|
+
H5: true,
|
|
6801
|
+
H6: true,
|
|
6380
6802
|
ColorPicker: true,
|
|
6381
6803
|
Link: true,
|
|
6382
6804
|
Table: true,
|
|
6383
6805
|
Image: true,
|
|
6384
6806
|
InlineImage: true,
|
|
6385
6807
|
Youtube: true,
|
|
6386
|
-
Insert: true,
|
|
6387
|
-
Heading: true,
|
|
6388
6808
|
FontFamily: true,
|
|
6389
6809
|
FontSize: true,
|
|
6810
|
+
Align: true,
|
|
6811
|
+
Heading: true,
|
|
6390
6812
|
Decorators: true,
|
|
6391
6813
|
CodeBlock: true,
|
|
6392
|
-
Align: true,
|
|
6393
6814
|
PageSetup: true
|
|
6394
6815
|
};
|
|
6395
6816
|
function sanitizePluginGroups(groups) {
|
|
6396
|
-
if (!groups || groups.length === 0) return [];
|
|
6817
|
+
if (!Array.isArray(groups) || groups.length === 0) return [];
|
|
6397
6818
|
return groups.map(
|
|
6398
|
-
(g) => (g
|
|
6819
|
+
(g) => (Array.isArray(g) ? g : []).map((t) => typeof t === "string" ? t.trim() : "").filter((t) => ALLOWED_TOKENS[t] === true)
|
|
6399
6820
|
).filter((g) => g.length > 0);
|
|
6400
6821
|
}
|
|
6401
6822
|
var ToolBarPlugins = (props) => {
|
|
@@ -6415,9 +6836,9 @@ var ToolBarPlugins = (props) => {
|
|
|
6415
6836
|
const [isLowercase, setIsLowercase] = React9.useState(false);
|
|
6416
6837
|
const [isCapitalize, setIsCapitalize] = React9.useState(false);
|
|
6417
6838
|
const [alignment, setAlignment] = React9.useState("left");
|
|
6418
|
-
const [
|
|
6419
|
-
const
|
|
6420
|
-
const presetGroups = getToolbarGroupsByLevel(props.level);
|
|
6839
|
+
const [decoratorOpen, setDecoratorOpen] = React9.useState(false);
|
|
6840
|
+
const decoratorSelectingRef = React9__namespace.default.useRef(false);
|
|
6841
|
+
const presetGroups = props.customToolbar ?? getToolbarGroupsByLevel(props.level);
|
|
6421
6842
|
const pluginGroups = React9.useMemo(() => sanitizePluginGroups(presetGroups), [presetGroups]);
|
|
6422
6843
|
const updateToolbarPlugins = () => {
|
|
6423
6844
|
const selection = lexical.$getSelection();
|
|
@@ -6459,6 +6880,10 @@ var ToolBarPlugins = (props) => {
|
|
|
6459
6880
|
setSelectNodeType("paragraph");
|
|
6460
6881
|
return;
|
|
6461
6882
|
}
|
|
6883
|
+
if ($isAlphaListNode(element)) {
|
|
6884
|
+
setSelectNodeType("alpha");
|
|
6885
|
+
return;
|
|
6886
|
+
}
|
|
6462
6887
|
if (list.$isListNode(element)) {
|
|
6463
6888
|
const parentList = utils.$getNearestNodeOfType(anchorNode, list.ListNode);
|
|
6464
6889
|
const type2 = parentList ? parentList.getTag() : element.getTag();
|
|
@@ -6470,23 +6895,15 @@ var ToolBarPlugins = (props) => {
|
|
|
6470
6895
|
["paragraph", "h1", "h2", "h3", "h4", "h5", "h6", "ul", "ol", "quote", "code"].includes(type) ? type : "paragraph"
|
|
6471
6896
|
);
|
|
6472
6897
|
};
|
|
6473
|
-
const applyToBlock = React9__namespace.default.useCallback(
|
|
6474
|
-
(fn) => {
|
|
6475
|
-
editor.update(() => {
|
|
6476
|
-
const saved = lastSelectionRef.current;
|
|
6477
|
-
if (saved) lexical.$setSelection(saved.clone());
|
|
6478
|
-
const sel = lexical.$getSelection();
|
|
6479
|
-
if (lexical.$isRangeSelection(sel)) fn(sel);
|
|
6480
|
-
});
|
|
6481
|
-
},
|
|
6482
|
-
[editor]
|
|
6483
|
-
);
|
|
6484
6898
|
const formatQuote = () => {
|
|
6485
|
-
|
|
6899
|
+
editor.update(() => {
|
|
6900
|
+
const selection$1 = lexical.$getSelection();
|
|
6901
|
+
if (!lexical.$isRangeSelection(selection$1)) return;
|
|
6486
6902
|
if (selectNodeType === "quote") {
|
|
6487
|
-
|
|
6903
|
+
formatParagraph(editor);
|
|
6488
6904
|
} else {
|
|
6489
|
-
|
|
6905
|
+
$splitBlocksAtLineBreaks(selection$1);
|
|
6906
|
+
selection.$setBlocksType(lexical.$getSelection(), () => richText.$createQuoteNode());
|
|
6490
6907
|
}
|
|
6491
6908
|
});
|
|
6492
6909
|
};
|
|
@@ -6503,8 +6920,6 @@ var ToolBarPlugins = (props) => {
|
|
|
6503
6920
|
editor.registerCommand(
|
|
6504
6921
|
lexical.SELECTION_CHANGE_COMMAND,
|
|
6505
6922
|
() => {
|
|
6506
|
-
const sel = lexical.$getSelection();
|
|
6507
|
-
if (lexical.$isRangeSelection(sel)) lastSelectionRef.current = sel.clone();
|
|
6508
6923
|
updateToolbarPlugins();
|
|
6509
6924
|
return false;
|
|
6510
6925
|
},
|
|
@@ -6536,52 +6951,16 @@ var ToolBarPlugins = (props) => {
|
|
|
6536
6951
|
editor.dispatchCommand(lexical.FORMAT_TEXT_COMMAND, "highlight");
|
|
6537
6952
|
break;
|
|
6538
6953
|
case "leftAlign" /* LeftAlign */:
|
|
6539
|
-
|
|
6540
|
-
const seen = /* @__PURE__ */ new Set();
|
|
6541
|
-
sel.getNodes().forEach((n) => {
|
|
6542
|
-
const t = n.getTopLevelElementOrThrow();
|
|
6543
|
-
if (!seen.has(t.getKey())) {
|
|
6544
|
-
seen.add(t.getKey());
|
|
6545
|
-
t.setFormat("left");
|
|
6546
|
-
}
|
|
6547
|
-
});
|
|
6548
|
-
});
|
|
6954
|
+
applyAlignmentWithSplit("left");
|
|
6549
6955
|
break;
|
|
6550
6956
|
case "rightAlign" /* RightAlign */:
|
|
6551
|
-
|
|
6552
|
-
const seen = /* @__PURE__ */ new Set();
|
|
6553
|
-
sel.getNodes().forEach((n) => {
|
|
6554
|
-
const t = n.getTopLevelElementOrThrow();
|
|
6555
|
-
if (!seen.has(t.getKey())) {
|
|
6556
|
-
seen.add(t.getKey());
|
|
6557
|
-
t.setFormat("right");
|
|
6558
|
-
}
|
|
6559
|
-
});
|
|
6560
|
-
});
|
|
6957
|
+
applyAlignmentWithSplit("right");
|
|
6561
6958
|
break;
|
|
6562
6959
|
case "centerAlign" /* CenterAlign */:
|
|
6563
|
-
|
|
6564
|
-
const seen = /* @__PURE__ */ new Set();
|
|
6565
|
-
sel.getNodes().forEach((n) => {
|
|
6566
|
-
const t = n.getTopLevelElementOrThrow();
|
|
6567
|
-
if (!seen.has(t.getKey())) {
|
|
6568
|
-
seen.add(t.getKey());
|
|
6569
|
-
t.setFormat("center");
|
|
6570
|
-
}
|
|
6571
|
-
});
|
|
6572
|
-
});
|
|
6960
|
+
applyAlignmentWithSplit("center");
|
|
6573
6961
|
break;
|
|
6574
6962
|
case "justifyAlign" /* JustifyAlign */:
|
|
6575
|
-
|
|
6576
|
-
const seen = /* @__PURE__ */ new Set();
|
|
6577
|
-
sel.getNodes().forEach((n) => {
|
|
6578
|
-
const t = n.getTopLevelElementOrThrow();
|
|
6579
|
-
if (!seen.has(t.getKey())) {
|
|
6580
|
-
seen.add(t.getKey());
|
|
6581
|
-
t.setFormat("justify");
|
|
6582
|
-
}
|
|
6583
|
-
});
|
|
6584
|
-
});
|
|
6963
|
+
applyAlignmentWithSplit("justify");
|
|
6585
6964
|
break;
|
|
6586
6965
|
case "undo" /* Undo */:
|
|
6587
6966
|
editor.dispatchCommand(lexical.UNDO_COMMAND, void 0);
|
|
@@ -6600,9 +6979,32 @@ var ToolBarPlugins = (props) => {
|
|
|
6600
6979
|
break;
|
|
6601
6980
|
}
|
|
6602
6981
|
};
|
|
6982
|
+
const applyAlignmentWithSplit = (formatType) => {
|
|
6983
|
+
editor.update(() => {
|
|
6984
|
+
const selection = lexical.$getSelection();
|
|
6985
|
+
if (!lexical.$isRangeSelection(selection)) return;
|
|
6986
|
+
$splitBlocksAtLineBreaks(selection);
|
|
6987
|
+
const sel = lexical.$getSelection();
|
|
6988
|
+
if (lexical.$isRangeSelection(sel)) {
|
|
6989
|
+
$splitBlockAtPartialSelection(sel);
|
|
6990
|
+
}
|
|
6991
|
+
});
|
|
6992
|
+
editor.dispatchCommand(lexical.FORMAT_ELEMENT_COMMAND, formatType);
|
|
6993
|
+
};
|
|
6603
6994
|
const updateHeading = (heading) => {
|
|
6604
|
-
|
|
6605
|
-
selection
|
|
6995
|
+
editor.update(() => {
|
|
6996
|
+
const selection$1 = lexical.$getSelection();
|
|
6997
|
+
if (lexical.$isRangeSelection(selection$1)) {
|
|
6998
|
+
$splitBlocksAtLineBreaks(selection$1);
|
|
6999
|
+
const sel = lexical.$getSelection();
|
|
7000
|
+
if (lexical.$isRangeSelection(sel)) {
|
|
7001
|
+
$splitBlockAtPartialSelection(sel);
|
|
7002
|
+
}
|
|
7003
|
+
selection.$setBlocksType(lexical.$getSelection(), () => richText.$createHeadingNode(heading));
|
|
7004
|
+
}
|
|
7005
|
+
});
|
|
7006
|
+
editor.getEditorState().read(() => {
|
|
7007
|
+
updateToolbarPlugins();
|
|
6606
7008
|
});
|
|
6607
7009
|
};
|
|
6608
7010
|
const renderToken = (token, groupIndex, tokenIndex) => {
|
|
@@ -6614,7 +7016,6 @@ var ToolBarPlugins = (props) => {
|
|
|
6614
7016
|
const brand = palette.themePrimary;
|
|
6615
7017
|
const brandHover = palette.themeDarkAlt ?? brand;
|
|
6616
7018
|
const brandPressed = palette.themeDark ?? brand;
|
|
6617
|
-
palette.white;
|
|
6618
7019
|
const bgHover = palette.neutralLighter;
|
|
6619
7020
|
const bgPressed = palette.neutralLight;
|
|
6620
7021
|
const bgActive = palette.neutralLighterAlt ?? palette.neutralLighter;
|
|
@@ -6661,13 +7062,14 @@ var ToolBarPlugins = (props) => {
|
|
|
6661
7062
|
marginRight: 8,
|
|
6662
7063
|
verticalAlign: "middle"
|
|
6663
7064
|
};
|
|
6664
|
-
const isDisabled = !isEditable || !!props.readOnly;
|
|
6665
7065
|
switch (token) {
|
|
6666
7066
|
case "Bold":
|
|
6667
7067
|
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
6668
7068
|
reactComponents.Button,
|
|
6669
7069
|
{
|
|
6670
7070
|
size: "small",
|
|
7071
|
+
"aria-label": "Bold",
|
|
7072
|
+
"aria-pressed": isBold,
|
|
6671
7073
|
disabled: !isEditable || props.readOnly,
|
|
6672
7074
|
icon: /* @__PURE__ */ jsxRuntime.jsx(reactIcons.TextBold24Regular, { style: { color: getIconColor(isBold) } }),
|
|
6673
7075
|
style: getButtonStyle(isBold),
|
|
@@ -6680,6 +7082,8 @@ var ToolBarPlugins = (props) => {
|
|
|
6680
7082
|
reactComponents.Button,
|
|
6681
7083
|
{
|
|
6682
7084
|
size: "small",
|
|
7085
|
+
"aria-label": "Italic",
|
|
7086
|
+
"aria-pressed": isItalic,
|
|
6683
7087
|
disabled: !isEditable || props.readOnly,
|
|
6684
7088
|
icon: /* @__PURE__ */ jsxRuntime.jsx(reactIcons.TextItalicFilled, { style: { color: getIconColor(isItalic) } }),
|
|
6685
7089
|
style: getButtonStyle(isItalic),
|
|
@@ -6692,6 +7096,8 @@ var ToolBarPlugins = (props) => {
|
|
|
6692
7096
|
reactComponents.Button,
|
|
6693
7097
|
{
|
|
6694
7098
|
size: "small",
|
|
7099
|
+
"aria-label": "Underline",
|
|
7100
|
+
"aria-pressed": isUnderline,
|
|
6695
7101
|
disabled: !isEditable || props.readOnly,
|
|
6696
7102
|
icon: /* @__PURE__ */ jsxRuntime.jsx(reactIcons.TextUnderlineFilled, { style: { color: getIconColor(isUnderline) } }),
|
|
6697
7103
|
style: getButtonStyle(isUnderline),
|
|
@@ -6702,7 +7108,14 @@ var ToolBarPlugins = (props) => {
|
|
|
6702
7108
|
case "ColorPicker":
|
|
6703
7109
|
return /* @__PURE__ */ jsxRuntime.jsx(ColorPickerPlugin, { disabled: !isEditable || props.readOnly }, key);
|
|
6704
7110
|
case "Link":
|
|
6705
|
-
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
7111
|
+
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
7112
|
+
InsertLinkPlugin,
|
|
7113
|
+
{
|
|
7114
|
+
disabled: !isEditable || props.readOnly,
|
|
7115
|
+
setIsLinkEditMode: props.setIsLinkEditMode
|
|
7116
|
+
},
|
|
7117
|
+
key
|
|
7118
|
+
);
|
|
6706
7119
|
case "Table":
|
|
6707
7120
|
return /* @__PURE__ */ jsxRuntime.jsx(TableItemPlugin, { disabled: !isEditable || props.readOnly }, key);
|
|
6708
7121
|
case "Image":
|
|
@@ -6710,7 +7123,9 @@ var ToolBarPlugins = (props) => {
|
|
|
6710
7123
|
InsertImageDialog,
|
|
6711
7124
|
{
|
|
6712
7125
|
activeEditor: editor,
|
|
6713
|
-
disabled: !isEditable || props.readOnly
|
|
7126
|
+
disabled: !isEditable || props.readOnly,
|
|
7127
|
+
maxImageSizeMB: props.maxImageSizeMB,
|
|
7128
|
+
validationMessages: props.validationMessages
|
|
6714
7129
|
},
|
|
6715
7130
|
key
|
|
6716
7131
|
);
|
|
@@ -6719,139 +7134,405 @@ var ToolBarPlugins = (props) => {
|
|
|
6719
7134
|
InsertInlineImageDialog,
|
|
6720
7135
|
{
|
|
6721
7136
|
activeEditor: editor,
|
|
6722
|
-
disabled: !isEditable || props.readOnly
|
|
7137
|
+
disabled: !isEditable || props.readOnly,
|
|
7138
|
+
maxImageSizeMB: props.maxImageSizeMB,
|
|
7139
|
+
validationMessages: props.validationMessages
|
|
6723
7140
|
},
|
|
6724
7141
|
key
|
|
6725
7142
|
);
|
|
6726
7143
|
case "Youtube":
|
|
6727
7144
|
return /* @__PURE__ */ jsxRuntime.jsx(YoutubeUploadPlugin, { disabled: !isEditable || props.readOnly }, key);
|
|
6728
|
-
case "Insert": {
|
|
6729
|
-
const menuIconColor = isDisabled ? fgDisabled : fg;
|
|
6730
|
-
return /* @__PURE__ */ jsxRuntime.jsxs(React9__namespace.default.Fragment, { children: [
|
|
6731
|
-
/* @__PURE__ */ jsxRuntime.jsxs(reactComponents.Menu, { children: [
|
|
6732
|
-
/* @__PURE__ */ jsxRuntime.jsx(reactComponents.MenuTrigger, { disableButtonEnhancement: true, children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
6733
|
-
reactComponents.Button,
|
|
6734
|
-
{
|
|
6735
|
-
size: "small",
|
|
6736
|
-
disabled: isDisabled,
|
|
6737
|
-
icon: /* @__PURE__ */ jsxRuntime.jsx(reactIcons.AddRegular, { style: { color: menuIconColor } }),
|
|
6738
|
-
style: {
|
|
6739
|
-
...getButtonStyle(false),
|
|
6740
|
-
gap: 4,
|
|
6741
|
-
paddingInline: 8
|
|
6742
|
-
},
|
|
6743
|
-
children: "Insert"
|
|
6744
|
-
}
|
|
6745
|
-
) }),
|
|
6746
|
-
/* @__PURE__ */ jsxRuntime.jsx(reactComponents.MenuPopover, { children: /* @__PURE__ */ jsxRuntime.jsxs(reactComponents.MenuList, { children: [
|
|
6747
|
-
/* @__PURE__ */ jsxRuntime.jsx(
|
|
6748
|
-
reactComponents.MenuItem,
|
|
6749
|
-
{
|
|
6750
|
-
icon: /* @__PURE__ */ jsxRuntime.jsx(reactIcons.TableAddRegular, { style: { color: menuIconColor } }),
|
|
6751
|
-
onClick: () => !isDisabled && setActiveInsertDialog("table"),
|
|
6752
|
-
children: "Table"
|
|
6753
|
-
}
|
|
6754
|
-
),
|
|
6755
|
-
/* @__PURE__ */ jsxRuntime.jsx(
|
|
6756
|
-
reactComponents.MenuItem,
|
|
6757
|
-
{
|
|
6758
|
-
icon: /* @__PURE__ */ jsxRuntime.jsx(reactIcons.ImageAddRegular, { style: { color: menuIconColor } }),
|
|
6759
|
-
onClick: () => !isDisabled && setActiveInsertDialog("image"),
|
|
6760
|
-
children: "Image"
|
|
6761
|
-
}
|
|
6762
|
-
),
|
|
6763
|
-
/* @__PURE__ */ jsxRuntime.jsx(
|
|
6764
|
-
reactComponents.MenuItem,
|
|
6765
|
-
{
|
|
6766
|
-
icon: /* @__PURE__ */ jsxRuntime.jsx(reactIcons.ImageEditRegular, { style: { color: menuIconColor } }),
|
|
6767
|
-
onClick: () => !isDisabled && setActiveInsertDialog("inlineImage"),
|
|
6768
|
-
children: "Inline Image"
|
|
6769
|
-
}
|
|
6770
|
-
),
|
|
6771
|
-
/* @__PURE__ */ jsxRuntime.jsx(
|
|
6772
|
-
reactComponents.MenuItem,
|
|
6773
|
-
{
|
|
6774
|
-
icon: /* @__PURE__ */ jsxRuntime.jsx(reactIcons.VideoClipRegular, { style: { color: menuIconColor } }),
|
|
6775
|
-
onClick: () => !isDisabled && setActiveInsertDialog("youtube"),
|
|
6776
|
-
children: "YouTube"
|
|
6777
|
-
}
|
|
6778
|
-
)
|
|
6779
|
-
] }) })
|
|
6780
|
-
] }),
|
|
6781
|
-
/* @__PURE__ */ jsxRuntime.jsx(
|
|
6782
|
-
TableItemPlugin,
|
|
6783
|
-
{
|
|
6784
|
-
disabled: isDisabled,
|
|
6785
|
-
open: activeInsertDialog === "table",
|
|
6786
|
-
onClose: () => setActiveInsertDialog(null)
|
|
6787
|
-
}
|
|
6788
|
-
),
|
|
6789
|
-
/* @__PURE__ */ jsxRuntime.jsx(
|
|
6790
|
-
InsertImageDialog,
|
|
6791
|
-
{
|
|
6792
|
-
activeEditor: editor,
|
|
6793
|
-
disabled: isDisabled,
|
|
6794
|
-
open: activeInsertDialog === "image",
|
|
6795
|
-
onClose: () => setActiveInsertDialog(null)
|
|
6796
|
-
}
|
|
6797
|
-
),
|
|
6798
|
-
/* @__PURE__ */ jsxRuntime.jsx(
|
|
6799
|
-
InsertInlineImageDialog,
|
|
6800
|
-
{
|
|
6801
|
-
activeEditor: editor,
|
|
6802
|
-
disabled: isDisabled,
|
|
6803
|
-
open: activeInsertDialog === "inlineImage",
|
|
6804
|
-
onClose: () => setActiveInsertDialog(null)
|
|
6805
|
-
}
|
|
6806
|
-
),
|
|
6807
|
-
/* @__PURE__ */ jsxRuntime.jsx(
|
|
6808
|
-
YoutubeUploadPlugin,
|
|
6809
|
-
{
|
|
6810
|
-
disabled: isDisabled,
|
|
6811
|
-
open: activeInsertDialog === "youtube",
|
|
6812
|
-
onClose: () => setActiveInsertDialog(null)
|
|
6813
|
-
}
|
|
6814
|
-
)
|
|
6815
|
-
] }, key);
|
|
6816
|
-
}
|
|
6817
7145
|
case "Heading": {
|
|
6818
7146
|
const headingLabel = selectNodeType === "paragraph" ? "Normal" : HEADING_OPTION.find((h) => h.key === selectNodeType)?.text ?? selectNodeType;
|
|
6819
7147
|
return /* @__PURE__ */ jsxRuntime.jsxs(
|
|
6820
7148
|
reactComponents.Dropdown,
|
|
6821
7149
|
{
|
|
6822
|
-
title: "Add heading",
|
|
6823
|
-
id: `heading-option-${groupIndex}`,
|
|
6824
|
-
placeholder: "Format",
|
|
6825
|
-
disabled: !isEditable,
|
|
6826
|
-
style: { minWidth: "100px" },
|
|
6827
|
-
className: styles.dropdown,
|
|
6828
|
-
value: headingLabel,
|
|
6829
|
-
selectedOptions: [selectNodeType],
|
|
6830
|
-
onOptionSelect: (_, data) => {
|
|
6831
|
-
const val = data.optionValue;
|
|
6832
|
-
if (!val) return;
|
|
6833
|
-
if (val === "paragraph") {
|
|
6834
|
-
|
|
7150
|
+
title: "Add heading",
|
|
7151
|
+
id: `heading-option-${groupIndex}`,
|
|
7152
|
+
placeholder: "Format",
|
|
7153
|
+
disabled: !isEditable,
|
|
7154
|
+
style: { minWidth: "100px" },
|
|
7155
|
+
className: styles.dropdown,
|
|
7156
|
+
value: headingLabel,
|
|
7157
|
+
selectedOptions: [selectNodeType],
|
|
7158
|
+
onOptionSelect: (_, data) => {
|
|
7159
|
+
const val = data.optionValue;
|
|
7160
|
+
if (!val) return;
|
|
7161
|
+
if (val === "paragraph") {
|
|
7162
|
+
formatParagraph(editor);
|
|
7163
|
+
setSelectNodeType("paragraph");
|
|
7164
|
+
} else {
|
|
7165
|
+
updateHeading(val);
|
|
7166
|
+
setSelectNodeType(val);
|
|
7167
|
+
}
|
|
7168
|
+
},
|
|
7169
|
+
children: [
|
|
7170
|
+
/* @__PURE__ */ jsxRuntime.jsx(reactComponents.Option, { value: "paragraph", children: "Normal" }),
|
|
7171
|
+
HEADING_OPTION.map((option, idx) => /* @__PURE__ */ jsxRuntime.jsx(reactComponents.Option, { value: option.key, children: option.text }, `${option.key}-${idx}`))
|
|
7172
|
+
]
|
|
7173
|
+
},
|
|
7174
|
+
key
|
|
7175
|
+
);
|
|
7176
|
+
}
|
|
7177
|
+
case "FontFamily":
|
|
7178
|
+
return /* @__PURE__ */ jsxRuntime.jsx(FontFamilyPlugin, { disabled: !isEditable || props.readOnly }, key);
|
|
7179
|
+
case "FontSize":
|
|
7180
|
+
return /* @__PURE__ */ jsxRuntime.jsx(FontSizePlugin, { disabled: !isEditable || props.readOnly }, key);
|
|
7181
|
+
case "|":
|
|
7182
|
+
return /* @__PURE__ */ jsxRuntime.jsx(reactComponents.ToolbarDivider, {}, key);
|
|
7183
|
+
// ── Standalone text-format toggle buttons ─────────────────────────────
|
|
7184
|
+
// These were previously only accessible inside the 'Decorators' dropdown.
|
|
7185
|
+
// Use them directly in customToolbar to show individual buttons instead.
|
|
7186
|
+
case "Strikethrough":
|
|
7187
|
+
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
7188
|
+
reactComponents.Button,
|
|
7189
|
+
{
|
|
7190
|
+
size: "small",
|
|
7191
|
+
"aria-label": "Strikethrough",
|
|
7192
|
+
"aria-pressed": isStrikethrough,
|
|
7193
|
+
disabled: !isEditable || props.readOnly,
|
|
7194
|
+
icon: /* @__PURE__ */ jsxRuntime.jsx(reactIcons.TextStrikethroughFilled, { style: { color: getIconColor(isStrikethrough) } }),
|
|
7195
|
+
style: getButtonStyle(isStrikethrough),
|
|
7196
|
+
onClick: () => onHandleSelectOption("strike" /* Strikethrough */)
|
|
7197
|
+
},
|
|
7198
|
+
key
|
|
7199
|
+
);
|
|
7200
|
+
case "Subscript":
|
|
7201
|
+
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
7202
|
+
reactComponents.Button,
|
|
7203
|
+
{
|
|
7204
|
+
size: "small",
|
|
7205
|
+
"aria-label": "Subscript",
|
|
7206
|
+
"aria-pressed": isSubscript,
|
|
7207
|
+
disabled: !isEditable || props.readOnly,
|
|
7208
|
+
icon: /* @__PURE__ */ jsxRuntime.jsx(reactIcons.TextSubscriptFilled, { style: { color: getIconColor(isSubscript) } }),
|
|
7209
|
+
style: getButtonStyle(isSubscript),
|
|
7210
|
+
onClick: () => onHandleSelectOption("subscript" /* Subscript */)
|
|
7211
|
+
},
|
|
7212
|
+
key
|
|
7213
|
+
);
|
|
7214
|
+
case "Superscript":
|
|
7215
|
+
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
7216
|
+
reactComponents.Button,
|
|
7217
|
+
{
|
|
7218
|
+
size: "small",
|
|
7219
|
+
"aria-label": "Superscript",
|
|
7220
|
+
"aria-pressed": isSuperscript,
|
|
7221
|
+
disabled: !isEditable || props.readOnly,
|
|
7222
|
+
icon: /* @__PURE__ */ jsxRuntime.jsx(reactIcons.TextSuperscriptFilled, { style: { color: getIconColor(isSuperscript) } }),
|
|
7223
|
+
style: getButtonStyle(isSuperscript),
|
|
7224
|
+
onClick: () => onHandleSelectOption("superscript" /* Superscript */)
|
|
7225
|
+
},
|
|
7226
|
+
key
|
|
7227
|
+
);
|
|
7228
|
+
case "Highlight":
|
|
7229
|
+
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
7230
|
+
reactComponents.Button,
|
|
7231
|
+
{
|
|
7232
|
+
size: "small",
|
|
7233
|
+
"aria-label": "Highlight",
|
|
7234
|
+
"aria-pressed": isHighlight,
|
|
7235
|
+
disabled: !isEditable || props.readOnly,
|
|
7236
|
+
icon: /* @__PURE__ */ jsxRuntime.jsx(
|
|
7237
|
+
reactIcons.HighlightAccentFilled,
|
|
7238
|
+
{
|
|
7239
|
+
style: { color: isEditable ? isHighlight ? brand : fg : fgDisabled }
|
|
7240
|
+
}
|
|
7241
|
+
),
|
|
7242
|
+
style: getButtonStyle(isHighlight),
|
|
7243
|
+
onClick: () => onHandleSelectOption("highlight" /* Highlight */)
|
|
7244
|
+
},
|
|
7245
|
+
key
|
|
7246
|
+
);
|
|
7247
|
+
case "Uppercase":
|
|
7248
|
+
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
7249
|
+
reactComponents.Button,
|
|
7250
|
+
{
|
|
7251
|
+
size: "small",
|
|
7252
|
+
"aria-label": "Uppercase",
|
|
7253
|
+
"aria-pressed": isUppercase,
|
|
7254
|
+
disabled: !isEditable || props.readOnly,
|
|
7255
|
+
icon: /* @__PURE__ */ jsxRuntime.jsx(reactIcons.TextCaseUppercaseFilled, { style: { color: getIconColor(isUppercase) } }),
|
|
7256
|
+
style: getButtonStyle(isUppercase),
|
|
7257
|
+
onClick: () => editor.dispatchCommand(lexical.FORMAT_TEXT_COMMAND, "uppercase")
|
|
7258
|
+
},
|
|
7259
|
+
key
|
|
7260
|
+
);
|
|
7261
|
+
case "Lowercase":
|
|
7262
|
+
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
7263
|
+
reactComponents.Button,
|
|
7264
|
+
{
|
|
7265
|
+
size: "small",
|
|
7266
|
+
"aria-label": "Lowercase",
|
|
7267
|
+
"aria-pressed": isLowercase,
|
|
7268
|
+
disabled: !isEditable || props.readOnly,
|
|
7269
|
+
icon: /* @__PURE__ */ jsxRuntime.jsx(reactIcons.TextCaseLowercaseFilled, { style: { color: getIconColor(isLowercase) } }),
|
|
7270
|
+
style: getButtonStyle(isLowercase),
|
|
7271
|
+
onClick: () => onHandleSelectOption("lowercase" /* Lowercase */)
|
|
7272
|
+
},
|
|
7273
|
+
key
|
|
7274
|
+
);
|
|
7275
|
+
case "Capitalize":
|
|
7276
|
+
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
7277
|
+
reactComponents.Button,
|
|
7278
|
+
{
|
|
7279
|
+
size: "small",
|
|
7280
|
+
"aria-label": "Capitalize",
|
|
7281
|
+
"aria-pressed": isCapitalize,
|
|
7282
|
+
disabled: !isEditable || props.readOnly,
|
|
7283
|
+
icon: /* @__PURE__ */ jsxRuntime.jsx(reactIcons.TextCaseTitleFilled, { style: { color: getIconColor(isCapitalize) } }),
|
|
7284
|
+
style: getButtonStyle(isCapitalize),
|
|
7285
|
+
onClick: () => onHandleSelectOption("capitalize" /* Capitalize */)
|
|
7286
|
+
},
|
|
7287
|
+
key
|
|
7288
|
+
);
|
|
7289
|
+
// ── Standalone list toggle buttons ────────────────────────────────────
|
|
7290
|
+
case "BulletList":
|
|
7291
|
+
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
7292
|
+
reactComponents.Button,
|
|
7293
|
+
{
|
|
7294
|
+
size: "small",
|
|
7295
|
+
"aria-label": "Bullet list",
|
|
7296
|
+
"aria-pressed": selectNodeType === "ul",
|
|
7297
|
+
disabled: !isEditable || props.readOnly,
|
|
7298
|
+
icon: /* @__PURE__ */ jsxRuntime.jsx(reactIcons.TextBulletListLtrFilled, { style: { color: getIconColor(selectNodeType === "ul") } }),
|
|
7299
|
+
style: getButtonStyle(selectNodeType === "ul"),
|
|
7300
|
+
onClick: () => editor.dispatchCommand(
|
|
7301
|
+
selectNodeType === "ul" ? list.REMOVE_LIST_COMMAND : list.INSERT_UNORDERED_LIST_COMMAND,
|
|
7302
|
+
void 0
|
|
7303
|
+
)
|
|
7304
|
+
},
|
|
7305
|
+
key
|
|
7306
|
+
);
|
|
7307
|
+
case "NumberList":
|
|
7308
|
+
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
7309
|
+
reactComponents.Button,
|
|
7310
|
+
{
|
|
7311
|
+
size: "small",
|
|
7312
|
+
"aria-label": "Number list",
|
|
7313
|
+
"aria-pressed": selectNodeType === "ol",
|
|
7314
|
+
disabled: !isEditable || props.readOnly,
|
|
7315
|
+
icon: /* @__PURE__ */ jsxRuntime.jsx(reactIcons.TextNumberListLtrFilled, { style: { color: getIconColor(selectNodeType === "ol") } }),
|
|
7316
|
+
style: getButtonStyle(selectNodeType === "ol"),
|
|
7317
|
+
onClick: () => editor.dispatchCommand(
|
|
7318
|
+
selectNodeType === "ol" ? list.REMOVE_LIST_COMMAND : list.INSERT_ORDERED_LIST_COMMAND,
|
|
7319
|
+
void 0
|
|
7320
|
+
)
|
|
7321
|
+
},
|
|
7322
|
+
key
|
|
7323
|
+
);
|
|
7324
|
+
case "AlphabeticalList":
|
|
7325
|
+
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
7326
|
+
reactComponents.Button,
|
|
7327
|
+
{
|
|
7328
|
+
size: "small",
|
|
7329
|
+
"aria-label": "Alphabetical list",
|
|
7330
|
+
"aria-pressed": selectNodeType === "alpha",
|
|
7331
|
+
disabled: !isEditable || props.readOnly,
|
|
7332
|
+
icon: /* @__PURE__ */ jsxRuntime.jsx(
|
|
7333
|
+
TextAlphaListLtrFilled,
|
|
7334
|
+
{
|
|
7335
|
+
style: { color: getIconColor(selectNodeType === "alpha") }
|
|
7336
|
+
}
|
|
7337
|
+
),
|
|
7338
|
+
style: getButtonStyle(selectNodeType === "alpha"),
|
|
7339
|
+
onClick: () => editor.update(() => $toggleAlphaList())
|
|
7340
|
+
},
|
|
7341
|
+
key
|
|
7342
|
+
);
|
|
7343
|
+
// ── Standalone block buttons ──────────────────────────────────────────
|
|
7344
|
+
case "Quote":
|
|
7345
|
+
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
7346
|
+
reactComponents.Button,
|
|
7347
|
+
{
|
|
7348
|
+
size: "small",
|
|
7349
|
+
"aria-label": "Quote",
|
|
7350
|
+
"aria-pressed": selectNodeType === "quote",
|
|
7351
|
+
disabled: !isEditable || props.readOnly,
|
|
7352
|
+
icon: /* @__PURE__ */ jsxRuntime.jsx(reactIcons.CommentQuoteRegular, { style: { color: getIconColor(selectNodeType === "quote") } }),
|
|
7353
|
+
style: getButtonStyle(selectNodeType === "quote"),
|
|
7354
|
+
onClick: () => formatQuote()
|
|
7355
|
+
},
|
|
7356
|
+
key
|
|
7357
|
+
);
|
|
7358
|
+
case "PageBreak":
|
|
7359
|
+
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
7360
|
+
reactComponents.Button,
|
|
7361
|
+
{
|
|
7362
|
+
size: "small",
|
|
7363
|
+
"aria-label": "Page break",
|
|
7364
|
+
disabled: !isEditable || props.readOnly,
|
|
7365
|
+
icon: /* @__PURE__ */ jsxRuntime.jsx(reactIcons.DocumentPageBreakRegular, { style: { color: getIconColor() } }),
|
|
7366
|
+
style: getButtonStyle(),
|
|
7367
|
+
onClick: () => editor.dispatchCommand(INSERT_PAGE_BREAK, void 0)
|
|
7368
|
+
},
|
|
7369
|
+
key
|
|
7370
|
+
);
|
|
7371
|
+
// ── Standalone heading-level toggle buttons ───────────────────────────
|
|
7372
|
+
// Each button sets (or toggles off) that specific heading level.
|
|
7373
|
+
// Clicking an active heading reverts to normal paragraph.
|
|
7374
|
+
case "H1":
|
|
7375
|
+
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
7376
|
+
reactComponents.Button,
|
|
7377
|
+
{
|
|
7378
|
+
size: "small",
|
|
7379
|
+
"aria-label": "Heading 1",
|
|
7380
|
+
"aria-pressed": selectNodeType === "h1",
|
|
7381
|
+
disabled: !isEditable || props.readOnly,
|
|
7382
|
+
style: {
|
|
7383
|
+
...getButtonStyle(selectNodeType === "h1"),
|
|
7384
|
+
color: getIconColor(selectNodeType === "h1"),
|
|
7385
|
+
fontSize: 12,
|
|
7386
|
+
fontWeight: 600
|
|
7387
|
+
},
|
|
7388
|
+
onClick: () => {
|
|
7389
|
+
if (selectNodeType === "h1") {
|
|
7390
|
+
formatParagraph(editor);
|
|
7391
|
+
setSelectNodeType("paragraph");
|
|
7392
|
+
} else {
|
|
7393
|
+
updateHeading("h1");
|
|
7394
|
+
setSelectNodeType("h1");
|
|
7395
|
+
}
|
|
7396
|
+
},
|
|
7397
|
+
children: "H1"
|
|
7398
|
+
},
|
|
7399
|
+
key
|
|
7400
|
+
);
|
|
7401
|
+
case "H2":
|
|
7402
|
+
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
7403
|
+
reactComponents.Button,
|
|
7404
|
+
{
|
|
7405
|
+
size: "small",
|
|
7406
|
+
"aria-label": "Heading 2",
|
|
7407
|
+
"aria-pressed": selectNodeType === "h2",
|
|
7408
|
+
disabled: !isEditable || props.readOnly,
|
|
7409
|
+
style: {
|
|
7410
|
+
...getButtonStyle(selectNodeType === "h2"),
|
|
7411
|
+
color: getIconColor(selectNodeType === "h2"),
|
|
7412
|
+
fontSize: 12,
|
|
7413
|
+
fontWeight: 600
|
|
7414
|
+
},
|
|
7415
|
+
onClick: () => {
|
|
7416
|
+
if (selectNodeType === "h2") {
|
|
7417
|
+
formatParagraph(editor);
|
|
7418
|
+
setSelectNodeType("paragraph");
|
|
7419
|
+
} else {
|
|
7420
|
+
updateHeading("h2");
|
|
7421
|
+
setSelectNodeType("h2");
|
|
7422
|
+
}
|
|
7423
|
+
},
|
|
7424
|
+
children: "H2"
|
|
7425
|
+
},
|
|
7426
|
+
key
|
|
7427
|
+
);
|
|
7428
|
+
case "H3":
|
|
7429
|
+
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
7430
|
+
reactComponents.Button,
|
|
7431
|
+
{
|
|
7432
|
+
size: "small",
|
|
7433
|
+
"aria-label": "Heading 3",
|
|
7434
|
+
"aria-pressed": selectNodeType === "h3",
|
|
7435
|
+
disabled: !isEditable || props.readOnly,
|
|
7436
|
+
style: {
|
|
7437
|
+
...getButtonStyle(selectNodeType === "h3"),
|
|
7438
|
+
color: getIconColor(selectNodeType === "h3"),
|
|
7439
|
+
fontSize: 12,
|
|
7440
|
+
fontWeight: 600
|
|
7441
|
+
},
|
|
7442
|
+
onClick: () => {
|
|
7443
|
+
if (selectNodeType === "h3") {
|
|
7444
|
+
formatParagraph(editor);
|
|
7445
|
+
setSelectNodeType("paragraph");
|
|
7446
|
+
} else {
|
|
7447
|
+
updateHeading("h3");
|
|
7448
|
+
setSelectNodeType("h3");
|
|
7449
|
+
}
|
|
7450
|
+
},
|
|
7451
|
+
children: "H3"
|
|
7452
|
+
},
|
|
7453
|
+
key
|
|
7454
|
+
);
|
|
7455
|
+
case "H4":
|
|
7456
|
+
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
7457
|
+
reactComponents.Button,
|
|
7458
|
+
{
|
|
7459
|
+
size: "small",
|
|
7460
|
+
"aria-label": "Heading 4",
|
|
7461
|
+
"aria-pressed": selectNodeType === "h4",
|
|
7462
|
+
disabled: !isEditable || props.readOnly,
|
|
7463
|
+
style: {
|
|
7464
|
+
...getButtonStyle(selectNodeType === "h4"),
|
|
7465
|
+
color: getIconColor(selectNodeType === "h4"),
|
|
7466
|
+
fontSize: 12,
|
|
7467
|
+
fontWeight: 600
|
|
7468
|
+
},
|
|
7469
|
+
onClick: () => {
|
|
7470
|
+
if (selectNodeType === "h4") {
|
|
7471
|
+
formatParagraph(editor);
|
|
7472
|
+
setSelectNodeType("paragraph");
|
|
7473
|
+
} else {
|
|
7474
|
+
updateHeading("h4");
|
|
7475
|
+
setSelectNodeType("h4");
|
|
7476
|
+
}
|
|
7477
|
+
},
|
|
7478
|
+
children: "H4"
|
|
7479
|
+
},
|
|
7480
|
+
key
|
|
7481
|
+
);
|
|
7482
|
+
case "H5":
|
|
7483
|
+
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
7484
|
+
reactComponents.Button,
|
|
7485
|
+
{
|
|
7486
|
+
size: "small",
|
|
7487
|
+
"aria-label": "Heading 5",
|
|
7488
|
+
"aria-pressed": selectNodeType === "h5",
|
|
7489
|
+
disabled: !isEditable || props.readOnly,
|
|
7490
|
+
style: {
|
|
7491
|
+
...getButtonStyle(selectNodeType === "h5"),
|
|
7492
|
+
color: getIconColor(selectNodeType === "h5"),
|
|
7493
|
+
fontSize: 12,
|
|
7494
|
+
fontWeight: 600
|
|
7495
|
+
},
|
|
7496
|
+
onClick: () => {
|
|
7497
|
+
if (selectNodeType === "h5") {
|
|
7498
|
+
formatParagraph(editor);
|
|
6835
7499
|
setSelectNodeType("paragraph");
|
|
6836
7500
|
} else {
|
|
6837
|
-
updateHeading(
|
|
6838
|
-
setSelectNodeType(
|
|
7501
|
+
updateHeading("h5");
|
|
7502
|
+
setSelectNodeType("h5");
|
|
6839
7503
|
}
|
|
6840
7504
|
},
|
|
6841
|
-
children:
|
|
6842
|
-
|
|
6843
|
-
|
|
6844
|
-
|
|
7505
|
+
children: "H5"
|
|
7506
|
+
},
|
|
7507
|
+
key
|
|
7508
|
+
);
|
|
7509
|
+
case "H6":
|
|
7510
|
+
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
7511
|
+
reactComponents.Button,
|
|
7512
|
+
{
|
|
7513
|
+
size: "small",
|
|
7514
|
+
"aria-label": "Heading 6",
|
|
7515
|
+
"aria-pressed": selectNodeType === "h6",
|
|
7516
|
+
disabled: !isEditable || props.readOnly,
|
|
7517
|
+
style: {
|
|
7518
|
+
...getButtonStyle(selectNodeType === "h6"),
|
|
7519
|
+
color: getIconColor(selectNodeType === "h6"),
|
|
7520
|
+
fontSize: 12,
|
|
7521
|
+
fontWeight: 600
|
|
7522
|
+
},
|
|
7523
|
+
onClick: () => {
|
|
7524
|
+
if (selectNodeType === "h6") {
|
|
7525
|
+
formatParagraph(editor);
|
|
7526
|
+
setSelectNodeType("paragraph");
|
|
7527
|
+
} else {
|
|
7528
|
+
updateHeading("h6");
|
|
7529
|
+
setSelectNodeType("h6");
|
|
7530
|
+
}
|
|
7531
|
+
},
|
|
7532
|
+
children: "H6"
|
|
6845
7533
|
},
|
|
6846
7534
|
key
|
|
6847
7535
|
);
|
|
6848
|
-
}
|
|
6849
|
-
case "FontFamily":
|
|
6850
|
-
return /* @__PURE__ */ jsxRuntime.jsx(FontFamilyPlugin, { disabled: !isEditable || props.readOnly }, key);
|
|
6851
|
-
case "FontSize":
|
|
6852
|
-
return /* @__PURE__ */ jsxRuntime.jsx(FontSizePlugin, { disabled: !isEditable || props.readOnly }, key);
|
|
6853
|
-
case "|":
|
|
6854
|
-
return /* @__PURE__ */ jsxRuntime.jsx(reactComponents.ToolbarDivider, {}, key);
|
|
6855
7536
|
case "Decorators": {
|
|
6856
7537
|
const activeDecorators = [
|
|
6857
7538
|
...isUppercase ? ["uppercase"] : [],
|
|
@@ -6863,6 +7544,7 @@ var ToolBarPlugins = (props) => {
|
|
|
6863
7544
|
...isHighlight ? ["highlight"] : [],
|
|
6864
7545
|
...selectNodeType === "ul" ? ["ul-list"] : [],
|
|
6865
7546
|
...selectNodeType === "ol" ? ["ol-list"] : [],
|
|
7547
|
+
...selectNodeType === "alpha" ? ["al-list"] : [],
|
|
6866
7548
|
...selectNodeType === "quote" ? ["quote"] : []
|
|
6867
7549
|
];
|
|
6868
7550
|
const DECORATOR_LABEL = {
|
|
@@ -6875,6 +7557,7 @@ var ToolBarPlugins = (props) => {
|
|
|
6875
7557
|
highlight: "Highlight",
|
|
6876
7558
|
"ul-list": "Bullet list",
|
|
6877
7559
|
"ol-list": "Number list",
|
|
7560
|
+
"al-list": "Alphabetical list",
|
|
6878
7561
|
quote: "Quote"
|
|
6879
7562
|
};
|
|
6880
7563
|
const decoratorValue = activeDecorators.length === 0 ? "" : activeDecorators.length === 1 ? DECORATOR_LABEL[activeDecorators[0]] : `${DECORATOR_LABEL[activeDecorators[0]]} +${activeDecorators.length - 1}`;
|
|
@@ -6891,7 +7574,16 @@ var ToolBarPlugins = (props) => {
|
|
|
6891
7574
|
button: { style: dropdownButtonStyle },
|
|
6892
7575
|
expandIcon: { style: dropdownExpandIconStyle },
|
|
6893
7576
|
listbox: { style: { minInlineSize: "180px" } },
|
|
7577
|
+
open: decoratorOpen,
|
|
7578
|
+
onOpenChange: (_, data) => {
|
|
7579
|
+
if (decoratorSelectingRef.current) {
|
|
7580
|
+
decoratorSelectingRef.current = false;
|
|
7581
|
+
return;
|
|
7582
|
+
}
|
|
7583
|
+
setDecoratorOpen(data.open);
|
|
7584
|
+
},
|
|
6894
7585
|
onOptionSelect: (_, data) => {
|
|
7586
|
+
decoratorSelectingRef.current = true;
|
|
6895
7587
|
switch (data.optionValue) {
|
|
6896
7588
|
case "uppercase":
|
|
6897
7589
|
editor.dispatchCommand(lexical.FORMAT_TEXT_COMMAND, "uppercase");
|
|
@@ -6915,10 +7607,19 @@ var ToolBarPlugins = (props) => {
|
|
|
6915
7607
|
onHandleSelectOption("highlight" /* Highlight */);
|
|
6916
7608
|
break;
|
|
6917
7609
|
case "ul-list":
|
|
6918
|
-
editor.dispatchCommand(
|
|
7610
|
+
editor.dispatchCommand(
|
|
7611
|
+
selectNodeType === "ul" ? list.REMOVE_LIST_COMMAND : list.INSERT_UNORDERED_LIST_COMMAND,
|
|
7612
|
+
void 0
|
|
7613
|
+
);
|
|
6919
7614
|
break;
|
|
6920
7615
|
case "ol-list":
|
|
6921
|
-
editor.dispatchCommand(
|
|
7616
|
+
editor.dispatchCommand(
|
|
7617
|
+
selectNodeType === "ol" ? list.REMOVE_LIST_COMMAND : list.INSERT_ORDERED_LIST_COMMAND,
|
|
7618
|
+
void 0
|
|
7619
|
+
);
|
|
7620
|
+
break;
|
|
7621
|
+
case "al-list":
|
|
7622
|
+
editor.update(() => $toggleAlphaList());
|
|
6922
7623
|
break;
|
|
6923
7624
|
case "page-break":
|
|
6924
7625
|
editor.dispatchCommand(INSERT_PAGE_BREAK, void 0);
|
|
@@ -6954,7 +7655,12 @@ var ToolBarPlugins = (props) => {
|
|
|
6954
7655
|
"Superscript"
|
|
6955
7656
|
] }),
|
|
6956
7657
|
/* @__PURE__ */ jsxRuntime.jsxs(reactComponents.Option, { value: "highlight", text: "Highlight", children: [
|
|
6957
|
-
/* @__PURE__ */ jsxRuntime.jsx(
|
|
7658
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
7659
|
+
reactIcons.HighlightAccentFilled,
|
|
7660
|
+
{
|
|
7661
|
+
style: { ...optionIconStyle, color: isEditable ? brand : fgDisabled }
|
|
7662
|
+
}
|
|
7663
|
+
),
|
|
6958
7664
|
"Highlight"
|
|
6959
7665
|
] }),
|
|
6960
7666
|
/* @__PURE__ */ jsxRuntime.jsxs(reactComponents.Option, { value: "ul-list", text: "Bullet list", children: [
|
|
@@ -6965,6 +7671,10 @@ var ToolBarPlugins = (props) => {
|
|
|
6965
7671
|
/* @__PURE__ */ jsxRuntime.jsx(reactIcons.TextNumberListLtrFilled, { style: optionIconStyle }),
|
|
6966
7672
|
"Number list"
|
|
6967
7673
|
] }),
|
|
7674
|
+
/* @__PURE__ */ jsxRuntime.jsxs(reactComponents.Option, { value: "al-list", text: "Alphabetical list", children: [
|
|
7675
|
+
/* @__PURE__ */ jsxRuntime.jsx(TextAlphaListLtrFilled, { style: optionIconStyle }),
|
|
7676
|
+
"Alphabetical list"
|
|
7677
|
+
] }),
|
|
6968
7678
|
/* @__PURE__ */ jsxRuntime.jsxs(reactComponents.Option, { value: "page-break", text: "Page Break", children: [
|
|
6969
7679
|
/* @__PURE__ */ jsxRuntime.jsx(reactIcons.DocumentPageBreakRegular, { style: optionIconStyle }),
|
|
6970
7680
|
"Page break"
|
|
@@ -6990,10 +7700,30 @@ var ToolBarPlugins = (props) => {
|
|
|
6990
7700
|
// );
|
|
6991
7701
|
case "Align": {
|
|
6992
7702
|
const ALIGN_OPTIONS = [
|
|
6993
|
-
{
|
|
6994
|
-
|
|
6995
|
-
|
|
6996
|
-
|
|
7703
|
+
{
|
|
7704
|
+
value: "left",
|
|
7705
|
+
label: "Left Align",
|
|
7706
|
+
icon: /* @__PURE__ */ jsxRuntime.jsx(reactIcons.TextAlignLeftFilled, { style: optionIconStyle }),
|
|
7707
|
+
action: "leftAlign" /* LeftAlign */
|
|
7708
|
+
},
|
|
7709
|
+
{
|
|
7710
|
+
value: "center",
|
|
7711
|
+
label: "Center Align",
|
|
7712
|
+
icon: /* @__PURE__ */ jsxRuntime.jsx(reactIcons.TextAlignCenterFilled, { style: optionIconStyle }),
|
|
7713
|
+
action: "centerAlign" /* CenterAlign */
|
|
7714
|
+
},
|
|
7715
|
+
{
|
|
7716
|
+
value: "right",
|
|
7717
|
+
label: "Right Align",
|
|
7718
|
+
icon: /* @__PURE__ */ jsxRuntime.jsx(reactIcons.TextAlignRightFilled, { style: optionIconStyle }),
|
|
7719
|
+
action: "rightAlign" /* RightAlign */
|
|
7720
|
+
},
|
|
7721
|
+
{
|
|
7722
|
+
value: "justify",
|
|
7723
|
+
label: "Justify Align",
|
|
7724
|
+
icon: /* @__PURE__ */ jsxRuntime.jsx(reactIcons.TextAlignJustifyFilled, { style: optionIconStyle }),
|
|
7725
|
+
action: "justifyAlign" /* JustifyAlign */
|
|
7726
|
+
}
|
|
6997
7727
|
];
|
|
6998
7728
|
const alignLabel = ALIGN_OPTIONS.find((o) => o.value === alignment)?.label ?? "Left Align";
|
|
6999
7729
|
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
@@ -7209,32 +7939,31 @@ function BrowserSpellCheckPlugin({ enabled }) {
|
|
|
7209
7939
|
}, [editor, enabled]);
|
|
7210
7940
|
return null;
|
|
7211
7941
|
}
|
|
7212
|
-
function
|
|
7213
|
-
|
|
7214
|
-
}) {
|
|
7215
|
-
const [editor] = LexicalComposerContext.useLexicalComposerContext();
|
|
7216
|
-
React9.useEffect(() => {
|
|
7217
|
-
return editor.registerUpdateListener(({ editorState }) => {
|
|
7218
|
-
editorState.read(() => {
|
|
7219
|
-
const text = lexical.$getRoot().getTextContent();
|
|
7220
|
-
const words = text.trim() === "" ? 0 : text.trim().split(/\s+/).length;
|
|
7221
|
-
onCountChange(words);
|
|
7222
|
-
});
|
|
7223
|
-
});
|
|
7224
|
-
}, [editor, onCountChange]);
|
|
7225
|
-
return null;
|
|
7226
|
-
}
|
|
7227
|
-
function CharCountPlugin({
|
|
7228
|
-
onCountChange
|
|
7942
|
+
function ContentMetricsPlugin({
|
|
7943
|
+
onMetricsChange
|
|
7229
7944
|
}) {
|
|
7230
7945
|
const [editor] = LexicalComposerContext.useLexicalComposerContext();
|
|
7946
|
+
const prevRef = React9.useRef({ words: 0, chars: 0, images: 0, links: 0, tables: 0 });
|
|
7231
7947
|
React9.useEffect(() => {
|
|
7232
|
-
return editor.registerUpdateListener(({
|
|
7233
|
-
|
|
7234
|
-
|
|
7235
|
-
|
|
7948
|
+
return editor.registerUpdateListener(({ dirtyElements, dirtyLeaves }) => {
|
|
7949
|
+
if (dirtyElements.size === 0 && dirtyLeaves.size === 0) return;
|
|
7950
|
+
const root = editor.getRootElement();
|
|
7951
|
+
if (!root) return;
|
|
7952
|
+
const text = root.innerText ?? "";
|
|
7953
|
+
const trimmed = text.trim();
|
|
7954
|
+
const words = trimmed === "" ? 0 : trimmed.split(/\s+/).length;
|
|
7955
|
+
const chars = trimmed.length;
|
|
7956
|
+
const images = root.querySelectorAll("img").length;
|
|
7957
|
+
const links = root.querySelectorAll("a[href]").length;
|
|
7958
|
+
const tables = root.querySelectorAll("table").length;
|
|
7959
|
+
const prev = prevRef.current;
|
|
7960
|
+
if (prev.words !== words || prev.chars !== chars || prev.images !== images || prev.links !== links || prev.tables !== tables) {
|
|
7961
|
+
const next = { words, chars, images, links, tables };
|
|
7962
|
+
prevRef.current = next;
|
|
7963
|
+
onMetricsChange(next);
|
|
7964
|
+
}
|
|
7236
7965
|
});
|
|
7237
|
-
}, [editor,
|
|
7966
|
+
}, [editor, onMetricsChange]);
|
|
7238
7967
|
return null;
|
|
7239
7968
|
}
|
|
7240
7969
|
function FocusEventsPlugin({
|
|
@@ -7255,7 +7984,8 @@ function FocusEventsPlugin({
|
|
|
7255
7984
|
const next = e.relatedTarget;
|
|
7256
7985
|
const container = containerRef.current;
|
|
7257
7986
|
const stillInside = !!next && (container ? container.contains(next) : root.contains(next));
|
|
7258
|
-
|
|
7987
|
+
const isEditorPortal = !!next?.closest?.("[data-lexical-editor-portal]");
|
|
7988
|
+
if (stillInside || isEditorPortal) return;
|
|
7259
7989
|
editor.update(() => {
|
|
7260
7990
|
lexical.$setSelection(null);
|
|
7261
7991
|
});
|
|
@@ -7310,10 +8040,7 @@ function _adaptRawSpell(data, text) {
|
|
|
7310
8040
|
}
|
|
7311
8041
|
const rawGrammar = data.grammar_correction ?? data.improved_text;
|
|
7312
8042
|
const grammarCorrection = rawGrammar && rawGrammar.trim() !== text.trim() ? rawGrammar.trim() : void 0;
|
|
7313
|
-
return {
|
|
7314
|
-
issues: issues.sort((a, b) => a.offset - b.offset),
|
|
7315
|
-
grammarCorrection
|
|
7316
|
-
};
|
|
8043
|
+
return { issues: issues.sort((a, b) => a.offset - b.offset), grammarCorrection };
|
|
7317
8044
|
}
|
|
7318
8045
|
function _adaptRawSuggest(data) {
|
|
7319
8046
|
if (!data) return null;
|
|
@@ -7368,387 +8095,460 @@ function _makeQueryFn(fn) {
|
|
|
7368
8095
|
};
|
|
7369
8096
|
};
|
|
7370
8097
|
}
|
|
7371
|
-
|
|
7372
|
-
const
|
|
7373
|
-
const
|
|
7374
|
-
|
|
7375
|
-
|
|
7376
|
-
|
|
7377
|
-
|
|
7378
|
-
|
|
7379
|
-
|
|
7380
|
-
|
|
7381
|
-
|
|
7382
|
-
)
|
|
7383
|
-
|
|
7384
|
-
|
|
7385
|
-
|
|
7386
|
-
|
|
7387
|
-
|
|
7388
|
-
[]
|
|
7389
|
-
);
|
|
7390
|
-
const [charCount, setCharCount] = React9.useState(0);
|
|
7391
|
-
const handleCharCount = React9.useCallback(
|
|
7392
|
-
(count) => setCharCount(count),
|
|
7393
|
-
[]
|
|
7394
|
-
);
|
|
7395
|
-
const [refErrors, setRefErrors] = React9.useState([]);
|
|
7396
|
-
const [pageSetup, setPageSetup] = React9.useState(DEFAULT_PAGE_SETUP);
|
|
7397
|
-
const pageCanvas = resolvePageCanvasMetrics(pageSetup);
|
|
7398
|
-
const contentEditableDomRef = React9.useRef(null);
|
|
7399
|
-
const previousOverLimitRef = React9.useRef(false);
|
|
7400
|
-
const focusedRef = React9.useRef(false);
|
|
7401
|
-
const setFocused = (focused) => {
|
|
7402
|
-
focusedRef.current = focused;
|
|
7403
|
-
};
|
|
7404
|
-
const containerRef = React9.useRef(null);
|
|
7405
|
-
const onAnchorRef = (elem) => {
|
|
7406
|
-
if (elem) setFloatingAnchorElem(elem);
|
|
7407
|
-
};
|
|
7408
|
-
const initialConfig = {
|
|
7409
|
-
namespace: props.namespace,
|
|
7410
|
-
theme,
|
|
7411
|
-
onError: () => {
|
|
7412
|
-
},
|
|
7413
|
-
nodes: [
|
|
7414
|
-
richText.HeadingNode,
|
|
7415
|
-
richText.QuoteNode,
|
|
7416
|
-
code.CodeHighlightNode,
|
|
7417
|
-
code.CodeNode,
|
|
7418
|
-
list.ListNode,
|
|
7419
|
-
list.ListItemNode,
|
|
7420
|
-
link.LinkNode,
|
|
7421
|
-
link.AutoLinkNode,
|
|
7422
|
-
table.TableNode,
|
|
7423
|
-
table.TableRowNode,
|
|
7424
|
-
table.TableCellNode,
|
|
7425
|
-
ImageNode,
|
|
7426
|
-
InlineImageNode,
|
|
7427
|
-
YouTubeNode,
|
|
7428
|
-
PageBreakNode,
|
|
7429
|
-
AutocompleteNode,
|
|
7430
|
-
SpellErrorNode,
|
|
7431
|
-
HtmlBlockNode
|
|
7432
|
-
]
|
|
7433
|
-
};
|
|
7434
|
-
const EditorStyles = react.mergeStyleSets({
|
|
7435
|
-
editorPlaceholder: {
|
|
7436
|
-
color: "var(--colorNeutralForeground3, grey)",
|
|
7437
|
-
position: "absolute",
|
|
7438
|
-
top: props.level !== "none" /* None */ ? "17px" : "27px",
|
|
7439
|
-
left: pageCanvas.paddingPx,
|
|
7440
|
-
right: pageCanvas.paddingPx,
|
|
7441
|
-
fontSize: "14px",
|
|
7442
|
-
pointerEvents: "none",
|
|
7443
|
-
userSelect: "none"
|
|
7444
|
-
},
|
|
7445
|
-
contentEditor: {
|
|
7446
|
-
zIndex: 0,
|
|
7447
|
-
flex: "auto",
|
|
7448
|
-
outline: "none",
|
|
7449
|
-
overflow: "auto",
|
|
7450
|
-
marginTop: "0px",
|
|
7451
|
-
position: "relative",
|
|
7452
|
-
background: "var(--colorNeutralBackground1, #ffffff)",
|
|
7453
|
-
justifyContent: "center",
|
|
7454
|
-
height: props.contentHeight ?? "100%",
|
|
7455
|
-
...isReadOnly && {
|
|
7456
|
-
cursor: "not-allowed",
|
|
7457
|
-
opacity: 0.75,
|
|
7458
|
-
userSelect: "text"
|
|
7459
|
-
}
|
|
7460
|
-
}
|
|
7461
|
-
});
|
|
7462
|
-
const urlRegExp = new RegExp(
|
|
7463
|
-
/((([A-Za-z]{3,9}:(?:\/\/)?)(?:[-;:&=+$,\w]+@)?[A-Za-z0-9.-]+|(?:www.|[-;:&=+$,\w]+@)[A-Za-z0-9.-]+)((?:\/[+~%/.\w-_]*)?\??(?:[-+=&;%@.\w_]*)#?(?:[\w]*))?)/
|
|
7464
|
-
);
|
|
7465
|
-
const validateUrl = (url) => url === "https://" || urlRegExp.test(url);
|
|
7466
|
-
const handleReadOnlyClickCapture = (e) => {
|
|
7467
|
-
if (!isReadOnly) return;
|
|
7468
|
-
const target = e.target;
|
|
7469
|
-
const anchor = target?.closest?.("a");
|
|
7470
|
-
if (anchor) {
|
|
7471
|
-
e.preventDefault();
|
|
7472
|
-
e.stopPropagation();
|
|
7473
|
-
}
|
|
7474
|
-
};
|
|
7475
|
-
const [touched, setTouched] = React9.useState(false);
|
|
7476
|
-
const isOverLimit = props.wordLimit !== void 0 && wordCount > props.wordLimit;
|
|
7477
|
-
const internalErrors = [];
|
|
7478
|
-
if (isOverLimit) {
|
|
7479
|
-
const m = props.errorMessages?.wordLimitExceeded;
|
|
7480
|
-
internalErrors.push(
|
|
7481
|
-
typeof m === "function" ? m(wordCount, props.wordLimit) : m ?? `Word limit exceeded (${wordCount} / ${props.wordLimit} words used)`
|
|
7482
|
-
);
|
|
7483
|
-
}
|
|
7484
|
-
if (props.required && touched && wordCount === 0) {
|
|
7485
|
-
internalErrors.push(
|
|
7486
|
-
props.errorMessages?.required ?? "This field is required"
|
|
7487
|
-
);
|
|
7488
|
-
}
|
|
7489
|
-
if (props.minWords !== void 0 && touched && wordCount < props.minWords) {
|
|
7490
|
-
const m = props.errorMessages?.minWords;
|
|
7491
|
-
internalErrors.push(
|
|
7492
|
-
typeof m === "function" ? m(wordCount, props.minWords) : m ?? `Minimum ${props.minWords} words required (${wordCount} entered)`
|
|
7493
|
-
);
|
|
7494
|
-
}
|
|
7495
|
-
if (props.maxChars !== void 0 && charCount > props.maxChars) {
|
|
7496
|
-
const m = props.errorMessages?.maxCharsExceeded;
|
|
7497
|
-
internalErrors.push(
|
|
7498
|
-
typeof m === "function" ? m(charCount, props.maxChars) : m ?? `Character limit exceeded (${charCount} / ${props.maxChars} characters used)`
|
|
8098
|
+
function EditorReadyPlugin({ onReady }) {
|
|
8099
|
+
const [editor] = LexicalComposerContext.useLexicalComposerContext();
|
|
8100
|
+
const calledRef = React9.useRef(false);
|
|
8101
|
+
React9.useEffect(() => {
|
|
8102
|
+
if (!onReady || calledRef.current) return;
|
|
8103
|
+
calledRef.current = true;
|
|
8104
|
+
onReady(editor);
|
|
8105
|
+
}, [editor, onReady]);
|
|
8106
|
+
return null;
|
|
8107
|
+
}
|
|
8108
|
+
var ContentEditorComponent = React9.forwardRef(
|
|
8109
|
+
(props, ref) => {
|
|
8110
|
+
const isReadOnly = !!props.readOnly;
|
|
8111
|
+
const resolvedSpellCheck = React9__namespace.default.useMemo(
|
|
8112
|
+
() => props.spellCheckFn ? _makeSpellCheckFn(props.spellCheckFn) : props.useSpellCheck,
|
|
8113
|
+
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
8114
|
+
[props.spellCheckFn, props.useSpellCheck]
|
|
7499
8115
|
);
|
|
7500
|
-
|
|
7501
|
-
|
|
7502
|
-
|
|
7503
|
-
|
|
7504
|
-
typeof m === "function" ? m(charCount, props.minChars) : m ?? `Minimum ${props.minChars} characters required (${charCount} entered)`
|
|
8116
|
+
const resolvedQuery = React9__namespace.default.useMemo(
|
|
8117
|
+
() => props.suggestFn ? _makeQueryFn(props.suggestFn) : props.useQuery,
|
|
8118
|
+
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
8119
|
+
[props.suggestFn, props.useQuery]
|
|
7505
8120
|
);
|
|
7506
|
-
|
|
7507
|
-
|
|
7508
|
-
|
|
7509
|
-
|
|
7510
|
-
|
|
7511
|
-
|
|
7512
|
-
|
|
7513
|
-
|
|
7514
|
-
|
|
7515
|
-
|
|
7516
|
-
const
|
|
7517
|
-
|
|
7518
|
-
|
|
7519
|
-
|
|
7520
|
-
|
|
7521
|
-
|
|
7522
|
-
|
|
7523
|
-
|
|
7524
|
-
}
|
|
7525
|
-
|
|
7526
|
-
|
|
7527
|
-
|
|
7528
|
-
|
|
7529
|
-
|
|
7530
|
-
|
|
7531
|
-
|
|
7532
|
-
|
|
7533
|
-
|
|
7534
|
-
|
|
7535
|
-
|
|
7536
|
-
|
|
7537
|
-
|
|
7538
|
-
|
|
7539
|
-
|
|
8121
|
+
const [floatingAnchorElem, setFloatingAnchorElem] = React9.useState(null);
|
|
8122
|
+
const [isLinkEditMode, setIsLinkEditMode] = React9.useState(false);
|
|
8123
|
+
const [metrics, setMetrics] = React9.useState({
|
|
8124
|
+
words: 0,
|
|
8125
|
+
chars: 0,
|
|
8126
|
+
images: 0,
|
|
8127
|
+
links: 0,
|
|
8128
|
+
tables: 0
|
|
8129
|
+
});
|
|
8130
|
+
const handleMetrics = React9.useCallback((m) => setMetrics(m), []);
|
|
8131
|
+
const [pageSetup, setPageSetup] = React9.useState(DEFAULT_PAGE_SETUP);
|
|
8132
|
+
const pageCanvas = resolvePageCanvasMetrics(pageSetup);
|
|
8133
|
+
const wordCount = metrics.words;
|
|
8134
|
+
const contentEditableDomRef = React9.useRef(null);
|
|
8135
|
+
const previousOverLimitRef = React9.useRef(false);
|
|
8136
|
+
const focusedRef = React9.useRef(false);
|
|
8137
|
+
const setFocused = (focused) => {
|
|
8138
|
+
focusedRef.current = focused;
|
|
8139
|
+
};
|
|
8140
|
+
const containerRef = React9.useRef(null);
|
|
8141
|
+
const onAnchorRef = (elem) => {
|
|
8142
|
+
if (elem) setFloatingAnchorElem(elem);
|
|
8143
|
+
};
|
|
8144
|
+
const initialConfig = React9__namespace.default.useMemo(() => {
|
|
8145
|
+
const config = {
|
|
8146
|
+
namespace: props.namespace ?? "",
|
|
8147
|
+
theme,
|
|
8148
|
+
onError: () => {
|
|
8149
|
+
},
|
|
8150
|
+
nodes: [
|
|
8151
|
+
richText.HeadingNode,
|
|
8152
|
+
richText.QuoteNode,
|
|
8153
|
+
code.CodeHighlightNode,
|
|
8154
|
+
code.CodeNode,
|
|
8155
|
+
list.ListNode,
|
|
8156
|
+
list.ListItemNode,
|
|
8157
|
+
AlphaListNode,
|
|
8158
|
+
link.LinkNode,
|
|
8159
|
+
link.AutoLinkNode,
|
|
8160
|
+
table.TableNode,
|
|
8161
|
+
table.TableRowNode,
|
|
8162
|
+
table.TableCellNode,
|
|
8163
|
+
ImageNode,
|
|
8164
|
+
InlineImageNode,
|
|
8165
|
+
YouTubeNode,
|
|
8166
|
+
PageBreakNode,
|
|
8167
|
+
AutocompleteNode,
|
|
8168
|
+
SpellErrorNode,
|
|
8169
|
+
HtmlBlockNode
|
|
8170
|
+
]
|
|
8171
|
+
};
|
|
8172
|
+
props.onBeforeInitialize?.(config);
|
|
8173
|
+
return config;
|
|
8174
|
+
}, []);
|
|
8175
|
+
const EditorStyles = react.mergeStyleSets({
|
|
8176
|
+
editorPlaceholder: {
|
|
8177
|
+
color: "var(--colorNeutralForeground3, grey)",
|
|
8178
|
+
position: "absolute",
|
|
8179
|
+
top: props.level !== "none" /* None */ ? "17px" : "27px",
|
|
8180
|
+
left: pageCanvas.paddingPx,
|
|
8181
|
+
right: pageCanvas.paddingPx,
|
|
8182
|
+
fontSize: "14px",
|
|
8183
|
+
pointerEvents: "none",
|
|
8184
|
+
userSelect: "none"
|
|
7540
8185
|
},
|
|
7541
|
-
|
|
7542
|
-
|
|
7543
|
-
|
|
7544
|
-
|
|
7545
|
-
|
|
7546
|
-
|
|
7547
|
-
|
|
7548
|
-
|
|
7549
|
-
|
|
7550
|
-
|
|
7551
|
-
|
|
8186
|
+
contentEditor: {
|
|
8187
|
+
zIndex: 0,
|
|
8188
|
+
flex: "auto",
|
|
8189
|
+
outline: "none",
|
|
8190
|
+
overflow: "auto",
|
|
8191
|
+
marginTop: "0px",
|
|
8192
|
+
position: "relative",
|
|
8193
|
+
background: "var(--colorNeutralBackground1, #ffffff)",
|
|
8194
|
+
justifyContent: "center",
|
|
8195
|
+
height: props.contentHeight ?? "100%",
|
|
8196
|
+
...isReadOnly && {
|
|
8197
|
+
cursor: "not-allowed",
|
|
8198
|
+
opacity: 0.75,
|
|
8199
|
+
userSelect: "text"
|
|
8200
|
+
}
|
|
8201
|
+
}
|
|
8202
|
+
});
|
|
8203
|
+
const urlRegExp = new RegExp(
|
|
8204
|
+
/((([A-Za-z]{3,9}:(?:\/\/)?)(?:[-;:&=+$,\w]+@)?[A-Za-z0-9.-]+|(?:www.|[-;:&=+$,\w]+@)[A-Za-z0-9.-]+)((?:\/[+~%/.\w-_]*)?\??(?:[-+=&;%@.\w_]*)#?(?:[\w]*))?)/
|
|
8205
|
+
);
|
|
8206
|
+
const validateUrl = (url) => url === "https://" || urlRegExp.test(url);
|
|
8207
|
+
const handleReadOnlyClickCapture = (e) => {
|
|
8208
|
+
if (!isReadOnly) return;
|
|
8209
|
+
const target = e.target;
|
|
8210
|
+
const anchor = target?.closest?.("a");
|
|
8211
|
+
if (anchor) {
|
|
8212
|
+
e.preventDefault();
|
|
8213
|
+
e.stopPropagation();
|
|
8214
|
+
}
|
|
8215
|
+
};
|
|
8216
|
+
const isOverLimit = props.wordLimit !== void 0 && wordCount > props.wordLimit;
|
|
8217
|
+
React9.useEffect(() => {
|
|
8218
|
+
if (props.wordLimit === void 0 || !props.onWordLimitExceeded) return;
|
|
8219
|
+
const wasOverLimit = previousOverLimitRef.current;
|
|
8220
|
+
if (isOverLimit !== wasOverLimit) {
|
|
8221
|
+
props.onWordLimitExceeded({
|
|
8222
|
+
wordCount,
|
|
8223
|
+
wordLimit: props.wordLimit,
|
|
8224
|
+
exceeded: isOverLimit
|
|
8225
|
+
});
|
|
8226
|
+
previousOverLimitRef.current = isOverLimit;
|
|
8227
|
+
}
|
|
8228
|
+
}, [isOverLimit, wordCount, props.wordLimit, props.onWordLimitExceeded]);
|
|
8229
|
+
const validationErrors = React9__namespace.default.useMemo(() => {
|
|
8230
|
+
const errors = [];
|
|
8231
|
+
const custom = props.validationMessages ?? {};
|
|
8232
|
+
const { words, chars, images, links, tables } = metrics;
|
|
8233
|
+
const msg = (key, ...args) => {
|
|
8234
|
+
const override = custom[key];
|
|
8235
|
+
if (override !== void 0) {
|
|
8236
|
+
return typeof override === "function" ? override(...args) : override;
|
|
8237
|
+
}
|
|
8238
|
+
const def = DEFAULT_VALIDATION_MESSAGES[key];
|
|
8239
|
+
return typeof def === "function" ? def(...args) : def;
|
|
8240
|
+
};
|
|
8241
|
+
const requiredFired = props.required && words === 0;
|
|
8242
|
+
if (requiredFired) {
|
|
8243
|
+
errors.push({ type: "required", message: msg("required") });
|
|
8244
|
+
} else if (props.minWords !== void 0 && words < props.minWords) {
|
|
8245
|
+
errors.push({ type: "minWords", message: msg("minWords", words, props.minWords) });
|
|
8246
|
+
}
|
|
8247
|
+
const effectiveMaxWords = props.maxWords ?? props.wordLimit;
|
|
8248
|
+
if (effectiveMaxWords !== void 0 && words > effectiveMaxWords) {
|
|
8249
|
+
errors.push({ type: "maxWords", message: msg("maxWords", words, effectiveMaxWords) });
|
|
8250
|
+
}
|
|
8251
|
+
if (!requiredFired && props.minChars !== void 0 && chars < props.minChars) {
|
|
8252
|
+
errors.push({ type: "minChars", message: msg("minChars", chars, props.minChars) });
|
|
8253
|
+
}
|
|
8254
|
+
if (props.maxChars !== void 0 && chars > props.maxChars) {
|
|
8255
|
+
errors.push({ type: "maxChars", message: msg("maxChars", chars, props.maxChars) });
|
|
8256
|
+
}
|
|
8257
|
+
if (props.noImages && images > 0) {
|
|
8258
|
+
errors.push({ type: "noImages", message: msg("noImages") });
|
|
8259
|
+
} else if (props.maxImages !== void 0 && images > props.maxImages) {
|
|
8260
|
+
errors.push({ type: "maxImages", message: msg("maxImages", images, props.maxImages) });
|
|
8261
|
+
}
|
|
8262
|
+
if (props.noLinks && links > 0) {
|
|
8263
|
+
errors.push({ type: "noLinks", message: msg("noLinks") });
|
|
8264
|
+
} else if (props.maxLinks !== void 0 && links > props.maxLinks) {
|
|
8265
|
+
errors.push({ type: "maxLinks", message: msg("maxLinks", links, props.maxLinks) });
|
|
8266
|
+
}
|
|
8267
|
+
if (props.noTables && tables > 0) {
|
|
8268
|
+
errors.push({ type: "noTables", message: msg("noTables") });
|
|
8269
|
+
}
|
|
8270
|
+
return errors;
|
|
8271
|
+
}, [
|
|
8272
|
+
metrics,
|
|
8273
|
+
props.required,
|
|
8274
|
+
props.minWords,
|
|
8275
|
+
props.maxWords,
|
|
8276
|
+
props.wordLimit,
|
|
8277
|
+
props.minChars,
|
|
8278
|
+
props.maxChars,
|
|
8279
|
+
props.noImages,
|
|
8280
|
+
props.maxImages,
|
|
8281
|
+
props.noLinks,
|
|
8282
|
+
props.maxLinks,
|
|
8283
|
+
props.noTables,
|
|
8284
|
+
props.validationMessages
|
|
8285
|
+
]);
|
|
8286
|
+
const previousErrorTypesRef = React9.useRef("");
|
|
8287
|
+
React9.useEffect(() => {
|
|
8288
|
+
if (!props.onValidationChange) return;
|
|
8289
|
+
const key = validationErrors.map((e) => e.type).join(",");
|
|
8290
|
+
if (key !== previousErrorTypesRef.current) {
|
|
8291
|
+
previousErrorTypesRef.current = key;
|
|
8292
|
+
props.onValidationChange(validationErrors);
|
|
8293
|
+
}
|
|
8294
|
+
}, [validationErrors, props.onValidationChange]);
|
|
8295
|
+
const trimmedErrorMessage = props.errorMessage?.trim() || "";
|
|
8296
|
+
const hasValidationError = validationErrors.length > 0 || !!trimmedErrorMessage;
|
|
8297
|
+
return /* @__PURE__ */ jsxRuntime.jsx(reactComponents.FluentProvider, { theme: reactComponents.webLightTheme, style: { height: "100%" }, children: /* @__PURE__ */ jsxRuntime.jsxs(LexicalComposer.LexicalComposer, { initialConfig, children: [
|
|
8298
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { ref: containerRef, className: "lexical-rich-editor-root", style: { height: "100%" }, children: /* @__PURE__ */ jsxRuntime.jsxs(
|
|
8299
|
+
react.Stack,
|
|
8300
|
+
{
|
|
8301
|
+
style: {
|
|
8302
|
+
zIndex: 1e3,
|
|
8303
|
+
background: "#fff",
|
|
8304
|
+
borderRadius: "2px",
|
|
8305
|
+
width: props.width ?? "100%",
|
|
8306
|
+
height: props.height ?? "100%",
|
|
8307
|
+
margin: props.margin ?? "5px auto",
|
|
8308
|
+
border: `1px solid ${isOverLimit || hasValidationError ? "#c4272c" : "var(--colorNeutralStroke1, #ccced1)"}`,
|
|
8309
|
+
transition: "border-color 0.2s",
|
|
8310
|
+
display: "flex",
|
|
8311
|
+
flexDirection: "column"
|
|
8312
|
+
},
|
|
8313
|
+
children: [
|
|
8314
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
8315
|
+
"div",
|
|
7552
8316
|
{
|
|
7553
|
-
|
|
7554
|
-
|
|
7555
|
-
|
|
7556
|
-
|
|
8317
|
+
className: "editor-toolbar-root",
|
|
8318
|
+
style: {
|
|
8319
|
+
pointerEvents: isReadOnly ? "none" : "auto",
|
|
8320
|
+
position: "sticky",
|
|
8321
|
+
opacity: isReadOnly ? 0.85 : 1
|
|
8322
|
+
},
|
|
8323
|
+
children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
8324
|
+
ToolBarPlugins,
|
|
8325
|
+
{
|
|
8326
|
+
level: props.level ?? "basic" /* Basic */,
|
|
8327
|
+
customToolbar: props.customToolbar,
|
|
8328
|
+
readOnly: props.readOnly,
|
|
8329
|
+
pageSetup,
|
|
8330
|
+
onPageSetupChange: setPageSetup,
|
|
8331
|
+
maxImageSizeMB: props.maxImageSizeMB,
|
|
8332
|
+
validationMessages: props.validationMessages,
|
|
8333
|
+
setIsLinkEditMode
|
|
8334
|
+
}
|
|
8335
|
+
)
|
|
7557
8336
|
}
|
|
7558
|
-
)
|
|
7559
|
-
|
|
7560
|
-
|
|
7561
|
-
|
|
7562
|
-
|
|
7563
|
-
|
|
7564
|
-
|
|
7565
|
-
|
|
7566
|
-
|
|
7567
|
-
|
|
7568
|
-
|
|
7569
|
-
|
|
7570
|
-
|
|
7571
|
-
|
|
7572
|
-
|
|
7573
|
-
|
|
7574
|
-
|
|
7575
|
-
/* @__PURE__ */ jsxRuntime.jsx(
|
|
7576
|
-
LexicalRichTextPlugin.RichTextPlugin,
|
|
7577
|
-
{
|
|
7578
|
-
ErrorBoundary: LexicalErrorBoundary.LexicalErrorBoundary,
|
|
7579
|
-
contentEditable: /* @__PURE__ */ jsxRuntime.jsx(
|
|
7580
|
-
"div",
|
|
8337
|
+
),
|
|
8338
|
+
/* @__PURE__ */ jsxRuntime.jsxs(
|
|
8339
|
+
"div",
|
|
8340
|
+
{
|
|
8341
|
+
style: {
|
|
8342
|
+
position: "relative",
|
|
8343
|
+
flexGrow: 1,
|
|
8344
|
+
padding: "15px 0px",
|
|
8345
|
+
overflowY: "scroll",
|
|
8346
|
+
overflowX: "auto",
|
|
8347
|
+
minWidth: 0,
|
|
8348
|
+
background: pageCanvas.widthPx !== void 0 ? "#eef0f2" : void 0
|
|
8349
|
+
},
|
|
8350
|
+
onClickCapture: handleReadOnlyClickCapture,
|
|
8351
|
+
children: [
|
|
8352
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
8353
|
+
LexicalRichTextPlugin.RichTextPlugin,
|
|
7581
8354
|
{
|
|
7582
|
-
|
|
7583
|
-
|
|
7584
|
-
|
|
7585
|
-
children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
7586
|
-
LexicalContentEditable.ContentEditable,
|
|
8355
|
+
ErrorBoundary: LexicalErrorBoundary.LexicalErrorBoundary,
|
|
8356
|
+
contentEditable: /* @__PURE__ */ jsxRuntime.jsx(
|
|
8357
|
+
"div",
|
|
7587
8358
|
{
|
|
7588
|
-
|
|
7589
|
-
|
|
7590
|
-
|
|
7591
|
-
|
|
7592
|
-
|
|
7593
|
-
|
|
7594
|
-
|
|
7595
|
-
|
|
7596
|
-
|
|
7597
|
-
|
|
7598
|
-
|
|
7599
|
-
|
|
7600
|
-
|
|
7601
|
-
|
|
8359
|
+
className: "editor",
|
|
8360
|
+
style: { height: "100%", position: "relative" },
|
|
8361
|
+
ref: onAnchorRef,
|
|
8362
|
+
children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
8363
|
+
LexicalContentEditable.ContentEditable,
|
|
8364
|
+
{
|
|
8365
|
+
ref: contentEditableDomRef,
|
|
8366
|
+
className: react.css(EditorStyles.contentEditor),
|
|
8367
|
+
style: {
|
|
8368
|
+
paddingTop: props.level !== "none" /* None */ ? 0 : 10,
|
|
8369
|
+
paddingLeft: pageCanvas.paddingPx,
|
|
8370
|
+
paddingRight: pageCanvas.paddingPx,
|
|
8371
|
+
maxWidth: pageCanvas.widthPx,
|
|
8372
|
+
marginLeft: pageCanvas.widthPx !== void 0 ? "auto" : void 0,
|
|
8373
|
+
marginRight: pageCanvas.widthPx !== void 0 ? "auto" : void 0,
|
|
8374
|
+
boxShadow: pageCanvas.widthPx !== void 0 ? "0 0 0 1px rgba(0,0,0,0.08), 0 2px 8px rgba(0,0,0,0.08)" : void 0
|
|
8375
|
+
},
|
|
8376
|
+
spellCheck: !resolvedSpellCheck,
|
|
8377
|
+
autoCorrect: resolvedSpellCheck ? "off" : void 0,
|
|
8378
|
+
autoCapitalize: resolvedSpellCheck ? "off" : void 0
|
|
8379
|
+
}
|
|
8380
|
+
)
|
|
7602
8381
|
}
|
|
7603
|
-
)
|
|
8382
|
+
),
|
|
8383
|
+
placeholder: /* @__PURE__ */ jsxRuntime.jsx(react.Stack, { className: react.css(EditorStyles.editorPlaceholder), children: props.placeholder })
|
|
7604
8384
|
}
|
|
7605
8385
|
),
|
|
7606
|
-
|
|
7607
|
-
|
|
7608
|
-
),
|
|
7609
|
-
props.wordLimit !== void 0 && /* @__PURE__ */ jsxRuntime.jsx(
|
|
7610
|
-
"div",
|
|
7611
|
-
{
|
|
7612
|
-
style: {
|
|
7613
|
-
position: "sticky",
|
|
7614
|
-
bottom: 0,
|
|
7615
|
-
display: "flex",
|
|
7616
|
-
justifyContent: "flex-end",
|
|
7617
|
-
paddingRight: 14,
|
|
7618
|
-
pointerEvents: "none",
|
|
7619
|
-
userSelect: "none"
|
|
7620
|
-
},
|
|
7621
|
-
children: /* @__PURE__ */ jsxRuntime.jsxs(
|
|
7622
|
-
"span",
|
|
8386
|
+
(props.wordLimit !== void 0 || props.maxWords !== void 0 || props.minWords !== void 0 || props.maxChars !== void 0 || props.minChars !== void 0) && /* @__PURE__ */ jsxRuntime.jsxs(
|
|
8387
|
+
"div",
|
|
7623
8388
|
{
|
|
7624
8389
|
style: {
|
|
7625
|
-
|
|
7626
|
-
|
|
7627
|
-
|
|
7628
|
-
|
|
8390
|
+
position: "sticky",
|
|
8391
|
+
bottom: 0,
|
|
8392
|
+
display: "flex",
|
|
8393
|
+
justifyContent: "flex-end",
|
|
8394
|
+
gap: 10,
|
|
8395
|
+
paddingRight: 14,
|
|
8396
|
+
pointerEvents: "none",
|
|
8397
|
+
userSelect: "none"
|
|
7629
8398
|
},
|
|
7630
8399
|
children: [
|
|
7631
|
-
|
|
7632
|
-
|
|
7633
|
-
|
|
7634
|
-
|
|
8400
|
+
(props.wordLimit !== void 0 || props.maxWords !== void 0 || props.minWords !== void 0) && /* @__PURE__ */ jsxRuntime.jsxs(
|
|
8401
|
+
"span",
|
|
8402
|
+
{
|
|
8403
|
+
style: {
|
|
8404
|
+
fontSize: "11px",
|
|
8405
|
+
color: hasValidationError ? "#c4272c" : "var(--colorNeutralForeground3, #aaa)",
|
|
8406
|
+
fontWeight: hasValidationError ? 600 : 400,
|
|
8407
|
+
transition: "color 0.2s, font-weight 0.2s"
|
|
8408
|
+
},
|
|
8409
|
+
children: [
|
|
8410
|
+
wordCount,
|
|
8411
|
+
(props.maxWords ?? props.wordLimit) !== void 0 && ` / ${props.maxWords ?? props.wordLimit}`,
|
|
8412
|
+
props.minWords !== void 0 && props.maxWords === void 0 && props.wordLimit === void 0 && ` (min ${props.minWords})`,
|
|
8413
|
+
" words"
|
|
8414
|
+
]
|
|
8415
|
+
}
|
|
8416
|
+
),
|
|
8417
|
+
(props.maxChars !== void 0 || props.minChars !== void 0) && /* @__PURE__ */ jsxRuntime.jsxs(
|
|
8418
|
+
"span",
|
|
8419
|
+
{
|
|
8420
|
+
style: {
|
|
8421
|
+
fontSize: "11px",
|
|
8422
|
+
color: hasValidationError ? "#c4272c" : "var(--colorNeutralForeground3, #aaa)",
|
|
8423
|
+
fontWeight: hasValidationError ? 600 : 400,
|
|
8424
|
+
transition: "color 0.2s, font-weight 0.2s"
|
|
8425
|
+
},
|
|
8426
|
+
children: [
|
|
8427
|
+
metrics.chars,
|
|
8428
|
+
props.maxChars !== void 0 && ` / ${props.maxChars}`,
|
|
8429
|
+
props.minChars !== void 0 && props.maxChars === void 0 && ` (min ${props.minChars})`,
|
|
8430
|
+
" chars"
|
|
8431
|
+
]
|
|
8432
|
+
}
|
|
8433
|
+
)
|
|
7635
8434
|
]
|
|
7636
8435
|
}
|
|
7637
8436
|
)
|
|
8437
|
+
]
|
|
8438
|
+
}
|
|
8439
|
+
),
|
|
8440
|
+
/* @__PURE__ */ jsxRuntime.jsx(ReadOnlyPlugin, { readonly: isReadOnly }),
|
|
8441
|
+
/* @__PURE__ */ jsxRuntime.jsx(BrowserSpellCheckPlugin, { enabled: !resolvedSpellCheck }),
|
|
8442
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
8443
|
+
FocusEventsPlugin,
|
|
8444
|
+
{
|
|
8445
|
+
onFocus: props.onFocus,
|
|
8446
|
+
onBlur: props.onBlur,
|
|
8447
|
+
setFocused,
|
|
8448
|
+
containerRef
|
|
8449
|
+
}
|
|
8450
|
+
),
|
|
8451
|
+
props.autoFocus && !isReadOnly && /* @__PURE__ */ jsxRuntime.jsx(LexicalAutoFocusPlugin.AutoFocusPlugin, {}),
|
|
8452
|
+
/* @__PURE__ */ jsxRuntime.jsx(LexicalHistoryPlugin.HistoryPlugin, {}),
|
|
8453
|
+
/* @__PURE__ */ jsxRuntime.jsx(LexicalListPlugin.ListPlugin, {}),
|
|
8454
|
+
/* @__PURE__ */ jsxRuntime.jsx(LexicalLinkPlugin.LinkPlugin, { validateUrl }),
|
|
8455
|
+
/* @__PURE__ */ jsxRuntime.jsx(LexicalAutoLinkPlugin.AutoLinkPlugin, { matchers: MATCHERS }),
|
|
8456
|
+
/* @__PURE__ */ jsxRuntime.jsx(LexicalTablePlugin.TablePlugin, { hasCellMerge: true, hasCellBackgroundColor: true }),
|
|
8457
|
+
!isReadOnly && /* @__PURE__ */ jsxRuntime.jsx(YoutubeDeletePlugin, {}),
|
|
8458
|
+
!isReadOnly && floatingAnchorElem && /* @__PURE__ */ jsxRuntime.jsx(TableActionMenuPlugin, {}),
|
|
8459
|
+
!isReadOnly && floatingAnchorElem && /* @__PURE__ */ jsxRuntime.jsx(TableCellResizerPlugin, { anchorElem: floatingAnchorElem }),
|
|
8460
|
+
!isReadOnly && /* @__PURE__ */ jsxRuntime.jsx(
|
|
8461
|
+
FloatingLinkEditorPlugin,
|
|
8462
|
+
{
|
|
8463
|
+
anchorElem: floatingAnchorElem,
|
|
8464
|
+
isLinkEditMode,
|
|
8465
|
+
setIsLinkEditMode
|
|
8466
|
+
}
|
|
8467
|
+
),
|
|
8468
|
+
!isReadOnly && /* @__PURE__ */ jsxRuntime.jsx(ImagePlugin_default, {}),
|
|
8469
|
+
!isReadOnly && /* @__PURE__ */ jsxRuntime.jsx(InlineImage_default, {}),
|
|
8470
|
+
!isReadOnly && /* @__PURE__ */ jsxRuntime.jsx(PageBreakPlugin, {}),
|
|
8471
|
+
!!resolvedQuery && !isReadOnly && /* @__PURE__ */ jsxRuntime.jsx(
|
|
8472
|
+
AutocompletePlugin,
|
|
8473
|
+
{
|
|
8474
|
+
useQuery: resolvedQuery,
|
|
8475
|
+
isReadOnly,
|
|
8476
|
+
onSuggestionShown: props.onSuggestionShown,
|
|
8477
|
+
onSuggestionAccept: props.onSuggestionAccept,
|
|
8478
|
+
idleMs: props.suggestIdleMs ?? 300,
|
|
8479
|
+
minWords: 4,
|
|
8480
|
+
prefixWindow: 300
|
|
8481
|
+
}
|
|
8482
|
+
),
|
|
8483
|
+
!!resolvedSpellCheck && !isReadOnly && /* @__PURE__ */ jsxRuntime.jsx(
|
|
8484
|
+
SpellCheckPlugin,
|
|
8485
|
+
{
|
|
8486
|
+
useSpellCheck: resolvedSpellCheck,
|
|
8487
|
+
onSpellCheckAccept: props.onSpellCheckAccept,
|
|
8488
|
+
idleMs: props.spellCheckIdleMs ?? 1200,
|
|
8489
|
+
enabled: props.spellCheckEnabled !== false
|
|
8490
|
+
}
|
|
8491
|
+
),
|
|
8492
|
+
!isReadOnly && props.showFloatingToolbar && /* @__PURE__ */ jsxRuntime.jsx(CharacterStylesPopupPlugin, {}),
|
|
8493
|
+
/* @__PURE__ */ jsxRuntime.jsx(CustomOnChangePlugin, { value: props.value, onChange: props.onChange }),
|
|
8494
|
+
(props.wordLimit !== void 0 || props.required || props.minWords !== void 0 || props.maxWords !== void 0 || props.minChars !== void 0 || props.maxChars !== void 0 || props.noImages || props.maxImages !== void 0 || props.noLinks || props.maxLinks !== void 0 || props.noTables) && /* @__PURE__ */ jsxRuntime.jsx(ContentMetricsPlugin, { onMetricsChange: handleMetrics }),
|
|
8495
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
8496
|
+
RefApiPlugin,
|
|
8497
|
+
{
|
|
8498
|
+
forwardedRef: ref,
|
|
8499
|
+
contentEditableDomRef,
|
|
8500
|
+
focusedRef
|
|
8501
|
+
}
|
|
8502
|
+
),
|
|
8503
|
+
(validationErrors.length > 0 || trimmedErrorMessage) && /* @__PURE__ */ jsxRuntime.jsxs("div", { style: { flexShrink: 0, padding: "6px 20px 8px" }, children: [
|
|
8504
|
+
validationErrors.map((err) => /* @__PURE__ */ jsxRuntime.jsxs(
|
|
8505
|
+
"div",
|
|
8506
|
+
{
|
|
8507
|
+
style: {
|
|
8508
|
+
display: "flex",
|
|
8509
|
+
alignItems: "flex-start",
|
|
8510
|
+
gap: 6,
|
|
8511
|
+
marginTop: 2,
|
|
8512
|
+
color: "#c4272c",
|
|
8513
|
+
fontSize: 12,
|
|
8514
|
+
lineHeight: "18px"
|
|
8515
|
+
},
|
|
8516
|
+
children: [
|
|
8517
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { style: { fontWeight: 600, flexShrink: 0 }, children: "\u26A0" }),
|
|
8518
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { children: err.message })
|
|
8519
|
+
]
|
|
8520
|
+
},
|
|
8521
|
+
err.type
|
|
8522
|
+
)),
|
|
8523
|
+
trimmedErrorMessage && /* @__PURE__ */ jsxRuntime.jsxs(
|
|
8524
|
+
"div",
|
|
8525
|
+
{
|
|
8526
|
+
style: {
|
|
8527
|
+
display: "flex",
|
|
8528
|
+
alignItems: "flex-start",
|
|
8529
|
+
gap: 6,
|
|
8530
|
+
marginTop: 2,
|
|
8531
|
+
color: "#c4272c",
|
|
8532
|
+
fontSize: 12,
|
|
8533
|
+
lineHeight: "18px"
|
|
8534
|
+
},
|
|
8535
|
+
children: [
|
|
8536
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { style: { fontWeight: 600, flexShrink: 0 }, children: "\u26A0" }),
|
|
8537
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { children: trimmedErrorMessage })
|
|
8538
|
+
]
|
|
7638
8539
|
}
|
|
7639
8540
|
)
|
|
7640
|
-
]
|
|
7641
|
-
|
|
7642
|
-
|
|
7643
|
-
|
|
7644
|
-
|
|
7645
|
-
|
|
7646
|
-
|
|
7647
|
-
|
|
7648
|
-
background: "#fff8f8",
|
|
7649
|
-
padding: "6px 12px 8px",
|
|
7650
|
-
display: "flex",
|
|
7651
|
-
flexDirection: "column",
|
|
7652
|
-
gap: 4
|
|
7653
|
-
},
|
|
7654
|
-
children: allErrors.map((err, i) => /* @__PURE__ */ jsxRuntime.jsxs(
|
|
7655
|
-
"div",
|
|
7656
|
-
{
|
|
7657
|
-
style: { display: "flex", alignItems: "center", gap: 6 },
|
|
7658
|
-
children: [
|
|
7659
|
-
/* @__PURE__ */ jsxRuntime.jsx(
|
|
7660
|
-
reactIcons.ErrorCircleRegular,
|
|
7661
|
-
{
|
|
7662
|
-
style: { fontSize: 14, color: "#c4272c", flexShrink: 0 }
|
|
7663
|
-
}
|
|
7664
|
-
),
|
|
7665
|
-
/* @__PURE__ */ jsxRuntime.jsx("span", { style: { fontSize: 12, color: "#c4272c" }, children: err })
|
|
7666
|
-
]
|
|
7667
|
-
},
|
|
7668
|
-
i
|
|
7669
|
-
))
|
|
7670
|
-
}
|
|
7671
|
-
),
|
|
7672
|
-
/* @__PURE__ */ jsxRuntime.jsx(ReadOnlyPlugin, { readonly: isReadOnly }),
|
|
7673
|
-
/* @__PURE__ */ jsxRuntime.jsx(BrowserSpellCheckPlugin, { enabled: !resolvedSpellCheck }),
|
|
7674
|
-
/* @__PURE__ */ jsxRuntime.jsx(
|
|
7675
|
-
FocusEventsPlugin,
|
|
7676
|
-
{
|
|
7677
|
-
onFocus: props.onFocus,
|
|
7678
|
-
onBlur: () => {
|
|
7679
|
-
setTouched(true);
|
|
7680
|
-
props.onBlur?.();
|
|
7681
|
-
},
|
|
7682
|
-
setFocused,
|
|
7683
|
-
containerRef
|
|
7684
|
-
}
|
|
7685
|
-
),
|
|
7686
|
-
props.autoFocus && !isReadOnly && /* @__PURE__ */ jsxRuntime.jsx(LexicalAutoFocusPlugin.AutoFocusPlugin, {}),
|
|
7687
|
-
/* @__PURE__ */ jsxRuntime.jsx(LexicalHistoryPlugin.HistoryPlugin, {}),
|
|
7688
|
-
/* @__PURE__ */ jsxRuntime.jsx(LexicalListPlugin.ListPlugin, {}),
|
|
7689
|
-
/* @__PURE__ */ jsxRuntime.jsx(LexicalLinkPlugin.LinkPlugin, { validateUrl }),
|
|
7690
|
-
/* @__PURE__ */ jsxRuntime.jsx(LexicalAutoLinkPlugin.AutoLinkPlugin, { matchers: MATCHERS }),
|
|
7691
|
-
/* @__PURE__ */ jsxRuntime.jsx(LexicalTablePlugin.TablePlugin, { hasCellMerge: true, hasCellBackgroundColor: true }),
|
|
7692
|
-
!isReadOnly && /* @__PURE__ */ jsxRuntime.jsx(YoutubeDeletePlugin, {}),
|
|
7693
|
-
!isReadOnly && floatingAnchorElem && /* @__PURE__ */ jsxRuntime.jsx(TableActionMenuPlugin, {}),
|
|
7694
|
-
!isReadOnly && floatingAnchorElem && /* @__PURE__ */ jsxRuntime.jsx(TableCellResizerPlugin, { anchorElem: floatingAnchorElem }),
|
|
7695
|
-
!isReadOnly && /* @__PURE__ */ jsxRuntime.jsx(
|
|
7696
|
-
FloatingLinkEditorPlugin,
|
|
7697
|
-
{
|
|
7698
|
-
anchorElem: floatingAnchorElem,
|
|
7699
|
-
isLinkEditMode,
|
|
7700
|
-
setIsLinkEditMode
|
|
7701
|
-
}
|
|
7702
|
-
),
|
|
7703
|
-
!isReadOnly && /* @__PURE__ */ jsxRuntime.jsx(ImagePlugin_default, {}),
|
|
7704
|
-
!isReadOnly && /* @__PURE__ */ jsxRuntime.jsx(InlineImage_default, {}),
|
|
7705
|
-
!isReadOnly && /* @__PURE__ */ jsxRuntime.jsx(PageBreakPlugin, {}),
|
|
7706
|
-
!!resolvedQuery && !isReadOnly && /* @__PURE__ */ jsxRuntime.jsx(
|
|
7707
|
-
AutocompletePlugin,
|
|
7708
|
-
{
|
|
7709
|
-
useQuery: resolvedQuery,
|
|
7710
|
-
isReadOnly,
|
|
7711
|
-
onSuggestionShown: props.onSuggestionShown,
|
|
7712
|
-
onSuggestionAccept: props.onSuggestionAccept,
|
|
7713
|
-
idleMs: props.suggestIdleMs ?? 300,
|
|
7714
|
-
minWords: 4,
|
|
7715
|
-
prefixWindow: 300
|
|
7716
|
-
}
|
|
7717
|
-
),
|
|
7718
|
-
!!resolvedSpellCheck && !isReadOnly && /* @__PURE__ */ jsxRuntime.jsx(
|
|
7719
|
-
SpellCheckPlugin,
|
|
7720
|
-
{
|
|
7721
|
-
useSpellCheck: resolvedSpellCheck,
|
|
7722
|
-
onSpellCheckAccept: props.onSpellCheckAccept,
|
|
7723
|
-
idleMs: props.spellCheckIdleMs ?? 1200,
|
|
7724
|
-
enabled: props.spellCheckEnabled !== false
|
|
7725
|
-
}
|
|
7726
|
-
),
|
|
7727
|
-
!isReadOnly && props.showFloatingToolbar && /* @__PURE__ */ jsxRuntime.jsx(CharacterStylesPopupPlugin, {}),
|
|
7728
|
-
/* @__PURE__ */ jsxRuntime.jsx(
|
|
7729
|
-
CustomOnChangePlugin,
|
|
7730
|
-
{
|
|
7731
|
-
value: props.value,
|
|
7732
|
-
onChange: props.onChange
|
|
7733
|
-
}
|
|
7734
|
-
),
|
|
7735
|
-
(props.wordLimit !== void 0 || props.required || props.minWords !== void 0) && /* @__PURE__ */ jsxRuntime.jsx(WordCountPlugin, { onCountChange: handleWordCount }),
|
|
7736
|
-
(props.maxChars !== void 0 || props.minChars !== void 0) && /* @__PURE__ */ jsxRuntime.jsx(CharCountPlugin, { onCountChange: handleCharCount }),
|
|
7737
|
-
/* @__PURE__ */ jsxRuntime.jsx(
|
|
7738
|
-
RefApiPlugin,
|
|
7739
|
-
{
|
|
7740
|
-
forwardedRef: ref,
|
|
7741
|
-
contentEditableDomRef,
|
|
7742
|
-
focusedRef,
|
|
7743
|
-
setRefErrors
|
|
7744
|
-
}
|
|
7745
|
-
)
|
|
7746
|
-
]
|
|
7747
|
-
}
|
|
7748
|
-
) }) }) });
|
|
7749
|
-
});
|
|
8541
|
+
] })
|
|
8542
|
+
]
|
|
8543
|
+
}
|
|
8544
|
+
) }),
|
|
8545
|
+
/* @__PURE__ */ jsxRuntime.jsx(EditorReadyPlugin, { onReady: props.onReady })
|
|
8546
|
+
] }) });
|
|
8547
|
+
}
|
|
8548
|
+
);
|
|
7750
8549
|
|
|
7751
8550
|
exports.ContentEditorComponent = ContentEditorComponent;
|
|
7752
8551
|
exports.ContentEditorLevel = ContentEditorLevel;
|
|
8552
|
+
exports.DEFAULT_VALIDATION_MESSAGES = DEFAULT_VALIDATION_MESSAGES;
|
|
7753
8553
|
//# sourceMappingURL=index.js.map
|
|
7754
8554
|
//# sourceMappingURL=index.js.map
|