• 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
16import { BaseElement, element } from '../BaseElement';
17
18const initHtmlStyle:string = `
19    <style>
20        :host{
21            display:inline-block;
22            -webkit-tap-highlight-color: transparent;
23        }
24        #name{
25            transition:0.31s width,0.31s height,0.31s background-color;
26            width:2.41em;
27            height:1.21em;
28            background: #3391FF;
29            display:flex;
30            padding:0.124em;
31            border-radius:1.21em;
32            cursor:pointer;
33        }
34
35        :host(:not([checked])) #name {
36           background: #999999;
37        }
38
39        #name::before{
40            content:'';
41            flex:0;
42            transition:.2s cubic-bezier(.12, .4, .29, 1.46) flex;
43        }
44        #name::after{
45            content:'';
46            width:.4em;
47            height:.4em;
48            border-radius:1.2em;
49            border:.4em solid #fff;
50            background-color:#ffffff;
51            transition:.3s background,.3s padding,.3s width,.3s height,.3s border-radius,.3s border;
52            box-shadow: 0 2px 4px 0 rgba(0,35,11,0.2);
53        }
54        #name:active::after{
55            padding:0 .3em;
56        }
57        #switch:checked+#name{
58            background:#42b983);
59        }
60        #switch:checked+#name::before{
61            flex:1;
62        }
63        #switch{
64            position:absolute;
65            clip:rect(0,0px,0px,0);
66        }
67        :host(:focus-within) #name::after,:host(:active) ::after{
68            background:#42b983;
69        }
70        :host(:focus-within) #name{
71            box-shadow: 0 0 10px rgba(0,0,0,0.1);
72        }
73        :host(:focus-within) #switch,:host(:active) #switch{
74            z-index:2
75        }
76        :host([disabled]){
77            pointer-events: none;
78            opacity:.5;
79        }
80        :host([disabled]) #name{
81            pointer-events: all;
82            cursor: not-allowed;
83        }
84        </style>
85    `;
86
87@element('lit-switch')
88export default class LitSwitch extends BaseElement {
89  private switch: HTMLInputElement | null | undefined;
90  private isfocus: boolean | undefined;
91
92  static get observedAttributes() {
93    return ['disabled', 'checked'];
94  }
95
96  get disabled():boolean {
97    return this.getAttribute('disabled') !== null;
98  }
99
100  get checked() {
101    return this.getAttribute('checked') !== null;
102  }
103
104  set checked(value) {
105    if (value === null || value === false) {
106      this.removeAttribute('checked');
107    } else {
108      this.setAttribute('checked', '');
109    }
110  }
111
112  set disabled(value:boolean) {
113    if (value === null || value === false) {
114      this.removeAttribute('disabled');
115    } else {
116      this.setAttribute('disabled', '');
117    }
118  }
119
120  get name() {
121    return this.getAttribute('name');
122  }
123
124  initElements(): void {}
125
126  initHtml(): string {
127    return `
128        ${initHtmlStyle}
129        <input type="checkbox" id="switch"><label id="name" for="switch"></label>
130        `;
131  }
132
133  connectedCallback() {
134    this.switch = this.shadowRoot?.getElementById('switch') as HTMLInputElement;
135    this.disabled = this.disabled;
136    this.checked = this.checked;
137    this.switch!.onchange = (ev) => {
138      this.checked = this.switch!.checked;
139      let changeEvent: CustomEventInit<LitSwitchChangeEvent> = {
140        detail: {
141          checked: this.checked,
142        },
143      };
144      this.dispatchEvent(new CustomEvent('change', changeEvent));
145    };
146    this.switch.onkeydown = (ev) => {
147      switch (ev.keyCode) {
148        case 13: //enter
149          this.checked = !this.checked;
150          let changeEvent: CustomEventInit<LitSwitchChangeEvent> = {
151            detail: {
152              checked: this.checked,
153            },
154          };
155          this.dispatchEvent(new CustomEvent('change', changeEvent));
156          break;
157        default:
158          break;
159      }
160    };
161    this.setEvent();
162  }
163
164  setEvent():void{
165    this.switch!.onfocus = (ev) => {
166      ev.stopPropagation();
167      if (!this.isfocus) {
168        this.dispatchEvent(
169          new CustomEvent('focus', {
170            detail: { value: this.switch!.value },
171          })
172        );
173      }
174    };
175    this.switch!.onblur = (ev) => {
176      ev.stopPropagation();
177      if (getComputedStyle(this.switch!).zIndex == '2') {
178        this.isfocus = true;
179      } else {
180        this.isfocus = false;
181        this.dispatchEvent(
182          new CustomEvent('blur', {
183            detail: { value: this.switch!.value },
184          })
185        );
186      }
187    };
188  }
189
190  attributeChangedCallback(name: string, oldValue: string, newValue: string) {
191    if (name === 'disabled' && this.switch) {
192      if (newValue !== null) {
193        this.switch.setAttribute('disabled', '');
194      } else {
195        this.switch.removeAttribute('disabled');
196      }
197    }
198    if (name === 'checked' && this.switch) {
199      if (newValue !== null) {
200        this.switch.checked = true;
201      } else {
202        this.switch.checked = false;
203      }
204    }
205  }
206}
207
208export interface LitSwitchChangeEvent {
209  checked: boolean;
210}
211