@riovir/wc-fontawesome
Version:
Web components for Font Awesome
102 lines (85 loc) • 3.64 kB
JavaScript
import { applyStyleWith } from './apply-style-with.js';
import { parseTransform, textToHtml } from './svg-core.js';
import { definePropsOn, BooleanProp, StringProp } from './core.js';
import { updateElementClass } from './utils.js';
import { Props as IconProps } from './font-awesome-icon.js';
const applyStyle = applyStyleWith({ css: /* css */`
:host {
box-sizing: border-box;
display: inline-block;
line-height: 1; }
.fa-layers-counter {
background: var(--fa-layers-counter-background, #ff253a); }
` });
export const template = document.createElement('template');
template.innerHTML = /* html */`
<span class="fa-layers-text"></span>
`;
function toHtmlFallback(text = '') {
const span = document.createElement('span');
span.className = 'fa-layers-text';
span.textContent = text;
return [span.outerHTML];
}
const Internal = {
CONTAINER: Symbol('container'),
NEEDS_REDRAW: Symbol('needs-complete-redraw-of-structure'),
};
const updateContainerClass = updateElementClass(Internal.CONTAINER);
const prefixContainerClass = prefix => updateContainerClass(value => prefix + value);
export const Props = {
value: StringProp({ attribute: 'value', observe: updateContainer }),
transform: { ...IconProps.transform, observe: updateContainer },
parsedTransform: IconProps.parsedTransform,
size: StringProp({ attribute: 'size', observe: prefixContainerClass('fa-') }),
position: StringProp({ attribute: 'position', observe: prefixContainerClass('fa-layers-') }),
fixedWidth: BooleanProp({ attribute: 'fixed-width', observe: updateContainerClass('fa-fw') }),
widthAuto: BooleanProp({ attribute: 'width-auto', observe: updateContainerClass('fa-width-auto') }),
inverse: BooleanProp({ attribute: 'inverse', observe: updateContainerClass('fa-inverse') }),
counter: BooleanProp({ attribute: 'counter', observe: updateContainer }),
};
export class FontAwesomeLayersText extends HTMLElement {
constructor() {
super();
const shadowRoot = this.attachShadow({ mode: 'open' });
shadowRoot.appendChild(template.content.cloneNode(true));
applyStyle(this);
this[Internal.CONTAINER] = shadowRoot.querySelector('.fa-layers-text');
this[Internal.NEEDS_REDRAW] = host => host.transform;
this._toHtml = textToHtml;
this._parseTransform = parseTransform;
}
}
definePropsOn(FontAwesomeLayersText, Props);
function updateContainer(host) {
if (host[Internal.NEEDS_REDRAW](host)) {
redrawElements(host);
}
updateLayerClass(host);
updateTextValue(host);
}
function redrawElements(host) {
const classes = host[Internal.CONTAINER].classList;
host[Internal.CONTAINER].remove();
const options = {
transform: host.parsedTransform,
};
const [container] = host._toHtml(String(host.value), options) || toHtmlFallback(host.value, options);
host.shadowRoot.innerHTML += container;
host[Internal.CONTAINER] = host.shadowRoot.querySelector('.fa-layers-text');
host[Internal.CONTAINER].classList.add(...classes);
const { transform } = host;
host[Internal.NEEDS_REDRAW] = host => transform !== host.transform;
}
function updateLayerClass(host) {
const classList = host[Internal.CONTAINER].classList;
const { classToAdd, classToRemove } = host.counter ?
{ classToAdd: 'fa-layers-counter', classToRemove: 'fa-layers-text' } :
{ classToAdd: 'fa-layers-text', classToRemove: 'fa-layers-counter' };
classList.add(classToAdd);
classList.remove(classToRemove);
}
function updateTextValue(host, value = host.value) {
const text = host.counter && !value ? 0 : value;
host[Internal.CONTAINER].textContent = text;
}