// Copyright 2023 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/enforce-custom-element-definitions-location */ import './ButtonDialog.js'; /* eslint-disable @devtools/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`${row.footnote}`; } return html`${row.map(part => { if ('key' in part) { return html`${part.key}`; } return html`${part.joinText}`; })} `; } #render(): void { if (!ComponentHelpers.ScheduledRender.isScheduledRender(this)) { throw new Error('Shortcut dialog render was not scheduled'); } // clang-format off render( html` `, this.#shadow, {host: this}); // clang-format on } } customElements.define('devtools-shortcut-dialog', ShortcutDialog);