@lexical/react
Version:
This package provides Lexical components and hooks for React applications.
10 lines (8 loc) • 7.21 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.
*
*/
;var e=require("@lexical/react/LexicalComposerContext"),t=require("@lexical/utils"),n=require("lexical"),l=require("react"),o=require("react/jsx-runtime");function r(e){var t=Object.create(null);if(e)for(var n in e)t[n]=e[n];return t.default=e,t}var i=r(l);const u="undefined"!=typeof window&&void 0!==window.document&&void 0!==window.document.createElement,c=u?l.useLayoutEffect:l.useEffect;const s=e=>{const t=document.getElementById("typeahead-menu");if(!t)return;const n=t.getBoundingClientRect();n.top+n.height>window.innerHeight&&t.scrollIntoView({block:"center"}),n.top<0&&t.scrollIntoView({block:"center"}),e.scrollIntoView({block:"nearest"})};function a(e,t){const n=e.getBoundingClientRect(),l=t.getBoundingClientRect();return n.top>l.top&&n.top<l.bottom}function m(t,n,o,r){const[i]=e.useLexicalComposerContext();l.useEffect((()=>{if(null!=n&&null!=t){const e=i.getRootElement(),t=null!=e?function(e,t){let n=getComputedStyle(e);const l="absolute"===n.position,o=/(auto|scroll)/;if("fixed"===n.position)return document.body;for(let t=e;t=t.parentElement;)if(n=getComputedStyle(t),(!l||"static"!==n.position)&&o.test(n.overflow+n.overflowY+n.overflowX))return t;return document.body}(e):document.body;let l=!1,u=a(n,t);const c=function(){l||(window.requestAnimationFrame((function(){o(),l=!1})),l=!0);const e=a(n,t);e!==u&&(u=e,null!=r&&r(e))},s=new ResizeObserver(o);return window.addEventListener("resize",o),document.addEventListener("scroll",c,{capture:!0,passive:!0}),s.observe(n),()=>{s.unobserve(n),window.removeEventListener("resize",o),document.removeEventListener("scroll",c,!0)}}}),[n,i,r,o,t])}const d=n.createCommand("SCROLL_TYPEAHEAD_OPTION_INTO_VIEW_COMMAND");function f({close:e,editor:o,anchorElementRef:r,resolution:i,options:u,menuRenderFn:a,onSelectOption:m,shouldSplitNodeWithQuery:f=!1,commandPriority:p=n.COMMAND_PRIORITY_LOW,preselectFirstItem:g=!0}){const[h,C]=l.useState(null),E=i.match&&i.match.matchingString;l.useEffect((()=>{g&&C(0)}),[E,g]);const v=l.useCallback((t=>{o.update((()=>{const l=null!=i.match&&f?function(e){const t=n.$getSelection();if(!n.$isRangeSelection(t)||!t.isCollapsed())return null;const l=t.anchor;if("text"!==l.type)return null;const o=l.getNode();if(!o.isSimpleText())return null;const r=l.offset,i=o.getTextContent().slice(0,r),u=e.replaceableString.length,c=r-function(e,t,n){let l=n;for(let n=l;n<=t.length;n++)e.slice(-n)===t.substring(0,n)&&(l=n);return l}(i,e.matchingString,u);if(c<0)return null;let s;return 0===c?[s]=o.splitText(r):[,s]=o.splitText(c,r),s}(i.match):null;m(t,l,e,i.match?i.match.matchingString:"")}))}),[o,f,i.match,m,e]),R=l.useCallback((e=>{const t=o.getRootElement();null!==t&&(t.setAttribute("aria-activedescendant","typeahead-item-"+e),C(e))}),[o]);l.useEffect((()=>()=>{const e=o.getRootElement();null!==e&&e.removeAttribute("aria-activedescendant")}),[o]),c((()=>{null===u?C(null):null===h&&g&&R(0)}),[u,h,R,g]),l.useEffect((()=>t.mergeRegister(o.registerCommand(d,(({option:e})=>!(!e.ref||null==e.ref.current)&&(s(e.ref.current),!0)),p))),[o,R,p]),l.useEffect((()=>t.mergeRegister(o.registerCommand(n.KEY_ARROW_DOWN_COMMAND,(e=>{const t=e;if(null!==u&&u.length){const e=null===h?0:h!==u.length-1?h+1:0;R(e);const n=u[e];null!=n.ref&&n.ref.current&&o.dispatchCommand(d,{index:e,option:n}),t.preventDefault(),t.stopImmediatePropagation()}return!0}),p),o.registerCommand(n.KEY_ARROW_UP_COMMAND,(e=>{const t=e;if(null!==u&&u.length){const e=null===h?u.length-1:0!==h?h-1:u.length-1;R(e);const n=u[e];null!=n.ref&&n.ref.current&&s(n.ref.current),t.preventDefault(),t.stopImmediatePropagation()}return!0}),p),o.registerCommand(n.KEY_ESCAPE_COMMAND,(t=>{const n=t;return n.preventDefault(),n.stopImmediatePropagation(),e(),!0}),p),o.registerCommand(n.KEY_TAB_COMMAND,(e=>{const t=e;return null!==u&&null!==h&&null!=u[h]&&(t.preventDefault(),t.stopImmediatePropagation(),v(u[h]),!0)}),p),o.registerCommand(n.KEY_ENTER_COMMAND,(e=>null!==u&&null!==h&&null!=u[h]&&(null!==e&&(e.preventDefault(),e.stopImmediatePropagation()),v(u[h]),!0)),p))),[v,e,o,u,h,R,p]);return a(r,l.useMemo((()=>({options:u,selectOptionAndCleanUp:v,selectedIndex:h,setHighlightedIndex:C})),[v,h,u]),i.match?i.match.matchingString:"")}function p(e,t){null!=t&&(e.className=t),e.setAttribute("aria-label","Typeahead menu"),e.setAttribute("role","listbox"),e.style.display="block",e.style.position="absolute"}exports.LexicalContextMenuPlugin=function({options:r,onWillOpen:c,onClose:s,onOpen:a,onSelectOption:d,menuRenderFn:g,anchorClassName:h,commandPriority:C=n.COMMAND_PRIORITY_LOW,parent:E}){const[v]=e.useLexicalComposerContext(),[R,b]=l.useState(null),w=i.useRef(null),x=function(t,n,o,r=(u?document.body:void 0),i=!0){const[c]=e.useLexicalComposerContext(),s=l.useRef(u?document.createElement("div"):null),a=l.useCallback((()=>{if(null===s.current||void 0===r)return;s.current.style.top=s.current.style.bottom;const e=c.getRootElement(),n=s.current,l=n.firstChild;if(null!==e&&null!==t){const{left:u,top:c,width:a,height:m}=t.getRect(),d=s.current.offsetHeight;if(n.style.top=`${c+d+3+(i?window.pageYOffset:0)}px`,n.style.left=`${u+window.pageXOffset}px`,n.style.height=`${m}px`,n.style.width=`${a}px`,null!==l){l.style.top=`${c}`;const t=l.getBoundingClientRect(),o=t.height,r=t.width,s=e.getBoundingClientRect();u+r>s.right&&(n.style.left=`${s.right-r+window.pageXOffset}px`),(c+o>window.innerHeight||c+o>s.bottom)&&c-s.top>o+m&&(n.style.top=`${c-o-m+(i?window.pageYOffset:0)}px`)}n.isConnected||(p(n,o),r.append(n)),n.setAttribute("id","typeahead-menu"),s.current=n,e.setAttribute("aria-controls","typeahead-menu")}}),[c,t,i,o,r]);l.useEffect((()=>{const e=c.getRootElement();return null!==t&&a(),()=>{null!==e&&e.removeAttribute("aria-controls");const t=s.current;null!==t&&t.isConnected&&(t.remove(),t.removeAttribute("id"))}}),[c,a,t]);const d=l.useCallback((e=>{null!==t&&(e||n(null))}),[t,n]);m(t,s.current,a,d);const f=s.current;return null!=f&&(p(f,o),null!=r&&r.append(f)),s}(R,b,h,E),O=l.useCallback((()=>{b(null),null!=s&&null!==R&&s()}),[s,R]),y=l.useCallback((e=>{b(e),null!=a&&null===R&&a(e)}),[a,R]),A=l.useCallback((e=>{e.preventDefault(),null!=c&&c(e);const n=t.calculateZoomLevel(e.target);y({getRect:()=>new DOMRect(e.clientX/n,e.clientY/n,1,1)})}),[y,c]),M=l.useCallback((e=>{null!==R&&null!=w.current&&null!=e.target&&n.isDOMNode(e.target)&&!w.current.contains(e.target)&&O()}),[O,R]);return l.useEffect((()=>{const e=v.getRootElement();if(e)return e.addEventListener("contextmenu",A),()=>e.removeEventListener("contextmenu",A)}),[v,A]),l.useEffect((()=>(document.addEventListener("click",M),()=>document.removeEventListener("click",M))),[v,M]),null===x.current||null===R||null===v?null:o.jsx(f,{close:O,resolution:R,editor:v,anchorElementRef:x,options:r,menuRenderFn:(e,t)=>g(e,t,{setMenuRef:e=>{w.current=e}}),onSelectOption:d,commandPriority:C})},exports.MenuOption=class{constructor(e){this.key=e,this.ref={current:null},this.setRefElement=this.setRefElement.bind(this)}setRefElement(e){this.ref={current:e}}};