link.js 7.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246
  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, Method, Prop } from "@stencil/core";
  7. import { focusElement, getElementDir } from "../../utils/dom";
  8. import { CSS_UTILITY } from "../../utils/resources";
  9. import { updateHostInteraction } from "../../utils/interactive";
  10. /** Any attributes placed on <calcite-link> component will propagate to the rendered child */
  11. /** Passing a 'href' will render an anchor link, instead of a span. Role will be set to link, or link, depending on this. */
  12. /** It is the consumers responsibility to add aria information, rel, target, for links, and any link attributes for form submission */
  13. /** @slot - A slot for adding text. */
  14. export class Link {
  15. constructor() {
  16. //--------------------------------------------------------------------------
  17. //
  18. // Properties
  19. //
  20. //--------------------------------------------------------------------------
  21. /** is the link disabled */
  22. this.disabled = false;
  23. /** Prompts the user to save the linked URL instead of navigating to it. Can be used with or without a value:
  24. * Without a value, the browser will suggest a filename/extension
  25. * See: https://developer.mozilla.org/en-US/docs/Web/HTML/Element/a#attr-download
  26. */
  27. this.download = false;
  28. //--------------------------------------------------------------------------
  29. //
  30. // Private Methods
  31. //
  32. //--------------------------------------------------------------------------
  33. this.storeTagRef = (el) => {
  34. this.childEl = el;
  35. };
  36. }
  37. //--------------------------------------------------------------------------
  38. //
  39. // Lifecycle
  40. //
  41. //--------------------------------------------------------------------------
  42. componentDidRender() {
  43. updateHostInteraction(this);
  44. }
  45. render() {
  46. const { download, el } = this;
  47. const dir = getElementDir(el);
  48. const childElType = this.href ? "a" : "span";
  49. const iconStartEl = (h("calcite-icon", { class: "calcite-link--icon icon-start", flipRtl: this.iconFlipRtl === "start" || this.iconFlipRtl === "both", icon: this.iconStart, scale: "s" }));
  50. const iconEndEl = (h("calcite-icon", { class: "calcite-link--icon icon-end", flipRtl: this.iconFlipRtl === "end" || this.iconFlipRtl === "both", icon: this.iconEnd, scale: "s" }));
  51. const Tag = childElType;
  52. const role = childElType === "span" ? "link" : null;
  53. const tabIndex = childElType === "span" ? 0 : null;
  54. return (h(Host, { role: "presentation" },
  55. h(Tag, { class: { [CSS_UTILITY.rtl]: dir === "rtl" },
  56. /*
  57. When the 'download' property of type 'boolean | string' is set to true, the value is "".
  58. This works around that issue for now.
  59. */
  60. download: Tag === "a" && (download === "" || download) ? download : null, href: Tag === "a" && this.href, ref: this.storeTagRef, rel: Tag === "a" && this.rel, role: role, tabIndex: tabIndex, target: Tag === "a" && this.target },
  61. this.iconStart ? iconStartEl : null,
  62. h("slot", null),
  63. this.iconEnd ? iconEndEl : null)));
  64. }
  65. //--------------------------------------------------------------------------
  66. //
  67. // Public Methods
  68. //
  69. //--------------------------------------------------------------------------
  70. /** Sets focus on the component. */
  71. async setFocus() {
  72. focusElement(this.childEl);
  73. }
  74. static get is() { return "calcite-link"; }
  75. static get encapsulation() { return "shadow"; }
  76. static get originalStyleUrls() { return {
  77. "$": ["link.scss"]
  78. }; }
  79. static get styleUrls() { return {
  80. "$": ["link.css"]
  81. }; }
  82. static get properties() { return {
  83. "disabled": {
  84. "type": "boolean",
  85. "mutable": false,
  86. "complexType": {
  87. "original": "boolean",
  88. "resolved": "boolean",
  89. "references": {}
  90. },
  91. "required": false,
  92. "optional": false,
  93. "docs": {
  94. "tags": [],
  95. "text": "is the link disabled"
  96. },
  97. "attribute": "disabled",
  98. "reflect": true,
  99. "defaultValue": "false"
  100. },
  101. "download": {
  102. "type": "any",
  103. "mutable": false,
  104. "complexType": {
  105. "original": "string | boolean",
  106. "resolved": "boolean | string",
  107. "references": {}
  108. },
  109. "required": false,
  110. "optional": false,
  111. "docs": {
  112. "tags": [],
  113. "text": "Prompts the user to save the linked URL instead of navigating to it. Can be used with or without a value:\nWithout a value, the browser will suggest a filename/extension\nSee: https://developer.mozilla.org/en-US/docs/Web/HTML/Element/a#attr-download"
  114. },
  115. "attribute": "download",
  116. "reflect": true,
  117. "defaultValue": "false"
  118. },
  119. "href": {
  120. "type": "string",
  121. "mutable": false,
  122. "complexType": {
  123. "original": "string",
  124. "resolved": "string",
  125. "references": {}
  126. },
  127. "required": false,
  128. "optional": true,
  129. "docs": {
  130. "tags": [],
  131. "text": "optionally pass a href - used to determine if the component should render as a link or an anchor"
  132. },
  133. "attribute": "href",
  134. "reflect": true
  135. },
  136. "iconEnd": {
  137. "type": "string",
  138. "mutable": false,
  139. "complexType": {
  140. "original": "string",
  141. "resolved": "string",
  142. "references": {}
  143. },
  144. "required": false,
  145. "optional": true,
  146. "docs": {
  147. "tags": [],
  148. "text": "optionally pass an icon to display at the end of a button - accepts calcite ui icon names"
  149. },
  150. "attribute": "icon-end",
  151. "reflect": true
  152. },
  153. "iconFlipRtl": {
  154. "type": "string",
  155. "mutable": false,
  156. "complexType": {
  157. "original": "FlipContext",
  158. "resolved": "\"both\" | \"end\" | \"start\"",
  159. "references": {
  160. "FlipContext": {
  161. "location": "import",
  162. "path": "../interfaces"
  163. }
  164. }
  165. },
  166. "required": false,
  167. "optional": true,
  168. "docs": {
  169. "tags": [],
  170. "text": "flip the icon(s) in rtl"
  171. },
  172. "attribute": "icon-flip-rtl",
  173. "reflect": true
  174. },
  175. "iconStart": {
  176. "type": "string",
  177. "mutable": false,
  178. "complexType": {
  179. "original": "string",
  180. "resolved": "string",
  181. "references": {}
  182. },
  183. "required": false,
  184. "optional": true,
  185. "docs": {
  186. "tags": [],
  187. "text": "optionally pass an icon to display at the start of a button - accepts calcite ui icon names"
  188. },
  189. "attribute": "icon-start",
  190. "reflect": true
  191. },
  192. "rel": {
  193. "type": "string",
  194. "mutable": false,
  195. "complexType": {
  196. "original": "string",
  197. "resolved": "string",
  198. "references": {}
  199. },
  200. "required": false,
  201. "optional": true,
  202. "docs": {
  203. "tags": [],
  204. "text": "The rel attribute to apply to the hyperlink"
  205. },
  206. "attribute": "rel",
  207. "reflect": false
  208. },
  209. "target": {
  210. "type": "string",
  211. "mutable": false,
  212. "complexType": {
  213. "original": "string",
  214. "resolved": "string",
  215. "references": {}
  216. },
  217. "required": false,
  218. "optional": true,
  219. "docs": {
  220. "tags": [],
  221. "text": "The target attribute to apply to the hyperlink"
  222. },
  223. "attribute": "target",
  224. "reflect": false
  225. }
  226. }; }
  227. static get methods() { return {
  228. "setFocus": {
  229. "complexType": {
  230. "signature": "() => Promise<void>",
  231. "parameters": [],
  232. "references": {
  233. "Promise": {
  234. "location": "global"
  235. }
  236. },
  237. "return": "Promise<void>"
  238. },
  239. "docs": {
  240. "text": "Sets focus on the component.",
  241. "tags": []
  242. }
  243. }
  244. }; }
  245. static get elementRef() { return "el"; }
  246. }