UNPKG

@lexical/react

Version:

This package provides Lexical components and hooks for React applications.

10 lines (8 loc) • 8.05 kB
/** * 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{useLexicalComposerContext as t}from"@lexical/react/LexicalComposerContext";import{CAN_USE_DOM as e,getRootOwnerDocument as n,mergeRegister as l,COMMAND_PRIORITY_LOW as o,KEY_ARROW_DOWN_COMMAND as r,KEY_ARROW_UP_COMMAND as i,KEY_ESCAPE_COMMAND as c,KEY_TAB_COMMAND as u,KEY_ENTER_COMMAND as s,isDOMShadowRoot as a,isHTMLElement as m,getParentElement as p,getDOMShadowRoots as d,registerEventListener as f,$getSelection as g,$isRangeSelection as h,$getNodeByKey as y}from"lexical";import{useLayoutEffect as x,useEffect as b,useRef as C,useCallback as v,useState as R,useMemo as w,startTransition as E}from"react";import{SCROLL_TYPEAHEAD_OPTION_INTO_VIEW_COMMAND as I}from"@lexical/react/LexicalTypeaheadMenuPluginUtils";import{getScrollParent as S}from"@lexical/utils";import P from"react-dom";import{jsx as k,jsxs as A}from"react/jsx-runtime";export{MenuOption}from"@lexical/react/LexicalMenuOption";const O=e?x:b,D=t=>{const e=t.closest("#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 B(t,e){const n=t.getBoundingClientRect(),l=e.getBoundingClientRect();return n.top>=l.top-6&&n.top<=l.bottom+6}function N({index:t,isSelected:e,onClick:n,onMouseEnter:l,option:o}){let r="item";return e&&(r+=" selected"),/*#__PURE__*/A("li",{tabIndex:-1,className:r,ref:o.setRefElement,role:"option","aria-selected":e,id:"typeahead-item-"+t,onMouseEnter:l,onClick:n,children:[o.icon,/*#__PURE__*/k("span",{className:"text",children:o.title})]},o.key)}function T({close:t,editor:e,anchorElementRef:n,resolution:a,options:m,menuRenderFn:p,onSelectOption:d,shouldSplitNodeWithQuery:f=!1,commandPriority:y=o,preselectFirstItem:x=!0}){const[C,E]=R(null),S=null!==C?Math.min(m.length-1,C):null,A=a.match&&a.match.matchingString;b(()=>{x&&E(0)},[A,x]);const B=v(n=>{e.update(()=>{const e=null!=a.match&&f?function(t){const e=g();if(!h(e)||!e.isCollapsed())return null;const n=e.anchor;if("text"!==n.type)return null;const l=n.getNode();if(!l.isSimpleText())return null;const o=n.offset,r=l.getTextContent().slice(0,o),i=t.replaceableString.length,c=o-function(t,e,n){let l=n;for(let n=l;n<=e.length;n++)t.slice(-n)===e.substring(0,n)&&(l=n);return l}(r,t.matchingString,i);if(c<0)return null;let u;return 0===c?[u]=l.splitText(o):[,u]=l.splitText(c,o),u}(a.match):null;d(n,e,t,a.match?a.match.matchingString:"")})},[e,f,a.match,d,t]),T=v(t=>{const n=e.getRootElement();null!==n&&(n.setAttribute("aria-activedescendant","typeahead-item-"+t),E(t))},[e]),M=v(()=>n.current&&m.length?/*#__PURE__*/P.createPortal(/*#__PURE__*/k("div",{className:"typeahead-popover mentions-menu",children:/*#__PURE__*/k("ul",{children:m.map((t,e)=>/*#__PURE__*/k(N,{index:e,isSelected:S===e,onClick:()=>{E(e),B(t)},onMouseEnter:()=>{E(e)},option:t},t.key))})}),n.current):null,[n,m,S,B,E]);b(()=>()=>{const t=e.getRootElement();null!==t&&t.removeAttribute("aria-activedescendant")},[e]),O(()=>{null===m?E(null):null===S&&x&&T(0)},[m,S,T,x]);const $=null==p&&(null===m||!m.length);b(()=>l(e.registerCommand(I,({option:t})=>!(!t.ref||null==t.ref.current)&&(D(t.ref.current),!0),y)),[e,T,y]),b(()=>l(e.registerCommand(r,t=>{const n=t;if($)return!1;const l=null===S?0:S!==m.length-1?S+1:0;T(l);const o=m[l];return o?(o.ref&&o.ref.current&&e.dispatchCommand(I,{index:l,option:o}),n.preventDefault(),n.stopImmediatePropagation(),!0):(T(-1),n.preventDefault(),n.stopImmediatePropagation(),!0)},y),e.registerCommand(i,t=>{const e=t;if($)return!1;const n=null===S?m.length-1:0!==S?S-1:m.length-1;T(n);const l=m[n];return l?(l.ref&&l.ref.current&&D(l.ref.current),e.preventDefault(),e.stopImmediatePropagation(),!0):(T(-1),e.preventDefault(),e.stopImmediatePropagation(),!0)},y),e.registerCommand(c,e=>{const n=e;return!$&&(n.preventDefault(),n.stopImmediatePropagation(),t(),!0)},y),e.registerCommand(u,t=>{const e=t;return null!==m&&null!==S&&null!=m[S]&&(e.preventDefault(),e.stopImmediatePropagation(),B(m[S]),!0)},y),e.registerCommand(s,t=>!(null===m||null===S||null==m[S]||t&&t.shiftKey)&&(null!==t&&(t.preventDefault(),t.stopImmediatePropagation()),B(m[S]),!0),y)),[B,t,e,m,$,S,T,y]);const F=w(()=>({options:m,selectOptionAndCleanUp:B,selectedIndex:S,setHighlightedIndex:E}),[B,S,m]);return null!=p?p(n,F,a.match?a.match.matchingString:""):M()}function M(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 $(t){if("static"!==t.position)return!0;const e=t.willChange;return"none"!==t.transform||"none"!==t.perspective||"none"!==t.filter||"none"!==t.backdropFilter||t.contain.includes("paint")||t.contain.includes("layout")||t.contain.includes("strict")||t.contain.includes("content")||e.includes("transform")||e.includes("perspective")||e.includes("filter")||e.includes("contain")}function F(o,r,i,c,u=!0){const[s]=t(),g=c??function(t){if(!e)return;const n=t.getRootElement();if(null!==n){const t=n.getRootNode();return a(t)?t:n.ownerDocument.body}return document.body}(s),h=e?n(s.getRootElement()).createElement("div"):null,y=C(h),x=v(()=>{if(null===y.current||void 0===g)return;y.current.style.top=y.current.style.bottom;const t=s.getRootElement(),e=y.current,n=e.firstChild;if(null!==t&&null!==o){const{left:l,top:r,width:c,height:s}=o.getRect(),d=y.current.offsetHeight,f=function(t){const e=a(t)?t.host:t;for(let t=m(e)?e:null;null!==t;t=p(t)){const e=t.ownerDocument.defaultView;if(null===e)break;if($(e.getComputedStyle(t))){const e=t.getBoundingClientRect();return{left:e.left+t.clientLeft-t.scrollLeft,top:e.top+t.clientTop-t.scrollTop}}}return null}(g),h=t=>null!==f?t-f.left:t+window.pageXOffset,x=t=>null!==f?t-f.top:t+(u?window.pageYOffset:0);if(e.style.top=`${x(r+d+3)}px`,e.style.left=`${h(l)}px`,e.style.height=`${s}px`,e.style.width=`${c}px`,null!==n){n.style.top=`${r}`;const o=n.getBoundingClientRect(),i=o.height,c=o.width,u=t.getBoundingClientRect();l+c>u.right&&(e.style.left=`${h(u.right-c)}px`),(r+i>window.innerHeight||r+i>u.bottom)&&r-u.top>i+s&&(e.style.top=`${x(r-i-s)}px`)}e.isConnected||(M(e,i),g.append(e)),e.setAttribute("id","typeahead-menu"),t.setAttribute("aria-controls","typeahead-menu")}},[s,o,u,i,g]);b(()=>{const t=s.getRootElement();return null!==o&&x(),()=>{null!==t&&t.removeAttribute("aria-controls");const e=y.current;null!==e&&e.isConnected&&(e.remove(),e.removeAttribute("id"))}},[s,x,o]);const R=v(t=>{null!==o&&(t||r(null))},[o,r]);return function(e,n,o,r){const[i]=t();b(()=>{if(null!=n&&null!=e){const t=i.getRootElement(),e=null!=t?S(t,!1):document.body;let c=!1,u=B(n,e);const s=function(){c||(window.requestAnimationFrame(function(){o(),c=!1}),c=!0);const t=B(n,e);t!==u&&(u=t,null!=r&&r(t))},a=new ResizeObserver(o),m=d(t??n);return a.observe(n),l(f(window,"resize",o),f(document,"scroll",s,{capture:!0,passive:!0}),...m.map(t=>f(t,"scroll",s,{capture:!0,passive:!0})),()=>a.unobserve(n))}},[n,i,r,o,e])}(o,y.current,x,R),null!=h&&h===y.current&&(M(h,i),null!=g&&g.append(h)),y}function L({options:e,nodeKey:n,onClose:l,onOpen:r,onSelectOption:i,menuRenderFn:c,anchorClassName:u,commandPriority:s=o,parent:a}){const[m]=t(),[p,d]=R(null),f=F(p,d,u,a),g=v(()=>{d(null),null!=l&&null!==p&&l()},[l,p]),h=v(t=>{d(t),null!=r&&null===p&&r(t)},[r,p]),x=v(()=>{n?m.update(()=>{const t=y(n),e=m.getElementByKey(n);null!=t&&null!=e&&null==p&&E(()=>h({getRect:()=>e.getBoundingClientRect()}))}):null==n&&null!=p&&g()},[g,m,n,h,p]);return b(()=>{x()},[x,n]),b(()=>{if(null!=n)return m.registerUpdateListener(({dirtyElements:t})=>{t.get(n)&&x()})},[m,x,n]),null===f.current||null===p||null===m?null:/*#__PURE__*/k(T,{close:g,resolution:p,editor:m,anchorElementRef:f,options:e,menuRenderFn:c,onSelectOption:i,commandPriority:s})}export{L as LexicalNodeMenuPlugin};