UNPKG

@lexical/react

Version:

This package provides Lexical components and hooks for React applications.

10 lines (8 loc) • 9.45 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,getDOMShadowRoots as n,mergeRegister as o,registerEventListener as l,getRootOwnerDocument as r,COMMAND_PRIORITY_LOW as i,KEY_ARROW_DOWN_COMMAND as c,KEY_ARROW_UP_COMMAND as u,KEY_ESCAPE_COMMAND as s,KEY_TAB_COMMAND as a,KEY_ENTER_COMMAND as d,isDOMShadowRoot as p,isHTMLElement as m,getParentElement as f,$getSelection as g,$isRangeSelection as h,$isTextNode as y,getDOMSelection as x,getDOMSelectionPoints as C}from"lexical";import{useLayoutEffect as b,useEffect as v,useRef as w,useCallback as R,useState as E,useMemo as I,startTransition as S}from"react";import{SCROLL_TYPEAHEAD_OPTION_INTO_VIEW_COMMAND as O}from"@lexical/react/LexicalTypeaheadMenuPluginUtils";export{PUNCTUATION,SCROLL_TYPEAHEAD_OPTION_INTO_VIEW_COMMAND,getScrollParent,useBasicTypeaheadTriggerMatch}from"@lexical/react/LexicalTypeaheadMenuPluginUtils";import{getScrollParent as T}from"@lexical/utils";import P from"react-dom";import{jsx as N,jsxs as A}from"react/jsx-runtime";export{MenuOption}from"@lexical/react/LexicalMenuOption";const k=e?b:v,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 M(t,e){const n=t.getBoundingClientRect(),o=e.getBoundingClientRect();return n.top>=o.top-6&&n.top<=o.bottom+6}function L(e,r,i,c){const[u]=t();v(()=>{if(null!=r&&null!=e){const t=u.getRootElement(),e=null!=t?T(t,!1):document.body;let s=!1,a=M(r,e);const d=function(){s||(window.requestAnimationFrame(function(){i(),s=!1}),s=!0);const t=M(r,e);t!==a&&(a=t,null!=c&&c(t))},p=new ResizeObserver(i),m=n(t??r);return p.observe(r),o(l(window,"resize",i),l(document,"scroll",d,{capture:!0,passive:!0}),...m.map(t=>l(t,"scroll",d,{capture:!0,passive:!0})),()=>p.unobserve(r))}},[r,u,c,i,e])}function B({index:t,isSelected:e,onClick:n,onMouseEnter:o,option:l}){let r="item";return e&&(r+=" selected"),/*#__PURE__*/A("li",{tabIndex:-1,className:r,ref:l.setRefElement,role:"option","aria-selected":e,id:"typeahead-item-"+t,onMouseEnter:o,onClick:n,children:[l.icon,/*#__PURE__*/N("span",{className:"text",children:l.title})]},l.key)}function F({close:t,editor:e,anchorElementRef:n,resolution:l,options:r,menuRenderFn:p,onSelectOption:m,shouldSplitNodeWithQuery:f=!1,commandPriority:y=i,preselectFirstItem:x=!0}){const[C,b]=E(null),w=null!==C?Math.min(r.length-1,C):null,S=l.match&&l.match.matchingString;v(()=>{x&&b(0)},[S,x]);const T=R(n=>{e.update(()=>{const e=null!=l.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 o=n.getNode();if(!o.isSimpleText())return null;const l=n.offset,r=o.getTextContent().slice(0,l),i=t.replaceableString.length,c=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(c<0)return null;let u;return 0===c?[u]=o.splitText(l):[,u]=o.splitText(c,l),u}(l.match):null;m(n,e,t,l.match?l.match.matchingString:"")})},[e,f,l.match,m,t]),A=R(t=>{const n=e.getRootElement();null!==n&&(n.setAttribute("aria-activedescendant","typeahead-item-"+t),b(t))},[e]),M=R(()=>n.current&&r.length?/*#__PURE__*/P.createPortal(/*#__PURE__*/N("div",{className:"typeahead-popover mentions-menu",children:/*#__PURE__*/N("ul",{children:r.map((t,e)=>/*#__PURE__*/N(B,{index:e,isSelected:w===e,onClick:()=>{b(e),T(t)},onMouseEnter:()=>{b(e)},option:t},t.key))})}),n.current):null,[n,r,w,T,b]);v(()=>()=>{const t=e.getRootElement();null!==t&&t.removeAttribute("aria-activedescendant")},[e]),k(()=>{null===r?b(null):null===w&&x&&A(0)},[r,w,A,x]);const L=null==p&&(null===r||!r.length);v(()=>o(e.registerCommand(O,({option:t})=>!(!t.ref||null==t.ref.current||(D(t.ref.current),0)),y)),[e,A,y]),v(()=>o(e.registerCommand(c,t=>{const n=t;if(L)return!1;const o=null===w?0:w!==r.length-1?w+1:0;A(o);const l=r[o];return l?(l.ref&&l.ref.current&&e.dispatchCommand(O,{index:o,option:l}),n.preventDefault(),n.stopImmediatePropagation(),!0):(A(-1),n.preventDefault(),n.stopImmediatePropagation(),!0)},y),e.registerCommand(u,t=>{const e=t;if(L)return!1;const n=null===w?r.length-1:0!==w?w-1:r.length-1;A(n);const o=r[n];return o?(o.ref&&o.ref.current&&D(o.ref.current),e.preventDefault(),e.stopImmediatePropagation(),!0):(A(-1),e.preventDefault(),e.stopImmediatePropagation(),!0)},y),e.registerCommand(s,e=>{const n=e;return!L&&(n.preventDefault(),n.stopImmediatePropagation(),t(),!0)},y),e.registerCommand(a,t=>{const e=t;return null!==r&&null!==w&&null!=r[w]&&(e.preventDefault(),e.stopImmediatePropagation(),T(r[w]),!0)},y),e.registerCommand(d,t=>!(null===r||null===w||null==r[w]||t&&t.shiftKey||(null!==t&&(t.preventDefault(),t.stopImmediatePropagation()),T(r[w]),0)),y)),[T,t,e,r,L,w,A,y]);const F=I(()=>({options:r,selectOptionAndCleanUp:T,selectedIndex:w,setHighlightedIndex:b}),[T,w,r]);return null!=p?p(n,F,l.match?l.match.matchingString:""):M()}function $(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 U(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 _({options:n,onQueryChange:o,onSelectOption:l,onOpen:c,onClose:u,menuRenderFn:s,triggerFn:a,anchorClassName:d,commandPriority:b=i,parent:I,preselectFirstItem:O=!0,ignoreEntityBoundary:T=!1}){const[P]=t(),[A,k]=E(null),D=w(0),M=w(!1),B=R(()=>{if(!M.current)return;M.current=!1;const t=D.current,e=()=>{D.current===t&&k(null)};let n;try{n=u&&u()}finally{n?n.then(e,e):e()}},[u]),_=R(t=>{D.current++,k(t),M.current||(M.current=!0,null!=c&&c(t))},[c]),H=function(n,o,l,i,c=!0){const[u]=t(),s=i??function(t){if(!e)return;const n=t.getRootElement();if(null!==n){const t=n.getRootNode();return p(t)?t:n.ownerDocument.body}return document.body}(u),a=e?r(u.getRootElement()).createElement("div"):null,d=w(a),g=R(()=>{if(null===d.current||void 0===s)return;d.current.style.top=d.current.style.bottom;const t=u.getRootElement(),e=d.current,o=e.firstChild;if(null!==t&&null!==n){const{left:r,top:i,width:u,height:a}=n.getRect(),g=d.current.offsetHeight,h=function(t){const e=p(t)?t.host:t;for(let t=m(e)?e:null;null!==t;t=f(t)){const e=t.ownerDocument.defaultView;if(null===e)break;if(U(e.getComputedStyle(t))){const e=t.getBoundingClientRect();return{left:e.left+t.clientLeft-t.scrollLeft,top:e.top+t.clientTop-t.scrollTop}}}return null}(s),y=t=>null!==h?t-h.left:t+window.pageXOffset,x=t=>null!==h?t-h.top:t+(c?window.pageYOffset:0);if(e.style.top=`${x(i+g+3)}px`,e.style.left=`${y(r)}px`,e.style.height=`${a}px`,e.style.width=`${u}px`,null!==o){o.style.top=`${i}`;const n=o.getBoundingClientRect(),l=n.height,c=n.width,u=t.getBoundingClientRect();r+c>u.right&&(e.style.left=`${y(u.right-c)}px`),(i+l>window.innerHeight||i+l>u.bottom)&&i-u.top>l+a&&(e.style.top=`${x(i-l-a)}px`)}e.isConnected||($(e,l),s.append(e)),e.setAttribute("id","typeahead-menu"),t.setAttribute("aria-controls","typeahead-menu")}},[u,n,c,l,s]);v(()=>{const t=u.getRootElement();return null!==n&&g(),()=>{null!==t&&t.removeAttribute("aria-controls");const e=d.current;null!==e&&e.isConnected&&(e.remove(),e.removeAttribute("id"))}},[u,g,n]);const h=R(t=>{null!==n&&(t||o(null))},[n,o]);return L(n,d.current,g,h),null!=a&&a===d.current&&($(a,l),null!=s&&s.append(a)),d}(A,R(t=>{null===t?B():k(t)},[B]),d,I);return v(()=>{const t=P.registerUpdateListener(()=>{P.read("latest",()=>{if(!P.isEditable())return void B();const t=()=>{P.isComposing()||B()},e=P._window||window,n=e.document.createRange(),l=g(),r=function(t){let e=null;return t.read("latest",()=>{const t=g();h(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}(P);if(!h(l)||!l.isCollapsed()||null===r||null===n)return void t();const i=a(r,P);if(o(i?i.matchingString:null),null!==i&&(T||!function(t,e){return 0===e&&t.read("latest",()=>{const t=g();if(h(t)){const e=t.anchor.getNode().getPreviousSibling();return y(e)&&e.isTextEntity()}return!1})}(P,i.leadOffset))){const t=function(t,e,n,o){const l=x(n);if(null===l||!l.isCollapsed)return!1;const r=C(l,o),i=r.anchorNode,c=t,u=r.anchorOffset;if(null==i||null==u)return!1;try{e.setStart(i,c),e.setEnd(i,u)}catch(t){return!1}return!0}(i.leadOffset,n,e,P.getRootElement());if(t)return void S(()=>_({getRect:()=>n.getBoundingClientRect(),match:i}))}t()})});return()=>{t()}},[P,a,o,A,B,_,T]),v(()=>P.registerEditableListener(t=>{t||B()}),[P,B]),null===A||null===P||null===H.current?null:/*#__PURE__*/N(F,{close:B,resolution:A,editor:P,anchorElementRef:H,options:n,menuRenderFn:s,shouldSplitNodeWithQuery:!0,onSelectOption:l,commandPriority:b,preselectFirstItem:O})}export{_ as LexicalTypeaheadMenuPlugin,L as useDynamicPositioning};