1/* 2 * Copyright (C) 2022 Huawei Device Co., Ltd. 3 * Licensed under the Apache License, Version 2.0 (the "License"); 4 * you may not use this file except in compliance with the License. 5 * You may obtain a copy of the License at 6 * 7 * http://www.apache.org/licenses/LICENSE-2.0 8 * 9 * Unless required by applicable law or agreed to in writing, software 10 * distributed under the License is distributed on an "AS IS" BASIS, 11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 * See the License for the specific language governing permissions and 13 * limitations under the License. 14 */ 15 16 17import {BaseElement, element} from "../BaseElement.js"; 18 19@element('lit-switch') 20export default class LitSwitch extends BaseElement { 21 private switch: HTMLInputElement | null | undefined 22 private isfocus: boolean | undefined 23 24 static get observedAttributes() { 25 return ['disabled', 'checked'] 26 } 27 28 get disabled() { 29 return this.getAttribute("disabled") !== null; 30 } 31 32 set disabled(value) { 33 if (value === null || value === false) { 34 this.removeAttribute("disabled"); 35 } else { 36 this.setAttribute("disabled", ""); 37 } 38 } 39 40 get checked() { 41 return this.getAttribute("checked") !== null; 42 } 43 44 set checked(value) { 45 if (value === null || value === false) { 46 this.removeAttribute("checked"); 47 } else { 48 this.setAttribute("checked", ""); 49 } 50 } 51 52 get name() { 53 return this.getAttribute("name"); 54 } 55 56 initElements(): void { 57 58 } 59 60 initHtml(): string { 61 return ` 62 <style> 63 :host{ 64 display:inline-block; 65 -webkit-tap-highlight-color: transparent; 66 } 67 #name{ 68 cursor:pointer; 69 display:flex; 70 width:2.4em; 71 height:1.2em; 72 padding:.125em; 73 border-radius:1.2em; 74 background: #3391FF; 75 transition:.3s width,.3s height,.3s background-color; 76 } 77 78 :host(:not([checked])) #name { 79 background: #999999; 80 } 81 82 #name::before{ 83 content:''; 84 flex:0; 85 transition:.2s cubic-bezier(.12, .4, .29, 1.46) flex; 86 } 87 #name::after{ 88 content:''; 89 width:.4em; 90 height:.4em; 91 border-radius:1.2em; 92 border:.4em solid #fff; 93 background-color:#ffffff; 94 transition:.3s background,.3s padding,.3s width,.3s height,.3s border-radius,.3s border; 95 box-shadow: 0 2px 4px 0 rgba(0,35,11,0.2); 96 } 97 #name:active::after{ 98 padding:0 .3em; 99 } 100 #switch:checked+#name{ 101 background:#42b983); 102 } 103 #switch:checked+#name::before{ 104 flex:1; 105 } 106 #switch{ 107 position:absolute; 108 clip:rect(0,0px,0px,0); 109 } 110 :host(:focus-within) #name::after,:host(:active) ::after{ 111 background:#42b983; 112 } 113 :host(:focus-within) #name{ 114 box-shadow: 0 0 10px rgba(0,0,0,0.1); 115 } 116 :host(:focus-within) #switch,:host(:active) #switch{ 117 z-index:2 118 } 119 :host([disabled]){ 120 pointer-events: none; 121 opacity:.5; 122 } 123 :host([disabled]) #name{ 124 pointer-events: all; 125 cursor: not-allowed; 126 } 127 </style> 128 <input type="checkbox" id="switch"><label id="name" for="switch"></label> 129 `; 130 } 131 132 connectedCallback() { 133 this.switch = this.shadowRoot?.getElementById("switch") as HTMLInputElement; 134 this.disabled = this.disabled; 135 this.checked = this.checked; 136 this.switch!.onchange = (ev) => { 137 this.checked = this.switch!.checked; 138 this.dispatchEvent(new CustomEvent("change", {detail: {checked: this.checked}})); 139 } 140 this.switch.onkeydown = (ev) => { 141 switch (ev.keyCode) { 142 case 13://enter 143 this.checked = !this.checked; 144 this.dispatchEvent(new CustomEvent("change", {detail: {checked: this.checked}})); 145 break; 146 default: 147 break; 148 } 149 } 150 this.switch.onfocus = (ev) => { 151 ev.stopPropagation(); 152 if (!this.isfocus) { 153 this.dispatchEvent(new CustomEvent("focus", {detail: {value: this.switch!.value}})) 154 } 155 } 156 this.switch.onblur = ev => { 157 ev.stopPropagation(); 158 if (getComputedStyle(this.switch!).zIndex == '2') { 159 this.isfocus = true; 160 } else { 161 this.isfocus = false; 162 this.dispatchEvent(new CustomEvent("blur", {detail: {value: this.switch!.value}})); 163 } 164 } 165 } 166 167 attributeChangedCallback(name: string, oldValue: string, newValue: string) { 168 if (name === "disabled" && this.switch) { 169 if (newValue !== null) { 170 this.switch.setAttribute("disabled", ""); 171 } else { 172 this.switch.removeAttribute("disabled"); 173 } 174 } 175 if (name === "checked" && this.switch) { 176 if (newValue !== null) { 177 this.switch.checked = true; 178 } else { 179 this.switch.checked = false; 180 } 181 } 182 } 183} 184 185