UNPKG

chrome-devtools-frontend

Version:
128 lines (112 loc) 3.77 kB
// Copyright (c) 2020 The Chromium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. import * as ComponentHelpers from '../../../ui/components/helpers/helpers.js'; import * as LitHtml from '../../../ui/lit-html/lit-html.js'; import * as Coordinator from '../render_coordinator/render_coordinator.js'; import iconStyles from './icon.css.js'; export interface IconWithPath { iconPath: string; color: string; width?: string; height?: string; } export interface IconWithName { iconName: string; color: string; width?: string; height?: string; } export type IconData = IconWithPath|IconWithName; const isString = (value: string|undefined): value is string => value !== undefined; const coordinator = Coordinator.RenderCoordinator.RenderCoordinator.instance(); export class Icon extends HTMLElement { static readonly litTagName = LitHtml.literal`devtools-icon`; readonly #shadow = this.attachShadow({mode: 'open'}); #iconPath: Readonly<string> = ''; #color: Readonly<string> = 'rgb(110 110 110)'; #width: Readonly<string> = '100%'; #height: Readonly<string> = '100%'; #iconName?: Readonly<string>; connectedCallback(): void { this.#shadow.adoptedStyleSheets = [iconStyles]; } set data(data: IconData) { const {width, height} = data; this.#color = data.color; this.#width = isString(width) ? width : (isString(height) ? height : this.#width); this.#height = isString(height) ? height : (isString(width) ? width : this.#height); if ('iconPath' in data && data.iconPath) { this.#iconPath = data.iconPath; } else if ('iconName' in data && data.iconName) { this.#iconPath = new URL(`../../../Images/${data.iconName}.svg`, import.meta.url).toString(); this.#iconName = data.iconName; } else { throw new Error('Misconfigured iconName or iconPath.'); } this.#render(); } get data(): IconData { const commonData = { color: this.#color, width: this.#width, height: this.#height, }; if (this.#iconName) { return { ...commonData, iconName: this.#iconName, }; } return { ...commonData, iconPath: this.#iconPath, }; } #getStyles(): {[key: string]: string} { const iconPath = this.#iconPath; const width = this.#width; const height = this.#height; const color = this.#color; const commonStyles = { width, height, display: 'block', }; if (color) { return { ...commonStyles, webkitMaskImage: `url(${iconPath})`, webkitMaskPosition: 'center', webkitMaskRepeat: 'no-repeat', // We are setting this to 99% to work around an issue where non-standard zoom levels would cause the icon to clip. webkitMaskSize: '99%', backgroundColor: `var(--icon-color, ${color})`, }; } return { ...commonStyles, backgroundImage: `url(${iconPath})`, backgroundPosition: 'center', backgroundRepeat: 'no-repeat', // We are setting this to 99% to work around an issue where non-standard zoom levels would cause the icon to clip. backgroundSize: '99%', }; } #render(): void { void coordinator.write(() => { // clang-format off LitHtml.render(LitHtml.html` <div class="icon-basic" style=${LitHtml.Directives.styleMap(this.#getStyles())}></div> `, this.#shadow, {host: this}); // clang-format on }); } } ComponentHelpers.CustomElements.defineComponent('devtools-icon', Icon); declare global { // eslint-disable-next-line @typescript-eslint/no-unused-vars interface HTMLElementTagNameMap { 'devtools-icon': Icon; } }