@localnerve/jump-scroll 0.9.25 → 0.9.26
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/jump-scroll.js +1 -1
- package/package.json +2 -2
package/dist/jump-scroll.js
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
/*! jump-scroll@0.9.
|
|
1
|
+
/*! jump-scroll@0.9.26, Copyright (c) 2023-2025 Alex Grant <alex@localnerve.com> (https://www.localnerve.com), LocalNerve LLC, BSD-3-Clause */
|
|
2
2
|
class t extends HTMLElement{#t=null;#e=null;#s=null;#i=!0;#o=!1;#r=0;#n="";#l=null;#h=null;#c=null;#a=null;#u=null;static#d=15;#b=null;#p=null;#v=null;#g=null;#m=null;#f=null;#y=null;#w=!1;#k=!1;#j=0;static#x=800;static#A=["target"];static#E={target:"section",display:"best",colormap:"",enablekeyboard:!0,scrollcontainer:""};static get observedAttributes(){return[...t.#A,"display","colormap","enablekeyboard","scrollcontainer"]}static getNumber(t){return parseFloat(t.replace(/[^.+\-\d]+/,""))}constructor(){super(),this.attachShadow({mode:"open",delegatesFocus:!0}),this.targetIntersection=this.targetIntersection.bind(this),this.controlIntersection=this.controlIntersection.bind(this),this.resizeHandler=this.resizeHandler.bind(this),this.clickTop=this.clickTop.bind(this),this.clickBottom=this.clickBottom.bind(this),this.clickNext=this.clickNext.bind(this),this.clickPrev=this.clickPrev.bind(this),this.controlBlur=this.controlBlur.bind(this),this.keydownHandler=this.keydownHandler.bind(this)}#T(e){if(this.hasAttribute(e)){const t=this.getAttribute(e);return/^\s*(?:true|false)\s*$/i.test(t)?"false"!==t:t}return t.#E[e]}get currentTarget(){return this.#a}set currentTarget(t){this.#u.has(t)&&(this.#a=t,this.#S())}jumpScroll(t){if(t!==this.#a){const e=this.#u.get(t);e&&(this.currentTarget=e.prev,this.#R("next",(t=>t<window.innerHeight)))}}get target(){return this.#T("target")}set target(t){const e="target";t?this.setAttribute(e,t):this.removeAttribute(e),this.#I(e)}get display(){return this.#T("display")}set display(t){const e="display",s=["both","best"];this.#p&&this.#p.classList.remove(...s.concat("up","down")),s.includes(t)?(this.setAttribute(e,t),this.#L(),this.#C(),this.#p&&this.#p.classList.add(t)):this.removeAttribute(e)}get colormap(){return this.#T("colormap")}set colormap(t){if(null===this.#p)return;this.#b&&this.#b.clear(),this.#b=null;const e="colormap",s=t&&t.split(";");if(s&&s.length>0&&s[0].includes("@")){this.setAttribute(e,t),this.#b=new Map;for(const t of s){let[e,s]=t.replace(/\s/,"").split("@"),[i,o]=s.replace(/\s/,"").split("/");i.startsWith("--")&&(i=`var(${i})`),o?.startsWith("--")&&(o=`var(${o})`),document.querySelectorAll(e).forEach((t=>{this.#b.set(t,{bgColor:i,bgColorFocus:o})}))}}else this.removeAttribute(e)}keydownHandler(t){const e={PageDown:{true:this.clickBottom,false:this.clickNext},Space:{true:this.clickPrev,false:this.clickNext},PageUp:{true:this.clickTop,false:this.clickPrev}},s=e[t.code]?.[Boolean(t.shiftKey).toString()];s&&s(t)}get enableKeyboard(){return this.#T("enablekeyboard")}set enableKeyboard(t){if(!this.#y)return;const e=t?"addEventListener":"removeEventListener";this.#y[e]("keydown",this.keydownHandler),this.setAttribute("enablekeyboard",t)}#q(){if(!this.#l||!this.#u)return;let t,e,s=1e6;const i=[],o=this.#u.keys();for(const r of o){for(e=r,t=0;e.parentElement;e=e.parentElement)t++;t<=s&&(s=t,i.unshift(r))}let r=i[0].parentElement??i[0];if(i.length>1){const t=new Range;t.setStart(i[0],0),t.setEnd(i[1],0),t.collapsed&&(t.setStart(i[1],0),t.setEnd(i[0],0)),r=t.commonAncestorContainer??r}return r}get scrollContainer(){return this.#T("scrollcontainer")}set scrollContainer(t){if(!this.#l||!this.#u)return;let e;if(this.#y?.id&&this.#y.id.startsWith("js-")&&(this.#y.id=""),t&&(e=document.querySelector(t)),this.#y=e??this.#q(),this.#y){let t;if(this.#y.id)t=this.#y.id;else{const e=new Uint8Array(10);t=`js-${btoa(crypto.getRandomValues(e))}`,this.#y.id=t}if(this.setAttribute("aria-controls",t),this.setAttribute("aria-valuemin","0"),this.#u){const t=this.#u.size-1;this.setAttribute("aria-valuemax",t>0?t:1)}}}#S(){this.#u&&this.setAttribute("aria-valuenow",this.#u.get(this.#a).index)}#H(t,e){const s=t=>{const e=this.#f;return Array.from(this.#p.querySelectorAll(`.${t} button`)).forEach((t=>{t.blur(),t.setAttribute("disabled","true"),t.setAttribute("aria-hidden","true")})),this.#v.get(e)},i=(t,e)=>{Array.from(this.#p.querySelectorAll(`.${t} button`)).forEach((t=>{t.removeAttribute("disabled"),t.setAttribute("aria-hidden","false"),t===e&&t.focus()}))};"mid"===t?"both"===this.display?["top","bot"].forEach((t=>i(t))):"down"===e?i("bot",s("top")):i("top",s("bot")):"start"===t?i("bot",s("top")):i("top",s("bot"))}#B(t){const e=[t],s=["mid","start","end","rest","up","down"];null!==this.#l&&s.push("none"),"best"===this.display&&"mid"===t&&(this.#i?e.push("down"):e.push("up")),this.#H(t,e[e.length-1]),this.#p.classList.remove(...s),this.#p.classList.add(...e),setTimeout((()=>{this.#p.classList.add("rest")}),500)}#R(e,s){const i=this.#u.get(this.#a);if(i[e]){const o=i[e],r=this.#u.get(o),n=Math.round(r.lastTop);this.currentTarget=o,this.#a.scrollIntoView({block:"nearest",inline:"start",behavior:"smooth"}),setTimeout((()=>{n===Math.round(r.lastTop)&&(s(n)?this.#R(e,s):window.scrollBy({top:n,behavior:"smooth"}))}),16.67*t.#d)}else this.#a.scrollIntoView({block:"nearest",inline:"start",behavior:"smooth"})}#P(t="start"){this.currentTarget="start"===t?this.#l:this.#h,this.#a.scrollIntoView({block:"nearest",inline:"start",behavior:"smooth"}),this.#B(t)}clickTop(t){t&&t.preventDefault(),this.#P("start")}clickBottom(t){t&&t.preventDefault(),this.#P("end")}clickNext(t){t&&t.preventDefault(),this.#R("next",(t=>t<window.innerHeight))}clickPrev(t){t&&t.preventDefault(),this.#R("prev",(t=>t>0))}saveFocus(t){this.#f=t}controlBlur(){this.#f=null}#I(e,s){if(!t.#A.includes(e)||!this.#w)return;let i,o;this.#l=null,this.#h=null,this.#c=null,this.#a=null,this.#u?this.#u.clear():this.#u=new Map;const r=[];if(document.querySelectorAll(this[e]).forEach((t=>{for(i=t.getBoundingClientRect(),o=0;o<r.length&&!(i.top<r[o].top);o++);(0===o||o>0&&r[o-1].top!==i.top)&&r.splice(o,0,{top:i.top,bot:i.bottom,el:t}),"function"==typeof s&&s(t)})),r.length>0){this.#l=r[0].el,this.#h=r[r.length-1].el,this.#c=new WeakMap([[this.#l,{pos:"start",down:!0}],[this.#h,{pos:"end",down:!1}]]);let t=0,e=0;const s=window.innerHeight;for(o=0;o<r.length;o++)0>r[o].top&&(e=r[o].bot<s?1:0,t=o+e<r.length?o+e:o),this.#u.set(r[o].el,{index:o,prev:o>0?r[o-1].el:null,next:o<r.length-1?r[o+1].el:null});this.currentTarget=r[t].el,0===t?this.#B("start"):t===r.length-1?this.#B("end"):this.#B("mid")}}targetIntersection(t){const e=t=>{const e=this.#u.get(t.target);t.isIntersecting&&t.intersectionRatio>=.95?e.lastTop?e.lastTop<t.boundingClientRect.top&&(e.lastTop=t.boundingClientRect.top):e.lastTop=t.boundingClientRect.top:t.isIntersecting||(e.lastTop=void 0)};let s,i;const o=(t,e,s,i)=>{let o=t;const r=s.target===e&&s||i.target===e&&i;return r&&(o?r.intersectionRatio<o.intersectionRatio&&(o=r):o=r),o},r=t.sort(((t,r)=>{const n=t.isIntersecting&&r.isIntersecting;let l=t.isIntersecting?-1:r.isIntersecting?1:0;return s=o(s,this.#l,t,r),i=o(i,this.#h,t,r),e(t),e(r),n&&(l=r.intersectionRatio-t.intersectionRatio),l}))[0],n=r.rootBounds?.height??1e6,l=r.boundingClientRect.height,h=l<=n?.49:n/2/l;if(r.isIntersecting){const t=this.#u.get(this.#a),e=this.#c.has(r.target),o=this.#u.get(r.target),n=r.boundingClientRect.top,l=r.intersectionRatio,c=r.target,a=e?0:h,{pos:u,down:d}=this.#c.get(c)??{pos:"mid",down:void 0===o.lastTop?this.#i:n<o.lastTop};if(o.lastTop=n,"mid"!==u)this.#o=l>h&&u;else if(this.#o){const t="start"===this.#o?s:i;t&&t.intersectionRatio<=h&&(this.#o=!1)}this.#o&&"mid"===u||((this.#i?o.index>t.index:o.index<t.index)&&l>a&&(this.currentTarget=c),this.#B(u),this.#i=d),this.#o&&r.intersectionRatio>=.98&&(this.currentTarget=c)}else r.intersectionRatio<=h&&(this.#u.get(r.target).lastTop=void 0)}controlIntersection(t,e){if(this.#b&&!this.#k){const s=e.filter((t=>t.isIntersecting));if(s.length>0){const e=s[0],{bgColor:i,bgColorFocus:o}=this.#b.get(e.target);this.#r++,this.#n=t,i?this.#p.style.setProperty("--js-bg-color",i):(this.#p.style.removeProperty("--js-bg-color"),this.#r=0),o?this.#p.style.setProperty("--js-bg-color-focus",o):this.#p.style.removeProperty("--js-bg-color-focus")}else{this.#r--;const e=t!==this.#n,s=this.#r<=0&&t===this.#n;(e||s)&&(this.#p.style.removeProperty("--js-bg-color"),this.#p.style.removeProperty("--js-bg-color-focus"),this.#r=0)}}}#C(){if(!this.#u)return;const e=window.innerHeight,s=this.offsetHeight,i=e-s,o=Math.abs(s-2),r=t.getNumber(window.getComputedStyle(this).bottom),n=e-r-2;this.#t=new IntersectionObserver(this.targetIntersection,{threshold:[.1,.2,.3,.4,.5,.6,.7,.8,.9,1]}),this.#e=new IntersectionObserver(this.controlIntersection.bind(null,"top"),{threshold:0,rootMargin:`-${i}px 0px -${o}px 0px`}),this.#s=new IntersectionObserver(this.controlIntersection.bind(null,"bot"),{threshold:0,rootMargin:`-${n}px 0px -${r}px 0px`});const l=this.#u.keys();for(const t of l)this.#t.observe(t);const h=this.#b.keys();for(const t of h)this.#e.observe(t),this.#s.observe(t)}#L(){this.#t&&this.#t.disconnect(),this.#e&&this.#e.disconnect(),this.#s&&this.#s.disconnect(),this.#t=null,this.#e=null,this.#s=null}resizeHandler(){this.#k||(this.#k=!0,setTimeout((()=>{let t=!1;const e=window.innerWidth;e!==this.#j&&(e>this.#j&&(t=!0),this.#j=e),this.#M(!1,t),this.#k=!1}),t.#x))}#z(){this.#k=!1,window.addEventListener("resize",this.resizeHandler)}#$(){window.removeEventListener("resize",this.resizeHandler),this.#k=!1}#M(e=!0,s=!0){let i=!1;this.#w?this.#F(e,s):i=!0,this.#w=!0,s&&t.#A.forEach((t=>{this.#I(t)})),i&&(this.#j=window.innerWidth,this.setAttribute("aria-label","Alternate scroller, jump directly to author's sections"),this.scrollContainer=this.scrollContainer,this.enableKeyboard=this.enableKeyboard),this.#C(),e&&this.#z()}#F(t=!0,e=!0){t&&this.#$(),this.#L(),e&&(this.#l=null,this.#h=null,this.#c=null,this.#a=null,this.#u&&this.#u.clear(),this.#u=null,this.#y=null,this.enableKeyboard=!1,this.#w=!1)}connectedCallback(){"complete"!==document.readyState?window.addEventListener("load",(()=>{this.#M()}),{once:!0}):this.#M();const{shadowRoot:t}=this;t.innerHTML='<style>:host{--js-width:3rem;--js-aspect-ratio:0.2;--js-height:calc(var(--js-width) * (1 / var(--js-aspect-ratio)));--js-bg-color:black;--js-bg-color-focus:darkorange;--js-bg-spread-focus:8px;--js-color:white;--js-opacity-full:0.8;--js-opacity-rest:0.5;--js-attach-right:1rem;--js-attach-bottom:1rem;position:fixed;bottom:var(--js-attach-bottom);right:var(--js-attach-right);color:var(--js-color)}.container{display:block;transition:opacity 1s;opacity:var(--js-opacity-full);width:var(--js-width);height:auto;aspect-ratio:var(--js-aspect-ratio)}.container button{padding:0;margin:0;border:none;color:transparent}.container.best{aspect-ratio:calc(var(--js-aspect-ratio) * 2)}.container.none{display:none}.container.rest{opacity:var(--js-opacity-rest)}.container.mid{transform:none}.container.best.mid.down .top,.container.start .top{pointer-events:none;opacity:0}.container.best.mid.up .bot,.container.end .bot{pointer-events:none;opacity:0;transform:translateY(102%)}.container.best.end .top,.container.best.mid.down .top,.container.best.mid.up .top{transform:translateY(5%)}.container.end .top{transform:translateY(102%)}button:hover{cursor:pointer}.bot,.top{position:absolute;width:var(--js-width);height:auto;aspect-ratio:calc(var(--js-aspect-ratio) * 2);transition:opacity 1s,transform 1s;pointer-events:auto}.top{top:0}.bot{bottom:0}.bc:focus-within{filter:drop-shadow(0px 0px var(--js-bg-spread-focus) var(--js-bg-color-focus))}.bc{position:absolute;width:var(--js-width)}.bc-end,.bc-start{height:calc(var(--js-height)/ 6)}.bc-next,.bc-prev{height:calc(var(--js-height)/ 4)}.bc-start{top:0}.bc-end{bottom:0}.bc-prev{top:calc((var(--js-height)/ 6) + 10%)}.bc-next{bottom:calc((var(--js-height)/ 6) + 10%)}.bot .end,.bot .next,.top .prev,.top .start{position:absolute;left:50%;width:100%;background:var(--js-bg-color);-webkit-user-select:none;user-select:none}.bot .end,.top .start{height:calc(var(--js-height)/ 6);clip-path:polygon(10% 0%,90% 0%,90% 30%,65% 30%,100% 100%,0% 100%,35% 30%,10% 30%)}.bot .next,.top .prev{height:calc(var(--js-height)/ 4);clip-path:polygon(50% 0%,100% 60%,65% 60%,100% 100%,0% 100%,35% 60%,0% 60%)}.top .prev,.top .start{transform:translateX(-50%)}.bot .end,.bot .next{transform:translateX(-50%) rotateX(180deg)}</style><div class="container none"><div class=top><div class="bc bc-start"><button type=button class=start>Scroll to start</button></div><div class="bc bc-prev"><button type=button class=prev>Scroll to previous</button></div></div><div class=bot><div class="bc bc-next"><button type=button class=next>Scroll to next</button></div><div class="bc bc-end"><button type=button class=end>Scroll to end</button></div></div></div>',this.#p=t.querySelector(".container"),this.display=this.display,this.colormap=this.colormap,this.addEventListener("blur",this.controlBlur),this.#g=[this.#p.querySelector('button[class*="next"]'),this.#p.querySelector('button[class*="prev"]'),this.#p.querySelector('button[class*="start"]'),this.#p.querySelector('button[class*="end"]')],this.#m=this.#g.map((t=>this.saveFocus.bind(this,t))),this.#g.forEach(((t,e)=>{t.addEventListener("focus",this.#m[e])})),this.#v=new WeakMap([[this.#g[0],this.#g[1]],[this.#g[1],this.#g[0]],[this.#g[2],this.#g[3]],[this.#g[3],this.#g[2]]]),t.querySelector(".bc-start").addEventListener("click",this.clickTop),t.querySelector(".bc-end").addEventListener("click",this.clickBottom),t.querySelector(".bc-prev").addEventListener("click",this.clickPrev),t.querySelector(".bc-next").addEventListener("click",this.clickNext)}disconnectedCallback(){this.#p=null,this.#f=null,this.#v=null,this.removeEventListener("blur",this.controlBlur),this.#g.forEach(((t,e)=>{t.removeEventListener("focus",this.#m[e])})),this.#g=null,this.#m=null,this.shadowRoot.querySelector(".bc-start").removeEventListener("click",this.clickTop),this.shadowRoot.querySelector(".bc-end").removeEventListener("click",this.clickBottom),this.shadowRoot.querySelector(".bc-prev").removeEventListener("click",this.clickPrev),this.shadowRoot.querySelector(".bc-next").removeEventListener("click",this.clickNext),this.#F()}attributeChangedCallback(t,e,s){s!==e&&(this[t]=this.getAttribute(t))}}customElements.define("jump-scroll",t);
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@localnerve/jump-scroll",
|
|
3
|
-
"version": "0.9.
|
|
3
|
+
"version": "0.9.26",
|
|
4
4
|
"description": "A small, fast, no-dep, jump-scroll web component",
|
|
5
5
|
"main": "dist/index.js",
|
|
6
6
|
"browser": "dist/jump-scroll.js",
|
|
@@ -12,7 +12,7 @@
|
|
|
12
12
|
},
|
|
13
13
|
"devDependencies": {
|
|
14
14
|
"@axe-core/cli": "^4.10.1",
|
|
15
|
-
"@localnerve/web-component-build": "^1.7.
|
|
15
|
+
"@localnerve/web-component-build": "^1.7.2"
|
|
16
16
|
},
|
|
17
17
|
"overrides": {
|
|
18
18
|
"follow-redirects": "latest"
|