ExamplesPlaygroundReference Source

coral-spectrum/coral-component-shell/src/scripts/ShellUser.js

  1. /**
  2. * Copyright 2019 Adobe. All rights reserved.
  3. * This file is licensed to you under the Apache License, Version 2.0 (the "License");
  4. * you may not use this file except in compliance with the License. You may obtain a copy
  5. * of the License at http://www.apache.org/licenses/LICENSE-2.0
  6. *
  7. * Unless required by applicable law or agreed to in writing, software distributed under
  8. * the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR REPRESENTATIONS
  9. * OF ANY KIND, either express or implied. See the License for the specific language
  10. * governing permissions and limitations under the License.
  11. */
  12.  
  13. import {BaseComponent} from '../../../coral-base-component';
  14. import user from '../templates/user';
  15.  
  16. const CLASSNAME = '_coral-Shell-user';
  17.  
  18. /**
  19. Enumeration for {@link ShellUser} avatar options. Avatar assets should use one of those provided, when no asset is set
  20.  
  21. @typedef {Object} ShellUserAvatarEnum
  22.  
  23. @property {String} DEFAULT
  24. Default avatar, show user icon from icon font.
  25. */
  26. const avatar = {
  27. DEFAULT: 'UserCircleColor_Light'
  28. };
  29.  
  30. /**
  31. @class Coral.Shell.User
  32. @classdesc A Shell User component
  33. @htmltag coral-shell-user
  34. @extends {HTMLElement}
  35. @extends {BaseComponent}
  36. */
  37. class ShellUser extends BaseComponent(HTMLElement) {
  38. /** @ignore */
  39. constructor() {
  40. super();
  41.  
  42. // Prepare templates
  43. this._elements = {
  44. // Fetch or create the content zone elements
  45. name: this.querySelector('coral-shell-user-name') || document.createElement('coral-shell-user-name'),
  46. heading: this.querySelector('coral-shell-user-heading') || document.createElement('coral-shell-user-heading'),
  47. subheading: this.querySelector('coral-shell-user-subheading') || document.createElement('coral-shell-user-subheading'),
  48. content: this.querySelector('coral-shell-user-content') || document.createElement('coral-shell-user-content'),
  49. footer: this.querySelector('coral-shell-user-footer') || document.createElement('coral-shell-user-footer')
  50. };
  51.  
  52. user.call(this._elements, {icon: avatar.DEFAULT});
  53. }
  54.  
  55. /**
  56. Specifies the asset used inside the avatar view.
  57. See {@link Icon} for valid usage and icon names.
  58.  
  59. @type {String}
  60. @default ShellUserAvatarEnum.DEFAULT
  61. @htmlattribute avatar
  62. */
  63. get avatar() {
  64. return this._elements.avatar.icon;
  65. }
  66.  
  67. set avatar(value) {
  68. this._elements.avatar.icon = value;
  69. }
  70.  
  71. /**
  72. The name content zone of the user-menu.
  73.  
  74. @type {ShellUserName}
  75. @contentzone
  76. */
  77. get name() {
  78. return this._getContentZone(this._elements.name);
  79. }
  80.  
  81. set name(value) {
  82. this._setContentZone('content', value, {
  83. handle: 'name',
  84. tagName: 'coral-shell-user-name',
  85. insert: function (content) {
  86. this._elements.container.appendChild(content);
  87. }
  88. });
  89. }
  90.  
  91. /**
  92. The heading content zone of the user-menu.
  93.  
  94. @type {ShellUserHeading}
  95. @contentzone
  96. */
  97. get heading() {
  98. return this._getContentZone(this._elements.heading);
  99. }
  100.  
  101. set heading(value) {
  102. this._setContentZone('heading', value, {
  103. handle: 'heading',
  104. tagName: 'coral-shell-user-heading',
  105. insert: function (content) {
  106. this._elements.container.appendChild(content);
  107. }
  108. });
  109. }
  110.  
  111. /**
  112. The subheading content zone of the user-menu.
  113.  
  114. @type {ShellUserSubheading}
  115. @contentzone
  116. */
  117. get subheading() {
  118. return this._getContentZone(this._elements.subheading);
  119. }
  120.  
  121. set subheading(value) {
  122. this._setContentZone('subheading', value, {
  123. handle: 'subheading',
  124. tagName: 'coral-shell-user-subheading',
  125. insert: function (content) {
  126. this._elements.container.appendChild(content);
  127. }
  128. });
  129. }
  130.  
  131. /**
  132. The main content zone of the user-menu.
  133.  
  134. @type {ShellUserContent}
  135. @contentzone
  136. */
  137. get content() {
  138. return this._getContentZone(this._elements.content);
  139. }
  140.  
  141. set content(value) {
  142. this._setContentZone('content', value, {
  143. handle: 'content',
  144. tagName: 'coral-shell-user-content',
  145. insert: function (content) {
  146. // Empty content to hide it
  147. if (content.innerHTML.trim() === '') {
  148. content.innerHTML = '';
  149. }
  150.  
  151. this.appendChild(content);
  152. }
  153. });
  154. }
  155.  
  156. /**
  157. The footer content zone of the user-menu.
  158.  
  159. @type {ShellUserFooter}
  160. @contentzone
  161. */
  162. get footer() {
  163. return this._getContentZone(this._elements.footer);
  164. }
  165.  
  166. set footer(value) {
  167. this._setContentZone('footer', value, {
  168. handle: 'footer',
  169. tagName: 'coral-shell-user-footer',
  170. insert: function (content) {
  171. this.appendChild(content);
  172. }
  173. });
  174. }
  175.  
  176. get _contentZones() {
  177. return {
  178. 'coral-shell-user-name': 'name',
  179. 'coral-shell-user-heading': 'heading',
  180. 'coral-shell-user-subheading': 'subheading',
  181. 'coral-shell-user-content': 'content',
  182. 'coral-shell-user-footer': 'footer'
  183. };
  184. }
  185.  
  186. /** @ignore */
  187. static get observedAttributes() {
  188. return super.observedAttributes.concat(['avatar']);
  189. }
  190.  
  191. /**
  192. Returns {@link ShellUser} avatar options.
  193.  
  194. @return {ShellUserAvatarEnum}
  195. */
  196. static get avatar() {
  197. return avatar;
  198. }
  199.  
  200. /** @ignore */
  201. render() {
  202. super.render();
  203.  
  204. this.classList.add(CLASSNAME);
  205.  
  206. const frag = document.createDocumentFragment();
  207.  
  208. // Render template
  209. frag.appendChild(this._elements.container);
  210.  
  211. for (const contentZone in this._contentZones) {
  212. const element = this._elements[this._contentZones[contentZone]];
  213. // Remove it so we can process children
  214. if (element.parentNode) {
  215. element.parentNode.removeChild(element);
  216. }
  217. }
  218.  
  219. while (this.firstChild) {
  220. const child = this.firstChild;
  221. if (child.nodeType === Node.TEXT_NODE ||
  222. child.nodeType === Node.ELEMENT_NODE && child.getAttribute('handle') !== 'container') {
  223. // Add non-template elements to the content
  224. this._elements.content.appendChild(child);
  225. } else {
  226. // Remove anything else element
  227. this.removeChild(child);
  228. }
  229. }
  230.  
  231. this.appendChild(frag);
  232.  
  233. // Assign the content zones so the insert functions will be called
  234. for (const contentZone in this._contentZones) {
  235. const contentZoneName = this._contentZones[contentZone];
  236. const element = this._elements[this._contentZones[contentZone]];
  237.  
  238. /** @ignore */
  239. this[contentZoneName] = element;
  240. }
  241. }
  242. }
  243.  
  244. export default ShellUser;