@wordpress/editor
Version:
Enhanced block editor for WordPress posts.
8 lines (7 loc) • 11.3 kB
Source Map (JSON)
{
"version": 3,
"sources": ["../../../src/hooks/push-changes-to-global-styles/format-style-value.js"],
"sourcesContent": ["import { capitalCase } from 'change-case';\n\n// Em dash shown when a value isn't set.\nexport const EMPTY_VALUE_LABEL = '\\u2014';\n\n// Preset values come in two forms: the user form `var:preset|color|vivid-red`\n// and the CSS custom property form `var(--wp--preset--color--vivid-red)`. In\n// both the slug (e.g. `vivid-red`) is the last segment.\nconst PRESET_USER_PREFIX = 'var:preset|';\nconst PRESET_CSS_VAR_REGEX =\n\t/^var\\(\\s*--wp--preset--[a-z0-9-]+?\\s*(?:,[^)]*)?\\)$/i;\n\n// Returns a preset's slug from either form, or `undefined` when the value isn't\n// a preset.\nfunction getPresetSlug( value ) {\n\tif ( value.startsWith( PRESET_USER_PREFIX ) ) {\n\t\treturn value.split( '|' ).pop();\n\t}\n\tif ( PRESET_CSS_VAR_REGEX.test( value ) ) {\n\t\treturn value\n\t\t\t.replace( /^var\\(\\s*/, '' )\n\t\t\t.replace( /\\s*(?:,[^)]*)?\\)$/, '' )\n\t\t\t.split( '--' )\n\t\t\t.pop();\n\t}\n\treturn undefined;\n}\n\n// True when a value is actually set.\nconst isSet = ( value ) =>\n\tvalue !== undefined && value !== null && value !== '';\n\nconst BORDER_SIDES = [ 'top', 'right', 'bottom', 'left' ];\n\n// Global Styles stores border style, width and color per side (e.g.\n// `border.top.style`). Collapse a per-side border object to flat\n// `{ width, style, color }`, keeping a value only when every set side agrees.\nfunction flattenBorder( border ) {\n\tif (\n\t\tisSet( border.width ) ||\n\t\tisSet( border.style ) ||\n\t\tisSet( border.color )\n\t) {\n\t\treturn border;\n\t}\n\n\tconst setSides = BORDER_SIDES.filter( ( side ) => border[ side ] );\n\tif ( ! setSides.length ) {\n\t\treturn border;\n\t}\n\n\tconst collapse = ( property ) => {\n\t\tconst values = setSides.map( ( side ) => border[ side ]?.[ property ] );\n\t\treturn values.every( ( value ) => value === values[ 0 ] )\n\t\t\t? values[ 0 ]\n\t\t\t: undefined;\n\t};\n\n\treturn {\n\t\twidth: collapse( 'width' ),\n\t\tstyle: collapse( 'style' ),\n\t\tcolor: collapse( 'color' ),\n\t};\n}\n\n/**\n * Turns a raw style value into readable text for the modal.\n *\n * - Empty, `null` or `undefined`: an em dash.\n * - Preset values (`var:preset|type|slug` or `var(--wp--preset--type--slug)`):\n * the readable slug.\n * - Strings and numbers: used as-is.\n * - Objects and arrays (like a border side): turned into text, or an em dash\n * when there's nothing to show.\n *\n * @param {*} value The raw style value.\n *\n * @return {string} Readable text for the value.\n */\nexport function formatStyleValue( value ) {\n\tif ( ! isSet( value ) ) {\n\t\treturn EMPTY_VALUE_LABEL;\n\t}\n\n\tif ( typeof value === 'string' ) {\n\t\tconst presetSlug = getPresetSlug( value );\n\t\tif ( presetSlug ) {\n\t\t\treturn capitalCase( presetSlug );\n\t\t}\n\t\treturn value;\n\t}\n\n\tif ( typeof value === 'number' ) {\n\t\treturn String( value );\n\t}\n\n\tif ( typeof value === 'object' ) {\n\t\ttry {\n\t\t\tconst stringified = JSON.stringify( value );\n\t\t\treturn stringified && stringified !== '{}' && stringified !== '[]'\n\t\t\t\t? stringified\n\t\t\t\t: EMPTY_VALUE_LABEL;\n\t\t} catch {\n\t\t\treturn EMPTY_VALUE_LABEL;\n\t\t}\n\t}\n\n\treturn String( value );\n}\n\n/**\n * Turns a border object into a single CSS `border` value, e.g.\n * `2px dashed #000fff`.\n *\n * The parts follow the CSS order of `width style color`, anything that isn't\n * set is left out, and preset colors are shown by name. A per-side object (as\n * Global Styles stores borders) is collapsed to its shared values first.\n * Returns an em dash when the border has nothing set.\n *\n * @param {*} border A border object, e.g. `{ color, width, style }`, or a\n * per-side object, e.g. `{ top: { style } }`.\n *\n * @return {string} The combined border value, or an em dash.\n */\nexport function formatBorderShorthand( border ) {\n\tif ( ! border || typeof border !== 'object' ) {\n\t\treturn formatStyleValue( border );\n\t}\n\n\tconst { width, style, color } = flattenBorder( border );\n\tconst parts = [ width, style, color ]\n\t\t.filter( isSet )\n\t\t.map( ( part ) => formatStyleValue( part ) );\n\n\treturn parts.length ? parts.join( ' ' ) : EMPTY_VALUE_LABEL;\n}\n\n// Corner order used by the CSS `border-radius` shorthand.\nconst RADIUS_CORNERS = [ 'topLeft', 'topRight', 'bottomRight', 'bottomLeft' ];\n\n/**\n * Turns a border radius into readable text.\n *\n * A plain string is used as-is. An object with a value per corner is joined in\n * CSS corner order, e.g. `1px 20px 1px 15px`. Returns an em dash when there's\n * nothing to show.\n *\n * @param {*} radius A radius string or an object with a value per corner.\n *\n * @return {string} The readable radius, or an em dash.\n */\nexport function formatBorderRadius( radius ) {\n\tif ( radius && typeof radius === 'object' ) {\n\t\tconst parts = RADIUS_CORNERS.map(\n\t\t\t( corner ) => radius[ corner ]\n\t\t).filter( isSet );\n\t\treturn parts.length ? parts.join( ' ' ) : EMPTY_VALUE_LABEL;\n\t}\n\n\treturn formatStyleValue( radius );\n}\n\n/**\n * Turns a spacing value (padding or margin) into a single CSS value.\n *\n * A plain string is used as-is. An object with a value per side is shortened\n * to the smallest CSS form: one value when every side matches, a\n * `vertical horizontal` pair when top/bottom and left/right match, otherwise\n * all four sides in `top right bottom left` order.\n *\n * The optional `resolve` callback swaps a raw value for its real one first,\n * e.g. turning `var:preset|spacing|40` into its actual size, which reads\n * better than the preset name.\n *\n * @param {*} spacing A spacing string or an object with a value per side.\n * @param {Function} resolve Optional callback to resolve each raw value.\n *\n * @return {string} The combined spacing, or an em dash.\n */\nexport function formatSpacingShorthand(\n\tspacing,\n\tresolve = ( value ) => value\n) {\n\tconst format = ( value ) => formatStyleValue( resolve( value ) );\n\n\tif ( ! spacing || typeof spacing !== 'object' ) {\n\t\treturn format( spacing );\n\t}\n\n\tconst { top, right, bottom, left } = spacing;\n\n\tif ( isSet( top ) && isSet( right ) && isSet( bottom ) && isSet( left ) ) {\n\t\tif ( top === right && right === bottom && bottom === left ) {\n\t\t\treturn format( top );\n\t\t}\n\t\tif ( top === bottom && left === right ) {\n\t\t\treturn `${ format( top ) } ${ format( left ) }`;\n\t\t}\n\t\treturn [ top, right, bottom, left ].map( format ).join( ' ' );\n\t}\n\n\tif (\n\t\t! isSet( top ) &&\n\t\t! isSet( right ) &&\n\t\t! isSet( bottom ) &&\n\t\t! isSet( left )\n\t) {\n\t\treturn EMPTY_VALUE_LABEL;\n\t}\n\n\t// Keep all four slots so an unset side still shows its position.\n\treturn [ top, right, bottom, left ]\n\t\t.map( ( value ) =>\n\t\t\tisSet( value ) ? format( value ) : EMPTY_VALUE_LABEL\n\t\t)\n\t\t.join( ' ' );\n}\n\n/**\n * Turns a block gap value into readable text.\n *\n * A plain string is used as-is. An axial object with a `top` (row) and `left`\n * (column) gap reads as one value when both match, or `row - column` when they\n * differ.\n *\n * The optional `resolve` callback swaps a raw value for its real one first,\n * e.g. turning `var:preset|spacing|40` into its actual size.\n *\n * @param {*} gap A gap string or an axial `{ top, left }` object.\n * @param {Function} resolve Optional callback to resolve each raw value.\n *\n * @return {string} The readable gap, or an em dash.\n */\nexport function formatBlockGap( gap, resolve = ( value ) => value ) {\n\tconst format = ( value ) => formatStyleValue( resolve( value ) );\n\n\tif ( ! gap || typeof gap !== 'object' ) {\n\t\treturn format( gap );\n\t}\n\n\tconst { top: row, left: column } = gap;\n\n\tif ( ! isSet( row ) && ! isSet( column ) ) {\n\t\treturn EMPTY_VALUE_LABEL;\n\t}\n\n\tif ( row === column ) {\n\t\treturn format( row );\n\t}\n\n\tconst rowLabel = isSet( row ) ? format( row ) : EMPTY_VALUE_LABEL;\n\tconst columnLabel = isSet( column ) ? format( column ) : EMPTY_VALUE_LABEL;\n\n\treturn `${ rowLabel } - ${ columnLabel }`;\n}\n"],
"mappings": "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",
"names": []
}