@lexical/react 0.38.3-nightly.20251113.0 → 0.38.3-nightly.20251117.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/LexicalAutoEmbedPlugin.d.ts +2 -3
- package/LexicalAutoEmbedPlugin.dev.js +0 -2
- package/LexicalAutoEmbedPlugin.dev.mjs +0 -2
- package/LexicalAutoEmbedPlugin.js.flow +0 -2
- package/LexicalAutoEmbedPlugin.prod.js +1 -1
- package/LexicalAutoEmbedPlugin.prod.mjs +1 -1
- package/LexicalNodeMenuPlugin.d.ts +3 -4
- package/LexicalNodeMenuPlugin.dev.js +49 -10
- package/LexicalNodeMenuPlugin.dev.mjs +51 -12
- package/LexicalNodeMenuPlugin.js.flow +0 -12
- package/LexicalNodeMenuPlugin.prod.js +1 -1
- package/LexicalNodeMenuPlugin.prod.mjs +1 -1
- package/LexicalTypeaheadMenuPlugin.d.ts +3 -4
- package/LexicalTypeaheadMenuPlugin.dev.js +52 -10
- package/LexicalTypeaheadMenuPlugin.dev.mjs +54 -12
- package/LexicalTypeaheadMenuPlugin.js.flow +0 -12
- package/LexicalTypeaheadMenuPlugin.prod.js +1 -1
- package/LexicalTypeaheadMenuPlugin.prod.mjs +1 -1
- package/package.json +18 -48
- package/shared/LexicalMenu.d.ts +4 -10
- package/LexicalContextMenuPlugin.d.ts +0 -36
- package/LexicalContextMenuPlugin.dev.js +0 -524
- package/LexicalContextMenuPlugin.dev.mjs +0 -509
- package/LexicalContextMenuPlugin.js +0 -11
- package/LexicalContextMenuPlugin.mjs +0 -13
- package/LexicalContextMenuPlugin.node.mjs +0 -11
- package/LexicalContextMenuPlugin.prod.js +0 -9
- package/LexicalContextMenuPlugin.prod.mjs +0 -9
|
@@ -8,9 +8,10 @@
|
|
|
8
8
|
|
|
9
9
|
import { useLexicalComposerContext } from '@lexical/react/LexicalComposerContext';
|
|
10
10
|
import { createCommand, COMMAND_PRIORITY_LOW, KEY_ARROW_DOWN_COMMAND, KEY_ARROW_UP_COMMAND, KEY_ESCAPE_COMMAND, KEY_TAB_COMMAND, KEY_ENTER_COMMAND, $getSelection, $isRangeSelection, $isTextNode, getDOMSelection } from 'lexical';
|
|
11
|
-
import React, { useLayoutEffect, useEffect, useRef, useCallback, useState
|
|
11
|
+
import React, { useLayoutEffect, useEffect, useRef, useCallback, useState } from 'react';
|
|
12
12
|
import { mergeRegister } from '@lexical/utils';
|
|
13
|
-
import
|
|
13
|
+
import ReactDOM from 'react-dom';
|
|
14
|
+
import { jsx, jsxs } from 'react/jsx-runtime';
|
|
14
15
|
|
|
15
16
|
/**
|
|
16
17
|
* Copyright (c) Meta Platforms, Inc. and affiliates.
|
|
@@ -68,6 +69,8 @@ const useLayoutEffectImpl = CAN_USE_DOM ? useLayoutEffect : useEffect;
|
|
|
68
69
|
class MenuOption {
|
|
69
70
|
key;
|
|
70
71
|
ref;
|
|
72
|
+
icon;
|
|
73
|
+
title;
|
|
71
74
|
constructor(key) {
|
|
72
75
|
this.key = key;
|
|
73
76
|
this.ref = {
|
|
@@ -217,13 +220,38 @@ function useDynamicPositioning(resolution, targetElement, onReposition, onVisibi
|
|
|
217
220
|
}, [targetElement, editor, onVisibilityChange, onReposition, resolution]);
|
|
218
221
|
}
|
|
219
222
|
const SCROLL_TYPEAHEAD_OPTION_INTO_VIEW_COMMAND$1 = createCommand('SCROLL_TYPEAHEAD_OPTION_INTO_VIEW_COMMAND');
|
|
223
|
+
function MenuItem({
|
|
224
|
+
index,
|
|
225
|
+
isSelected,
|
|
226
|
+
onClick,
|
|
227
|
+
onMouseEnter,
|
|
228
|
+
option
|
|
229
|
+
}) {
|
|
230
|
+
let className = 'item';
|
|
231
|
+
if (isSelected) {
|
|
232
|
+
className += ' selected';
|
|
233
|
+
}
|
|
234
|
+
return /*#__PURE__*/jsxs("li", {
|
|
235
|
+
tabIndex: -1,
|
|
236
|
+
className: className,
|
|
237
|
+
ref: option.setRefElement,
|
|
238
|
+
role: "option",
|
|
239
|
+
"aria-selected": isSelected,
|
|
240
|
+
id: 'typeahead-item-' + index,
|
|
241
|
+
onMouseEnter: onMouseEnter,
|
|
242
|
+
onClick: onClick,
|
|
243
|
+
children: [option.icon, /*#__PURE__*/jsx("span", {
|
|
244
|
+
className: "text",
|
|
245
|
+
children: option.title
|
|
246
|
+
})]
|
|
247
|
+
}, option.key);
|
|
248
|
+
}
|
|
220
249
|
function LexicalMenu({
|
|
221
250
|
close,
|
|
222
251
|
editor,
|
|
223
252
|
anchorElementRef,
|
|
224
253
|
resolution,
|
|
225
254
|
options,
|
|
226
|
-
menuRenderFn,
|
|
227
255
|
onSelectOption,
|
|
228
256
|
shouldSplitNodeWithQuery = false,
|
|
229
257
|
commandPriority = COMMAND_PRIORITY_LOW,
|
|
@@ -251,6 +279,25 @@ function LexicalMenu({
|
|
|
251
279
|
setHighlightedIndex(index);
|
|
252
280
|
}
|
|
253
281
|
}, [editor]);
|
|
282
|
+
const menuRenderFn = useCallback(() => {
|
|
283
|
+
return anchorElementRef.current && options.length ? /*#__PURE__*/ReactDOM.createPortal(/*#__PURE__*/jsx("div", {
|
|
284
|
+
className: "typeahead-popover mentions-menu",
|
|
285
|
+
children: /*#__PURE__*/jsx("ul", {
|
|
286
|
+
children: options.map((option, i) => /*#__PURE__*/jsx(MenuItem, {
|
|
287
|
+
index: i,
|
|
288
|
+
isSelected: selectedIndex === i,
|
|
289
|
+
onClick: () => {
|
|
290
|
+
setHighlightedIndex(i);
|
|
291
|
+
selectOptionAndCleanUp(option);
|
|
292
|
+
},
|
|
293
|
+
onMouseEnter: () => {
|
|
294
|
+
setHighlightedIndex(i);
|
|
295
|
+
},
|
|
296
|
+
option: option
|
|
297
|
+
}, option.key))
|
|
298
|
+
})
|
|
299
|
+
}), anchorElementRef.current) : null;
|
|
300
|
+
}, [anchorElementRef, options, selectedIndex, selectOptionAndCleanUp, setHighlightedIndex]);
|
|
254
301
|
useEffect(() => {
|
|
255
302
|
return () => {
|
|
256
303
|
const rootElem = editor.getRootElement();
|
|
@@ -346,13 +393,7 @@ function LexicalMenu({
|
|
|
346
393
|
return true;
|
|
347
394
|
}, commandPriority));
|
|
348
395
|
}, [selectOptionAndCleanUp, close, editor, options, selectedIndex, updateSelectedIndex, commandPriority]);
|
|
349
|
-
|
|
350
|
-
options,
|
|
351
|
-
selectOptionAndCleanUp,
|
|
352
|
-
selectedIndex,
|
|
353
|
-
setHighlightedIndex
|
|
354
|
-
}), [selectOptionAndCleanUp, selectedIndex, options]);
|
|
355
|
-
return menuRenderFn(anchorElementRef, listItemProps, resolution.match ? resolution.match.matchingString : '');
|
|
396
|
+
return menuRenderFn();
|
|
356
397
|
}
|
|
357
398
|
function setContainerDivAttributes(containerDiv, className) {
|
|
358
399
|
if (className != null) {
|
|
@@ -562,7 +603,6 @@ function LexicalTypeaheadMenuPlugin({
|
|
|
562
603
|
onSelectOption,
|
|
563
604
|
onOpen,
|
|
564
605
|
onClose,
|
|
565
|
-
menuRenderFn,
|
|
566
606
|
triggerFn,
|
|
567
607
|
anchorClassName,
|
|
568
608
|
commandPriority = COMMAND_PRIORITY_LOW,
|
|
@@ -593,6 +633,9 @@ function LexicalTypeaheadMenuPlugin({
|
|
|
593
633
|
closeTypeahead();
|
|
594
634
|
return;
|
|
595
635
|
}
|
|
636
|
+
if (editor.isComposing()) {
|
|
637
|
+
return;
|
|
638
|
+
}
|
|
596
639
|
const editorWindow = editor._window || window;
|
|
597
640
|
const range = editorWindow.document.createRange();
|
|
598
641
|
const selection = $getSelection();
|
|
@@ -632,7 +675,6 @@ function LexicalTypeaheadMenuPlugin({
|
|
|
632
675
|
editor: editor,
|
|
633
676
|
anchorElementRef: anchorElementRef,
|
|
634
677
|
options: options,
|
|
635
|
-
menuRenderFn: menuRenderFn,
|
|
636
678
|
shouldSplitNodeWithQuery: true,
|
|
637
679
|
onSelectOption: onSelectOption,
|
|
638
680
|
commandPriority: commandPriority,
|
|
@@ -36,17 +36,6 @@ declare export var SCROLL_TYPEAHEAD_OPTION_INTO_VIEW_COMMAND: LexicalCommand<{
|
|
|
36
36
|
option: MenuOption,
|
|
37
37
|
}>;
|
|
38
38
|
|
|
39
|
-
export type MenuRenderFn<TOption> = (
|
|
40
|
-
anchorElementRef: {current: HTMLElement | null},
|
|
41
|
-
itemProps: {
|
|
42
|
-
selectedIndex: number | null,
|
|
43
|
-
selectOptionAndCleanUp: (option: TOption) => void,
|
|
44
|
-
setHighlightedIndex: (index: number) => void,
|
|
45
|
-
options: Array<TOption>,
|
|
46
|
-
},
|
|
47
|
-
matchingString: string,
|
|
48
|
-
) => React.Portal | React.MixedElement | null;
|
|
49
|
-
|
|
50
39
|
declare export function getScrollParent(
|
|
51
40
|
element: HTMLElement,
|
|
52
41
|
includeHidden: boolean,
|
|
@@ -66,7 +55,6 @@ export type TypeaheadMenuPluginProps<TOption> = {
|
|
|
66
55
|
matchingString: string,
|
|
67
56
|
) => void,
|
|
68
57
|
options: Array<TOption>,
|
|
69
|
-
menuRenderFn: MenuRenderFn<TOption>,
|
|
70
58
|
triggerFn: TriggerFn,
|
|
71
59
|
onOpen?: (resolution: MenuResolution) => void,
|
|
72
60
|
onClose?: () => void,
|
|
@@ -6,4 +6,4 @@
|
|
|
6
6
|
*
|
|
7
7
|
*/
|
|
8
8
|
|
|
9
|
-
"use strict";var e=require("@lexical/react/LexicalComposerContext"),t=require("lexical"),n=require("react"),o=require("@lexical/utils"),r=require("react/jsx-runtime");const
|
|
9
|
+
"use strict";var e=require("@lexical/react/LexicalComposerContext"),t=require("lexical"),n=require("react"),o=require("@lexical/utils"),r=require("react-dom"),l=require("react/jsx-runtime");const i="startTransition";const s="undefined"!=typeof window&&void 0!==window.document&&void 0!==window.document.createElement,u=s?n.useLayoutEffect:n.useEffect;const c=e=>{const t=document.getElementById("typeahead-menu");if(!t)return;const n=t.getBoundingClientRect();n.top+n.height>window.innerHeight&&t.scrollIntoView({block:"center"}),n.top<0&&t.scrollIntoView({block:"center"}),e.scrollIntoView({block:"nearest"})};function a(e,t){const n=e.getBoundingClientRect(),o=t.getBoundingClientRect();return n.top>=o.top-6&&n.top<=o.bottom+6}function d(t,o,r,l){const[i]=e.useLexicalComposerContext();n.useEffect(()=>{if(null!=o&&null!=t){const e=i.getRootElement(),t=null!=e?function(e){let t=getComputedStyle(e);const n="absolute"===t.position,o=/(auto|scroll)/;if("fixed"===t.position)return document.body;for(let r=e;r=r.parentElement;)if(t=getComputedStyle(r),(!n||"static"!==t.position)&&o.test(t.overflow+t.overflowY+t.overflowX))return r;return document.body}(e):document.body;let n=!1,s=a(o,t);const u=function(){n||(window.requestAnimationFrame(function(){r(),n=!1}),n=!0);const e=a(o,t);e!==s&&(s=e,null!=l&&l(e))},c=new ResizeObserver(r);return window.addEventListener("resize",r),document.addEventListener("scroll",u,{capture:!0,passive:!0}),c.observe(o),()=>{c.unobserve(o),window.removeEventListener("resize",r),document.removeEventListener("scroll",u,!0)}}},[o,i,l,r,t])}const f=t.createCommand("SCROLL_TYPEAHEAD_OPTION_INTO_VIEW_COMMAND");function m({index:e,isSelected:t,onClick:n,onMouseEnter:o,option:r}){let i="item";return t&&(i+=" selected"),l.jsxs("li",{tabIndex:-1,className:i,ref:r.setRefElement,role:"option","aria-selected":t,id:"typeahead-item-"+e,onMouseEnter:o,onClick:n,children:[r.icon,l.jsx("span",{className:"text",children:r.title})]},r.key)}function p({close:e,editor:i,anchorElementRef:s,resolution:a,options:d,onSelectOption:p,shouldSplitNodeWithQuery:g=!1,commandPriority:h=t.COMMAND_PRIORITY_LOW,preselectFirstItem:C=!0}){const[E,x]=n.useState(null),y=null!==E?Math.min(d.length-1,E):null,b=a.match&&a.match.matchingString;n.useEffect(()=>{C&&x(0)},[b,C]);const O=n.useCallback(n=>{i.update(()=>{const o=null!=a.match&&g?function(e){const n=t.$getSelection();if(!t.$isRangeSelection(n)||!n.isCollapsed())return null;const o=n.anchor;if("text"!==o.type)return null;const r=o.getNode();if(!r.isSimpleText())return null;const l=o.offset,i=r.getTextContent().slice(0,l),s=e.replaceableString.length,u=l-function(e,t,n){let o=n;for(let n=o;n<=t.length;n++)e.slice(-n)===t.substring(0,n)&&(o=n);return o}(i,e.matchingString,s);if(u<0)return null;let c;return 0===u?[c]=r.splitText(l):[,c]=r.splitText(u,l),c}(a.match):null;p(n,o,e,a.match?a.match.matchingString:"")})},[i,g,a.match,p,e]),w=n.useCallback(e=>{const t=i.getRootElement();null!==t&&(t.setAttribute("aria-activedescendant","typeahead-item-"+e),x(e))},[i]),v=n.useCallback(()=>s.current&&d.length?r.createPortal(l.jsx("div",{className:"typeahead-popover mentions-menu",children:l.jsx("ul",{children:d.map((e,t)=>l.jsx(m,{index:t,isSelected:y===t,onClick:()=>{x(t),O(e)},onMouseEnter:()=>{x(t)},option:e},e.key))})}),s.current):null,[s,d,y,O,x]);return n.useEffect(()=>()=>{const e=i.getRootElement();null!==e&&e.removeAttribute("aria-activedescendant")},[i]),u(()=>{null===d?x(null):null===y&&C&&w(0)},[d,y,w,C]),n.useEffect(()=>o.mergeRegister(i.registerCommand(f,({option:e})=>!(!e.ref||null==e.ref.current)&&(c(e.ref.current),!0),h)),[i,w,h]),n.useEffect(()=>o.mergeRegister(i.registerCommand(t.KEY_ARROW_DOWN_COMMAND,e=>{const t=e;if(null!==d&&d.length){const e=null===y?0:y!==d.length-1?y+1:0;w(e);const n=d[e];if(!n)return w(-1),t.preventDefault(),t.stopImmediatePropagation(),!0;n.ref&&n.ref.current&&i.dispatchCommand(f,{index:e,option:n}),t.preventDefault(),t.stopImmediatePropagation()}return!0},h),i.registerCommand(t.KEY_ARROW_UP_COMMAND,e=>{const t=e;if(null!==d&&d.length){const e=null===y?d.length-1:0!==y?y-1:d.length-1;w(e);const n=d[e];if(!n)return w(-1),t.preventDefault(),t.stopImmediatePropagation(),!0;n.ref&&n.ref.current&&c(n.ref.current),t.preventDefault(),t.stopImmediatePropagation()}return!0},h),i.registerCommand(t.KEY_ESCAPE_COMMAND,t=>{const n=t;return n.preventDefault(),n.stopImmediatePropagation(),e(),!0},h),i.registerCommand(t.KEY_TAB_COMMAND,e=>{const t=e;return null!==d&&null!==y&&null!=d[y]&&(t.preventDefault(),t.stopImmediatePropagation(),O(d[y]),!0)},h),i.registerCommand(t.KEY_ENTER_COMMAND,e=>null!==d&&null!==y&&null!=d[y]&&(null!==e&&(e.preventDefault(),e.stopImmediatePropagation()),O(d[y]),!0),h)),[O,e,i,d,y,w,h]),v()}function g(e,t){null!=t&&(e.className=t),e.setAttribute("aria-label","Typeahead menu"),e.setAttribute("role","listbox"),e.style.display="block",e.style.position="absolute"}const h="\\.,\\+\\*\\?\\$\\@\\|#{}\\(\\)\\^\\-\\[\\]\\\\/!%'\"~=<>_:;";const C=t.createCommand("SCROLL_TYPEAHEAD_OPTION_INTO_VIEW_COMMAND");exports.LexicalTypeaheadMenuPlugin=function({options:o,onQueryChange:r,onSelectOption:u,onOpen:c,onClose:a,triggerFn:f,anchorClassName:m,commandPriority:h=t.COMMAND_PRIORITY_LOW,parent:C,preselectFirstItem:E=!0,ignoreEntityBoundary:x=!1}){const[y]=e.useLexicalComposerContext(),[b,O]=n.useState(null),w=function(t,o,r,l=(s?document.body:void 0),i=!0){const[u]=e.useLexicalComposerContext(),c=s?document.createElement("div"):null,a=n.useRef(c),f=n.useCallback(()=>{if(null===a.current||void 0===l)return;a.current.style.top=a.current.style.bottom;const e=u.getRootElement(),n=a.current,o=n.firstChild;if(null!==e&&null!==t){const{left:s,top:u,width:c,height:d}=t.getRect(),f=a.current.offsetHeight;if(n.style.top=`${u+f+3+(i?window.pageYOffset:0)}px`,n.style.left=`${s+window.pageXOffset}px`,n.style.height=`${d}px`,n.style.width=`${c}px`,null!==o){o.style.top=`${u}`;const t=o.getBoundingClientRect(),r=t.height,l=t.width,c=e.getBoundingClientRect();s+l>c.right&&(n.style.left=`${c.right-l+window.pageXOffset}px`),(u+r>window.innerHeight||u+r>c.bottom)&&u-c.top>r+d&&(n.style.top=`${u-r-d+(i?window.pageYOffset:0)}px`)}n.isConnected||(g(n,r),l.append(n)),n.setAttribute("id","typeahead-menu"),e.setAttribute("aria-controls","typeahead-menu")}},[u,t,i,r,l]);n.useEffect(()=>{const e=u.getRootElement();return null!==t&&f(),()=>{null!==e&&e.removeAttribute("aria-controls");const t=a.current;null!==t&&t.isConnected&&(t.remove(),t.removeAttribute("id"))}},[u,f,t]);const m=n.useCallback(e=>{null!==t&&(e||o(null))},[t,o]);return d(t,a.current,f,m),null!=c&&c===a.current&&(g(c,r),null!=l&&l.append(c)),a}(b,O,m,C),v=n.useCallback(()=>{O(null),null!=a&&null!==b&&a()},[a,b]),R=n.useCallback(e=>{O(e),null!=c&&null===b&&c(e)},[c,b]);return n.useEffect(()=>{const e=y.registerUpdateListener(()=>{y.getEditorState().read(()=>{if(!y.isEditable())return void v();if(y.isComposing())return;const e=y._window||window,o=e.document.createRange(),l=t.$getSelection(),s=function(e){let n=null;return e.getEditorState().read(()=>{const e=t.$getSelection();t.$isRangeSelection(e)&&(n=function(e){const t=e.anchor;if("text"!==t.type)return null;const n=t.getNode();if(!n.isSimpleText())return null;const o=t.offset;return n.getTextContent().slice(0,o)}(e))}),n}(y);if(!t.$isRangeSelection(l)||!l.isCollapsed()||null===s||null===o)return void v();const u=f(s,y);if(r(u?u.matchingString:null),null!==u&&(x||!function(e,n){return 0===n&&e.getEditorState().read(()=>{const e=t.$getSelection();if(t.$isRangeSelection(e)){const n=e.anchor.getNode().getPreviousSibling();return t.$isTextNode(n)&&n.isTextEntity()}return!1})}(y,u.leadOffset))){const r=function(e,n,o){const r=t.getDOMSelection(o);if(null===r||!r.isCollapsed)return!1;const l=r.anchorNode,i=e,s=r.anchorOffset;if(null==l||null==s)return!1;try{n.setStart(l,i),n.setEnd(l,s)}catch(e){return!1}return!0}(u.leadOffset,o,e);if(null!==r)return c=()=>R({getRect:()=>o.getBoundingClientRect(),match:u}),void(i in n?n[i](c):c())}var c;v()})});return()=>{e()}},[y,f,r,b,v,R,x]),n.useEffect(()=>y.registerEditableListener(e=>{e||v()}),[y,v]),null===b||null===y||null===w.current?null:l.jsx(p,{close:v,resolution:b,editor:y,anchorElementRef:w,options:o,shouldSplitNodeWithQuery:!0,onSelectOption:u,commandPriority:h,preselectFirstItem:E})},exports.MenuOption=class{key;ref;icon;title;constructor(e){this.key=e,this.ref={current:null},this.setRefElement=this.setRefElement.bind(this)}setRefElement(e){this.ref={current:e}}},exports.PUNCTUATION=h,exports.SCROLL_TYPEAHEAD_OPTION_INTO_VIEW_COMMAND=C,exports.getScrollParent=function(e,t){let n=getComputedStyle(e);const o="absolute"===n.position,r=t?/(auto|scroll|hidden)/:/(auto|scroll)/;if("fixed"===n.position)return document.body;for(let t=e;t=t.parentElement;)if(n=getComputedStyle(t),(!o||"static"!==n.position)&&r.test(n.overflow+n.overflowY+n.overflowX))return t;return document.body},exports.useBasicTypeaheadTriggerMatch=function(e,{minLength:t=1,maxLength:o=75,punctuation:r=h,allowWhitespace:l=!1}){return n.useCallback(n=>{const i=new RegExp("(^|\\s|\\()(["+e+"]((?:"+("[^"+e+r+(l?"":"\\s")+"]")+"){0,"+o+"}))$").exec(n);if(null!==i){const e=i[1],n=i[3];if(n.length>=t)return{leadOffset:i.index+e.length,matchingString:n,replaceableString:i[2]}}return null},[l,e,r,o,t])},exports.useDynamicPositioning=d;
|
|
@@ -6,4 +6,4 @@
|
|
|
6
6
|
*
|
|
7
7
|
*/
|
|
8
8
|
|
|
9
|
-
import{useLexicalComposerContext as t}from"@lexical/react/LexicalComposerContext";import{createCommand as e,COMMAND_PRIORITY_LOW as n,KEY_ARROW_DOWN_COMMAND as o,KEY_ARROW_UP_COMMAND as r,KEY_ESCAPE_COMMAND as l,KEY_TAB_COMMAND as i,KEY_ENTER_COMMAND as u,$getSelection as s,$isRangeSelection as c,$isTextNode as a,getDOMSelection as d}from"lexical";import m,{useLayoutEffect as
|
|
9
|
+
import{useLexicalComposerContext as t}from"@lexical/react/LexicalComposerContext";import{createCommand as e,COMMAND_PRIORITY_LOW as n,KEY_ARROW_DOWN_COMMAND as o,KEY_ARROW_UP_COMMAND as r,KEY_ESCAPE_COMMAND as l,KEY_TAB_COMMAND as i,KEY_ENTER_COMMAND as u,$getSelection as s,$isRangeSelection as c,$isTextNode as a,getDOMSelection as d}from"lexical";import m,{useLayoutEffect as p,useEffect as f,useRef as g,useCallback as h,useState as y}from"react";import{mergeRegister as w}from"@lexical/utils";import v from"react-dom";import{jsx as C,jsxs as E}from"react/jsx-runtime";const b="startTransition";const x="undefined"!=typeof window&&void 0!==window.document&&void 0!==window.document.createElement,S=x?p:f;class R{key;ref;icon;title;constructor(t){this.key=t,this.ref={current:null},this.setRefElement=this.setRefElement.bind(this)}setRefElement(t){this.ref={current:t}}}const O=t=>{const e=document.getElementById("typeahead-menu");if(!e)return;const n=e.getBoundingClientRect();n.top+n.height>window.innerHeight&&e.scrollIntoView({block:"center"}),n.top<0&&e.scrollIntoView({block:"center"}),t.scrollIntoView({block:"nearest"})};function I(t,e){const n=t.getBoundingClientRect(),o=e.getBoundingClientRect();return n.top>=o.top-6&&n.top<=o.bottom+6}function N(e,n,o,r){const[l]=t();f(()=>{if(null!=n&&null!=e){const t=l.getRootElement(),e=null!=t?function(t){let e=getComputedStyle(t);const n="absolute"===e.position,o=/(auto|scroll)/;if("fixed"===e.position)return document.body;for(let r=t;r=r.parentElement;)if(e=getComputedStyle(r),(!n||"static"!==e.position)&&o.test(e.overflow+e.overflowY+e.overflowX))return r;return document.body}(t):document.body;let i=!1,u=I(n,e);const s=function(){i||(window.requestAnimationFrame(function(){o(),i=!1}),i=!0);const t=I(n,e);t!==u&&(u=t,null!=r&&r(t))},c=new ResizeObserver(o);return window.addEventListener("resize",o),document.addEventListener("scroll",s,{capture:!0,passive:!0}),c.observe(n),()=>{c.unobserve(n),window.removeEventListener("resize",o),document.removeEventListener("scroll",s,!0)}}},[n,l,r,o,e])}const P=e("SCROLL_TYPEAHEAD_OPTION_INTO_VIEW_COMMAND");function A({index:t,isSelected:e,onClick:n,onMouseEnter:o,option:r}){let l="item";return e&&(l+=" selected"),E("li",{tabIndex:-1,className:l,ref:r.setRefElement,role:"option","aria-selected":e,id:"typeahead-item-"+t,onMouseEnter:o,onClick:n,children:[r.icon,C("span",{className:"text",children:r.title})]},r.key)}function T({close:t,editor:e,anchorElementRef:a,resolution:d,options:m,onSelectOption:p,shouldSplitNodeWithQuery:g=!1,commandPriority:E=n,preselectFirstItem:b=!0}){const[x,R]=y(null),I=null!==x?Math.min(m.length-1,x):null,N=d.match&&d.match.matchingString;f(()=>{b&&R(0)},[N,b]);const T=h(n=>{e.update(()=>{const e=null!=d.match&&g?function(t){const e=s();if(!c(e)||!e.isCollapsed())return null;const n=e.anchor;if("text"!==n.type)return null;const o=n.getNode();if(!o.isSimpleText())return null;const r=n.offset,l=o.getTextContent().slice(0,r),i=t.replaceableString.length,u=r-function(t,e,n){let o=n;for(let n=o;n<=e.length;n++)t.slice(-n)===e.substring(0,n)&&(o=n);return o}(l,t.matchingString,i);if(u<0)return null;let a;return 0===u?[a]=o.splitText(r):[,a]=o.splitText(u,r),a}(d.match):null;p(n,e,t,d.match?d.match.matchingString:"")})},[e,g,d.match,p,t]),L=h(t=>{const n=e.getRootElement();null!==n&&(n.setAttribute("aria-activedescendant","typeahead-item-"+t),R(t))},[e]),_=h(()=>a.current&&m.length?v.createPortal(C("div",{className:"typeahead-popover mentions-menu",children:C("ul",{children:m.map((t,e)=>C(A,{index:e,isSelected:I===e,onClick:()=>{R(e),T(t)},onMouseEnter:()=>{R(e)},option:t},t.key))})}),a.current):null,[a,m,I,T,R]);return f(()=>()=>{const t=e.getRootElement();null!==t&&t.removeAttribute("aria-activedescendant")},[e]),S(()=>{null===m?R(null):null===I&&b&&L(0)},[m,I,L,b]),f(()=>w(e.registerCommand(P,({option:t})=>!(!t.ref||null==t.ref.current)&&(O(t.ref.current),!0),E)),[e,L,E]),f(()=>w(e.registerCommand(o,t=>{const n=t;if(null!==m&&m.length){const t=null===I?0:I!==m.length-1?I+1:0;L(t);const o=m[t];if(!o)return L(-1),n.preventDefault(),n.stopImmediatePropagation(),!0;o.ref&&o.ref.current&&e.dispatchCommand(P,{index:t,option:o}),n.preventDefault(),n.stopImmediatePropagation()}return!0},E),e.registerCommand(r,t=>{const e=t;if(null!==m&&m.length){const t=null===I?m.length-1:0!==I?I-1:m.length-1;L(t);const n=m[t];if(!n)return L(-1),e.preventDefault(),e.stopImmediatePropagation(),!0;n.ref&&n.ref.current&&O(n.ref.current),e.preventDefault(),e.stopImmediatePropagation()}return!0},E),e.registerCommand(l,e=>{const n=e;return n.preventDefault(),n.stopImmediatePropagation(),t(),!0},E),e.registerCommand(i,t=>{const e=t;return null!==m&&null!==I&&null!=m[I]&&(e.preventDefault(),e.stopImmediatePropagation(),T(m[I]),!0)},E),e.registerCommand(u,t=>null!==m&&null!==I&&null!=m[I]&&(null!==t&&(t.preventDefault(),t.stopImmediatePropagation()),T(m[I]),!0),E)),[T,t,e,m,I,L,E]),_()}function L(t,e){null!=e&&(t.className=e),t.setAttribute("aria-label","Typeahead menu"),t.setAttribute("role","listbox"),t.style.display="block",t.style.position="absolute"}const _="\\.,\\+\\*\\?\\$\\@\\|#{}\\(\\)\\^\\-\\[\\]\\\\/!%'\"~=<>_:;";function k(t,e){let n=getComputedStyle(t);const o="absolute"===n.position,r=e?/(auto|scroll|hidden)/:/(auto|scroll)/;if("fixed"===n.position)return document.body;for(let e=t;e=e.parentElement;)if(n=getComputedStyle(e),(!o||"static"!==n.position)&&r.test(n.overflow+n.overflowY+n.overflowX))return e;return document.body}const D=e("SCROLL_TYPEAHEAD_OPTION_INTO_VIEW_COMMAND");function $(t,{minLength:e=1,maxLength:n=75,punctuation:o=_,allowWhitespace:r=!1}){return h(l=>{const i=new RegExp("(^|\\s|\\()(["+t+"]((?:"+("[^"+t+o+(r?"":"\\s")+"]")+"){0,"+n+"}))$").exec(l);if(null!==i){const t=i[1],n=i[3];if(n.length>=e)return{leadOffset:i.index+t.length,matchingString:n,replaceableString:i[2]}}return null},[r,t,o,n,e])}function B({options:e,onQueryChange:o,onSelectOption:r,onOpen:l,onClose:i,triggerFn:u,anchorClassName:p,commandPriority:w=n,parent:v,preselectFirstItem:E=!0,ignoreEntityBoundary:S=!1}){const[R]=t(),[O,I]=y(null),P=function(e,n,o,r=(x?document.body:void 0),l=!0){const[i]=t(),u=x?document.createElement("div"):null,s=g(u),c=h(()=>{if(null===s.current||void 0===r)return;s.current.style.top=s.current.style.bottom;const t=i.getRootElement(),n=s.current,u=n.firstChild;if(null!==t&&null!==e){const{left:i,top:c,width:a,height:d}=e.getRect(),m=s.current.offsetHeight;if(n.style.top=`${c+m+3+(l?window.pageYOffset:0)}px`,n.style.left=`${i+window.pageXOffset}px`,n.style.height=`${d}px`,n.style.width=`${a}px`,null!==u){u.style.top=`${c}`;const e=u.getBoundingClientRect(),o=e.height,r=e.width,s=t.getBoundingClientRect();i+r>s.right&&(n.style.left=`${s.right-r+window.pageXOffset}px`),(c+o>window.innerHeight||c+o>s.bottom)&&c-s.top>o+d&&(n.style.top=`${c-o-d+(l?window.pageYOffset:0)}px`)}n.isConnected||(L(n,o),r.append(n)),n.setAttribute("id","typeahead-menu"),t.setAttribute("aria-controls","typeahead-menu")}},[i,e,l,o,r]);f(()=>{const t=i.getRootElement();return null!==e&&c(),()=>{null!==t&&t.removeAttribute("aria-controls");const e=s.current;null!==e&&e.isConnected&&(e.remove(),e.removeAttribute("id"))}},[i,c,e]);const a=h(t=>{null!==e&&(t||n(null))},[e,n]);return N(e,s.current,c,a),null!=u&&u===s.current&&(L(u,o),null!=r&&r.append(u)),s}(O,I,p,v),A=h(()=>{I(null),null!=i&&null!==O&&i()},[i,O]),_=h(t=>{I(t),null!=l&&null===O&&l(t)},[l,O]);return f(()=>{const t=R.registerUpdateListener(()=>{R.getEditorState().read(()=>{if(!R.isEditable())return void A();if(R.isComposing())return;const t=R._window||window,e=t.document.createRange(),n=s(),r=function(t){let e=null;return t.getEditorState().read(()=>{const t=s();c(t)&&(e=function(t){const e=t.anchor;if("text"!==e.type)return null;const n=e.getNode();if(!n.isSimpleText())return null;const o=e.offset;return n.getTextContent().slice(0,o)}(t))}),e}(R);if(!c(n)||!n.isCollapsed()||null===r||null===e)return void A();const l=u(r,R);if(o(l?l.matchingString:null),null!==l&&(S||!function(t,e){return 0===e&&t.getEditorState().read(()=>{const t=s();if(c(t)){const e=t.anchor.getNode().getPreviousSibling();return a(e)&&e.isTextEntity()}return!1})}(R,l.leadOffset))){const n=function(t,e,n){const o=d(n);if(null===o||!o.isCollapsed)return!1;const r=o.anchorNode,l=t,i=o.anchorOffset;if(null==r||null==i)return!1;try{e.setStart(r,l),e.setEnd(r,i)}catch(t){return!1}return!0}(l.leadOffset,e,t);if(null!==n)return i=()=>_({getRect:()=>e.getBoundingClientRect(),match:l}),void(b in m?m[b](i):i())}var i;A()})});return()=>{t()}},[R,u,o,O,A,_,S]),f(()=>R.registerEditableListener(t=>{t||A()}),[R,A]),null===O||null===R||null===P.current?null:C(T,{close:A,resolution:O,editor:R,anchorElementRef:P,options:e,shouldSplitNodeWithQuery:!0,onSelectOption:r,commandPriority:w,preselectFirstItem:E})}export{B as LexicalTypeaheadMenuPlugin,R as MenuOption,_ as PUNCTUATION,D as SCROLL_TYPEAHEAD_OPTION_INTO_VIEW_COMMAND,k as getScrollParent,$ as useBasicTypeaheadTriggerMatch,N as useDynamicPositioning};
|
package/package.json
CHANGED
|
@@ -8,26 +8,26 @@
|
|
|
8
8
|
"rich-text"
|
|
9
9
|
],
|
|
10
10
|
"license": "MIT",
|
|
11
|
-
"version": "0.38.3-nightly.
|
|
11
|
+
"version": "0.38.3-nightly.20251117.0",
|
|
12
12
|
"dependencies": {
|
|
13
13
|
"@floating-ui/react": "^0.27.16",
|
|
14
|
-
"@lexical/devtools-core": "0.38.3-nightly.
|
|
15
|
-
"@lexical/dragon": "0.38.3-nightly.
|
|
16
|
-
"@lexical/extension": "0.38.3-nightly.
|
|
17
|
-
"@lexical/hashtag": "0.38.3-nightly.
|
|
18
|
-
"@lexical/history": "0.38.3-nightly.
|
|
19
|
-
"@lexical/link": "0.38.3-nightly.
|
|
20
|
-
"@lexical/list": "0.38.3-nightly.
|
|
21
|
-
"@lexical/mark": "0.38.3-nightly.
|
|
22
|
-
"@lexical/markdown": "0.38.3-nightly.
|
|
23
|
-
"@lexical/overflow": "0.38.3-nightly.
|
|
24
|
-
"@lexical/plain-text": "0.38.3-nightly.
|
|
25
|
-
"@lexical/rich-text": "0.38.3-nightly.
|
|
26
|
-
"@lexical/table": "0.38.3-nightly.
|
|
27
|
-
"@lexical/text": "0.38.3-nightly.
|
|
28
|
-
"@lexical/utils": "0.38.3-nightly.
|
|
29
|
-
"@lexical/yjs": "0.38.3-nightly.
|
|
30
|
-
"lexical": "0.38.3-nightly.
|
|
14
|
+
"@lexical/devtools-core": "0.38.3-nightly.20251117.0",
|
|
15
|
+
"@lexical/dragon": "0.38.3-nightly.20251117.0",
|
|
16
|
+
"@lexical/extension": "0.38.3-nightly.20251117.0",
|
|
17
|
+
"@lexical/hashtag": "0.38.3-nightly.20251117.0",
|
|
18
|
+
"@lexical/history": "0.38.3-nightly.20251117.0",
|
|
19
|
+
"@lexical/link": "0.38.3-nightly.20251117.0",
|
|
20
|
+
"@lexical/list": "0.38.3-nightly.20251117.0",
|
|
21
|
+
"@lexical/mark": "0.38.3-nightly.20251117.0",
|
|
22
|
+
"@lexical/markdown": "0.38.3-nightly.20251117.0",
|
|
23
|
+
"@lexical/overflow": "0.38.3-nightly.20251117.0",
|
|
24
|
+
"@lexical/plain-text": "0.38.3-nightly.20251117.0",
|
|
25
|
+
"@lexical/rich-text": "0.38.3-nightly.20251117.0",
|
|
26
|
+
"@lexical/table": "0.38.3-nightly.20251117.0",
|
|
27
|
+
"@lexical/text": "0.38.3-nightly.20251117.0",
|
|
28
|
+
"@lexical/utils": "0.38.3-nightly.20251117.0",
|
|
29
|
+
"@lexical/yjs": "0.38.3-nightly.20251117.0",
|
|
30
|
+
"lexical": "0.38.3-nightly.20251117.0",
|
|
31
31
|
"react-error-boundary": "^6.0.0"
|
|
32
32
|
},
|
|
33
33
|
"peerDependencies": {
|
|
@@ -460,36 +460,6 @@
|
|
|
460
460
|
"default": "./LexicalContentEditable.js"
|
|
461
461
|
}
|
|
462
462
|
},
|
|
463
|
-
"./LexicalContextMenuPlugin": {
|
|
464
|
-
"import": {
|
|
465
|
-
"types": "./LexicalContextMenuPlugin.d.ts",
|
|
466
|
-
"development": "./LexicalContextMenuPlugin.dev.mjs",
|
|
467
|
-
"production": "./LexicalContextMenuPlugin.prod.mjs",
|
|
468
|
-
"node": "./LexicalContextMenuPlugin.node.mjs",
|
|
469
|
-
"default": "./LexicalContextMenuPlugin.mjs"
|
|
470
|
-
},
|
|
471
|
-
"require": {
|
|
472
|
-
"types": "./LexicalContextMenuPlugin.d.ts",
|
|
473
|
-
"development": "./LexicalContextMenuPlugin.dev.js",
|
|
474
|
-
"production": "./LexicalContextMenuPlugin.prod.js",
|
|
475
|
-
"default": "./LexicalContextMenuPlugin.js"
|
|
476
|
-
}
|
|
477
|
-
},
|
|
478
|
-
"./LexicalContextMenuPlugin.js": {
|
|
479
|
-
"import": {
|
|
480
|
-
"types": "./LexicalContextMenuPlugin.d.ts",
|
|
481
|
-
"development": "./LexicalContextMenuPlugin.dev.mjs",
|
|
482
|
-
"production": "./LexicalContextMenuPlugin.prod.mjs",
|
|
483
|
-
"node": "./LexicalContextMenuPlugin.node.mjs",
|
|
484
|
-
"default": "./LexicalContextMenuPlugin.mjs"
|
|
485
|
-
},
|
|
486
|
-
"require": {
|
|
487
|
-
"types": "./LexicalContextMenuPlugin.d.ts",
|
|
488
|
-
"development": "./LexicalContextMenuPlugin.dev.js",
|
|
489
|
-
"production": "./LexicalContextMenuPlugin.prod.js",
|
|
490
|
-
"default": "./LexicalContextMenuPlugin.js"
|
|
491
|
-
}
|
|
492
|
-
},
|
|
493
463
|
"./LexicalDecoratorBlockNode": {
|
|
494
464
|
"import": {
|
|
495
465
|
"types": "./LexicalDecoratorBlockNode.d.ts",
|
package/shared/LexicalMenu.d.ts
CHANGED
|
@@ -7,7 +7,7 @@
|
|
|
7
7
|
*/
|
|
8
8
|
import type { JSX } from 'react';
|
|
9
9
|
import { CommandListenerPriority, LexicalCommand, LexicalEditor, TextNode } from 'lexical';
|
|
10
|
-
import {
|
|
10
|
+
import { RefObject } from 'react';
|
|
11
11
|
export type MenuTextMatch = {
|
|
12
12
|
leadOffset: number;
|
|
13
13
|
matchingString: string;
|
|
@@ -17,33 +17,27 @@ export type MenuResolution = {
|
|
|
17
17
|
match?: MenuTextMatch;
|
|
18
18
|
getRect: () => DOMRect;
|
|
19
19
|
};
|
|
20
|
-
export declare const PUNCTUATION = "\\.,\\+\\*\\?\\$\\@\\|#{}\\(\\)\\^\\-\\[\\]\\\\/!%'\"~=<>_:;";
|
|
21
20
|
export declare class MenuOption {
|
|
22
21
|
key: string;
|
|
23
22
|
ref?: RefObject<HTMLElement | null>;
|
|
23
|
+
icon?: JSX.Element;
|
|
24
|
+
title?: JSX.Element | string | null;
|
|
24
25
|
constructor(key: string);
|
|
25
26
|
setRefElement(element: HTMLElement | null): void;
|
|
26
27
|
}
|
|
27
|
-
export type MenuRenderFn<TOption extends MenuOption> = (anchorElementRef: RefObject<HTMLElement | null>, itemProps: {
|
|
28
|
-
selectedIndex: number | null;
|
|
29
|
-
selectOptionAndCleanUp: (option: TOption) => void;
|
|
30
|
-
setHighlightedIndex: (index: number) => void;
|
|
31
|
-
options: Array<TOption>;
|
|
32
|
-
}, matchingString: string | null) => ReactPortal | JSX.Element | null;
|
|
33
28
|
export declare function getScrollParent(element: HTMLElement, includeHidden: boolean): HTMLElement | HTMLBodyElement;
|
|
34
29
|
export declare function useDynamicPositioning(resolution: MenuResolution | null, targetElement: HTMLElement | null, onReposition: () => void, onVisibilityChange?: (isInView: boolean) => void): void;
|
|
35
30
|
export declare const SCROLL_TYPEAHEAD_OPTION_INTO_VIEW_COMMAND: LexicalCommand<{
|
|
36
31
|
index: number;
|
|
37
32
|
option: MenuOption;
|
|
38
33
|
}>;
|
|
39
|
-
export declare function LexicalMenu<TOption extends MenuOption>({ close, editor, anchorElementRef, resolution, options,
|
|
34
|
+
export declare function LexicalMenu<TOption extends MenuOption>({ close, editor, anchorElementRef, resolution, options, onSelectOption, shouldSplitNodeWithQuery, commandPriority, preselectFirstItem, }: {
|
|
40
35
|
close: () => void;
|
|
41
36
|
editor: LexicalEditor;
|
|
42
37
|
anchorElementRef: RefObject<HTMLElement | null>;
|
|
43
38
|
resolution: MenuResolution;
|
|
44
39
|
options: Array<TOption>;
|
|
45
40
|
shouldSplitNodeWithQuery?: boolean;
|
|
46
|
-
menuRenderFn: MenuRenderFn<TOption>;
|
|
47
41
|
onSelectOption: (option: TOption, textNodeContainingQuery: TextNode | null, closeMenu: () => void, matchingString: string) => void;
|
|
48
42
|
commandPriority?: CommandListenerPriority;
|
|
49
43
|
preselectFirstItem?: boolean;
|
|
@@ -1,36 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Copyright (c) Meta Platforms, Inc. and affiliates.
|
|
3
|
-
*
|
|
4
|
-
* This source code is licensed under the MIT license found in the
|
|
5
|
-
* LICENSE file in the root directory of this source tree.
|
|
6
|
-
*
|
|
7
|
-
*/
|
|
8
|
-
import type { MenuRenderFn, MenuResolution } from './shared/LexicalMenu';
|
|
9
|
-
import type { JSX } from 'react';
|
|
10
|
-
import { CommandListenerPriority, LexicalNode } from 'lexical';
|
|
11
|
-
import { ReactPortal, RefObject } from 'react';
|
|
12
|
-
import { MenuOption } from './shared/LexicalMenu';
|
|
13
|
-
export type ContextMenuRenderFn<TOption extends MenuOption> = (anchorElementRef: RefObject<HTMLElement | null>, itemProps: {
|
|
14
|
-
selectedIndex: number | null;
|
|
15
|
-
selectOptionAndCleanUp: (option: TOption) => void;
|
|
16
|
-
setHighlightedIndex: (index: number) => void;
|
|
17
|
-
options: Array<TOption>;
|
|
18
|
-
}, menuProps: {
|
|
19
|
-
setMenuRef: (element: HTMLElement | null) => void;
|
|
20
|
-
}) => ReactPortal | JSX.Element | null;
|
|
21
|
-
export type LexicalContextMenuPluginProps<TOption extends MenuOption> = {
|
|
22
|
-
onSelectOption: (option: TOption, textNodeContainingQuery: LexicalNode | null, closeMenu: () => void, matchingString: string) => void;
|
|
23
|
-
options: Array<TOption>;
|
|
24
|
-
onClose?: () => void;
|
|
25
|
-
onWillOpen?: (event: MouseEvent) => void;
|
|
26
|
-
onOpen?: (resolution: MenuResolution) => void;
|
|
27
|
-
menuRenderFn: ContextMenuRenderFn<TOption>;
|
|
28
|
-
anchorClassName?: string;
|
|
29
|
-
commandPriority?: CommandListenerPriority;
|
|
30
|
-
parent?: HTMLElement;
|
|
31
|
-
};
|
|
32
|
-
/**
|
|
33
|
-
* @deprecated Use LexicalNodeContextMenuPlugin instead.
|
|
34
|
-
*/
|
|
35
|
-
export declare function LexicalContextMenuPlugin<TOption extends MenuOption>({ options, onWillOpen, onClose, onOpen, onSelectOption, menuRenderFn: contextMenuRenderFn, anchorClassName, commandPriority, parent, }: LexicalContextMenuPluginProps<TOption>): JSX.Element | null;
|
|
36
|
-
export { MenuOption, MenuRenderFn, MenuResolution };
|