web-ui-pack
Version:
Web package with UI elements
161 lines (160 loc) • 4.95 kB
JavaScript
import { WUPCssIconHover, WUPcssHidden } from "../styles";
import WUPBaseControl from "./baseControl";
const tagName = "wup-switch";
export default class WUPSwitchControl extends WUPBaseControl {
#ctr = this.constructor;
static get $styleRoot() {
return `:root {
--ctrl-switch-padding: 1em;
--ctrl-switch-on: #fff;
--ctrl-switch-off: #fff;
--ctrl-switch-off-bg: #9f9f9f;
--ctrl-switch-on-bg: #00778d;
--ctrl-switch-shadow: #0003;
--ctrl-switch-h: var(--ctrl-icon-size);
--ctrl-switch-w: calc(var(--ctrl-icon-size) * 2.8);
--ctrl-switch-r: calc(var(--ctrl-icon-size) * 1.4);
}
[wupdark] {
--ctrl-switch-on: #e7e7e7;
--ctrl-switch-off: #e7e7e7;
--ctrl-switch-off-bg: #707070;
--ctrl-switch-shadow: #000;
}`;
}
static get $style() {
return `${super.$style}
:host {
background: none;
cursor: pointer;
}
:host[readonly] {
cursor: initial;
}
:host label {
display: flex;
gap: 0.5em;
padding: var(--ctrl-switch-padding);
}
:host strong {
box-sizing: border-box;
text-overflow: ellipsis;
overflow: hidden;
white-space: nowrap;
font-weight: normal;
text-decoration: none;
color: inherit;
}
:host [bar] {
display: inline-flex;
align-items: center;
overflow: visible;
width: var(--ctrl-switch-w);
min-width: var(--ctrl-switch-w);
height: var(--ctrl-switch-h);
border-radius: 999px;
color: whitesmoke;
background: var(--ctrl-switch-off-bg);
}
${WUPCssIconHover(":host", "[thumb]")}
:host [thumb] {
z-index: 2;
display: inline-block;
height: var(--ctrl-switch-r);
width: var(--ctrl-switch-r);
background: var(--ctrl-switch-off);
box-shadow: 0 1px 4px 0 var(--ctrl-switch-shadow);
border-radius: 50%;
transform: translateX(-1px);
}
:host input { ${WUPcssHidden} }
:host[checked] [bar] {
background-color: var(--ctrl-switch-on-bg);
}
:host[checked] [thumb] {
background: var(--ctrl-switch-on);
transform: translateX(var(--ctrl-switch-w)) translateX(calc(-100% + 1px));
}
:host[w-reverse] label {
flex-direction: row-reverse;
}
:host[w-reverse] strong {
margin-right: auto;
}
not all and (prefers-reduced-motion) {
:host [bar] { transition: background-color var(--anim); }
:host [thumb] { transition: transform var(--anim); }
}`;
}
static $isEqual(v1, v2) {
return !!v1 === !!v2;
}
static get observedAttributes() {
const arr = super.observedAttributes;
arr.push("defaultchecked");
return arr;
}
static $defaults = {
...WUPBaseControl.$defaults,
validationRules: { ...WUPBaseControl.$defaults.validationRules },
reverse: false,
};
get $value() {
return !!super.$value;
}
set $value(v) {
super.$value = !!v;
}
parse(text) {
return text === "" || text === "1" || text.toLowerCase() === "true";
}
valueToStorage(v) {
return v ? "1" : null;
}
renderControl() {
this.$refInput.id = this.#ctr.$uniqueId;
this.$refLabel.setAttribute("for", this.$refInput.id);
this.$refInput.type = "checkbox";
this.$refLabel.appendChild(this.$refInput);
this.$refLabel.appendChild(this.$refTitle);
const sp = document.createElement("span");
sp.setAttribute("bar", "");
sp.appendChild(document.createElement("span")).setAttribute("thumb", "");
this.$refLabel.appendChild(sp);
this.appendChild(this.$refLabel);
}
gotReady() {
super.gotReady();
this.$refInput.oninput = (e) => this.gotInput(e);
}
gotInput(e) {
const el = e.target;
if (this.$isReadOnly) {
el.checked = !el.checked;
}
else {
this.setValue(el.checked, 3);
}
}
setValue(v, reason) {
const r = super.setValue(v, reason);
this.$refInput.checked = !!v;
this.setAttr("checked", this.$refInput.checked, true);
return r;
}
gotChanges(propsChanged) {
super.gotChanges(propsChanged);
this.setAttr("w-reverse", this._opts.reverse, true);
}
gotFormChanges(propsChanged) {
super.gotFormChanges(propsChanged);
this.setAttr.call(this.$refInput, "aria-readonly", this.$isReadOnly);
}
attributeChangedCallback(name, oldValue, newValue) {
if (name === "defaultchecked") {
name = "initvalue";
}
super.attributeChangedCallback(name, oldValue, newValue);
}
}
customElements.define(tagName, WUPSwitchControl);