From 26a029d407be480d791972afb5975cf62c9360a6 Mon Sep 17 00:00:00 2001 From: Daniel Baumann Date: Fri, 19 Apr 2024 02:47:55 +0200 Subject: Adding upstream version 124.0.1. Signed-off-by: Daniel Baumann --- .../flexbox/components/FlexItemSizingProperties.js | 326 +++++++++++++++++++++ 1 file changed, 326 insertions(+) create mode 100644 devtools/client/inspector/flexbox/components/FlexItemSizingProperties.js (limited to 'devtools/client/inspector/flexbox/components/FlexItemSizingProperties.js') diff --git a/devtools/client/inspector/flexbox/components/FlexItemSizingProperties.js b/devtools/client/inspector/flexbox/components/FlexItemSizingProperties.js new file mode 100644 index 0000000000..00bea31e57 --- /dev/null +++ b/devtools/client/inspector/flexbox/components/FlexItemSizingProperties.js @@ -0,0 +1,326 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +"use strict"; + +const { + PureComponent, +} = require("resource://devtools/client/shared/vendor/react.js"); +const dom = require("resource://devtools/client/shared/vendor/react-dom-factories.js"); +const PropTypes = require("resource://devtools/client/shared/vendor/react-prop-types.js"); +const { + getStr, +} = require("resource://devtools/client/inspector/layout/utils/l10n.js"); + +const Types = require("resource://devtools/client/inspector/flexbox/types.js"); + +const getFlexibilityReasons = ({ + lineGrowthState, + computedFlexGrow, + computedFlexShrink, + grew, + shrank, +}) => { + const reasons = []; + + // Tell users whether the item was set to grow or shrink. + if (computedFlexGrow && lineGrowthState === "growing") { + reasons.push(getStr("flexbox.itemSizing.setToGrow")); + } + if (computedFlexShrink && lineGrowthState === "shrinking") { + reasons.push(getStr("flexbox.itemSizing.setToShrink")); + } + if (!computedFlexGrow && !grew && !shrank && lineGrowthState === "growing") { + reasons.push(getStr("flexbox.itemSizing.notSetToGrow")); + } + if ( + !computedFlexShrink && + !grew && + !shrank && + lineGrowthState === "shrinking" + ) { + reasons.push(getStr("flexbox.itemSizing.notSetToShrink")); + } + + return reasons; +}; + +class FlexItemSizingProperties extends PureComponent { + static get propTypes() { + return { + flexDirection: PropTypes.string.isRequired, + flexItem: PropTypes.shape(Types.flexItem).isRequired, + }; + } + + /** + * Rounds some size in pixels and render it. + * The rendered value will end with 'px' (unless the dimension is 0 in which case the + * unit will be omitted) + * + * @param {Number} value + * The number to be rounded + * @param {Boolean} prependPlusSign + * If set to true, the + sign will be printed before a positive value + * @return {Object} + * The React component representing this rounded size + */ + renderSize(value, prependPlusSign) { + if (value == 0) { + return dom.span({ className: "value" }, "0"); + } + + value = Math.round(value * 100) / 100; + if (prependPlusSign && value > 0) { + value = "+" + value; + } + + return dom.span( + { className: "value" }, + value, + dom.span({ className: "unit" }, "px") + ); + } + + /** + * Render an authored CSS property. + * + * @param {String} name + * The name for this CSS property + * @param {String} value + * The property value + * @param {Booleam} isDefaultValue + * Whether the value come from the browser default style + * @return {Object} + * The React component representing this CSS property + */ + renderCssProperty(name, value, isDefaultValue) { + return dom.span({ className: "css-property-link" }, `(${name}: ${value})`); + } + + /** + * Render a list of sentences to be displayed in the UI as reasons why a certain sizing + * value happened. + * + * @param {Array} sentences + * The list of sentences as Strings + * @return {Object} + * The React component representing these sentences + */ + renderReasons(sentences) { + return dom.ul( + { className: "reasons" }, + sentences.map(sentence => dom.li({}, sentence)) + ); + } + + renderBaseSizeSection({ mainBaseSize, clampState }, properties, dimension) { + const flexBasisValue = properties["flex-basis"]; + const dimensionValue = properties[dimension]; + + let title = getStr("flexbox.itemSizing.baseSizeSectionHeader"); + let property = null; + + if (flexBasisValue) { + // If flex-basis is defined, then that's what is used for the base size. + property = this.renderCssProperty("flex-basis", flexBasisValue); + } else if (dimensionValue) { + // If not and width/height is defined, then that's what defines the base size. + property = this.renderCssProperty(dimension, dimensionValue); + } else { + // Finally, if nothing is set, then the base size is the max-content size. + // In this case replace the section's title. + title = getStr("flexbox.itemSizing.itemContentSize"); + } + + const className = "section base"; + return dom.li( + { className: className + (property ? "" : " no-property") }, + dom.span({ className: "name" }, title, property), + this.renderSize(mainBaseSize) + ); + } + + renderFlexibilitySection( + flexItemSizing, + mainFinalSize, + properties, + computedStyle + ) { + const { mainDeltaSize, mainBaseSize, lineGrowthState } = flexItemSizing; + + // Don't display anything if all interesting sizes are 0. + if (!mainFinalSize && !mainBaseSize && !mainDeltaSize) { + return null; + } + + // Also don't display anything if the item did not grow or shrink. + const grew = mainDeltaSize > 0; + const shrank = mainDeltaSize < 0; + if (!grew && !shrank) { + return null; + } + + const definedFlexGrow = properties["flex-grow"]; + const computedFlexGrow = computedStyle.flexGrow; + const definedFlexShrink = properties["flex-shrink"]; + const computedFlexShrink = computedStyle.flexShrink; + + const reasons = getFlexibilityReasons({ + lineGrowthState, + computedFlexGrow, + computedFlexShrink, + grew, + shrank, + }); + + let property = null; + + if (grew && definedFlexGrow && computedFlexGrow) { + // If the item grew it's normally because it was set to grow (flex-grow is non 0). + property = this.renderCssProperty("flex-grow", definedFlexGrow); + } else if (shrank && definedFlexShrink && computedFlexShrink) { + // If the item shrank it's either because flex-shrink is non 0. + property = this.renderCssProperty("flex-shrink", definedFlexShrink); + } else if (shrank && computedFlexShrink) { + // Or also because it's default value is 1 anyway. + property = this.renderCssProperty( + "flex-shrink", + computedFlexShrink, + true + ); + } + + // Don't display the section at all if there's nothing useful to show users. + if (!property && !reasons.length) { + return null; + } + + const className = "section flexibility"; + return dom.li( + { className: className + (property ? "" : " no-property") }, + dom.span( + { className: "name" }, + getStr("flexbox.itemSizing.flexibilitySectionHeader"), + property + ), + this.renderSize(mainDeltaSize, true), + this.renderReasons(reasons) + ); + } + + renderMinimumSizeSection(flexItemSizing, properties, dimension) { + const { clampState, mainMinSize, mainDeltaSize } = flexItemSizing; + const grew = mainDeltaSize > 0; + const shrank = mainDeltaSize < 0; + const minDimensionValue = properties[`min-${dimension}`]; + + // We only display the minimum size when the item actually violates that size during + // layout & is clamped. + if (clampState !== "clamped_to_min") { + return null; + } + + const reasons = []; + if (grew || shrank) { + // The item may have wanted to grow less, but was min-clamped to a larger size. + // Or the item may have wanted to shrink more but was min-clamped to a larger size. + reasons.push(getStr("flexbox.itemSizing.clampedToMin")); + } + + return dom.li( + { className: "section min" }, + dom.span( + { className: "name" }, + getStr("flexbox.itemSizing.minSizeSectionHeader"), + minDimensionValue.length + ? this.renderCssProperty(`min-${dimension}`, minDimensionValue) + : null + ), + this.renderSize(mainMinSize), + this.renderReasons(reasons) + ); + } + + renderMaximumSizeSection(flexItemSizing, properties, dimension) { + const { clampState, mainMaxSize, mainDeltaSize } = flexItemSizing; + const grew = mainDeltaSize > 0; + const shrank = mainDeltaSize < 0; + const maxDimensionValue = properties[`max-${dimension}`]; + + if (clampState !== "clamped_to_max") { + return null; + } + + const reasons = []; + if (grew || shrank) { + // The item may have wanted to grow more than it did, because it was max-clamped. + // Or the item may have wanted shrink more, but it was clamped to its max size. + reasons.push(getStr("flexbox.itemSizing.clampedToMax")); + } + + return dom.li( + { className: "section max" }, + dom.span( + { className: "name" }, + getStr("flexbox.itemSizing.maxSizeSectionHeader"), + maxDimensionValue.length + ? this.renderCssProperty(`max-${dimension}`, maxDimensionValue) + : null + ), + this.renderSize(mainMaxSize), + this.renderReasons(reasons) + ); + } + + renderFinalSizeSection(mainFinalSize) { + return dom.li( + { className: "section final no-property" }, + dom.span( + { className: "name" }, + getStr("flexbox.itemSizing.finalSizeSectionHeader") + ), + this.renderSize(mainFinalSize) + ); + } + + render() { + const { flexItem } = this.props; + const { computedStyle, flexItemSizing, properties } = flexItem; + const { + mainAxisDirection, + mainBaseSize, + mainDeltaSize, + mainMaxSize, + mainMinSize, + } = flexItemSizing; + const dimension = mainAxisDirection.startsWith("horizontal") + ? "width" + : "height"; + + // Calculate the final size. This is base + delta, then clamped by min or max. + let mainFinalSize = mainBaseSize + mainDeltaSize; + mainFinalSize = Math.max(mainFinalSize, mainMinSize); + mainFinalSize = + mainMaxSize === null + ? mainFinalSize + : Math.min(mainFinalSize, mainMaxSize); + + return dom.ul( + { className: "flex-item-sizing" }, + this.renderBaseSizeSection(flexItemSizing, properties, dimension), + this.renderFlexibilitySection( + flexItemSizing, + mainFinalSize, + properties, + computedStyle + ), + this.renderMinimumSizeSection(flexItemSizing, properties, dimension), + this.renderMaximumSizeSection(flexItemSizing, properties, dimension), + this.renderFinalSizeSection(mainFinalSize) + ); + } +} + +module.exports = FlexItemSizingProperties; -- cgit v1.2.3