-
Notifications
You must be signed in to change notification settings - Fork 75
/
calcite-switch.tsx
121 lines (100 loc) · 2.97 KB
/
calcite-switch.tsx
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
import {
Component,
h,
Prop,
Event,
Element,
Host,
EventEmitter,
Listen,
Watch,
Build
} from "@stencil/core";
import { SPACE, ENTER } from "../../utils/keys";
@Component({
tag: "calcite-switch",
styleUrl: "calcite-switch.scss",
shadow: true
})
export class CalciteSwitch {
@Element() el: HTMLElement;
/** True if the switch is initially on */
@Prop({ reflect: true, mutable: true }) switched?: boolean = false;
/** The name of the checkbox input */
@Prop({ reflect: true, mutable: true }) name?: string = "";
/** The value of the checkbox input */
@Prop({ reflect: true, mutable: true }) value?: string = "";
/** What color the switch should be */
@Prop() color?: "red" | "blue" = "blue";
@Event() calciteSwitchChange: EventEmitter;
private observer: MutationObserver;
@Listen("click") onClick(e) {
// prevent duplicate click events that occur
// when the component is wrapped in a label and checkbox is clicked
if (
(this.el.closest("label") && e.target === this.inputProxy) ||
(!this.el.closest("label") && e.target === this.el)
) {
this.switched = !this.switched;
}
}
@Listen("keydown") keyDownHandler(e: KeyboardEvent) {
if (e.keyCode === SPACE || e.keyCode === ENTER) {
this.switched = !this.switched;
}
}
@Watch("switched") switchWatcher() {
this.calciteSwitchChange.emit();
this.switched
? this.inputProxy.setAttribute("checked", "")
: this.inputProxy.removeAttribute("checked");
}
private inputProxy: HTMLInputElement;
connectedCallback() {
this.setupProxyInput();
}
disconnectedCallback() {
this.observer.disconnect();
}
componentWillRender() {
this.syncProxyInputToThis();
}
render() {
return (
<Host role="checkbox" aria-checked={this.switched} tabindex="0">
<div class="track">
<div class="handle" />
</div>
<slot />
</Host>
);
}
private setupProxyInput() {
// check for a proxy input
this.inputProxy = this.el.querySelector("input");
// if the user didn't pass a proxy input create one for them
if (!this.inputProxy) {
this.inputProxy = document.createElement("input");
this.inputProxy.type = "checkbox";
this.syncProxyInputToThis();
this.el.appendChild(this.inputProxy);
}
this.syncThisToProxyInput();
if (Build.isBrowser) {
this.observer = new MutationObserver(this.syncThisToProxyInput);
this.observer.observe(this.inputProxy, { attributes: true });
}
}
private syncThisToProxyInput = () => {
this.switched = this.inputProxy.hasAttribute("checked");
this.name = this.inputProxy.name;
this.value = this.inputProxy.value;
};
private syncProxyInputToThis = () => {
this.switched
? this.inputProxy.setAttribute("checked", "")
: this.inputProxy.removeAttribute("checked");
this.inputProxy.setAttribute("name", this.name);
this.inputProxy.setAttribute("value", this.value);
};
}