@lexical/react 0.39.1-nightly.20260109.0 → 0.39.1-nightly.20260113.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.
|
@@ -16,6 +16,28 @@ var react = require('react');
|
|
|
16
16
|
var reactDom = require('react-dom');
|
|
17
17
|
var jsxRuntime = require('react/jsx-runtime');
|
|
18
18
|
|
|
19
|
+
/**
|
|
20
|
+
* Copyright (c) Meta Platforms, Inc. and affiliates.
|
|
21
|
+
*
|
|
22
|
+
* This source code is licensed under the MIT license found in the
|
|
23
|
+
* LICENSE file in the root directory of this source tree.
|
|
24
|
+
*
|
|
25
|
+
*/
|
|
26
|
+
|
|
27
|
+
const CAN_USE_DOM = typeof window !== 'undefined' && typeof window.document !== 'undefined' && typeof window.document.createElement !== 'undefined';
|
|
28
|
+
|
|
29
|
+
/**
|
|
30
|
+
* Copyright (c) Meta Platforms, Inc. and affiliates.
|
|
31
|
+
*
|
|
32
|
+
* This source code is licensed under the MIT license found in the
|
|
33
|
+
* LICENSE file in the root directory of this source tree.
|
|
34
|
+
*
|
|
35
|
+
*/
|
|
36
|
+
|
|
37
|
+
const documentMode = CAN_USE_DOM && 'documentMode' in document ? document.documentMode : null;
|
|
38
|
+
const IS_FIREFOX = CAN_USE_DOM && /^(?!.*Seamonkey)(?=.*Firefox).*/i.test(navigator.userAgent);
|
|
39
|
+
CAN_USE_DOM && 'InputEvent' in window && !documentMode ? 'getTargetRanges' in new window.InputEvent('input') : false;
|
|
40
|
+
|
|
19
41
|
/**
|
|
20
42
|
* Copyright (c) Meta Platforms, Inc. and affiliates.
|
|
21
43
|
*
|
|
@@ -473,6 +495,10 @@ function useDraggableBlockMenu(editor, anchorElem, menuRef, targetLineRef, isEdi
|
|
|
473
495
|
return false;
|
|
474
496
|
}
|
|
475
497
|
if (targetNode === draggedNode) {
|
|
498
|
+
// Firefox-specific fix: Even when no move occurs, restore focus to ensure cursor visibility
|
|
499
|
+
if (IS_FIREFOX) {
|
|
500
|
+
editor.focus();
|
|
501
|
+
}
|
|
476
502
|
return true;
|
|
477
503
|
}
|
|
478
504
|
const targetBlockElemTop = targetBlockElem.getBoundingClientRect().top;
|
|
@@ -482,6 +508,15 @@ function useDraggableBlockMenu(editor, anchorElem, menuRef, targetLineRef, isEdi
|
|
|
482
508
|
targetNode.insertBefore(draggedNode);
|
|
483
509
|
}
|
|
484
510
|
setDraggableBlockElem(null);
|
|
511
|
+
|
|
512
|
+
// Firefox-specific fix: Use editor.focus() after drop to properly restore
|
|
513
|
+
// both focus and selection. This ensures cursor visibility immediately.
|
|
514
|
+
if (IS_FIREFOX) {
|
|
515
|
+
// Using $onUpdate ensures this happens after the current update cycle finishes
|
|
516
|
+
lexical.$onUpdate(() => {
|
|
517
|
+
editor.focus();
|
|
518
|
+
});
|
|
519
|
+
}
|
|
485
520
|
return true;
|
|
486
521
|
}
|
|
487
522
|
return utils.mergeRegister(editor.registerCommand(lexical.DRAGOVER_COMMAND, event => {
|
|
@@ -490,6 +525,63 @@ function useDraggableBlockMenu(editor, anchorElem, menuRef, targetLineRef, isEdi
|
|
|
490
525
|
return $onDrop(event);
|
|
491
526
|
}, lexical.COMMAND_PRIORITY_HIGH));
|
|
492
527
|
}, [anchorElem, editor, targetLineRef, setDraggableBlockElem]);
|
|
528
|
+
|
|
529
|
+
// Firefox-specific: Prevent blur when clicking on drag handle to maintain cursor visibility.
|
|
530
|
+
// Firefox fires blur before dragstart, causing focus loss. We detect this by checking if
|
|
531
|
+
// the blur's relatedTarget is on the menu using isOnMenu, then restore focus synchronously.
|
|
532
|
+
react.useEffect(() => {
|
|
533
|
+
if (!IS_FIREFOX || !isEditable) {
|
|
534
|
+
return;
|
|
535
|
+
}
|
|
536
|
+
return utils.mergeRegister(editor.registerRootListener((rootElement, prevRootElement) => {
|
|
537
|
+
function onBlur(event) {
|
|
538
|
+
const relatedTarget = event.relatedTarget;
|
|
539
|
+
if (relatedTarget && relatedTarget instanceof HTMLElement && isOnMenu(relatedTarget)) {
|
|
540
|
+
// Blur is caused by clicking on drag handle - restore focus immediately
|
|
541
|
+
// to prevent cursor from disappearing. This must be synchronous to work.
|
|
542
|
+
if (rootElement) {
|
|
543
|
+
rootElement.focus({
|
|
544
|
+
preventScroll: true
|
|
545
|
+
});
|
|
546
|
+
// Force selection update to ensure cursor is visible
|
|
547
|
+
editor.update(() => {
|
|
548
|
+
const selection = lexical.$getSelection();
|
|
549
|
+
if (selection !== null && !selection.dirty) {
|
|
550
|
+
selection.dirty = true;
|
|
551
|
+
}
|
|
552
|
+
});
|
|
553
|
+
}
|
|
554
|
+
// Prevent the event from propagating to LexicalEvents handler
|
|
555
|
+
event.stopImmediatePropagation();
|
|
556
|
+
}
|
|
557
|
+
}
|
|
558
|
+
if (rootElement) {
|
|
559
|
+
rootElement.addEventListener('blur', onBlur, true);
|
|
560
|
+
}
|
|
561
|
+
if (prevRootElement) {
|
|
562
|
+
prevRootElement.removeEventListener('blur', onBlur, true);
|
|
563
|
+
}
|
|
564
|
+
}),
|
|
565
|
+
// Intercept BLUR_COMMAND if focus is on the menu (fallback in case event propagation wasn't stopped)
|
|
566
|
+
editor.registerCommand(lexical.BLUR_COMMAND, () => {
|
|
567
|
+
const rootElement = editor.getRootElement();
|
|
568
|
+
const activeElement = document.activeElement;
|
|
569
|
+
if (rootElement && activeElement && activeElement instanceof HTMLElement && isOnMenu(activeElement)) {
|
|
570
|
+
// Focus is on menu - restore to root and prevent blur command
|
|
571
|
+
rootElement.focus({
|
|
572
|
+
preventScroll: true
|
|
573
|
+
});
|
|
574
|
+
editor.update(() => {
|
|
575
|
+
const selection = lexical.$getSelection();
|
|
576
|
+
if (selection !== null && !selection.dirty) {
|
|
577
|
+
selection.dirty = true;
|
|
578
|
+
}
|
|
579
|
+
});
|
|
580
|
+
return true; // Prevent command from propagating
|
|
581
|
+
}
|
|
582
|
+
return false;
|
|
583
|
+
}, lexical.COMMAND_PRIORITY_HIGH));
|
|
584
|
+
}, [editor, isEditable, isOnMenu]);
|
|
493
585
|
function onDragStart(event) {
|
|
494
586
|
const dataTransfer = event.dataTransfer;
|
|
495
587
|
if (!dataTransfer || !draggableBlockElem) {
|
|
@@ -505,10 +597,38 @@ function useDraggableBlockMenu(editor, anchorElem, menuRef, targetLineRef, isEdi
|
|
|
505
597
|
});
|
|
506
598
|
isDraggingBlockRef.current = true;
|
|
507
599
|
dataTransfer.setData(DRAG_DATA_FORMAT, nodeKey);
|
|
600
|
+
|
|
601
|
+
// Firefox-specific: Restore focus synchronously after drag starts to prevent cursor loss.
|
|
602
|
+
// The blur handler should have already restored focus, but we do it here as a fallback
|
|
603
|
+
// and to ensure selection is properly maintained during drag.
|
|
604
|
+
if (IS_FIREFOX) {
|
|
605
|
+
const rootElement = editor.getRootElement();
|
|
606
|
+
if (rootElement !== null && document.activeElement !== rootElement) {
|
|
607
|
+
// Restore focus synchronously - don't use requestAnimationFrame as blur already happened
|
|
608
|
+
// and we need immediate focus restoration to maintain cursor visibility
|
|
609
|
+
rootElement.focus({
|
|
610
|
+
preventScroll: true
|
|
611
|
+
});
|
|
612
|
+
// Force selection update to ensure cursor is visible
|
|
613
|
+
editor.update(() => {
|
|
614
|
+
const selection = lexical.$getSelection();
|
|
615
|
+
if (selection !== null && !selection.dirty) {
|
|
616
|
+
selection.dirty = true;
|
|
617
|
+
}
|
|
618
|
+
});
|
|
619
|
+
}
|
|
620
|
+
}
|
|
508
621
|
}
|
|
509
622
|
function onDragEnd() {
|
|
510
623
|
isDraggingBlockRef.current = false;
|
|
511
624
|
hideTargetLine(targetLineRef.current);
|
|
625
|
+
|
|
626
|
+
// Firefox-specific fix: Use editor.focus() to properly restore both focus and
|
|
627
|
+
// selection after drag ends. This ensures cursor visibility immediately.
|
|
628
|
+
if (IS_FIREFOX) {
|
|
629
|
+
// editor.focus() handles both focus restoration and selection update properly
|
|
630
|
+
editor.focus();
|
|
631
|
+
}
|
|
512
632
|
}
|
|
513
633
|
return /*#__PURE__*/reactDom.createPortal(/*#__PURE__*/jsxRuntime.jsxs(jsxRuntime.Fragment, {
|
|
514
634
|
children: [/*#__PURE__*/jsxRuntime.jsx("div", {
|
|
@@ -9,11 +9,33 @@
|
|
|
9
9
|
import { useLexicalComposerContext } from '@lexical/react/LexicalComposerContext';
|
|
10
10
|
import { eventFiles } from '@lexical/rich-text';
|
|
11
11
|
import { calculateZoomLevel, mergeRegister, isHTMLElement } from '@lexical/utils';
|
|
12
|
-
import { DRAGOVER_COMMAND, COMMAND_PRIORITY_LOW, DROP_COMMAND, COMMAND_PRIORITY_HIGH, $getNodeByKey, $getNearestNodeFromDOMNode, $getRoot } from 'lexical';
|
|
12
|
+
import { DRAGOVER_COMMAND, COMMAND_PRIORITY_LOW, DROP_COMMAND, COMMAND_PRIORITY_HIGH, BLUR_COMMAND, $getSelection, $getNodeByKey, $getNearestNodeFromDOMNode, $onUpdate, $getRoot } from 'lexical';
|
|
13
13
|
import { useRef, useState, useCallback, useEffect } from 'react';
|
|
14
14
|
import { createPortal } from 'react-dom';
|
|
15
15
|
import { jsxs, Fragment, jsx } from 'react/jsx-runtime';
|
|
16
16
|
|
|
17
|
+
/**
|
|
18
|
+
* Copyright (c) Meta Platforms, Inc. and affiliates.
|
|
19
|
+
*
|
|
20
|
+
* This source code is licensed under the MIT license found in the
|
|
21
|
+
* LICENSE file in the root directory of this source tree.
|
|
22
|
+
*
|
|
23
|
+
*/
|
|
24
|
+
|
|
25
|
+
const CAN_USE_DOM = typeof window !== 'undefined' && typeof window.document !== 'undefined' && typeof window.document.createElement !== 'undefined';
|
|
26
|
+
|
|
27
|
+
/**
|
|
28
|
+
* Copyright (c) Meta Platforms, Inc. and affiliates.
|
|
29
|
+
*
|
|
30
|
+
* This source code is licensed under the MIT license found in the
|
|
31
|
+
* LICENSE file in the root directory of this source tree.
|
|
32
|
+
*
|
|
33
|
+
*/
|
|
34
|
+
|
|
35
|
+
const documentMode = CAN_USE_DOM && 'documentMode' in document ? document.documentMode : null;
|
|
36
|
+
const IS_FIREFOX = CAN_USE_DOM && /^(?!.*Seamonkey)(?=.*Firefox).*/i.test(navigator.userAgent);
|
|
37
|
+
CAN_USE_DOM && 'InputEvent' in window && !documentMode ? 'getTargetRanges' in new window.InputEvent('input') : false;
|
|
38
|
+
|
|
17
39
|
/**
|
|
18
40
|
* Copyright (c) Meta Platforms, Inc. and affiliates.
|
|
19
41
|
*
|
|
@@ -471,6 +493,10 @@ function useDraggableBlockMenu(editor, anchorElem, menuRef, targetLineRef, isEdi
|
|
|
471
493
|
return false;
|
|
472
494
|
}
|
|
473
495
|
if (targetNode === draggedNode) {
|
|
496
|
+
// Firefox-specific fix: Even when no move occurs, restore focus to ensure cursor visibility
|
|
497
|
+
if (IS_FIREFOX) {
|
|
498
|
+
editor.focus();
|
|
499
|
+
}
|
|
474
500
|
return true;
|
|
475
501
|
}
|
|
476
502
|
const targetBlockElemTop = targetBlockElem.getBoundingClientRect().top;
|
|
@@ -480,6 +506,15 @@ function useDraggableBlockMenu(editor, anchorElem, menuRef, targetLineRef, isEdi
|
|
|
480
506
|
targetNode.insertBefore(draggedNode);
|
|
481
507
|
}
|
|
482
508
|
setDraggableBlockElem(null);
|
|
509
|
+
|
|
510
|
+
// Firefox-specific fix: Use editor.focus() after drop to properly restore
|
|
511
|
+
// both focus and selection. This ensures cursor visibility immediately.
|
|
512
|
+
if (IS_FIREFOX) {
|
|
513
|
+
// Using $onUpdate ensures this happens after the current update cycle finishes
|
|
514
|
+
$onUpdate(() => {
|
|
515
|
+
editor.focus();
|
|
516
|
+
});
|
|
517
|
+
}
|
|
483
518
|
return true;
|
|
484
519
|
}
|
|
485
520
|
return mergeRegister(editor.registerCommand(DRAGOVER_COMMAND, event => {
|
|
@@ -488,6 +523,63 @@ function useDraggableBlockMenu(editor, anchorElem, menuRef, targetLineRef, isEdi
|
|
|
488
523
|
return $onDrop(event);
|
|
489
524
|
}, COMMAND_PRIORITY_HIGH));
|
|
490
525
|
}, [anchorElem, editor, targetLineRef, setDraggableBlockElem]);
|
|
526
|
+
|
|
527
|
+
// Firefox-specific: Prevent blur when clicking on drag handle to maintain cursor visibility.
|
|
528
|
+
// Firefox fires blur before dragstart, causing focus loss. We detect this by checking if
|
|
529
|
+
// the blur's relatedTarget is on the menu using isOnMenu, then restore focus synchronously.
|
|
530
|
+
useEffect(() => {
|
|
531
|
+
if (!IS_FIREFOX || !isEditable) {
|
|
532
|
+
return;
|
|
533
|
+
}
|
|
534
|
+
return mergeRegister(editor.registerRootListener((rootElement, prevRootElement) => {
|
|
535
|
+
function onBlur(event) {
|
|
536
|
+
const relatedTarget = event.relatedTarget;
|
|
537
|
+
if (relatedTarget && relatedTarget instanceof HTMLElement && isOnMenu(relatedTarget)) {
|
|
538
|
+
// Blur is caused by clicking on drag handle - restore focus immediately
|
|
539
|
+
// to prevent cursor from disappearing. This must be synchronous to work.
|
|
540
|
+
if (rootElement) {
|
|
541
|
+
rootElement.focus({
|
|
542
|
+
preventScroll: true
|
|
543
|
+
});
|
|
544
|
+
// Force selection update to ensure cursor is visible
|
|
545
|
+
editor.update(() => {
|
|
546
|
+
const selection = $getSelection();
|
|
547
|
+
if (selection !== null && !selection.dirty) {
|
|
548
|
+
selection.dirty = true;
|
|
549
|
+
}
|
|
550
|
+
});
|
|
551
|
+
}
|
|
552
|
+
// Prevent the event from propagating to LexicalEvents handler
|
|
553
|
+
event.stopImmediatePropagation();
|
|
554
|
+
}
|
|
555
|
+
}
|
|
556
|
+
if (rootElement) {
|
|
557
|
+
rootElement.addEventListener('blur', onBlur, true);
|
|
558
|
+
}
|
|
559
|
+
if (prevRootElement) {
|
|
560
|
+
prevRootElement.removeEventListener('blur', onBlur, true);
|
|
561
|
+
}
|
|
562
|
+
}),
|
|
563
|
+
// Intercept BLUR_COMMAND if focus is on the menu (fallback in case event propagation wasn't stopped)
|
|
564
|
+
editor.registerCommand(BLUR_COMMAND, () => {
|
|
565
|
+
const rootElement = editor.getRootElement();
|
|
566
|
+
const activeElement = document.activeElement;
|
|
567
|
+
if (rootElement && activeElement && activeElement instanceof HTMLElement && isOnMenu(activeElement)) {
|
|
568
|
+
// Focus is on menu - restore to root and prevent blur command
|
|
569
|
+
rootElement.focus({
|
|
570
|
+
preventScroll: true
|
|
571
|
+
});
|
|
572
|
+
editor.update(() => {
|
|
573
|
+
const selection = $getSelection();
|
|
574
|
+
if (selection !== null && !selection.dirty) {
|
|
575
|
+
selection.dirty = true;
|
|
576
|
+
}
|
|
577
|
+
});
|
|
578
|
+
return true; // Prevent command from propagating
|
|
579
|
+
}
|
|
580
|
+
return false;
|
|
581
|
+
}, COMMAND_PRIORITY_HIGH));
|
|
582
|
+
}, [editor, isEditable, isOnMenu]);
|
|
491
583
|
function onDragStart(event) {
|
|
492
584
|
const dataTransfer = event.dataTransfer;
|
|
493
585
|
if (!dataTransfer || !draggableBlockElem) {
|
|
@@ -503,10 +595,38 @@ function useDraggableBlockMenu(editor, anchorElem, menuRef, targetLineRef, isEdi
|
|
|
503
595
|
});
|
|
504
596
|
isDraggingBlockRef.current = true;
|
|
505
597
|
dataTransfer.setData(DRAG_DATA_FORMAT, nodeKey);
|
|
598
|
+
|
|
599
|
+
// Firefox-specific: Restore focus synchronously after drag starts to prevent cursor loss.
|
|
600
|
+
// The blur handler should have already restored focus, but we do it here as a fallback
|
|
601
|
+
// and to ensure selection is properly maintained during drag.
|
|
602
|
+
if (IS_FIREFOX) {
|
|
603
|
+
const rootElement = editor.getRootElement();
|
|
604
|
+
if (rootElement !== null && document.activeElement !== rootElement) {
|
|
605
|
+
// Restore focus synchronously - don't use requestAnimationFrame as blur already happened
|
|
606
|
+
// and we need immediate focus restoration to maintain cursor visibility
|
|
607
|
+
rootElement.focus({
|
|
608
|
+
preventScroll: true
|
|
609
|
+
});
|
|
610
|
+
// Force selection update to ensure cursor is visible
|
|
611
|
+
editor.update(() => {
|
|
612
|
+
const selection = $getSelection();
|
|
613
|
+
if (selection !== null && !selection.dirty) {
|
|
614
|
+
selection.dirty = true;
|
|
615
|
+
}
|
|
616
|
+
});
|
|
617
|
+
}
|
|
618
|
+
}
|
|
506
619
|
}
|
|
507
620
|
function onDragEnd() {
|
|
508
621
|
isDraggingBlockRef.current = false;
|
|
509
622
|
hideTargetLine(targetLineRef.current);
|
|
623
|
+
|
|
624
|
+
// Firefox-specific fix: Use editor.focus() to properly restore both focus and
|
|
625
|
+
// selection after drag ends. This ensures cursor visibility immediately.
|
|
626
|
+
if (IS_FIREFOX) {
|
|
627
|
+
// editor.focus() handles both focus restoration and selection update properly
|
|
628
|
+
editor.focus();
|
|
629
|
+
}
|
|
510
630
|
}
|
|
511
631
|
return /*#__PURE__*/createPortal(/*#__PURE__*/jsxs(Fragment, {
|
|
512
632
|
children: [/*#__PURE__*/jsx("div", {
|
|
@@ -6,4 +6,4 @@
|
|
|
6
6
|
*
|
|
7
7
|
*/
|
|
8
8
|
|
|
9
|
-
"use strict";var t=require("@lexical/react/LexicalComposerContext"),e=require("@lexical/rich-text"),n=require("@lexical/utils"),
|
|
9
|
+
"use strict";var t=require("@lexical/react/LexicalComposerContext"),e=require("@lexical/rich-text"),n=require("@lexical/utils"),o=require("lexical"),r=require("react"),i=require("react-dom"),s=require("react/jsx-runtime");const l="undefined"!=typeof window&&void 0!==window.document&&void 0!==window.document.createElement,a=l&&"documentMode"in document?document.documentMode:null,c=l&&/^(?!.*Seamonkey)(?=.*Firefox).*/i.test(navigator.userAgent);l&&"InputEvent"in window&&!a&&new window.InputEvent("input");class u{_x;_y;constructor(t,e){this._x=t,this._y=e}get x(){return this._x}get y(){return this._y}equals({x:t,y:e}){return this.x===t&&this.y===e}calcDeltaXTo({x:t}){return this.x-t}calcDeltaYTo({y:t}){return this.y-t}calcHorizontalDistanceTo(t){return Math.abs(this.calcDeltaXTo(t))}calcVerticalDistance(t){return Math.abs(this.calcDeltaYTo(t))}calcDistanceTo(t){return Math.sqrt(Math.pow(this.calcDeltaXTo(t),2)+Math.pow(this.calcDeltaYTo(t),2))}}class m{_left;_top;_right;_bottom;constructor(t,e,n,o){const[r,i]=e<=o?[e,o]:[o,e],[s,l]=t<=n?[t,n]:[n,t];this._top=r,this._right=l,this._left=s,this._bottom=i}get top(){return this._top}get right(){return this._right}get bottom(){return this._bottom}get left(){return this._left}get width(){return Math.abs(this._left-this._right)}get height(){return Math.abs(this._bottom-this._top)}equals({top:t,left:e,bottom:n,right:o}){return t===this._top&&n===this._bottom&&e===this._left&&o===this._right}contains(t){if(t instanceof u){const{x:e,y:n}=t,o=n<this._top,r=n>this._bottom,i=e<this._left,s=e>this._right;return{reason:{isOnBottomSide:r,isOnLeftSide:i,isOnRightSide:s,isOnTopSide:o},result:!(o||r||i||s)}}{const{top:e,left:n,bottom:o,right:r}=t;return e>=this._top&&e<=this._bottom&&o>=this._top&&o<=this._bottom&&n>=this._left&&n<=this._right&&r>=this._left&&r<=this._right}}intersectsWith(t){const{left:e,top:n,width:o,height:r}=t,{left:i,top:s,width:l,height:a}=this;return(e+o>=i+l?e+o:i+l)-(e<=i?e:i)<=o+l&&(n+r>=s+a?n+r:s+a)-(n<=s?n:s)<=r+a}generateNewRect({left:t=this.left,top:e=this.top,right:n=this.right,bottom:o=this.bottom}){return new m(t,e,n,o)}static fromLTRB(t,e,n,o){return new m(t,e,n,o)}static fromLWTH(t,e,n,o){return new m(t,n,t+e,n+o)}static fromPoints(t,e){const{y:n,x:o}=t,{y:r,x:i}=e;return m.fromLTRB(o,n,i,r)}static fromDOM(t){const{top:e,width:n,left:o,height:r}=t.getBoundingClientRect();return m.fromLWTH(o,n,e,r)}}const g="application/x-lexical-drag-block";let d=1/0;function f(t){const e=(t,e)=>t?parseFloat(window.getComputedStyle(t)[e]):0,{marginTop:n,marginBottom:o}=window.getComputedStyle(t),r=e(t.previousElementSibling,"marginBottom"),i=e(t.nextElementSibling,"marginTop"),s=Math.max(parseFloat(n),r);return{marginBottom:Math.max(parseFloat(o),i),marginTop:s}}function h(t,e,r,i=!1){const s=t.getBoundingClientRect(),l=function(t){return t.getEditorState().read(()=>o.$getRoot().getChildrenKeys())}(e);let a=null;return e.getEditorState().read(()=>{if(i){const[t,o]=[e.getElementByKey(l[0]),e.getElementByKey(l[l.length-1])],[i,s]=[null!=t?t.getBoundingClientRect():void 0,null!=o?o.getBoundingClientRect():void 0];if(i&&s){const e=n.calculateZoomLevel(t),l=n.calculateZoomLevel(o);if(r.y/e<i.top?a=t:r.y/l>s.bottom&&(a=o),a)return}}let t=0===(o=l.length)?1/0:d>=0&&d<o?d:Math.floor(o/2);var o;let c=0;for(;t>=0&&t<l.length;){const o=l[t],i=e.getElementByKey(o);if(null===i)break;const g=n.calculateZoomLevel(i),h=new u(r.x/g,r.y/g),p=m.fromDOM(i),{marginTop:y,marginBottom:_}=f(i),v=p.generateNewRect({bottom:p.bottom+_,left:s.left,right:s.right,top:p.top-y}),{result:x,reason:{isOnTopSide:E,isOnBottomSide:M}}=v.contains(h);if(x){a=i,d=t;break}0===c&&(c=E?-1:M?1:1/0),t+=c}}),a}function p(t,l,a,u,m,d,p,y,_){const v=l.parentElement,x=r.useRef(!1),[E,M]=r.useState(null),R=r.useCallback(t=>{M(t),_&&_(t)},[_]);return r.useEffect(()=>{function e(e){const o=e.target;if(!n.isHTMLElement(o))return void R(null);if(y(o))return;const r=h(l,t,e);R(r)}function o(){R(null)}return null!=v&&(v.addEventListener("mousemove",e),v.addEventListener("mouseleave",o)),()=>{null!=v&&(v.removeEventListener("mousemove",e),v.removeEventListener("mouseleave",o))}},[v,l,t,y,R]),r.useEffect(()=>{const t=n.calculateZoomLevel(document.getElementsByClassName("ContentEditable__root")[0],!0);a.current&&function(t,e,n,o){if(!t)return void(e.style.display="none");const r=t.getBoundingClientRect(),i=window.getComputedStyle(t),s=e.getBoundingClientRect(),l=n.getBoundingClientRect();let a=parseInt(i.lineHeight,10);isNaN(a)&&(a=r.bottom-r.top);const c=(r.top+(a-(s.height||a))/2-l.top+n.scrollTop)/o;e.style.display="flex",e.style.opacity="1",e.style.transform=`translate(4px, ${c}px)`}(E,a.current,l,t)},[l,E,a]),r.useEffect(()=>{function r(o){if(!x.current)return!1;const[r]=e.eventFiles(o);if(r)return!1;const{pageY:i,target:s}=o;if(!n.isHTMLElement(s))return!1;const a=h(l,t,o,!0),c=u.current;return null!==a&&null!==c&&(function(t,e,n,o){const{top:r,height:i}=e.getBoundingClientRect(),{top:s,width:l}=o.getBoundingClientRect(),{marginTop:a,marginBottom:c}=f(e);let u=r;n>=r?u+=i+c/2:u-=a/2;const m=u-s-2+o.scrollTop;t.style.transform=`translate(24px, ${m}px)`,t.style.width=l-48+"px",t.style.opacity=".4"}(c,a,i/n.calculateZoomLevel(s),l),o.preventDefault(),!0)}return n.mergeRegister(t.registerCommand(o.DRAGOVER_COMMAND,t=>r(t),o.COMMAND_PRIORITY_LOW),t.registerCommand(o.DROP_COMMAND,r=>function(r){if(!x.current)return!1;const[i]=e.eventFiles(r);if(i)return!1;const{target:s,dataTransfer:a,pageY:u}=r,m=null!=a?a.getData(g):"",d=o.$getNodeByKey(m);if(!d)return!1;if(!n.isHTMLElement(s))return!1;const f=h(l,t,r,!0);if(!f)return!1;const p=o.$getNearestNodeFromDOMNode(f);if(!p)return!1;if(p===d)return c&&t.focus(),!0;const y=f.getBoundingClientRect().top;return u/n.calculateZoomLevel(s)>=y?p.insertAfter(d):p.insertBefore(d),R(null),c&&o.$onUpdate(()=>{t.focus()}),!0}(r),o.COMMAND_PRIORITY_HIGH))},[l,t,u,R]),r.useEffect(()=>{if(c&&m)return n.mergeRegister(t.registerRootListener((e,n)=>{function r(n){const r=n.relatedTarget;r&&r instanceof HTMLElement&&y(r)&&(e&&(e.focus({preventScroll:!0}),t.update(()=>{const t=o.$getSelection();null===t||t.dirty||(t.dirty=!0)})),n.stopImmediatePropagation())}e&&e.addEventListener("blur",r,!0),n&&n.removeEventListener("blur",r,!0)}),t.registerCommand(o.BLUR_COMMAND,()=>{const e=t.getRootElement(),n=document.activeElement;return!!(e&&n&&n instanceof HTMLElement&&y(n))&&(e.focus({preventScroll:!0}),t.update(()=>{const t=o.$getSelection();null===t||t.dirty||(t.dirty=!0)}),!0)},o.COMMAND_PRIORITY_HIGH))},[t,m,y]),i.createPortal(s.jsxs(s.Fragment,{children:[s.jsx("div",{draggable:!0,onDragStart:function(e){const n=e.dataTransfer;if(!n||!E)return;!function(t,e){const{transform:n}=e.style;e.style.transform="translateZ(0)",t.setDragImage(e,0,0),setTimeout(()=>{e.style.transform=n})}(n,E);let r="";if(t.update(()=>{const t=o.$getNearestNodeFromDOMNode(E);t&&(r=t.getKey())}),x.current=!0,n.setData(g,r),c){const e=t.getRootElement();null!==e&&document.activeElement!==e&&(e.focus({preventScroll:!0}),t.update(()=>{const t=o.$getSelection();null===t||t.dirty||(t.dirty=!0)}))}},onDragEnd:function(){var e;x.current=!1,(e=u.current)&&(e.style.opacity="0",e.style.transform="translate(-10000px, -10000px)"),c&&t.focus()},children:m&&d}),p]}),l)}exports.DraggableBlockPlugin_EXPERIMENTAL=function({anchorElem:e=document.body,menuRef:n,targetLineRef:o,menuComponent:r,targetLineComponent:i,isOnMenu:s,onElementChanged:l}){const[a]=t.useLexicalComposerContext();return p(a,e,n,o,a._editable,r,i,s,l)};
|
|
@@ -6,4 +6,4 @@
|
|
|
6
6
|
*
|
|
7
7
|
*/
|
|
8
8
|
|
|
9
|
-
import{useLexicalComposerContext as t}from"@lexical/react/LexicalComposerContext";import{eventFiles as e}from"@lexical/rich-text";import{calculateZoomLevel as n,mergeRegister as
|
|
9
|
+
import{useLexicalComposerContext as t}from"@lexical/react/LexicalComposerContext";import{eventFiles as e}from"@lexical/rich-text";import{calculateZoomLevel as n,mergeRegister as o,isHTMLElement as r}from"@lexical/utils";import{DRAGOVER_COMMAND as i,COMMAND_PRIORITY_LOW as s,DROP_COMMAND as l,COMMAND_PRIORITY_HIGH as a,BLUR_COMMAND as c,$getSelection as u,$getNodeByKey as m,$getNearestNodeFromDOMNode as g,$onUpdate as h,$getRoot as f}from"lexical";import{useRef as d,useState as p,useCallback as y,useEffect as _}from"react";import{createPortal as x}from"react-dom";import{jsxs as b,Fragment as v,jsx as w}from"react/jsx-runtime";const E="undefined"!=typeof window&&void 0!==window.document&&void 0!==window.document.createElement,T=E&&"documentMode"in document?document.documentMode:null,B=E&&/^(?!.*Seamonkey)(?=.*Firefox).*/i.test(navigator.userAgent);E&&"InputEvent"in window&&!T&&new window.InputEvent("input");class C{_x;_y;constructor(t,e){this._x=t,this._y=e}get x(){return this._x}get y(){return this._y}equals({x:t,y:e}){return this.x===t&&this.y===e}calcDeltaXTo({x:t}){return this.x-t}calcDeltaYTo({y:t}){return this.y-t}calcHorizontalDistanceTo(t){return Math.abs(this.calcDeltaXTo(t))}calcVerticalDistance(t){return Math.abs(this.calcDeltaYTo(t))}calcDistanceTo(t){return Math.sqrt(Math.pow(this.calcDeltaXTo(t),2)+Math.pow(this.calcDeltaYTo(t),2))}}class R{_left;_top;_right;_bottom;constructor(t,e,n,o){const[r,i]=e<=o?[e,o]:[o,e],[s,l]=t<=n?[t,n]:[n,t];this._top=r,this._right=l,this._left=s,this._bottom=i}get top(){return this._top}get right(){return this._right}get bottom(){return this._bottom}get left(){return this._left}get width(){return Math.abs(this._left-this._right)}get height(){return Math.abs(this._bottom-this._top)}equals({top:t,left:e,bottom:n,right:o}){return t===this._top&&n===this._bottom&&e===this._left&&o===this._right}contains(t){if(t instanceof C){const{x:e,y:n}=t,o=n<this._top,r=n>this._bottom,i=e<this._left,s=e>this._right;return{reason:{isOnBottomSide:r,isOnLeftSide:i,isOnRightSide:s,isOnTopSide:o},result:!(o||r||i||s)}}{const{top:e,left:n,bottom:o,right:r}=t;return e>=this._top&&e<=this._bottom&&o>=this._top&&o<=this._bottom&&n>=this._left&&n<=this._right&&r>=this._left&&r<=this._right}}intersectsWith(t){const{left:e,top:n,width:o,height:r}=t,{left:i,top:s,width:l,height:a}=this;return(e+o>=i+l?e+o:i+l)-(e<=i?e:i)<=o+l&&(n+r>=s+a?n+r:s+a)-(n<=s?n:s)<=r+a}generateNewRect({left:t=this.left,top:e=this.top,right:n=this.right,bottom:o=this.bottom}){return new R(t,e,n,o)}static fromLTRB(t,e,n,o){return new R(t,e,n,o)}static fromLWTH(t,e,n,o){return new R(t,n,t+e,n+o)}static fromPoints(t,e){const{y:n,x:o}=t,{y:r,x:i}=e;return R.fromLTRB(o,n,i,r)}static fromDOM(t){const{top:e,width:n,left:o,height:r}=t.getBoundingClientRect();return R.fromLWTH(o,n,e,r)}}const S="application/x-lexical-drag-block";let D=1/0;function L(t){const e=(t,e)=>t?parseFloat(window.getComputedStyle(t)[e]):0,{marginTop:n,marginBottom:o}=window.getComputedStyle(t),r=e(t.previousElementSibling,"marginBottom"),i=e(t.nextElementSibling,"marginTop"),s=Math.max(parseFloat(n),r);return{marginBottom:Math.max(parseFloat(o),i),marginTop:s}}function M(t,e,o,r=!1){const i=t.getBoundingClientRect(),s=function(t){return t.getEditorState().read(()=>f().getChildrenKeys())}(e);let l=null;return e.getEditorState().read(()=>{if(r){const[t,r]=[e.getElementByKey(s[0]),e.getElementByKey(s[s.length-1])],[i,a]=[null!=t?t.getBoundingClientRect():void 0,null!=r?r.getBoundingClientRect():void 0];if(i&&a){const e=n(t),s=n(r);if(o.y/e<i.top?l=t:o.y/s>a.bottom&&(l=r),l)return}}let t=0===(a=s.length)?1/0:D>=0&&D<a?D:Math.floor(a/2);var a;let c=0;for(;t>=0&&t<s.length;){const r=s[t],a=e.getElementByKey(r);if(null===a)break;const u=n(a),m=new C(o.x/u,o.y/u),g=R.fromDOM(a),{marginTop:h,marginBottom:f}=L(a),d=g.generateNewRect({bottom:g.bottom+f,left:i.left,right:i.right,top:g.top-h}),{result:p,reason:{isOnTopSide:y,isOnBottomSide:_}}=d.contains(m);if(p){l=a,D=t;break}0===c&&(c=y?-1:_?1:1/0),t+=c}}),l}function O(t,f,E,T,C,R,D,O,H){const I=f.parentElement,K=d(!1),[N,Y]=p(null),k=y(t=>{Y(t),H&&H(t)},[H]);return _(()=>{function e(e){const n=e.target;if(!r(n))return void k(null);if(O(n))return;const o=M(f,t,e);k(o)}function n(){k(null)}return null!=I&&(I.addEventListener("mousemove",e),I.addEventListener("mouseleave",n)),()=>{null!=I&&(I.removeEventListener("mousemove",e),I.removeEventListener("mouseleave",n))}},[I,f,t,O,k]),_(()=>{const t=n(document.getElementsByClassName("ContentEditable__root")[0],!0);E.current&&function(t,e,n,o){if(!t)return void(e.style.display="none");const r=t.getBoundingClientRect(),i=window.getComputedStyle(t),s=e.getBoundingClientRect(),l=n.getBoundingClientRect();let a=parseInt(i.lineHeight,10);isNaN(a)&&(a=r.bottom-r.top);const c=(r.top+(a-(s.height||a))/2-l.top+n.scrollTop)/o;e.style.display="flex",e.style.opacity="1",e.style.transform=`translate(4px, ${c}px)`}(N,E.current,f,t)},[f,N,E]),_(()=>{function c(o){if(!K.current)return!1;const[i]=e(o);if(i)return!1;const{pageY:s,target:l}=o;if(!r(l))return!1;const a=M(f,t,o,!0),c=T.current;return null!==a&&null!==c&&(function(t,e,n,o){const{top:r,height:i}=e.getBoundingClientRect(),{top:s,width:l}=o.getBoundingClientRect(),{marginTop:a,marginBottom:c}=L(e);let u=r;n>=r?u+=i+c/2:u-=a/2;const m=u-s-2+o.scrollTop;t.style.transform=`translate(24px, ${m}px)`,t.style.width=l-48+"px",t.style.opacity=".4"}(c,a,s/n(l),f),o.preventDefault(),!0)}return o(t.registerCommand(i,t=>c(t),s),t.registerCommand(l,o=>function(o){if(!K.current)return!1;const[i]=e(o);if(i)return!1;const{target:s,dataTransfer:l,pageY:a}=o,c=null!=l?l.getData(S):"",u=m(c);if(!u)return!1;if(!r(s))return!1;const d=M(f,t,o,!0);if(!d)return!1;const p=g(d);if(!p)return!1;if(p===u)return B&&t.focus(),!0;const y=d.getBoundingClientRect().top;return a/n(s)>=y?p.insertAfter(u):p.insertBefore(u),k(null),B&&h(()=>{t.focus()}),!0}(o),a))},[f,t,T,k]),_(()=>{if(B&&C)return o(t.registerRootListener((e,n)=>{function o(n){const o=n.relatedTarget;o&&o instanceof HTMLElement&&O(o)&&(e&&(e.focus({preventScroll:!0}),t.update(()=>{const t=u();null===t||t.dirty||(t.dirty=!0)})),n.stopImmediatePropagation())}e&&e.addEventListener("blur",o,!0),n&&n.removeEventListener("blur",o,!0)}),t.registerCommand(c,()=>{const e=t.getRootElement(),n=document.activeElement;return!!(e&&n&&n instanceof HTMLElement&&O(n))&&(e.focus({preventScroll:!0}),t.update(()=>{const t=u();null===t||t.dirty||(t.dirty=!0)}),!0)},a))},[t,C,O]),x(b(v,{children:[w("div",{draggable:!0,onDragStart:function(e){const n=e.dataTransfer;if(!n||!N)return;!function(t,e){const{transform:n}=e.style;e.style.transform="translateZ(0)",t.setDragImage(e,0,0),setTimeout(()=>{e.style.transform=n})}(n,N);let o="";if(t.update(()=>{const t=g(N);t&&(o=t.getKey())}),K.current=!0,n.setData(S,o),B){const e=t.getRootElement();null!==e&&document.activeElement!==e&&(e.focus({preventScroll:!0}),t.update(()=>{const t=u();null===t||t.dirty||(t.dirty=!0)}))}},onDragEnd:function(){var e;K.current=!1,(e=T.current)&&(e.style.opacity="0",e.style.transform="translate(-10000px, -10000px)"),B&&t.focus()},children:C&&R}),D]}),f)}function H({anchorElem:e=document.body,menuRef:n,targetLineRef:o,menuComponent:r,targetLineComponent:i,isOnMenu:s,onElementChanged:l}){const[a]=t();return O(a,e,n,o,a._editable,r,i,s,l)}export{H as DraggableBlockPlugin_EXPERIMENTAL};
|
package/package.json
CHANGED
|
@@ -8,26 +8,26 @@
|
|
|
8
8
|
"rich-text"
|
|
9
9
|
],
|
|
10
10
|
"license": "MIT",
|
|
11
|
-
"version": "0.39.1-nightly.
|
|
11
|
+
"version": "0.39.1-nightly.20260113.0",
|
|
12
12
|
"dependencies": {
|
|
13
13
|
"@floating-ui/react": "^0.27.16",
|
|
14
|
-
"@lexical/devtools-core": "0.39.1-nightly.
|
|
15
|
-
"@lexical/dragon": "0.39.1-nightly.
|
|
16
|
-
"@lexical/extension": "0.39.1-nightly.
|
|
17
|
-
"@lexical/hashtag": "0.39.1-nightly.
|
|
18
|
-
"@lexical/history": "0.39.1-nightly.
|
|
19
|
-
"@lexical/link": "0.39.1-nightly.
|
|
20
|
-
"@lexical/list": "0.39.1-nightly.
|
|
21
|
-
"@lexical/mark": "0.39.1-nightly.
|
|
22
|
-
"@lexical/markdown": "0.39.1-nightly.
|
|
23
|
-
"@lexical/overflow": "0.39.1-nightly.
|
|
24
|
-
"@lexical/plain-text": "0.39.1-nightly.
|
|
25
|
-
"@lexical/rich-text": "0.39.1-nightly.
|
|
26
|
-
"@lexical/table": "0.39.1-nightly.
|
|
27
|
-
"@lexical/text": "0.39.1-nightly.
|
|
28
|
-
"@lexical/utils": "0.39.1-nightly.
|
|
29
|
-
"@lexical/yjs": "0.39.1-nightly.
|
|
30
|
-
"lexical": "0.39.1-nightly.
|
|
14
|
+
"@lexical/devtools-core": "0.39.1-nightly.20260113.0",
|
|
15
|
+
"@lexical/dragon": "0.39.1-nightly.20260113.0",
|
|
16
|
+
"@lexical/extension": "0.39.1-nightly.20260113.0",
|
|
17
|
+
"@lexical/hashtag": "0.39.1-nightly.20260113.0",
|
|
18
|
+
"@lexical/history": "0.39.1-nightly.20260113.0",
|
|
19
|
+
"@lexical/link": "0.39.1-nightly.20260113.0",
|
|
20
|
+
"@lexical/list": "0.39.1-nightly.20260113.0",
|
|
21
|
+
"@lexical/mark": "0.39.1-nightly.20260113.0",
|
|
22
|
+
"@lexical/markdown": "0.39.1-nightly.20260113.0",
|
|
23
|
+
"@lexical/overflow": "0.39.1-nightly.20260113.0",
|
|
24
|
+
"@lexical/plain-text": "0.39.1-nightly.20260113.0",
|
|
25
|
+
"@lexical/rich-text": "0.39.1-nightly.20260113.0",
|
|
26
|
+
"@lexical/table": "0.39.1-nightly.20260113.0",
|
|
27
|
+
"@lexical/text": "0.39.1-nightly.20260113.0",
|
|
28
|
+
"@lexical/utils": "0.39.1-nightly.20260113.0",
|
|
29
|
+
"@lexical/yjs": "0.39.1-nightly.20260113.0",
|
|
30
|
+
"lexical": "0.39.1-nightly.20260113.0",
|
|
31
31
|
"react-error-boundary": "^6.0.0"
|
|
32
32
|
},
|
|
33
33
|
"peerDependencies": {
|