@tarviks/lexical-rich-editor 1.3.11 → 1.3.13
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.js +94 -17
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +95 -18
- package/dist/index.mjs.map +1 -1
- package/package.json +2 -2
package/dist/index.mjs
CHANGED
|
@@ -5,7 +5,7 @@ import { jsx, jsxs, Fragment } from 'react/jsx-runtime';
|
|
|
5
5
|
import { useLexicalComposerContext } from '@lexical/react/LexicalComposerContext';
|
|
6
6
|
import { useLexicalEditable } from '@lexical/react/useLexicalEditable';
|
|
7
7
|
import { useLexicalNodeSelection } from '@lexical/react/useLexicalNodeSelection';
|
|
8
|
-
import { createCommand, DecoratorNode, COMMAND_PRIORITY_HIGH, TextNode, ElementNode, SELECTION_CHANGE_COMMAND, KEY_BACKSPACE_COMMAND, KEY_DELETE_COMMAND, $getSelection, $isRangeSelection, $findMatchingParent, COMMAND_PRIORITY_LOW, KEY_DOWN_COMMAND, $getNodeByKey, $createRangeSelection, $setSelection, $createParagraphNode, $insertNodes, $isRootOrShadowRoot, COMMAND_PRIORITY_EDITOR, PASTE_COMMAND, DRAGSTART_COMMAND, DRAGOVER_COMMAND, DROP_COMMAND, $getRoot, $createTextNode, $
|
|
8
|
+
import { createCommand, $isTextNode, DecoratorNode, COMMAND_PRIORITY_HIGH, TextNode, ElementNode, SELECTION_CHANGE_COMMAND, KEY_BACKSPACE_COMMAND, KEY_DELETE_COMMAND, $getSelection, $isRangeSelection, $findMatchingParent, COMMAND_PRIORITY_LOW, KEY_DOWN_COMMAND, $getNodeByKey, $createRangeSelection, $setSelection, $createParagraphNode, $insertNodes, $isRootOrShadowRoot, COMMAND_PRIORITY_EDITOR, PASTE_COMMAND, DRAGSTART_COMMAND, DRAGOVER_COMMAND, DROP_COMMAND, $getRoot, $createTextNode, $isElementNode, FORMAT_ELEMENT_COMMAND, CLICK_COMMAND, $isNodeSelection, $applyNodeReplacement, FORMAT_TEXT_COMMAND, $isDecoratorNode, $getNearestNodeFromDOMNode, COMMAND_PRIORITY_CRITICAL, REDO_COMMAND, UNDO_COMMAND, getDOMSelection, KEY_ESCAPE_COMMAND, isHTMLElement, getDOMSelectionFromTarget, $isLineBreakNode, SKIP_SELECTION_FOCUS_TAG, createEditor, KEY_ENTER_COMMAND } from 'lexical';
|
|
9
9
|
import { mergeStyleSets, Stack, css, useTheme, Callout, TextField } from '@fluentui/react';
|
|
10
10
|
import { makeStyles, FluentProvider, webLightTheme, Menu, MenuTrigger, MenuPopover, MenuList, MenuGroup, MenuGroupHeader, MenuItem, MenuDivider, Dropdown, Option, Button, ToolbarDivider, MenuItemRadio, Field, Input, MessageBar, MessageBarBody, Popover, PopoverSurface, PopoverTrigger } from '@fluentui/react-components';
|
|
11
11
|
import { CodeHighlightNode, CodeNode, $isCodeHighlightNode } from '@lexical/code';
|
|
@@ -2209,6 +2209,48 @@ function $createYouTubeNode(videoID, width = DEFAULT_WIDTH, height = DEFAULT_HEI
|
|
|
2209
2209
|
function $isYouTubeNode(node) {
|
|
2210
2210
|
return node instanceof YouTubeNode;
|
|
2211
2211
|
}
|
|
2212
|
+
var PRESERVED_STYLE_PROPS = [
|
|
2213
|
+
["fontFamily", "font-family"],
|
|
2214
|
+
["fontSize", "font-size"],
|
|
2215
|
+
["color", "color"],
|
|
2216
|
+
["backgroundColor", "background-color"]
|
|
2217
|
+
];
|
|
2218
|
+
var $convertSpanElementWithStyle = (domNode) => {
|
|
2219
|
+
const style = domNode.style;
|
|
2220
|
+
const cssParts = [];
|
|
2221
|
+
for (const [domProp, cssProp] of PRESERVED_STYLE_PROPS) {
|
|
2222
|
+
const value = style[domProp];
|
|
2223
|
+
if (value) cssParts.push(`${cssProp}: ${value}`);
|
|
2224
|
+
}
|
|
2225
|
+
const cssText = cssParts.length > 0 ? `${cssParts.join("; ")};` : "";
|
|
2226
|
+
const fontWeight = style.fontWeight;
|
|
2227
|
+
const textDecoration = style.textDecoration.split(" ");
|
|
2228
|
+
const hasBoldFontWeight = fontWeight === "700" || fontWeight === "bold";
|
|
2229
|
+
const hasLinethroughTextDecoration = textDecoration.includes("line-through");
|
|
2230
|
+
const hasItalicFontStyle = style.fontStyle === "italic";
|
|
2231
|
+
const hasUnderlineTextDecoration = textDecoration.includes("underline");
|
|
2232
|
+
const verticalAlign = style.verticalAlign;
|
|
2233
|
+
return {
|
|
2234
|
+
node: null,
|
|
2235
|
+
forChild: (lexicalNode) => {
|
|
2236
|
+
if (!$isTextNode(lexicalNode)) return lexicalNode;
|
|
2237
|
+
if (cssText) lexicalNode.setStyle(cssText);
|
|
2238
|
+
if (hasBoldFontWeight && !lexicalNode.hasFormat("bold")) lexicalNode.toggleFormat("bold");
|
|
2239
|
+
if (hasLinethroughTextDecoration && !lexicalNode.hasFormat("strikethrough")) lexicalNode.toggleFormat("strikethrough");
|
|
2240
|
+
if (hasItalicFontStyle && !lexicalNode.hasFormat("italic")) lexicalNode.toggleFormat("italic");
|
|
2241
|
+
if (hasUnderlineTextDecoration && !lexicalNode.hasFormat("underline")) lexicalNode.toggleFormat("underline");
|
|
2242
|
+
if (verticalAlign === "sub" && !lexicalNode.hasFormat("subscript")) lexicalNode.toggleFormat("subscript");
|
|
2243
|
+
if (verticalAlign === "super" && !lexicalNode.hasFormat("superscript")) lexicalNode.toggleFormat("superscript");
|
|
2244
|
+
return lexicalNode;
|
|
2245
|
+
}
|
|
2246
|
+
};
|
|
2247
|
+
};
|
|
2248
|
+
var preserveTextStyleImportMap = {
|
|
2249
|
+
span: () => ({
|
|
2250
|
+
conversion: $convertSpanElementWithStyle,
|
|
2251
|
+
priority: 0
|
|
2252
|
+
})
|
|
2253
|
+
};
|
|
2212
2254
|
var normalize = (s) => (s ?? "").replace(/\s+/g, " ").trim();
|
|
2213
2255
|
function readContextWindow(maxChars = 300, cursorIndex) {
|
|
2214
2256
|
const full = normalize($getRoot().getTextContent());
|
|
@@ -3156,12 +3198,16 @@ function splitHeadingsAtBrSequences(html) {
|
|
|
3156
3198
|
});
|
|
3157
3199
|
return doc.body.innerHTML;
|
|
3158
3200
|
}
|
|
3159
|
-
var CustomOnChangePlugin = ({ value, onChange }) => {
|
|
3201
|
+
var CustomOnChangePlugin = ({ value, onChange, isReadOnly }) => {
|
|
3160
3202
|
const [editor] = useLexicalComposerContext();
|
|
3161
3203
|
const initializedRef = useRef(false);
|
|
3204
|
+
const lastImportedValueRef = useRef(null);
|
|
3162
3205
|
useEffect(() => {
|
|
3163
|
-
if (!value
|
|
3206
|
+
if (!value) return;
|
|
3207
|
+
if (!isReadOnly && initializedRef.current) return;
|
|
3208
|
+
if (value === lastImportedValueRef.current) return;
|
|
3164
3209
|
initializedRef.current = true;
|
|
3210
|
+
lastImportedValueRef.current = value;
|
|
3165
3211
|
editor.update(() => {
|
|
3166
3212
|
const root = $getRoot();
|
|
3167
3213
|
root.clear();
|
|
@@ -3172,14 +3218,17 @@ var CustomOnChangePlugin = ({ value, onChange }) => {
|
|
|
3172
3218
|
const nodes = $generateNodesFromDOM(editor, dom);
|
|
3173
3219
|
root.append(...nodes);
|
|
3174
3220
|
});
|
|
3175
|
-
}, [editor, value]);
|
|
3221
|
+
}, [editor, value, isReadOnly]);
|
|
3176
3222
|
return /* @__PURE__ */ jsx(
|
|
3177
3223
|
OnChangePlugin,
|
|
3178
3224
|
{
|
|
3225
|
+
ignoreSelectionChange: true,
|
|
3179
3226
|
onChange: (editorState) => {
|
|
3180
3227
|
editorState.read(() => {
|
|
3181
3228
|
const raw = $generateHtmlFromNodes(editor);
|
|
3182
|
-
|
|
3229
|
+
const html = postProcessOutput(splitHeadingsAtBrSequences(raw));
|
|
3230
|
+
lastImportedValueRef.current = html;
|
|
3231
|
+
onChange(html);
|
|
3183
3232
|
});
|
|
3184
3233
|
}
|
|
3185
3234
|
}
|
|
@@ -5149,16 +5198,18 @@ function getScrollClipAncestor(el) {
|
|
|
5149
5198
|
}
|
|
5150
5199
|
return null;
|
|
5151
5200
|
}
|
|
5201
|
+
var BUTTON_VERTICAL_FOOTPRINT = 34;
|
|
5152
5202
|
function isRectVisible(rect, cellDom) {
|
|
5153
5203
|
if (rect.width === 0 && rect.height === 0) return false;
|
|
5154
|
-
if (rect.bottom <= 0 || rect.top >= window.innerHeight) return false;
|
|
5155
|
-
if (rect.right <= 0 || rect.left >= window.innerWidth) return false;
|
|
5156
5204
|
const clipAncestor = getScrollClipAncestor(cellDom);
|
|
5157
|
-
|
|
5158
|
-
|
|
5159
|
-
|
|
5160
|
-
|
|
5161
|
-
|
|
5205
|
+
const containerRect = clipAncestor?.getBoundingClientRect();
|
|
5206
|
+
const visibleTop = containerRect ? Math.max(0, containerRect.top) : 0;
|
|
5207
|
+
const visibleBottom = containerRect ? Math.min(window.innerHeight, containerRect.bottom) : window.innerHeight;
|
|
5208
|
+
const visibleLeft = containerRect ? Math.max(0, containerRect.left) : 0;
|
|
5209
|
+
const visibleRight = containerRect ? Math.min(window.innerWidth, containerRect.right) : window.innerWidth;
|
|
5210
|
+
if (rect.top < visibleTop) return false;
|
|
5211
|
+
if (rect.top + BUTTON_VERTICAL_FOOTPRINT > visibleBottom) return false;
|
|
5212
|
+
if (rect.left >= visibleRight || rect.right <= visibleLeft) return false;
|
|
5162
5213
|
return true;
|
|
5163
5214
|
}
|
|
5164
5215
|
function TableActionMenuPlugin({ disabled = false }) {
|
|
@@ -5310,9 +5361,25 @@ function TableActionMenuPlugin({ disabled = false }) {
|
|
|
5310
5361
|
const canShow = isInTable && !!anchorRect && isAnchorVisible && !disabled;
|
|
5311
5362
|
const handleStyle = React9.useMemo(() => {
|
|
5312
5363
|
if (!anchorRect) return void 0;
|
|
5313
|
-
const
|
|
5314
|
-
const
|
|
5315
|
-
const
|
|
5364
|
+
const BUTTON_SIZE = 28;
|
|
5365
|
+
const PAD = 8;
|
|
5366
|
+
const editorRect = editor.getRootElement()?.getBoundingClientRect();
|
|
5367
|
+
const clipRect = editorRect ? {
|
|
5368
|
+
top: Math.max(editorRect.top, 0),
|
|
5369
|
+
left: Math.max(editorRect.left, 0),
|
|
5370
|
+
right: Math.min(editorRect.right, window.innerWidth),
|
|
5371
|
+
bottom: Math.min(editorRect.bottom, window.innerHeight)
|
|
5372
|
+
} : { top: 0, left: 0, right: window.innerWidth, bottom: window.innerHeight };
|
|
5373
|
+
const isCellVisible = anchorRect.bottom > clipRect.top && anchorRect.top < clipRect.bottom && anchorRect.right > clipRect.left && anchorRect.left < clipRect.right;
|
|
5374
|
+
if (!isCellVisible) return void 0;
|
|
5375
|
+
const minTop = editorRect ? editorRect.top + PAD : PAD;
|
|
5376
|
+
const maxTop = editorRect ? Math.max(minTop, editorRect.bottom - BUTTON_SIZE - PAD) : window.innerHeight - BUTTON_SIZE - PAD;
|
|
5377
|
+
const minLeft = editorRect ? editorRect.left + PAD : PAD;
|
|
5378
|
+
const maxLeft = editorRect ? Math.max(minLeft, editorRect.right - BUTTON_SIZE - PAD) : window.innerWidth - BUTTON_SIZE - PAD;
|
|
5379
|
+
const top = Math.min(Math.max(anchorRect.top + 6, minTop), maxTop);
|
|
5380
|
+
const clampedCellRight = Math.min(anchorRect.right, maxLeft + BUTTON_SIZE);
|
|
5381
|
+
const rawLeft = contentRight !== null ? Math.max(anchorRect.left + 4, Math.min(contentRight + 4, clampedCellRight - 32)) : anchorRect.left + 8;
|
|
5382
|
+
const left = Math.min(Math.max(rawLeft, minLeft), maxLeft);
|
|
5316
5383
|
return {
|
|
5317
5384
|
position: "fixed",
|
|
5318
5385
|
top,
|
|
@@ -5322,7 +5389,7 @@ function TableActionMenuPlugin({ disabled = false }) {
|
|
|
5322
5389
|
// button renders behind the modal chrome in a full-page/Panel view.
|
|
5323
5390
|
zIndex: 10000010
|
|
5324
5391
|
};
|
|
5325
|
-
}, [anchorRect, contentRight]);
|
|
5392
|
+
}, [anchorRect, contentRight, editor]);
|
|
5326
5393
|
const dangerStyle = {
|
|
5327
5394
|
color: "var(--colorPaletteRedForeground1)"
|
|
5328
5395
|
};
|
|
@@ -8266,7 +8333,10 @@ var ContentEditorComponent = forwardRef(
|
|
|
8266
8333
|
AutocompleteNode,
|
|
8267
8334
|
SpellErrorNode,
|
|
8268
8335
|
HtmlBlockNode
|
|
8269
|
-
]
|
|
8336
|
+
],
|
|
8337
|
+
html: {
|
|
8338
|
+
import: preserveTextStyleImportMap
|
|
8339
|
+
}
|
|
8270
8340
|
};
|
|
8271
8341
|
props.onBeforeInitialize?.(config);
|
|
8272
8342
|
return config;
|
|
@@ -8594,7 +8664,14 @@ var ContentEditorComponent = forwardRef(
|
|
|
8594
8664
|
}
|
|
8595
8665
|
),
|
|
8596
8666
|
!isReadOnly && props.showFloatingToolbar && /* @__PURE__ */ jsx(CharacterStylesPopupPlugin, {}),
|
|
8597
|
-
/* @__PURE__ */ jsx(
|
|
8667
|
+
/* @__PURE__ */ jsx(
|
|
8668
|
+
CustomOnChangePlugin,
|
|
8669
|
+
{
|
|
8670
|
+
value: props.value,
|
|
8671
|
+
onChange: props.onChange,
|
|
8672
|
+
isReadOnly
|
|
8673
|
+
}
|
|
8674
|
+
),
|
|
8598
8675
|
(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__ */ jsx(ContentMetricsPlugin, { onMetricsChange: handleMetrics }),
|
|
8599
8676
|
/* @__PURE__ */ jsx(
|
|
8600
8677
|
RefApiPlugin,
|