hologram-web-library
Version:
Hologram Web Library components
245 lines (204 loc) • 6.35 kB
JavaScript
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);
}