UNPKG

@wordpress/components

Version:
154 lines (152 loc) 4.91 kB
/** * External dependencies */ import { View, Platform } from 'react-native'; import RNLinearGradient from 'react-native-linear-gradient'; import gradientParser from 'gradient-parser'; /** * WordPress dependencies */ import { RadialGradient, Stop, SVG, Defs, Rect } from '@wordpress/primitives'; import { useResizeObserver } from '@wordpress/compose'; import { useMemo } from '@wordpress/element'; /** * Internal dependencies */ import styles from './style.scss'; import { colorsUtils } from '../color-settings/utils'; import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime"; export function getGradientAngle(gradientValue) { const angleBase = 45; const matchAngle = /\(((\d+deg)|(to\s[^,]+))/; const angle = matchAngle.exec(gradientValue) ? matchAngle.exec(gradientValue)[1] : '180deg'; const angleType = angle.includes('deg') ? 'angle' : 'sideOrCorner'; if (angleType === 'sideOrCorner') { switch (angle) { case 'to top': return 0; case 'to top right': case 'to right top': return angleBase; case 'to right': return 2 * angleBase; case 'to bottom right': case 'to right bottom': return 3 * angleBase; case 'to bottom': return 4 * angleBase; case 'to bottom left': case 'to left bottom': return 5 * angleBase; case 'to left': return 6 * angleBase; case 'to top left': case 'to left top': return 7 * angleBase; } } else if (angleType === 'angle') { return parseFloat(angle); } else { return 4 * angleBase; } } export function getGradientColorGroup(gradientValue) { const colorNeedParenthesis = ['rgb', 'rgba']; const excludeSideOrCorner = /linear-gradient\(to\s+([a-z\s]+,)/; // Parser has some difficulties with angle defined as a side or corner (e.g. `to left`) // so it's going to be excluded in order to matching color groups. const modifiedGradientValue = gradientValue.replace(excludeSideOrCorner, 'linear-gradient('); return [].concat(...gradientParser.parse(modifiedGradientValue)?.map(gradient => gradient.colorStops?.map((color, index) => { const { type, value, length } = color; const fallbackLength = `${100 * (index / (gradient.colorStops.length - 1))}%`; const colorLength = length ? `${length.value}${length.type}` : fallbackLength; if (colorNeedParenthesis.includes(type)) { return [`${type}(${value.join(',')})`, colorLength]; } else if (type === 'literal') { return [value, colorLength]; } return [`#${value}`, colorLength]; }))); } export function getGradientBaseColors(colorGroup) { return colorGroup.map(color => color[0]); } export function getColorLocations(colorGroup) { return colorGroup.map(location => Number(location[1].replace('%', '')) / 100); } function Gradient({ gradientValue, style, angleCenter = { x: 0.5, y: 0.5 }, children, ...otherProps }) { const [resizeObserver, sizes] = useResizeObserver(); const { width = 0, height = 0 } = sizes || {}; const { isGradient, getGradientType, gradients } = colorsUtils; const colorGroup = useMemo(() => getGradientColorGroup(gradientValue), [gradientValue]); const locations = useMemo(() => getColorLocations(colorGroup), [colorGroup]); const colors = useMemo(() => getGradientBaseColors(colorGroup), [colorGroup]); if (!gradientValue || !isGradient(gradientValue)) { return null; } const isLinearGradient = getGradientType(gradientValue) === gradients.linear; if (isLinearGradient) { return /*#__PURE__*/_jsx(RNLinearGradient, { colors: colors, useAngle: true, angle: getGradientAngle(gradientValue), locations: locations, angleCenter: angleCenter, style: style, ...otherProps, children: children }); } return /*#__PURE__*/_jsxs(View, { style: [style, styles.overflow], children: [/*#__PURE__*/_jsx(View, { style: styles.radialGradientContent, children: children }), resizeObserver, /*#__PURE__*/_jsxs(SVG, { children: [/*#__PURE__*/_jsx(Defs, { children: /*#__PURE__*/_jsx(RadialGradient // eslint-disable-next-line no-restricted-syntax , { id: "radialGradient", gradientUnits: "userSpaceOnUse", rx: "70%", ry: "70%", cy: Platform.OS === 'android' ? width / 2 : '50%', children: colorGroup.map(group => { return /*#__PURE__*/_jsx(Stop, { offset: group[1], stopColor: group[0], stopOpacity: "1" }, `${group[1]}-${group[0]}`); }) }) }), /*#__PURE__*/_jsx(Rect, { height: height, width: width, fill: "url(#radialGradient)" })] })] }); } export default Gradient; //# sourceMappingURL=index.native.js.map