diff --git a/packages/block-editor/src/components/height-control/index.js b/packages/block-editor/src/components/height-control/index.js index fe041013d55a02..8825b97d487296 100644 --- a/packages/block-editor/src/components/height-control/index.js +++ b/packages/block-editor/src/components/height-control/index.js @@ -26,6 +26,28 @@ const RANGE_CONTROL_CUSTOM_SETTINGS = { vh: { max: 100, step: 1 }, em: { max: 50, step: 0.1 }, rem: { max: 50, step: 0.1 }, + svw: { max: 100, step: 1 }, + lvw: { max: 100, step: 1 }, + dvw: { max: 100, step: 1 }, + svh: { max: 100, step: 1 }, + lvh: { max: 100, step: 1 }, + dvh: { max: 100, step: 1 }, + vi: { max: 100, step: 1 }, + svi: { max: 100, step: 1 }, + lvi: { max: 100, step: 1 }, + dvi: { max: 100, step: 1 }, + vb: { max: 100, step: 1 }, + svb: { max: 100, step: 1 }, + lvb: { max: 100, step: 1 }, + dvb: { max: 100, step: 1 }, + vmin: { max: 100, step: 1 }, + svmin: { max: 100, step: 1 }, + lvmin: { max: 100, step: 1 }, + dvmin: { max: 100, step: 1 }, + vmax: { max: 100, step: 1 }, + svmax: { max: 100, step: 1 }, + lvmax: { max: 100, step: 1 }, + dvmax: { max: 100, step: 1 }, }; /** @@ -86,10 +108,36 @@ export default function HeightControl( { // Convert to pixel value assuming a root size of 16px. onChange( Math.round( currentValue * 16 ) + newUnit ); } else if ( - [ 'vh', 'vw', '%' ].includes( newUnit ) && + [ + '%', + 'vw', + 'svw', + 'lvw', + 'dvw', + 'vh', + 'svh', + 'lvh', + 'dvh', + 'vi', + 'svi', + 'lvi', + 'dvi', + 'vb', + 'svb', + 'lvb', + 'dvb', + 'vmin', + 'svmin', + 'lvmin', + 'dvmin', + 'vmax', + 'svmax', + 'lvmax', + 'dvmax', + ].includes( newUnit ) && currentValue > 100 ) { - // When converting to `vh`, `vw`, or `%` units, cap the new value at 100. + // When converting to `%` or viewport-relative units, cap the new value at 100. onChange( 100 + newUnit ); } }; diff --git a/packages/block-editor/src/components/spacing-sizes-control/input-controls/spacing-input-control.js b/packages/block-editor/src/components/spacing-sizes-control/input-controls/spacing-input-control.js index f423596daaa4a5..1b324835e362dc 100644 --- a/packages/block-editor/src/components/spacing-sizes-control/input-controls/spacing-input-control.js +++ b/packages/block-editor/src/components/spacing-sizes-control/input-controls/spacing-input-control.js @@ -38,6 +38,28 @@ const CUSTOM_VALUE_SETTINGS = { vh: { max: 100, steps: 1 }, em: { max: 10, steps: 0.1 }, rm: { max: 10, steps: 0.1 }, + svw: { max: 100, steps: 1 }, + lvw: { max: 100, steps: 1 }, + dvw: { max: 100, steps: 1 }, + svh: { max: 100, steps: 1 }, + lvh: { max: 100, steps: 1 }, + dvh: { max: 100, steps: 1 }, + vi: { max: 100, steps: 1 }, + svi: { max: 100, steps: 1 }, + lvi: { max: 100, steps: 1 }, + dvi: { max: 100, steps: 1 }, + vb: { max: 100, steps: 1 }, + svb: { max: 100, steps: 1 }, + lvb: { max: 100, steps: 1 }, + dvb: { max: 100, steps: 1 }, + vmin: { max: 100, steps: 1 }, + svmin: { max: 100, steps: 1 }, + lvmin: { max: 100, steps: 1 }, + dvmin: { max: 100, steps: 1 }, + vmax: { max: 100, steps: 1 }, + svmax: { max: 100, steps: 1 }, + lvmax: { max: 100, steps: 1 }, + dvmax: { max: 100, steps: 1 }, }; export default function SpacingInputControl( { diff --git a/packages/block-editor/src/layouts/grid.js b/packages/block-editor/src/layouts/grid.js index 55ac1e53bcd87e..93f7768a76e259 100644 --- a/packages/block-editor/src/layouts/grid.js +++ b/packages/block-editor/src/layouts/grid.js @@ -27,6 +27,28 @@ const RANGE_CONTROL_MAX_VALUES = { vh: 100, em: 38, rem: 38, + svw: 100, + lvw: 100, + dvw: 100, + svh: 100, + lvh: 100, + dvh: 100, + vi: 100, + svi: 100, + lvi: 100, + dvi: 100, + vb: 100, + svb: 100, + lvb: 100, + dvb: 100, + vmin: 100, + svmin: 100, + lvmin: 100, + dvmin: 100, + vmax: 100, + svmax: 100, + lvmax: 100, + dvmax: 100, }; export default { @@ -131,10 +153,36 @@ function GridLayoutMinimumWidthControl( { layout, onChange } ) { // Convert to pixel value assuming a root size of 16px. newValue = Math.round( quantity * 16 ) + newUnit; } else if ( - [ 'vh', 'vw', '%' ].includes( newUnit ) && + [ + 'vh', + 'vw', + '%', + 'svw', + 'lvw', + 'dvw', + 'svh', + 'lvh', + 'dvh', + 'vi', + 'svi', + 'lvi', + 'dvi', + 'vb', + 'svb', + 'lvb', + 'dvb', + 'vmin', + 'svmin', + 'lvmin', + 'dvmin', + 'vmax', + 'svmax', + 'lvmax', + 'dvmax', + ].includes( newUnit ) && quantity > 100 ) { - // When converting to `vh`, `vw`, or `%` units, cap the new value at 100. + // When converting to `%` or viewport-relativew units, cap the new value at 100. newValue = 100 + newUnit; } diff --git a/packages/block-editor/src/layouts/utils.js b/packages/block-editor/src/layouts/utils.js index 51c92b5eb457e7..30280b8906e7a0 100644 --- a/packages/block-editor/src/layouts/utils.js +++ b/packages/block-editor/src/layouts/utils.js @@ -90,7 +90,8 @@ export function getBlockGapCSS( export function getAlignmentsInfo( layout ) { const { contentSize, wideSize, type = 'default' } = layout; const alignmentInfo = {}; - const sizeRegex = /^(?!0)\d+(px|em|rem|vw|vh|%)?$/i; + const sizeRegex = + /^(?!0)\d+(px|em|rem|vw|vh|%|svw|lvw|dvw|svh|lvh|dvh|vi|svi|lvi|dvi|vb|svb|lvb|dvb|vmin|svmin|lvmin|dvmin|vmax|svmax|lvmax|dvmax)?$/i; if ( sizeRegex.test( contentSize ) && type === 'constrained' ) { // translators: %s: container size (i.e. 600px etc) alignmentInfo.none = sprintf( __( 'Max %s wide' ), contentSize ); diff --git a/packages/block-editor/src/utils/parse-css-unit-to-px.js b/packages/block-editor/src/utils/parse-css-unit-to-px.js index da2337496f926e..8689de98696095 100644 --- a/packages/block-editor/src/utils/parse-css-unit-to-px.js +++ b/packages/block-editor/src/utils/parse-css-unit-to-px.js @@ -211,6 +211,26 @@ function convertParsedUnitToPx( parsedUnit, options ) { ex: 7.15625, // X-height of the element's font. Approximate. lh: setOptions.lineHeight, }; + relativeUnits.svw = relativeUnits.vmin; + relativeUnits.lvw = relativeUnits.vmax; + relativeUnits.dvw = relativeUnits.vw; + relativeUnits.svh = relativeUnits.vmin; + relativeUnits.lvh = relativeUnits.vmax; + relativeUnits.dvh = relativeUnits.vh; + relativeUnits.vi = relativeUnits.vh; + relativeUnits.svi = relativeUnits.vmin; + relativeUnits.lvi = relativeUnits.vmax; + relativeUnits.dvi = relativeUnits.vw; + relativeUnits.vb = relativeUnits.vh; + relativeUnits.svb = relativeUnits.vmin; + relativeUnits.lvb = relativeUnits.vmax; + relativeUnits.dvb = relativeUnits.vh; + relativeUnits.svmin = relativeUnits.vmin; + relativeUnits.lvmin = relativeUnits.vmin; + relativeUnits.dvmin = relativeUnits.vmin; + relativeUnits.svmax = relativeUnits.vmax; + relativeUnits.lvmax = relativeUnits.vmax; + relativeUnits.dvmax = relativeUnits.vmax; const absoluteUnits = { in: PIXELS_PER_INCH, diff --git a/packages/components/src/font-size-picker/utils.ts b/packages/components/src/font-size-picker/utils.ts index 492f47b7c62ace..cf81c7ed27b182 100644 --- a/packages/components/src/font-size-picker/utils.ts +++ b/packages/components/src/font-size-picker/utils.ts @@ -19,7 +19,8 @@ import { parseQuantityAndUnitFromRawValue } from '../unit-control'; export function isSimpleCssValue( value: NonNullable< FontSizePickerProps[ 'value' ] > ) { - const sizeRegex = /^[\d\.]+(px|em|rem|vw|vh|%)?$/i; + const sizeRegex = + /^[\d\.]+(px|em|rem|vw|vh|%|svw|lvw|dvw|svh|lvh|dvh|vi|svi|lvi|dvi|vb|svb|lvb|dvb|vmin|svmin|lvmin|dvmin|vmax|svmax|lvmax|dvmax)?$/i; return sizeRegex.test( String( value ) ); } diff --git a/packages/components/src/sandbox/index.native.js b/packages/components/src/sandbox/index.native.js index 0b1b0eb88f2def..b9bbc9a4e3281f 100644 --- a/packages/components/src/sandbox/index.native.js +++ b/packages/components/src/sandbox/index.native.js @@ -68,7 +68,7 @@ const observeAndResizeJS = ` style ) { if ( - /^\\d+(vmin|vmax|vh|vw)$/.test( ruleOrNode.style[ style ] ) + /^\\d+(vw|vh|svw|lvw|dvw|svh|lvh|dvh|vi|svi|lvi|dvi|vb|svb|lvb|dvb|vmin|svmin|lvmin|dvmin|vmax|svmax|lvmax|dvmax)$/.test( ruleOrNode.style[ style ] ) ) { ruleOrNode.style[ style ] = ''; } diff --git a/packages/components/src/sandbox/index.tsx b/packages/components/src/sandbox/index.tsx index ecd51e1fc26643..9d67160ddc606c 100644 --- a/packages/components/src/sandbox/index.tsx +++ b/packages/components/src/sandbox/index.tsx @@ -55,7 +55,9 @@ const observeAndResizeJS = function () { [ 'width', 'height', 'minHeight', 'maxHeight' ] as const ).forEach( function ( style ) { if ( - /^\\d+(vmin|vmax|vh|vw)$/.test( ruleOrNode.style[ style ] ) + /^\\d+(vw|vh|svw|lvw|dvw|svh|lvh|dvh|vi|svi|lvi|dvi|vb|svb|lvb|dvb|vmin|svmin|lvmin|dvmin|vmax|svmax|lvmax|dvmax)$/.test( + ruleOrNode.style[ style ] + ) ) { ruleOrNode.style[ style ] = ''; } diff --git a/packages/components/src/unit-control/utils.ts b/packages/components/src/unit-control/utils.ts index cbca50459086c0..15fd03cc930d67 100644 --- a/packages/components/src/unit-control/utils.ts +++ b/packages/components/src/unit-control/utils.ts @@ -102,6 +102,126 @@ const allUnits: Record< string, WPUnitControlUnit > = { a11yLabel: __( 'Points (pt)' ), step: 1, }, + svw: { + value: 'svw', + label: isWeb ? 'svw' : __( 'Small viewport width (svw)' ), + a11yLabel: __( 'Small viewport width (svw)' ), + step: 0.1, + }, + svh: { + value: 'svh', + label: isWeb ? 'svh' : __( 'Small viewport height (svh)' ), + a11yLabel: __( 'Small viewport height (svh)' ), + step: 0.1, + }, + svi: { + value: 'svi', + label: isWeb ? 'svi' : __( 'Small viewport width or height (svi)' ), + a11yLabel: __( 'Small viewport width or height (svi)' ), + step: 0.1, + }, + svb: { + value: 'svb', + label: isWeb ? 'svb' : __( 'Small viewport width or height (svb)' ), + a11yLabel: __( 'Small viewport width or height (svb)' ), + step: 0.1, + }, + svmin: { + value: 'svmin', + label: isWeb + ? 'svmin' + : __( 'Small viewport smallest dimension (svmin)' ), + a11yLabel: __( 'Small viewport smallest dimension (svmin)' ), + step: 0.1, + }, + lvw: { + value: 'lvw', + label: isWeb ? 'lvw' : __( 'Large viewport width (lvw)' ), + a11yLabel: __( 'Large viewport width (lvw)' ), + step: 0.1, + }, + lvh: { + value: 'lvh', + label: isWeb ? 'lvh' : __( 'Large viewport height (lvh)' ), + a11yLabel: __( 'Large viewport height (lvh)' ), + step: 0.1, + }, + lvi: { + value: 'lvi', + label: isWeb ? 'lvi' : __( 'Large viewport width or height (lvi)' ), + a11yLabel: __( 'Large viewport width or height (lvi)' ), + step: 0.1, + }, + lvb: { + value: 'lvb', + label: isWeb ? 'lvb' : __( 'Large viewport width or height (lvb)' ), + a11yLabel: __( 'Large viewport width or height (lvb)' ), + step: 0.1, + }, + lvmin: { + value: 'lvmin', + label: isWeb + ? 'lvmin' + : __( 'Large viewport smallest dimension (lvmin)' ), + a11yLabel: __( 'Large viewport smallest dimension (lvmin)' ), + step: 0.1, + }, + dvw: { + value: 'dvw', + label: isWeb ? 'dvw' : __( 'Dynamic viewport width (dvw)' ), + a11yLabel: __( 'Dynamic viewport width (dvw)' ), + step: 0.1, + }, + dvh: { + value: 'dvh', + label: isWeb ? 'dvh' : __( 'Dynamic viewport height (dvh)' ), + a11yLabel: __( 'Dynamic viewport height (dvh)' ), + step: 0.1, + }, + dvi: { + value: 'dvi', + label: isWeb ? 'dvi' : __( 'Dynamic viewport width or height (dvi)' ), + a11yLabel: __( 'Dynamic viewport width or height (dvi)' ), + step: 0.1, + }, + dvb: { + value: 'dvb', + label: isWeb ? 'dvb' : __( 'Dynamic viewport width or height (dvb)' ), + a11yLabel: __( 'Dynamic viewport width or height (dvb)' ), + step: 0.1, + }, + dvmin: { + value: 'dvmin', + label: isWeb + ? 'dvmin' + : __( 'Dynamic viewport smallest dimension (dvmin)' ), + a11yLabel: __( 'Dynamic viewport smallest dimension (dvmin)' ), + step: 0.1, + }, + dvmax: { + value: 'dvmax', + label: isWeb + ? 'dvmax' + : __( 'Dynamic viewport largest dimension (dvmax)' ), + a11yLabel: __( 'Dynamic viewport largest dimension (dvmax)' ), + step: 0.1, + }, + svmax: { + value: 'svmax', + label: isWeb + ? 'svmax' + : __( 'Small viewport largest dimension (svmax)' ), + a11yLabel: __( 'Small viewport largest dimension (svmax)' ), + step: 0.1, + }, + lvmax: { + value: 'lvmax', + label: isWeb + ? 'lvmax' + : __( 'Large viewport largest dimension (lvmax)' ), + a11yLabel: __( 'Large viewport largest dimension (lvmax)' ), + step: 0.1, + }, }; /** diff --git a/packages/components/src/utils/unit-values.ts b/packages/components/src/utils/unit-values.ts index e38c65494c1a36..7bd09ab67ec97f 100644 --- a/packages/components/src/utils/unit-values.ts +++ b/packages/components/src/utils/unit-values.ts @@ -1,5 +1,5 @@ const UNITED_VALUE_REGEX = - /^([\d.\-+]*)\s*(fr|cm|mm|Q|in|pc|pt|px|em|ex|ch|rem|lh|vw|vh|vmin|vmax|%|cap|ic|rlh|vi|vb|deg|grad|rad|turn|s|ms|Hz|kHz|dpi|dpcm|dppx)?$/; + /^([\d.\-+]*)\s*(fr|cm|mm|Q|in|pc|pt|px|em|ex|ch|rem|lh|vw|vh|vmin|vmax|%|cap|ic|rlh|vi|vb|deg|grad|rad|turn|s|ms|Hz|kHz|dpi|dpcm|dppx|svw|lvw|dvw|svh|lvh|dvh|svi|lvi|dvi|svb|lvb|dvb|svmin|lvmin|dvmin|svmax|lvmax|dvmax)?$/; /** * Parses a number and unit from a value. diff --git a/schemas/json/theme.json b/schemas/json/theme.json index f7b3fdb819fc22..e795efc4894fb9 100644 --- a/schemas/json/theme.json +++ b/schemas/json/theme.json @@ -428,9 +428,31 @@ "px", "em", "rem", - "vh", + "%", "vw", - "%" + "svw", + "lvw", + "dvw", + "vh", + "svh", + "lvh", + "dvh", + "vi", + "svi", + "lvi", + "dvi", + "vb", + "svb", + "lvb", + "dvb", + "vmin", + "svmin", + "lvmin", + "dvmin", + "vmax", + "svmax", + "lvmax", + "dvmax" ], "default": "rem" }