chrome-devtools-frontend
Version:
Chrome DevTools UI
140 lines (121 loc) • 4.28 kB
text/typescript
// 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.
import type * as Protocol from '../../generated/protocol.js';
import * as TextUtils from '../../models/text_utils/text_utils.js';
import type {CSSModel} from './CSSModel.js';
import {CSSQuery} from './CSSQuery.js';
import type {DOMNode} from './DOMModel.js';
export class CSSContainerQuery extends CSSQuery {
name?: string;
physicalAxes?: Protocol.DOM.PhysicalAxes;
logicalAxes?: Protocol.DOM.LogicalAxes;
queriesScrollState?: boolean;
queriesAnchored?: boolean;
static parseContainerQueriesPayload(cssModel: CSSModel, payload: Protocol.CSS.CSSContainerQuery[]):
CSSContainerQuery[] {
return payload.map(cq => new CSSContainerQuery(cssModel, cq));
}
constructor(cssModel: CSSModel, payload: Protocol.CSS.CSSContainerQuery) {
super(cssModel);
this.reinitialize(payload);
}
reinitialize(payload: Protocol.CSS.CSSContainerQuery): void {
this.text = payload.text;
this.range = payload.range ? TextUtils.TextRange.TextRange.fromObject(payload.range) : null;
this.styleSheetId = payload.styleSheetId;
this.name = payload.name;
this.physicalAxes = payload.physicalAxes;
this.logicalAxes = payload.logicalAxes;
this.queriesScrollState = payload.queriesScrollState;
this.queriesAnchored = payload.queriesAnchored;
}
active(): boolean {
return true;
}
async getContainerForNode(nodeId: Protocol.DOM.NodeId): Promise<CSSContainerQueryContainer|undefined> {
const containerNode = await this.cssModel.domModel().getContainerForNode(
nodeId, this.name, this.physicalAxes, this.logicalAxes, this.queriesScrollState, this.queriesAnchored);
if (!containerNode) {
return;
}
return new CSSContainerQueryContainer(containerNode);
}
}
export class CSSContainerQueryContainer {
readonly containerNode: DOMNode;
constructor(containerNode: DOMNode) {
this.containerNode = containerNode;
}
async getContainerSizeDetails(): Promise<ContainerQueriedSizeDetails|undefined> {
const styles = await this.containerNode.domModel().cssModel().getComputedStyle(this.containerNode.id);
if (!styles) {
return;
}
const containerType = styles.get('container-type');
const writingMode = styles.get('writing-mode');
if (!containerType || !writingMode) {
return;
}
const queryAxis = getQueryAxisFromContainerType(`${containerType}`);
const physicalAxis = getPhysicalAxisFromQueryAxis(queryAxis, writingMode);
let width, height;
if (physicalAxis === PhysicalAxis.BOTH || physicalAxis === PhysicalAxis.HORIZONTAL) {
width = styles.get('width');
}
if (physicalAxis === PhysicalAxis.BOTH || physicalAxis === PhysicalAxis.VERTICAL) {
height = styles.get('height');
}
return {
queryAxis,
physicalAxis,
width,
height,
};
}
}
export const getQueryAxisFromContainerType = (propertyValue: string): QueryAxis => {
const segments = propertyValue.split(' ');
let isInline = false;
for (const segment of segments) {
if (segment === 'size') {
return QueryAxis.BOTH;
}
isInline = isInline || segment === 'inline-size';
}
if (isInline) {
return QueryAxis.INLINE;
}
return QueryAxis.NONE;
};
export const getPhysicalAxisFromQueryAxis = (queryAxis: QueryAxis, writingMode: string): PhysicalAxis => {
const isVerticalWritingMode = writingMode.startsWith('vertical');
switch (queryAxis) {
case QueryAxis.NONE:
return PhysicalAxis.NONE;
case QueryAxis.BOTH:
return PhysicalAxis.BOTH;
case QueryAxis.INLINE:
return isVerticalWritingMode ? PhysicalAxis.VERTICAL : PhysicalAxis.HORIZONTAL;
case QueryAxis.BLOCK:
return isVerticalWritingMode ? PhysicalAxis.HORIZONTAL : PhysicalAxis.VERTICAL;
}
};
export interface ContainerQueriedSizeDetails {
queryAxis: QueryAxis;
physicalAxis: PhysicalAxis;
width?: string;
height?: string;
}
export const enum QueryAxis {
NONE = '',
INLINE = 'inline-size',
BLOCK = 'block-size',
BOTH = 'size',
}
export const enum PhysicalAxis {
NONE = '',
HORIZONTAL = 'Horizontal',
VERTICAL = 'Vertical',
BOTH = 'Both',
}