block-section.js 7.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232
  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.97
  5. */
  6. import { h, Host } from "@stencil/core";
  7. import { getElementDir, toAriaBoolean } from "../../utils/dom";
  8. import { CSS, ICONS, TEXT } from "./resources";
  9. import { guid } from "../../utils/guid";
  10. import { isActivationKey } from "../../utils/key";
  11. /**
  12. * @slot - A slot for adding content to the component.
  13. */
  14. export class BlockSection {
  15. constructor() {
  16. /**
  17. * When `true`, expands the component and its contents.
  18. */
  19. this.open = false;
  20. /**
  21. * Specifies the component's toggle display -
  22. *
  23. * `"button"` (selectable header), or
  24. *
  25. * `"switch"` (toggle switch).
  26. */
  27. this.toggleDisplay = "button";
  28. this.guid = guid();
  29. // --------------------------------------------------------------------------
  30. //
  31. // Private Methods
  32. //
  33. // --------------------------------------------------------------------------
  34. this.handleHeaderKeyDown = (event) => {
  35. if (isActivationKey(event.key)) {
  36. this.toggleSection();
  37. event.preventDefault();
  38. event.stopPropagation();
  39. }
  40. };
  41. this.toggleSection = () => {
  42. this.open = !this.open;
  43. this.calciteBlockSectionToggle.emit();
  44. };
  45. }
  46. // --------------------------------------------------------------------------
  47. //
  48. // Render Methods
  49. //
  50. // --------------------------------------------------------------------------
  51. renderStatusIcon() {
  52. var _a;
  53. const { status } = this;
  54. const statusIcon = (_a = ICONS[status]) !== null && _a !== void 0 ? _a : false;
  55. const statusIconClasses = {
  56. [CSS.statusIcon]: true,
  57. [CSS.valid]: status == "valid",
  58. [CSS.invalid]: status == "invalid"
  59. };
  60. return !!statusIcon ? (h("calcite-icon", { class: statusIconClasses, icon: statusIcon, scale: "s" })) : null;
  61. }
  62. render() {
  63. const { el, intlCollapse, intlExpand, open, text, toggleDisplay } = this;
  64. const dir = getElementDir(el);
  65. const arrowIcon = open
  66. ? ICONS.menuOpen
  67. : dir === "rtl"
  68. ? ICONS.menuClosedLeft
  69. : ICONS.menuClosedRight;
  70. const toggleLabel = open ? intlCollapse || TEXT.collapse : intlExpand || TEXT.expand;
  71. const { guid } = this;
  72. const regionId = `${guid}-region`;
  73. const buttonId = `${guid}-button`;
  74. const headerNode = toggleDisplay === "switch" ? (h("div", { "aria-controls": regionId, "aria-label": toggleLabel, class: {
  75. [CSS.toggle]: true,
  76. [CSS.toggleSwitch]: true
  77. }, id: buttonId, onClick: this.toggleSection, onKeyDown: this.handleHeaderKeyDown, tabIndex: 0, title: toggleLabel }, h("div", { class: CSS.toggleSwitchContent }, h("span", { class: CSS.toggleSwitchText }, text)), h("calcite-switch", { checked: open, label: toggleLabel, scale: "s", tabIndex: -1 }), this.renderStatusIcon())) : (h("button", { "aria-controls": regionId, "aria-label": toggleLabel, class: {
  78. [CSS.sectionHeader]: true,
  79. [CSS.toggle]: true
  80. }, id: buttonId, name: toggleLabel, onClick: this.toggleSection }, h("calcite-icon", { icon: arrowIcon, scale: "s" }), h("span", { class: CSS.sectionHeaderText }, text), this.renderStatusIcon()));
  81. return (h(Host, null, headerNode, h("section", { "aria-expanded": toAriaBoolean(open), "aria-labelledby": buttonId, class: CSS.content, hidden: !open, id: regionId }, h("slot", null))));
  82. }
  83. static get is() { return "calcite-block-section"; }
  84. static get encapsulation() { return "shadow"; }
  85. static get originalStyleUrls() {
  86. return {
  87. "$": ["block-section.scss"]
  88. };
  89. }
  90. static get styleUrls() {
  91. return {
  92. "$": ["block-section.css"]
  93. };
  94. }
  95. static get properties() {
  96. return {
  97. "intlCollapse": {
  98. "type": "string",
  99. "mutable": false,
  100. "complexType": {
  101. "original": "string",
  102. "resolved": "string",
  103. "references": {}
  104. },
  105. "required": false,
  106. "optional": true,
  107. "docs": {
  108. "tags": [],
  109. "text": "Accessible name for the component's collapse button."
  110. },
  111. "attribute": "intl-collapse",
  112. "reflect": false
  113. },
  114. "intlExpand": {
  115. "type": "string",
  116. "mutable": false,
  117. "complexType": {
  118. "original": "string",
  119. "resolved": "string",
  120. "references": {}
  121. },
  122. "required": false,
  123. "optional": true,
  124. "docs": {
  125. "tags": [],
  126. "text": "Accessible name for the component's expand button."
  127. },
  128. "attribute": "intl-expand",
  129. "reflect": false
  130. },
  131. "open": {
  132. "type": "boolean",
  133. "mutable": true,
  134. "complexType": {
  135. "original": "boolean",
  136. "resolved": "boolean",
  137. "references": {}
  138. },
  139. "required": false,
  140. "optional": false,
  141. "docs": {
  142. "tags": [],
  143. "text": "When `true`, expands the component and its contents."
  144. },
  145. "attribute": "open",
  146. "reflect": true,
  147. "defaultValue": "false"
  148. },
  149. "status": {
  150. "type": "string",
  151. "mutable": false,
  152. "complexType": {
  153. "original": "Status",
  154. "resolved": "\"idle\" | \"invalid\" | \"valid\"",
  155. "references": {
  156. "Status": {
  157. "location": "import",
  158. "path": "../interfaces"
  159. }
  160. }
  161. },
  162. "required": false,
  163. "optional": true,
  164. "docs": {
  165. "tags": [],
  166. "text": "Displays a status-related indicator icon."
  167. },
  168. "attribute": "status",
  169. "reflect": true
  170. },
  171. "text": {
  172. "type": "string",
  173. "mutable": false,
  174. "complexType": {
  175. "original": "string",
  176. "resolved": "string",
  177. "references": {}
  178. },
  179. "required": false,
  180. "optional": false,
  181. "docs": {
  182. "tags": [],
  183. "text": "The component header text."
  184. },
  185. "attribute": "text",
  186. "reflect": false
  187. },
  188. "toggleDisplay": {
  189. "type": "string",
  190. "mutable": false,
  191. "complexType": {
  192. "original": "BlockSectionToggleDisplay",
  193. "resolved": "\"button\" | \"switch\"",
  194. "references": {
  195. "BlockSectionToggleDisplay": {
  196. "location": "import",
  197. "path": "./interfaces"
  198. }
  199. }
  200. },
  201. "required": false,
  202. "optional": false,
  203. "docs": {
  204. "tags": [],
  205. "text": "Specifies the component's toggle display -\n\n`\"button\"` (selectable header), or\n\n`\"switch\"` (toggle switch)."
  206. },
  207. "attribute": "toggle-display",
  208. "reflect": true,
  209. "defaultValue": "\"button\""
  210. }
  211. };
  212. }
  213. static get events() {
  214. return [{
  215. "method": "calciteBlockSectionToggle",
  216. "name": "calciteBlockSectionToggle",
  217. "bubbles": true,
  218. "cancelable": false,
  219. "composed": true,
  220. "docs": {
  221. "tags": [],
  222. "text": "Emits when the header has been clicked."
  223. },
  224. "complexType": {
  225. "original": "void",
  226. "resolved": "void",
  227. "references": {}
  228. }
  229. }];
  230. }
  231. static get elementRef() { return "el"; }
  232. }