@lexical/react
Version:
This package provides Lexical components and hooks for React applications.
10 lines (8 loc) • 6.51 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{useLexicalComposerContext as t}from"@lexical/react/LexicalComposerContext";import{createCommand as e,KEY_ARROW_DOWN_COMMAND as n,KEY_ARROW_UP_COMMAND as o,KEY_ESCAPE_COMMAND as l,KEY_TAB_COMMAND as r,KEY_ENTER_COMMAND as i,COMMAND_PRIORITY_LOW as s,$getSelection as u,$isRangeSelection as c,$getNodeByKey as a}from"lexical";import m,{useLayoutEffect as d,useEffect as p,useState as f,useCallback as g,useMemo as h,useRef as y}from"react";import{mergeRegister as w}from"@lexical/utils";import{jsx as b}from"react/jsx-runtime";const v="startTransition";const C="undefined"!=typeof window&&void 0!==window.document&&void 0!==window.document.createElement?d:p;class x{constructor(t){this.key=t,this.ref={current:null},this.setRefElement=this.setRefElement.bind(this)}setRefElement(t){this.ref={current:t}}}const E=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 R(t,e){const n=t.getBoundingClientRect(),o=e.getBoundingClientRect();return n.top>o.top&&n.top<o.bottom}function O(e,n,o,l){const[r]=t();p((()=>{if(null!=n&&null!=e){const t=r.getRootElement(),e=null!=t?function(t,e){let n=getComputedStyle(t);const o="absolute"===n.position,l=/(auto|scroll)/;if("fixed"===n.position)return document.body;for(let e=t;e=e.parentElement;)if(n=getComputedStyle(e),(!o||"static"!==n.position)&&l.test(n.overflow+n.overflowY+n.overflowX))return e;return document.body}(t):document.body;let i=!1,s=R(n,e);const u=function(){i||(window.requestAnimationFrame((function(){o(),i=!1})),i=!0);const t=R(n,e);t!==s&&(s=t,null!=l&&l(t))},c=new ResizeObserver(o);return window.addEventListener("resize",o),document.addEventListener("scroll",u,{capture:!0,passive:!0}),c.observe(n),()=>{c.unobserve(n),window.removeEventListener("resize",o),document.removeEventListener("scroll",u,!0)}}}),[n,r,l,o,e])}const I=e("SCROLL_TYPEAHEAD_OPTION_INTO_VIEW_COMMAND");function S({close:t,editor:e,anchorElementRef:a,resolution:m,options:d,menuRenderFn:y,onSelectOption:b,shouldSplitNodeWithQuery:v=!1,commandPriority:x=s}){const[R,O]=f(null),S=m.match&&m.match.matchingString;p((()=>{O(0)}),[S]);const A=g((n=>{e.update((()=>{const e=null!=m.match&&v?function(t){const e=u();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,s=l-function(t,e,n){let o=n;for(let n=o;n<=e.length;n++)t.substr(-n)===e.substr(0,n)&&(o=n);return o}(r,t.matchingString,i);if(s<0)return null;let a;return 0===s?[a]=o.splitText(l):[,a]=o.splitText(s,l),a}(m.match):null;b(n,e,t,m.match?m.match.matchingString:"")}))}),[e,v,m.match,b,t]),P=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]),C((()=>{null===d?O(null):null===R&&P(0)}),[d,R,P]),p((()=>w(e.registerCommand(I,(({option:t})=>!(!t.ref||null==t.ref.current)&&(E(t.ref.current),!0)),x))),[e,P,x]),p((()=>w(e.registerCommand(n,(t=>{const n=t;if(null!==d&&d.length&&null!==R){const t=R!==d.length-1?R+1:0;P(t);const o=d[t];null!=o.ref&&o.ref.current&&e.dispatchCommand(I,{index:t,option:o}),n.preventDefault(),n.stopImmediatePropagation()}return!0}),x),e.registerCommand(o,(t=>{const e=t;if(null!==d&&d.length&&null!==R){const t=0!==R?R-1:d.length-1;P(t);const n=d[t];null!=n.ref&&n.ref.current&&E(n.ref.current),e.preventDefault(),e.stopImmediatePropagation()}return!0}),x),e.registerCommand(l,(e=>{const n=e;return n.preventDefault(),n.stopImmediatePropagation(),t(),!0}),x),e.registerCommand(r,(t=>{const e=t;return null!==d&&null!==R&&null!=d[R]&&(e.preventDefault(),e.stopImmediatePropagation(),A(d[R]),!0)}),x),e.registerCommand(i,(t=>null!==d&&null!==R&&null!=d[R]&&(null!==t&&(t.preventDefault(),t.stopImmediatePropagation()),A(d[R]),!0)),x))),[A,t,e,d,R,P,x]);return y(a,h((()=>({options:d,selectOptionAndCleanUp:A,selectedIndex:R,setHighlightedIndex:O})),[A,R,d]),m.match?m.match.matchingString:"")}function A({options:e,nodeKey:n,onClose:o,onOpen:l,onSelectOption:r,menuRenderFn:i,anchorClassName:u,commandPriority:c=s,parent:d}){const[h]=t(),[w,C]=f(null),x=function(e,n,o,l=document.body,r=!0){const[i]=t(),s=y(document.createElement("div")),u=g((()=>{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||(null!=o&&(n.className=o),n.setAttribute("aria-label","Typeahead menu"),n.setAttribute("id","typeahead-menu"),n.setAttribute("role","listbox"),n.style.display="block",n.style.position="absolute",l.append(n)),s.current=n,t.setAttribute("aria-controls","typeahead-menu")}}),[i,e,r,o,l]);p((()=>{const t=i.getRootElement();if(null!==e)return u(),()=>{null!==t&&t.removeAttribute("aria-controls");const e=s.current;null!==e&&e.isConnected&&e.remove()}}),[i,u,e]);const c=g((t=>{null!==e&&(t||n(null))}),[e,n]);return O(e,s.current,u,c),s}(w,C,u,d),E=g((()=>{C(null),null!=o&&null!==w&&o()}),[o,w]),R=g((t=>{C(t),null!=l&&null===w&&l(t)}),[l,w]),I=g((()=>{n?h.update((()=>{const t=a(n),e=h.getElementByKey(n);var o;null!=t&&null!=e&&null==w&&(o=()=>R({getRect:()=>e.getBoundingClientRect()}),v in m?m[v](o):o())})):null==n&&null!=w&&E()}),[E,h,n,R,w]);return p((()=>{I()}),[I,n]),p((()=>{if(null!=n)return h.registerUpdateListener((({dirtyElements:t})=>{t.get(n)&&I()}))}),[h,I,n]),null===w||null===h?null:b(S,{close:E,resolution:w,editor:h,anchorElementRef:x,options:e,menuRenderFn:i,onSelectOption:r,commandPriority:c})}export{A as LexicalNodeMenuPlugin,x as MenuOption};