@lexical/react 0.38.3-nightly.20251113.0 → 0.38.3-nightly.20251114.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.
@@ -7,7 +7,7 @@
7
7
  */
8
8
  import type { CommandListenerPriority, LexicalNode } from 'lexical';
9
9
  import type { JSX } from 'react';
10
- import { MenuOption, MenuRenderFn } from '@lexical/react/LexicalNodeMenuPlugin';
10
+ import { MenuOption } from '@lexical/react/LexicalNodeMenuPlugin';
11
11
  import { LexicalCommand, LexicalEditor } from 'lexical';
12
12
  export type EmbedMatchResult<TEmbedMatchResult = unknown> = {
13
13
  url: string;
@@ -32,8 +32,7 @@ type LexicalAutoEmbedPluginProps<TEmbedConfig extends EmbedConfig> = {
32
32
  embedConfigs: Array<TEmbedConfig>;
33
33
  onOpenEmbedModalForConfig: (embedConfig: TEmbedConfig) => void;
34
34
  getMenuOptions: (activeEmbedConfig: TEmbedConfig, embedFn: () => void, dismissFn: () => void) => Array<AutoEmbedOption>;
35
- menuRenderFn: MenuRenderFn<AutoEmbedOption>;
36
35
  menuCommandPriority?: CommandListenerPriority;
37
36
  };
38
- export declare function LexicalAutoEmbedPlugin<TEmbedConfig extends EmbedConfig>({ embedConfigs, onOpenEmbedModalForConfig, getMenuOptions, menuRenderFn, menuCommandPriority, }: LexicalAutoEmbedPluginProps<TEmbedConfig>): JSX.Element | null;
37
+ export declare function LexicalAutoEmbedPlugin<TEmbedConfig extends EmbedConfig>({ embedConfigs, onOpenEmbedModalForConfig, getMenuOptions, menuCommandPriority, }: LexicalAutoEmbedPluginProps<TEmbedConfig>): JSX.Element | null;
39
38
  export {};
@@ -39,7 +39,6 @@ function LexicalAutoEmbedPlugin({
39
39
  embedConfigs,
40
40
  onOpenEmbedModalForConfig,
41
41
  getMenuOptions,
42
- menuRenderFn,
43
42
  menuCommandPriority = lexical.COMMAND_PRIORITY_LOW
44
43
  }) {
45
44
  const [editor] = LexicalComposerContext.useLexicalComposerContext();
@@ -135,7 +134,6 @@ function LexicalAutoEmbedPlugin({
135
134
  onClose: reset,
136
135
  onSelectOption: onSelectOption,
137
136
  options: options,
138
- menuRenderFn: menuRenderFn,
139
137
  commandPriority: menuCommandPriority
140
138
  }) : null;
141
139
  }
@@ -37,7 +37,6 @@ function LexicalAutoEmbedPlugin({
37
37
  embedConfigs,
38
38
  onOpenEmbedModalForConfig,
39
39
  getMenuOptions,
40
- menuRenderFn,
41
40
  menuCommandPriority = COMMAND_PRIORITY_LOW
42
41
  }) {
43
42
  const [editor] = useLexicalComposerContext();
@@ -133,7 +132,6 @@ function LexicalAutoEmbedPlugin({
133
132
  onClose: reset,
134
133
  onSelectOption: onSelectOption,
135
134
  options: options,
136
- menuRenderFn: menuRenderFn,
137
135
  commandPriority: menuCommandPriority
138
136
  }) : null;
139
137
  }
@@ -13,7 +13,6 @@ import {MenuOption} from '@lexical/react/LexicalTypeaheadMenuPlugin';
13
13
  import type {LexicalCommand, LexicalEditor, NodeKey, TextNode} from 'lexical';
14
14
  import * as React from 'react';
15
15
  import {createCommand} from 'lexical';
16
- import type {MenuRenderFn} from './LexicalTypeaheadMenuPlugin';
17
16
 
18
17
  export type EmbedMatchResult = {
19
18
  url: string,
@@ -43,7 +42,6 @@ type LexicalAutoEmbedPluginProps<TEmbedConfig> = {
43
42
  embedFn: () => void,
44
43
  dismissFn: () => void,
45
44
  ) => Array<AutoEmbedOption>,
46
- menuRenderFn: MenuRenderFn<AutoEmbedOption>,
47
45
  };
48
46
 
49
47
  declare export class AutoEmbedOption extends MenuOption {
@@ -6,4 +6,4 @@
6
6
  *
7
7
  */
8
8
 
9
- "use strict";var e=require("@lexical/link"),t=require("@lexical/react/LexicalComposerContext"),n=require("@lexical/react/LexicalNodeMenuPlugin"),o=require("@lexical/utils"),i=require("lexical"),l=require("react"),r=require("react/jsx-runtime");const s=i.createCommand("INSERT_EMBED_COMMAND");class u extends n.MenuOption{title;onSelect;constructor(e,t){super(e),this.title=e,this.onSelect=t.onSelect.bind(this)}}exports.AutoEmbedOption=u,exports.INSERT_EMBED_COMMAND=s,exports.LexicalAutoEmbedPlugin=function({embedConfigs:u,onOpenEmbedModalForConfig:a,getMenuOptions:c,menuRenderFn:d,menuCommandPriority:m=i.COMMAND_PRIORITY_LOW}){const[p]=t.useLexicalComposerContext(),[x,C]=l.useState(null),[f,M]=l.useState(null),g=l.useCallback(()=>{C(null),M(null)},[]),E=l.useCallback(async t=>{const n=p.getEditorState().read(function(){const n=i.$getNodeByKey(t);if(e.$isLinkNode(n))return n.getURL()});if(void 0!==n)for(const e of u){null!=await Promise.resolve(e.parseUrl(n))&&(M(e),C(t))}},[p,u]);l.useEffect(()=>o.mergeRegister(...[e.LinkNode,e.AutoLinkNode].map(e=>p.registerMutationListener(e,(...e)=>((e,{updateTags:t,dirtyLeaves:n})=>{for(const[o,l]of e)"created"===l&&t.has(i.PASTE_TAG)&&n.size<=3?E(o):o===x&&g()})(...e),{skipInitialization:!0}))),[E,p,u,x,g]),l.useEffect(()=>p.registerCommand(s,e=>{const t=u.find(({type:t})=>t===e);return!!t&&(a(t),!0)},i.COMMAND_PRIORITY_EDITOR),[p,u,a]);const N=l.useCallback(async function(){if(null!=f&&null!=x){const t=p.getEditorState().read(()=>{const t=i.$getNodeByKey(x);return e.$isLinkNode(t)?t:null});if(e.$isLinkNode(t)){const e=await Promise.resolve(f.parseUrl(t.__url));null!=e&&p.update(()=>{i.$getSelection()||t.selectEnd(),f.insertNode(p,e),t.isAttached()&&t.remove()})}}},[f,p,x]),L=l.useMemo(()=>null!=f&&null!=x?c(f,N,g):[],[f,N,c,x,g]),A=l.useCallback((e,t,n)=>{p.update(()=>{e.onSelect(t),n()})},[p]);return null!=x?r.jsx(n.LexicalNodeMenuPlugin,{nodeKey:x,onClose:g,onSelectOption:A,options:L,menuRenderFn:d,commandPriority:m}):null},exports.URL_MATCHER=/((https?:\/\/(www\.)?)|(www\.))[-a-zA-Z0-9@:%._+~#=]{1,256}\.[a-zA-Z0-9()]{1,6}\b([-a-zA-Z0-9()@:%_+.~#?&//=]*)/;
9
+ "use strict";var e=require("@lexical/link"),t=require("@lexical/react/LexicalComposerContext"),n=require("@lexical/react/LexicalNodeMenuPlugin"),o=require("@lexical/utils"),i=require("lexical"),l=require("react"),r=require("react/jsx-runtime");const s=i.createCommand("INSERT_EMBED_COMMAND");class a extends n.MenuOption{title;onSelect;constructor(e,t){super(e),this.title=e,this.onSelect=t.onSelect.bind(this)}}exports.AutoEmbedOption=a,exports.INSERT_EMBED_COMMAND=s,exports.LexicalAutoEmbedPlugin=function({embedConfigs:a,onOpenEmbedModalForConfig:u,getMenuOptions:c,menuCommandPriority:d=i.COMMAND_PRIORITY_LOW}){const[m]=t.useLexicalComposerContext(),[p,x]=l.useState(null),[C,f]=l.useState(null),M=l.useCallback(()=>{x(null),f(null)},[]),g=l.useCallback(async t=>{const n=m.getEditorState().read(function(){const n=i.$getNodeByKey(t);if(e.$isLinkNode(n))return n.getURL()});if(void 0!==n)for(const e of a){null!=await Promise.resolve(e.parseUrl(n))&&(f(e),x(t))}},[m,a]);l.useEffect(()=>o.mergeRegister(...[e.LinkNode,e.AutoLinkNode].map(e=>m.registerMutationListener(e,(...e)=>((e,{updateTags:t,dirtyLeaves:n})=>{for(const[o,l]of e)"created"===l&&t.has(i.PASTE_TAG)&&n.size<=3?g(o):o===p&&M()})(...e),{skipInitialization:!0}))),[g,m,a,p,M]),l.useEffect(()=>m.registerCommand(s,e=>{const t=a.find(({type:t})=>t===e);return!!t&&(u(t),!0)},i.COMMAND_PRIORITY_EDITOR),[m,a,u]);const E=l.useCallback(async function(){if(null!=C&&null!=p){const t=m.getEditorState().read(()=>{const t=i.$getNodeByKey(p);return e.$isLinkNode(t)?t:null});if(e.$isLinkNode(t)){const e=await Promise.resolve(C.parseUrl(t.__url));null!=e&&m.update(()=>{i.$getSelection()||t.selectEnd(),C.insertNode(m,e),t.isAttached()&&t.remove()})}}},[C,m,p]),N=l.useMemo(()=>null!=C&&null!=p?c(C,E,M):[],[C,E,c,p,M]),L=l.useCallback((e,t,n)=>{m.update(()=>{e.onSelect(t),n()})},[m]);return null!=p?r.jsx(n.LexicalNodeMenuPlugin,{nodeKey:p,onClose:M,onSelectOption:L,options:N,commandPriority:d}):null},exports.URL_MATCHER=/((https?:\/\/(www\.)?)|(www\.))[-a-zA-Z0-9@:%._+~#=]{1,256}\.[a-zA-Z0-9()]{1,6}\b([-a-zA-Z0-9()@:%_+.~#?&//=]*)/;
@@ -6,4 +6,4 @@
6
6
  *
7
7
  */
8
8
 
9
- import{$isLinkNode as e,LinkNode as t,AutoLinkNode as n}from"@lexical/link";import{useLexicalComposerContext as o}from"@lexical/react/LexicalComposerContext";import{MenuOption as r,LexicalNodeMenuPlugin as i}from"@lexical/react/LexicalNodeMenuPlugin";import{mergeRegister as l}from"@lexical/utils";import{createCommand as s,$getNodeByKey as a,COMMAND_PRIORITY_EDITOR as c,$getSelection as u,COMMAND_PRIORITY_LOW as m,PASTE_TAG as d}from"lexical";import{useState as p,useCallback as f,useEffect as x,useMemo as g}from"react";import{jsx as w}from"react/jsx-runtime";const C=/((https?:\/\/(www\.)?)|(www\.))[-a-zA-Z0-9@:%._+~#=]{1,256}\.[a-zA-Z0-9()]{1,6}\b([-a-zA-Z0-9()@:%_+.~#?&//=]*)/,S=s("INSERT_EMBED_COMMAND");class y extends r{title;onSelect;constructor(e,t){super(e),this.title=e,this.onSelect=t.onSelect.bind(this)}}function E({embedConfigs:r,onOpenEmbedModalForConfig:s,getMenuOptions:C,menuRenderFn:y,menuCommandPriority:E=m}){const[M]=o(),[h,_]=p(null),[v,z]=p(null),A=f(()=>{_(null),z(null)},[]),L=f(async t=>{const n=M.getEditorState().read(function(){const n=a(t);if(e(n))return n.getURL()});if(void 0!==n)for(const e of r){null!=await Promise.resolve(e.parseUrl(n))&&(z(e),_(t))}},[M,r]);x(()=>l(...[t,n].map(e=>M.registerMutationListener(e,(...e)=>((e,{updateTags:t,dirtyLeaves:n})=>{for(const[o,r]of e)"created"===r&&t.has(d)&&n.size<=3?L(o):o===h&&A()})(...e),{skipInitialization:!0}))),[L,M,r,h,A]),x(()=>M.registerCommand(S,e=>{const t=r.find(({type:t})=>t===e);return!!t&&(s(t),!0)},c),[M,r,s]);const P=f(async function(){if(null!=v&&null!=h){const t=M.getEditorState().read(()=>{const t=a(h);return e(t)?t:null});if(e(t)){const e=await Promise.resolve(v.parseUrl(t.__url));null!=e&&M.update(()=>{u()||t.selectEnd(),v.insertNode(M,e),t.isAttached()&&t.remove()})}}},[v,M,h]),b=g(()=>null!=v&&null!=h?C(v,P,A):[],[v,P,C,h,A]),N=f((e,t,n)=>{M.update(()=>{e.onSelect(t),n()})},[M]);return null!=h?w(i,{nodeKey:h,onClose:A,onSelectOption:N,options:b,menuRenderFn:y,commandPriority:E}):null}export{y as AutoEmbedOption,S as INSERT_EMBED_COMMAND,E as LexicalAutoEmbedPlugin,C as URL_MATCHER};
9
+ import{$isLinkNode as t,LinkNode as e,AutoLinkNode as o}from"@lexical/link";import{useLexicalComposerContext as n}from"@lexical/react/LexicalComposerContext";import{MenuOption as i,LexicalNodeMenuPlugin as r}from"@lexical/react/LexicalNodeMenuPlugin";import{mergeRegister as l}from"@lexical/utils";import{createCommand as s,$getNodeByKey as a,COMMAND_PRIORITY_EDITOR as c,$getSelection as u,COMMAND_PRIORITY_LOW as m,PASTE_TAG as d}from"lexical";import{useState as p,useCallback as f,useEffect as x,useMemo as g}from"react";import{jsx as w}from"react/jsx-runtime";const C=/((https?:\/\/(www\.)?)|(www\.))[-a-zA-Z0-9@:%._+~#=]{1,256}\.[a-zA-Z0-9()]{1,6}\b([-a-zA-Z0-9()@:%_+.~#?&//=]*)/,S=s("INSERT_EMBED_COMMAND");class y extends i{title;onSelect;constructor(t,e){super(t),this.title=t,this.onSelect=e.onSelect.bind(this)}}function E({embedConfigs:i,onOpenEmbedModalForConfig:s,getMenuOptions:C,menuCommandPriority:y=m}){const[E]=n(),[M,h]=p(null),[_,v]=p(null),z=f(()=>{h(null),v(null)},[]),A=f(async e=>{const o=E.getEditorState().read(function(){const o=a(e);if(t(o))return o.getURL()});if(void 0!==o)for(const t of i){null!=await Promise.resolve(t.parseUrl(o))&&(v(t),h(e))}},[E,i]);x(()=>l(...[e,o].map(t=>E.registerMutationListener(t,(...t)=>((t,{updateTags:e,dirtyLeaves:o})=>{for(const[n,i]of t)"created"===i&&e.has(d)&&o.size<=3?A(n):n===M&&z()})(...t),{skipInitialization:!0}))),[A,E,i,M,z]),x(()=>E.registerCommand(S,t=>{const e=i.find(({type:e})=>e===t);return!!e&&(s(e),!0)},c),[E,i,s]);const L=f(async function(){if(null!=_&&null!=M){const e=E.getEditorState().read(()=>{const e=a(M);return t(e)?e:null});if(t(e)){const t=await Promise.resolve(_.parseUrl(e.__url));null!=t&&E.update(()=>{u()||e.selectEnd(),_.insertNode(E,t),e.isAttached()&&e.remove()})}}},[_,E,M]),P=g(()=>null!=_&&null!=M?C(_,L,z):[],[_,L,C,M,z]),b=f((t,e,o)=>{E.update(()=>{t.onSelect(e),o()})},[E]);return null!=M?w(r,{nodeKey:M,onClose:z,onSelectOption:b,options:P,commandPriority:y}):null}export{y as AutoEmbedOption,S as INSERT_EMBED_COMMAND,E as LexicalAutoEmbedPlugin,C as URL_MATCHER};
@@ -5,7 +5,7 @@
5
5
  * LICENSE file in the root directory of this source tree.
6
6
  *
7
7
  */
8
- import type { MenuRenderFn, MenuResolution } from './shared/LexicalMenu';
8
+ import type { MenuResolution } from './shared/LexicalMenu';
9
9
  import type { JSX } from 'react';
10
10
  import { CommandListenerPriority, NodeKey, TextNode } from 'lexical';
11
11
  import { MenuOption } from './shared/LexicalMenu';
@@ -15,10 +15,9 @@ export type NodeMenuPluginProps<TOption extends MenuOption> = {
15
15
  nodeKey: NodeKey | null;
16
16
  onClose?: () => void;
17
17
  onOpen?: (resolution: MenuResolution) => void;
18
- menuRenderFn: MenuRenderFn<TOption>;
19
18
  anchorClassName?: string;
20
19
  commandPriority?: CommandListenerPriority;
21
20
  parent?: HTMLElement;
22
21
  };
23
- export declare function LexicalNodeMenuPlugin<TOption extends MenuOption>({ options, nodeKey, onClose, onOpen, onSelectOption, menuRenderFn, anchorClassName, commandPriority, parent, }: NodeMenuPluginProps<TOption>): JSX.Element | null;
24
- export { MenuOption, MenuRenderFn, MenuResolution };
22
+ export declare function LexicalNodeMenuPlugin<TOption extends MenuOption>({ options, nodeKey, onClose, onOpen, onSelectOption, anchorClassName, commandPriority, parent, }: NodeMenuPluginProps<TOption>): JSX.Element | null;
23
+ export { MenuOption, MenuResolution };
@@ -12,6 +12,7 @@ var LexicalComposerContext = require('@lexical/react/LexicalComposerContext');
12
12
  var lexical = require('lexical');
13
13
  var React = require('react');
14
14
  var utils = require('@lexical/utils');
15
+ var ReactDOM = require('react-dom');
15
16
  var jsxRuntime = require('react/jsx-runtime');
16
17
 
17
18
  /**
@@ -70,6 +71,8 @@ const useLayoutEffectImpl = CAN_USE_DOM ? React.useLayoutEffect : React.useEffec
70
71
  class MenuOption {
71
72
  key;
72
73
  ref;
74
+ icon;
75
+ title;
73
76
  constructor(key) {
74
77
  this.key = key;
75
78
  this.ref = {
@@ -219,13 +222,38 @@ function useDynamicPositioning(resolution, targetElement, onReposition, onVisibi
219
222
  }, [targetElement, editor, onVisibilityChange, onReposition, resolution]);
220
223
  }
221
224
  const SCROLL_TYPEAHEAD_OPTION_INTO_VIEW_COMMAND = lexical.createCommand('SCROLL_TYPEAHEAD_OPTION_INTO_VIEW_COMMAND');
225
+ function MenuItem({
226
+ index,
227
+ isSelected,
228
+ onClick,
229
+ onMouseEnter,
230
+ option
231
+ }) {
232
+ let className = 'item';
233
+ if (isSelected) {
234
+ className += ' selected';
235
+ }
236
+ return /*#__PURE__*/jsxRuntime.jsxs("li", {
237
+ tabIndex: -1,
238
+ className: className,
239
+ ref: option.setRefElement,
240
+ role: "option",
241
+ "aria-selected": isSelected,
242
+ id: 'typeahead-item-' + index,
243
+ onMouseEnter: onMouseEnter,
244
+ onClick: onClick,
245
+ children: [option.icon, /*#__PURE__*/jsxRuntime.jsx("span", {
246
+ className: "text",
247
+ children: option.title
248
+ })]
249
+ }, option.key);
250
+ }
222
251
  function LexicalMenu({
223
252
  close,
224
253
  editor,
225
254
  anchorElementRef,
226
255
  resolution,
227
256
  options,
228
- menuRenderFn,
229
257
  onSelectOption,
230
258
  shouldSplitNodeWithQuery = false,
231
259
  commandPriority = lexical.COMMAND_PRIORITY_LOW,
@@ -253,6 +281,25 @@ function LexicalMenu({
253
281
  setHighlightedIndex(index);
254
282
  }
255
283
  }, [editor]);
284
+ const menuRenderFn = React.useCallback(() => {
285
+ return anchorElementRef.current && options.length ? /*#__PURE__*/ReactDOM.createPortal(/*#__PURE__*/jsxRuntime.jsx("div", {
286
+ className: "typeahead-popover mentions-menu",
287
+ children: /*#__PURE__*/jsxRuntime.jsx("ul", {
288
+ children: options.map((option, i) => /*#__PURE__*/jsxRuntime.jsx(MenuItem, {
289
+ index: i,
290
+ isSelected: selectedIndex === i,
291
+ onClick: () => {
292
+ setHighlightedIndex(i);
293
+ selectOptionAndCleanUp(option);
294
+ },
295
+ onMouseEnter: () => {
296
+ setHighlightedIndex(i);
297
+ },
298
+ option: option
299
+ }, option.key))
300
+ })
301
+ }), anchorElementRef.current) : null;
302
+ }, [anchorElementRef, options, selectedIndex, selectOptionAndCleanUp, setHighlightedIndex]);
256
303
  React.useEffect(() => {
257
304
  return () => {
258
305
  const rootElem = editor.getRootElement();
@@ -348,13 +395,7 @@ function LexicalMenu({
348
395
  return true;
349
396
  }, commandPriority));
350
397
  }, [selectOptionAndCleanUp, close, editor, options, selectedIndex, updateSelectedIndex, commandPriority]);
351
- const listItemProps = React.useMemo(() => ({
352
- options,
353
- selectOptionAndCleanUp,
354
- selectedIndex,
355
- setHighlightedIndex
356
- }), [selectOptionAndCleanUp, selectedIndex, options]);
357
- return menuRenderFn(anchorElementRef, listItemProps, resolution.match ? resolution.match.matchingString : '');
398
+ return menuRenderFn();
358
399
  }
359
400
  function setContainerDivAttributes(containerDiv, className) {
360
401
  if (className != null) {
@@ -460,7 +501,6 @@ function LexicalNodeMenuPlugin({
460
501
  onClose,
461
502
  onOpen,
462
503
  onSelectOption,
463
- menuRenderFn,
464
504
  anchorClassName,
465
505
  commandPriority = lexical.COMMAND_PRIORITY_LOW,
466
506
  parent
@@ -517,7 +557,6 @@ function LexicalNodeMenuPlugin({
517
557
  editor: editor,
518
558
  anchorElementRef: anchorElementRef,
519
559
  options: options,
520
- menuRenderFn: menuRenderFn,
521
560
  onSelectOption: onSelectOption,
522
561
  commandPriority: commandPriority
523
562
  });
@@ -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, $getNodeByKey } from 'lexical';
11
- import React, { useLayoutEffect, useEffect, useRef, useCallback, useState, useMemo } from 'react';
11
+ import React, { useLayoutEffect, useEffect, useRef, useCallback, useState } from 'react';
12
12
  import { mergeRegister } from '@lexical/utils';
13
- import { jsx } from 'react/jsx-runtime';
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 = 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
- const listItemProps = useMemo(() => ({
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) {
@@ -458,7 +499,6 @@ function LexicalNodeMenuPlugin({
458
499
  onClose,
459
500
  onOpen,
460
501
  onSelectOption,
461
- menuRenderFn,
462
502
  anchorClassName,
463
503
  commandPriority = COMMAND_PRIORITY_LOW,
464
504
  parent
@@ -515,7 +555,6 @@ function LexicalNodeMenuPlugin({
515
555
  editor: editor,
516
556
  anchorElementRef: anchorElementRef,
517
557
  options: options,
518
- menuRenderFn: menuRenderFn,
519
558
  onSelectOption: onSelectOption,
520
559
  commandPriority: commandPriority
521
560
  });
@@ -28,17 +28,6 @@ declare export class MenuOption {
28
28
  setRefElement(element: HTMLElement | null): void;
29
29
  }
30
30
 
31
- export type MenuRenderFn<TOption> = (
32
- anchorElementRef: {current: HTMLElement | null},
33
- itemProps: {
34
- selectedIndex: number | null,
35
- selectOptionAndCleanUp: (option: TOption) => void,
36
- setHighlightedIndex: (index: number) => void,
37
- options: Array<TOption>,
38
- },
39
- matchingString: string,
40
- ) => React.Portal | React.MixedElement | null;
41
-
42
31
  export type TriggerFn = (
43
32
  text: string,
44
33
  editor: LexicalEditor,
@@ -55,7 +44,6 @@ type NodeMenuPluginProps<TOption> = {
55
44
  nodeKey: NodeKey | null,
56
45
  onClose?: () => void,
57
46
  onOpen?: (resolution: MenuResolution) => void,
58
- menuRenderFn: MenuRenderFn<TOption>,
59
47
  anchorClassName?: string,
60
48
  };
61
49
 
@@ -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"),l=require("react/jsx-runtime");const r="startTransition";const i="undefined"!=typeof window&&void 0!==window.document&&void 0!==window.document.createElement,u=i?n.useLayoutEffect:n.useEffect;const s=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 c(e,t){const n=e.getBoundingClientRect(),o=t.getBoundingClientRect();return n.top>=o.top-6&&n.top<=o.bottom+6}function a(t,o,l,r){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 l=e;l=l.parentElement;)if(t=getComputedStyle(l),(!n||"static"!==t.position)&&o.test(t.overflow+t.overflowY+t.overflowX))return l;return document.body}(e):document.body;let n=!1,u=c(o,t);const s=function(){n||(window.requestAnimationFrame(function(){l(),n=!1}),n=!0);const e=c(o,t);e!==u&&(u=e,null!=r&&r(e))},a=new ResizeObserver(l);return window.addEventListener("resize",l),document.addEventListener("scroll",s,{capture:!0,passive:!0}),a.observe(o),()=>{a.unobserve(o),window.removeEventListener("resize",l),document.removeEventListener("scroll",s,!0)}}},[o,i,r,l,t])}const d=t.createCommand("SCROLL_TYPEAHEAD_OPTION_INTO_VIEW_COMMAND");function m({close:e,editor:l,anchorElementRef:r,resolution:i,options:c,menuRenderFn:a,onSelectOption:m,shouldSplitNodeWithQuery:f=!1,commandPriority:p=t.COMMAND_PRIORITY_LOW,preselectFirstItem:g=!0}){const[h,C]=n.useState(null),E=null!==h?Math.min(c.length-1,h):null,y=i.match&&i.match.matchingString;n.useEffect(()=>{g&&C(0)},[y,g]);const b=n.useCallback(n=>{l.update(()=>{const o=null!=i.match&&f?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 l=o.getNode();if(!l.isSimpleText())return null;const r=o.offset,i=l.getTextContent().slice(0,r),u=e.replaceableString.length,s=r-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,u);if(s<0)return null;let c;return 0===s?[c]=l.splitText(r):[,c]=l.splitText(s,r),c}(i.match):null;m(n,o,e,i.match?i.match.matchingString:"")})},[l,f,i.match,m,e]),R=n.useCallback(e=>{const t=l.getRootElement();null!==t&&(t.setAttribute("aria-activedescendant","typeahead-item-"+e),C(e))},[l]);n.useEffect(()=>()=>{const e=l.getRootElement();null!==e&&e.removeAttribute("aria-activedescendant")},[l]),u(()=>{null===c?C(null):null===E&&g&&R(0)},[c,E,R,g]),n.useEffect(()=>o.mergeRegister(l.registerCommand(d,({option:e})=>!(!e.ref||null==e.ref.current)&&(s(e.ref.current),!0),p)),[l,R,p]),n.useEffect(()=>o.mergeRegister(l.registerCommand(t.KEY_ARROW_DOWN_COMMAND,e=>{const t=e;if(null!==c&&c.length){const e=null===E?0:E!==c.length-1?E+1:0;R(e);const n=c[e];if(!n)return R(-1),t.preventDefault(),t.stopImmediatePropagation(),!0;n.ref&&n.ref.current&&l.dispatchCommand(d,{index:e,option:n}),t.preventDefault(),t.stopImmediatePropagation()}return!0},p),l.registerCommand(t.KEY_ARROW_UP_COMMAND,e=>{const t=e;if(null!==c&&c.length){const e=null===E?c.length-1:0!==E?E-1:c.length-1;R(e);const n=c[e];if(!n)return R(-1),t.preventDefault(),t.stopImmediatePropagation(),!0;n.ref&&n.ref.current&&s(n.ref.current),t.preventDefault(),t.stopImmediatePropagation()}return!0},p),l.registerCommand(t.KEY_ESCAPE_COMMAND,t=>{const n=t;return n.preventDefault(),n.stopImmediatePropagation(),e(),!0},p),l.registerCommand(t.KEY_TAB_COMMAND,e=>{const t=e;return null!==c&&null!==E&&null!=c[E]&&(t.preventDefault(),t.stopImmediatePropagation(),b(c[E]),!0)},p),l.registerCommand(t.KEY_ENTER_COMMAND,e=>null!==c&&null!==E&&null!=c[E]&&(null!==e&&(e.preventDefault(),e.stopImmediatePropagation()),b(c[E]),!0),p)),[b,e,l,c,E,R,p]);return a(r,n.useMemo(()=>({options:c,selectOptionAndCleanUp:b,selectedIndex:E,setHighlightedIndex:C}),[b,E,c]),i.match?i.match.matchingString:"")}function f(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"}exports.LexicalNodeMenuPlugin=function({options:o,nodeKey:u,onClose:s,onOpen:c,onSelectOption:d,menuRenderFn:p,anchorClassName:g,commandPriority:h=t.COMMAND_PRIORITY_LOW,parent:C}){const[E]=e.useLexicalComposerContext(),[y,b]=n.useState(null),R=function(t,o,l,r=(i?document.body:void 0),u=!0){const[s]=e.useLexicalComposerContext(),c=i?document.createElement("div"):null,d=n.useRef(c),m=n.useCallback(()=>{if(null===d.current||void 0===r)return;d.current.style.top=d.current.style.bottom;const e=s.getRootElement(),n=d.current,o=n.firstChild;if(null!==e&&null!==t){const{left:i,top:s,width:c,height:a}=t.getRect(),m=d.current.offsetHeight;if(n.style.top=`${s+m+3+(u?window.pageYOffset:0)}px`,n.style.left=`${i+window.pageXOffset}px`,n.style.height=`${a}px`,n.style.width=`${c}px`,null!==o){o.style.top=`${s}`;const t=o.getBoundingClientRect(),l=t.height,r=t.width,c=e.getBoundingClientRect();i+r>c.right&&(n.style.left=`${c.right-r+window.pageXOffset}px`),(s+l>window.innerHeight||s+l>c.bottom)&&s-c.top>l+a&&(n.style.top=`${s-l-a+(u?window.pageYOffset:0)}px`)}n.isConnected||(f(n,l),r.append(n)),n.setAttribute("id","typeahead-menu"),e.setAttribute("aria-controls","typeahead-menu")}},[s,t,u,l,r]);n.useEffect(()=>{const e=s.getRootElement();return null!==t&&m(),()=>{null!==e&&e.removeAttribute("aria-controls");const t=d.current;null!==t&&t.isConnected&&(t.remove(),t.removeAttribute("id"))}},[s,m,t]);const p=n.useCallback(e=>{null!==t&&(e||o(null))},[t,o]);return a(t,d.current,m,p),null!=c&&c===d.current&&(f(c,l),null!=r&&r.append(c)),d}(y,b,g,C),w=n.useCallback(()=>{b(null),null!=s&&null!==y&&s()},[s,y]),v=n.useCallback(e=>{b(e),null!=c&&null===y&&c(e)},[c,y]),x=n.useCallback(()=>{u?E.update(()=>{const e=t.$getNodeByKey(u),o=E.getElementByKey(u);var l;null!=e&&null!=o&&null==y&&(l=()=>v({getRect:()=>o.getBoundingClientRect()}),r in n?n[r](l):l())}):null==u&&null!=y&&w()},[w,E,u,v,y]);return n.useEffect(()=>{x()},[x,u]),n.useEffect(()=>{if(null!=u)return E.registerUpdateListener(({dirtyElements:e})=>{e.get(u)&&x()})},[E,x,u]),null===R.current||null===y||null===E?null:l.jsx(m,{close:w,resolution:y,editor:E,anchorElementRef:R,options:o,menuRenderFn:p,onSelectOption:d,commandPriority:h})},exports.MenuOption=class{key;ref;constructor(e){this.key=e,this.ref={current:null},this.setRefElement=this.setRefElement.bind(this)}setRefElement(e){this.ref={current:e}}};
9
+ "use strict";var e=require("@lexical/react/LexicalComposerContext"),t=require("lexical"),n=require("react"),l=require("@lexical/utils"),o=require("react-dom"),r=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(),l=t.getBoundingClientRect();return n.top>=l.top-6&&n.top<=l.bottom+6}function d(t,l,o,r){const[i]=e.useLexicalComposerContext();n.useEffect(()=>{if(null!=l&&null!=t){const e=i.getRootElement(),t=null!=e?function(e){let t=getComputedStyle(e);const n="absolute"===t.position,l=/(auto|scroll)/;if("fixed"===t.position)return document.body;for(let o=e;o=o.parentElement;)if(t=getComputedStyle(o),(!n||"static"!==t.position)&&l.test(t.overflow+t.overflowY+t.overflowX))return o;return document.body}(e):document.body;let n=!1,s=a(l,t);const u=function(){n||(window.requestAnimationFrame(function(){o(),n=!1}),n=!0);const e=a(l,t);e!==s&&(s=e,null!=r&&r(e))},c=new ResizeObserver(o);return window.addEventListener("resize",o),document.addEventListener("scroll",u,{capture:!0,passive:!0}),c.observe(l),()=>{c.unobserve(l),window.removeEventListener("resize",o),document.removeEventListener("scroll",u,!0)}}},[l,i,r,o,t])}const m=t.createCommand("SCROLL_TYPEAHEAD_OPTION_INTO_VIEW_COMMAND");function p({index:e,isSelected:t,onClick:n,onMouseEnter:l,option:o}){let i="item";return t&&(i+=" selected"),r.jsxs("li",{tabIndex:-1,className:i,ref:o.setRefElement,role:"option","aria-selected":t,id:"typeahead-item-"+e,onMouseEnter:l,onClick:n,children:[o.icon,r.jsx("span",{className:"text",children:o.title})]},o.key)}function f({close:e,editor:i,anchorElementRef:s,resolution:a,options:d,onSelectOption:f,shouldSplitNodeWithQuery:g=!1,commandPriority:h=t.COMMAND_PRIORITY_LOW,preselectFirstItem:C=!0}){const[E,y]=n.useState(null),x=null!==E?Math.min(d.length-1,E):null,b=a.match&&a.match.matchingString;n.useEffect(()=>{C&&y(0)},[b,C]);const v=n.useCallback(n=>{i.update(()=>{const l=null!=a.match&&g?function(e){const n=t.$getSelection();if(!t.$isRangeSelection(n)||!n.isCollapsed())return null;const l=n.anchor;if("text"!==l.type)return null;const o=l.getNode();if(!o.isSimpleText())return null;const r=l.offset,i=o.getTextContent().slice(0,r),s=e.replaceableString.length,u=r-function(e,t,n){let l=n;for(let n=l;n<=t.length;n++)e.slice(-n)===t.substring(0,n)&&(l=n);return l}(i,e.matchingString,s);if(u<0)return null;let c;return 0===u?[c]=o.splitText(r):[,c]=o.splitText(u,r),c}(a.match):null;f(n,l,e,a.match?a.match.matchingString:"")})},[i,g,a.match,f,e]),w=n.useCallback(e=>{const t=i.getRootElement();null!==t&&(t.setAttribute("aria-activedescendant","typeahead-item-"+e),y(e))},[i]),R=n.useCallback(()=>s.current&&d.length?o.createPortal(r.jsx("div",{className:"typeahead-popover mentions-menu",children:r.jsx("ul",{children:d.map((e,t)=>r.jsx(p,{index:t,isSelected:x===t,onClick:()=>{y(t),v(e)},onMouseEnter:()=>{y(t)},option:e},e.key))})}),s.current):null,[s,d,x,v,y]);return n.useEffect(()=>()=>{const e=i.getRootElement();null!==e&&e.removeAttribute("aria-activedescendant")},[i]),u(()=>{null===d?y(null):null===x&&C&&w(0)},[d,x,w,C]),n.useEffect(()=>l.mergeRegister(i.registerCommand(m,({option:e})=>!(!e.ref||null==e.ref.current)&&(c(e.ref.current),!0),h)),[i,w,h]),n.useEffect(()=>l.mergeRegister(i.registerCommand(t.KEY_ARROW_DOWN_COMMAND,e=>{const t=e;if(null!==d&&d.length){const e=null===x?0:x!==d.length-1?x+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(m,{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===x?d.length-1:0!==x?x-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!==x&&null!=d[x]&&(t.preventDefault(),t.stopImmediatePropagation(),v(d[x]),!0)},h),i.registerCommand(t.KEY_ENTER_COMMAND,e=>null!==d&&null!==x&&null!=d[x]&&(null!==e&&(e.preventDefault(),e.stopImmediatePropagation()),v(d[x]),!0),h)),[v,e,i,d,x,w,h]),R()}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"}exports.LexicalNodeMenuPlugin=function({options:l,nodeKey:o,onClose:u,onOpen:c,onSelectOption:a,anchorClassName:m,commandPriority:p=t.COMMAND_PRIORITY_LOW,parent:h}){const[C]=e.useLexicalComposerContext(),[E,y]=n.useState(null),x=function(t,l,o,r=(s?document.body:void 0),i=!0){const[u]=e.useLexicalComposerContext(),c=s?document.createElement("div"):null,a=n.useRef(c),m=n.useCallback(()=>{if(null===a.current||void 0===r)return;a.current.style.top=a.current.style.bottom;const e=u.getRootElement(),n=a.current,l=n.firstChild;if(null!==e&&null!==t){const{left:s,top:u,width:c,height:d}=t.getRect(),m=a.current.offsetHeight;if(n.style.top=`${u+m+3+(i?window.pageYOffset:0)}px`,n.style.left=`${s+window.pageXOffset}px`,n.style.height=`${d}px`,n.style.width=`${c}px`,null!==l){l.style.top=`${u}`;const t=l.getBoundingClientRect(),o=t.height,r=t.width,c=e.getBoundingClientRect();s+r>c.right&&(n.style.left=`${c.right-r+window.pageXOffset}px`),(u+o>window.innerHeight||u+o>c.bottom)&&u-c.top>o+d&&(n.style.top=`${u-o-d+(i?window.pageYOffset:0)}px`)}n.isConnected||(g(n,o),r.append(n)),n.setAttribute("id","typeahead-menu"),e.setAttribute("aria-controls","typeahead-menu")}},[u,t,i,o,r]);n.useEffect(()=>{const e=u.getRootElement();return null!==t&&m(),()=>{null!==e&&e.removeAttribute("aria-controls");const t=a.current;null!==t&&t.isConnected&&(t.remove(),t.removeAttribute("id"))}},[u,m,t]);const p=n.useCallback(e=>{null!==t&&(e||l(null))},[t,l]);return d(t,a.current,m,p),null!=c&&c===a.current&&(g(c,o),null!=r&&r.append(c)),a}(E,y,m,h),b=n.useCallback(()=>{y(null),null!=u&&null!==E&&u()},[u,E]),v=n.useCallback(e=>{y(e),null!=c&&null===E&&c(e)},[c,E]),w=n.useCallback(()=>{o?C.update(()=>{const e=t.$getNodeByKey(o),l=C.getElementByKey(o);var r;null!=e&&null!=l&&null==E&&(r=()=>v({getRect:()=>l.getBoundingClientRect()}),i in n?n[i](r):r())}):null==o&&null!=E&&b()},[b,C,o,v,E]);return n.useEffect(()=>{w()},[w,o]),n.useEffect(()=>{if(null!=o)return C.registerUpdateListener(({dirtyElements:e})=>{e.get(o)&&w()})},[C,w,o]),null===x.current||null===E||null===C?null:r.jsx(f,{close:b,resolution:E,editor:C,anchorElementRef:x,options:l,onSelectOption:a,commandPriority:p})},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}}};
@@ -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 l,KEY_ESCAPE_COMMAND as r,KEY_TAB_COMMAND as i,KEY_ENTER_COMMAND as u,$getSelection as s,$isRangeSelection as c,$getNodeByKey as a}from"lexical";import m,{useLayoutEffect as d,useEffect as p,useRef as f,useCallback as g,useState as h,useMemo as y}from"react";import{mergeRegister as w}from"@lexical/utils";import{jsx as v}from"react/jsx-runtime";const b="startTransition";const C="undefined"!=typeof window&&void 0!==window.document&&void 0!==window.document.createElement,x=C?d:p;class E{key;ref;constructor(t){this.key=t,this.ref={current:null},this.setRefElement=this.setRefElement.bind(this)}setRefElement(t){this.ref={current:t}}}const R=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 O(e,n,o,l){const[r]=t();p(()=>{if(null!=n&&null!=e){const t=r.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 l=t;l=l.parentElement;)if(e=getComputedStyle(l),(!n||"static"!==e.position)&&o.test(e.overflow+e.overflowY+e.overflowX))return l;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!=l&&l(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,r,l,o,e])}const A=e("SCROLL_TYPEAHEAD_OPTION_INTO_VIEW_COMMAND");function S({close:t,editor:e,anchorElementRef:a,resolution:m,options:d,menuRenderFn:f,onSelectOption:v,shouldSplitNodeWithQuery:b=!1,commandPriority:C=n,preselectFirstItem:E=!0}){const[I,O]=h(null),S=null!==I?Math.min(d.length-1,I):null,P=m.match&&m.match.matchingString;p(()=>{E&&O(0)},[P,E]);const D=g(n=>{e.update(()=>{const e=null!=m.match&&b?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 l=n.offset,r=o.getTextContent().slice(0,l),i=t.replaceableString.length,u=l-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}(r,t.matchingString,i);if(u<0)return null;let a;return 0===u?[a]=o.splitText(l):[,a]=o.splitText(u,l),a}(m.match):null;v(n,e,t,m.match?m.match.matchingString:"")})},[e,b,m.match,v,t]),T=g(t=>{const n=e.getRootElement();null!==n&&(n.setAttribute("aria-activedescendant","typeahead-item-"+t),O(t))},[e]);p(()=>()=>{const t=e.getRootElement();null!==t&&t.removeAttribute("aria-activedescendant")},[e]),x(()=>{null===d?O(null):null===S&&E&&T(0)},[d,S,T,E]),p(()=>w(e.registerCommand(A,({option:t})=>!(!t.ref||null==t.ref.current)&&(R(t.ref.current),!0),C)),[e,T,C]),p(()=>w(e.registerCommand(o,t=>{const n=t;if(null!==d&&d.length){const t=null===S?0:S!==d.length-1?S+1:0;T(t);const o=d[t];if(!o)return T(-1),n.preventDefault(),n.stopImmediatePropagation(),!0;o.ref&&o.ref.current&&e.dispatchCommand(A,{index:t,option:o}),n.preventDefault(),n.stopImmediatePropagation()}return!0},C),e.registerCommand(l,t=>{const e=t;if(null!==d&&d.length){const t=null===S?d.length-1:0!==S?S-1:d.length-1;T(t);const n=d[t];if(!n)return T(-1),e.preventDefault(),e.stopImmediatePropagation(),!0;n.ref&&n.ref.current&&R(n.ref.current),e.preventDefault(),e.stopImmediatePropagation()}return!0},C),e.registerCommand(r,e=>{const n=e;return n.preventDefault(),n.stopImmediatePropagation(),t(),!0},C),e.registerCommand(i,t=>{const e=t;return null!==d&&null!==S&&null!=d[S]&&(e.preventDefault(),e.stopImmediatePropagation(),D(d[S]),!0)},C),e.registerCommand(u,t=>null!==d&&null!==S&&null!=d[S]&&(null!==t&&(t.preventDefault(),t.stopImmediatePropagation()),D(d[S]),!0),C)),[D,t,e,d,S,T,C]);return f(a,y(()=>({options:d,selectOptionAndCleanUp:D,selectedIndex:S,setHighlightedIndex:O}),[D,S,d]),m.match?m.match.matchingString:"")}function P(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"}function D({options:e,nodeKey:o,onClose:l,onOpen:r,onSelectOption:i,menuRenderFn:u,anchorClassName:s,commandPriority:c=n,parent:d}){const[y]=t(),[w,x]=h(null),E=function(e,n,o,l=(C?document.body:void 0),r=!0){const[i]=t(),u=C?document.createElement("div"):null,s=f(u),c=g(()=>{if(null===s.current||void 0===l)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:m}=e.getRect(),d=s.current.offsetHeight;if(n.style.top=`${c+d+3+(r?window.pageYOffset:0)}px`,n.style.left=`${i+window.pageXOffset}px`,n.style.height=`${m}px`,n.style.width=`${a}px`,null!==u){u.style.top=`${c}`;const e=u.getBoundingClientRect(),o=e.height,l=e.width,s=t.getBoundingClientRect();i+l>s.right&&(n.style.left=`${s.right-l+window.pageXOffset}px`),(c+o>window.innerHeight||c+o>s.bottom)&&c-s.top>o+m&&(n.style.top=`${c-o-m+(r?window.pageYOffset:0)}px`)}n.isConnected||(P(n,o),l.append(n)),n.setAttribute("id","typeahead-menu"),t.setAttribute("aria-controls","typeahead-menu")}},[i,e,r,o,l]);p(()=>{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=g(t=>{null!==e&&(t||n(null))},[e,n]);return O(e,s.current,c,a),null!=u&&u===s.current&&(P(u,o),null!=l&&l.append(u)),s}(w,x,s,d),R=g(()=>{x(null),null!=l&&null!==w&&l()},[l,w]),I=g(t=>{x(t),null!=r&&null===w&&r(t)},[r,w]),A=g(()=>{o?y.update(()=>{const t=a(o),e=y.getElementByKey(o);var n;null!=t&&null!=e&&null==w&&(n=()=>I({getRect:()=>e.getBoundingClientRect()}),b in m?m[b](n):n())}):null==o&&null!=w&&R()},[R,y,o,I,w]);return p(()=>{A()},[A,o]),p(()=>{if(null!=o)return y.registerUpdateListener(({dirtyElements:t})=>{t.get(o)&&A()})},[y,A,o]),null===E.current||null===w||null===y?null:v(S,{close:R,resolution:w,editor:y,anchorElementRef:E,options:e,menuRenderFn:u,onSelectOption:i,commandPriority:c})}export{D as LexicalNodeMenuPlugin,E as MenuOption};
9
+ import{useLexicalComposerContext as e}from"@lexical/react/LexicalComposerContext";import{createCommand as t,COMMAND_PRIORITY_LOW as n,KEY_ARROW_DOWN_COMMAND as o,KEY_ARROW_UP_COMMAND as l,KEY_ESCAPE_COMMAND as r,KEY_TAB_COMMAND as i,KEY_ENTER_COMMAND as u,$getSelection as s,$isRangeSelection as c,$getNodeByKey as a}from"lexical";import m,{useLayoutEffect as d,useEffect as p,useRef as f,useCallback as g,useState as h}from"react";import{mergeRegister as y}from"@lexical/utils";import v from"react-dom";import{jsx as w,jsxs as b}from"react/jsx-runtime";const C="startTransition";const E="undefined"!=typeof window&&void 0!==window.document&&void 0!==window.document.createElement,x=E?d:p;class R{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}}}const I=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 O(e,t){const n=e.getBoundingClientRect(),o=t.getBoundingClientRect();return n.top>=o.top-6&&n.top<=o.bottom+6}function S(t,n,o,l){const[r]=e();p(()=>{if(null!=n&&null!=t){const e=r.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 l=e;l=l.parentElement;)if(t=getComputedStyle(l),(!n||"static"!==t.position)&&o.test(t.overflow+t.overflowY+t.overflowX))return l;return document.body}(e):document.body;let i=!1,u=O(n,t);const s=function(){i||(window.requestAnimationFrame(function(){o(),i=!1}),i=!0);const e=O(n,t);e!==u&&(u=e,null!=l&&l(e))},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,r,l,o,t])}const P=t("SCROLL_TYPEAHEAD_OPTION_INTO_VIEW_COMMAND");function A({index:e,isSelected:t,onClick:n,onMouseEnter:o,option:l}){let r="item";return t&&(r+=" selected"),b("li",{tabIndex:-1,className:r,ref:l.setRefElement,role:"option","aria-selected":t,id:"typeahead-item-"+e,onMouseEnter:o,onClick:n,children:[l.icon,w("span",{className:"text",children:l.title})]},l.key)}function k({close:e,editor:t,anchorElementRef:a,resolution:m,options:d,onSelectOption:f,shouldSplitNodeWithQuery:b=!1,commandPriority:C=n,preselectFirstItem:E=!0}){const[R,O]=h(null),S=null!==R?Math.min(d.length-1,R):null,k=m.match&&m.match.matchingString;p(()=>{E&&O(0)},[k,E]);const N=g(n=>{t.update(()=>{const t=null!=m.match&&b?function(e){const t=s();if(!c(t)||!t.isCollapsed())return null;const n=t.anchor;if("text"!==n.type)return null;const o=n.getNode();if(!o.isSimpleText())return null;const l=n.offset,r=o.getTextContent().slice(0,l),i=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}(r,e.matchingString,i);if(u<0)return null;let a;return 0===u?[a]=o.splitText(l):[,a]=o.splitText(u,l),a}(m.match):null;f(n,t,e,m.match?m.match.matchingString:"")})},[t,b,m.match,f,e]),D=g(e=>{const n=t.getRootElement();null!==n&&(n.setAttribute("aria-activedescendant","typeahead-item-"+e),O(e))},[t]),T=g(()=>a.current&&d.length?v.createPortal(w("div",{className:"typeahead-popover mentions-menu",children:w("ul",{children:d.map((e,t)=>w(A,{index:t,isSelected:S===t,onClick:()=>{O(t),N(e)},onMouseEnter:()=>{O(t)},option:e},e.key))})}),a.current):null,[a,d,S,N,O]);return p(()=>()=>{const e=t.getRootElement();null!==e&&e.removeAttribute("aria-activedescendant")},[t]),x(()=>{null===d?O(null):null===S&&E&&D(0)},[d,S,D,E]),p(()=>y(t.registerCommand(P,({option:e})=>!(!e.ref||null==e.ref.current)&&(I(e.ref.current),!0),C)),[t,D,C]),p(()=>y(t.registerCommand(o,e=>{const n=e;if(null!==d&&d.length){const e=null===S?0:S!==d.length-1?S+1:0;D(e);const o=d[e];if(!o)return D(-1),n.preventDefault(),n.stopImmediatePropagation(),!0;o.ref&&o.ref.current&&t.dispatchCommand(P,{index:e,option:o}),n.preventDefault(),n.stopImmediatePropagation()}return!0},C),t.registerCommand(l,e=>{const t=e;if(null!==d&&d.length){const e=null===S?d.length-1:0!==S?S-1:d.length-1;D(e);const n=d[e];if(!n)return D(-1),t.preventDefault(),t.stopImmediatePropagation(),!0;n.ref&&n.ref.current&&I(n.ref.current),t.preventDefault(),t.stopImmediatePropagation()}return!0},C),t.registerCommand(r,t=>{const n=t;return n.preventDefault(),n.stopImmediatePropagation(),e(),!0},C),t.registerCommand(i,e=>{const t=e;return null!==d&&null!==S&&null!=d[S]&&(t.preventDefault(),t.stopImmediatePropagation(),N(d[S]),!0)},C),t.registerCommand(u,e=>null!==d&&null!==S&&null!=d[S]&&(null!==e&&(e.preventDefault(),e.stopImmediatePropagation()),N(d[S]),!0),C)),[N,e,t,d,S,D,C]),T()}function N(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"}function D({options:t,nodeKey:o,onClose:l,onOpen:r,onSelectOption:i,anchorClassName:u,commandPriority:s=n,parent:c}){const[d]=e(),[y,v]=h(null),b=function(t,n,o,l=(E?document.body:void 0),r=!0){const[i]=e(),u=E?document.createElement("div"):null,s=f(u),c=g(()=>{if(null===s.current||void 0===l)return;s.current.style.top=s.current.style.bottom;const e=i.getRootElement(),n=s.current,u=n.firstChild;if(null!==e&&null!==t){const{left:i,top:c,width:a,height:m}=t.getRect(),d=s.current.offsetHeight;if(n.style.top=`${c+d+3+(r?window.pageYOffset:0)}px`,n.style.left=`${i+window.pageXOffset}px`,n.style.height=`${m}px`,n.style.width=`${a}px`,null!==u){u.style.top=`${c}`;const t=u.getBoundingClientRect(),o=t.height,l=t.width,s=e.getBoundingClientRect();i+l>s.right&&(n.style.left=`${s.right-l+window.pageXOffset}px`),(c+o>window.innerHeight||c+o>s.bottom)&&c-s.top>o+m&&(n.style.top=`${c-o-m+(r?window.pageYOffset:0)}px`)}n.isConnected||(N(n,o),l.append(n)),n.setAttribute("id","typeahead-menu"),e.setAttribute("aria-controls","typeahead-menu")}},[i,t,r,o,l]);p(()=>{const e=i.getRootElement();return null!==t&&c(),()=>{null!==e&&e.removeAttribute("aria-controls");const t=s.current;null!==t&&t.isConnected&&(t.remove(),t.removeAttribute("id"))}},[i,c,t]);const a=g(e=>{null!==t&&(e||n(null))},[t,n]);return S(t,s.current,c,a),null!=u&&u===s.current&&(N(u,o),null!=l&&l.append(u)),s}(y,v,u,c),x=g(()=>{v(null),null!=l&&null!==y&&l()},[l,y]),R=g(e=>{v(e),null!=r&&null===y&&r(e)},[r,y]),I=g(()=>{o?d.update(()=>{const e=a(o),t=d.getElementByKey(o);var n;null!=e&&null!=t&&null==y&&(n=()=>R({getRect:()=>t.getBoundingClientRect()}),C in m?m[C](n):n())}):null==o&&null!=y&&x()},[x,d,o,R,y]);return p(()=>{I()},[I,o]),p(()=>{if(null!=o)return d.registerUpdateListener(({dirtyElements:e})=>{e.get(o)&&I()})},[d,I,o]),null===b.current||null===y||null===d?null:w(k,{close:x,resolution:y,editor:d,anchorElementRef:b,options:t,onSelectOption:i,commandPriority:s})}export{D as LexicalNodeMenuPlugin,R as MenuOption};
@@ -5,7 +5,7 @@
5
5
  * LICENSE file in the root directory of this source tree.
6
6
  *
7
7
  */
8
- import type { MenuRenderFn, MenuResolution, MenuTextMatch, TriggerFn } from './shared/LexicalMenu';
8
+ import type { MenuResolution, MenuTextMatch, TriggerFn } from './shared/LexicalMenu';
9
9
  import type { JSX } from 'react';
10
10
  import { CommandListenerPriority, LexicalCommand, TextNode } from 'lexical';
11
11
  import { MenuOption } from './shared/LexicalMenu';
@@ -26,7 +26,6 @@ export type TypeaheadMenuPluginProps<TOption extends MenuOption> = {
26
26
  onQueryChange: (matchingString: string | null) => void;
27
27
  onSelectOption: (option: TOption, textNodeContainingQuery: TextNode | null, closeMenu: () => void, matchingString: string) => void;
28
28
  options: Array<TOption>;
29
- menuRenderFn: MenuRenderFn<TOption>;
30
29
  triggerFn: TriggerFn;
31
30
  onOpen?: (resolution: MenuResolution) => void;
32
31
  onClose?: () => void;
@@ -36,5 +35,5 @@ export type TypeaheadMenuPluginProps<TOption extends MenuOption> = {
36
35
  preselectFirstItem?: boolean;
37
36
  ignoreEntityBoundary?: boolean;
38
37
  };
39
- export declare function LexicalTypeaheadMenuPlugin<TOption extends MenuOption>({ options, onQueryChange, onSelectOption, onOpen, onClose, menuRenderFn, triggerFn, anchorClassName, commandPriority, parent, preselectFirstItem, ignoreEntityBoundary, }: TypeaheadMenuPluginProps<TOption>): JSX.Element | null;
40
- export { MenuOption, MenuRenderFn, MenuResolution, MenuTextMatch, TriggerFn };
38
+ export declare function LexicalTypeaheadMenuPlugin<TOption extends MenuOption>({ options, onQueryChange, onSelectOption, onOpen, onClose, triggerFn, anchorClassName, commandPriority, parent, preselectFirstItem, ignoreEntityBoundary, }: TypeaheadMenuPluginProps<TOption>): JSX.Element | null;
39
+ export { MenuOption, MenuResolution, MenuTextMatch, TriggerFn };
@@ -12,6 +12,7 @@ var LexicalComposerContext = require('@lexical/react/LexicalComposerContext');
12
12
  var lexical = require('lexical');
13
13
  var React = require('react');
14
14
  var utils = require('@lexical/utils');
15
+ var ReactDOM = require('react-dom');
15
16
  var jsxRuntime = require('react/jsx-runtime');
16
17
 
17
18
  /**
@@ -70,6 +71,8 @@ const useLayoutEffectImpl = CAN_USE_DOM ? React.useLayoutEffect : React.useEffec
70
71
  class MenuOption {
71
72
  key;
72
73
  ref;
74
+ icon;
75
+ title;
73
76
  constructor(key) {
74
77
  this.key = key;
75
78
  this.ref = {
@@ -219,13 +222,38 @@ function useDynamicPositioning(resolution, targetElement, onReposition, onVisibi
219
222
  }, [targetElement, editor, onVisibilityChange, onReposition, resolution]);
220
223
  }
221
224
  const SCROLL_TYPEAHEAD_OPTION_INTO_VIEW_COMMAND$1 = lexical.createCommand('SCROLL_TYPEAHEAD_OPTION_INTO_VIEW_COMMAND');
225
+ function MenuItem({
226
+ index,
227
+ isSelected,
228
+ onClick,
229
+ onMouseEnter,
230
+ option
231
+ }) {
232
+ let className = 'item';
233
+ if (isSelected) {
234
+ className += ' selected';
235
+ }
236
+ return /*#__PURE__*/jsxRuntime.jsxs("li", {
237
+ tabIndex: -1,
238
+ className: className,
239
+ ref: option.setRefElement,
240
+ role: "option",
241
+ "aria-selected": isSelected,
242
+ id: 'typeahead-item-' + index,
243
+ onMouseEnter: onMouseEnter,
244
+ onClick: onClick,
245
+ children: [option.icon, /*#__PURE__*/jsxRuntime.jsx("span", {
246
+ className: "text",
247
+ children: option.title
248
+ })]
249
+ }, option.key);
250
+ }
222
251
  function LexicalMenu({
223
252
  close,
224
253
  editor,
225
254
  anchorElementRef,
226
255
  resolution,
227
256
  options,
228
- menuRenderFn,
229
257
  onSelectOption,
230
258
  shouldSplitNodeWithQuery = false,
231
259
  commandPriority = lexical.COMMAND_PRIORITY_LOW,
@@ -253,6 +281,25 @@ function LexicalMenu({
253
281
  setHighlightedIndex(index);
254
282
  }
255
283
  }, [editor]);
284
+ const menuRenderFn = React.useCallback(() => {
285
+ return anchorElementRef.current && options.length ? /*#__PURE__*/ReactDOM.createPortal(/*#__PURE__*/jsxRuntime.jsx("div", {
286
+ className: "typeahead-popover mentions-menu",
287
+ children: /*#__PURE__*/jsxRuntime.jsx("ul", {
288
+ children: options.map((option, i) => /*#__PURE__*/jsxRuntime.jsx(MenuItem, {
289
+ index: i,
290
+ isSelected: selectedIndex === i,
291
+ onClick: () => {
292
+ setHighlightedIndex(i);
293
+ selectOptionAndCleanUp(option);
294
+ },
295
+ onMouseEnter: () => {
296
+ setHighlightedIndex(i);
297
+ },
298
+ option: option
299
+ }, option.key))
300
+ })
301
+ }), anchorElementRef.current) : null;
302
+ }, [anchorElementRef, options, selectedIndex, selectOptionAndCleanUp, setHighlightedIndex]);
256
303
  React.useEffect(() => {
257
304
  return () => {
258
305
  const rootElem = editor.getRootElement();
@@ -348,13 +395,7 @@ function LexicalMenu({
348
395
  return true;
349
396
  }, commandPriority));
350
397
  }, [selectOptionAndCleanUp, close, editor, options, selectedIndex, updateSelectedIndex, commandPriority]);
351
- const listItemProps = React.useMemo(() => ({
352
- options,
353
- selectOptionAndCleanUp,
354
- selectedIndex,
355
- setHighlightedIndex
356
- }), [selectOptionAndCleanUp, selectedIndex, options]);
357
- return menuRenderFn(anchorElementRef, listItemProps, resolution.match ? resolution.match.matchingString : '');
398
+ return menuRenderFn();
358
399
  }
359
400
  function setContainerDivAttributes(containerDiv, className) {
360
401
  if (className != null) {
@@ -564,7 +605,6 @@ function LexicalTypeaheadMenuPlugin({
564
605
  onSelectOption,
565
606
  onOpen,
566
607
  onClose,
567
- menuRenderFn,
568
608
  triggerFn,
569
609
  anchorClassName,
570
610
  commandPriority = lexical.COMMAND_PRIORITY_LOW,
@@ -595,6 +635,9 @@ function LexicalTypeaheadMenuPlugin({
595
635
  closeTypeahead();
596
636
  return;
597
637
  }
638
+ if (editor.isComposing()) {
639
+ return;
640
+ }
598
641
  const editorWindow = editor._window || window;
599
642
  const range = editorWindow.document.createRange();
600
643
  const selection = lexical.$getSelection();
@@ -634,7 +677,6 @@ function LexicalTypeaheadMenuPlugin({
634
677
  editor: editor,
635
678
  anchorElementRef: anchorElementRef,
636
679
  options: options,
637
- menuRenderFn: menuRenderFn,
638
680
  shouldSplitNodeWithQuery: true,
639
681
  onSelectOption: onSelectOption,
640
682
  commandPriority: commandPriority,