neotoc
Version:
Ultra-smooth table of contents UI generator for your docs and blogs.
3 lines (2 loc) • 10.6 kB
JavaScript
function t(t){if(t===document.documentElement)return[0,t.clientHeight];const e=t.getBoundingClientRect().y+t.clientTop;return[e,e+t.clientHeight]}function e([l,o],n){const[i,r]=t(n);let d=null,s=null;return null===l?[l,o]:(l<=i?o>i&&(d=i):l<r&&(d=l),o<=r?o>i&&(s=o):l<r&&(s=r),n===document.documentElement?[d,s]:e([d,s],n.parentElement))}function l(l,o,n){const[i,r]=t(l),[d,s]=[i+o,r-n],c=l.parentElement;return c?e([d,s],c):[d,s]}function o(t,e){let l=t.parentElement.parentElement.parentElement;return"A"===t.tagName&&(l=l.parentElement),l.classList.contains(e)?l:null}function n(t,e){let l=e;for(let e=0;e<t.length;e++){const o=t[e].getBoundingClientRect().bottom;o<l&&(l=o)}return l}function i(t,e){const l=t.scrollTop;return[l+e,l+t.clientHeight-e]}function r(t,e,l){const o=l?30:-30,n=l?.5:-.5;for(let i=0;(l?i<o:i>o)&&(t.scrollTop=e+i,!(l?t.scrollTop>=e:t.scrollTop<=e));i+=n);}function d(t,e,l){if(l.isScrolling){const n=()=>{const e=l.motorcycleScrollingStartScrollTop+l.scrollNeeded;let o=!0;l.scrollNeeded>0?o=!0:l.scrollNeeded<0&&(o=!1),r(t,e,o),l.isScrolling=!1},i=t.scrollTop;l.timeFrac=(e-l.motorcycleScrollingStartTime)/300,l.timeFrac>1&&(l.timeFrac=1);const d=l.scrollNeeded*(o=l.timeFrac,1-Math.pow(1-o,3));null===l.lastAutoScrollTop||l.lastAutoScrollTop===i?(t.scrollTop=l.motorcycleScrollingStartScrollTop+d,l.lastAutoScrollTop=t.scrollTop):(l.isScrolling=!1,l.lastAutoScrollTop=null),1==l.timeFrac&&n()}var o}function s(t){return`calc(calc(var(--toggle-fold-btn-width) / 2) * pow(calc(100 / var(--relative-font-size)), ${t}) + calc(var(--indent-line-width) / 2))`}function c(t){return`calc(var(--max-indent-width) - ${s(t)})`}function a({io:t,to:e,title:a="On this page",fillAnchor:u=t=>t.textContent,ellipsis:p=!1,classPrefix:g="nt-",initialFoldLevel:m=6,offsetTop:f=0,offsetBottom:h=0,autoScrollOffset:w=50}){function v(t,e){const l=document.createElement(t);return e&&(l.className=g+e),l}function T(t,e){t.classList.add(g+e)}function y(t,e){t.classList.toggle(g+e)}const b=[],B={startTime:0,duration:1e3,on:!1},S={},E=new Map,[F,x,L]=t.split(">>").map((t=>t.trim())),A=document.querySelectorAll(`${F} :is(${x})`),$=A.length>0?+A[0].tagName[1]:0;function C(t,e){for(let l=0;l<b.length;l++){const{isFolded:o,level:n,toggleFold:i}=b[l];t?!o&&n>=e&&i():o&&n<=e&&i()}N()}let q;function N(){const t=b[0].isFolded;let e,l=!0;for(let e=1;e<b.length;e++)b[e].isFolded!=t&&(l=!1);var o;e=l?t?"allFolded":"allUnfolded":"mixed",e!=q&&(q=e,"allFolded"==(o=e)?(V.disabled=!0,j.disabled=!1):"allUnfolded"==o?(V.disabled=!1,j.disabled=!0):"mixed"==o&&(V.disabled=!1,j.disabled=!1))}const k=function t(e){if(!e.length)return;const l=v("ul");for(let o=0;o<e.length;o++){const n=e[o],i=v("li"),r=v("a","a"),d=v("div","non-foldable");r.href=`#${n.id}`,r.append(u(n));const a=n.textContent.trim().replace(/\s+/g," ");p&&(T(r,"ellipsis"),d.title=a),d.append(r),i.append(d),S[n.id]=r;const f=[],h=+n.tagName[1];for(let t=o+1;t<e.length&&+e[t].tagName[1]>h;t++)f.push(e[t]);const w=h-$;if(f.length>0){const e=t(f),l=v("div","toggle-fold-btn"),o=v("div","foldable"),n=v("hr","fold-indicator-line"),r=h>=m;r&&T(o,"foldable-folded"),l.tabIndex=0,l.role="button",l.ariaPressed=r?"true":"false",l.ariaExpanded=r?"false":"true",l.ariaLabel="Toggle fold",l.title="",l.innerHTML='<svg xmlns="http://www.w3.org/2000/svg" width="1em" height="1em" viewBox="0 0 16 16"><path fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="1.5" d="M3.75 5.75L8 10.25l4.25-4.5"/></svg>',l.classList.add(g+`level-${w+1}`);const s="toggle-fold-btn-folded",c="opacity-1";r&&(T(l,s),T(n,c)),d.prepend(l),d.append(n),o.append(e),i.append(o);const a={isFolded:r,level:h,toggleFold(){a.isFolded=!a.isFolded,l.ariaPressed=a.isFolded?"true":"false",l.ariaExpanded=a.isFolded?"false":"true",y(o,"foldable-folded"),y(l,s),y(n,c),a.isFolded&&(B.on=!0),N()}};b.push(a);const u=()=>{a.toggleFold()};l.addEventListener("click",(()=>{u()})),l.addEventListener("keydown",(t=>{"Enter"!=t.key&&" "!=t.key||(" "==t.key&&t.preventDefault(),u())}))}else{const t=v("div","unfoldable-icon");t.innerHTML='<svg xmlns="http://www.w3.org/2000/svg" width="1em" height="1em" viewBox="0 0 24 24"><circle cx="12.1" cy="12.1" r="1" fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="2.65"/></svg>',d.prepend(t)}let E="",F="";for(let t=1;t<=w;t++){const e=v("div","indent-block");d.prepend(e),E=`${s(t)} ${t==w?"":c(t)} var(--indent-line-gap) ${E}`,F=`calc(${s(t)} ${t==w?"":`+ ${c(t)}`} + var(--indent-line-gap)) ${F?`+ ${F}`:""}`}d.style.cssText=`--max-indent-width: ${s(w)}; grid-template-columns: ${E} var(--toggle-fold-btn-width) 1fr`,F=`calc(${F?`${F} + `:""}var(--toggle-fold-btn-width) + var(--anchor-padding-inline))`,r.style.paddingLeft=F,l.append(i),o+=f.length}return l}(A);if(!k)return()=>{};const M=L?document.querySelector(L):e;if(!M)throw new Error("Nothing was found to append Neotoc to!");const H=v("div","widget"),R=v("div","body"),I=v("div","header"),z=v("h2","title"),P=v("div","btn-group"),U="header-btn",V=v("button",U),j=v("button",U),O=v("div","top-gradient"),D=v("div","bottom-gradient");R.style.position="relative",R.ariaLabel=a,R.tabIndex=0,V.innerHTML='<svg xmlns="http://www.w3.org/2000/svg" width="1em" height="1em" viewBox="0 0 24 24"><path fill="currentColor" d="m12 16.9l-2.4 2.4q-.275.275-.7.275t-.7-.275t-.275-.7t.275-.7l3.1-3.1q.15-.15.325-.212t.375-.063t.375.063t.325.212l3.1 3.1q.275.275.275.7t-.275.7t-.7.275t-.7-.275zm0-9.8l2.4-2.4q.275-.275.7-.275t.7.275t.275.7t-.275.7l-3.1 3.1q-.15.15-.325.213T12 9.475t-.375-.062T11.3 9.2L8.2 6.1q-.275-.275-.275-.7t.275-.7t.7-.275t.7.275z"/></svg>',j.innerHTML='<svg xmlns="http://www.w3.org/2000/svg" width="1em" height="1em" viewBox="0 0 24 24"><path fill="currentColor" d="m12 18.1l2.325-2.325q.3-.3.725-.3t.725.3t.3.725t-.3.725L12.7 20.3q-.15.15-.325.213t-.375.062t-.375-.062t-.325-.213l-3.075-3.075q-.3-.3-.3-.725t.3-.725t.725-.3t.725.3zM12 6L9.675 8.325q-.3.3-.725.3t-.725-.3t-.3-.725t.3-.725L11.3 3.8q.15-.15.325-.213T12 3.526t.375.063t.325.212l3.075 3.075q.3.3.3.725t-.3.725t-.725.3t-.725-.3z"/></svg>';const G=["Fold all","Unfold all"];V.ariaLabel=G[0],V.title=G[0],j.ariaLabel=G[1],j.title=G[1],z.innerHTML=a,I.append(z),b.length&&(P.append(V,j),I.append(P),N()),R.append(k,O,D),H.append(I),H.append(R),M.append(H);const J=+getComputedStyle(R).paddingTop.slice(0,-2)+ +getComputedStyle(R).paddingBottom.slice(0,-2);function K(){const t=R.scrollTop,e=R.scrollHeight-R.clientHeight;O.style.top=t+"px",D.style.bottom=-t+"px",O.style.opacity=t>5?"1":"0",D.style.opacity=t+5<e?"1":"0"}K(),k.querySelectorAll("a").forEach((t=>{const e=function(t,e,l){const n=[],i=l+e;let r=o(t,i);for(;r;)n.push(r),r=o(r,i);return n}(t,"foldable",g);E.set(t,e)}));const Q=document.querySelector(F);let W;const X={isScrolling:!1,wasTopEndAboveTopBoundary:null,wasBottomEndBelowBottomBoundary:null,timeFrac:0,scrollNeeded:0,motorcycleScrollingStartScrollTop:0,motorcycleScrollingStartTime:0,lastAutoScrollTop:null},Y=function(t){let e=t.parentElement;for(;e;){const{overflow:t}=window.getComputedStyle(e);if(t.split(" ").every((t=>"auto"===t||"scroll"===t)))return e;e=e.parentElement}return document.documentElement}(Q),Z=function(t,e,l,o,n){const i=e("div","light-bar"),r=e("div","light-bar-top"),d=e("div","light"),s=e("div","light-bar-bottom");i.append(r,d,s),i.style.position="absolute",i.style.display="none",t.append(i);let c=[];const a="on-fold",u="enlightend-a";return t=>{if(t.isVisible){const{top:e,height:d,isTopInAFold:p,isBottomInAFold:g,anchors:m}=t;i.style.display="",i.style.top=`${e}px`,i.style.height=`${d}px`,p?l(r,a):o(r,a),g?l(s,a):o(s,a),c.forEach((t=>{m.includes(t)||o(t,u)})),m.forEach((t=>{n(t,u)||l(t,u)})),c=m}else i.style.display="none",c.forEach((t=>o(t,u)))}}(R,v,T,(function(t,e){t.classList.remove(g+e)}),(function(t,e){return t.classList.contains(g+e)}));let _=null,tt=null,et=null,lt=null,ot=null,nt=null,it=null,rt=null;const dt=t=>{const[e,o]=l(Y,f+1,h),s=[];let c=null,a=null,u=null;for(let t=0;t<A.length;t++){const l=A[t],n=A[t+1],i=l.getBoundingClientRect().top,r=n?n.getBoundingClientRect().top:Q.getBoundingClientRect().bottom,d=r-i;if(null!==e)if(i<e){if(r>e){const t=(Math.min(r,o)-e)/d;c?a=t:c=t,s.push(S[l.id]),null===u&&(u=(e-i)/d)}}else if(i<o){const t=(Math.min(r,o)-i)/d;c?a=t:c=t,s.push(S[l.id]),null===u&&(u=0)}}if(s.length){const l=s[0],g=l.parentElement.getBoundingClientRect(),m=g.top+g.height*u;let f=m+g.height*c;const h=E.get(l),v=n(h,m);let T=n(h,f);if(s.length>1){const t=s[s.length-1],e=t.parentElement.getBoundingClientRect();f=e.top+e.height*a,T=n(E.get(t),f)}const y=R.getBoundingClientRect().top,b=R.scrollTop,B=R.clientTop;ot=null===e?null:o-e;const S=v+b-y-B,F=T+b-y-B;nt=Y.scrollTop,it=m+b-y-B,rt=f+b-y-B,p=()=>{const e=nt-(tt||nt),l=e>0?"down":e<0?"up":"down";!function(t,e,l,o,n){const d=t.scrollTop,[s,c]=i(t,o),a=e<s,u=l>c;null===n.wasTopEndAboveTopBoundary&&(n.wasTopEndAboveTopBoundary=a),null===n.wasBottomEndBelowBottomBoundary&&(n.wasBottomEndBelowBottomBoundary=u),a&&!1===n.wasTopEndAboveTopBoundary&&r(t,d-(s-e),!1),u&&!1===n.wasBottomEndBelowBottomBoundary&&r(t,d+l-c,!0)}(R,S,F,w,X),function(t,e,l,o,n,r,d){const[s,c]=i(e,n);if(d.isScrolling=!(l>s&&o<c)&&(l===s?"up"!=t&&o>c:o!==c||"down"!=t&&l<s),d.isScrolling){d.scrollNeeded="up"==t?l-s:o-c;const n=e.scrollTop,i=e.scrollHeight-e.clientHeight,a=n+d.scrollNeeded;a<0?d.scrollNeeded=-n:a>i&&(d.scrollNeeded=i-n),d.scrollNeeded||(d.isScrolling=!1),d.timeFrac=0,d.motorcycleScrollingStartTime=r,d.motorcycleScrollingStartScrollTop=n}}(l,R,S,F,w,t,X)},((it!==et||rt!==lt)&&nt!==tt||ot!==_)&&p(),function(t,e,l,o,n){const[r,d]=i(t,o),s=e<r,c=l>d;n.wasTopEndAboveTopBoundary=s,n.wasBottomEndBelowBottomBoundary=c}(R,S,F,w,X),d(R,t,X),Z({height:T-v,top:S,bottom:F,isTopInAFold:Math.round(v)<Math.round(m),isBottomInAFold:Math.round(T)<Math.round(f),anchors:s,time:t,isVisible:!0}),K(),_=ot,tt=nt,et=it,lt=rt}else ot=nt=it=rt=null,Z({isVisible:!1,time:t}),K(),_=tt=et=lt=null;var p;if(B.on){0===B.startTime&&(B.startTime=t);const e=R.scrollHeight;let l=R.firstElementChild?.getBoundingClientRect().height;"number"==typeof l&&(l=Math.round(l+J),0!=R.scrollTop&&(R.scrollTop=R.scrollTop-(e-l))),t-B.startTime>B.duration&&(B.on=!1,B.startTime=0)}};let st=0;const ct=t=>{(0===st||t-st>8)&&(dt(t),st=t),W=window.requestAnimationFrame(ct)};return W=window.requestAnimationFrame(ct),V.addEventListener("click",(()=>C(!0,1))),j.addEventListener("click",(()=>C(!1,5))),()=>{H.remove(),window.cancelAnimationFrame(W)}}export{a as default};
//# sourceMappingURL=index.js.map