@tarviks/lexical-rich-editor 1.0.0 → 1.0.2
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/LICENSE +21 -0
- package/README.md +198 -198
- package/dist/index.js +96 -88
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +98 -90
- package/dist/index.mjs.map +1 -1
- package/package.json +92 -92
package/dist/index.mjs
CHANGED
|
@@ -7,7 +7,7 @@ import { useLexicalEditable } from '@lexical/react/useLexicalEditable';
|
|
|
7
7
|
import { useLexicalNodeSelection } from '@lexical/react/useLexicalNodeSelection';
|
|
8
8
|
import { createCommand, DecoratorNode, COMMAND_PRIORITY_HIGH, TextNode, ElementNode, SELECTION_CHANGE_COMMAND, $getNodeByKey, KEY_BACKSPACE_COMMAND, KEY_DELETE_COMMAND, $getSelection, $isRangeSelection, $findMatchingParent, COMMAND_PRIORITY_LOW, KEY_DOWN_COMMAND, $insertNodes, $isRootOrShadowRoot, $createParagraphNode, COMMAND_PRIORITY_EDITOR, PASTE_COMMAND, DRAGSTART_COMMAND, DRAGOVER_COMMAND, DROP_COMMAND, $getRoot, $createTextNode, $isTextNode, $createRangeSelection, $setSelection, $isElementNode, $isNodeSelection, CLICK_COMMAND, $applyNodeReplacement, FORMAT_TEXT_COMMAND, $isDecoratorNode, $getNearestNodeFromDOMNode, COMMAND_PRIORITY_CRITICAL, REDO_COMMAND, UNDO_COMMAND, FORMAT_ELEMENT_COMMAND, getDOMSelection, KEY_ESCAPE_COMMAND, isHTMLElement, getDOMSelectionFromTarget, createEditor, KEY_ENTER_COMMAND } from 'lexical';
|
|
9
9
|
import { mergeStyleSets, Stack, css, useTheme, Callout, TextField, DefaultButton } from '@fluentui/react';
|
|
10
|
-
import { makeStyles, FluentProvider, webLightTheme, Button, Menu,
|
|
10
|
+
import { makeStyles, FluentProvider, webLightTheme, Button, Menu, MenuPopover, MenuList, MenuGroup, MenuGroupHeader, MenuItem, MenuDivider, Dropdown, Option, ToolbarDivider, Popover, PopoverTrigger, PopoverSurface, Field, Input } from '@fluentui/react-components';
|
|
11
11
|
import { CodeHighlightNode, CodeNode, $isCodeHighlightNode } from '@lexical/code';
|
|
12
12
|
import { LinkNode, AutoLinkNode, $isLinkNode, $isAutoLinkNode, TOGGLE_LINK_COMMAND, $createLinkNode } from '@lexical/link';
|
|
13
13
|
import { ListNode, ListItemNode, $isListNode, REMOVE_LIST_COMMAND, INSERT_ORDERED_LIST_COMMAND, INSERT_UNORDERED_LIST_COMMAND } from '@lexical/list';
|
|
@@ -25,7 +25,7 @@ import { HeadingNode, QuoteNode, $isHeadingNode, $createQuoteNode, $createHeadin
|
|
|
25
25
|
import { TableNode, TableRowNode, TableCellNode, $isTableSelection, $isTableNode, $isTableCellNode, $insertTableColumnAtSelection, $insertTableRowAtSelection, $deleteTableRowAtSelection, $deleteTableColumnAtSelection, $getTableNodeFromLexicalNodeOrThrow, getDOMCellFromTarget, getTableObserverFromTableElement, $getTableRowIndexFromTableCellNode, $isTableRowNode, $getTableColumnIndexFromTableCellNode, $createTableNodeWithDimensions } from '@lexical/table';
|
|
26
26
|
import { BlockWithAlignableContents } from '@lexical/react/LexicalBlockWithAlignableContents';
|
|
27
27
|
import { DecoratorBlockNode } from '@lexical/react/LexicalDecoratorBlockNode';
|
|
28
|
-
import { DeleteRegular,
|
|
28
|
+
import { DeleteRegular, ArrowUpRegular, RowTripleRegular, ArrowDownRegular, ArrowLeftRegular, ColumnTripleRegular, ArrowRightRegular, TextCaseUppercaseFilled, TextCaseLowercaseFilled, TextCaseTitleFilled, TextStrikethroughFilled, TextSubscriptFilled, TextSuperscriptFilled, HighlightAccentFilled, TextBulletListLtrFilled, TextNumberListLtrFilled, DocumentPageBreakRegular, CommentQuoteRegular, TextUnderlineFilled, TextItalicFilled, TextBold24Regular, TextAlignLeftFilled, TextAlignCenterFilled, TextAlignRightFilled, TextAlignJustifyFilled, VideoClipRegular, ImageEditRegular, AttachFilled, ImageAddRegular, TableAddRegular, LinkAddRegular, TextColorRegular, PaintBucket16Filled, CodeFilled, LinkFilled } from '@fluentui/react-icons';
|
|
29
29
|
import { $setBlocksType, $patchStyleText, $isAtNodeEnd, $getSelectionStyleValueForProperty } from '@lexical/selection';
|
|
30
30
|
import { createPortal } from 'react-dom';
|
|
31
31
|
import { $generateNodesFromDOM, $generateHtmlFromNodes } from '@lexical/html';
|
|
@@ -2442,6 +2442,8 @@ function CharacterStylesPopupPlugin(props) {
|
|
|
2442
2442
|
var CustomOnChangePlugin = ({ value, onChange }) => {
|
|
2443
2443
|
const [editor] = useLexicalComposerContext();
|
|
2444
2444
|
const initializedRef = useRef(false);
|
|
2445
|
+
const onChangeRef = useRef(onChange);
|
|
2446
|
+
onChangeRef.current = onChange;
|
|
2445
2447
|
useEffect(() => {
|
|
2446
2448
|
if (!value || initializedRef.current) return;
|
|
2447
2449
|
initializedRef.current = true;
|
|
@@ -2452,16 +2454,19 @@ var CustomOnChangePlugin = ({ value, onChange }) => {
|
|
|
2452
2454
|
const dom = parser.parseFromString(value, "text/html");
|
|
2453
2455
|
const nodes = $generateNodesFromDOM(editor, dom);
|
|
2454
2456
|
root.append(...nodes);
|
|
2457
|
+
$setSelection(null);
|
|
2455
2458
|
});
|
|
2456
2459
|
}, [editor, value]);
|
|
2460
|
+
const handleChange = useCallback((editorState) => {
|
|
2461
|
+
editorState.read(() => {
|
|
2462
|
+
onChangeRef.current($generateHtmlFromNodes(editor));
|
|
2463
|
+
});
|
|
2464
|
+
}, [editor]);
|
|
2457
2465
|
return /* @__PURE__ */ jsx(
|
|
2458
2466
|
OnChangePlugin,
|
|
2459
2467
|
{
|
|
2460
|
-
onChange:
|
|
2461
|
-
|
|
2462
|
-
onChange($generateHtmlFromNodes(editor));
|
|
2463
|
-
});
|
|
2464
|
-
}
|
|
2468
|
+
onChange: handleChange,
|
|
2469
|
+
ignoreSelectionChange: true
|
|
2465
2470
|
}
|
|
2466
2471
|
);
|
|
2467
2472
|
};
|
|
@@ -4273,8 +4278,8 @@ function SpellCheckPlugin({
|
|
|
4273
4278
|
function TableActionMenuPlugin({ disabled = false }) {
|
|
4274
4279
|
const [editor] = useLexicalComposerContext();
|
|
4275
4280
|
const [isInTable, setIsInTable] = React6.useState(false);
|
|
4276
|
-
const [anchorRect, setAnchorRect] = React6.useState(null);
|
|
4277
4281
|
const [open, setOpen] = React6.useState(false);
|
|
4282
|
+
const [menuPos, setMenuPos] = React6.useState(null);
|
|
4278
4283
|
const updateFromSelection = React6.useCallback(() => {
|
|
4279
4284
|
const root = editor.getRootElement();
|
|
4280
4285
|
if (!root) return;
|
|
@@ -4283,34 +4288,21 @@ function TableActionMenuPlugin({ disabled = false }) {
|
|
|
4283
4288
|
if ($isTableSelection(selection)) {
|
|
4284
4289
|
const tableNode = selection.getNodes().find((n) => $isTableNode(n));
|
|
4285
4290
|
if (tableNode) {
|
|
4286
|
-
|
|
4287
|
-
|
|
4288
|
-
setIsInTable(true);
|
|
4289
|
-
setAnchorRect(dom.getBoundingClientRect());
|
|
4290
|
-
return;
|
|
4291
|
-
}
|
|
4291
|
+
setIsInTable(true);
|
|
4292
|
+
return;
|
|
4292
4293
|
}
|
|
4293
4294
|
}
|
|
4294
4295
|
if (!$isRangeSelection(selection)) {
|
|
4295
4296
|
setIsInTable(false);
|
|
4296
|
-
setAnchorRect(null);
|
|
4297
4297
|
return;
|
|
4298
4298
|
}
|
|
4299
4299
|
const anchorNode = selection.anchor.getNode();
|
|
4300
4300
|
const cellNode = $isTableCellNode(anchorNode) ? anchorNode : $findMatchingParent(anchorNode, (n) => $isTableCellNode(n));
|
|
4301
4301
|
if (!cellNode || !$isTableCellNode(cellNode)) {
|
|
4302
4302
|
setIsInTable(false);
|
|
4303
|
-
setAnchorRect(null);
|
|
4304
|
-
return;
|
|
4305
|
-
}
|
|
4306
|
-
const cellDom = editor.getElementByKey(cellNode.getKey());
|
|
4307
|
-
if (!cellDom) {
|
|
4308
|
-
setIsInTable(false);
|
|
4309
|
-
setAnchorRect(null);
|
|
4310
4303
|
return;
|
|
4311
4304
|
}
|
|
4312
4305
|
setIsInTable(true);
|
|
4313
|
-
setAnchorRect(cellDom.getBoundingClientRect());
|
|
4314
4306
|
});
|
|
4315
4307
|
}, [editor]);
|
|
4316
4308
|
React6.useEffect(() => {
|
|
@@ -4372,18 +4364,33 @@ function TableActionMenuPlugin({ disabled = false }) {
|
|
|
4372
4364
|
React6.useEffect(() => {
|
|
4373
4365
|
if (!isInTable && open) setOpen(false);
|
|
4374
4366
|
}, [isInTable, open]);
|
|
4375
|
-
|
|
4376
|
-
|
|
4377
|
-
if (!
|
|
4378
|
-
const
|
|
4379
|
-
|
|
4380
|
-
|
|
4381
|
-
|
|
4382
|
-
|
|
4383
|
-
|
|
4384
|
-
|
|
4367
|
+
React6.useEffect(() => {
|
|
4368
|
+
const root = editor.getRootElement();
|
|
4369
|
+
if (!root) return;
|
|
4370
|
+
const handleContextMenu = (e) => {
|
|
4371
|
+
if (disabled) return;
|
|
4372
|
+
let inTable = false;
|
|
4373
|
+
editor.getEditorState().read(() => {
|
|
4374
|
+
const selection = $getSelection();
|
|
4375
|
+
if ($isTableSelection(selection)) {
|
|
4376
|
+
inTable = true;
|
|
4377
|
+
return;
|
|
4378
|
+
}
|
|
4379
|
+
if ($isRangeSelection(selection)) {
|
|
4380
|
+
const node = selection.anchor.getNode();
|
|
4381
|
+
const cell = $isTableCellNode(node) ? node : $findMatchingParent(node, (n) => $isTableCellNode(n));
|
|
4382
|
+
if (cell) inTable = true;
|
|
4383
|
+
}
|
|
4384
|
+
});
|
|
4385
|
+
if (inTable) {
|
|
4386
|
+
e.preventDefault();
|
|
4387
|
+
setMenuPos({ x: e.clientX, y: e.clientY });
|
|
4388
|
+
setOpen(true);
|
|
4389
|
+
}
|
|
4385
4390
|
};
|
|
4386
|
-
|
|
4391
|
+
root.addEventListener("contextmenu", handleContextMenu);
|
|
4392
|
+
return () => root.removeEventListener("contextmenu", handleContextMenu);
|
|
4393
|
+
}, [editor, disabled]);
|
|
4387
4394
|
const dangerStyle = {
|
|
4388
4395
|
color: "var(--colorPaletteRedForeground1)"
|
|
4389
4396
|
};
|
|
@@ -4416,63 +4423,55 @@ function TableActionMenuPlugin({ disabled = false }) {
|
|
|
4416
4423
|
const table = $getTableNodeFromLexicalNodeOrThrow(cell);
|
|
4417
4424
|
table.remove();
|
|
4418
4425
|
});
|
|
4419
|
-
|
|
4426
|
+
const virtualTarget = React6.useMemo(() => {
|
|
4427
|
+
if (!menuPos) return void 0;
|
|
4428
|
+
return {
|
|
4429
|
+
getBoundingClientRect: () => new DOMRect(menuPos.x, menuPos.y, 0, 0)
|
|
4430
|
+
};
|
|
4431
|
+
}, [menuPos]);
|
|
4432
|
+
if (disabled) return null;
|
|
4420
4433
|
return createPortal(
|
|
4421
|
-
/* @__PURE__ */ jsx(
|
|
4422
|
-
/* @__PURE__ */
|
|
4423
|
-
"
|
|
4424
|
-
{
|
|
4425
|
-
|
|
4426
|
-
|
|
4427
|
-
|
|
4428
|
-
|
|
4429
|
-
|
|
4430
|
-
|
|
4431
|
-
|
|
4432
|
-
|
|
4433
|
-
|
|
4434
|
-
|
|
4435
|
-
|
|
4436
|
-
/* @__PURE__ */ jsx(
|
|
4437
|
-
|
|
4438
|
-
/* @__PURE__ */ jsxs("span", { className: "aoMenuLabel", children: [
|
|
4439
|
-
/* @__PURE__ */ jsx(ArrowUpRegular, {}),
|
|
4440
|
-
" Row above"
|
|
4441
|
-
] }),
|
|
4442
|
-
/* @__PURE__ */ jsx("span", { className: "aoMenuShortcut", children: "Alt \u21E7 \u2191" })
|
|
4443
|
-
] }) }),
|
|
4444
|
-
/* @__PURE__ */ jsx(MenuItem, { icon: /* @__PURE__ */ jsx(RowTripleRegular, {}), onClick: insertRowBelow, children: /* @__PURE__ */ jsxs("span", { className: "aoMenuRow", children: [
|
|
4445
|
-
/* @__PURE__ */ jsxs("span", { className: "aoMenuLabel", children: [
|
|
4446
|
-
/* @__PURE__ */ jsx(ArrowDownRegular, {}),
|
|
4447
|
-
" Row below"
|
|
4448
|
-
] }),
|
|
4449
|
-
/* @__PURE__ */ jsx("span", { className: "aoMenuShortcut", children: "Alt \u21E7 \u2193" })
|
|
4450
|
-
] }) }),
|
|
4451
|
-
/* @__PURE__ */ jsx(MenuDivider, {}),
|
|
4452
|
-
/* @__PURE__ */ jsx(MenuItem, { icon: /* @__PURE__ */ jsx(ColumnTripleRegular, {}), onClick: insertColLeft, children: /* @__PURE__ */ jsxs("span", { className: "aoMenuRow", children: [
|
|
4453
|
-
/* @__PURE__ */ jsxs("span", { className: "aoMenuLabel", children: [
|
|
4454
|
-
/* @__PURE__ */ jsx(ArrowLeftRegular, {}),
|
|
4455
|
-
" Column left"
|
|
4456
|
-
] }),
|
|
4457
|
-
/* @__PURE__ */ jsx("span", { className: "aoMenuShortcut", children: "Alt \u21E7 \u2190" })
|
|
4458
|
-
] }) }),
|
|
4459
|
-
/* @__PURE__ */ jsx(MenuItem, { icon: /* @__PURE__ */ jsx(ColumnTripleRegular, {}), onClick: insertColRight, children: /* @__PURE__ */ jsxs("span", { className: "aoMenuRow", children: [
|
|
4460
|
-
/* @__PURE__ */ jsxs("span", { className: "aoMenuLabel", children: [
|
|
4461
|
-
/* @__PURE__ */ jsx(ArrowRightRegular, {}),
|
|
4462
|
-
" Column right"
|
|
4463
|
-
] }),
|
|
4464
|
-
/* @__PURE__ */ jsx("span", { className: "aoMenuShortcut", children: "Alt \u21E7 \u2192" })
|
|
4465
|
-
] }) })
|
|
4466
|
-
] }),
|
|
4434
|
+
/* @__PURE__ */ jsx(Menu, { open, onOpenChange: (_, data) => setOpen(data.open), positioning: { target: virtualTarget }, children: /* @__PURE__ */ jsx(MenuPopover, { className: "aoTableActionPopover", children: /* @__PURE__ */ jsxs(MenuList, { children: [
|
|
4435
|
+
/* @__PURE__ */ jsxs(MenuGroup, { children: [
|
|
4436
|
+
/* @__PURE__ */ jsx(MenuGroupHeader, { children: "Insert" }),
|
|
4437
|
+
/* @__PURE__ */ jsx(MenuItem, { icon: /* @__PURE__ */ jsx(RowTripleRegular, {}), onClick: insertRowAbove, children: /* @__PURE__ */ jsxs("span", { className: "aoMenuRow", children: [
|
|
4438
|
+
/* @__PURE__ */ jsxs("span", { className: "aoMenuLabel", children: [
|
|
4439
|
+
/* @__PURE__ */ jsx(ArrowUpRegular, {}),
|
|
4440
|
+
" Row above"
|
|
4441
|
+
] }),
|
|
4442
|
+
/* @__PURE__ */ jsx("span", { className: "aoMenuShortcut", children: "Alt \u21E7 \u2191" })
|
|
4443
|
+
] }) }),
|
|
4444
|
+
/* @__PURE__ */ jsx(MenuItem, { icon: /* @__PURE__ */ jsx(RowTripleRegular, {}), onClick: insertRowBelow, children: /* @__PURE__ */ jsxs("span", { className: "aoMenuRow", children: [
|
|
4445
|
+
/* @__PURE__ */ jsxs("span", { className: "aoMenuLabel", children: [
|
|
4446
|
+
/* @__PURE__ */ jsx(ArrowDownRegular, {}),
|
|
4447
|
+
" Row below"
|
|
4448
|
+
] }),
|
|
4449
|
+
/* @__PURE__ */ jsx("span", { className: "aoMenuShortcut", children: "Alt \u21E7 \u2193" })
|
|
4450
|
+
] }) }),
|
|
4467
4451
|
/* @__PURE__ */ jsx(MenuDivider, {}),
|
|
4468
|
-
/* @__PURE__ */ jsxs(
|
|
4469
|
-
/* @__PURE__ */
|
|
4470
|
-
|
|
4471
|
-
|
|
4472
|
-
|
|
4473
|
-
|
|
4474
|
-
|
|
4475
|
-
|
|
4452
|
+
/* @__PURE__ */ jsx(MenuItem, { icon: /* @__PURE__ */ jsx(ColumnTripleRegular, {}), onClick: insertColLeft, children: /* @__PURE__ */ jsxs("span", { className: "aoMenuRow", children: [
|
|
4453
|
+
/* @__PURE__ */ jsxs("span", { className: "aoMenuLabel", children: [
|
|
4454
|
+
/* @__PURE__ */ jsx(ArrowLeftRegular, {}),
|
|
4455
|
+
" Column left"
|
|
4456
|
+
] }),
|
|
4457
|
+
/* @__PURE__ */ jsx("span", { className: "aoMenuShortcut", children: "Alt \u21E7 \u2190" })
|
|
4458
|
+
] }) }),
|
|
4459
|
+
/* @__PURE__ */ jsx(MenuItem, { icon: /* @__PURE__ */ jsx(ColumnTripleRegular, {}), onClick: insertColRight, children: /* @__PURE__ */ jsxs("span", { className: "aoMenuRow", children: [
|
|
4460
|
+
/* @__PURE__ */ jsxs("span", { className: "aoMenuLabel", children: [
|
|
4461
|
+
/* @__PURE__ */ jsx(ArrowRightRegular, {}),
|
|
4462
|
+
" Column right"
|
|
4463
|
+
] }),
|
|
4464
|
+
/* @__PURE__ */ jsx("span", { className: "aoMenuShortcut", children: "Alt \u21E7 \u2192" })
|
|
4465
|
+
] }) })
|
|
4466
|
+
] }),
|
|
4467
|
+
/* @__PURE__ */ jsx(MenuDivider, {}),
|
|
4468
|
+
/* @__PURE__ */ jsxs(MenuGroup, { children: [
|
|
4469
|
+
/* @__PURE__ */ jsx(MenuGroupHeader, { children: "Delete" }),
|
|
4470
|
+
/* @__PURE__ */ jsx(MenuItem, { icon: /* @__PURE__ */ jsx(DeleteRegular, {}), onClick: deleteRow, style: dangerStyle, children: "Delete row" }),
|
|
4471
|
+
/* @__PURE__ */ jsx(MenuItem, { icon: /* @__PURE__ */ jsx(DeleteRegular, {}), onClick: deleteCol, style: dangerStyle, children: "Delete column" }),
|
|
4472
|
+
/* @__PURE__ */ jsx(MenuItem, { icon: /* @__PURE__ */ jsx(DeleteRegular, {}), onClick: deleteTable, style: dangerStyle, children: "Delete table" })
|
|
4473
|
+
] })
|
|
4474
|
+
] }) }) }),
|
|
4476
4475
|
document.body
|
|
4477
4476
|
);
|
|
4478
4477
|
}
|
|
@@ -6465,6 +6464,9 @@ function FocusEventsPlugin({
|
|
|
6465
6464
|
const next = e.relatedTarget;
|
|
6466
6465
|
const stillInside = !!next && root.contains(next);
|
|
6467
6466
|
if (stillInside) return;
|
|
6467
|
+
editor.update(() => {
|
|
6468
|
+
$setSelection(null);
|
|
6469
|
+
});
|
|
6468
6470
|
setFocused(false);
|
|
6469
6471
|
onBlur?.();
|
|
6470
6472
|
};
|
|
@@ -6835,7 +6837,13 @@ var ContentEditorComponent = forwardRef(
|
|
|
6835
6837
|
}
|
|
6836
6838
|
),
|
|
6837
6839
|
!isReadOnly && props.showFloatingToolbar && /* @__PURE__ */ jsx(CharacterStylesPopupPlugin, {}),
|
|
6838
|
-
/* @__PURE__ */ jsx(
|
|
6840
|
+
/* @__PURE__ */ jsx(
|
|
6841
|
+
CustomOnChangePlugin,
|
|
6842
|
+
{
|
|
6843
|
+
value: props.value,
|
|
6844
|
+
onChange: props.onChange
|
|
6845
|
+
}
|
|
6846
|
+
),
|
|
6839
6847
|
props.wordLimit !== void 0 && /* @__PURE__ */ jsx(WordCountPlugin, { onCountChange: handleWordCount }),
|
|
6840
6848
|
/* @__PURE__ */ jsx(
|
|
6841
6849
|
RefApiPlugin,
|