• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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