loader.js 7.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244
  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, h, Host, Prop } from "@stencil/core";
  7. import { guid } from "../../utils/guid";
  8. export class Loader {
  9. constructor() {
  10. //--------------------------------------------------------------------------
  11. //
  12. // Properties
  13. //
  14. //--------------------------------------------------------------------------
  15. /** Show the loader */
  16. this.active = false;
  17. /** Inline loaders are smaller and will appear to the left of the text */
  18. this.inline = false;
  19. /** Speficy the scale of the loader. Defaults to "m" */
  20. this.scale = "m";
  21. /** Percent complete of 100, only valid for determinate indicators */
  22. this.value = 0;
  23. /** Text which should appear under the loading indicator (optional) */
  24. this.text = "";
  25. /** Turn off spacing around the loader */
  26. this.noPadding = false;
  27. }
  28. //--------------------------------------------------------------------------
  29. //
  30. // Lifecycle
  31. //
  32. //--------------------------------------------------------------------------
  33. render() {
  34. const { el, inline, label, scale, text, type, value } = this;
  35. const id = el.id || guid();
  36. const radiusRatio = 0.45;
  37. const size = inline ? this.getInlineSize(scale) : this.getSize(scale);
  38. const radius = size * radiusRatio;
  39. const viewbox = `0 0 ${size} ${size}`;
  40. const isDeterminate = type === "determinate";
  41. const circumference = 2 * radius * Math.PI;
  42. const progress = (value / 100) * circumference;
  43. const remaining = circumference - progress;
  44. const valueNow = Math.floor(value);
  45. const hostAttributes = {
  46. "aria-valuenow": valueNow,
  47. "aria-valuemin": 0,
  48. "aria-valuemax": 100,
  49. complete: valueNow === 100
  50. };
  51. const svgAttributes = { r: radius, cx: size / 2, cy: size / 2 };
  52. const determinateStyle = { "stroke-dasharray": `${progress} ${remaining}` };
  53. return (h(Host, Object.assign({ "aria-label": label, id: id, role: "progressbar" }, (isDeterminate ? hostAttributes : {})),
  54. h("div", { class: "loader__svgs" },
  55. h("svg", { class: "loader__svg loader__svg--1", viewBox: viewbox },
  56. h("circle", Object.assign({}, svgAttributes))),
  57. h("svg", { class: "loader__svg loader__svg--2", viewBox: viewbox },
  58. h("circle", Object.assign({}, svgAttributes))),
  59. h("svg", Object.assign({ class: "loader__svg loader__svg--3", viewBox: viewbox }, (isDeterminate ? { style: determinateStyle } : {})),
  60. h("circle", Object.assign({}, svgAttributes)))),
  61. text && h("div", { class: "loader__text" }, text),
  62. isDeterminate && h("div", { class: "loader__percentage" }, value)));
  63. }
  64. //--------------------------------------------------------------------------
  65. //
  66. // Private Methods
  67. //
  68. //--------------------------------------------------------------------------
  69. /**
  70. * Return the proper sizes based on the scale property
  71. */
  72. getSize(scale) {
  73. return {
  74. s: 32,
  75. m: 56,
  76. l: 80
  77. }[scale];
  78. }
  79. getInlineSize(scale) {
  80. return {
  81. s: 12,
  82. m: 16,
  83. l: 20
  84. }[scale];
  85. }
  86. static get is() { return "calcite-loader"; }
  87. static get encapsulation() { return "shadow"; }
  88. static get originalStyleUrls() { return {
  89. "$": ["loader.scss"]
  90. }; }
  91. static get styleUrls() { return {
  92. "$": ["loader.css"]
  93. }; }
  94. static get properties() { return {
  95. "active": {
  96. "type": "boolean",
  97. "mutable": false,
  98. "complexType": {
  99. "original": "boolean",
  100. "resolved": "boolean",
  101. "references": {}
  102. },
  103. "required": false,
  104. "optional": false,
  105. "docs": {
  106. "tags": [],
  107. "text": "Show the loader"
  108. },
  109. "attribute": "active",
  110. "reflect": true,
  111. "defaultValue": "false"
  112. },
  113. "inline": {
  114. "type": "boolean",
  115. "mutable": false,
  116. "complexType": {
  117. "original": "boolean",
  118. "resolved": "boolean",
  119. "references": {}
  120. },
  121. "required": false,
  122. "optional": false,
  123. "docs": {
  124. "tags": [],
  125. "text": "Inline loaders are smaller and will appear to the left of the text"
  126. },
  127. "attribute": "inline",
  128. "reflect": true,
  129. "defaultValue": "false"
  130. },
  131. "label": {
  132. "type": "string",
  133. "mutable": false,
  134. "complexType": {
  135. "original": "string",
  136. "resolved": "string",
  137. "references": {}
  138. },
  139. "required": true,
  140. "optional": false,
  141. "docs": {
  142. "tags": [],
  143. "text": "Accessible name for the component"
  144. },
  145. "attribute": "label",
  146. "reflect": false
  147. },
  148. "scale": {
  149. "type": "string",
  150. "mutable": false,
  151. "complexType": {
  152. "original": "Scale",
  153. "resolved": "\"l\" | \"m\" | \"s\"",
  154. "references": {
  155. "Scale": {
  156. "location": "import",
  157. "path": "../interfaces"
  158. }
  159. }
  160. },
  161. "required": false,
  162. "optional": false,
  163. "docs": {
  164. "tags": [],
  165. "text": "Speficy the scale of the loader. Defaults to \"m\""
  166. },
  167. "attribute": "scale",
  168. "reflect": true,
  169. "defaultValue": "\"m\""
  170. },
  171. "type": {
  172. "type": "string",
  173. "mutable": false,
  174. "complexType": {
  175. "original": "\"indeterminate\" | \"determinate\"",
  176. "resolved": "\"determinate\" | \"indeterminate\"",
  177. "references": {}
  178. },
  179. "required": false,
  180. "optional": false,
  181. "docs": {
  182. "tags": [],
  183. "text": "Use indeterminate if finding actual progress value is impossible"
  184. },
  185. "attribute": "type",
  186. "reflect": true
  187. },
  188. "value": {
  189. "type": "number",
  190. "mutable": false,
  191. "complexType": {
  192. "original": "number",
  193. "resolved": "number",
  194. "references": {}
  195. },
  196. "required": false,
  197. "optional": false,
  198. "docs": {
  199. "tags": [],
  200. "text": "Percent complete of 100, only valid for determinate indicators"
  201. },
  202. "attribute": "value",
  203. "reflect": false,
  204. "defaultValue": "0"
  205. },
  206. "text": {
  207. "type": "string",
  208. "mutable": false,
  209. "complexType": {
  210. "original": "string",
  211. "resolved": "string",
  212. "references": {}
  213. },
  214. "required": false,
  215. "optional": false,
  216. "docs": {
  217. "tags": [],
  218. "text": "Text which should appear under the loading indicator (optional)"
  219. },
  220. "attribute": "text",
  221. "reflect": false,
  222. "defaultValue": "\"\""
  223. },
  224. "noPadding": {
  225. "type": "boolean",
  226. "mutable": false,
  227. "complexType": {
  228. "original": "boolean",
  229. "resolved": "boolean",
  230. "references": {}
  231. },
  232. "required": false,
  233. "optional": false,
  234. "docs": {
  235. "tags": [],
  236. "text": "Turn off spacing around the loader"
  237. },
  238. "attribute": "no-padding",
  239. "reflect": false,
  240. "defaultValue": "false"
  241. }
  242. }; }
  243. static get elementRef() { return "el"; }
  244. }