UNPKG

chrome-devtools-frontend

Version:
185 lines (161 loc) • 5.83 kB
// Copyright 2021 The Chromium Authors // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. /* eslint-disable @devtools/no-lit-render-outside-of-view, @devtools/enforce-custom-element-definitions-location */ import '../tooltips/tooltips.js'; import './SettingDeprecationWarning.js'; import '../../kit/kit.js'; import type * as Common from '../../../core/common/common.js'; import * as Host from '../../../core/host/host.js'; import * as i18n from '../../../core/i18n/i18n.js'; import * as Lit from '../../lit/lit.js'; import * as VisualLogging from '../../visual_logging/visual_logging.js'; import * as Buttons from '../buttons/buttons.js'; import * as Input from '../input/input.js'; import settingCheckboxStyles from './settingCheckbox.css.js'; const {html, Directives: {ifDefined}} = Lit; const UIStrings = { /** * @description Text that is usually a hyperlink to more documentation */ learnMore: 'Learn more', } as const; const str_ = i18n.i18n.registerUIStrings('ui/components/settings/SettingCheckbox.ts', UIStrings); const i18nString = i18n.i18n.getLocalizedString.bind(undefined, str_); export interface SettingCheckboxData { setting: Common.Settings.Setting<boolean>; textOverride?: string; } /** * A simple checkbox that is backed by a boolean setting. */ export class SettingCheckbox extends HTMLElement { readonly #shadow = this.attachShadow({mode: 'open'}); #setting?: Common.Settings.Setting<boolean>; #changeListenerDescriptor?: Common.EventTarget.EventDescriptor; #textOverride?: string; set data(data: SettingCheckboxData) { if (this.#changeListenerDescriptor && this.#setting) { this.#setting.removeChangeListener(this.#changeListenerDescriptor.listener); } this.#setting = data.setting; this.#textOverride = data.textOverride; this.#changeListenerDescriptor = this.#setting.addChangeListener(() => { this.#render(); }); this.#render(); } icon(): Lit.TemplateResult|undefined { if (!this.#setting) { return undefined; } if (this.#setting.deprecation) { return html`<devtools-setting-deprecation-warning .data=${ this.#setting.deprecation}></devtools-setting-deprecation-warning>`; } const learnMore = this.#setting.learnMore(); if (learnMore) { const jsLogContext = `${this.#setting.name}-documentation`; const data: Buttons.Button.ButtonData = { iconName: 'info', variant: Buttons.Button.Variant.ICON, size: Buttons.Button.Size.SMALL, jslogContext: jsLogContext, }; const url = learnMore.url; if (learnMore.tooltip) { const id = `${this.#setting.name}-information`; // clang-format off return html` <devtools-button class="info-icon" aria-details=${id} .data=${data} ></devtools-button> <devtools-tooltip id=${id} variant="rich"> <span>${learnMore.tooltip()}</span><br /> ${url ? html`<devtools-link href=${url} class="link" .jslogContext=${jsLogContext} >${i18nString(UIStrings.learnMore)}</devtools-link >` : Lit.nothing} </devtools-tooltip> `; // clang-format on } if (url) { const handleClick = (event: MouseEvent): void => { Host.InspectorFrontendHost.InspectorFrontendHostInstance.openInNewTab(url); event.consume(); }; data.iconName = 'help'; data.title = i18nString(UIStrings.learnMore); // clang-format off return html`<devtools-button class="info-icon" @click=${handleClick} .data=${data} ></devtools-button>`; // clang-format on } } return undefined; } get checked(): boolean { if (!this.#setting || this.#setting.disabledReasons().length > 0) { return false; } return this.#setting.get(); } #render(): void { if (!this.#setting) { throw new Error('No "Setting" object provided for rendering'); } const icon = this.icon(); const title = `${this.#setting.learnMore() ? this.#setting.learnMore()?.tooltip?.() : ''}`; const disabledReasons = this.#setting.disabledReasons(); const reason = disabledReasons.length ? html` <devtools-button class="disabled-reason" .iconName=${'info'} .variant=${Buttons.Button.Variant.ICON} .size=${ Buttons.Button.Size.SMALL} title=${ifDefined(disabledReasons.join('\n'))} @click=${ onclick}></devtools-button> ` : Lit.nothing; Lit.render( html` <style>${Input.checkboxStyles}</style> <style>${settingCheckboxStyles}</style> <p> <label title=${title}> <input type="checkbox" .checked=${this.checked} ?disabled=${this.#setting.disabled()} @change=${this.#checkboxChanged} jslog=${VisualLogging.toggle().track({change: true}).context(this.#setting.name)} aria-label=${this.#setting.title()} /> ${this.#textOverride || this.#setting.title()}${reason} </label> ${icon} </p>`, this.#shadow, {host: this}); } #checkboxChanged(e: Event): void { this.#setting?.set((e.target as HTMLInputElement).checked); this.dispatchEvent(new CustomEvent('change', { bubbles: true, composed: false, })); } } // eslint-disable-next-line @devtools/enforce-custom-element-prefix customElements.define('setting-checkbox', SettingCheckbox); declare global { interface HTMLElementTagNameMap { 'setting-checkbox': SettingCheckbox; } }