import { NavigationMixin } from '@littoral/literally/navigation/navigation.mixin';
import { LitElement, css, html } from 'lit';
import { customElement, property } from 'lit/decorators.js';
import { contrast, hexToRgb } from '../utils/color';
/**
* Element for displaying material symbol icons.
*/
@customElement('er-icon')
export class ErIcon extends NavigationMixin(LitElement) {
static styles = [
css`
:host {
--color: var(
--er-icon-color,
var(--color-default, var(--md-sys-color-container))
);
--on-color: var(
--er-icon-on-color,
var(--on-color-default, var(--md-sys-color-on-container))
);
aspect-ratio: 1;
background-color: var(--color);
border: 1px solid transparent;
box-sizing: border-box;
color: var(--on-color);
display: inline-block;
/* Hack to get around extra whitespace around icon. */
font-size: 0;
font-variation-settings:
'FILL' 0,
'wght' 400,
'GRAD' 0,
'opsz' 24;
line-height: 1;
padding: 0;
text-align: center;
}
:host([disabled]) {
opacity: 0.25;
}
:host(.dim) {
opacity: 0.25;
transition: opacity 0.25s ease-in-out;
}
:host(.dim.link:hover) {
opacity: 0.75;
}
:host(.link) {
cursor: pointer;
}
:host(.outline) {
background-color: var(--on-color);
border-color: var(--color);
color: var(--color);
}
:host(.rounded) {
border-radius: 50%;
}
:host(.roundish) {
border-radius: var(--er-icon-border-radius, var(--space-small));
}
:host(.padSmall) {
padding: var(--space-small);
}
:host(.padMedium) {
padding: var(--space-medium);
}
:host(.themePrimary) {
--color-default: var(--md-sys-color-primary);
--on-color-default: var(--md-sys-color-on-primary);
}
:host(.themePrimarySurface) {
--color-default: var(--md-sys-color-primary-surface);
--on-color-default: var(--md-sys-color-on-primary-surface);
}
:host(.themeSecondary) {
--color-default: var(--md-sys-color-secondary);
--on-color-default: var(--md-sys-color-on-secondary);
}
:host(.themeTertiary) {
--color-default: var(--md-sys-color-secondary);
--on-color-default: var(--md-sys-color-on-secondary);
}
.material-symbols-outlined {
display: inline-block;
font-size: var(--er-icon-font-size, 24px);
line-height: 1;
overflow: hidden;
max-width: 24px;
}
@media print {
:host {
color: var(--er-icon-color, #000);
background-color: transparent;
}
}
`,
];
@property({ reflect: true })
icon = '';
@property({ reflect: true })
color?: string;
@property({ type: Boolean, reflect: true })
disabled = false;
@property({ type: Boolean, attribute: 'keep-color', reflect: true })
keepColor = false;
render() {
if (this.color) {
this.style.setProperty('--er-icon-color', this.color);
// Determine which color has the greates constrast on the color to
// determine icon color.
const colorRGB = hexToRgb(this.color);
if (colorRGB && !this.keepColor) {
const whiteContrast = contrast(
{
red: 255,
green: 255,
blue: 255,
},
colorRGB,
);
const blackContrast = contrast(
{
red: 0,
green: 0,
blue: 0,
},
colorRGB,
);
this.style.setProperty(
'--er-icon-on-color',
whiteContrast > blackContrast ? '#ffffff' : '#000000',
);
}
}
return html`
${this.icon}
`;
}
}
declare global {
interface HTMLElementTagNameMap {
'er-icon': ErIcon;
}
}