| // 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 '../../../ui/kit/kit.js'; |
| import '../../../ui/components/node_text/node_text.js'; |
| |
| import * as SDK from '../../../core/sdk/sdk.js'; |
| import * as Lit from '../../../ui/lit/lit.js'; |
| import * as VisualLogging from '../../../ui/visual_logging/visual_logging.js'; |
| |
| import type {DOMNode} from './Helper.js'; |
| import queryContainerStyles from './queryContainer.css.js'; |
| |
| const {render, html} = Lit; |
| const {PhysicalAxis, QueryAxis} = SDK.CSSContainerQuery; |
| |
| export class QueriedSizeRequestedEvent extends Event { |
| static readonly eventName = 'queriedsizerequested'; |
| constructor() { |
| super(QueriedSizeRequestedEvent.eventName, {}); |
| } |
| } |
| |
| export interface QueryContainerData { |
| container: DOMNode; |
| queryName?: string; |
| onContainerLinkClick: (event: Event) => void; |
| } |
| |
| export class QueryContainer extends HTMLElement { |
| readonly #shadow = this.attachShadow({mode: 'open'}); |
| #queryName?: string; |
| #container?: DOMNode; |
| #onContainerLinkClick?: (event: Event) => void; |
| #isContainerLinkHovered = false; |
| #queriedSizeDetails?: SDK.CSSContainerQuery.ContainerQueriedSizeDetails; |
| |
| set data(data: QueryContainerData) { |
| this.#queryName = data.queryName; |
| this.#container = data.container; |
| this.#onContainerLinkClick = data.onContainerLinkClick; |
| this.#render(); |
| } |
| |
| updateContainerQueriedSizeDetails(details: SDK.CSSContainerQuery.ContainerQueriedSizeDetails): void { |
| this.#queriedSizeDetails = details; |
| this.#render(); |
| } |
| |
| async #onContainerLinkMouseEnter(): Promise<void> { |
| this.#container?.highlightNode('container-outline'); |
| this.#isContainerLinkHovered = true; |
| this.dispatchEvent(new QueriedSizeRequestedEvent()); |
| } |
| |
| #onContainerLinkMouseLeave(): void { |
| this.#container?.clearHighlight(); |
| this.#isContainerLinkHovered = false; |
| this.#render(); |
| } |
| |
| #render(): void { |
| if (!this.#container) { |
| return; |
| } |
| |
| let idToDisplay, classesToDisplay; |
| if (!this.#queryName) { |
| idToDisplay = this.#container.getAttribute('id'); |
| classesToDisplay = this.#container.getAttribute('class')?.split(/\s+/).filter(Boolean); |
| } |
| |
| const nodeTitle = this.#queryName || this.#container.nodeNameNicelyCased; |
| |
| // Disabled until https://crbug.com/1079231 is fixed. |
| // clang-format off |
| // eslint-disable-next-line @devtools/no-a-tags-in-lit |
| render(html` |
| <style>${queryContainerStyles}</style> |
| → |
| <a href="#" draggable=false class="container-link" |
| jslog=${VisualLogging.cssRuleHeader('container-query').track({click: true})} |
| @click=${this.#onContainerLinkClick} |
| @mouseenter=${this.#onContainerLinkMouseEnter} |
| @mouseleave=${this.#onContainerLinkMouseLeave}> |
| <devtools-node-text data-node-title=${nodeTitle} .data=${{ |
| nodeTitle, |
| nodeId: idToDisplay, |
| nodeClasses: classesToDisplay, |
| }}> |
| </devtools-node-text> |
| </a> |
| ${this.#isContainerLinkHovered ? this.#renderQueriedSizeDetails() : Lit.nothing} |
| `, this.#shadow, { |
| host: this, |
| }); |
| // clang-format on |
| } |
| |
| #renderQueriedSizeDetails(): Lit.LitTemplate { |
| if (!this.#queriedSizeDetails || this.#queriedSizeDetails.queryAxis === QueryAxis.NONE) { |
| return Lit.nothing; |
| } |
| |
| const areBothAxesQueried = this.#queriedSizeDetails.queryAxis === QueryAxis.BOTH; |
| |
| const axisIconClasses = Lit.Directives.classMap({ |
| 'axis-icon': true, |
| hidden: areBothAxesQueried, |
| vertical: this.#queriedSizeDetails.physicalAxis === PhysicalAxis.VERTICAL, |
| }); |
| |
| // Disabled until https://crbug.com/1079231 is fixed. |
| // clang-format off |
| return html` |
| <span class="queried-size-details"> |
| (${this.#queriedSizeDetails.queryAxis} |
| <devtools-icon |
| class=${axisIconClasses} name="width"></devtools-icon> |
| ) ${areBothAxesQueried && this.#queriedSizeDetails.width ? ' width: ' : Lit.nothing} |
| ${this.#queriedSizeDetails.width || Lit.nothing} |
| ${areBothAxesQueried && this.#queriedSizeDetails.height ? ' height: ' : Lit.nothing} |
| ${this.#queriedSizeDetails.height || Lit.nothing} |
| </span> |
| `; |
| // clang-format on |
| } |
| } |
| |
| customElements.define('devtools-query-container', QueryContainer); |
| |
| declare global { |
| interface HTMLElementTagNameMap { |
| 'devtools-query-container': QueryContainer; |
| } |
| } |