| // 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 */ |
| |
| import type * as Platform from '../../../core/platform/platform.js'; |
| import * as EmulationModel from '../../../models/emulation/emulation.js'; |
| import * as UILegacy from '../../../ui/legacy/legacy.js'; |
| import {html, render} from '../../../ui/lit/lit.js'; |
| import * as VisualLogging from '../../../ui/visual_logging/visual_logging.js'; |
| |
| class SizeChangedEvent extends Event { |
| static readonly eventName = 'sizechanged'; |
| constructor(public size: number) { |
| super(SizeChangedEvent.eventName); |
| } |
| } |
| |
| function getInputValue(event: Event): number { |
| return Number((event.target as HTMLInputElement).value); |
| } |
| |
| export class SizeInputElement extends HTMLElement { |
| #root = this.attachShadow({mode: 'open'}); |
| #disabled = false; |
| #size = '0'; |
| #placeholder = ''; |
| #title: Platform.UIString.LocalizedString; |
| #jslogContext: string; |
| |
| constructor(title: Platform.UIString.LocalizedString, {jslogContext}: {jslogContext: string}) { |
| super(); |
| this.#title = title; |
| this.#jslogContext = jslogContext; |
| } |
| |
| connectedCallback(): void { |
| this.render(); |
| } |
| |
| set disabled(disabled: boolean) { |
| this.#disabled = disabled; |
| this.render(); |
| } |
| |
| set size(size: string) { |
| this.#size = size; |
| this.render(); |
| } |
| |
| set placeholder(placeholder: string) { |
| this.#placeholder = placeholder; |
| this.render(); |
| } |
| |
| render(): void { |
| render( |
| // Since the emulation code runs in a different frame, we can't |
| // use constructed stylesheets (they are disallowed cross-frame). |
| // For now, use an inline style tag and later we can refactor this |
| // to use proper constructed stylesheets, when the code runs |
| // in the correct frame context. |
| html` |
| <style> |
| input { |
| /* |
| * 4 characters for the maximum size of the value, |
| * 2 characters for the width of the step-buttons, |
| * 2 pixels padding between the characters and the |
| * step-buttons. |
| */ |
| width: calc(4ch + 2ch + 2px); |
| max-height: 18px; |
| border: var(--sys-color-neutral-outline); |
| border-radius: 4px; |
| margin: 0 2px; |
| text-align: center; |
| font-size: inherit; |
| font-family: inherit; |
| } |
| |
| input:disabled { |
| user-select: none; |
| } |
| |
| input:focus::-webkit-input-placeholder { |
| color: transparent; |
| } |
| </style> |
| <input type="number" |
| max=${EmulationModel.DeviceModeModel.MaxDeviceSize} |
| min=${EmulationModel.DeviceModeModel.MinDeviceSize} |
| jslog=${VisualLogging.textField().track({change: true}).context(this.#jslogContext)} |
| maxlength="4" |
| title=${this.#title} |
| placeholder=${this.#placeholder} |
| ?disabled=${this.#disabled} |
| .value=${this.#size} |
| @change=${this.#fireSizeChange} |
| @keydown=${this.#handleModifierKeys} /> |
| `, |
| this.#root, {host: this}); |
| } |
| |
| #fireSizeChange(event: Event): void { |
| this.dispatchEvent(new SizeChangedEvent(getInputValue(event))); |
| } |
| |
| #handleModifierKeys(event: Event): void { |
| let modifiedValue = UILegacy.UIUtils.modifiedFloatNumber(getInputValue(event), event); |
| if (modifiedValue === null) { |
| return; |
| } |
| |
| modifiedValue = Math.min(modifiedValue, EmulationModel.DeviceModeModel.MaxDeviceSize); |
| modifiedValue = Math.max(modifiedValue, EmulationModel.DeviceModeModel.MinDeviceSize); |
| |
| event.preventDefault(); |
| (event.target as HTMLInputElement).value = String(modifiedValue); |
| this.dispatchEvent(new SizeChangedEvent(modifiedValue)); |
| } |
| } |
| |
| // eslint-disable-next-line @devtools/enforce-custom-element-prefix |
| customElements.define('device-mode-emulation-size-input', SizeInputElement); |
| |
| declare global { |
| interface HTMLElementTagNameMap { |
| 'device-mode-emulation-size-input': SizeInputElement; |
| } |
| interface HTMLElementEventMap { |
| sizechanged: SizeChangedEvent; |
| } |
| } |