tab.js 6.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240
  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, Prop, Element, Listen, Method, Event, h, State, Host } from "@stencil/core";
  7. import { guid } from "../../utils/guid";
  8. import { nodeListToArray, toAriaBoolean } from "../../utils/dom";
  9. /**
  10. * @slot - A slot for adding custom content.
  11. */
  12. export class Tab {
  13. constructor() {
  14. /**
  15. * Show this tab
  16. */
  17. this.active = false;
  18. /** @internal Parent tabs component scale value */
  19. this.scale = "m";
  20. this.guid = `calcite-tab-title-${guid()}`;
  21. }
  22. //--------------------------------------------------------------------------
  23. //
  24. // Lifecycle
  25. //
  26. //--------------------------------------------------------------------------
  27. render() {
  28. const id = this.el.id || this.guid;
  29. return (h(Host, { "aria-expanded": toAriaBoolean(this.active), "aria-labelledby": this.labeledBy, id: id, role: "tabpanel" },
  30. h("section", null,
  31. h("slot", null))));
  32. }
  33. connectedCallback() {
  34. this.parentTabsEl = this.el.closest("calcite-tabs");
  35. }
  36. componentDidLoad() {
  37. this.calciteTabRegister.emit();
  38. }
  39. componentWillRender() {
  40. var _a;
  41. this.scale = (_a = this.parentTabsEl) === null || _a === void 0 ? void 0 : _a.scale;
  42. }
  43. disconnectedCallback() {
  44. var _a;
  45. // Dispatching to body in order to be listened by other elements that are still connected to the DOM.
  46. (_a = document.body) === null || _a === void 0 ? void 0 : _a.dispatchEvent(new CustomEvent("calciteTabUnregister", {
  47. detail: this.el
  48. }));
  49. }
  50. //--------------------------------------------------------------------------
  51. //
  52. // Event Listeners
  53. //
  54. //--------------------------------------------------------------------------
  55. internalTabChangeHandler(event) {
  56. const targetTabsEl = event
  57. .composedPath()
  58. .find((el) => el.tagName === "CALCITE-TABS");
  59. // to allow `<calcite-tabs>` to be nested we need to make sure this
  60. // `calciteTabChange` event was actually fired from a within the same
  61. // `<calcite-tabs>` that is the a parent of this tab.
  62. if (targetTabsEl !== this.parentTabsEl) {
  63. return;
  64. }
  65. if (this.tab) {
  66. this.active = this.tab === event.detail.tab;
  67. }
  68. else {
  69. this.getTabIndex().then((index) => {
  70. this.active = index === event.detail.tab;
  71. });
  72. }
  73. }
  74. //--------------------------------------------------------------------------
  75. //
  76. // Public Methods
  77. //
  78. //--------------------------------------------------------------------------
  79. /**
  80. * Return the index of this tab within the tab array
  81. */
  82. async getTabIndex() {
  83. return Array.prototype.indexOf.call(nodeListToArray(this.el.parentElement.children).filter((e) => e.matches("calcite-tab")), this.el);
  84. }
  85. //--------------------------------------------------------------------------
  86. //
  87. // Private Methods
  88. //
  89. //--------------------------------------------------------------------------
  90. /**
  91. * @internal
  92. */
  93. async updateAriaInfo(tabIds = [], titleIds = []) {
  94. this.labeledBy = titleIds[tabIds.indexOf(this.el.id)] || null;
  95. }
  96. static get is() { return "calcite-tab"; }
  97. static get encapsulation() { return "shadow"; }
  98. static get originalStyleUrls() { return {
  99. "$": ["tab.scss"]
  100. }; }
  101. static get styleUrls() { return {
  102. "$": ["tab.css"]
  103. }; }
  104. static get properties() { return {
  105. "tab": {
  106. "type": "string",
  107. "mutable": false,
  108. "complexType": {
  109. "original": "string",
  110. "resolved": "string",
  111. "references": {}
  112. },
  113. "required": false,
  114. "optional": false,
  115. "docs": {
  116. "tags": [],
  117. "text": "Optionally include a unique name for this tab,\nbe sure to also set this name on the associated title."
  118. },
  119. "attribute": "tab",
  120. "reflect": true
  121. },
  122. "active": {
  123. "type": "boolean",
  124. "mutable": true,
  125. "complexType": {
  126. "original": "boolean",
  127. "resolved": "boolean",
  128. "references": {}
  129. },
  130. "required": false,
  131. "optional": false,
  132. "docs": {
  133. "tags": [],
  134. "text": "Show this tab"
  135. },
  136. "attribute": "active",
  137. "reflect": true,
  138. "defaultValue": "false"
  139. },
  140. "scale": {
  141. "type": "string",
  142. "mutable": true,
  143. "complexType": {
  144. "original": "Scale",
  145. "resolved": "\"l\" | \"m\" | \"s\"",
  146. "references": {
  147. "Scale": {
  148. "location": "import",
  149. "path": "../interfaces"
  150. }
  151. }
  152. },
  153. "required": false,
  154. "optional": false,
  155. "docs": {
  156. "tags": [{
  157. "name": "internal",
  158. "text": "Parent tabs component scale value"
  159. }],
  160. "text": ""
  161. },
  162. "attribute": "scale",
  163. "reflect": true,
  164. "defaultValue": "\"m\""
  165. }
  166. }; }
  167. static get states() { return {
  168. "labeledBy": {}
  169. }; }
  170. static get events() { return [{
  171. "method": "calciteTabRegister",
  172. "name": "calciteTabRegister",
  173. "bubbles": true,
  174. "cancelable": true,
  175. "composed": true,
  176. "docs": {
  177. "tags": [{
  178. "name": "internal",
  179. "text": undefined
  180. }],
  181. "text": ""
  182. },
  183. "complexType": {
  184. "original": "any",
  185. "resolved": "any",
  186. "references": {}
  187. }
  188. }]; }
  189. static get methods() { return {
  190. "getTabIndex": {
  191. "complexType": {
  192. "signature": "() => Promise<number>",
  193. "parameters": [],
  194. "references": {
  195. "Promise": {
  196. "location": "global"
  197. }
  198. },
  199. "return": "Promise<number>"
  200. },
  201. "docs": {
  202. "text": "Return the index of this tab within the tab array",
  203. "tags": []
  204. }
  205. },
  206. "updateAriaInfo": {
  207. "complexType": {
  208. "signature": "(tabIds?: string[], titleIds?: string[]) => Promise<void>",
  209. "parameters": [{
  210. "tags": [],
  211. "text": ""
  212. }, {
  213. "tags": [],
  214. "text": ""
  215. }],
  216. "references": {
  217. "Promise": {
  218. "location": "global"
  219. }
  220. },
  221. "return": "Promise<void>"
  222. },
  223. "docs": {
  224. "text": "",
  225. "tags": [{
  226. "name": "internal",
  227. "text": undefined
  228. }]
  229. }
  230. }
  231. }; }
  232. static get elementRef() { return "el"; }
  233. static get listeners() { return [{
  234. "name": "calciteInternalTabChange",
  235. "method": "internalTabChangeHandler",
  236. "target": "body",
  237. "capture": false,
  238. "passive": false
  239. }]; }
  240. }