UNPKG

chrome-devtools-frontend

Version:
142 lines (120 loc) 4.36 kB
// Copyright 2023 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 './ButtonDialog.js'; /* eslint-disable rulesdir/no-lit-render-outside-of-view */ import * as i18n from '../../../core/i18n/i18n.js'; import type * as Platform from '../../../core/platform/platform.js'; import * as Buttons from '../../../ui/components/buttons/buttons.js'; import * as ComponentHelpers from '../../../ui/components/helpers/helpers.js'; import {html, nothing, render, type TemplateResult} from '../../../ui/lit/lit.js'; import type {ButtonDialogData} from './ButtonDialog.js'; import shortcutDialogStyles from './shortcutDialog.css.js'; const UIStrings = { /** * @description Title of question mark button for the shortcuts dialog. */ showShortcutTitle: 'Show shortcuts', /** * @description Title of the keyboard shortcuts help menu. */ dialogTitle: 'Keyboard shortcuts', } as const; const str_ = i18n.i18n.registerUIStrings('ui/components/dialogs/ShortcutDialog.ts', UIStrings); const i18nString = i18n.i18n.getLocalizedString.bind(undefined, str_); declare global { interface HTMLElementTagNameMap { 'devtools-shortcut-dialog': ShortcutDialog; } } export type ShortcutPart = { key: string, }|{joinText: string}; export type ShortcutRow = ShortcutPart[]|{footnote: string}; export interface Shortcut { title: string|Platform.UIString.LocalizedString; rows: readonly ShortcutRow[]; } export interface ShortcutDialogData { shortcuts: Shortcut[]; open?: boolean; customTitle?: Platform.UIString.LocalizedString; } export class ShortcutDialog extends HTMLElement { readonly #shadow = this.attachShadow({mode: 'open'}); #shortcuts: Shortcut[] = []; #openOnRender = false; #customTitle?: Platform.UIString.LocalizedString; #prependedElement: HTMLElement|null = null; get data(): ShortcutDialogData { return { shortcuts: this.#shortcuts, open: this.#openOnRender, customTitle: this.#customTitle, }; } set data(data: ShortcutDialogData) { this.#shortcuts = data.shortcuts; if (data.open) { this.#openOnRender = data.open; } if (data.customTitle) { this.#customTitle = data.customTitle; } void ComponentHelpers.ScheduledRender.scheduleRender(this, this.#render); } prependElement(element: HTMLElement): void { this.#prependedElement = element; } #renderRow(row: ShortcutRow): TemplateResult { if (!Array.isArray(row)) { // If it's not an array it's a footnote, which is the easier case, so // render that and return. return html`<span class="footnote">${row.footnote}</span>`; } return html`${row.map(part => { if ('key' in part) { return html`<span class="keybinds-key">${part.key}</span>`; } return html`<span class="keybinds-join-text">${part.joinText}</span>`; })} `; } #render(): void { if (!ComponentHelpers.ScheduledRender.isScheduledRender(this)) { throw new Error('Shortcut dialog render was not scheduled'); } // clang-format off render( html` <style>${shortcutDialogStyles}</style> <devtools-button-dialog .data=${{ openOnRender: this.#openOnRender, closeButton: true, dialogTitle: this.#customTitle ?? i18nString(UIStrings.dialogTitle), variant: Buttons.Button.Variant.TOOLBAR, iconName: 'help', iconTitle: i18nString(UIStrings.showShortcutTitle), } as ButtonDialogData}> <ul class="keybinds-list"> ${(this.#prependedElement) ? html`${this.#prependedElement}` : nothing} ${this.#shortcuts.map(shortcut => html` <li class="keybinds-list-item"> <div class="keybinds-list-title">${shortcut.title}</div> <div class="shortcuts-for-actions"> ${shortcut.rows.map(row => { return html`<div class="row-container">${this.#renderRow(row)}</div> `; })} </div> </li>`, )} </ul> </devtools-button-dialog> `, this.#shadow, {host: this}); // clang-format on } } customElements.define('devtools-shortcut-dialog', ShortcutDialog);