@lexical/react
Version:
This package provides Lexical components and hooks for React applications.
10 lines (8 loc) • 3.2 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.
*
*/
"use strict";var e=require("@floating-ui/react"),t=require("@lexical/react/LexicalComposerContext"),s=require("lexical"),n=require("react"),i=require("react/jsx-runtime");class a{key;ref;constructor(e){this.key=e,this.ref={current:null},this.setRefElement=this.setRefElement.bind(this)}setRefElement(e){this.ref={current:e}}}const o=n.forwardRef(({className:e,disabled:t,...s},n)=>i.jsx("hr",{className:e})),r=n.forwardRef(({className:e,label:t,disabled:s,icon:n,...a},o)=>i.jsxs("button",{...a,className:e,ref:o,role:"menuitem",disabled:s,children:[n,t]})),l=n.forwardRef(({items:a,className:l,itemClassName:c,separatorClassName:u},d)=>{const[m]=t.useLexicalComposerContext(),[p,h]=n.useState(null),[f,x]=n.useState(!1),y=n.useRef([]),g=n.useRef([]),{refs:N,floatingStyles:b,context:k}=e.useFloating({middleware:[e.offset({alignmentAxis:4,mainAxis:5}),e.flip({fallbackPlacements:["left-start"]}),e.shift({padding:10})],onOpenChange:x,open:f,placement:"right-start",strategy:"fixed",whileElementsMounted:e.autoUpdate}),w=e.useRole(k,{role:"menu"}),C=e.useDismiss(k),$=e.useListNavigation(k,{activeIndex:p,listRef:y,onNavigate:h}),O=e.useTypeahead(k,{activeIndex:p,enabled:f,listRef:g,onMatch:h}),{getFloatingProps:R,getItemProps:v}=e.useInteractions([w,C,$,O]),[S,E]=n.useState([]);return n.useEffect(()=>{function e(e){e.preventDefault(),N.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=[];a&&m.read(()=>{const n=s.$getNearestNodeFromDOMNode(e.target);n&&(t=a.filter(e=>!e.$showOn||e.$showOn(n)))});const n=t.map((e,t)=>"separator"===e.type?{className:u,key:e.key+"-"+t,type:e.type}:{className:c,disabled:e.disabled,icon:e.icon,key:e.key,label:e.title,onClick:()=>m.update(()=>e.$onSelect()),title:e.title,type:e.type});g.current=n.map(e=>e.key),E(n),x(!0)}return m.registerRootListener(t=>{if(null!==t)return t.addEventListener("contextmenu",e),()=>t.removeEventListener("contextmenu",e)})},[a,c,u,N,m]),i.jsx(e.FloatingPortal,{children:f&&i.jsx(e.FloatingOverlay,{lockScroll:!0,children:i.jsx(e.FloatingFocusManager,{context:k,initialFocus:N.floating,children:i.jsx("div",{className:l,ref:N.setFloating,style:b,...R(),children:S.map((e,t)=>"item"===e.type?n.createElement(r,{...v({...e,onClick(){e.onClick(),x(!1)},onMouseUp(){e.onClick(),x(!1)},ref(e){y.current[t]=e},tabIndex:p===t?0:-1}),key:e.key}):"separator"===e.type?n.createElement(o,{...v({...e,ref(e){y.current[t]=e},tabIndex:p===t?0:-1}),key:e.key}):void 0)})})})})});exports.NodeContextMenuOption=class extends a{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)}},exports.NodeContextMenuPlugin=l,exports.NodeContextMenuSeparator=class extends a{type;$showOn;constructor(e){super("_separator"),this.type="separator",e&&e.$showOn&&(this.$showOn=e.$showOn)}};