@coderundebug/ui-web
Version:
A collection of UI web components that can be used in any web project.
2 lines • 9.02 kB
JavaScript
/* By Stephen Paul Hassall (web: https://coderundebug.com) */
import{UiTools as i}from"./ui-tools.js";export class UiToggle extends HTMLElement{static get formAssociated(){return!0}constructor(){super(),this.attachShadow({mode:"open",delegatesFocus:!0}),this.shadowRoot.innerHTML=UiToggle.uiHtml,this.shadowRoot.adoptedStyleSheets=[UiToggle.uiCssStyleSheet],this.i=this.attachInternals(),this.t=this.shadowRoot.querySelector(".base"),this.o=this.shadowRoot.querySelector('slot[name="on"]'),this.u=this.shadowRoot.querySelector('slot[name="off"]'),this.l=this.l.bind(this),this.h=this.h.bind(this),this.v=this.v.bind(this),this.p=!1,this.i.setFormValue(!1),this.setAttribute("aria-checked","false")}get value(){return this.p.toString()}set value(i){if(!i)return this.p=!1,this.m(),void this.i.setFormValue(!1);"true"===i.toLowerCase()?this.p=!0:this.p=!1,this.i.setFormValue(this.p),this.m()}get checked(){return this.p}set checked(i){this.p=i,this.i.setFormValue(this.p),this.m();const t=new Event("change",{bubbles:!0,composed:!0});this.dispatchEvent(t)}connectedCallback(){this.t.addEventListener("click",this.l),this.t.addEventListener("keydown",this.h),this.o.addEventListener("slotchange",this.v),this.u.addEventListener("slotchange",this.v),this.m()}disconnectedCallback(){this.t.removeEventListener("click",this.l),this.t.removeEventListener("keydown",this.h),this.o.removeEventListener("slotchange",this.v),this.u.removeEventListener("slotchange",this.v)}attributeChangedCallback(i,t,o){if("value"===i){if(!value)return this.p=!1,this.i.setFormValue(!1),void this.m();"true"===value.toLowerCase()?this.p=!0:this.p=!1,this.i.setFormValue(this.p),this.m()}"checked"===i&&(this.p=null!==o,this.i.setFormValue(this.p),this.m())}static get observedAttributes(){return["checked","value"]}l(){if(!0===this.t.hasAttribute("disabled"))return;this.p=!this.p,this.i.setFormValue(this.p),this.m();const i=new Event("change",{bubbles:!0,composed:!0});this.dispatchEvent(i)}h(i){if("Space"===i.code||"Enter"===i.key){if(!0===this.t.hasAttribute("disabled"))return;this.p=!this.p,this.i.setFormValue(this.p),this.m();const t=new Event("change",{bubbles:!0,composed:!0});this.dispatchEvent(t),i.preventDefault(),i.stopPropagation()}}v(){0!==this.o.assignedElements().length?this.t.classList.add("on-slot"):this.t.classList.remove("on-slot");0!==this.u.assignedElements().length?this.t.classList.add("off-slot"):this.t.classList.remove("off-slot")}m(){!0===this.p?(this.setAttribute("aria-checked","true"),this.t.setAttribute("toggle","on")):(this.setAttribute("aria-checked","false"),this.t.setAttribute("toggle","off"))}formDisabledCallback(i){!0===i?this.t.setAttribute("disabled",""):this.t.removeAttribute("disabled")}formStateRestoreCallback(i){"true"===i.toLowerCase()?this.p=!0:this.p=!1,this.i.setFormValue(this.p),this.m()}formResetCallback(){this.p=!1,this.i.setFormValue(!1),this.m()}}UiToggle.uiCss=' :host{display:inline-block;}.base{display:block;position:relative;direction:ltr;--ui-tp:var(--ui-toggle-padding, 3px);--ui-ts:var(--ui-toggle-size, 24px);--ui-tg:var(--ui-toggle-gap, 0px);--ui-tb:0px;--ui-th:calc(var(--ui-ts) - (var(--ui-tp) * 2) - (var(--ui-tb) * 2));--ui-tob:var(--ui-toggle-on-background, var(--ui-success-background, hsl(104 50% 90% / 1)));--ui-tof:var(--ui-toggle-on-foreground, var(--ui-success-foreground, hsl(104 50% 30% / 1)));--ui-tfb:var(--ui-toggle-off-background, var(--ui-default-background, hsl(0 0% 90% / 1)));--ui-tff:var(--ui-toggle-off-foreground, var(--ui-default-foreground, hsl(0 0% 30% / 1)));--ui-tdb:var( --ui-toggle-disabled-background, color-mix( in srgb-linear, var(--ui-foreground, hsl(0 0% 18% / 1)) 75%, var(--ui-background, hsl(0 0% 97% / 1)) 25% ) );--ui-tdf:var( --ui-toggle-disabled-foreground, color-mix( in srgb-linear, var(--ui-foreground, hsl(0 0% 18% / 1)) 25%, var(--ui-background, hsl(0 0% 97% / 1)) 75% ) );height:var(--ui-th);width:calc((var(--ui-ts) * 2) + var(--ui-tg) - (var(--ui-tp) * 2) - (var(--ui-tb) * 2));padding:var(--ui-tp);box-sizing:content-box;border-radius:10rem;cursor:pointer;transition:background-color var(--ui-animation-duration-default, 200ms) ease-in-out;-webkit-tap-highlight-color:transparent;}.dot{position:absolute;inset:unset;border-radius:10rem;height:var(--ui-th);width:var(--ui-th);transition:inset-inline-start var(--ui-animation-duration-default, 200ms) ease-in-out, background-color var(--ui-animation-duration-default, 200ms) ease-in-out;}.base[toggle="on"] .dot{inset-inline-start:calc(var(--ui-ts) + var(--ui-tp) + var(--ui-tg));background-color:var(--ui-tof);}.base[toggle="on"]{background-color:var(--ui-tob);}.base[toggle="off"] .dot{inset-inline-start:var(--ui-tp);background-color:var(--ui-tff);}.base[toggle="off"]{background-color:var(--ui-tfb);}.on, .off{display:grid;justify-items:center;align-items:center;position:absolute;inset:unset;height:var(--ui-th);width:var(--ui-th);background-color:transparent;border-radius:10rem;overflow:hidden;transition:stroke var(--ui-animation-duration-default, 200ms) ease-in-out;}.on{inset-inline-start:var(--ui-tp);--ui-icon-primary-color:var(--ui-tof);}.off{inset-inline-end:var(--ui-tp);--ui-icon-primary-color:var(--ui-tff);}svg{height:calc(var(--ui-th) / 2);width:calc(var(--ui-th) / 2);height:round(calc(var(--ui-th) * 0.6), 2px);width:round(calc(var(--ui-th) * 0.6), 2px);fill:none;stroke-width:3;stroke-linecap:round;stroke:var(--ui-icon-primary-color);}.base.on-slot .on svg, .base.off-slot .off svg{display:none;}::slotted(*){height:75%;width:75%;height:round(calc(var(--ui-th) * 0.6), 2px);width:round(calc(var(--ui-th) * 0.6), 2px);}.base[disabled]{cursor:not-allowed;}.base[disabled], .base[disabled] .on, .base[disabled] .off{background-color:var(--ui-tdb);--ui-icon-primary-color:var(--ui-tdf);}:host([outline]) .base[toggle="off"][disabled], :host([outline]) .base[toggle="on"][disabled]{border-color:var(--ui-tdf);}:host([outline]) .base[disabled] .off, :host([outline]) .base[disabled] .on{--ui-icon-primary-color:var(--ui-tdf);}.base[disabled] .dot{background-color:var(--ui-tdf);}:host([icons-off]){& .on, .off{display:none;}} :host([icons-inside]){& .dot{z-index:0;}& .on, .off{z-index:1;opacity:1;background-color:transparent;}& .on{inset-inline-start:unset;inset-inline-end:var(--ui-tp);}& .off{inset-inline-start:var(--ui-tp);inset-inline-end:unset;}& .base[toggle="on"] .on{opacity:1;}& .base[toggle="on"] .off{opacity:0;}& .base[toggle="off"] .off{opacity:1;}& .base[toggle="off"] .on{opacity:0;}& .base[toggle="on"] .on{--ui-icon-primary-color:var(--ui-tob);}& .base[toggle="off"] .off{--ui-icon-primary-color:var(--ui-tfb);}& .base[toggle="on"] .on{animation-name:turn-on;animation-duration:var(--ui-animation-duration-default, 200ms);animation-timing-function:linear;}& .base[toggle="on"] .off{animation-name:turn-off;animation-duration:var(--ui-animation-duration-default, 200ms);animation-timing-function:linear;}& .base[toggle="off"] .off{animation-name:turn-on;animation-duration:var(--ui-animation-duration-default, 200ms);animation-timing-function:linear;}& .base[toggle="off"] .on{animation-name:turn-off;animation-duration:var(--ui-animation-duration-default, 200ms);animation-timing-function:linear;}} @keyframes turn-on{0%{opacity:0;}99%{opacity:0;}100%{opacity:1;}} @keyframes turn-off{0%{opacity:1;}1%{opacity:0;}100%{opacity:0;}} :host([outline]){& .base{--ui-tb:var(--ui-toggle-border-width, var(--ui-border-width, 1px));border-style:var(--ui-toggle-border-style, solid);border-width:var(--ui-toggle-border-width, var(--ui-border-width, 1px));}& .base[toggle="on"]{border-color:var(--ui-tof);}& .base[toggle="off"]{border-color:var(--ui-tff);}& .on, .off{background-color:transparent;}& .on{--ui-icon-primary-color:var(--ui-tof);}& .off{--ui-icon-primary-color:var(--ui-tff);}} :host([square]){& .base{border-radius:var(--ui-toggle-square-radius, var(--ui-border-radius-normal, 4px));}& .dot{border-radius:var(--ui-toggle-square-radius, var(--ui-border-radius-normal, 4px));}} :host([reverse]) .base{direction:rtl;}.base[toggle="on"]:focus-visible{outline-offset:2px;outline-style:solid;outline-width:2px;outline-color:var(--ui-tof);}.base[toggle="off"]:focus-visible{outline-offset:2px;outline-style:solid;outline-width:2px;outline-color:var(--ui-tff);}@media (forced-colors:active) or (prefers-contrast:more){.base{border-style:solid;border-color:fieldtext;border-width:2px;box-shadow:none;transition:none;}.dot{border-style:solid;border-width:2px;border-color:fieldtext;box-sizing:border-box;}} @media (prefers-reduced-motion){.base, .dot, .on, .off{transition:none;}} ',UiToggle.uiHtml='<div class="base" tabindex="0"><div class="on" aria-hidden="true"><slot name="on"></slot><svg viewBox="0 0 16 16"><path d="M 6,12 14,4"></path><path d="m 2,8 4,4"></path></svg></div><div class="off" aria-hidden="true"><slot name="off"></slot><svg viewBox="0 0 16 16"><path d="M 2,2 14,14"></path><path d="M 2,14 14,2"></path></svg></div><div class="dot" aria-hidden="true"></div></div>',i.createUi(UiToggle,"ui-toggle",import.meta.url);