1 line
6.8 KiB
JavaScript
1 line
6.8 KiB
JavaScript
const smMenu=document.createElement("template");smMenu.innerHTML='\n<style> \n*{\n padding: 0;\n margin: 0;\n -webkit-box-sizing: border-box;\n box-sizing: border-box;\n} \n.menu{\n display: -ms-grid;\n display: grid;\n place-items: center;\n position: relative;\n height: 2rem;\n width: 2rem;\n outline: none;\n}\n.icon {\n position: absolute;\n fill: rgba(var(--text-color), 0.7);\n height: 2.4rem;\n width: 2.4rem;\n padding: 0.5rem;\n border-radius: 2rem;\n -webkit-transition: background 0.3s;\n -o-transition: background 0.3s;\n transition: background 0.3s;\n} \n:host{\n display: -webkit-inline-box;\n display: -ms-inline-flexbox;\n display: inline-flex;\n}\n.hide{\n opacity: 0;\n pointer-events: none;\n user-select: none;\n}\n.select{\n position: relative;\n display: -webkit-box;\n display: -ms-flexbox;\n display: flex;\n -webkit-box-orient: vertical;\n -webkit-box-direction: normal;\n -ms-flex-direction: column;\n flex-direction: column;\n cursor: pointer;\n width: 100%;\n -webkit-tap-highlight-color: transparent;\n}\n.menu:focus .icon,\n.focused{\n background: rgba(var(--text-color), 0.1); \n}\n:host([align-options="left"]) .options{\n left: 0;\n}\n:host([align-options="right"]) .options{\n right: 0;\n}\n.options{\n padding: 0.5rem 0;\n overflow: hidden auto;\n position: absolute;\n display: -webkit-box;\n display: -ms-flexbox;\n display: flex;\n min-width: -webkit-max-content;\n min-width: -moz-max-content;\n min-width: max-content;\n -webkit-transform: translateY(-1rem);\n -ms-transform: translateY(-1rem);\n transform: translateY(-1rem);\n -webkit-box-orient: vertical;\n -webkit-box-direction: normal;\n -ms-flex-direction: column;\n flex-direction: column;\n background: rgba(var(--background-color), 1);\n -webkit-transition: opacity 0.3s, -webkit-transform 0.3s;\n transition: opacity 0.3s, -webkit-transform 0.3s;\n -o-transition: opacity 0.3s, transform 0.3s;\n transition: opacity 0.3s, transform 0.3s;\n transition: opacity 0.3s, transform 0.3s, -webkit-transform 0.3s;\n border: solid 1px rgba(var(--text-color), 0.2);\n border-radius: 0.3rem;\n z-index: 1;\n -webkit-box-shadow: 0.4rem 0.8rem 1.2rem #00000030;\n box-shadow: 0.4rem 0.8rem 1.2rem #00000030;\n top: 100%;\n bottom: auto;\n}\n.moveUp{\n top: auto;\n bottom: 100%;\n -webkit-transform: translateY(3rem);\n -ms-transform: translateY(3rem);\n transform: translateY(3rem);\n}\n.moveLeft{\n left: auto;\n right: 0;\n}\n.no-transformations{\n -webkit-transform: none !important;\n -ms-transform: none !important;\n transform: none !important;\n}\n@media (hover: hover){\n .menu:hover .icon{\n background: rgba(var(--text-color), 0.1); \n }\n}\n</style>\n<div class="select">\n <div class="menu" tabindex="0">\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="M12 3c-1.1 0-2 .9-2 2s.9 2 2 2 2-.9 2-2-.9-2-2-2zm0 14c-1.1 0-2 .9-2 2s.9 2 2 2 2-.9 2-2-.9-2-2-2zm0-7c-1.1 0-2 .9-2 2s.9 2 2 2 2-.9 2-2-.9-2-2-2z"/></svg>\n </div>\n <div class="options hide">\n <slot></slot> \n </div>\n</div>',customElements.define("sm-menu",class extends HTMLElement{constructor(){super(),this.attachShadow({mode:"open"}).append(smMenu.content.cloneNode(!0)),this.open=!1,this.availableOptions,this.containerDimensions,this.optionList=this.shadowRoot.querySelector(".options"),this.menu=this.shadowRoot.querySelector(".menu"),this.icon=this.shadowRoot.querySelector(".icon"),this.expand=this.expand.bind(this)}static get observedAttributes(){return["value"]}get value(){return this.getAttribute("value")}set value(n){this.setAttribute("value",n)}expand(){this.open||(this.optionList.classList.remove("hide"),this.optionList.classList.add("no-transformations"),this.open=!0,this.icon.classList.add("focused"),this.availableOptions.forEach(n=>{n.setAttribute("tabindex","0")}))}collapse(){this.open&&(this.open=!1,this.icon.classList.remove("focused"),this.optionList.classList.add("hide"),this.optionList.classList.remove("no-transformations"),this.availableOptions.forEach(n=>{n.removeAttribute("tabindex")}))}connectedCallback(){this.setAttribute("role","listbox");const n=this.shadowRoot.querySelector(".options slot");n.addEventListener("slotchange",t=>{this.availableOptions=n.assignedElements(),this.containerDimensions=this.optionList.getBoundingClientRect()}),this.menu.addEventListener("click",n=>{this.open?this.collapse():this.expand()}),this.menu.addEventListener("keydown",n=>{"ArrowDown"!==n.code&&"ArrowRight"!==n.code||(n.preventDefault(),this.availableOptions[0].focus()),"Enter"!==n.code&&"Space"!==n.code||(n.preventDefault(),this.open?this.collapse():this.expand())}),this.optionList.addEventListener("keydown",n=>{"ArrowUp"!==n.code&&"ArrowRight"!==n.code||(n.preventDefault(),document.activeElement.previousElementSibling?document.activeElement.previousElementSibling.focus():this.availableOptions[this.availableOptions.length-1].focus()),"ArrowDown"!==n.code&&"ArrowLeft"!==n.code||(n.preventDefault(),document.activeElement.nextElementSibling?document.activeElement.nextElementSibling.focus():this.availableOptions[0].focus())}),this.optionList.addEventListener("click",n=>{this.collapse()}),window.addEventListener("mousedown",n=>{this.contains(n.target)||2===n.button||this.collapse()})}});const menuOption=document.createElement("template");menuOption.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 display: -webkit-box;\n display: -ms-flexbox;\n display: flex;\n --padding: 0.6rem 1.6rem;\n}\n.option{\n display: -webkit-box;\n display: -ms-flexbox;\n display: flex;\n min-width: 100%;\n padding: var(--padding);\n cursor: pointer;\n overflow-wrap: break-word;\n white-space: nowrap;\n outline: none;\n font-size: 1rem;\n user-select: none;\n -webkit-box-align: center;\n -ms-flex-align: center;\n align-items: center;\n}\n:host(:focus){\n outline: none;\n background: rgba(var(--text-color), 0.1);\n}\n@media (hover: hover){\n .option:hover{\n background: rgba(var(--text-color), 0.1);\n }\n}\n</style>\n<div class="option">\n <slot></slot> \n</div>',customElements.define("menu-option",class extends HTMLElement{constructor(){super(),this.attachShadow({mode:"open"}).append(menuOption.content.cloneNode(!0))}connectedCallback(){this.setAttribute("role","option"),this.addEventListener("keyup",n=>{"Enter"!==n.code&&"Space"!==n.code||(n.preventDefault(),this.click())})}}); |