UNPKG

hologram-web-library

Version:
245 lines (204 loc) 6.35 kB
import HTMLParsedElement from './hw-common'; import HWIcons from "./hw-icons"; /** * NOTE(Tayfun): This is a container/parent element not the actual * element, this element creates the actual element which is the button * for this component. We should keep this in mind while working with * grid or flex layouts */ export default class HWButton extends HTMLParsedElement { appearance; status; size; type; styles; containerStyles; disabled; button; constructor() { super(); this.appearance = null; this.status = null; this.size = null; this.type = null; this.button = null; this.styles = null; this.containerStyles = null; this.disabled = null; } parsedCallback() { this.appearance = this.getAttribute('appearance'); this.status = this.getAttribute('status'); this.size = this.getAttribute('size'); this.styles = this.getAttribute('styles'); this.containerStyles = this.getAttribute('container-styles'); this.disabled = this.getAttribute('disabled'); this.button = document.createElement('button'); this.button.type = 'button'; const { button } = this; const rightIcon = this.getAttribute('right-icon') || ''; const leftIcon = this.getAttribute('left-icon') || ''; const rightIconColor = this.getAttribute('right-icon-color' || ''); const leftIconColor = this.getAttribute('left-icon-color' || ''); const iconStyles = this.getAttribute('icon-styles' || ''); const icons = this.getIcons(leftIcon, rightIcon, iconStyles); this.setButtonStyles(button, this.appearance, this.status, this.size, this.styles); this.setButtonDisabledState(button, this.disabled); const { childNodes } = this; const childList = []; // NOTE(Tayfun): we are pushing all the child nodes to // another array to prevent changing the size of 'children' // array during the 'removeChild' operation, otherwise we // are losing some items due to size change of children array // while looping throught it for (let i = 0; i < childNodes.length; i += 1) { childList.push(childNodes[i]); } // we saved all the childs into a temporary array that is not // seeing any add/remove operation so the size is not changing for (let i = 0; i < childList.length; i += 1) { const child = childList[i]; this.removeChild(child); button.appendChild(child); } const { svgLeft, svgRight } = icons; if (svgLeft) { if (button.firstChild) { button.insertBefore(svgLeft, button.firstChild); } else { button.appendChild(svgLeft); } } if (svgRight) { button.appendChild(svgRight); } if (rightIconColor) { icons.rightIconColor = rightIconColor; } if (leftIconColor) { icons.leftIconColor = leftIconColor; } this.appendChild(button); this.setContainerStyles(this, this.containerStyles); } static get observedAttributes() { return ['appearance', 'status', 'size', 'styles', 'container-styles', 'disabled', 'right-icon-color', 'left-icon-color']; } attributeChangedCallback(name, oldValue, newValue) { if (name === 'appearance') { this.appearance = newValue; } if (name === 'status') { this.status = newValue; } if (name === 'size') { this.size = newValue; } if (name === 'styles') { this.styles = newValue; } if (name === 'container-styles') { this.containerStyles = newValue; } if (name === 'disabled') { this.disabled = newValue; } if (name === 'right-icon-color') { this.rightIconColor = newValue; } if (name === 'left-icon-color') { this.leftIconColor = newValue; } this.setContainerStyles(this, this.containerStyles); this.setButtonStyles(this.button, this.appearance, this.status, this.size, this.styles); this.setButtonDisabledState(this.button, this.disabled); } setContainerStyles(container, styles) { if (styles) { container.className = styles; } } setButtonStyles(btnElem, appearance, status, size, styles) { if (btnElem) { btnElem.className = ''; const classNameList = []; classNameList.push(this.getAppearanceClass(appearance)); classNameList.push(this.getStatusClass(status)); classNameList.push(this.getSizeClass(size)); if (styles) { classNameList.push(styles); } classNameList.push('group'); // NOTE(Tayfun): This class is added to match the // dummy parent element's width to help flex layout // since the flex layout will be applied to parent // not to the child on this container element classNameList.push('w-full'); btnElem.className = classNameList.join(' '); } } setButtonDisabledState(btnElem, disabled) { if (btnElem) { if (disabled === 'true') { btnElem.disabled = true; } else { btnElem.disabled = false; } } } getAppearanceClass(appearance) { switch (appearance) { case 'secondary': return 'hw-btn-secondary'; case 'light': return 'hw-btn-light'; case 'primary-toggle': return 'hw-button-primary-toggle'; case 'primary': default: return 'hw-button-primary'; } } getStatusClass(status) { switch (status) { case 'outline': return 'hw-btn-outline'; case 'ghost': return 'hw-btn-ghost'; case 'filled': default: return 'hw-btn-filled'; } } getSizeClass(size) { switch (size) { case 'xs': return 'hw-btn-xsmall '; case 'sm': return 'hw-btn-small'; case 'lg': return 'hw-btn-large'; case 'xl': return 'hw-btn-xlarge'; case 'base': default: return 'hw-btn-base'; } } getIcons(leftIcon, rightIcon, styles) { const icons = { svgLeft: null, svgRight: null, }; if (leftIcon !== '') { icons.svgLeft = HWIcons[leftIcon](null, null, this.leftIconColor, styles); } if (rightIcon) { icons.svgRight = HWIcons[rightIcon](null, null, this.rightIconColor, styles); } return icons; } } if (!customElements.get('hw-button')) { customElements.define('hw-button', HWButton); }