UNPKG

@wordpress/components

Version:
130 lines (116 loc) 3.52 kB
/** * External dependencies */ import gradientParser from 'gradient-parser'; import { colord, extend } from 'colord'; import namesPlugin from 'colord/plugins/names'; /** * Internal dependencies */ import { DEFAULT_GRADIENT, HORIZONTAL_GRADIENT_ORIENTATION, DIRECTIONAL_ORIENTATION_ANGLE_MAP, } from './constants'; import { serializeGradient } from './serializer'; import type { ControlPoint } from './types'; extend( [ namesPlugin ] ); export function getLinearGradientRepresentation( gradientAST: gradientParser.GradientNode ) { return serializeGradient( { type: 'linear-gradient', orientation: HORIZONTAL_GRADIENT_ORIENTATION, colorStops: gradientAST.colorStops, } ); } function hasUnsupportedLength( item: gradientParser.ColorStop ) { return item.length === undefined || item.length.type !== '%'; } export function getGradientAstWithDefault( value?: string | null ) { // gradientAST will contain the gradient AST as parsed by gradient-parser npm module. // More information of its structure available at https://www.npmjs.com/package/gradient-parser#ast. let gradientAST: gradientParser.GradientNode | undefined; let hasGradient = !! value; const valueToParse = value ?? DEFAULT_GRADIENT; try { gradientAST = gradientParser.parse( valueToParse )[ 0 ]; } catch ( error ) { // eslint-disable-next-line no-console console.warn( 'wp.components.CustomGradientPicker failed to parse the gradient with error', error ); gradientAST = gradientParser.parse( DEFAULT_GRADIENT )[ 0 ]; hasGradient = false; } if ( ! Array.isArray( gradientAST.orientation ) && gradientAST.orientation?.type === 'directional' ) { gradientAST.orientation = { type: 'angular', value: DIRECTIONAL_ORIENTATION_ANGLE_MAP[ gradientAST.orientation.value ].toString(), }; } if ( gradientAST.colorStops.some( hasUnsupportedLength ) ) { const { colorStops } = gradientAST; const step = 100 / ( colorStops.length - 1 ); colorStops.forEach( ( stop, index ) => { stop.length = { value: `${ step * index }`, type: '%', }; } ); } return { gradientAST, hasGradient }; } export function getGradientAstWithControlPoints( gradientAST: gradientParser.GradientNode, newControlPoints: ControlPoint[] ) { return { ...gradientAST, colorStops: newControlPoints.map( ( { position, color } ) => { const { r, g, b, a } = colord( color ).toRgb(); return { length: { type: '%', value: position?.toString(), }, type: a < 1 ? 'rgba' : 'rgb', value: a < 1 ? [ `${ r }`, `${ g }`, `${ b }`, `${ a }` ] : [ `${ r }`, `${ g }`, `${ b }` ], }; } ), } as gradientParser.GradientNode; } export function getStopCssColor( colorStop: gradientParser.ColorStop ) { switch ( colorStop.type ) { case 'hex': return `#${ colorStop.value }`; case 'literal': return colorStop.value; case 'var': return `${ colorStop.type }(${ colorStop.value })`; case 'rgb': case 'rgba': return `${ colorStop.type }(${ colorStop.value.join( ',' ) })`; case 'hsl': { const [ hue, saturation, lightness ] = colorStop.value; return `hsl(${ hue },${ saturation }%,${ lightness }%)`; } case 'hsla': { const [ hue, saturation, lightness, alpha ] = colorStop.value; return `hsla(${ hue },${ saturation }%,${ lightness }%,${ alpha })`; } default: // Should be unreachable if passing an AST from gradient-parser. // See https://github.com/rafaelcaricio/gradient-parser#ast. return 'transparent'; } }