UNPKG

@magic-spells/scrolling-content

Version:

Infinite scrolling marquee web component — hover to pause, drag to scrub, no dependencies

1 lines 6.84 kB
!function(e,t){"object"==typeof exports&&"undefined"!=typeof module?t(exports):"function"==typeof define&&define.amd?define(["exports"],t):t((e="undefined"!=typeof globalThis?globalThis:e||self).ScrollingContent={})}(this,(function(e){Object.defineProperty(e,Symbol.toStringTag,{value:"Module"});var t=60,n="left",r=["mobile-speed","desktop-speed","breakpoint"],i=!1,s=class extends HTMLElement{},o=class extends HTMLElement{},a=class extends HTMLElement{#e=null;#t=[];#n=null;#r=null;#i=null;#s=null;#o=!1;#a=!1;#l=!1;#c=!1;#d=null;#g=0;#p=0;#u=0;#f=0;#h=0;#m=0;#b=t;static get observedAttributes(){return["speed","direction","paused","pause-on-hover","drag","fade"]}connectedCallback(){const e=this;e.#o||(e.#o=!0,e.#v(),e.#k()),e.#y(),e.#C(),e.#r=new ResizeObserver((()=>e.refresh())),e.#r.observe(e),e.#t[0]&&e.#r.observe(e.#t[0])}disconnectedCallback(){const e=this;e.#w(),e.#n?.abort(),e.#n=null,e.#r?.disconnect(),e.#r=null,e.#l=!1,e.#A()}attributeChangedCallback(e,t,n){t!==n&&this.#o&&("speed"===e&&(this.#b=this.#P()),"fade"===e&&this.#y(),this.#E())}start(){this.removeAttribute("paused")}stop(){this.setAttribute("paused","")}refresh(){const e=this;e.isConnected&&e.#e&&(e.#h=e.getBoundingClientRect().width,e.#b=e.#P(),e.#S(),e.#I(),e.#L(),e.#E())}get speed(){return this.#b}set speed(e){this.setAttribute("speed",String(e))}get direction(){return"right"===this.getAttribute("direction")?"right":n}set direction(e){this.setAttribute("direction","right"===e?"right":"left")}get paused(){return this.hasAttribute("paused")}set paused(e){this.toggleAttribute("paused",Boolean(e))}#v(){if(i)return;const e=r.filter((e=>this.hasAttribute(e)));e.length&&(i=!0,console.warn(`<scrolling-content>: ${e.join(", ")} ${e.length>1?"were":"was"} removed in v2. Use the \`speed\` attribute (px/sec) and override it per breakpoint with the \`--scrolling-content-speed\` custom property.`))}#y(){const e=this.getAttribute("fade");e?this.style.setProperty("--scrolling-content-fade",e):this.style.removeProperty("--scrolling-content-fade")}#k(){const e=this;if(e.#e=e.querySelector("scrolling-track"),!e.#e){for(e.#e=document.createElement("scrolling-track");e.firstChild;)e.#e.appendChild(e.firstChild);e.appendChild(e.#e)}if(!e.#e.querySelector("scrolling-item")){const t=document.createElement("scrolling-item");for(;e.#e.firstChild;)t.appendChild(e.#e.firstChild);e.#e.appendChild(t)}e.#t=Array.from(e.#e.children)}#C(){const e=this;e.#n?.abort(),e.#n=new AbortController;const{signal:t}=e.#n;e.addEventListener("mouseenter",(()=>e.#O(!0)),{signal:t}),e.addEventListener("mouseleave",(()=>e.#O(!1)),{signal:t}),e.#e.addEventListener("pointerdown",(t=>e.#z(t)),{signal:t}),e.#e.addEventListener("pointermove",(t=>e.#x(t)),{signal:t}),e.#e.addEventListener("pointerup",(t=>e.#M(t)),{signal:t}),e.#e.addEventListener("pointercancel",(t=>e.#M(t)),{signal:t}),window.addEventListener("resize",(()=>e.refresh()),{passive:!0,signal:t}),e.#i=window.matchMedia("(prefers-reduced-motion: reduce)"),e.#i.addEventListener("change",(()=>e.#E()),{signal:t})}#P(){const e=getComputedStyle(this).getPropertyValue("--scrolling-content-speed").trim(),n=""===e?NaN:parseFloat(e);if(Number.isFinite(n))return n;const r=parseFloat(this.getAttribute("speed"));return Number.isFinite(r)?r:t}#S(){const e=this,t=e.#t[0];if(!t)return;const n=t.getBoundingClientRect().width;if(!(n>=1))return void(e.#m=0);e.#m=n+(parseFloat(getComputedStyle(e.#e).columnGap)||0);const r=Math.min(Math.ceil(2*e.#h/e.#m)+1,200);for(let i=e.#t.length;i<r;i++)e.#e.appendChild(e.#D(t));e.#t=Array.from(e.#e.children)}#D(e){const t=e.cloneNode(!0);t.setAttribute("aria-hidden","true"),t.inert=!0,t.removeAttribute("id");for(const n of t.querySelectorAll("[id]"))n.removeAttribute("id");return t}#I(){const e=this.#m;this.#p=e>0?(this.#p%e+e)%e-e:0}#L(){this.#e&&(this.#e.style.transform=`translateX(${this.#p}px)`)}get#X(){return this.#i?.matches??!1}get#F(){const e=this;return e.isConnected&&e.#m>0&&!e.paused&&!e.#l&&!e.#c&&!e.#X}#E(){this.#F?this.#T():this.#w()}#T(){const e=this;e.#a||(e.#a=!0,e.#g=performance.now(),e.#s=requestAnimationFrame((t=>e.#_(t))),e.#R("start"))}#w(){const e=this;e.#a&&(cancelAnimationFrame(e.#s),e.#s=null,e.#a=!1,e.#R("stop"))}#_(e){const t=this;if(!t.#a)return;const n=Math.min(e-t.#g,64)/1e3;t.#g=e;const r=t.#b*n;t.#p+="right"===t.direction?r:-r,t.#I(),t.#L(),t.#s=requestAnimationFrame((e=>t.#_(e)))}#O(e){"false"!==this.getAttribute("pause-on-hover")&&(this.#l=e,this.#E())}get#q(){return"false"!==this.getAttribute("drag")}#z(e){const t=this;if(t.#q&&!t.#c&&e.isPrimary){t.#c=!0,t.#d=e.pointerId,t.#u=e.clientX,t.#f=t.#p,t.setAttribute("dragging",""),t.#E(),t.#R("drag-start");try{t.#e.setPointerCapture(e.pointerId)}catch{}}}#x(e){const t=this;t.#c&&e.pointerId===t.#d&&(t.#p=t.#f+(e.clientX-t.#u),t.#I(),t.#L())}#M(e){this.#c&&e.pointerId===this.#d&&this.#A()}#A(){const e=this;e.#c&&(null!==e.#d&&e.#e?.hasPointerCapture(e.#d)&&e.#e.releasePointerCapture(e.#d),e.#c=!1,e.#d=null,e.removeAttribute("dragging"),e.#E(),e.#R("drag-end"))}#R(e){this.dispatchEvent(new CustomEvent(`scrolling-content:${e}`,{bubbles:!0,composed:!0}))}};!function(){if("undefined"==typeof document)return;if(document.querySelector("style[data-scrolling-content]"))return;const e=document.createElement("style");e.setAttribute("data-scrolling-content",""),e.textContent="@layer scrolling-content {\nscrolling-content:not(:defined){visibility:hidden}scrolling-content{display:block;overflow:hidden}scrolling-content[fade]{--_fade:var(--scrolling-content-fade,4rem);-webkit-mask-image:linear-gradient(90deg, transparent, #000 var(--_fade), #000 calc(100% - var(--_fade)), transparent);-webkit-mask-image:linear-gradient(90deg, transparent, #000 var(--_fade), #000 calc(100% - var(--_fade)), transparent);-webkit-mask-image:linear-gradient(90deg, transparent, #000 var(--_fade), #000 calc(100% - var(--_fade)), transparent);mask-image:linear-gradient(90deg, transparent, #000 var(--_fade), #000 calc(100% - var(--_fade)), transparent)}scrolling-track{align-items:center;gap:var(--scrolling-content-gap,1rem);will-change:transform;touch-action:pan-y;cursor:grab;flex-wrap:nowrap;width:max-content;display:flex}scrolling-content[drag=false] scrolling-track{cursor:auto;touch-action:auto}scrolling-content[dragging] scrolling-track{cursor:grabbing;-webkit-user-select:none;user-select:none}scrolling-item{align-items:center;gap:var(--scrolling-content-gap,1rem);padding:var(--scrolling-content-item-padding,0);flex:none;display:flex}\n}",document.head.prepend(e)}(),customElements.get("scrolling-track")||customElements.define("scrolling-track",s),customElements.get("scrolling-item")||customElements.define("scrolling-item",o),customElements.get("scrolling-content")||customElements.define("scrolling-content",a),e.ScrollingContent=a,e.ScrollingItem=o,e.ScrollingTrack=s}));