@tarviks/lexical-rich-editor 1.2.0 → 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 +137 -49
- 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 +2095 -1058
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +2097 -1061
- 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,37 +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
|
-
|
|
645
|
-
|
|
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
|
+
) });
|
|
646
641
|
};
|
|
647
642
|
ImageComponent_default = ImageComponent;
|
|
648
643
|
}
|
|
@@ -876,6 +871,7 @@ __export(InlineImageComponent_exports, {
|
|
|
876
871
|
var imageCache2, useSuspenseImage2, LazyImage2, InlineImageComponent, InlineImageComponent_default;
|
|
877
872
|
var init_InlineImageComponent = __esm({
|
|
878
873
|
"src/Nodes/InlineImageComponent.tsx"() {
|
|
874
|
+
init_ImageResizer();
|
|
879
875
|
init_InlineImage();
|
|
880
876
|
init_InlineImageNode();
|
|
881
877
|
imageCache2 = /* @__PURE__ */ new Set();
|
|
@@ -912,6 +908,7 @@ var init_InlineImageComponent = __esm({
|
|
|
912
908
|
};
|
|
913
909
|
InlineImageComponent = ({ src, altText, nodeKey, width, height, showCaption, caption, position }) => {
|
|
914
910
|
const [isSelected, setSelected, clearSelection] = useLexicalNodeSelection.useLexicalNodeSelection(nodeKey);
|
|
911
|
+
const [isResizing, setIsResizing] = React9.useState(false);
|
|
915
912
|
const [selection, setSelection] = React9.useState(null);
|
|
916
913
|
const activeEditorRef = React9.useRef(null);
|
|
917
914
|
const imageRef = React9.useRef(null);
|
|
@@ -973,6 +970,25 @@ var init_InlineImageComponent = __esm({
|
|
|
973
970
|
},
|
|
974
971
|
[caption, editor, setSelected]
|
|
975
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
|
+
);
|
|
976
992
|
React9.useEffect(() => {
|
|
977
993
|
let isMounted = true;
|
|
978
994
|
const unregister = utils.mergeRegister(
|
|
@@ -991,48 +1007,13 @@ var init_InlineImageComponent = __esm({
|
|
|
991
1007
|
),
|
|
992
1008
|
editor.registerCommand(
|
|
993
1009
|
lexical.CLICK_COMMAND,
|
|
994
|
-
|
|
995
|
-
const event = payload;
|
|
996
|
-
if (event.target === imageRef.current) {
|
|
997
|
-
if (event.shiftKey) {
|
|
998
|
-
setSelected(!isSelected);
|
|
999
|
-
} else {
|
|
1000
|
-
clearSelection();
|
|
1001
|
-
setSelected(true);
|
|
1002
|
-
}
|
|
1003
|
-
return true;
|
|
1004
|
-
}
|
|
1005
|
-
return false;
|
|
1006
|
-
},
|
|
1007
|
-
lexical.COMMAND_PRIORITY_LOW
|
|
1008
|
-
),
|
|
1009
|
-
editor.registerCommand(
|
|
1010
|
-
lexical.DRAGSTART_COMMAND,
|
|
1011
|
-
(event) => {
|
|
1012
|
-
if (event.target === imageRef.current) {
|
|
1013
|
-
event.preventDefault();
|
|
1014
|
-
return true;
|
|
1015
|
-
}
|
|
1016
|
-
return false;
|
|
1017
|
-
},
|
|
1018
|
-
lexical.COMMAND_PRIORITY_LOW
|
|
1019
|
-
),
|
|
1020
|
-
editor.registerCommand(
|
|
1021
|
-
lexical.KEY_DELETE_COMMAND,
|
|
1022
|
-
$onDelete,
|
|
1023
|
-
lexical.COMMAND_PRIORITY_LOW
|
|
1024
|
-
),
|
|
1025
|
-
editor.registerCommand(
|
|
1026
|
-
lexical.KEY_BACKSPACE_COMMAND,
|
|
1027
|
-
$onDelete,
|
|
1010
|
+
onClick,
|
|
1028
1011
|
lexical.COMMAND_PRIORITY_LOW
|
|
1029
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),
|
|
1030
1015
|
editor.registerCommand(lexical.KEY_ENTER_COMMAND, $onEnter, lexical.COMMAND_PRIORITY_LOW),
|
|
1031
|
-
editor.registerCommand(
|
|
1032
|
-
lexical.KEY_ESCAPE_COMMAND,
|
|
1033
|
-
$onEscape,
|
|
1034
|
-
lexical.COMMAND_PRIORITY_LOW
|
|
1035
|
-
)
|
|
1016
|
+
editor.registerCommand(lexical.KEY_ESCAPE_COMMAND, $onEscape, lexical.COMMAND_PRIORITY_LOW)
|
|
1036
1017
|
);
|
|
1037
1018
|
return () => {
|
|
1038
1019
|
isMounted = false;
|
|
@@ -1041,27 +1022,59 @@ var init_InlineImageComponent = __esm({
|
|
|
1041
1022
|
}, [
|
|
1042
1023
|
clearSelection,
|
|
1043
1024
|
editor,
|
|
1025
|
+
isResizing,
|
|
1044
1026
|
isSelected,
|
|
1045
1027
|
nodeKey,
|
|
1046
1028
|
$onDelete,
|
|
1047
1029
|
$onEnter,
|
|
1048
1030
|
$onEscape,
|
|
1031
|
+
onClick,
|
|
1049
1032
|
setSelected
|
|
1050
1033
|
]);
|
|
1051
|
-
const
|
|
1052
|
-
|
|
1053
|
-
|
|
1054
|
-
|
|
1055
|
-
{
|
|
1056
|
-
|
|
1057
|
-
|
|
1058
|
-
|
|
1059
|
-
|
|
1060
|
-
|
|
1061
|
-
|
|
1062
|
-
|
|
1063
|
-
}
|
|
1064
|
-
|
|
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;
|
|
1049
|
+
const isFocused = (isSelected || isResizing) && isEditable;
|
|
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(
|
|
1052
|
+
LazyImage2,
|
|
1053
|
+
{
|
|
1054
|
+
className: isFocused ? `focused ${lexical.$isNodeSelection(selection) ? "draggable" : ""}` : null,
|
|
1055
|
+
src,
|
|
1056
|
+
altText,
|
|
1057
|
+
imageRef,
|
|
1058
|
+
width,
|
|
1059
|
+
height,
|
|
1060
|
+
position
|
|
1061
|
+
}
|
|
1062
|
+
),
|
|
1063
|
+
lexical.$isNodeSelection(selection) && isFocused && /* @__PURE__ */ jsxRuntime.jsx(
|
|
1064
|
+
ImageResizer_default,
|
|
1065
|
+
{
|
|
1066
|
+
showCaption: false,
|
|
1067
|
+
setShowCaption: () => {
|
|
1068
|
+
},
|
|
1069
|
+
captionsEnabled: false,
|
|
1070
|
+
editor,
|
|
1071
|
+
buttonRef,
|
|
1072
|
+
imageRef,
|
|
1073
|
+
onResizeStart,
|
|
1074
|
+
onResizeEnd
|
|
1075
|
+
}
|
|
1076
|
+
)
|
|
1077
|
+
] }) });
|
|
1065
1078
|
};
|
|
1066
1079
|
InlineImageComponent_default = InlineImageComponent;
|
|
1067
1080
|
}
|
|
@@ -1249,6 +1262,19 @@ var ContentEditorLevel = /* @__PURE__ */ ((ContentEditorLevel2) => {
|
|
|
1249
1262
|
ContentEditorLevel2["Pro"] = "pro";
|
|
1250
1263
|
return ContentEditorLevel2;
|
|
1251
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
|
+
};
|
|
1252
1278
|
|
|
1253
1279
|
// src/Types/PageSetup.ts
|
|
1254
1280
|
var DEFAULT_PAGE_SETUP = {
|
|
@@ -1289,6 +1315,106 @@ function resolvePageCanvasMetrics(value) {
|
|
|
1289
1315
|
paddingPx: Math.round(margin.valueIn * CSS_PX_PER_INCH)
|
|
1290
1316
|
};
|
|
1291
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
|
+
}
|
|
1292
1418
|
var AutocompleteNode = class _AutocompleteNode extends lexical.TextNode {
|
|
1293
1419
|
static getType() {
|
|
1294
1420
|
return "autocomplete";
|
|
@@ -1299,6 +1425,13 @@ var AutocompleteNode = class _AutocompleteNode extends lexical.TextNode {
|
|
|
1299
1425
|
static importJSON(serializedNode) {
|
|
1300
1426
|
return new _AutocompleteNode(serializedNode.text, serializedNode.uuid);
|
|
1301
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
|
+
}
|
|
1302
1435
|
exportJSON() {
|
|
1303
1436
|
return { ...super.exportJSON(), uuid: this.__uuid };
|
|
1304
1437
|
}
|
|
@@ -1613,13 +1746,20 @@ function VideoResizer({
|
|
|
1613
1746
|
const dy = ev.clientY - rs.startY;
|
|
1614
1747
|
let newW = rs.startW;
|
|
1615
1748
|
let newH = rs.startH;
|
|
1616
|
-
if (dir === "se") {
|
|
1749
|
+
if (dir === "se" || dir === "ne") {
|
|
1617
1750
|
newW = Math.max(MIN_WIDTH, rs.startW + dx);
|
|
1618
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;
|
|
1619
1755
|
} else if (dir === "e") {
|
|
1620
1756
|
newW = Math.max(MIN_WIDTH, rs.startW + dx);
|
|
1757
|
+
} else if (dir === "w") {
|
|
1758
|
+
newW = Math.max(MIN_WIDTH, rs.startW - dx);
|
|
1621
1759
|
} else if (dir === "s") {
|
|
1622
1760
|
newH = Math.max(MIN_HEIGHT, rs.startH + dy);
|
|
1761
|
+
} else if (dir === "n") {
|
|
1762
|
+
newH = Math.max(MIN_HEIGHT, rs.startH - dy);
|
|
1623
1763
|
}
|
|
1624
1764
|
container.style.width = `${newW}px`;
|
|
1625
1765
|
container.style.height = `${newH}px`;
|
|
@@ -1639,13 +1779,23 @@ function VideoResizer({
|
|
|
1639
1779
|
/* @__PURE__ */ jsxRuntime.jsx(
|
|
1640
1780
|
"div",
|
|
1641
1781
|
{
|
|
1642
|
-
style: {
|
|
1643
|
-
|
|
1644
|
-
|
|
1645
|
-
|
|
1646
|
-
|
|
1647
|
-
|
|
1648
|
-
|
|
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" },
|
|
1649
1799
|
onPointerDown: (e) => startResize(e, "e"),
|
|
1650
1800
|
title: "Resize width"
|
|
1651
1801
|
}
|
|
@@ -1653,13 +1803,15 @@ function VideoResizer({
|
|
|
1653
1803
|
/* @__PURE__ */ jsxRuntime.jsx(
|
|
1654
1804
|
"div",
|
|
1655
1805
|
{
|
|
1656
|
-
style: {
|
|
1657
|
-
|
|
1658
|
-
|
|
1659
|
-
|
|
1660
|
-
|
|
1661
|
-
|
|
1662
|
-
|
|
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" },
|
|
1663
1815
|
onPointerDown: (e) => startResize(e, "s"),
|
|
1664
1816
|
title: "Resize height"
|
|
1665
1817
|
}
|
|
@@ -1667,15 +1819,30 @@ function VideoResizer({
|
|
|
1667
1819
|
/* @__PURE__ */ jsxRuntime.jsx(
|
|
1668
1820
|
"div",
|
|
1669
1821
|
{
|
|
1670
|
-
style: { ...handleBase, bottom: -5,
|
|
1671
|
-
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"),
|
|
1672
1840
|
title: "Resize (proportional)"
|
|
1673
1841
|
}
|
|
1674
1842
|
)
|
|
1675
1843
|
] });
|
|
1676
1844
|
}
|
|
1677
1845
|
function YouTubeComponent({
|
|
1678
|
-
className,
|
|
1679
1846
|
format,
|
|
1680
1847
|
nodeKey,
|
|
1681
1848
|
videoID,
|
|
@@ -1683,9 +1850,48 @@ function YouTubeComponent({
|
|
|
1683
1850
|
height,
|
|
1684
1851
|
editor
|
|
1685
1852
|
}) {
|
|
1853
|
+
const wrapperRef = React9__namespace.useRef(null);
|
|
1686
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);
|
|
1687
1858
|
const [isHovered, setIsHovered] = React9__namespace.useState(false);
|
|
1688
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]);
|
|
1689
1895
|
const handleDelete = (e) => {
|
|
1690
1896
|
e.preventDefault();
|
|
1691
1897
|
e.stopPropagation();
|
|
@@ -1694,71 +1900,172 @@ function YouTubeComponent({
|
|
|
1694
1900
|
node?.remove();
|
|
1695
1901
|
});
|
|
1696
1902
|
};
|
|
1903
|
+
const handleResizeStart = () => {
|
|
1904
|
+
isResizingRef.current = true;
|
|
1905
|
+
setIsResizing(true);
|
|
1906
|
+
if (iframeRef.current) iframeRef.current.style.pointerEvents = "none";
|
|
1907
|
+
};
|
|
1697
1908
|
const handleResizeEnd = (w, h) => {
|
|
1909
|
+
isResizingRef.current = false;
|
|
1698
1910
|
setIsResizing(false);
|
|
1911
|
+
if (iframeRef.current) iframeRef.current.style.pointerEvents = "";
|
|
1912
|
+
setIsHovered(true);
|
|
1699
1913
|
editor.update(() => {
|
|
1700
1914
|
const node = lexical.$getNodeByKey(nodeKey);
|
|
1701
|
-
if ($isYouTubeNode(node))
|
|
1702
|
-
node.setSize(Math.round(w), Math.round(h));
|
|
1703
|
-
}
|
|
1915
|
+
if ($isYouTubeNode(node)) node.setSize(Math.round(w), Math.round(h));
|
|
1704
1916
|
});
|
|
1705
1917
|
};
|
|
1706
|
-
|
|
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(
|
|
1707
1938
|
"div",
|
|
1708
1939
|
{
|
|
1709
1940
|
ref: containerRef,
|
|
1710
|
-
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
|
+
},
|
|
1711
1950
|
onMouseEnter: () => setIsHovered(true),
|
|
1712
1951
|
onMouseLeave: () => {
|
|
1713
|
-
if (!
|
|
1952
|
+
if (!isResizingRef.current) setIsHovered(false);
|
|
1714
1953
|
},
|
|
1715
1954
|
children: [
|
|
1716
|
-
|
|
1717
|
-
|
|
1718
|
-
|
|
1719
|
-
|
|
1720
|
-
|
|
1721
|
-
|
|
1722
|
-
allow: "accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture",
|
|
1723
|
-
allowFullScreen: true,
|
|
1724
|
-
title: "YouTube video",
|
|
1725
|
-
style: { display: "block", border: "none", pointerEvents: isResizing ? "none" : "auto" }
|
|
1726
|
-
}
|
|
1727
|
-
),
|
|
1728
|
-
isHovered && /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
|
|
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. */
|
|
1729
1961
|
/* @__PURE__ */ jsxRuntime.jsx(
|
|
1730
|
-
"
|
|
1962
|
+
"iframe",
|
|
1731
1963
|
{
|
|
1732
|
-
|
|
1733
|
-
|
|
1734
|
-
|
|
1735
|
-
|
|
1736
|
-
|
|
1737
|
-
|
|
1738
|
-
|
|
1739
|
-
|
|
1740
|
-
|
|
1741
|
-
borderRadius: "50%",
|
|
1742
|
-
background: "rgba(0,0,0,0.65)",
|
|
1743
|
-
color: "#fff",
|
|
1744
|
-
border: "none",
|
|
1745
|
-
cursor: "pointer",
|
|
1746
|
-
fontSize: 18,
|
|
1747
|
-
lineHeight: 1,
|
|
1748
|
-
padding: 0,
|
|
1749
|
-
zIndex: 10,
|
|
1750
|
-
display: "flex",
|
|
1751
|
-
alignItems: "center",
|
|
1752
|
-
justifyContent: "center"
|
|
1753
|
-
},
|
|
1754
|
-
children: "\xD7"
|
|
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" }
|
|
1755
1973
|
}
|
|
1756
|
-
)
|
|
1757
|
-
|
|
1758
|
-
|
|
1759
|
-
|
|
1760
|
-
|
|
1761
|
-
|
|
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,
|
|
1762
2069
|
onResizeEnd: handleResizeEnd
|
|
1763
2070
|
}
|
|
1764
2071
|
)
|
|
@@ -1819,6 +2126,7 @@ var YouTubeNode = class _YouTubeNode extends LexicalDecoratorBlockNode.Decorator
|
|
|
1819
2126
|
iframe.setAttribute("width", String(this.__width));
|
|
1820
2127
|
iframe.setAttribute("height", String(this.__height));
|
|
1821
2128
|
iframe.style.border = "none";
|
|
2129
|
+
iframe.setAttribute("sandbox", "allow-same-origin allow-scripts allow-popups allow-presentation");
|
|
1822
2130
|
iframe.setAttribute(
|
|
1823
2131
|
"allow",
|
|
1824
2132
|
"accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture"
|
|
@@ -1846,16 +2154,10 @@ var YouTubeNode = class _YouTubeNode extends LexicalDecoratorBlockNode.Decorator
|
|
|
1846
2154
|
writable.__width = width;
|
|
1847
2155
|
writable.__height = height;
|
|
1848
2156
|
}
|
|
1849
|
-
decorate(_editor,
|
|
1850
|
-
const embedBlockTheme = config.theme.embedBlock || {};
|
|
1851
|
-
const className = {
|
|
1852
|
-
base: embedBlockTheme.base || "",
|
|
1853
|
-
focus: embedBlockTheme.focus || ""
|
|
1854
|
-
};
|
|
2157
|
+
decorate(_editor, _config) {
|
|
1855
2158
|
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
1856
2159
|
YouTubeComponent,
|
|
1857
2160
|
{
|
|
1858
|
-
className,
|
|
1859
2161
|
format: this.__format,
|
|
1860
2162
|
nodeKey: this.getKey(),
|
|
1861
2163
|
videoID: this.__id,
|
|
@@ -2221,12 +2523,12 @@ function useFloatingPortalContainer(editor) {
|
|
|
2221
2523
|
}, [editor]);
|
|
2222
2524
|
return container;
|
|
2223
2525
|
}
|
|
2224
|
-
function setPopupPositionFixed(popupEl, rect) {
|
|
2526
|
+
function setPopupPositionFixed(popupEl, rect, topBoundary) {
|
|
2225
2527
|
const GAP = 8;
|
|
2226
2528
|
const MARGIN = 8;
|
|
2227
2529
|
let top = rect.top - popupEl.offsetHeight - GAP;
|
|
2228
|
-
let left = rect.left
|
|
2229
|
-
if (top <
|
|
2530
|
+
let left = rect.left;
|
|
2531
|
+
if (top < topBoundary) top = rect.bottom + GAP;
|
|
2230
2532
|
left = clamp2(left, MARGIN, window.innerWidth - popupEl.offsetWidth - MARGIN);
|
|
2231
2533
|
popupEl.style.top = `${top}px`;
|
|
2232
2534
|
popupEl.style.left = `${left}px`;
|
|
@@ -2268,10 +2570,22 @@ function FloatingCharacterStylesEditor({
|
|
|
2268
2570
|
popupEl.classList.remove("is-open");
|
|
2269
2571
|
return;
|
|
2270
2572
|
}
|
|
2271
|
-
|
|
2272
|
-
|
|
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;
|
|
2273
2587
|
if (!mouseDownRef.current) {
|
|
2274
|
-
setPopupPositionFixed(popupEl, rect);
|
|
2588
|
+
setPopupPositionFixed(popupEl, rect, topBoundary);
|
|
2275
2589
|
}
|
|
2276
2590
|
popupEl.classList.add("is-open");
|
|
2277
2591
|
}, [editor]);
|
|
@@ -2479,6 +2793,11 @@ function useCharacterStylesPopup(editor, opts) {
|
|
|
2479
2793
|
setIsText(false);
|
|
2480
2794
|
return;
|
|
2481
2795
|
}
|
|
2796
|
+
const activeElement = document.activeElement;
|
|
2797
|
+
if (activeElement && activeElement !== document.body && rootElement && !rootElement.contains(activeElement)) {
|
|
2798
|
+
setIsText(false);
|
|
2799
|
+
return;
|
|
2800
|
+
}
|
|
2482
2801
|
if (!lexical.$isRangeSelection(selection)) return;
|
|
2483
2802
|
const node = getSelectedNode(selection);
|
|
2484
2803
|
setIsBold(selection.hasFormat("bold"));
|
|
@@ -2499,7 +2818,11 @@ function useCharacterStylesPopup(editor, opts) {
|
|
|
2499
2818
|
}, [editor]);
|
|
2500
2819
|
React9.useEffect(() => {
|
|
2501
2820
|
document.addEventListener("selectionchange", updatePopupState);
|
|
2502
|
-
|
|
2821
|
+
document.addEventListener("focusin", updatePopupState);
|
|
2822
|
+
return () => {
|
|
2823
|
+
document.removeEventListener("selectionchange", updatePopupState);
|
|
2824
|
+
document.removeEventListener("focusin", updatePopupState);
|
|
2825
|
+
};
|
|
2503
2826
|
}, [updatePopupState]);
|
|
2504
2827
|
React9.useEffect(() => editor.registerUpdateListener(updatePopupState), [editor, updatePopupState]);
|
|
2505
2828
|
if (!portalContainer || !isText || isLink) return null;
|
|
@@ -2757,34 +3080,57 @@ function normalizeToBlockHtml(html) {
|
|
|
2757
3080
|
if (pendingP) body.appendChild(pendingP);
|
|
2758
3081
|
return body.innerHTML;
|
|
2759
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
|
+
}
|
|
2760
3108
|
var CustomOnChangePlugin = ({ value, onChange }) => {
|
|
2761
3109
|
const [editor] = LexicalComposerContext.useLexicalComposerContext();
|
|
2762
3110
|
const initializedRef = React9.useRef(false);
|
|
2763
|
-
const onChangeRef = React9.useRef(onChange);
|
|
2764
|
-
onChangeRef.current = onChange;
|
|
2765
3111
|
React9.useEffect(() => {
|
|
2766
3112
|
if (!value || initializedRef.current) return;
|
|
2767
3113
|
initializedRef.current = true;
|
|
2768
3114
|
editor.update(() => {
|
|
2769
3115
|
const root = lexical.$getRoot();
|
|
2770
3116
|
root.clear();
|
|
3117
|
+
const safe = sanitizeHtml(value);
|
|
3118
|
+
const cleaned = normalizeToBlockHtml(splitHeadingsAtBrSequences(safe));
|
|
2771
3119
|
const parser = new DOMParser();
|
|
2772
|
-
const dom = parser.parseFromString(
|
|
3120
|
+
const dom = parser.parseFromString(cleaned, "text/html");
|
|
2773
3121
|
const nodes = html.$generateNodesFromDOM(editor, dom);
|
|
2774
3122
|
root.append(...nodes);
|
|
2775
|
-
lexical.$setSelection(null);
|
|
2776
3123
|
});
|
|
2777
3124
|
}, [editor, value]);
|
|
2778
|
-
const handleChange = React9.useCallback((editorState) => {
|
|
2779
|
-
editorState.read(() => {
|
|
2780
|
-
onChangeRef.current(postProcessOutput(html.$generateHtmlFromNodes(editor)));
|
|
2781
|
-
});
|
|
2782
|
-
}, [editor]);
|
|
2783
3125
|
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
2784
3126
|
LexicalOnChangePlugin.OnChangePlugin,
|
|
2785
3127
|
{
|
|
2786
|
-
onChange:
|
|
2787
|
-
|
|
3128
|
+
onChange: (editorState) => {
|
|
3129
|
+
editorState.read(() => {
|
|
3130
|
+
const raw = html.$generateHtmlFromNodes(editor);
|
|
3131
|
+
onChange(postProcessOutput(splitHeadingsAtBrSequences(raw)));
|
|
3132
|
+
});
|
|
3133
|
+
}
|
|
2788
3134
|
}
|
|
2789
3135
|
);
|
|
2790
3136
|
};
|
|
@@ -2878,7 +3224,7 @@ var FloatingLinkEditor = ({ editor, isLink, setIsLink, anchorElem, isLinkEditMod
|
|
|
2878
3224
|
return;
|
|
2879
3225
|
}
|
|
2880
3226
|
const rootElement = editor.getRootElement();
|
|
2881
|
-
if (selection !== null && nativeSelection !== null && rootElement !== null && rootElement.contains(nativeSelection.anchorNode) && editor.isEditable()) {
|
|
3227
|
+
if (isLink && selection !== null && nativeSelection !== null && rootElement !== null && rootElement.contains(nativeSelection.anchorNode) && editor.isEditable()) {
|
|
2882
3228
|
const domRect = nativeSelection.focusNode?.parentElement?.getBoundingClientRect();
|
|
2883
3229
|
if (domRect) {
|
|
2884
3230
|
domRect.y += 40;
|
|
@@ -2894,7 +3240,7 @@ var FloatingLinkEditor = ({ editor, isLink, setIsLink, anchorElem, isLinkEditMod
|
|
|
2894
3240
|
setLinkUrl("");
|
|
2895
3241
|
}
|
|
2896
3242
|
return true;
|
|
2897
|
-
}, [anchorElem, editor, setIsLinkEditMode, isLinkEditMode, linkUrl]);
|
|
3243
|
+
}, [anchorElem, editor, setIsLinkEditMode, isLinkEditMode, isLink, linkUrl]);
|
|
2898
3244
|
React9.useEffect(() => {
|
|
2899
3245
|
const scrollerElem = anchorElem.parentElement;
|
|
2900
3246
|
const update = () => {
|
|
@@ -3001,17 +3347,20 @@ var FloatingLinkEditor = ({ editor, isLink, setIsLink, anchorElem, isLinkEditMod
|
|
|
3001
3347
|
}
|
|
3002
3348
|
}
|
|
3003
3349
|
),
|
|
3004
|
-
/* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
|
|
3350
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "link-input-actions", children: [
|
|
3005
3351
|
/* @__PURE__ */ jsxRuntime.jsx(
|
|
3006
3352
|
"div",
|
|
3007
3353
|
{
|
|
3008
3354
|
className: "link-cancel",
|
|
3009
3355
|
role: "button",
|
|
3010
3356
|
tabIndex: 0,
|
|
3357
|
+
title: "Cancel",
|
|
3358
|
+
"aria-label": "Cancel",
|
|
3011
3359
|
onMouseDown: preventDefault,
|
|
3012
3360
|
onClick: () => {
|
|
3013
3361
|
setIsLinkEditMode(false);
|
|
3014
|
-
}
|
|
3362
|
+
},
|
|
3363
|
+
children: /* @__PURE__ */ jsxRuntime.jsx(reactIcons.DismissRegular, { fontSize: 16 })
|
|
3015
3364
|
}
|
|
3016
3365
|
),
|
|
3017
3366
|
/* @__PURE__ */ jsxRuntime.jsx(
|
|
@@ -3020,8 +3369,11 @@ var FloatingLinkEditor = ({ editor, isLink, setIsLink, anchorElem, isLinkEditMod
|
|
|
3020
3369
|
className: "link-confirm",
|
|
3021
3370
|
role: "button",
|
|
3022
3371
|
tabIndex: 0,
|
|
3372
|
+
title: "Confirm",
|
|
3373
|
+
"aria-label": "Confirm",
|
|
3023
3374
|
onMouseDown: preventDefault,
|
|
3024
|
-
onClick: handleLinkSubmission
|
|
3375
|
+
onClick: handleLinkSubmission,
|
|
3376
|
+
children: /* @__PURE__ */ jsxRuntime.jsx(reactIcons.CheckmarkRegular, { fontSize: 16 })
|
|
3025
3377
|
}
|
|
3026
3378
|
)
|
|
3027
3379
|
] })
|
|
@@ -3041,12 +3393,15 @@ var FloatingLinkEditor = ({ editor, isLink, setIsLink, anchorElem, isLinkEditMod
|
|
|
3041
3393
|
className: "link-edit",
|
|
3042
3394
|
role: "button",
|
|
3043
3395
|
tabIndex: 0,
|
|
3396
|
+
title: "Edit link",
|
|
3397
|
+
"aria-label": "Edit link",
|
|
3044
3398
|
onMouseDown: preventDefault,
|
|
3045
3399
|
onClick: (event) => {
|
|
3046
3400
|
event.preventDefault();
|
|
3047
3401
|
setEditedLinkUrl(linkUrl);
|
|
3048
3402
|
setIsLinkEditMode(true);
|
|
3049
|
-
}
|
|
3403
|
+
},
|
|
3404
|
+
children: /* @__PURE__ */ jsxRuntime.jsx(reactIcons.EditRegular, { fontSize: 16 })
|
|
3050
3405
|
}
|
|
3051
3406
|
),
|
|
3052
3407
|
/* @__PURE__ */ jsxRuntime.jsx(
|
|
@@ -3055,10 +3410,13 @@ var FloatingLinkEditor = ({ editor, isLink, setIsLink, anchorElem, isLinkEditMod
|
|
|
3055
3410
|
className: "link-trash",
|
|
3056
3411
|
role: "button",
|
|
3057
3412
|
tabIndex: 0,
|
|
3413
|
+
title: "Remove link",
|
|
3414
|
+
"aria-label": "Remove link",
|
|
3058
3415
|
onMouseDown: preventDefault,
|
|
3059
3416
|
onClick: () => {
|
|
3060
3417
|
editor.dispatchCommand(link.TOGGLE_LINK_COMMAND, null);
|
|
3061
|
-
}
|
|
3418
|
+
},
|
|
3419
|
+
children: /* @__PURE__ */ jsxRuntime.jsx(reactIcons.DeleteRegular, { fontSize: 16 })
|
|
3062
3420
|
}
|
|
3063
3421
|
)
|
|
3064
3422
|
] }) });
|
|
@@ -3141,8 +3499,6 @@ var FloatingLinkEditorPlugin = ({ anchorElem, isLinkEditMode, setIsLinkEditMode
|
|
|
3141
3499
|
setIsLinkEditMode
|
|
3142
3500
|
);
|
|
3143
3501
|
};
|
|
3144
|
-
|
|
3145
|
-
// src/Plugins/ImagePlugin.tsx
|
|
3146
3502
|
init_ImageNode();
|
|
3147
3503
|
var INSERT_IMAGE_COMMAND = lexical.createCommand("INSERT_IMAGE_COMMAND");
|
|
3148
3504
|
var readClipboardImageAsDataURL = async (event) => {
|
|
@@ -3170,7 +3526,7 @@ var InsertImageByURL = ({
|
|
|
3170
3526
|
const [src, setSrc] = React9.useState("");
|
|
3171
3527
|
const isDisabled = disabled || src === "";
|
|
3172
3528
|
return /* @__PURE__ */ jsxRuntime.jsxs(react.Stack, { tokens: { childrenGap: 6, padding: "10px 0px 0px 0px" }, children: [
|
|
3173
|
-
/* @__PURE__ */ jsxRuntime.jsx(reactComponents.Field, { label: "Enter URL",
|
|
3529
|
+
/* @__PURE__ */ jsxRuntime.jsx(reactComponents.Field, { label: "Enter URL", size: "small", children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
3174
3530
|
reactComponents.Input,
|
|
3175
3531
|
{
|
|
3176
3532
|
autoFocus: !disabled,
|
|
@@ -3181,7 +3537,7 @@ var InsertImageByURL = ({
|
|
|
3181
3537
|
value: src
|
|
3182
3538
|
}
|
|
3183
3539
|
) }),
|
|
3184
|
-
/* @__PURE__ */ jsxRuntime.jsx(reactComponents.Field, { label: "Alt Text",
|
|
3540
|
+
/* @__PURE__ */ jsxRuntime.jsx(reactComponents.Field, { label: "Alt Text", size: "small", children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
3185
3541
|
reactComponents.Input,
|
|
3186
3542
|
{
|
|
3187
3543
|
placeholder: "Alt text",
|
|
@@ -3219,16 +3575,19 @@ var InsertImageByURL = ({
|
|
|
3219
3575
|
};
|
|
3220
3576
|
var InsertImageDialog = ({
|
|
3221
3577
|
activeEditor,
|
|
3222
|
-
disabled
|
|
3578
|
+
disabled,
|
|
3579
|
+
maxImageSizeMB,
|
|
3580
|
+
validationMessages
|
|
3223
3581
|
}) => {
|
|
3224
3582
|
const [src, setSrc] = React9.useState("");
|
|
3225
3583
|
const [altText, setAltText] = React9.useState("");
|
|
3226
3584
|
const [isOpen, setIsOpen] = React9.useState(false);
|
|
3227
3585
|
const [selectedValue, setSelectedValue] = React9.useState("Upload");
|
|
3228
3586
|
const [fileName, setFileName] = React9.useState("");
|
|
3587
|
+
const [fileSizeError, setFileSizeError] = React9.useState(null);
|
|
3229
3588
|
const hasModifier = React9.useRef(false);
|
|
3230
3589
|
const iconColor = disabled ? "var(--colorNeutralForegroundDisabled, #A6A6A6)" : "#333333";
|
|
3231
|
-
const isDisabled = disabled || src === "";
|
|
3590
|
+
const isDisabled = disabled || src === "" || !!fileSizeError;
|
|
3232
3591
|
React9.useEffect(() => {
|
|
3233
3592
|
hasModifier.current = false;
|
|
3234
3593
|
const handler = (e) => {
|
|
@@ -3244,31 +3603,44 @@ var InsertImageDialog = ({
|
|
|
3244
3603
|
setAltText("");
|
|
3245
3604
|
setSrc("");
|
|
3246
3605
|
setFileName("");
|
|
3606
|
+
setFileSizeError(null);
|
|
3247
3607
|
};
|
|
3248
3608
|
const loadImage = (event) => {
|
|
3249
3609
|
if (disabled) return;
|
|
3250
3610
|
const files = event.target.files;
|
|
3251
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);
|
|
3252
3626
|
const reader = new FileReader();
|
|
3253
3627
|
reader.onload = () => {
|
|
3254
3628
|
if (typeof reader.result === "string") {
|
|
3255
3629
|
setSrc(reader.result);
|
|
3256
|
-
setFileName(
|
|
3630
|
+
setFileName(file.name);
|
|
3257
3631
|
}
|
|
3258
3632
|
};
|
|
3259
|
-
reader.readAsDataURL(
|
|
3633
|
+
reader.readAsDataURL(file);
|
|
3260
3634
|
};
|
|
3261
3635
|
return /* @__PURE__ */ jsxRuntime.jsxs(
|
|
3262
|
-
reactComponents.
|
|
3636
|
+
reactComponents.Dialog,
|
|
3263
3637
|
{
|
|
3264
|
-
trapFocus: true,
|
|
3265
|
-
withArrow: true,
|
|
3266
3638
|
open: disabled ? false : isOpen,
|
|
3267
3639
|
onOpenChange: (_, data) => {
|
|
3268
3640
|
if (!disabled) setIsOpen(data.open);
|
|
3269
3641
|
},
|
|
3270
3642
|
children: [
|
|
3271
|
-
/* @__PURE__ */ jsxRuntime.jsx(reactComponents.
|
|
3643
|
+
/* @__PURE__ */ jsxRuntime.jsx(reactComponents.DialogTrigger, { disableButtonEnhancement: true, children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
3272
3644
|
reactComponents.Button,
|
|
3273
3645
|
{
|
|
3274
3646
|
size: "small",
|
|
@@ -3292,81 +3664,73 @@ var InsertImageDialog = ({
|
|
|
3292
3664
|
},
|
|
3293
3665
|
"upload-image"
|
|
3294
3666
|
) }),
|
|
3295
|
-
/* @__PURE__ */ jsxRuntime.jsxs(
|
|
3296
|
-
reactComponents.
|
|
3297
|
-
{
|
|
3298
|
-
|
|
3299
|
-
|
|
3300
|
-
|
|
3301
|
-
|
|
3302
|
-
|
|
3303
|
-
|
|
3304
|
-
|
|
3305
|
-
|
|
3306
|
-
|
|
3307
|
-
|
|
3308
|
-
|
|
3309
|
-
|
|
3310
|
-
|
|
3311
|
-
|
|
3312
|
-
|
|
3313
|
-
|
|
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(
|
|
3671
|
+
"label",
|
|
3672
|
+
{
|
|
3673
|
+
style: {
|
|
3674
|
+
cursor: disabled ? "not-allowed" : "pointer",
|
|
3675
|
+
display: "flex",
|
|
3676
|
+
alignItems: "center",
|
|
3677
|
+
gap: 8,
|
|
3678
|
+
opacity: disabled ? 0.75 : 1
|
|
3679
|
+
},
|
|
3680
|
+
children: [
|
|
3681
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
3682
|
+
"input",
|
|
3683
|
+
{
|
|
3684
|
+
type: "file",
|
|
3685
|
+
accept: "image/*",
|
|
3686
|
+
style: { display: "none" },
|
|
3687
|
+
disabled,
|
|
3688
|
+
onChange: loadImage
|
|
3314
3689
|
},
|
|
3315
|
-
|
|
3316
|
-
|
|
3317
|
-
|
|
3318
|
-
|
|
3319
|
-
|
|
3320
|
-
|
|
3321
|
-
|
|
3322
|
-
|
|
3323
|
-
|
|
3324
|
-
|
|
3325
|
-
|
|
3326
|
-
|
|
3327
|
-
|
|
3328
|
-
|
|
3329
|
-
|
|
3330
|
-
|
|
3331
|
-
|
|
3332
|
-
|
|
3333
|
-
|
|
3334
|
-
|
|
3335
|
-
|
|
3336
|
-
|
|
3337
|
-
|
|
3338
|
-
|
|
3339
|
-
|
|
3340
|
-
|
|
3341
|
-
|
|
3342
|
-
|
|
3343
|
-
|
|
3344
|
-
|
|
3345
|
-
|
|
3346
|
-
|
|
3347
|
-
|
|
3348
|
-
|
|
3349
|
-
|
|
3350
|
-
|
|
3351
|
-
|
|
3352
|
-
|
|
3353
|
-
|
|
3354
|
-
|
|
3355
|
-
|
|
3356
|
-
|
|
3357
|
-
|
|
3358
|
-
|
|
3359
|
-
selectedValue === "URL" && /* @__PURE__ */ jsxRuntime.jsx(
|
|
3360
|
-
InsertImageByURL,
|
|
3361
|
-
{
|
|
3362
|
-
disabled,
|
|
3363
|
-
setIsOpen: (open) => setIsOpen(open),
|
|
3364
|
-
onClick: (payload) => onClick(payload)
|
|
3365
|
-
}
|
|
3366
|
-
)
|
|
3367
|
-
]
|
|
3368
|
-
}
|
|
3369
|
-
)
|
|
3690
|
+
"inline-image-upload"
|
|
3691
|
+
),
|
|
3692
|
+
/* @__PURE__ */ jsxRuntime.jsxs(react.Stack, { horizontal: true, children: [
|
|
3693
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
3694
|
+
reactIcons.AttachFilled,
|
|
3695
|
+
{
|
|
3696
|
+
style: {
|
|
3697
|
+
fontSize: "16px",
|
|
3698
|
+
color: disabled ? "var(--colorNeutralForegroundDisabled, #A6A6A6)" : "#808080",
|
|
3699
|
+
marginTop: 2
|
|
3700
|
+
}
|
|
3701
|
+
}
|
|
3702
|
+
),
|
|
3703
|
+
!fileName && /* @__PURE__ */ jsxRuntime.jsx("span", { style: { fontSize: 12, color: "#808080" }, children: "Upload File" })
|
|
3704
|
+
] }),
|
|
3705
|
+
fileName && /* @__PURE__ */ jsxRuntime.jsx("span", { style: { fontSize: 12, color: "#808080" }, children: fileName })
|
|
3706
|
+
]
|
|
3707
|
+
}
|
|
3708
|
+
) }),
|
|
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(
|
|
3711
|
+
reactComponents.Input,
|
|
3712
|
+
{
|
|
3713
|
+
placeholder: "Alt text",
|
|
3714
|
+
appearance: "underline",
|
|
3715
|
+
disabled,
|
|
3716
|
+
onChange: (_, d) => setAltText(d.value),
|
|
3717
|
+
value: altText
|
|
3718
|
+
}
|
|
3719
|
+
) }),
|
|
3720
|
+
selectedValue === "URL" && /* @__PURE__ */ jsxRuntime.jsx(
|
|
3721
|
+
InsertImageByURL,
|
|
3722
|
+
{
|
|
3723
|
+
disabled,
|
|
3724
|
+
setIsOpen: (open) => setIsOpen(open),
|
|
3725
|
+
onClick: (payload) => onClick(payload)
|
|
3726
|
+
}
|
|
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" })
|
|
3732
|
+
] })
|
|
3733
|
+
] }) })
|
|
3370
3734
|
]
|
|
3371
3735
|
}
|
|
3372
3736
|
);
|
|
@@ -3382,9 +3746,21 @@ var ImagesPlugin = ({ captionsEnabled }) => {
|
|
|
3382
3746
|
INSERT_IMAGE_COMMAND,
|
|
3383
3747
|
(payload) => {
|
|
3384
3748
|
const imageNode = $createImageNode(payload);
|
|
3385
|
-
lexical.$
|
|
3386
|
-
if (lexical.$
|
|
3387
|
-
|
|
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
|
+
}
|
|
3388
3764
|
}
|
|
3389
3765
|
return true;
|
|
3390
3766
|
},
|
|
@@ -3435,12 +3811,25 @@ var TRANSPARENT_IMAGE = "data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAA
|
|
|
3435
3811
|
var img = document.createElement("img");
|
|
3436
3812
|
img.src = TRANSPARENT_IMAGE;
|
|
3437
3813
|
var $onDragStart = (event) => {
|
|
3438
|
-
|
|
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
|
+
}
|
|
3439
3823
|
if (!node) return false;
|
|
3440
3824
|
const dataTransfer = event.dataTransfer;
|
|
3441
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
|
+
}
|
|
3442
3832
|
dataTransfer.setData("text/plain", "_");
|
|
3443
|
-
dataTransfer.setDragImage(img, 0, 0);
|
|
3444
3833
|
dataTransfer.setData(
|
|
3445
3834
|
"application/x-lexical-drag",
|
|
3446
3835
|
JSON.stringify({
|
|
@@ -3468,20 +3857,23 @@ var $onDragover = (event) => {
|
|
|
3468
3857
|
return true;
|
|
3469
3858
|
};
|
|
3470
3859
|
var $onDrop = (event, editor) => {
|
|
3471
|
-
const node = $getImageNodeInSelection();
|
|
3472
|
-
if (!node) return false;
|
|
3473
3860
|
const data = getDragImageData(event);
|
|
3474
3861
|
if (!data) return false;
|
|
3475
3862
|
event.preventDefault();
|
|
3476
3863
|
if (canDropImage(event)) {
|
|
3864
|
+
const sourceKey = data.key;
|
|
3865
|
+
if (sourceKey) {
|
|
3866
|
+
const sourceNode = lexical.$getNodeByKey(sourceKey);
|
|
3867
|
+
if (sourceNode) sourceNode.remove();
|
|
3868
|
+
}
|
|
3477
3869
|
const range = getDragSelection(event);
|
|
3478
|
-
node.remove();
|
|
3479
3870
|
const rangeSelection = lexical.$createRangeSelection();
|
|
3480
3871
|
if (range !== null && range !== void 0) {
|
|
3481
3872
|
rangeSelection.applyDOMRange(range);
|
|
3482
3873
|
}
|
|
3483
3874
|
lexical.$setSelection(rangeSelection);
|
|
3484
|
-
|
|
3875
|
+
const { key: _key, ...insertPayload } = data;
|
|
3876
|
+
editor.dispatchCommand(INSERT_IMAGE_COMMAND, insertPayload);
|
|
3485
3877
|
}
|
|
3486
3878
|
return true;
|
|
3487
3879
|
};
|
|
@@ -3501,7 +3893,7 @@ var getDragImageData = (event) => {
|
|
|
3501
3893
|
};
|
|
3502
3894
|
var canDropImage = (event) => {
|
|
3503
3895
|
const target = event.target;
|
|
3504
|
-
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"]'));
|
|
3505
3897
|
};
|
|
3506
3898
|
var getDragSelection = (event) => {
|
|
3507
3899
|
let range;
|
|
@@ -3516,8 +3908,6 @@ var getDragSelection = (event) => {
|
|
|
3516
3908
|
}
|
|
3517
3909
|
return range;
|
|
3518
3910
|
};
|
|
3519
|
-
|
|
3520
|
-
// src/Plugins/InlineImage.tsx
|
|
3521
3911
|
init_InlineImage();
|
|
3522
3912
|
init_InlineImageNode();
|
|
3523
3913
|
var INSERT_INLINE_IMAGE_COMMAND = lexical.createCommand(
|
|
@@ -3535,7 +3925,9 @@ var useStyles = reactComponents.makeStyles({
|
|
|
3535
3925
|
});
|
|
3536
3926
|
var InsertInlineImageDialog = ({
|
|
3537
3927
|
disabled,
|
|
3538
|
-
activeEditor
|
|
3928
|
+
activeEditor,
|
|
3929
|
+
maxImageSizeMB,
|
|
3930
|
+
validationMessages
|
|
3539
3931
|
}) => {
|
|
3540
3932
|
const hasModifier = React9.useRef(false);
|
|
3541
3933
|
const [src, setSrc] = React9.useState("");
|
|
@@ -3543,21 +3935,36 @@ var InsertInlineImageDialog = ({
|
|
|
3543
3935
|
const [altText, setAltText] = React9.useState("");
|
|
3544
3936
|
const [fileName, setFileName] = React9.useState("");
|
|
3545
3937
|
const [position, setPosition] = React9.useState("left");
|
|
3938
|
+
const [fileSizeError, setFileSizeError] = React9.useState(null);
|
|
3546
3939
|
const styles = useStyles();
|
|
3547
3940
|
const iconColor = disabled ? "var(--colorNeutralForegroundDisabled, #A6A6A6)" : "#333333";
|
|
3548
|
-
const isDisabled = disabled || src === "";
|
|
3941
|
+
const isDisabled = disabled || src === "" || !!fileSizeError;
|
|
3549
3942
|
const loadImage = (event) => {
|
|
3550
3943
|
if (disabled) return;
|
|
3551
3944
|
const files = event.target.files;
|
|
3552
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);
|
|
3553
3960
|
const reader = new FileReader();
|
|
3554
3961
|
reader.onload = () => {
|
|
3555
3962
|
if (typeof reader.result === "string") {
|
|
3556
3963
|
setSrc(reader.result);
|
|
3557
|
-
setFileName(
|
|
3964
|
+
setFileName(file.name);
|
|
3558
3965
|
}
|
|
3559
3966
|
};
|
|
3560
|
-
reader.readAsDataURL(
|
|
3967
|
+
reader.readAsDataURL(file);
|
|
3561
3968
|
};
|
|
3562
3969
|
React9.useEffect(() => {
|
|
3563
3970
|
const handler = (e) => {
|
|
@@ -3574,18 +3981,17 @@ var InsertInlineImageDialog = ({
|
|
|
3574
3981
|
setAltText("");
|
|
3575
3982
|
setSrc("");
|
|
3576
3983
|
setFileName("");
|
|
3984
|
+
setFileSizeError(null);
|
|
3577
3985
|
};
|
|
3578
3986
|
return /* @__PURE__ */ jsxRuntime.jsxs(
|
|
3579
|
-
reactComponents.
|
|
3987
|
+
reactComponents.Dialog,
|
|
3580
3988
|
{
|
|
3581
|
-
trapFocus: true,
|
|
3582
|
-
withArrow: true,
|
|
3583
3989
|
open: disabled ? false : isOpen,
|
|
3584
3990
|
onOpenChange: (_, data) => {
|
|
3585
3991
|
if (!disabled) setIsOpen(data.open);
|
|
3586
3992
|
},
|
|
3587
3993
|
children: [
|
|
3588
|
-
/* @__PURE__ */ jsxRuntime.jsx(reactComponents.
|
|
3994
|
+
/* @__PURE__ */ jsxRuntime.jsx(reactComponents.DialogTrigger, { disableButtonEnhancement: true, children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
3589
3995
|
reactComponents.Button,
|
|
3590
3996
|
{
|
|
3591
3997
|
size: "small",
|
|
@@ -3609,104 +4015,100 @@ var InsertInlineImageDialog = ({
|
|
|
3609
4015
|
},
|
|
3610
4016
|
"upload-inline-image"
|
|
3611
4017
|
) }),
|
|
3612
|
-
/* @__PURE__ */ jsxRuntime.jsx(
|
|
3613
|
-
reactComponents.
|
|
3614
|
-
{
|
|
3615
|
-
|
|
3616
|
-
|
|
3617
|
-
|
|
3618
|
-
|
|
3619
|
-
|
|
3620
|
-
|
|
3621
|
-
|
|
3622
|
-
|
|
3623
|
-
|
|
3624
|
-
|
|
3625
|
-
|
|
3626
|
-
|
|
3627
|
-
|
|
3628
|
-
|
|
3629
|
-
|
|
3630
|
-
|
|
3631
|
-
|
|
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(
|
|
4022
|
+
"label",
|
|
4023
|
+
{
|
|
4024
|
+
style: {
|
|
4025
|
+
cursor: disabled ? "not-allowed" : "pointer",
|
|
4026
|
+
display: "flex",
|
|
4027
|
+
alignItems: "center",
|
|
4028
|
+
gap: 8,
|
|
4029
|
+
opacity: disabled ? 0.75 : 1
|
|
4030
|
+
},
|
|
4031
|
+
children: [
|
|
4032
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
4033
|
+
"input",
|
|
4034
|
+
{
|
|
4035
|
+
type: "file",
|
|
4036
|
+
accept: "image/*",
|
|
4037
|
+
style: { display: "none" },
|
|
4038
|
+
disabled,
|
|
4039
|
+
onChange: loadImage
|
|
4040
|
+
},
|
|
4041
|
+
"inline-image-upload"
|
|
4042
|
+
),
|
|
4043
|
+
/* @__PURE__ */ jsxRuntime.jsxs(react.Stack, { horizontal: true, children: [
|
|
3632
4044
|
/* @__PURE__ */ jsxRuntime.jsx(
|
|
3633
|
-
|
|
4045
|
+
reactIcons.AttachFilled,
|
|
3634
4046
|
{
|
|
3635
|
-
|
|
3636
|
-
|
|
3637
|
-
|
|
3638
|
-
|
|
3639
|
-
onChange: loadImage
|
|
3640
|
-
},
|
|
3641
|
-
"inline-image-upload"
|
|
3642
|
-
),
|
|
3643
|
-
/* @__PURE__ */ jsxRuntime.jsxs(react.Stack, { horizontal: true, children: [
|
|
3644
|
-
/* @__PURE__ */ jsxRuntime.jsx(
|
|
3645
|
-
reactIcons.AttachFilled,
|
|
3646
|
-
{
|
|
3647
|
-
style: {
|
|
3648
|
-
fontSize: "16px",
|
|
3649
|
-
color: disabled ? "var(--colorNeutralForegroundDisabled, #A6A6A6)" : "#808080",
|
|
3650
|
-
marginTop: 2
|
|
3651
|
-
}
|
|
4047
|
+
style: {
|
|
4048
|
+
fontSize: "16px",
|
|
4049
|
+
color: disabled ? "var(--colorNeutralForegroundDisabled, #A6A6A6)" : "#808080",
|
|
4050
|
+
marginTop: 2
|
|
3652
4051
|
}
|
|
3653
|
-
|
|
3654
|
-
|
|
3655
|
-
|
|
3656
|
-
|
|
3657
|
-
|
|
3658
|
-
|
|
3659
|
-
|
|
3660
|
-
|
|
3661
|
-
|
|
3662
|
-
|
|
3663
|
-
|
|
3664
|
-
|
|
3665
|
-
|
|
3666
|
-
|
|
3667
|
-
|
|
3668
|
-
|
|
3669
|
-
|
|
3670
|
-
|
|
3671
|
-
|
|
3672
|
-
|
|
3673
|
-
|
|
3674
|
-
|
|
3675
|
-
|
|
3676
|
-
|
|
3677
|
-
|
|
3678
|
-
|
|
3679
|
-
|
|
3680
|
-
|
|
3681
|
-
|
|
3682
|
-
|
|
3683
|
-
|
|
3684
|
-
|
|
3685
|
-
|
|
3686
|
-
|
|
3687
|
-
|
|
3688
|
-
|
|
3689
|
-
|
|
3690
|
-
|
|
3691
|
-
|
|
3692
|
-
|
|
3693
|
-
|
|
3694
|
-
|
|
3695
|
-
|
|
3696
|
-
|
|
3697
|
-
|
|
3698
|
-
|
|
3699
|
-
|
|
3700
|
-
|
|
3701
|
-
|
|
3702
|
-
|
|
3703
|
-
|
|
3704
|
-
|
|
3705
|
-
|
|
3706
|
-
|
|
3707
|
-
|
|
3708
|
-
|
|
3709
|
-
|
|
4052
|
+
}
|
|
4053
|
+
),
|
|
4054
|
+
!fileName && /* @__PURE__ */ jsxRuntime.jsx("span", { style: { fontSize: 12, color: "#808080" }, children: "Upload File" })
|
|
4055
|
+
] }),
|
|
4056
|
+
fileName && /* @__PURE__ */ jsxRuntime.jsx("span", { style: { fontSize: 12, color: "#808080" }, children: fileName })
|
|
4057
|
+
]
|
|
4058
|
+
}
|
|
4059
|
+
) }),
|
|
4060
|
+
/* @__PURE__ */ jsxRuntime.jsx(reactComponents.Field, { label: "Position", size: "small", children: /* @__PURE__ */ jsxRuntime.jsxs(
|
|
4061
|
+
reactComponents.Dropdown,
|
|
4062
|
+
{
|
|
4063
|
+
className: styles.alignDropdown,
|
|
4064
|
+
disabled,
|
|
4065
|
+
value: position === "full" ? "Full" : position === "right" ? "Right" : "Left",
|
|
4066
|
+
selectedOptions: [position ?? "left"],
|
|
4067
|
+
listbox: { style: { width: "120px" } },
|
|
4068
|
+
root: { style: { borderBottom: "1px solid black" } },
|
|
4069
|
+
onOptionSelect: (_, data) => setPosition(data.optionValue),
|
|
4070
|
+
children: [
|
|
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")
|
|
4074
|
+
]
|
|
4075
|
+
}
|
|
4076
|
+
) }),
|
|
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(
|
|
4079
|
+
reactComponents.Input,
|
|
4080
|
+
{
|
|
4081
|
+
placeholder: "Alt text",
|
|
4082
|
+
appearance: "underline",
|
|
4083
|
+
disabled,
|
|
4084
|
+
value: altText,
|
|
4085
|
+
onChange: (_, d) => setAltText(d.value)
|
|
4086
|
+
}
|
|
4087
|
+
) })
|
|
4088
|
+
] }) }),
|
|
4089
|
+
/* @__PURE__ */ jsxRuntime.jsxs(reactComponents.DialogActions, { children: [
|
|
4090
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
4091
|
+
reactComponents.Button,
|
|
4092
|
+
{
|
|
4093
|
+
size: "small",
|
|
4094
|
+
disabled: isDisabled,
|
|
4095
|
+
onClick: handleOnClick,
|
|
4096
|
+
children: "Add"
|
|
4097
|
+
},
|
|
4098
|
+
"file-inline-upload-btn"
|
|
4099
|
+
),
|
|
4100
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
4101
|
+
reactComponents.Button,
|
|
4102
|
+
{
|
|
4103
|
+
size: "small",
|
|
4104
|
+
disabled,
|
|
4105
|
+
onClick: () => setIsOpen(false),
|
|
4106
|
+
children: "Cancel"
|
|
4107
|
+
},
|
|
4108
|
+
"file-inline-upload-cancel"
|
|
4109
|
+
)
|
|
4110
|
+
] })
|
|
4111
|
+
] }) })
|
|
3710
4112
|
]
|
|
3711
4113
|
}
|
|
3712
4114
|
);
|
|
@@ -3726,6 +4128,11 @@ var InlineImagePlugin = () => {
|
|
|
3726
4128
|
if (lexical.$isRootOrShadowRoot(imageNode.getParentOrThrow())) {
|
|
3727
4129
|
utils.$wrapNodeInElement(imageNode, lexical.$createParagraphNode).selectEnd();
|
|
3728
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
|
+
}
|
|
3729
4136
|
return true;
|
|
3730
4137
|
},
|
|
3731
4138
|
lexical.COMMAND_PRIORITY_EDITOR
|
|
@@ -3754,12 +4161,23 @@ var TRANSPARENT_IMAGE2 = "data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEA
|
|
|
3754
4161
|
var img2 = document.createElement("img");
|
|
3755
4162
|
img2.src = TRANSPARENT_IMAGE2;
|
|
3756
4163
|
function $onDragStart2(event) {
|
|
3757
|
-
|
|
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
|
+
}
|
|
3758
4171
|
if (!node) return false;
|
|
3759
4172
|
const dataTransfer = event.dataTransfer;
|
|
3760
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
|
+
}
|
|
3761
4180
|
dataTransfer.setData("text/plain", "_");
|
|
3762
|
-
dataTransfer.setDragImage(img2, 0, 0);
|
|
3763
4181
|
dataTransfer.setData(
|
|
3764
4182
|
"application/x-lexical-drag",
|
|
3765
4183
|
JSON.stringify({
|
|
@@ -3778,28 +4196,31 @@ function $onDragStart2(event) {
|
|
|
3778
4196
|
return true;
|
|
3779
4197
|
}
|
|
3780
4198
|
var $onDragover2 = (event) => {
|
|
3781
|
-
const
|
|
3782
|
-
if (!
|
|
4199
|
+
const hasDragData = !!event.dataTransfer?.types.includes("application/x-lexical-drag");
|
|
4200
|
+
if (!hasDragData) return false;
|
|
3783
4201
|
if (!canDropImage2(event)) {
|
|
3784
4202
|
event.preventDefault();
|
|
3785
4203
|
}
|
|
3786
4204
|
return true;
|
|
3787
4205
|
};
|
|
3788
4206
|
var $onDrop2 = (event, editor) => {
|
|
3789
|
-
const node = $getImageNodeInSelection2();
|
|
3790
|
-
if (!node) return false;
|
|
3791
4207
|
const data = getDragImageData2(event);
|
|
3792
4208
|
if (!data) return false;
|
|
3793
4209
|
event.preventDefault();
|
|
3794
4210
|
if (canDropImage2(event)) {
|
|
4211
|
+
const sourceKey = data.key;
|
|
4212
|
+
if (sourceKey) {
|
|
4213
|
+
const sourceNode = lexical.$getNodeByKey(sourceKey);
|
|
4214
|
+
if (sourceNode) sourceNode.remove();
|
|
4215
|
+
}
|
|
3795
4216
|
const range = getDragSelection2(event);
|
|
3796
|
-
node.remove();
|
|
3797
4217
|
const rangeSelection = lexical.$createRangeSelection();
|
|
3798
4218
|
if (range !== null && range !== void 0) {
|
|
3799
4219
|
rangeSelection.applyDOMRange(range);
|
|
3800
4220
|
}
|
|
3801
4221
|
lexical.$setSelection(rangeSelection);
|
|
3802
|
-
|
|
4222
|
+
const { key: _key, ...insertPayload } = data;
|
|
4223
|
+
editor.dispatchCommand(INSERT_INLINE_IMAGE_COMMAND, insertPayload);
|
|
3803
4224
|
}
|
|
3804
4225
|
return true;
|
|
3805
4226
|
};
|
|
@@ -3819,7 +4240,7 @@ var getDragImageData2 = (event) => {
|
|
|
3819
4240
|
};
|
|
3820
4241
|
var canDropImage2 = (event) => {
|
|
3821
4242
|
const target = event.target;
|
|
3822
|
-
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"]'));
|
|
3823
4244
|
};
|
|
3824
4245
|
var getDragSelection2 = (event) => {
|
|
3825
4246
|
let range;
|
|
@@ -3910,20 +4331,79 @@ function hasBlock(editor, kind) {
|
|
|
3910
4331
|
}
|
|
3911
4332
|
|
|
3912
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
|
+
}
|
|
3913
4371
|
function RefApiPlugin({
|
|
3914
4372
|
forwardedRef,
|
|
3915
4373
|
contentEditableDomRef,
|
|
3916
|
-
focusedRef
|
|
3917
|
-
setRefErrors
|
|
4374
|
+
focusedRef
|
|
3918
4375
|
}) {
|
|
3919
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]);
|
|
3920
4399
|
React9.useImperativeHandle(
|
|
3921
4400
|
forwardedRef,
|
|
3922
4401
|
() => ({
|
|
3923
4402
|
setValue: (html$1) => {
|
|
3924
4403
|
editor.update(() => {
|
|
4404
|
+
const safe = normalizeToBlockHtml(sanitizeHtml(html$1 || ""));
|
|
3925
4405
|
const parser = new DOMParser();
|
|
3926
|
-
const dom = parser.parseFromString(
|
|
4406
|
+
const dom = parser.parseFromString(safe || "<p></p>", "text/html");
|
|
3927
4407
|
const nodes = html.$generateNodesFromDOM(editor, dom);
|
|
3928
4408
|
const root = lexical.$getRoot();
|
|
3929
4409
|
root.clear();
|
|
@@ -3933,9 +4413,9 @@ function RefApiPlugin({
|
|
|
3933
4413
|
getValue: () => {
|
|
3934
4414
|
let html$1 = "";
|
|
3935
4415
|
editor.getEditorState().read(() => {
|
|
3936
|
-
html$1 = html.$generateHtmlFromNodes(editor, null);
|
|
4416
|
+
html$1 = postProcessOutput(splitHeadingsAtBrSequences(html.$generateHtmlFromNodes(editor, null)));
|
|
3937
4417
|
});
|
|
3938
|
-
return
|
|
4418
|
+
return html$1;
|
|
3939
4419
|
},
|
|
3940
4420
|
clear: () => {
|
|
3941
4421
|
editor.update(() => {
|
|
@@ -3953,14 +4433,20 @@ function RefApiPlugin({
|
|
|
3953
4433
|
},
|
|
3954
4434
|
isFocused: () => focusedRef.current,
|
|
3955
4435
|
getEditor: () => editor,
|
|
3956
|
-
setErrors: (messages) => setRefErrors(messages),
|
|
3957
|
-
clearErrors: () => setRefErrors([]),
|
|
3958
4436
|
// Generic blocks (signature, footer, banner, etc.)
|
|
3959
4437
|
upsertBlock: (spec) => upsertBlock(editor, spec),
|
|
3960
4438
|
removeBlock: (kind) => removeBlock(editor, kind),
|
|
3961
|
-
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
|
+
}
|
|
3962
4448
|
}),
|
|
3963
|
-
[editor, contentEditableDomRef, focusedRef
|
|
4449
|
+
[editor, contentEditableDomRef, focusedRef]
|
|
3964
4450
|
);
|
|
3965
4451
|
return null;
|
|
3966
4452
|
}
|
|
@@ -4601,8 +5087,22 @@ function TableActionMenuPlugin({ disabled = false }) {
|
|
|
4601
5087
|
const [editor] = LexicalComposerContext.useLexicalComposerContext();
|
|
4602
5088
|
const [isInTable, setIsInTable] = React9__namespace.useState(false);
|
|
4603
5089
|
const [anchorRect, setAnchorRect] = React9__namespace.useState(null);
|
|
5090
|
+
const [contentRight, setContentRight] = React9__namespace.useState(null);
|
|
4604
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
|
+
}, []);
|
|
4605
5104
|
const updateFromSelection = React9__namespace.useCallback(() => {
|
|
5105
|
+
if (openRef.current) return;
|
|
4606
5106
|
const root = editor.getRootElement();
|
|
4607
5107
|
if (!root) return;
|
|
4608
5108
|
editor.getEditorState().read(() => {
|
|
@@ -4614,6 +5114,7 @@ function TableActionMenuPlugin({ disabled = false }) {
|
|
|
4614
5114
|
if (dom) {
|
|
4615
5115
|
setIsInTable(true);
|
|
4616
5116
|
setAnchorRect(dom.getBoundingClientRect());
|
|
5117
|
+
setContentRight(null);
|
|
4617
5118
|
return;
|
|
4618
5119
|
}
|
|
4619
5120
|
}
|
|
@@ -4621,6 +5122,7 @@ function TableActionMenuPlugin({ disabled = false }) {
|
|
|
4621
5122
|
if (!lexical.$isRangeSelection(selection)) {
|
|
4622
5123
|
setIsInTable(false);
|
|
4623
5124
|
setAnchorRect(null);
|
|
5125
|
+
setContentRight(null);
|
|
4624
5126
|
return;
|
|
4625
5127
|
}
|
|
4626
5128
|
const anchorNode = selection.anchor.getNode();
|
|
@@ -4628,18 +5130,28 @@ function TableActionMenuPlugin({ disabled = false }) {
|
|
|
4628
5130
|
if (!cellNode || !table.$isTableCellNode(cellNode)) {
|
|
4629
5131
|
setIsInTable(false);
|
|
4630
5132
|
setAnchorRect(null);
|
|
5133
|
+
setContentRight(null);
|
|
4631
5134
|
return;
|
|
4632
5135
|
}
|
|
4633
5136
|
const cellDom = editor.getElementByKey(cellNode.getKey());
|
|
4634
5137
|
if (!cellDom) {
|
|
4635
5138
|
setIsInTable(false);
|
|
4636
5139
|
setAnchorRect(null);
|
|
5140
|
+
setContentRight(null);
|
|
4637
5141
|
return;
|
|
4638
5142
|
}
|
|
4639
5143
|
setIsInTable(true);
|
|
4640
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
|
+
}
|
|
4641
5153
|
});
|
|
4642
|
-
}, [editor]);
|
|
5154
|
+
}, [editor, measureContentRight]);
|
|
4643
5155
|
React9__namespace.useEffect(() => {
|
|
4644
5156
|
return utils.mergeRegister(
|
|
4645
5157
|
editor.registerCommand(
|
|
@@ -4696,30 +5208,37 @@ function TableActionMenuPlugin({ disabled = false }) {
|
|
|
4696
5208
|
lexical.COMMAND_PRIORITY_HIGH
|
|
4697
5209
|
);
|
|
4698
5210
|
}, [editor, disabled]);
|
|
4699
|
-
React9__namespace.useEffect(() => {
|
|
4700
|
-
if (!isInTable && open) setOpen(false);
|
|
4701
|
-
}, [isInTable, open]);
|
|
4702
5211
|
const canShow = isInTable && !!anchorRect && !disabled;
|
|
4703
5212
|
const handleStyle = React9__namespace.useMemo(() => {
|
|
4704
5213
|
if (!anchorRect) return void 0;
|
|
4705
5214
|
const top = Math.max(8, anchorRect.top + 6);
|
|
4706
|
-
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);
|
|
4707
5217
|
return {
|
|
4708
5218
|
position: "fixed",
|
|
4709
5219
|
top,
|
|
4710
5220
|
left,
|
|
4711
5221
|
zIndex: 9999
|
|
4712
5222
|
};
|
|
4713
|
-
}, [anchorRect]);
|
|
5223
|
+
}, [anchorRect, contentRight]);
|
|
4714
5224
|
const dangerStyle = {
|
|
4715
5225
|
color: "var(--colorPaletteRedForeground1)"
|
|
4716
5226
|
};
|
|
4717
5227
|
const run = React9__namespace.useCallback(
|
|
4718
5228
|
(fn) => {
|
|
4719
5229
|
if (disabled) return;
|
|
4720
|
-
|
|
4721
|
-
editor.update(() => fn());
|
|
5230
|
+
openRef.current = false;
|
|
4722
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
|
+
});
|
|
4723
5242
|
},
|
|
4724
5243
|
[disabled, editor]
|
|
4725
5244
|
);
|
|
@@ -4729,32 +5248,31 @@ function TableActionMenuPlugin({ disabled = false }) {
|
|
|
4729
5248
|
const insertColLeft = () => run(() => table.$insertTableColumnAtSelection(false));
|
|
4730
5249
|
const deleteRow = () => run(() => table.$deleteTableRowAtSelection());
|
|
4731
5250
|
const deleteCol = () => run(() => table.$deleteTableColumnAtSelection());
|
|
4732
|
-
const deleteTable = () =>
|
|
4733
|
-
|
|
4734
|
-
|
|
4735
|
-
|
|
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));
|
|
4736
5261
|
if (tableNode) tableNode.remove();
|
|
4737
|
-
|
|
4738
|
-
|
|
4739
|
-
if (!lexical.$isRangeSelection(selection)) return;
|
|
4740
|
-
const node = selection.anchor.getNode();
|
|
4741
|
-
const cell = lexical.$findMatchingParent(node, (n) => table.$isTableCellNode(n)) ?? (table.$isTableCellNode(node) ? node : null);
|
|
4742
|
-
if (!cell) return;
|
|
4743
|
-
const table$1 = table.$getTableNodeFromLexicalNodeOrThrow(cell);
|
|
4744
|
-
table$1.remove();
|
|
4745
|
-
});
|
|
5262
|
+
});
|
|
5263
|
+
};
|
|
4746
5264
|
if (!canShow || !handleStyle) return null;
|
|
4747
5265
|
return reactDom.createPortal(
|
|
4748
|
-
/* @__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: [
|
|
4749
5270
|
/* @__PURE__ */ jsxRuntime.jsx(reactComponents.MenuTrigger, { disableButtonEnhancement: true, children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
4750
5271
|
"button",
|
|
4751
5272
|
{
|
|
4752
5273
|
type: "button",
|
|
4753
5274
|
className: "aoTableActionHandleBtn",
|
|
4754
5275
|
"aria-label": "Table options",
|
|
4755
|
-
onMouseDown: (e) => {
|
|
4756
|
-
e.preventDefault();
|
|
4757
|
-
},
|
|
4758
5276
|
children: /* @__PURE__ */ jsxRuntime.jsx(reactIcons.ChevronDown12Regular, {})
|
|
4759
5277
|
}
|
|
4760
5278
|
) }),
|
|
@@ -5105,6 +5623,85 @@ function getToolbarGroupsByLevel(level) {
|
|
|
5105
5623
|
];
|
|
5106
5624
|
}
|
|
5107
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
|
+
};
|
|
5108
5705
|
var PRESET = [
|
|
5109
5706
|
"#000000",
|
|
5110
5707
|
"#434343",
|
|
@@ -5388,7 +5985,7 @@ var ColorPickerControl = ({ value, title, disabled, onChange, icon, onOpenChange
|
|
|
5388
5985
|
directionalHint: 4,
|
|
5389
5986
|
className: "aoColorCallout",
|
|
5390
5987
|
preventDismissOnEvent,
|
|
5391
|
-
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: [
|
|
5392
5989
|
/* @__PURE__ */ jsxRuntime.jsxs("div", { style: { display: "flex", alignItems: "center", justifyContent: "space-between" }, children: [
|
|
5393
5990
|
/* @__PURE__ */ jsxRuntime.jsx("div", { style: { fontSize: 13, fontWeight: 600, color: "#242424", letterSpacing: 0.1 }, children: title }),
|
|
5394
5991
|
/* @__PURE__ */ jsxRuntime.jsx(
|
|
@@ -5401,8 +5998,8 @@ var ColorPickerControl = ({ value, title, disabled, onChange, icon, onOpenChange
|
|
|
5401
5998
|
display: "flex",
|
|
5402
5999
|
alignItems: "center",
|
|
5403
6000
|
justifyContent: "center",
|
|
5404
|
-
width:
|
|
5405
|
-
height:
|
|
6001
|
+
width: 18,
|
|
6002
|
+
height: 18,
|
|
5406
6003
|
padding: 0,
|
|
5407
6004
|
border: "none",
|
|
5408
6005
|
borderRadius: 4,
|
|
@@ -5425,7 +6022,7 @@ var ColorPickerControl = ({ value, title, disabled, onChange, icon, onOpenChange
|
|
|
5425
6022
|
style: {
|
|
5426
6023
|
position: "relative",
|
|
5427
6024
|
width: "100%",
|
|
5428
|
-
height:
|
|
6025
|
+
height: 125,
|
|
5429
6026
|
borderRadius: 8,
|
|
5430
6027
|
overflow: "hidden",
|
|
5431
6028
|
cursor: "crosshair",
|
|
@@ -5514,8 +6111,8 @@ var ColorPickerControl = ({ value, title, disabled, onChange, icon, onOpenChange
|
|
|
5514
6111
|
"div",
|
|
5515
6112
|
{
|
|
5516
6113
|
style: {
|
|
5517
|
-
width:
|
|
5518
|
-
height:
|
|
6114
|
+
width: 20,
|
|
6115
|
+
height: 20,
|
|
5519
6116
|
borderRadius: 6,
|
|
5520
6117
|
flexShrink: 0,
|
|
5521
6118
|
background: hex,
|
|
@@ -5556,10 +6153,10 @@ var ColorPickerControl = ({ value, title, disabled, onChange, icon, onOpenChange
|
|
|
5556
6153
|
title: c,
|
|
5557
6154
|
"aria-label": c,
|
|
5558
6155
|
style: {
|
|
5559
|
-
width:
|
|
5560
|
-
height:
|
|
6156
|
+
width: 18,
|
|
6157
|
+
height: 18,
|
|
5561
6158
|
padding: 0,
|
|
5562
|
-
borderRadius:
|
|
6159
|
+
borderRadius: 4,
|
|
5563
6160
|
background: c,
|
|
5564
6161
|
cursor: "pointer",
|
|
5565
6162
|
boxShadow: isSelected ? "0 0 0 2px #fff, 0 0 0 3px #4a86e8" : "inset 0 0 0 1px rgba(0,0,0,0.15)",
|
|
@@ -5769,7 +6366,6 @@ var FontFamilyPlugin = ({ disabled = false }) => {
|
|
|
5769
6366
|
"font-family"
|
|
5770
6367
|
);
|
|
5771
6368
|
};
|
|
5772
|
-
var DEFAULT_FONT_SIZE = 15;
|
|
5773
6369
|
var FONT_SIZE_OPTIONS = [
|
|
5774
6370
|
"8",
|
|
5775
6371
|
"9",
|
|
@@ -5905,104 +6501,42 @@ var FontSizePlugin = ({ disabled }) => {
|
|
|
5905
6501
|
"fontsize"
|
|
5906
6502
|
) });
|
|
5907
6503
|
};
|
|
5908
|
-
var InsertLinkPlugin = ({
|
|
6504
|
+
var InsertLinkPlugin = ({
|
|
6505
|
+
disabled,
|
|
6506
|
+
setIsLinkEditMode
|
|
6507
|
+
}) => {
|
|
5909
6508
|
const [editor] = LexicalComposerContext.useLexicalComposerContext();
|
|
5910
|
-
const [isOpen, setIsOpen] = React9.useState(false);
|
|
5911
|
-
const [text, setText] = React9.useState("");
|
|
5912
|
-
const [link$1, setLink] = React9.useState("");
|
|
5913
6509
|
const iconColor = disabled ? "var(--colorNeutralForegroundDisabled, #A6A6A6)" : "#333333";
|
|
5914
|
-
const insertLink = (
|
|
6510
|
+
const insertLink = () => {
|
|
5915
6511
|
if (disabled) return;
|
|
5916
6512
|
editor.update(() => {
|
|
5917
|
-
setText("");
|
|
5918
|
-
setLink("");
|
|
5919
6513
|
const selection = lexical.$getSelection();
|
|
5920
|
-
if (lexical.$isRangeSelection(selection))
|
|
5921
|
-
|
|
5922
|
-
|
|
5923
|
-
|
|
5924
|
-
|
|
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://");
|
|
5925
6519
|
}
|
|
5926
|
-
setIsOpen(false);
|
|
5927
6520
|
});
|
|
6521
|
+
setIsLinkEditMode(true);
|
|
5928
6522
|
};
|
|
5929
|
-
return /* @__PURE__ */ jsxRuntime.
|
|
5930
|
-
reactComponents.
|
|
6523
|
+
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
6524
|
+
reactComponents.Button,
|
|
5931
6525
|
{
|
|
5932
|
-
|
|
5933
|
-
|
|
5934
|
-
|
|
5935
|
-
|
|
5936
|
-
|
|
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"
|
|
5937
6536
|
},
|
|
5938
|
-
|
|
5939
|
-
|
|
5940
|
-
|
|
5941
|
-
{
|
|
5942
|
-
size: "small",
|
|
5943
|
-
title: "Add link",
|
|
5944
|
-
disabled,
|
|
5945
|
-
icon: /* @__PURE__ */ jsxRuntime.jsx(reactIcons.LinkAddRegular, { style: { color: iconColor } }),
|
|
5946
|
-
style: {
|
|
5947
|
-
background: isOpen && !disabled ? "#ebebeb" : "none",
|
|
5948
|
-
border: "none",
|
|
5949
|
-
margin: 2,
|
|
5950
|
-
opacity: disabled ? 0.55 : 1,
|
|
5951
|
-
cursor: disabled ? "not-allowed" : "pointer"
|
|
5952
|
-
},
|
|
5953
|
-
onClick: () => {
|
|
5954
|
-
if (!disabled) setIsOpen((prev) => !prev);
|
|
5955
|
-
}
|
|
5956
|
-
},
|
|
5957
|
-
"upload-link"
|
|
5958
|
-
) }),
|
|
5959
|
-
/* @__PURE__ */ jsxRuntime.jsx(
|
|
5960
|
-
reactComponents.PopoverSurface,
|
|
5961
|
-
{
|
|
5962
|
-
style: {
|
|
5963
|
-
width: "270px",
|
|
5964
|
-
opacity: disabled ? 0.6 : 1,
|
|
5965
|
-
pointerEvents: disabled ? "none" : "auto"
|
|
5966
|
-
},
|
|
5967
|
-
children: /* @__PURE__ */ jsxRuntime.jsxs(react.Stack, { tokens: { childrenGap: 10 }, children: [
|
|
5968
|
-
/* @__PURE__ */ jsxRuntime.jsx(reactComponents.Field, { label: "Text", orientation: "horizontal", size: "small", children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
5969
|
-
reactComponents.Input,
|
|
5970
|
-
{
|
|
5971
|
-
autoFocus: !disabled,
|
|
5972
|
-
value: text,
|
|
5973
|
-
appearance: "underline",
|
|
5974
|
-
placeholder: "Text",
|
|
5975
|
-
disabled,
|
|
5976
|
-
onChange: (_, v) => setText(v.value)
|
|
5977
|
-
}
|
|
5978
|
-
) }),
|
|
5979
|
-
/* @__PURE__ */ jsxRuntime.jsx(reactComponents.Field, { label: "Link", orientation: "horizontal", size: "small", children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
5980
|
-
reactComponents.Input,
|
|
5981
|
-
{
|
|
5982
|
-
value: link$1,
|
|
5983
|
-
appearance: "underline",
|
|
5984
|
-
placeholder: "Link",
|
|
5985
|
-
disabled,
|
|
5986
|
-
onChange: (_, v) => setLink(v.value)
|
|
5987
|
-
}
|
|
5988
|
-
) }),
|
|
5989
|
-
/* @__PURE__ */ jsxRuntime.jsxs(react.Stack, { horizontal: true, horizontalAlign: "end", tokens: { childrenGap: 6 }, children: [
|
|
5990
|
-
/* @__PURE__ */ jsxRuntime.jsx(
|
|
5991
|
-
reactComponents.Button,
|
|
5992
|
-
{
|
|
5993
|
-
size: "small",
|
|
5994
|
-
disabled: disabled || !text || !link$1,
|
|
5995
|
-
onClick: () => insertLink(text, link$1),
|
|
5996
|
-
children: "Add"
|
|
5997
|
-
}
|
|
5998
|
-
),
|
|
5999
|
-
/* @__PURE__ */ jsxRuntime.jsx(reactComponents.Button, { size: "small", disabled, onClick: () => setIsOpen(false), children: "Cancel" })
|
|
6000
|
-
] })
|
|
6001
|
-
] })
|
|
6002
|
-
}
|
|
6003
|
-
)
|
|
6004
|
-
]
|
|
6005
|
-
}
|
|
6537
|
+
onClick: insertLink
|
|
6538
|
+
},
|
|
6539
|
+
"insert-link"
|
|
6006
6540
|
);
|
|
6007
6541
|
};
|
|
6008
6542
|
function PageSetupPlugin({ disabled, value, onChange }) {
|
|
@@ -6079,16 +6613,14 @@ var TableItemPlugin = ({ disabled }) => {
|
|
|
6079
6613
|
setIsOpen(false);
|
|
6080
6614
|
};
|
|
6081
6615
|
return /* @__PURE__ */ jsxRuntime.jsxs(
|
|
6082
|
-
reactComponents.
|
|
6616
|
+
reactComponents.Dialog,
|
|
6083
6617
|
{
|
|
6084
|
-
trapFocus: true,
|
|
6085
|
-
withArrow: true,
|
|
6086
6618
|
open: disabled ? false : isOpen,
|
|
6087
6619
|
onOpenChange: (_, data) => {
|
|
6088
6620
|
if (!disabled) setIsOpen(data.open);
|
|
6089
6621
|
},
|
|
6090
6622
|
children: [
|
|
6091
|
-
/* @__PURE__ */ jsxRuntime.jsx(reactComponents.
|
|
6623
|
+
/* @__PURE__ */ jsxRuntime.jsx(reactComponents.DialogTrigger, { disableButtonEnhancement: true, children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
6092
6624
|
reactComponents.Button,
|
|
6093
6625
|
{
|
|
6094
6626
|
size: "small",
|
|
@@ -6111,58 +6643,45 @@ var TableItemPlugin = ({ disabled }) => {
|
|
|
6111
6643
|
},
|
|
6112
6644
|
"insert-table-nodes"
|
|
6113
6645
|
) }),
|
|
6114
|
-
/* @__PURE__ */ jsxRuntime.jsx(
|
|
6115
|
-
reactComponents.
|
|
6116
|
-
{
|
|
6117
|
-
|
|
6118
|
-
|
|
6119
|
-
|
|
6120
|
-
|
|
6121
|
-
|
|
6122
|
-
|
|
6123
|
-
|
|
6124
|
-
|
|
6125
|
-
|
|
6126
|
-
|
|
6127
|
-
|
|
6128
|
-
|
|
6129
|
-
|
|
6130
|
-
|
|
6131
|
-
|
|
6132
|
-
|
|
6133
|
-
|
|
6134
|
-
|
|
6135
|
-
|
|
6136
|
-
|
|
6137
|
-
|
|
6138
|
-
|
|
6139
|
-
|
|
6140
|
-
|
|
6141
|
-
|
|
6142
|
-
|
|
6143
|
-
|
|
6144
|
-
|
|
6145
|
-
|
|
6146
|
-
|
|
6147
|
-
|
|
6148
|
-
|
|
6149
|
-
|
|
6150
|
-
|
|
6151
|
-
|
|
6152
|
-
|
|
6153
|
-
{
|
|
6154
|
-
size: "small",
|
|
6155
|
-
appearance: "primary",
|
|
6156
|
-
disabled: disabled || !rows || !columns,
|
|
6157
|
-
onClick: onAddTable,
|
|
6158
|
-
children: "Add"
|
|
6159
|
-
}
|
|
6160
|
-
),
|
|
6161
|
-
/* @__PURE__ */ jsxRuntime.jsx(reactComponents.Button, { size: "small", disabled, onClick: () => setIsOpen(false), children: "Cancel" })
|
|
6162
|
-
] })
|
|
6163
|
-
] })
|
|
6164
|
-
}
|
|
6165
|
-
)
|
|
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,
|
|
6651
|
+
{
|
|
6652
|
+
autoFocus: !disabled,
|
|
6653
|
+
value: rows,
|
|
6654
|
+
placeholder: "Rows",
|
|
6655
|
+
appearance: "underline",
|
|
6656
|
+
disabled,
|
|
6657
|
+
onChange: (_, v) => setRows(v.value)
|
|
6658
|
+
}
|
|
6659
|
+
) }),
|
|
6660
|
+
/* @__PURE__ */ jsxRuntime.jsx(reactComponents.Field, { label: "Columns", size: "small", children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
6661
|
+
reactComponents.Input,
|
|
6662
|
+
{
|
|
6663
|
+
value: columns,
|
|
6664
|
+
placeholder: "Columns",
|
|
6665
|
+
appearance: "underline",
|
|
6666
|
+
disabled,
|
|
6667
|
+
onChange: (_, v) => setColumns(v.value)
|
|
6668
|
+
}
|
|
6669
|
+
) })
|
|
6670
|
+
] }) }),
|
|
6671
|
+
/* @__PURE__ */ jsxRuntime.jsxs(reactComponents.DialogActions, { children: [
|
|
6672
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
6673
|
+
reactComponents.Button,
|
|
6674
|
+
{
|
|
6675
|
+
size: "small",
|
|
6676
|
+
appearance: "primary",
|
|
6677
|
+
disabled: disabled || !rows || !columns,
|
|
6678
|
+
onClick: onAddTable,
|
|
6679
|
+
children: "Add"
|
|
6680
|
+
}
|
|
6681
|
+
),
|
|
6682
|
+
/* @__PURE__ */ jsxRuntime.jsx(reactComponents.Button, { size: "small", disabled, onClick: () => setIsOpen(false), children: "Cancel" })
|
|
6683
|
+
] })
|
|
6684
|
+
] }) })
|
|
6166
6685
|
]
|
|
6167
6686
|
}
|
|
6168
6687
|
);
|
|
@@ -6186,16 +6705,14 @@ var YoutubeUploadPlugin = ({ disabled }) => {
|
|
|
6186
6705
|
setIsOpen(false);
|
|
6187
6706
|
};
|
|
6188
6707
|
return /* @__PURE__ */ jsxRuntime.jsxs(
|
|
6189
|
-
reactComponents.
|
|
6708
|
+
reactComponents.Dialog,
|
|
6190
6709
|
{
|
|
6191
|
-
trapFocus: true,
|
|
6192
|
-
withArrow: true,
|
|
6193
6710
|
open: disabled ? false : isOpen,
|
|
6194
6711
|
onOpenChange: (_, data) => {
|
|
6195
6712
|
if (!disabled) setIsOpen(data.open);
|
|
6196
6713
|
},
|
|
6197
6714
|
children: [
|
|
6198
|
-
/* @__PURE__ */ jsxRuntime.jsx(reactComponents.
|
|
6715
|
+
/* @__PURE__ */ jsxRuntime.jsx(reactComponents.DialogTrigger, { disableButtonEnhancement: true, children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
6199
6716
|
reactComponents.Button,
|
|
6200
6717
|
{
|
|
6201
6718
|
title: "Add youtube URL",
|
|
@@ -6217,37 +6734,36 @@ var YoutubeUploadPlugin = ({ disabled }) => {
|
|
|
6217
6734
|
},
|
|
6218
6735
|
"upload-video"
|
|
6219
6736
|
) }),
|
|
6220
|
-
/* @__PURE__ */ jsxRuntime.jsx(
|
|
6221
|
-
reactComponents.
|
|
6222
|
-
{
|
|
6223
|
-
|
|
6224
|
-
|
|
6225
|
-
|
|
6226
|
-
|
|
6227
|
-
|
|
6228
|
-
|
|
6229
|
-
|
|
6230
|
-
|
|
6231
|
-
|
|
6232
|
-
|
|
6233
|
-
|
|
6234
|
-
|
|
6235
|
-
|
|
6236
|
-
|
|
6237
|
-
|
|
6238
|
-
}
|
|
6239
|
-
) }),
|
|
6240
|
-
/* @__PURE__ */ jsxRuntime.jsxs(react.Stack, { horizontal: true, horizontalAlign: "end", tokens: { childrenGap: 6 }, children: [
|
|
6241
|
-
/* @__PURE__ */ jsxRuntime.jsx(reactComponents.Button, { size: "small", disabled: disabled || !url, onClick: onHandleEmbeded, children: "Add" }),
|
|
6242
|
-
/* @__PURE__ */ jsxRuntime.jsx(reactComponents.Button, { size: "small", disabled, onClick: () => setIsOpen(false), children: "Cancel" })
|
|
6243
|
-
] })
|
|
6244
|
-
] })
|
|
6245
|
-
}
|
|
6246
|
-
)
|
|
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
|
+
) }) }) }),
|
|
6750
|
+
/* @__PURE__ */ jsxRuntime.jsxs(reactComponents.DialogActions, { children: [
|
|
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" })
|
|
6753
|
+
] })
|
|
6754
|
+
] }) })
|
|
6247
6755
|
]
|
|
6248
6756
|
}
|
|
6249
6757
|
);
|
|
6250
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
|
+
] });
|
|
6251
6767
|
var useStyles4 = reactComponents.makeStyles({
|
|
6252
6768
|
dropdown: {
|
|
6253
6769
|
minInlineSize: "90px",
|
|
@@ -6265,24 +6781,42 @@ var ALLOWED_TOKENS = {
|
|
|
6265
6781
|
Bold: true,
|
|
6266
6782
|
Italic: true,
|
|
6267
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,
|
|
6268
6802
|
ColorPicker: true,
|
|
6269
6803
|
Link: true,
|
|
6270
6804
|
Table: true,
|
|
6271
6805
|
Image: true,
|
|
6272
6806
|
InlineImage: true,
|
|
6273
6807
|
Youtube: true,
|
|
6274
|
-
Heading: true,
|
|
6275
6808
|
FontFamily: true,
|
|
6276
6809
|
FontSize: true,
|
|
6810
|
+
Align: true,
|
|
6811
|
+
Heading: true,
|
|
6277
6812
|
Decorators: true,
|
|
6278
6813
|
CodeBlock: true,
|
|
6279
|
-
Align: true,
|
|
6280
6814
|
PageSetup: true
|
|
6281
6815
|
};
|
|
6282
6816
|
function sanitizePluginGroups(groups) {
|
|
6283
|
-
if (!groups || groups.length === 0) return [];
|
|
6817
|
+
if (!Array.isArray(groups) || groups.length === 0) return [];
|
|
6284
6818
|
return groups.map(
|
|
6285
|
-
(g) => (g
|
|
6819
|
+
(g) => (Array.isArray(g) ? g : []).map((t) => typeof t === "string" ? t.trim() : "").filter((t) => ALLOWED_TOKENS[t] === true)
|
|
6286
6820
|
).filter((g) => g.length > 0);
|
|
6287
6821
|
}
|
|
6288
6822
|
var ToolBarPlugins = (props) => {
|
|
@@ -6302,8 +6836,9 @@ var ToolBarPlugins = (props) => {
|
|
|
6302
6836
|
const [isLowercase, setIsLowercase] = React9.useState(false);
|
|
6303
6837
|
const [isCapitalize, setIsCapitalize] = React9.useState(false);
|
|
6304
6838
|
const [alignment, setAlignment] = React9.useState("left");
|
|
6305
|
-
const
|
|
6306
|
-
const
|
|
6839
|
+
const [decoratorOpen, setDecoratorOpen] = React9.useState(false);
|
|
6840
|
+
const decoratorSelectingRef = React9__namespace.default.useRef(false);
|
|
6841
|
+
const presetGroups = props.customToolbar ?? getToolbarGroupsByLevel(props.level);
|
|
6307
6842
|
const pluginGroups = React9.useMemo(() => sanitizePluginGroups(presetGroups), [presetGroups]);
|
|
6308
6843
|
const updateToolbarPlugins = () => {
|
|
6309
6844
|
const selection = lexical.$getSelection();
|
|
@@ -6345,6 +6880,10 @@ var ToolBarPlugins = (props) => {
|
|
|
6345
6880
|
setSelectNodeType("paragraph");
|
|
6346
6881
|
return;
|
|
6347
6882
|
}
|
|
6883
|
+
if ($isAlphaListNode(element)) {
|
|
6884
|
+
setSelectNodeType("alpha");
|
|
6885
|
+
return;
|
|
6886
|
+
}
|
|
6348
6887
|
if (list.$isListNode(element)) {
|
|
6349
6888
|
const parentList = utils.$getNearestNodeOfType(anchorNode, list.ListNode);
|
|
6350
6889
|
const type2 = parentList ? parentList.getTag() : element.getTag();
|
|
@@ -6356,23 +6895,15 @@ var ToolBarPlugins = (props) => {
|
|
|
6356
6895
|
["paragraph", "h1", "h2", "h3", "h4", "h5", "h6", "ul", "ol", "quote", "code"].includes(type) ? type : "paragraph"
|
|
6357
6896
|
);
|
|
6358
6897
|
};
|
|
6359
|
-
const applyToBlock = React9__namespace.default.useCallback(
|
|
6360
|
-
(fn) => {
|
|
6361
|
-
editor.update(() => {
|
|
6362
|
-
const saved = lastSelectionRef.current;
|
|
6363
|
-
if (saved) lexical.$setSelection(saved.clone());
|
|
6364
|
-
const sel = lexical.$getSelection();
|
|
6365
|
-
if (lexical.$isRangeSelection(sel)) fn(sel);
|
|
6366
|
-
});
|
|
6367
|
-
},
|
|
6368
|
-
[editor]
|
|
6369
|
-
);
|
|
6370
6898
|
const formatQuote = () => {
|
|
6371
|
-
|
|
6899
|
+
editor.update(() => {
|
|
6900
|
+
const selection$1 = lexical.$getSelection();
|
|
6901
|
+
if (!lexical.$isRangeSelection(selection$1)) return;
|
|
6372
6902
|
if (selectNodeType === "quote") {
|
|
6373
|
-
|
|
6903
|
+
formatParagraph(editor);
|
|
6374
6904
|
} else {
|
|
6375
|
-
|
|
6905
|
+
$splitBlocksAtLineBreaks(selection$1);
|
|
6906
|
+
selection.$setBlocksType(lexical.$getSelection(), () => richText.$createQuoteNode());
|
|
6376
6907
|
}
|
|
6377
6908
|
});
|
|
6378
6909
|
};
|
|
@@ -6389,8 +6920,6 @@ var ToolBarPlugins = (props) => {
|
|
|
6389
6920
|
editor.registerCommand(
|
|
6390
6921
|
lexical.SELECTION_CHANGE_COMMAND,
|
|
6391
6922
|
() => {
|
|
6392
|
-
const sel = lexical.$getSelection();
|
|
6393
|
-
if (lexical.$isRangeSelection(sel)) lastSelectionRef.current = sel.clone();
|
|
6394
6923
|
updateToolbarPlugins();
|
|
6395
6924
|
return false;
|
|
6396
6925
|
},
|
|
@@ -6422,52 +6951,16 @@ var ToolBarPlugins = (props) => {
|
|
|
6422
6951
|
editor.dispatchCommand(lexical.FORMAT_TEXT_COMMAND, "highlight");
|
|
6423
6952
|
break;
|
|
6424
6953
|
case "leftAlign" /* LeftAlign */:
|
|
6425
|
-
|
|
6426
|
-
const seen = /* @__PURE__ */ new Set();
|
|
6427
|
-
sel.getNodes().forEach((n) => {
|
|
6428
|
-
const t = n.getTopLevelElementOrThrow();
|
|
6429
|
-
if (!seen.has(t.getKey())) {
|
|
6430
|
-
seen.add(t.getKey());
|
|
6431
|
-
t.setFormat("left");
|
|
6432
|
-
}
|
|
6433
|
-
});
|
|
6434
|
-
});
|
|
6954
|
+
applyAlignmentWithSplit("left");
|
|
6435
6955
|
break;
|
|
6436
6956
|
case "rightAlign" /* RightAlign */:
|
|
6437
|
-
|
|
6438
|
-
const seen = /* @__PURE__ */ new Set();
|
|
6439
|
-
sel.getNodes().forEach((n) => {
|
|
6440
|
-
const t = n.getTopLevelElementOrThrow();
|
|
6441
|
-
if (!seen.has(t.getKey())) {
|
|
6442
|
-
seen.add(t.getKey());
|
|
6443
|
-
t.setFormat("right");
|
|
6444
|
-
}
|
|
6445
|
-
});
|
|
6446
|
-
});
|
|
6957
|
+
applyAlignmentWithSplit("right");
|
|
6447
6958
|
break;
|
|
6448
6959
|
case "centerAlign" /* CenterAlign */:
|
|
6449
|
-
|
|
6450
|
-
const seen = /* @__PURE__ */ new Set();
|
|
6451
|
-
sel.getNodes().forEach((n) => {
|
|
6452
|
-
const t = n.getTopLevelElementOrThrow();
|
|
6453
|
-
if (!seen.has(t.getKey())) {
|
|
6454
|
-
seen.add(t.getKey());
|
|
6455
|
-
t.setFormat("center");
|
|
6456
|
-
}
|
|
6457
|
-
});
|
|
6458
|
-
});
|
|
6960
|
+
applyAlignmentWithSplit("center");
|
|
6459
6961
|
break;
|
|
6460
6962
|
case "justifyAlign" /* JustifyAlign */:
|
|
6461
|
-
|
|
6462
|
-
const seen = /* @__PURE__ */ new Set();
|
|
6463
|
-
sel.getNodes().forEach((n) => {
|
|
6464
|
-
const t = n.getTopLevelElementOrThrow();
|
|
6465
|
-
if (!seen.has(t.getKey())) {
|
|
6466
|
-
seen.add(t.getKey());
|
|
6467
|
-
t.setFormat("justify");
|
|
6468
|
-
}
|
|
6469
|
-
});
|
|
6470
|
-
});
|
|
6963
|
+
applyAlignmentWithSplit("justify");
|
|
6471
6964
|
break;
|
|
6472
6965
|
case "undo" /* Undo */:
|
|
6473
6966
|
editor.dispatchCommand(lexical.UNDO_COMMAND, void 0);
|
|
@@ -6486,9 +6979,32 @@ var ToolBarPlugins = (props) => {
|
|
|
6486
6979
|
break;
|
|
6487
6980
|
}
|
|
6488
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
|
+
};
|
|
6489
6994
|
const updateHeading = (heading) => {
|
|
6490
|
-
|
|
6491
|
-
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();
|
|
6492
7008
|
});
|
|
6493
7009
|
};
|
|
6494
7010
|
const renderToken = (token, groupIndex, tokenIndex) => {
|
|
@@ -6500,7 +7016,6 @@ var ToolBarPlugins = (props) => {
|
|
|
6500
7016
|
const brand = palette.themePrimary;
|
|
6501
7017
|
const brandHover = palette.themeDarkAlt ?? brand;
|
|
6502
7018
|
const brandPressed = palette.themeDark ?? brand;
|
|
6503
|
-
palette.white;
|
|
6504
7019
|
const bgHover = palette.neutralLighter;
|
|
6505
7020
|
const bgPressed = palette.neutralLight;
|
|
6506
7021
|
const bgActive = palette.neutralLighterAlt ?? palette.neutralLighter;
|
|
@@ -6553,6 +7068,8 @@ var ToolBarPlugins = (props) => {
|
|
|
6553
7068
|
reactComponents.Button,
|
|
6554
7069
|
{
|
|
6555
7070
|
size: "small",
|
|
7071
|
+
"aria-label": "Bold",
|
|
7072
|
+
"aria-pressed": isBold,
|
|
6556
7073
|
disabled: !isEditable || props.readOnly,
|
|
6557
7074
|
icon: /* @__PURE__ */ jsxRuntime.jsx(reactIcons.TextBold24Regular, { style: { color: getIconColor(isBold) } }),
|
|
6558
7075
|
style: getButtonStyle(isBold),
|
|
@@ -6565,6 +7082,8 @@ var ToolBarPlugins = (props) => {
|
|
|
6565
7082
|
reactComponents.Button,
|
|
6566
7083
|
{
|
|
6567
7084
|
size: "small",
|
|
7085
|
+
"aria-label": "Italic",
|
|
7086
|
+
"aria-pressed": isItalic,
|
|
6568
7087
|
disabled: !isEditable || props.readOnly,
|
|
6569
7088
|
icon: /* @__PURE__ */ jsxRuntime.jsx(reactIcons.TextItalicFilled, { style: { color: getIconColor(isItalic) } }),
|
|
6570
7089
|
style: getButtonStyle(isItalic),
|
|
@@ -6577,6 +7096,8 @@ var ToolBarPlugins = (props) => {
|
|
|
6577
7096
|
reactComponents.Button,
|
|
6578
7097
|
{
|
|
6579
7098
|
size: "small",
|
|
7099
|
+
"aria-label": "Underline",
|
|
7100
|
+
"aria-pressed": isUnderline,
|
|
6580
7101
|
disabled: !isEditable || props.readOnly,
|
|
6581
7102
|
icon: /* @__PURE__ */ jsxRuntime.jsx(reactIcons.TextUnderlineFilled, { style: { color: getIconColor(isUnderline) } }),
|
|
6582
7103
|
style: getButtonStyle(isUnderline),
|
|
@@ -6587,7 +7108,14 @@ var ToolBarPlugins = (props) => {
|
|
|
6587
7108
|
case "ColorPicker":
|
|
6588
7109
|
return /* @__PURE__ */ jsxRuntime.jsx(ColorPickerPlugin, { disabled: !isEditable || props.readOnly }, key);
|
|
6589
7110
|
case "Link":
|
|
6590
|
-
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
|
+
);
|
|
6591
7119
|
case "Table":
|
|
6592
7120
|
return /* @__PURE__ */ jsxRuntime.jsx(TableItemPlugin, { disabled: !isEditable || props.readOnly }, key);
|
|
6593
7121
|
case "Image":
|
|
@@ -6595,7 +7123,9 @@ var ToolBarPlugins = (props) => {
|
|
|
6595
7123
|
InsertImageDialog,
|
|
6596
7124
|
{
|
|
6597
7125
|
activeEditor: editor,
|
|
6598
|
-
disabled: !isEditable || props.readOnly
|
|
7126
|
+
disabled: !isEditable || props.readOnly,
|
|
7127
|
+
maxImageSizeMB: props.maxImageSizeMB,
|
|
7128
|
+
validationMessages: props.validationMessages
|
|
6599
7129
|
},
|
|
6600
7130
|
key
|
|
6601
7131
|
);
|
|
@@ -6604,7 +7134,9 @@ var ToolBarPlugins = (props) => {
|
|
|
6604
7134
|
InsertInlineImageDialog,
|
|
6605
7135
|
{
|
|
6606
7136
|
activeEditor: editor,
|
|
6607
|
-
disabled: !isEditable || props.readOnly
|
|
7137
|
+
disabled: !isEditable || props.readOnly,
|
|
7138
|
+
maxImageSizeMB: props.maxImageSizeMB,
|
|
7139
|
+
validationMessages: props.validationMessages
|
|
6608
7140
|
},
|
|
6609
7141
|
key
|
|
6610
7142
|
);
|
|
@@ -6627,7 +7159,7 @@ var ToolBarPlugins = (props) => {
|
|
|
6627
7159
|
const val = data.optionValue;
|
|
6628
7160
|
if (!val) return;
|
|
6629
7161
|
if (val === "paragraph") {
|
|
6630
|
-
|
|
7162
|
+
formatParagraph(editor);
|
|
6631
7163
|
setSelectNodeType("paragraph");
|
|
6632
7164
|
} else {
|
|
6633
7165
|
updateHeading(val);
|
|
@@ -6648,83 +7180,456 @@ var ToolBarPlugins = (props) => {
|
|
|
6648
7180
|
return /* @__PURE__ */ jsxRuntime.jsx(FontSizePlugin, { disabled: !isEditable || props.readOnly }, key);
|
|
6649
7181
|
case "|":
|
|
6650
7182
|
return /* @__PURE__ */ jsxRuntime.jsx(reactComponents.ToolbarDivider, {}, key);
|
|
6651
|
-
|
|
6652
|
-
|
|
6653
|
-
|
|
6654
|
-
|
|
6655
|
-
|
|
6656
|
-
|
|
6657
|
-
...isSubscript ? ["subscript"] : [],
|
|
6658
|
-
...isSuperscript ? ["superscript"] : [],
|
|
6659
|
-
...isHighlight ? ["highlight"] : [],
|
|
6660
|
-
...selectNodeType === "ul" ? ["ul-list"] : [],
|
|
6661
|
-
...selectNodeType === "ol" ? ["ol-list"] : [],
|
|
6662
|
-
...selectNodeType === "quote" ? ["quote"] : []
|
|
6663
|
-
];
|
|
6664
|
-
const DECORATOR_LABEL = {
|
|
6665
|
-
uppercase: "Uppercase",
|
|
6666
|
-
lowercase: "Lowercase",
|
|
6667
|
-
capitalize: "Capitalize",
|
|
6668
|
-
strike: "Strikethrough",
|
|
6669
|
-
subscript: "Subscript",
|
|
6670
|
-
superscript: "Superscript",
|
|
6671
|
-
highlight: "Highlight",
|
|
6672
|
-
"ul-list": "Bullet list",
|
|
6673
|
-
"ol-list": "Number list",
|
|
6674
|
-
quote: "Quote"
|
|
6675
|
-
};
|
|
6676
|
-
const decoratorValue = activeDecorators.length === 0 ? "" : activeDecorators.length === 1 ? DECORATOR_LABEL[activeDecorators[0]] : `${DECORATOR_LABEL[activeDecorators[0]]} +${activeDecorators.length - 1}`;
|
|
6677
|
-
return /* @__PURE__ */ jsxRuntime.jsxs(
|
|
6678
|
-
reactComponents.Dropdown,
|
|
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,
|
|
6679
7189
|
{
|
|
6680
|
-
|
|
6681
|
-
|
|
6682
|
-
|
|
6683
|
-
|
|
6684
|
-
|
|
6685
|
-
|
|
6686
|
-
|
|
6687
|
-
|
|
6688
|
-
|
|
6689
|
-
|
|
6690
|
-
|
|
6691
|
-
|
|
6692
|
-
|
|
6693
|
-
|
|
6694
|
-
|
|
6695
|
-
|
|
6696
|
-
|
|
6697
|
-
|
|
6698
|
-
|
|
6699
|
-
|
|
6700
|
-
|
|
6701
|
-
|
|
6702
|
-
|
|
6703
|
-
|
|
6704
|
-
|
|
6705
|
-
|
|
6706
|
-
|
|
6707
|
-
|
|
6708
|
-
|
|
6709
|
-
|
|
6710
|
-
|
|
6711
|
-
|
|
6712
|
-
|
|
6713
|
-
|
|
6714
|
-
|
|
6715
|
-
|
|
6716
|
-
|
|
6717
|
-
|
|
6718
|
-
|
|
6719
|
-
|
|
6720
|
-
|
|
6721
|
-
|
|
6722
|
-
|
|
6723
|
-
|
|
6724
|
-
|
|
6725
|
-
|
|
6726
|
-
|
|
6727
|
-
|
|
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);
|
|
7499
|
+
setSelectNodeType("paragraph");
|
|
7500
|
+
} else {
|
|
7501
|
+
updateHeading("h5");
|
|
7502
|
+
setSelectNodeType("h5");
|
|
7503
|
+
}
|
|
7504
|
+
},
|
|
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"
|
|
7533
|
+
},
|
|
7534
|
+
key
|
|
7535
|
+
);
|
|
7536
|
+
case "Decorators": {
|
|
7537
|
+
const activeDecorators = [
|
|
7538
|
+
...isUppercase ? ["uppercase"] : [],
|
|
7539
|
+
...isLowercase ? ["lowercase"] : [],
|
|
7540
|
+
...isCapitalize ? ["capitalize"] : [],
|
|
7541
|
+
...isStrikethrough ? ["strike"] : [],
|
|
7542
|
+
...isSubscript ? ["subscript"] : [],
|
|
7543
|
+
...isSuperscript ? ["superscript"] : [],
|
|
7544
|
+
...isHighlight ? ["highlight"] : [],
|
|
7545
|
+
...selectNodeType === "ul" ? ["ul-list"] : [],
|
|
7546
|
+
...selectNodeType === "ol" ? ["ol-list"] : [],
|
|
7547
|
+
...selectNodeType === "alpha" ? ["al-list"] : [],
|
|
7548
|
+
...selectNodeType === "quote" ? ["quote"] : []
|
|
7549
|
+
];
|
|
7550
|
+
const DECORATOR_LABEL = {
|
|
7551
|
+
uppercase: "Uppercase",
|
|
7552
|
+
lowercase: "Lowercase",
|
|
7553
|
+
capitalize: "Capitalize",
|
|
7554
|
+
strike: "Strikethrough",
|
|
7555
|
+
subscript: "Subscript",
|
|
7556
|
+
superscript: "Superscript",
|
|
7557
|
+
highlight: "Highlight",
|
|
7558
|
+
"ul-list": "Bullet list",
|
|
7559
|
+
"ol-list": "Number list",
|
|
7560
|
+
"al-list": "Alphabetical list",
|
|
7561
|
+
quote: "Quote"
|
|
7562
|
+
};
|
|
7563
|
+
const decoratorValue = activeDecorators.length === 0 ? "" : activeDecorators.length === 1 ? DECORATOR_LABEL[activeDecorators[0]] : `${DECORATOR_LABEL[activeDecorators[0]]} +${activeDecorators.length - 1}`;
|
|
7564
|
+
return /* @__PURE__ */ jsxRuntime.jsxs(
|
|
7565
|
+
reactComponents.Dropdown,
|
|
7566
|
+
{
|
|
7567
|
+
multiselect: true,
|
|
7568
|
+
id: `${groupIndex}-set-decorators`,
|
|
7569
|
+
placeholder: "Text",
|
|
7570
|
+
value: decoratorValue,
|
|
7571
|
+
selectedOptions: activeDecorators,
|
|
7572
|
+
disabled: !isEditable,
|
|
7573
|
+
className: styles.alignDropdown,
|
|
7574
|
+
button: { style: dropdownButtonStyle },
|
|
7575
|
+
expandIcon: { style: dropdownExpandIconStyle },
|
|
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
|
+
},
|
|
7585
|
+
onOptionSelect: (_, data) => {
|
|
7586
|
+
decoratorSelectingRef.current = true;
|
|
7587
|
+
switch (data.optionValue) {
|
|
7588
|
+
case "uppercase":
|
|
7589
|
+
editor.dispatchCommand(lexical.FORMAT_TEXT_COMMAND, "uppercase");
|
|
7590
|
+
break;
|
|
7591
|
+
case "lowercase":
|
|
7592
|
+
onHandleSelectOption("lowercase" /* Lowercase */);
|
|
7593
|
+
break;
|
|
7594
|
+
case "capitalize":
|
|
7595
|
+
onHandleSelectOption("capitalize" /* Capitalize */);
|
|
7596
|
+
break;
|
|
7597
|
+
case "strike":
|
|
7598
|
+
onHandleSelectOption("strike" /* Strikethrough */);
|
|
7599
|
+
break;
|
|
7600
|
+
case "subscript":
|
|
7601
|
+
onHandleSelectOption("subscript" /* Subscript */);
|
|
7602
|
+
break;
|
|
7603
|
+
case "superscript":
|
|
7604
|
+
onHandleSelectOption("superscript" /* Superscript */);
|
|
7605
|
+
break;
|
|
7606
|
+
case "highlight":
|
|
7607
|
+
onHandleSelectOption("highlight" /* Highlight */);
|
|
7608
|
+
break;
|
|
7609
|
+
case "ul-list":
|
|
7610
|
+
editor.dispatchCommand(
|
|
7611
|
+
selectNodeType === "ul" ? list.REMOVE_LIST_COMMAND : list.INSERT_UNORDERED_LIST_COMMAND,
|
|
7612
|
+
void 0
|
|
7613
|
+
);
|
|
7614
|
+
break;
|
|
7615
|
+
case "ol-list":
|
|
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());
|
|
7623
|
+
break;
|
|
7624
|
+
case "page-break":
|
|
7625
|
+
editor.dispatchCommand(INSERT_PAGE_BREAK, void 0);
|
|
7626
|
+
break;
|
|
7627
|
+
case "quote":
|
|
7628
|
+
formatQuote();
|
|
7629
|
+
break;
|
|
7630
|
+
}
|
|
7631
|
+
},
|
|
7632
|
+
children: [
|
|
6728
7633
|
/* @__PURE__ */ jsxRuntime.jsxs(reactComponents.Option, { value: "uppercase", text: "Uppercase", children: [
|
|
6729
7634
|
/* @__PURE__ */ jsxRuntime.jsx(reactIcons.TextCaseUppercaseFilled, { style: optionIconStyle }),
|
|
6730
7635
|
"Uppercase"
|
|
@@ -6750,7 +7655,12 @@ var ToolBarPlugins = (props) => {
|
|
|
6750
7655
|
"Superscript"
|
|
6751
7656
|
] }),
|
|
6752
7657
|
/* @__PURE__ */ jsxRuntime.jsxs(reactComponents.Option, { value: "highlight", text: "Highlight", children: [
|
|
6753
|
-
/* @__PURE__ */ jsxRuntime.jsx(
|
|
7658
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
7659
|
+
reactIcons.HighlightAccentFilled,
|
|
7660
|
+
{
|
|
7661
|
+
style: { ...optionIconStyle, color: isEditable ? brand : fgDisabled }
|
|
7662
|
+
}
|
|
7663
|
+
),
|
|
6754
7664
|
"Highlight"
|
|
6755
7665
|
] }),
|
|
6756
7666
|
/* @__PURE__ */ jsxRuntime.jsxs(reactComponents.Option, { value: "ul-list", text: "Bullet list", children: [
|
|
@@ -6761,6 +7671,10 @@ var ToolBarPlugins = (props) => {
|
|
|
6761
7671
|
/* @__PURE__ */ jsxRuntime.jsx(reactIcons.TextNumberListLtrFilled, { style: optionIconStyle }),
|
|
6762
7672
|
"Number list"
|
|
6763
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
|
+
] }),
|
|
6764
7678
|
/* @__PURE__ */ jsxRuntime.jsxs(reactComponents.Option, { value: "page-break", text: "Page Break", children: [
|
|
6765
7679
|
/* @__PURE__ */ jsxRuntime.jsx(reactIcons.DocumentPageBreakRegular, { style: optionIconStyle }),
|
|
6766
7680
|
"Page break"
|
|
@@ -6786,10 +7700,30 @@ var ToolBarPlugins = (props) => {
|
|
|
6786
7700
|
// );
|
|
6787
7701
|
case "Align": {
|
|
6788
7702
|
const ALIGN_OPTIONS = [
|
|
6789
|
-
{
|
|
6790
|
-
|
|
6791
|
-
|
|
6792
|
-
|
|
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
|
+
}
|
|
6793
7727
|
];
|
|
6794
7728
|
const alignLabel = ALIGN_OPTIONS.find((o) => o.value === alignment)?.label ?? "Left Align";
|
|
6795
7729
|
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
@@ -7005,28 +7939,31 @@ function BrowserSpellCheckPlugin({ enabled }) {
|
|
|
7005
7939
|
}, [editor, enabled]);
|
|
7006
7940
|
return null;
|
|
7007
7941
|
}
|
|
7008
|
-
function
|
|
7009
|
-
|
|
7010
|
-
|
|
7011
|
-
return editor.registerUpdateListener(({ editorState }) => {
|
|
7012
|
-
editorState.read(() => {
|
|
7013
|
-
const text = lexical.$getRoot().getTextContent();
|
|
7014
|
-
const words = text.trim() === "" ? 0 : text.trim().split(/\s+/).length;
|
|
7015
|
-
onCountChange(words);
|
|
7016
|
-
});
|
|
7017
|
-
});
|
|
7018
|
-
}, [editor, onCountChange]);
|
|
7019
|
-
return null;
|
|
7020
|
-
}
|
|
7021
|
-
function CharCountPlugin({ onCountChange }) {
|
|
7942
|
+
function ContentMetricsPlugin({
|
|
7943
|
+
onMetricsChange
|
|
7944
|
+
}) {
|
|
7022
7945
|
const [editor] = LexicalComposerContext.useLexicalComposerContext();
|
|
7946
|
+
const prevRef = React9.useRef({ words: 0, chars: 0, images: 0, links: 0, tables: 0 });
|
|
7023
7947
|
React9.useEffect(() => {
|
|
7024
|
-
return editor.registerUpdateListener(({
|
|
7025
|
-
|
|
7026
|
-
|
|
7027
|
-
|
|
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
|
+
}
|
|
7028
7965
|
});
|
|
7029
|
-
}, [editor,
|
|
7966
|
+
}, [editor, onMetricsChange]);
|
|
7030
7967
|
return null;
|
|
7031
7968
|
}
|
|
7032
7969
|
function FocusEventsPlugin({
|
|
@@ -7047,7 +7984,8 @@ function FocusEventsPlugin({
|
|
|
7047
7984
|
const next = e.relatedTarget;
|
|
7048
7985
|
const container = containerRef.current;
|
|
7049
7986
|
const stillInside = !!next && (container ? container.contains(next) : root.contains(next));
|
|
7050
|
-
|
|
7987
|
+
const isEditorPortal = !!next?.closest?.("[data-lexical-editor-portal]");
|
|
7988
|
+
if (stillInside || isEditorPortal) return;
|
|
7051
7989
|
editor.update(() => {
|
|
7052
7990
|
lexical.$setSelection(null);
|
|
7053
7991
|
});
|
|
@@ -7157,6 +8095,16 @@ function _makeQueryFn(fn) {
|
|
|
7157
8095
|
};
|
|
7158
8096
|
};
|
|
7159
8097
|
}
|
|
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
|
+
}
|
|
7160
8108
|
var ContentEditorComponent = React9.forwardRef(
|
|
7161
8109
|
(props, ref) => {
|
|
7162
8110
|
const isReadOnly = !!props.readOnly;
|
|
@@ -7172,13 +8120,17 @@ var ContentEditorComponent = React9.forwardRef(
|
|
|
7172
8120
|
);
|
|
7173
8121
|
const [floatingAnchorElem, setFloatingAnchorElem] = React9.useState(null);
|
|
7174
8122
|
const [isLinkEditMode, setIsLinkEditMode] = React9.useState(false);
|
|
7175
|
-
const [
|
|
7176
|
-
|
|
7177
|
-
|
|
7178
|
-
|
|
7179
|
-
|
|
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), []);
|
|
7180
8131
|
const [pageSetup, setPageSetup] = React9.useState(DEFAULT_PAGE_SETUP);
|
|
7181
8132
|
const pageCanvas = resolvePageCanvasMetrics(pageSetup);
|
|
8133
|
+
const wordCount = metrics.words;
|
|
7182
8134
|
const contentEditableDomRef = React9.useRef(null);
|
|
7183
8135
|
const previousOverLimitRef = React9.useRef(false);
|
|
7184
8136
|
const focusedRef = React9.useRef(false);
|
|
@@ -7189,32 +8141,37 @@ var ContentEditorComponent = React9.forwardRef(
|
|
|
7189
8141
|
const onAnchorRef = (elem) => {
|
|
7190
8142
|
if (elem) setFloatingAnchorElem(elem);
|
|
7191
8143
|
};
|
|
7192
|
-
const initialConfig = {
|
|
7193
|
-
|
|
7194
|
-
|
|
7195
|
-
|
|
7196
|
-
|
|
7197
|
-
|
|
7198
|
-
|
|
7199
|
-
|
|
7200
|
-
|
|
7201
|
-
|
|
7202
|
-
|
|
7203
|
-
|
|
7204
|
-
|
|
7205
|
-
|
|
7206
|
-
|
|
7207
|
-
|
|
7208
|
-
|
|
7209
|
-
|
|
7210
|
-
|
|
7211
|
-
|
|
7212
|
-
|
|
7213
|
-
|
|
7214
|
-
|
|
7215
|
-
|
|
7216
|
-
|
|
7217
|
-
|
|
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
|
+
}, []);
|
|
7218
8175
|
const EditorStyles = react.mergeStyleSets({
|
|
7219
8176
|
editorPlaceholder: {
|
|
7220
8177
|
color: "var(--colorNeutralForeground3, grey)",
|
|
@@ -7256,41 +8213,7 @@ var ContentEditorComponent = React9.forwardRef(
|
|
|
7256
8213
|
e.stopPropagation();
|
|
7257
8214
|
}
|
|
7258
8215
|
};
|
|
7259
|
-
const [touched, setTouched] = React9.useState(false);
|
|
7260
8216
|
const isOverLimit = props.wordLimit !== void 0 && wordCount > props.wordLimit;
|
|
7261
|
-
const internalErrors = [];
|
|
7262
|
-
if (isOverLimit) {
|
|
7263
|
-
const m = props.errorMessages?.wordLimitExceeded;
|
|
7264
|
-
internalErrors.push(
|
|
7265
|
-
typeof m === "function" ? m(wordCount, props.wordLimit) : m ?? `Word limit exceeded (${wordCount} / ${props.wordLimit} words used)`
|
|
7266
|
-
);
|
|
7267
|
-
}
|
|
7268
|
-
if (props.required && touched && wordCount === 0) {
|
|
7269
|
-
internalErrors.push(
|
|
7270
|
-
props.errorMessages?.required ?? "This field is required"
|
|
7271
|
-
);
|
|
7272
|
-
}
|
|
7273
|
-
if (props.minWords !== void 0 && touched && wordCount < props.minWords) {
|
|
7274
|
-
const m = props.errorMessages?.minWords;
|
|
7275
|
-
internalErrors.push(
|
|
7276
|
-
typeof m === "function" ? m(wordCount, props.minWords) : m ?? `Minimum ${props.minWords} words required (${wordCount} entered)`
|
|
7277
|
-
);
|
|
7278
|
-
}
|
|
7279
|
-
if (props.maxChars !== void 0 && charCount > props.maxChars) {
|
|
7280
|
-
const m = props.errorMessages?.maxCharsExceeded;
|
|
7281
|
-
internalErrors.push(
|
|
7282
|
-
typeof m === "function" ? m(charCount, props.maxChars) : m ?? `Character limit exceeded (${charCount} / ${props.maxChars} characters used)`
|
|
7283
|
-
);
|
|
7284
|
-
}
|
|
7285
|
-
if (props.minChars !== void 0 && touched && charCount < props.minChars && charCount > 0) {
|
|
7286
|
-
const m = props.errorMessages?.minCharsRequired;
|
|
7287
|
-
internalErrors.push(
|
|
7288
|
-
typeof m === "function" ? m(charCount, props.minChars) : m ?? `Minimum ${props.minChars} characters required (${charCount} entered)`
|
|
7289
|
-
);
|
|
7290
|
-
}
|
|
7291
|
-
const allErrors = [...internalErrors, ...props.errors ?? [], ...refErrors];
|
|
7292
|
-
const hasErrors = allErrors.length > 0;
|
|
7293
|
-
const hasRedBorder = hasErrors;
|
|
7294
8217
|
React9.useEffect(() => {
|
|
7295
8218
|
if (props.wordLimit === void 0 || !props.onWordLimitExceeded) return;
|
|
7296
8219
|
const wasOverLimit = previousOverLimitRef.current;
|
|
@@ -7303,215 +8226,329 @@ var ContentEditorComponent = React9.forwardRef(
|
|
|
7303
8226
|
previousOverLimitRef.current = isOverLimit;
|
|
7304
8227
|
}
|
|
7305
8228
|
}, [isOverLimit, wordCount, props.wordLimit, props.onWordLimitExceeded]);
|
|
7306
|
-
|
|
7307
|
-
|
|
7308
|
-
{
|
|
7309
|
-
|
|
7310
|
-
|
|
7311
|
-
|
|
7312
|
-
|
|
7313
|
-
|
|
7314
|
-
|
|
7315
|
-
|
|
7316
|
-
|
|
7317
|
-
|
|
7318
|
-
|
|
7319
|
-
|
|
7320
|
-
}
|
|
7321
|
-
|
|
7322
|
-
|
|
7323
|
-
|
|
7324
|
-
|
|
7325
|
-
|
|
7326
|
-
|
|
7327
|
-
|
|
7328
|
-
|
|
7329
|
-
|
|
7330
|
-
|
|
7331
|
-
|
|
7332
|
-
|
|
7333
|
-
|
|
7334
|
-
|
|
7335
|
-
|
|
7336
|
-
|
|
7337
|
-
|
|
7338
|
-
|
|
7339
|
-
|
|
7340
|
-
|
|
7341
|
-
|
|
7342
|
-
|
|
7343
|
-
|
|
7344
|
-
|
|
7345
|
-
|
|
7346
|
-
|
|
7347
|
-
|
|
7348
|
-
|
|
7349
|
-
|
|
7350
|
-
|
|
7351
|
-
|
|
7352
|
-
|
|
7353
|
-
|
|
7354
|
-
|
|
7355
|
-
|
|
7356
|
-
|
|
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",
|
|
8316
|
+
{
|
|
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,
|
|
7357
8325
|
{
|
|
7358
|
-
|
|
7359
|
-
|
|
7360
|
-
|
|
7361
|
-
|
|
7362
|
-
|
|
7363
|
-
|
|
7364
|
-
|
|
7365
|
-
|
|
7366
|
-
|
|
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
|
+
)
|
|
8336
|
+
}
|
|
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,
|
|
8354
|
+
{
|
|
8355
|
+
ErrorBoundary: LexicalErrorBoundary.LexicalErrorBoundary,
|
|
8356
|
+
contentEditable: /* @__PURE__ */ jsxRuntime.jsx(
|
|
8357
|
+
"div",
|
|
8358
|
+
{
|
|
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
|
+
)
|
|
8381
|
+
}
|
|
8382
|
+
),
|
|
8383
|
+
placeholder: /* @__PURE__ */ jsxRuntime.jsx(react.Stack, { className: react.css(EditorStyles.editorPlaceholder), children: props.placeholder })
|
|
8384
|
+
}
|
|
8385
|
+
),
|
|
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",
|
|
8388
|
+
{
|
|
8389
|
+
style: {
|
|
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"
|
|
8398
|
+
},
|
|
8399
|
+
children: [
|
|
8400
|
+
(props.wordLimit !== void 0 || props.maxWords !== void 0 || props.minWords !== void 0) && /* @__PURE__ */ jsxRuntime.jsxs(
|
|
8401
|
+
"span",
|
|
7367
8402
|
{
|
|
7368
|
-
ref: contentEditableDomRef,
|
|
7369
|
-
className: react.css(EditorStyles.contentEditor),
|
|
7370
8403
|
style: {
|
|
7371
|
-
|
|
7372
|
-
|
|
7373
|
-
|
|
7374
|
-
|
|
7375
|
-
marginLeft: pageCanvas.widthPx !== void 0 ? "auto" : void 0,
|
|
7376
|
-
marginRight: pageCanvas.widthPx !== void 0 ? "auto" : void 0,
|
|
7377
|
-
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
|
|
8404
|
+
fontSize: "11px",
|
|
8405
|
+
color: hasValidationError ? "#c4272c" : "var(--colorNeutralForeground3, #aaa)",
|
|
8406
|
+
fontWeight: hasValidationError ? 600 : 400,
|
|
8407
|
+
transition: "color 0.2s, font-weight 0.2s"
|
|
7378
8408
|
},
|
|
7379
|
-
|
|
7380
|
-
|
|
7381
|
-
|
|
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
|
+
]
|
|
7382
8432
|
}
|
|
7383
8433
|
)
|
|
7384
|
-
|
|
7385
|
-
|
|
7386
|
-
|
|
7387
|
-
|
|
7388
|
-
|
|
7389
|
-
|
|
7390
|
-
|
|
7391
|
-
|
|
7392
|
-
|
|
7393
|
-
|
|
7394
|
-
|
|
7395
|
-
|
|
7396
|
-
|
|
7397
|
-
|
|
7398
|
-
|
|
7399
|
-
|
|
7400
|
-
|
|
7401
|
-
|
|
7402
|
-
|
|
7403
|
-
|
|
7404
|
-
|
|
7405
|
-
|
|
7406
|
-
|
|
7407
|
-
|
|
7408
|
-
|
|
7409
|
-
|
|
7410
|
-
|
|
7411
|
-
|
|
7412
|
-
|
|
7413
|
-
|
|
7414
|
-
|
|
7415
|
-
|
|
7416
|
-
|
|
7417
|
-
|
|
7418
|
-
|
|
7419
|
-
|
|
7420
|
-
|
|
7421
|
-
|
|
7422
|
-
|
|
7423
|
-
|
|
7424
|
-
|
|
7425
|
-
|
|
7426
|
-
|
|
7427
|
-
|
|
7428
|
-
|
|
7429
|
-
|
|
7430
|
-
|
|
7431
|
-
|
|
7432
|
-
|
|
7433
|
-
|
|
7434
|
-
|
|
7435
|
-
|
|
7436
|
-
|
|
7437
|
-
|
|
7438
|
-
|
|
7439
|
-
|
|
7440
|
-
|
|
7441
|
-
|
|
7442
|
-
|
|
7443
|
-
|
|
7444
|
-
{
|
|
7445
|
-
|
|
7446
|
-
|
|
7447
|
-
|
|
7448
|
-
|
|
7449
|
-
|
|
7450
|
-
|
|
7451
|
-
|
|
7452
|
-
|
|
7453
|
-
|
|
7454
|
-
|
|
7455
|
-
|
|
7456
|
-
|
|
7457
|
-
|
|
7458
|
-
|
|
7459
|
-
|
|
7460
|
-
|
|
7461
|
-
|
|
7462
|
-
|
|
7463
|
-
|
|
7464
|
-
|
|
7465
|
-
|
|
7466
|
-
|
|
7467
|
-
|
|
7468
|
-
|
|
7469
|
-
|
|
7470
|
-
|
|
7471
|
-
|
|
7472
|
-
|
|
7473
|
-
|
|
7474
|
-
|
|
7475
|
-
|
|
7476
|
-
|
|
7477
|
-
|
|
7478
|
-
|
|
7479
|
-
|
|
7480
|
-
|
|
7481
|
-
|
|
7482
|
-
|
|
7483
|
-
|
|
7484
|
-
|
|
7485
|
-
|
|
7486
|
-
|
|
7487
|
-
|
|
7488
|
-
|
|
7489
|
-
|
|
7490
|
-
|
|
7491
|
-
|
|
7492
|
-
|
|
7493
|
-
|
|
7494
|
-
|
|
7495
|
-
|
|
7496
|
-
|
|
7497
|
-
(props.wordLimit !== void 0 || props.required || props.minWords !== void 0) && /* @__PURE__ */ jsxRuntime.jsx(WordCountPlugin, { onCountChange: handleWordCount }),
|
|
7498
|
-
(props.maxChars !== void 0 || props.minChars !== void 0) && /* @__PURE__ */ jsxRuntime.jsx(CharCountPlugin, { onCountChange: handleCharCount }),
|
|
7499
|
-
/* @__PURE__ */ jsxRuntime.jsx(
|
|
7500
|
-
RefApiPlugin,
|
|
7501
|
-
{
|
|
7502
|
-
forwardedRef: ref,
|
|
7503
|
-
contentEditableDomRef,
|
|
7504
|
-
focusedRef,
|
|
7505
|
-
setRefErrors
|
|
7506
|
-
}
|
|
7507
|
-
)
|
|
7508
|
-
]
|
|
7509
|
-
}
|
|
7510
|
-
) }) }) });
|
|
8434
|
+
]
|
|
8435
|
+
}
|
|
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
|
+
]
|
|
8539
|
+
}
|
|
8540
|
+
)
|
|
8541
|
+
] })
|
|
8542
|
+
]
|
|
8543
|
+
}
|
|
8544
|
+
) }),
|
|
8545
|
+
/* @__PURE__ */ jsxRuntime.jsx(EditorReadyPlugin, { onReady: props.onReady })
|
|
8546
|
+
] }) });
|
|
7511
8547
|
}
|
|
7512
8548
|
);
|
|
7513
8549
|
|
|
7514
8550
|
exports.ContentEditorComponent = ContentEditorComponent;
|
|
7515
8551
|
exports.ContentEditorLevel = ContentEditorLevel;
|
|
8552
|
+
exports.DEFAULT_VALIDATION_MESSAGES = DEFAULT_VALIDATION_MESSAGES;
|
|
7516
8553
|
//# sourceMappingURL=index.js.map
|
|
7517
8554
|
//# sourceMappingURL=index.js.map
|