@wordpress/components
Version:
UI components for WordPress.
130 lines (116 loc) • 3.52 kB
text/typescript
/**
* 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';
}
}