switch.js 7.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286
  1. /*!
  2. * All material copyright ESRI, All Rights Reserved, unless otherwise specified.
  3. * See https://github.com/Esri/calcite-components/blob/master/LICENSE.md for details.
  4. * v1.0.0-beta.82
  5. */
  6. import { Component, Element, Event, h, Host, Method, Prop, Watch } from "@stencil/core";
  7. import { focusElement, toAriaBoolean } from "../../utils/dom";
  8. import { connectLabel, disconnectLabel, getLabelText } from "../../utils/label";
  9. import { connectForm, disconnectForm, HiddenFormInputSlot } from "../../utils/form";
  10. import { updateHostInteraction } from "../../utils/interactive";
  11. export class Switch {
  12. constructor() {
  13. //--------------------------------------------------------------------------
  14. //
  15. // Properties
  16. //
  17. //--------------------------------------------------------------------------
  18. /** True if the switch is disabled */
  19. this.disabled = false;
  20. /** The scale of the switch */
  21. this.scale = "m";
  22. /** True if the switch is initially on
  23. * @deprecated use 'checked' instead.
  24. */
  25. this.switched = false;
  26. /** True if the switch is initially on */
  27. this.checked = false;
  28. //--------------------------------------------------------------------------
  29. //
  30. // Private Methods
  31. //
  32. //--------------------------------------------------------------------------
  33. this.keyDownHandler = (e) => {
  34. const key = e.key;
  35. if (!this.disabled && (key === " " || key === "Enter")) {
  36. this.toggle();
  37. e.preventDefault();
  38. }
  39. };
  40. this.clickHandler = () => {
  41. this.toggle();
  42. };
  43. this.setSwitchEl = (el) => {
  44. this.switchEl = el;
  45. };
  46. }
  47. switchedWatcher(switched) {
  48. this.checked = switched;
  49. }
  50. //--------------------------------------------------------------------------
  51. //
  52. // Public Methods
  53. //
  54. //--------------------------------------------------------------------------
  55. /** Sets focus on the component. */
  56. async setFocus() {
  57. focusElement(this.switchEl);
  58. }
  59. onLabelClick() {
  60. if (!this.disabled) {
  61. this.toggle();
  62. this.setFocus();
  63. }
  64. }
  65. toggle() {
  66. this.checked = !this.checked;
  67. this.calciteSwitchChange.emit({
  68. // todo: We should remove emmitting redudant props in event payload.
  69. // https://github.com/Esri/calcite-components/issues/3163
  70. switched: this.checked
  71. });
  72. }
  73. //--------------------------------------------------------------------------
  74. //
  75. // Lifecycle
  76. //
  77. //--------------------------------------------------------------------------
  78. connectedCallback() {
  79. const initiallyChecked = this.checked || this.switched;
  80. if (initiallyChecked) {
  81. // if either prop is set, we ensure both are synced initially
  82. this.switched = this.checked = initiallyChecked;
  83. }
  84. connectLabel(this);
  85. connectForm(this);
  86. }
  87. disconnectedCallback() {
  88. disconnectLabel(this);
  89. disconnectForm(this);
  90. }
  91. componentDidRender() {
  92. updateHostInteraction(this);
  93. }
  94. // --------------------------------------------------------------------------
  95. //
  96. // Render Methods
  97. //
  98. // --------------------------------------------------------------------------
  99. render() {
  100. return (h(Host, { onClick: this.clickHandler, onKeyDown: this.keyDownHandler },
  101. h("div", { "aria-checked": toAriaBoolean(this.checked), "aria-label": getLabelText(this), class: "container", ref: this.setSwitchEl, role: "switch", tabIndex: 0 },
  102. h("div", { class: "track" },
  103. h("div", { class: "handle" })),
  104. h(HiddenFormInputSlot, { component: this }))));
  105. }
  106. static get is() { return "calcite-switch"; }
  107. static get encapsulation() { return "shadow"; }
  108. static get originalStyleUrls() { return {
  109. "$": ["switch.scss"]
  110. }; }
  111. static get styleUrls() { return {
  112. "$": ["switch.css"]
  113. }; }
  114. static get properties() { return {
  115. "disabled": {
  116. "type": "boolean",
  117. "mutable": false,
  118. "complexType": {
  119. "original": "boolean",
  120. "resolved": "boolean",
  121. "references": {}
  122. },
  123. "required": false,
  124. "optional": false,
  125. "docs": {
  126. "tags": [],
  127. "text": "True if the switch is disabled"
  128. },
  129. "attribute": "disabled",
  130. "reflect": true,
  131. "defaultValue": "false"
  132. },
  133. "label": {
  134. "type": "string",
  135. "mutable": false,
  136. "complexType": {
  137. "original": "string",
  138. "resolved": "string",
  139. "references": {}
  140. },
  141. "required": false,
  142. "optional": true,
  143. "docs": {
  144. "tags": [],
  145. "text": "Applies to the aria-label attribute on the switch"
  146. },
  147. "attribute": "label",
  148. "reflect": false
  149. },
  150. "name": {
  151. "type": "string",
  152. "mutable": false,
  153. "complexType": {
  154. "original": "string",
  155. "resolved": "string",
  156. "references": {}
  157. },
  158. "required": false,
  159. "optional": false,
  160. "docs": {
  161. "tags": [],
  162. "text": "The name of the switch input"
  163. },
  164. "attribute": "name",
  165. "reflect": true
  166. },
  167. "scale": {
  168. "type": "string",
  169. "mutable": false,
  170. "complexType": {
  171. "original": "Scale",
  172. "resolved": "\"l\" | \"m\" | \"s\"",
  173. "references": {
  174. "Scale": {
  175. "location": "import",
  176. "path": "../interfaces"
  177. }
  178. }
  179. },
  180. "required": false,
  181. "optional": false,
  182. "docs": {
  183. "tags": [],
  184. "text": "The scale of the switch"
  185. },
  186. "attribute": "scale",
  187. "reflect": true,
  188. "defaultValue": "\"m\""
  189. },
  190. "switched": {
  191. "type": "boolean",
  192. "mutable": true,
  193. "complexType": {
  194. "original": "boolean",
  195. "resolved": "boolean",
  196. "references": {}
  197. },
  198. "required": false,
  199. "optional": false,
  200. "docs": {
  201. "tags": [{
  202. "name": "deprecated",
  203. "text": "use 'checked' instead."
  204. }],
  205. "text": "True if the switch is initially on"
  206. },
  207. "attribute": "switched",
  208. "reflect": false,
  209. "defaultValue": "false"
  210. },
  211. "checked": {
  212. "type": "boolean",
  213. "mutable": true,
  214. "complexType": {
  215. "original": "boolean",
  216. "resolved": "boolean",
  217. "references": {}
  218. },
  219. "required": false,
  220. "optional": false,
  221. "docs": {
  222. "tags": [],
  223. "text": "True if the switch is initially on"
  224. },
  225. "attribute": "checked",
  226. "reflect": true,
  227. "defaultValue": "false"
  228. },
  229. "value": {
  230. "type": "any",
  231. "mutable": false,
  232. "complexType": {
  233. "original": "any",
  234. "resolved": "any",
  235. "references": {}
  236. },
  237. "required": false,
  238. "optional": false,
  239. "docs": {
  240. "tags": [],
  241. "text": "The value of the switch input"
  242. },
  243. "attribute": "value",
  244. "reflect": false
  245. }
  246. }; }
  247. static get events() { return [{
  248. "method": "calciteSwitchChange",
  249. "name": "calciteSwitchChange",
  250. "bubbles": true,
  251. "cancelable": true,
  252. "composed": true,
  253. "docs": {
  254. "tags": [],
  255. "text": "Fires when the checked value has changed."
  256. },
  257. "complexType": {
  258. "original": "any",
  259. "resolved": "any",
  260. "references": {}
  261. }
  262. }]; }
  263. static get methods() { return {
  264. "setFocus": {
  265. "complexType": {
  266. "signature": "() => Promise<void>",
  267. "parameters": [],
  268. "references": {
  269. "Promise": {
  270. "location": "global"
  271. }
  272. },
  273. "return": "Promise<void>"
  274. },
  275. "docs": {
  276. "text": "Sets focus on the component.",
  277. "tags": []
  278. }
  279. }
  280. }; }
  281. static get elementRef() { return "el"; }
  282. static get watchers() { return [{
  283. "propName": "switched",
  284. "methodName": "switchedWatcher"
  285. }]; }
  286. }