@lexical/react
Version:
This package provides Lexical components and hooks for React applications.
10 lines (8 loc) • 3.23 kB
JavaScript
/**
* Copyright (c) Meta Platforms, Inc. and affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*
*/
import{useFloating as e,autoUpdate as t,offset as n,flip as s,shift as i,useRole as l,useDismiss as o,useListNavigation as r,useTypeahead as a,useInteractions as c,FloatingPortal as m,FloatingOverlay as d,FloatingFocusManager as h}from"@floating-ui/react";import{useLexicalComposerContext as p}from"@lexical/react/LexicalComposerContext";import{$getNearestNodeFromDOMNode as u,$getRoot as f}from"lexical";import{forwardRef as y,useState as x,useRef as g,useEffect as b,createElement as k}from"react";import{jsx as $,jsxs as w}from"react/jsx-runtime";class N{key;ref;constructor(e){this.key=e,this.ref={current:null},this.setRefElement=this.setRefElement.bind(this)}setRefElement(e){this.ref={current:e}}}class O extends N{type;title;icon;disabled;$onSelect;$showOn;constructor(e,t){super(e),this.type="item",this.title=e,this.disabled=t.disabled??!1,this.icon=t.icon??null,this.$onSelect=t.$onSelect,t.$showOn&&(this.$showOn=t.$showOn)}}class C extends N{type;$showOn;constructor(e){super("_separator"),this.type="separator",e&&e.$showOn&&(this.$showOn=e.$showOn)}}const v=y(({className:e,disabled:t,...n},s)=>$("hr",{className:e})),R=y(({className:e,label:t,disabled:n,icon:s,...i},l)=>w("button",{...i,className:e,ref:l,role:"menuitem",disabled:n,children:[s,t]})),E=y(({items:y,className:w,itemClassName:N,separatorClassName:O},C)=>{const[E]=p(),[S,I]=x(null),[L,P]=x(!1),F=g([]),M=g([]),{refs:X,floatingStyles:Y,context:A}=e({middleware:[n({alignmentAxis:4,mainAxis:5}),s({fallbackPlacements:["left-start"]}),i({padding:10})],onOpenChange:P,open:L,placement:"right-start",strategy:"fixed",whileElementsMounted:t}),j=l(A,{role:"menu"}),B=o(A),D=r(A,{activeIndex:S,listRef:F,onNavigate:I}),U=a(A,{activeIndex:S,enabled:L,listRef:M,onMatch:I}),{getFloatingProps:_,getItemProps:q}=c([j,B,D,U]),[z,G]=x([]);return b(()=>{function e(e){e.preventDefault(),X.setPositionReference({getBoundingClientRect:()=>({bottom:e.clientY,height:0,left:e.clientX,right:e.clientX,top:e.clientY,width:0,x:e.clientX,y:e.clientY})});let t=[];y&&E.read(()=>{const n=u(e.target)??f();n&&(t=y.filter(e=>!e.$showOn||e.$showOn(n)))});const n=t.map((e,t)=>"separator"===e.type?{className:O,key:e.key+"-"+t,type:e.type}:{className:N,disabled:e.disabled,icon:e.icon,key:e.key,label:e.title,onClick:()=>E.update(()=>e.$onSelect()),title:e.title,type:e.type});M.current=n.map(e=>e.key),G(n),P(!0)}return E.registerRootListener(t=>{if(null!==t)return t.addEventListener("contextmenu",e),()=>t.removeEventListener("contextmenu",e)})},[y,N,O,X,E]),$(m,{children:L&&$(d,{lockScroll:!0,children:$(h,{context:A,initialFocus:X.floating,children:$("div",{className:w,ref:X.setFloating,style:Y,..._(),children:z.map((e,t)=>"item"===e.type?k(R,{...q({...e,onClick(){e.onClick(),P(!1)},onMouseUp(){e.onClick(),P(!1)},ref(e){F.current[t]=e},tabIndex:S===t?0:-1}),key:e.key}):"separator"===e.type?k(v,{...q({...e,ref(e){F.current[t]=e},tabIndex:S===t?0:-1}),key:e.key}):void 0)})})})})});export{O as NodeContextMenuOption,E as NodeContextMenuPlugin,C as NodeContextMenuSeparator};