UNPKG

@builder.io/mitosis

Version:

Write components once, run everywhere. Compiles to Vue, React, Solid, and Liquid. Import code from Figma and Builder.io

134 lines (133 loc) 5.8 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.cleanReactNativeBlockStyles = void 0; const extract_css_var_default_value_1 = require("./extract-css-var-default-value"); const lengthPattern = /^-?\d*\.?\d+(px|%)?$/; const pixelPattern = /^-?\d*\.?\d+(px)?$/; const numberPattern = /^-?\d*\.?\d+$/; const colorPattern = /^(#[0-9A-Fa-f]{3,8}|(rgb|hsl)a?\(.*\)|[a-zA-Z]+)$/; // List of unsupported properties in React Native const unsupportedProps = [ 'textShadow', 'boxShadow', 'transition', 'cursor', 'filter', 'overflowX', 'overflowY', 'animation', 'backgroundImage', 'backgroundPosition', 'backgroundSize', 'backgroundRepeat', 'whiteSpace', ]; // Ensure CSS property value is valid for React Native function validateReactNativeCssProperty(key, value) { const cssProperties = { width: (value) => lengthPattern.test(value), height: (value) => lengthPattern.test(value), backgroundColor: (value) => pixelPattern.test(value) || /^#[0-9A-Fa-f]{6}/.test(value), minWidth: (value) => lengthPattern.test(value) || value === 'auto', maxWidth: (value) => lengthPattern.test(value) || value === 'auto', minHeight: (value) => lengthPattern.test(value) || value === 'auto', maxHeight: (value) => lengthPattern.test(value) || value === 'auto', aspectRatio: (value) => numberPattern.test(value) || /^\d+\/\d+$/.test(value), // Flexbox Properties flex: (value) => numberPattern.test(value), flexBasis: (value) => lengthPattern.test(value) || value === 'auto', flexDirection: (value) => ['row', 'row-reverse', 'column', 'column-reverse'].includes(value), flexGrow: (value) => numberPattern.test(value), flexShrink: (value) => numberPattern.test(value), flexWrap: (value) => ['wrap', 'nowrap', 'wrap-reverse'].includes(value), // Alignment Properties alignContent: (value) => ['flex-start', 'flex-end', 'center', 'stretch', 'space-between', 'space-around'].includes(value), alignItems: (value) => ['flex-start', 'flex-end', 'center', 'stretch', 'baseline'].includes(value), alignSelf: (value) => ['auto', 'flex-start', 'flex-end', 'center', 'stretch', 'baseline'].includes(value), justifyContent: (value) => [ 'flex-start', 'flex-end', 'center', 'space-between', 'space-around', 'space-evenly', ].includes(value), // Text Properties color: (value) => colorPattern.test(value), fontFamily: () => true, // Any string is valid fontSize: (value) => pixelPattern.test(value), fontStyle: (value) => ['normal', 'italic'].includes(value), fontWeight: (value) => ['normal', 'bold', '100', '200', '300', '400', '500', '600', '700', '800', '900'].includes(value), display: (value) => ['none', 'flex'].includes(value), }; // If the property is not explicitly defined, consider it valid if (!cssProperties[key]) return true; // Convert number to string for validation const stringValue = typeof value === 'number' ? value.toString() : value; return cssProperties[key](stringValue); } // Clean up shorthand and unsupported styles for React Native function cleanReactNativeBlockStyles(styles) { return Object.entries(styles).reduce((acc, [key, value]) => { var _a; // Remove unsupported properties if (unsupportedProps.includes(key)) return acc; // Handle CSS variables if (typeof value === 'string' && value.includes('var(')) { value = (_a = (0, extract_css_var_default_value_1.extractCssVarDefaultValue)(value)) !== null && _a !== void 0 ? _a : value; } // Parse pixel units if (typeof value === 'string') { const pixelMatch = value.match(/^(-?\d+(\.\d+)?)px$/); if (pixelMatch) value = parseFloat(pixelMatch[1]); } // Handle shorthand properties if (key === 'margin' || key === 'padding') { return { ...acc, ...expandShorthand(key, value) }; } // Convert 'background' to 'backgroundColor' if (key === 'background' && typeof value === 'string') { acc.backgroundColor = value; return { ...acc, backgroundColor: value }; } // Handle borderRadius if (key === 'borderRadius' && typeof value === 'string') { return { ...acc, ...expandBorderRadius(value) }; } // Handle invalid display values if (key === 'display' && value !== 'flex' && value !== 'none') { return acc; } // Validate and add the property if (validateReactNativeCssProperty(key, value)) { acc[key] = value; } return acc; }, {}); } exports.cleanReactNativeBlockStyles = cleanReactNativeBlockStyles; function expandShorthand(property, value) { if (typeof value !== 'string') return { [property]: value }; const values = value.split(' ').map((v) => parseFloat(v) || 0); const [top, right = top, bottom = top, left = right] = values; return { [`${property}Top`]: top, [`${property}Right`]: right, [`${property}Bottom`]: bottom, [`${property}Left`]: left, }; } function expandBorderRadius(value) { const values = value.split(' ').map((v) => parseInt(v, 10)); const [topLeft, topRight = topLeft, bottomRight = topLeft, bottomLeft = topRight] = values; return { borderTopLeftRadius: topLeft, borderTopRightRadius: topRight, borderBottomRightRadius: bottomRight, borderBottomLeftRadius: bottomLeft, }; }