UNPKG

@esri/calcite-components

Version:

Web Components for Esri's Calcite Design System.

271 lines (270 loc) • 7.27 kB
import { Component, h, Prop, Event, Element, Host, Listen, Watch, Build } from "@stencil/core"; import { getElementDir, hasLabel } from "../../utils/dom"; import { getKey } from "../../utils/key"; export class CalciteSwitch { constructor() { /** True if the switch is disabled */ this.disabled = false; /** The name of the checkbox input */ this.name = ""; /** The scale of the switch */ this.scale = "m"; /** True if the switch is initially on */ this.switched = false; /** The value of the checkbox input */ this.value = ""; this.syncThisToProxyInput = () => { this.switched = this.inputProxy.hasAttribute("checked"); this.name = this.inputProxy.name; this.value = this.inputProxy.value; }; this.syncProxyInputToThis = () => { this.switched ? this.inputProxy.setAttribute("checked", "") : this.inputProxy.removeAttribute("checked"); this.inputProxy.setAttribute("name", this.name); this.inputProxy.setAttribute("value", this.value); }; } handleLabelFocus(e) { if (!this.disabled && !this.el.contains(e.detail.interactedEl) && hasLabel(e.detail.labelEl, this.el)) { this.el.focus(); } else return; } onClick(e) { // prevent duplicate click events that occur // when the component is wrapped in a label and checkbox is clicked if ((!this.disabled && this.el.closest("label") && e.target === this.inputProxy) || (!this.el.closest("label") && e.target === this.el)) { this.updateSwitch(e); } } keyDownHandler(e) { const key = getKey(e.key); if (!this.disabled && (key === " " || key === "Enter")) { this.updateSwitch(e); } } switchWatcher() { this.switched ? this.inputProxy.setAttribute("checked", "") : this.inputProxy.removeAttribute("checked"); } connectedCallback() { this.setupProxyInput(); } disconnectedCallback() { this.observer.disconnect(); } componentWillRender() { this.syncProxyInputToThis(); } render() { const dir = getElementDir(this.el); return (h(Host, { "aria-checked": this.switched.toString(), dir: dir, tabIndex: this.disabled ? -1 : this.tabIndex }, h("div", { class: "track" }, h("div", { class: "handle" })))); } get tabIndex() { const hasTabIndex = this.el.hasAttribute("tabindex"); if (hasTabIndex) { return Number(this.el.getAttribute("tabindex")); } return 0; } 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.inputProxy.disabled = this.disabled; 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 }); } } updateSwitch(e) { e.preventDefault(); this.switched = !this.switched; this.calciteSwitchChange.emit({ switched: this.switched }); } static get is() { return "calcite-switch"; } static get encapsulation() { return "shadow"; } static get originalStyleUrls() { return { "$": ["calcite-switch.scss"] }; } static get styleUrls() { return { "$": ["calcite-switch.css"] }; } static get properties() { return { "disabled": { "type": "boolean", "mutable": false, "complexType": { "original": "boolean", "resolved": "boolean", "references": {} }, "required": false, "optional": true, "docs": { "tags": [], "text": "True if the switch is disabled" }, "attribute": "disabled", "reflect": true, "defaultValue": "false" }, "name": { "type": "string", "mutable": true, "complexType": { "original": "string", "resolved": "string", "references": {} }, "required": false, "optional": true, "docs": { "tags": [], "text": "The name of the checkbox input" }, "attribute": "name", "reflect": true, "defaultValue": "\"\"" }, "scale": { "type": "string", "mutable": false, "complexType": { "original": "Scale", "resolved": "\"l\" | \"m\" | \"s\"", "references": { "Scale": { "location": "import", "path": "../interfaces" } } }, "required": false, "optional": false, "docs": { "tags": [], "text": "The scale of the switch" }, "attribute": "scale", "reflect": true, "defaultValue": "\"m\"" }, "switched": { "type": "boolean", "mutable": true, "complexType": { "original": "boolean", "resolved": "boolean", "references": {} }, "required": false, "optional": true, "docs": { "tags": [], "text": "True if the switch is initially on" }, "attribute": "switched", "reflect": true, "defaultValue": "false" }, "theme": { "type": "string", "mutable": false, "complexType": { "original": "Theme", "resolved": "\"dark\" | \"light\"", "references": { "Theme": { "location": "import", "path": "../interfaces" } } }, "required": false, "optional": false, "docs": { "tags": [], "text": "The component's theme." }, "attribute": "theme", "reflect": true }, "value": { "type": "string", "mutable": true, "complexType": { "original": "string", "resolved": "string", "references": {} }, "required": false, "optional": true, "docs": { "tags": [], "text": "The value of the checkbox input" }, "attribute": "value", "reflect": true, "defaultValue": "\"\"" } }; } static get events() { return [{ "method": "calciteSwitchChange", "name": "calciteSwitchChange", "bubbles": true, "cancelable": true, "composed": true, "docs": { "tags": [], "text": "" }, "complexType": { "original": "any", "resolved": "any", "references": {} } }]; } static get elementRef() { return "el"; } static get watchers() { return [{ "propName": "switched", "methodName": "switchWatcher" }]; } static get listeners() { return [{ "name": "calciteLabelFocus", "method": "handleLabelFocus", "target": "window", "capture": false, "passive": false }, { "name": "click", "method": "onClick", "target": undefined, "capture": false, "passive": false }, { "name": "keydown", "method": "keyDownHandler", "target": undefined, "capture": false, "passive": false }]; } }