@tarviks/lexical-rich-editor 1.3.5 → 1.3.7
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 +0 -84
- package/dist/index.css.map +1 -1
- package/dist/index.js +133 -157
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +134 -158
- package/dist/index.mjs.map +1 -1
- package/package.json +1 -1
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, 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, $isTextNode, $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
|
-
import { makeStyles, FluentProvider, webLightTheme, Menu, MenuTrigger, MenuPopover, MenuList, MenuGroup, MenuGroupHeader, MenuItem, MenuDivider, Dropdown, Option, Button, ToolbarDivider, MenuItemRadio, Field, Input, MessageBar, MessageBarBody, Popover,
|
|
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';
|
|
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, $removeList, $insertList, $isListItemNode } from '@lexical/list';
|
|
@@ -3143,33 +3143,6 @@ var getSelectedNode2 = (selection) => {
|
|
|
3143
3143
|
return $isAtNodeEnd(anchor) ? anchorNode : focusNode;
|
|
3144
3144
|
}
|
|
3145
3145
|
};
|
|
3146
|
-
var VERTICAL_GAP = 10;
|
|
3147
|
-
var HORIZONTAL_OFFSET = 5;
|
|
3148
|
-
var VIEWPORT_MARGIN = 8;
|
|
3149
|
-
var setFloatingElemPositionForLinkEditor = (targetRect, floatingElem, topBoundary = VIEWPORT_MARGIN, verticalGap = VERTICAL_GAP, horizontalOffset = HORIZONTAL_OFFSET) => {
|
|
3150
|
-
if (targetRect === null) {
|
|
3151
|
-
floatingElem.style.opacity = "0";
|
|
3152
|
-
floatingElem.style.transform = "translate(-10000px, -10000px)";
|
|
3153
|
-
return;
|
|
3154
|
-
}
|
|
3155
|
-
const floatingElemRect = floatingElem.getBoundingClientRect();
|
|
3156
|
-
let top = targetRect.bottom + verticalGap;
|
|
3157
|
-
let left = targetRect.left - horizontalOffset;
|
|
3158
|
-
if (top + floatingElemRect.height > window.innerHeight - VIEWPORT_MARGIN) {
|
|
3159
|
-
top = targetRect.top - floatingElemRect.height - verticalGap;
|
|
3160
|
-
}
|
|
3161
|
-
if (top < topBoundary) {
|
|
3162
|
-
top = topBoundary;
|
|
3163
|
-
}
|
|
3164
|
-
left = Math.max(VIEWPORT_MARGIN, Math.min(left, window.innerWidth - floatingElemRect.width - VIEWPORT_MARGIN));
|
|
3165
|
-
const origin = getFixedPositionOrigin(floatingElem);
|
|
3166
|
-
top -= origin.top;
|
|
3167
|
-
left -= origin.left;
|
|
3168
|
-
floatingElem.style.opacity = "1";
|
|
3169
|
-
floatingElem.style.transform = "none";
|
|
3170
|
-
floatingElem.style.top = `${top}px`;
|
|
3171
|
-
floatingElem.style.left = `${left}px`;
|
|
3172
|
-
};
|
|
3173
3146
|
var SUPPORTED_URL_PROTOCOLS = /* @__PURE__ */ new Set([
|
|
3174
3147
|
"http:",
|
|
3175
3148
|
"https:",
|
|
@@ -3195,49 +3168,38 @@ var FloatingLinkEditor = ({ editor, isLink, setIsLink, isLinkEditMode, setIsLink
|
|
|
3195
3168
|
const [editedLinkUrl, setEditedLinkUrl] = useState("https://");
|
|
3196
3169
|
const [lastSelection, setLastSelection] = useState(null);
|
|
3197
3170
|
const [linkUrl, setLinkUrl] = useState("");
|
|
3198
|
-
const
|
|
3171
|
+
const [target, setTarget] = useState(null);
|
|
3199
3172
|
const inputRef = useRef(null);
|
|
3200
3173
|
const $updateLinkEditor = useCallback(() => {
|
|
3201
3174
|
const selection = $getSelection();
|
|
3175
|
+
let hasLink = false;
|
|
3202
3176
|
if ($isRangeSelection(selection)) {
|
|
3203
3177
|
const node = getSelectedNode2(selection);
|
|
3204
3178
|
const linkParent = $findMatchingParent$1(node, $isLinkNode);
|
|
3205
|
-
|
|
3206
|
-
|
|
3207
|
-
|
|
3208
|
-
setLinkUrl(node.getURL());
|
|
3209
|
-
} else {
|
|
3210
|
-
setLinkUrl("");
|
|
3211
|
-
}
|
|
3179
|
+
hasLink = !!linkParent || $isLinkNode(node);
|
|
3180
|
+
const url = linkParent ? linkParent.getURL() : $isLinkNode(node) ? node.getURL() : "";
|
|
3181
|
+
setLinkUrl(url);
|
|
3212
3182
|
if (isLinkEditMode) {
|
|
3213
|
-
setEditedLinkUrl(
|
|
3183
|
+
setEditedLinkUrl(url);
|
|
3214
3184
|
}
|
|
3215
3185
|
}
|
|
3216
|
-
const editorElem = editorRef.current;
|
|
3217
3186
|
const nativeSelection = getDOMSelection(editor._window);
|
|
3218
3187
|
const activeElement = document.activeElement;
|
|
3219
|
-
if (editorElem === null) {
|
|
3220
|
-
return;
|
|
3221
|
-
}
|
|
3222
3188
|
const rootElement = editor.getRootElement();
|
|
3223
|
-
if (
|
|
3189
|
+
if (hasLink && selection !== null && nativeSelection !== null && rootElement !== null && rootElement.contains(nativeSelection.anchorNode) && editor.isEditable()) {
|
|
3224
3190
|
const domRect = nativeSelection.focusNode?.parentElement?.getBoundingClientRect();
|
|
3225
3191
|
if (domRect) {
|
|
3226
|
-
|
|
3227
|
-
const topBoundary = toolbarEl ? toolbarEl.getBoundingClientRect().bottom + 8 : 8;
|
|
3228
|
-
setFloatingElemPositionForLinkEditor(domRect, editorElem, topBoundary);
|
|
3192
|
+
setTarget({ getBoundingClientRect: () => domRect });
|
|
3229
3193
|
}
|
|
3230
3194
|
setLastSelection(selection);
|
|
3231
|
-
} else if (!activeElement || activeElement
|
|
3232
|
-
|
|
3233
|
-
setFloatingElemPositionForLinkEditor(null, editorElem);
|
|
3234
|
-
}
|
|
3195
|
+
} else if (!(activeElement instanceof HTMLInputElement) || activeElement !== inputRef.current) {
|
|
3196
|
+
setTarget(null);
|
|
3235
3197
|
setLastSelection(null);
|
|
3236
3198
|
setIsLinkEditMode(false);
|
|
3237
3199
|
setLinkUrl("");
|
|
3238
3200
|
}
|
|
3239
3201
|
return true;
|
|
3240
|
-
}, [editor, setIsLinkEditMode, isLinkEditMode
|
|
3202
|
+
}, [editor, setIsLinkEditMode, isLinkEditMode]);
|
|
3241
3203
|
useEffect(() => {
|
|
3242
3204
|
const update = () => {
|
|
3243
3205
|
editor.getEditorState().read(() => {
|
|
@@ -3305,6 +3267,7 @@ var FloatingLinkEditor = ({ editor, isLink, setIsLink, isLinkEditMode, setIsLink
|
|
|
3305
3267
|
if (lastSelection !== null) {
|
|
3306
3268
|
if (linkUrl !== "") {
|
|
3307
3269
|
editor.update(() => {
|
|
3270
|
+
$setSelection(lastSelection.clone());
|
|
3308
3271
|
editor.dispatchCommand(
|
|
3309
3272
|
TOGGLE_LINK_COMMAND,
|
|
3310
3273
|
sanitizeUrl(editedLinkUrl)
|
|
@@ -3327,99 +3290,119 @@ var FloatingLinkEditor = ({ editor, isLink, setIsLink, isLinkEditMode, setIsLink
|
|
|
3327
3290
|
setIsLinkEditMode(false);
|
|
3328
3291
|
}
|
|
3329
3292
|
};
|
|
3330
|
-
return /* @__PURE__ */ jsx(
|
|
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
|
-
|
|
3360
|
-
|
|
3361
|
-
|
|
3362
|
-
|
|
3363
|
-
|
|
3364
|
-
|
|
3365
|
-
|
|
3366
|
-
|
|
3367
|
-
|
|
3368
|
-
|
|
3369
|
-
|
|
3370
|
-
|
|
3371
|
-
|
|
3372
|
-
|
|
3373
|
-
|
|
3374
|
-
|
|
3375
|
-
|
|
3376
|
-
|
|
3377
|
-
|
|
3378
|
-
|
|
3379
|
-
|
|
3380
|
-
|
|
3381
|
-
|
|
3382
|
-
|
|
3383
|
-
|
|
3384
|
-
|
|
3385
|
-
|
|
3386
|
-
|
|
3387
|
-
|
|
3388
|
-
|
|
3389
|
-
|
|
3390
|
-
|
|
3391
|
-
|
|
3392
|
-
|
|
3393
|
-
|
|
3394
|
-
|
|
3395
|
-
|
|
3396
|
-
|
|
3397
|
-
|
|
3398
|
-
|
|
3399
|
-
|
|
3400
|
-
|
|
3401
|
-
|
|
3402
|
-
|
|
3403
|
-
|
|
3404
|
-
|
|
3405
|
-
|
|
3406
|
-
|
|
3407
|
-
|
|
3408
|
-
|
|
3409
|
-
|
|
3410
|
-
|
|
3411
|
-
|
|
3412
|
-
|
|
3413
|
-
|
|
3414
|
-
|
|
3415
|
-
|
|
3416
|
-
|
|
3417
|
-
|
|
3293
|
+
return /* @__PURE__ */ jsx(
|
|
3294
|
+
Popover,
|
|
3295
|
+
{
|
|
3296
|
+
open: isLink && !!target,
|
|
3297
|
+
onOpenChange: (_, data) => {
|
|
3298
|
+
if (!data.open) setIsLink(false);
|
|
3299
|
+
},
|
|
3300
|
+
positioning: { target: target ?? void 0, position: "below", align: "start" },
|
|
3301
|
+
unstable_disableAutoFocus: true,
|
|
3302
|
+
children: /* @__PURE__ */ jsx(PopoverSurface, { style: { display: "flex", alignItems: "center", gap: 6, padding: 8, maxWidth: 360 }, children: isLinkEditMode ? /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
3303
|
+
/* @__PURE__ */ jsx(
|
|
3304
|
+
"input",
|
|
3305
|
+
{
|
|
3306
|
+
ref: inputRef,
|
|
3307
|
+
value: editedLinkUrl,
|
|
3308
|
+
style: {
|
|
3309
|
+
flex: 1,
|
|
3310
|
+
minWidth: 180,
|
|
3311
|
+
border: "none",
|
|
3312
|
+
outline: "none",
|
|
3313
|
+
background: "#f1f1f1",
|
|
3314
|
+
borderRadius: 15,
|
|
3315
|
+
padding: "8px 12px",
|
|
3316
|
+
fontSize: 14
|
|
3317
|
+
},
|
|
3318
|
+
onChange: (event) => {
|
|
3319
|
+
setEditedLinkUrl(event.target.value);
|
|
3320
|
+
},
|
|
3321
|
+
onKeyDown: (event) => {
|
|
3322
|
+
monitorInputInteraction(event);
|
|
3323
|
+
}
|
|
3324
|
+
}
|
|
3325
|
+
),
|
|
3326
|
+
/* @__PURE__ */ jsx(
|
|
3327
|
+
Button,
|
|
3328
|
+
{
|
|
3329
|
+
appearance: "subtle",
|
|
3330
|
+
size: "small",
|
|
3331
|
+
icon: /* @__PURE__ */ jsx(DismissRegular, { fontSize: 16 }),
|
|
3332
|
+
title: "Cancel",
|
|
3333
|
+
"aria-label": "Cancel",
|
|
3334
|
+
onMouseDown: preventDefault,
|
|
3335
|
+
onClick: () => {
|
|
3336
|
+
setIsLinkEditMode(false);
|
|
3337
|
+
}
|
|
3338
|
+
}
|
|
3339
|
+
),
|
|
3340
|
+
/* @__PURE__ */ jsx(
|
|
3341
|
+
Button,
|
|
3342
|
+
{
|
|
3343
|
+
appearance: "primary",
|
|
3344
|
+
size: "small",
|
|
3345
|
+
icon: /* @__PURE__ */ jsx(CheckmarkRegular, { fontSize: 16 }),
|
|
3346
|
+
title: "Confirm",
|
|
3347
|
+
"aria-label": "Confirm",
|
|
3348
|
+
onMouseDown: preventDefault,
|
|
3349
|
+
onClick: handleLinkSubmission
|
|
3350
|
+
}
|
|
3351
|
+
)
|
|
3352
|
+
] }) : /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
3353
|
+
/* @__PURE__ */ jsx(
|
|
3354
|
+
"a",
|
|
3355
|
+
{
|
|
3356
|
+
href: sanitizeUrl(linkUrl),
|
|
3357
|
+
target: "_blank",
|
|
3358
|
+
rel: "noopener noreferrer",
|
|
3359
|
+
style: {
|
|
3360
|
+
padding: "0 8px",
|
|
3361
|
+
overflow: "hidden",
|
|
3362
|
+
textOverflow: "ellipsis",
|
|
3363
|
+
whiteSpace: "nowrap",
|
|
3364
|
+
maxWidth: 260
|
|
3365
|
+
},
|
|
3366
|
+
children: linkUrl
|
|
3367
|
+
}
|
|
3368
|
+
),
|
|
3369
|
+
/* @__PURE__ */ jsx(
|
|
3370
|
+
Button,
|
|
3371
|
+
{
|
|
3372
|
+
appearance: "subtle",
|
|
3373
|
+
size: "small",
|
|
3374
|
+
icon: /* @__PURE__ */ jsx(EditRegular, { fontSize: 16 }),
|
|
3375
|
+
title: "Edit link",
|
|
3376
|
+
"aria-label": "Edit link",
|
|
3377
|
+
onMouseDown: preventDefault,
|
|
3378
|
+
onClick: (event) => {
|
|
3379
|
+
event.preventDefault();
|
|
3380
|
+
setEditedLinkUrl(linkUrl);
|
|
3381
|
+
setIsLinkEditMode(true);
|
|
3382
|
+
}
|
|
3383
|
+
}
|
|
3384
|
+
),
|
|
3385
|
+
/* @__PURE__ */ jsx(
|
|
3386
|
+
Button,
|
|
3387
|
+
{
|
|
3388
|
+
appearance: "subtle",
|
|
3389
|
+
size: "small",
|
|
3390
|
+
icon: /* @__PURE__ */ jsx(DeleteRegular, { fontSize: 16 }),
|
|
3391
|
+
title: "Remove link",
|
|
3392
|
+
"aria-label": "Remove link",
|
|
3393
|
+
onMouseDown: preventDefault,
|
|
3394
|
+
onClick: () => {
|
|
3395
|
+
editor.dispatchCommand(TOGGLE_LINK_COMMAND, null);
|
|
3396
|
+
}
|
|
3397
|
+
}
|
|
3398
|
+
)
|
|
3399
|
+
] }) })
|
|
3400
|
+
}
|
|
3401
|
+
);
|
|
3418
3402
|
};
|
|
3419
|
-
var useFloatingLinkEditorToolbar = (editor,
|
|
3403
|
+
var useFloatingLinkEditorToolbar = (editor, isLinkEditMode, setIsLinkEditMode) => {
|
|
3420
3404
|
const [activeEditor, setActiveEditor] = useState(editor);
|
|
3421
3405
|
const [isLink, setIsLink] = useState(false);
|
|
3422
|
-
const portalContainer = useFloatingPortalContainer(editor);
|
|
3423
3406
|
useEffect(() => {
|
|
3424
3407
|
function $updateToolbar() {
|
|
3425
3408
|
const selection = $getSelection();
|
|
@@ -3467,29 +3450,21 @@ var useFloatingLinkEditorToolbar = (editor, anchorElem, isLinkEditMode, setIsLin
|
|
|
3467
3450
|
)
|
|
3468
3451
|
);
|
|
3469
3452
|
}, [editor]);
|
|
3470
|
-
|
|
3471
|
-
|
|
3472
|
-
|
|
3473
|
-
|
|
3474
|
-
|
|
3475
|
-
|
|
3476
|
-
|
|
3477
|
-
|
|
3478
|
-
|
|
3479
|
-
setIsLink,
|
|
3480
|
-
isLinkEditMode,
|
|
3481
|
-
setIsLinkEditMode
|
|
3482
|
-
}
|
|
3483
|
-
),
|
|
3484
|
-
portalContainer
|
|
3453
|
+
return /* @__PURE__ */ jsx(
|
|
3454
|
+
FloatingLinkEditor,
|
|
3455
|
+
{
|
|
3456
|
+
isLink,
|
|
3457
|
+
editor: activeEditor,
|
|
3458
|
+
setIsLink,
|
|
3459
|
+
isLinkEditMode,
|
|
3460
|
+
setIsLinkEditMode
|
|
3461
|
+
}
|
|
3485
3462
|
);
|
|
3486
3463
|
};
|
|
3487
|
-
var FloatingLinkEditorPlugin = ({
|
|
3464
|
+
var FloatingLinkEditorPlugin = ({ isLinkEditMode, setIsLinkEditMode }) => {
|
|
3488
3465
|
const [editor] = useLexicalComposerContext();
|
|
3489
|
-
const validAnchorElem = anchorElem && anchorElem instanceof HTMLElement ? anchorElem : document.body;
|
|
3490
3466
|
return useFloatingLinkEditorToolbar(
|
|
3491
3467
|
editor,
|
|
3492
|
-
validAnchorElem,
|
|
3493
3468
|
isLinkEditMode,
|
|
3494
3469
|
setIsLinkEditMode
|
|
3495
3470
|
);
|
|
@@ -6561,6 +6536,7 @@ var InsertLinkPlugin = ({
|
|
|
6561
6536
|
opacity: disabled ? 0.55 : 1,
|
|
6562
6537
|
cursor: disabled ? "not-allowed" : "pointer"
|
|
6563
6538
|
},
|
|
6539
|
+
onMouseDown: (event) => event.preventDefault(),
|
|
6564
6540
|
onClick: insertLink
|
|
6565
6541
|
},
|
|
6566
6542
|
"insert-link"
|