1 line
9.0 KiB
JavaScript
1 line
9.0 KiB
JavaScript
const smChips=document.createElement("template");smChips.innerHTML='\n<style>\n *{\n padding: 0;\n margin: 0;\n -webkit-box-sizing: border-box;\n box-sizing: border-box;\n } \n :host{\n padding: 1rem 0;\n max-width: 100%;\n }\n .hide{\n opacity: 0;\n pointer-events: none;\n }\n input[type="radio"]{\n display: none;\n }\n .scrolling-container{\n position: relative;\n display: grid;\n grid-template-columns: min-content minmax(0,1fr) min-content;\n grid-template-rows: 1fr;\n }\n .sm-chips{\n display: flex;\n position: relative;\n grid-area: 1/1/2/-1;\n gap: var(--gap, 0.5rem);\n overflow: auto hidden;\n }\n :host([multiline]) .sm-chips{\n flex-wrap: wrap;\n }\n :host(:not([multiline])) .sm-chips{\n max-width: 100%; \n align-items: center;\n }\n .nav-button{\n display: flex;\n z-index: 2;\n border: none;\n padding: 0.3rem;\n cursor: pointer;\n align-items: center;\n background: rgba(var(--background-color,(255,255,255)), 1);\n grid-row: 1;\n transition: opacity 0.2s;\n }\n .nav-button--left{\n grid-column: 1;\n justify-self: start;\n }\n .nav-button--right{\n grid-column: 3;\n justify-self: end;\n }\n .cover{\n position: absolute;\n z-index: 1;\n width: 5rem;\n height: 100%;\n pointer-events: none;\n grid-row: 1;\n transition: opacity 0.2s;\n }\n .cover--left{\n grid-column: 1;\n }\n .cover--right{\n grid-column: 3;\n }\n .nav-button--right::before{\n background-color: red;\n }\n .icon{\n height: 1.2rem;\n width: 1.2rem;\n fill: rgba(var(--text-color,(17,17,17)), .8);\n }\n @media (hover: none){\n ::-webkit-scrollbar {\n height: 0;\n }\n .nav-button{\n display: none;\n }\n .sm-chips{\n overflow: auto hidden;\n }\n .cover{\n width: 2rem;\n }\n .cover--left{\n background: linear-gradient(90deg, rgba(var(--background-color,(255,255,255)), 1), transparent);\n }\n .cover--right{\n right: 0;\n background: linear-gradient(90deg, transparent, rgba(var(--background-color,(255,255,255)), 1));\n }\n }\n @media (hover: hover){\n ::-webkit-scrollbar-track {\n background-color: transparent !important;\n }\n ::-webkit-scrollbar {\n height: 0;\n background-color: transparent;\n }\n .sm-chips{\n overflow: hidden;\n }\n .cover--left{\n background: linear-gradient(90deg, rgba(var(--background-color,(255,255,255)), 1) 60%, transparent);\n }\n .cover--right{\n right: 0;\n background: linear-gradient(90deg, transparent 0%, rgba(var(--background-color,(255,255,255)), 1) 40%);\n }\n }\n</style>\n<section class="scrolling-container">\n <div class="cover cover--left hide"></div>\n <button class="nav-button nav-button--left hide">\n <svg class="icon" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" width="24" height="24"><path fill="none" d="M0 0h24v24H0z"/><path d="M10.828 12l4.95 4.95-1.414 1.414L8 12l6.364-6.364 1.414 1.414z"/></svg>\n </button>\n <section class="sm-chips" part="chips-wrapper">\n <slot></slot>\n </section>\n <button class="nav-button nav-button--right hide">\n <svg class="icon" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" width="24" height="24"><path fill="none" d="M0 0h24v24H0z"/><path d="M13.172 12l-4.95-4.95 1.414-1.414L16 12l-6.364 6.364-1.414-1.414z"/></svg>\n </button>\n <div class="cover cover--right hide"></div>\n</section>\n\n',customElements.define("sm-chips",class extends HTMLElement{constructor(){super(),this.attachShadow({mode:"open"}).append(smChips.content.cloneNode(!0)),this.chipsWrapper=this.shadowRoot.querySelector(".sm-chips"),this.coverLeft=this.shadowRoot.querySelector(".cover--left"),this.coverRight=this.shadowRoot.querySelector(".cover--right"),this.navButtonLeft=this.shadowRoot.querySelector(".nav-button--left"),this.navButtonRight=this.shadowRoot.querySelector(".nav-button--right"),this.slottedOptions=void 0,this._value=void 0,this.scrollDistance=0,this.assignedElements=[],this.scrollLeft=this.scrollLeft.bind(this),this.scrollRight=this.scrollRight.bind(this),this.fireEvent=this.fireEvent.bind(this),this.setSelectedOption=this.setSelectedOption.bind(this)}get value(){return this._value}set value(t){this.setSelectedOption(t)}scrollLeft(){this.chipsWrapper.scrollBy({left:-this.scrollDistance,behavior:"smooth"})}scrollRight(){this.chipsWrapper.scrollBy({left:this.scrollDistance,behavior:"smooth"})}setSelectedOption(t){this._value!==t&&(this._value=t,this.assignedElements.forEach(e=>{e.value==t?(e.setAttribute("selected",""),e.scrollIntoView({behavior:"smooth",block:"nearest",inline:"center"})):e.removeAttribute("selected")}))}fireEvent(){this.dispatchEvent(new CustomEvent("change",{bubbles:!0,composed:!0,detail:{value:this._value}}))}connectedCallback(){this.setAttribute("role","listbox");const t=this.shadowRoot.querySelector("slot");t.addEventListener("slotchange",e=>{n.disconnect(),i.disconnect(),this.observeSelf.disconnect(),clearTimeout(this.slotChangeTimeout),this.slotChangeTimeout=setTimeout(()=>{this.assignedElements=t.assignedElements(),this.assignedElements.forEach(t=>{t.hasAttribute("selected")&&(this._value=t.value)}),this.observeSelf.observe(this)},0)});const e=new ResizeObserver(t=>{t.forEach(t=>{if(t.contentBoxSize){const e=Array.isArray(t.contentBoxSize)?t.contentBoxSize[0]:t.contentBoxSize;this.scrollDistance=.6*e.inlineSize}else this.scrollDistance=.6*t.contentRect.width})});e.observe(this),this.observeSelf=new IntersectionObserver((t,e)=>{t.forEach(t=>{t.isIntersecting&&!this.hasAttribute("multiline")&&this.assignedElements.length>0&&(n.observe(this.assignedElements[0]),i.observe(this.assignedElements[this.assignedElements.length-1]),e.unobserve(this))})},{threshold:1}),this.chipsWrapper.addEventListener("option-clicked",t=>{this._value!==t.target.value&&(this.setSelectedOption(t.target.value),this.fireEvent())});const n=new IntersectionObserver(t=>{t.forEach(t=>{t.isIntersecting?(this.navButtonLeft.classList.add("hide"),this.coverLeft.classList.add("hide")):(this.navButtonLeft.classList.remove("hide"),this.coverLeft.classList.remove("hide"))})},{threshold:1,root:this}),i=new IntersectionObserver(t=>{t.forEach(t=>{t.isIntersecting?(this.navButtonRight.classList.add("hide"),this.coverRight.classList.add("hide")):(this.navButtonRight.classList.remove("hide"),this.coverRight.classList.remove("hide"))})},{threshold:1,root:this});this.navButtonLeft.addEventListener("click",this.scrollLeft),this.navButtonRight.addEventListener("click",this.scrollRight)}disconnectedCallback(){this.navButtonLeft.removeEventListener("click",this.scrollLeft),this.navButtonRight.removeEventListener("click",this.scrollRight)}});const smChip=document.createElement("template");smChip.innerHTML='\n<style>\n *{\n padding: 0;\n margin: 0;\n -webkit-box-sizing: border-box;\n box-sizing: border-box;\n } \n :host(:focus-within){\n outline: none;\n }\n :host(:focus-within) .sm-chip{\n box-shadow: 0 0 0 0.1rem var(--accent-color,teal) inset;\n }\n :host(:hover:not([selected])) .sm-chip{\n background-color: rgba(var(--text-color,(17,17,17)), 0.06);\n }\n .sm-chip{\n display: flex;\n flex-shrink: 0;\n cursor: pointer;\n white-space: nowrap;\n padding: var(--padding, 0.5rem 0.8rem);\n transition: background 0.3s;\n border-radius: var(--border-radius, 0.5rem);\n -webkit-tap-highlight-color: transparent;\n background: var(--background,inherit);\n }\n .sm-chip[selected]{\n background-color: var(--accent-color,teal);\n color: rgba(var(--background-color, (255,255,255)), 1);\n }\n</style>\n<span class="sm-chip" part="chip">\n <slot></slot>\n</span>\n',customElements.define("sm-chip",class extends HTMLElement{constructor(){super(),this.attachShadow({mode:"open"}).append(smChip.content.cloneNode(!0)),this._value=void 0,this.radioButton=this.shadowRoot.querySelector("input"),this.fireEvent=this.fireEvent.bind(this),this.handleKeyDown=this.handleKeyDown.bind(this)}get value(){return this._value}fireEvent(){this.dispatchEvent(new CustomEvent("option-clicked",{bubbles:!0,composed:!0,detail:{value:this._value}}))}handleKeyDown(t){"Enter"!==t.key&&"Space"!==t.key||this.fireEvent()}connectedCallback(){this.setAttribute("role","option"),this.setAttribute("tabindex","0"),this._value=this.getAttribute("value"),this.addEventListener("click",this.fireEvent),this.addEventListener("keydown",this.handleKeyDown)}disconnectedCallback(){this.removeEventListener("click",this.fireEvent),this.removeEventListener("keydown",this.handleKeyDown)}}); |