UNPKG

react-active-menu

Version:

A React hook to build an active scrolling menu navigation.

3 lines (2 loc) 1.88 kB
"use strict";Object.defineProperty(exports,"__esModule",{value:!0});var e=require("react/jsx-runtime"),t=require("react");const r=t.createContext({}),n=e=>{let t=0;for(;e;)t+=e.offsetTop,e=e.offsetParent;return t};exports.ActiveMenuProvider=({children:t,menu:n})=>e.jsx(r.Provider,Object.assign({value:n},{children:t})),exports.useActiveMenu=(e={})=>{const{activeClassName:r="active",offset:s=0,smooth:o=!1}=e,[i,c]=t.useState(),u=t.useRef(),l=t.useRef(new Map),f=t.useRef(new Map);return t.useEffect((()=>{const e=u.current,t=l.current;if(t.size){const r=()=>{let r,n,o=-1/0;for(const[i,c]of t.entries()){const{top:t=0}=(null==e?void 0:e.getBoundingClientRect())||{},{top:u}=c.getBoundingClientRect();u<=0+t+s&&u>o&&(o=u,r=i),n||(n=i)}c(r||n)};return r(),window.addEventListener("resize",r),e?(e.addEventListener("scroll",r),()=>{window.removeEventListener("resize",r),e.removeEventListener("scroll",r)}):(window.addEventListener("scroll",r),()=>{window.removeEventListener("resize",r),window.removeEventListener("scroll",r)})}}),[s]),t.useEffect((()=>{const e=u.current,t=l.current,r=f.current;if(t.size&&r.size){const i=r=>i=>{i.preventDefault();const c=t.get(r);if(c&&i.target instanceof HTMLElement)if(e){const{top:t}=e.getBoundingClientRect();e.scrollTo({behavior:o?"smooth":"auto",top:n(c)-t-s})}else window.scrollTo({behavior:o?"smooth":"auto",top:n(c)-s})};let c=[];for(const[e,t]of r.entries()){const r=i(e);t.addEventListener("click",r),c.push((()=>t.removeEventListener("click",r)))}return()=>{for(const e of c)e()}}}),[s,o]),t.useEffect((()=>{const e=f.current;if(e.size)for(const[t,n]of e.entries())n.classList.remove(r),t===i&&n.classList.add(r)}),[r,i]),{activeId:i,registerContainer:e=>u.current=e,registerSection:e=>t=>l.current.set(e,t),registerTrigger:e=>t=>f.current.set(e,t)}},exports.useActiveMenuContext=()=>t.useContext(r); //# sourceMappingURL=index.js.map