@builder.io/mitosis 0.5.0 → 0.5.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/src/generators/react/generator.js +1 -1
- package/dist/src/generators/react/types.d.ts +1 -0
- package/dist/src/generators/react-native/extract-css-var-default-value.d.ts +1 -0
- package/dist/src/generators/react-native/extract-css-var-default-value.js +15 -0
- package/dist/src/generators/react-native/helpers.d.ts +3 -0
- package/dist/src/generators/react-native/helpers.js +133 -0
- package/dist/src/generators/react-native/index.d.ts +2 -1
- package/dist/src/generators/react-native/index.js +3 -3
- package/dist/src/generators/react-native/sanitize-react-native-block-styles.d.ts +2 -1
- package/dist/src/generators/react-native/sanitize-react-native-block-styles.js +8 -2
- package/dist/src/generators/react-native/types.d.ts +1 -0
- package/dist/src/parsers/jsx/state.js +4 -1
- package/package.json +1 -3
|
@@ -342,7 +342,7 @@ const _componentToReact = (json, options, isSubComponent = false) => {
|
|
|
342
342
|
// NOTE: `collectReactNativeStyles` must run before style generation in the component generation body, as it has
|
|
343
343
|
// side effects that delete styles bindings from the JSON.
|
|
344
344
|
const reactNativeStyles = options.stylesType === 'react-native' && componentHasStyles
|
|
345
|
-
? (0, react_native_1.collectReactNativeStyles)(json)
|
|
345
|
+
? (0, react_native_1.collectReactNativeStyles)(json, options)
|
|
346
346
|
: undefined;
|
|
347
347
|
const propType = json.propsTypeRef || 'any';
|
|
348
348
|
const componentArgs = [`props${options.typescript ? `:${propType}` : ''}`, options.forwardRef]
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare function extractCssVarDefaultValue(value: string): string;
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.extractCssVarDefaultValue = void 0;
|
|
4
|
+
function extractCssVarDefaultValue(value) {
|
|
5
|
+
// Regular expression to find var() expressions
|
|
6
|
+
const varRegex = /var\(--[^,]+?,\s*([^)]+)\)/;
|
|
7
|
+
// Function to replace var() with its fallback
|
|
8
|
+
let newValue = value;
|
|
9
|
+
let match;
|
|
10
|
+
while ((match = newValue.match(varRegex))) {
|
|
11
|
+
newValue = newValue.replace(match[0], match[1].trim());
|
|
12
|
+
}
|
|
13
|
+
return newValue;
|
|
14
|
+
}
|
|
15
|
+
exports.extractCssVarDefaultValue = extractCssVarDefaultValue;
|
|
@@ -0,0 +1,133 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.cleanReactNativeBlockStyles = void 0;
|
|
4
|
+
const extract_css_var_default_value_1 = require("./extract-css-var-default-value");
|
|
5
|
+
const lengthPattern = /^-?\d*\.?\d+(px|%)?$/;
|
|
6
|
+
const pixelPattern = /^-?\d*\.?\d+(px)?$/;
|
|
7
|
+
const numberPattern = /^-?\d*\.?\d+$/;
|
|
8
|
+
const colorPattern = /^(#[0-9A-Fa-f]{3,8}|(rgb|hsl)a?\(.*\)|[a-zA-Z]+)$/;
|
|
9
|
+
// List of unsupported properties in React Native
|
|
10
|
+
const unsupportedProps = [
|
|
11
|
+
'textShadow',
|
|
12
|
+
'boxShadow',
|
|
13
|
+
'transition',
|
|
14
|
+
'cursor',
|
|
15
|
+
'filter',
|
|
16
|
+
'overflowX',
|
|
17
|
+
'overflowY',
|
|
18
|
+
'animation',
|
|
19
|
+
'backgroundImage',
|
|
20
|
+
'backgroundPosition',
|
|
21
|
+
'backgroundSize',
|
|
22
|
+
'backgroundRepeat',
|
|
23
|
+
'whiteSpace',
|
|
24
|
+
];
|
|
25
|
+
// Ensure CSS property value is valid for React Native
|
|
26
|
+
function validateReactNativeCssProperty(key, value) {
|
|
27
|
+
const cssProperties = {
|
|
28
|
+
width: (value) => lengthPattern.test(value),
|
|
29
|
+
height: (value) => lengthPattern.test(value),
|
|
30
|
+
backgroundColor: (value) => pixelPattern.test(value) || /^#[0-9A-Fa-f]{6}/.test(value),
|
|
31
|
+
minWidth: (value) => lengthPattern.test(value) || value === 'auto',
|
|
32
|
+
maxWidth: (value) => lengthPattern.test(value) || value === 'auto',
|
|
33
|
+
minHeight: (value) => lengthPattern.test(value) || value === 'auto',
|
|
34
|
+
maxHeight: (value) => lengthPattern.test(value) || value === 'auto',
|
|
35
|
+
aspectRatio: (value) => numberPattern.test(value) || /^\d+\/\d+$/.test(value),
|
|
36
|
+
// Flexbox Properties
|
|
37
|
+
flex: (value) => numberPattern.test(value),
|
|
38
|
+
flexBasis: (value) => lengthPattern.test(value) || value === 'auto',
|
|
39
|
+
flexDirection: (value) => ['row', 'row-reverse', 'column', 'column-reverse'].includes(value),
|
|
40
|
+
flexGrow: (value) => numberPattern.test(value),
|
|
41
|
+
flexShrink: (value) => numberPattern.test(value),
|
|
42
|
+
flexWrap: (value) => ['wrap', 'nowrap', 'wrap-reverse'].includes(value),
|
|
43
|
+
// Alignment Properties
|
|
44
|
+
alignContent: (value) => ['flex-start', 'flex-end', 'center', 'stretch', 'space-between', 'space-around'].includes(value),
|
|
45
|
+
alignItems: (value) => ['flex-start', 'flex-end', 'center', 'stretch', 'baseline'].includes(value),
|
|
46
|
+
alignSelf: (value) => ['auto', 'flex-start', 'flex-end', 'center', 'stretch', 'baseline'].includes(value),
|
|
47
|
+
justifyContent: (value) => [
|
|
48
|
+
'flex-start',
|
|
49
|
+
'flex-end',
|
|
50
|
+
'center',
|
|
51
|
+
'space-between',
|
|
52
|
+
'space-around',
|
|
53
|
+
'space-evenly',
|
|
54
|
+
].includes(value),
|
|
55
|
+
// Text Properties
|
|
56
|
+
color: (value) => colorPattern.test(value),
|
|
57
|
+
fontFamily: () => true, // Any string is valid
|
|
58
|
+
fontSize: (value) => pixelPattern.test(value),
|
|
59
|
+
fontStyle: (value) => ['normal', 'italic'].includes(value),
|
|
60
|
+
fontWeight: (value) => ['normal', 'bold', '100', '200', '300', '400', '500', '600', '700', '800', '900'].includes(value),
|
|
61
|
+
display: (value) => ['none', 'flex'].includes(value),
|
|
62
|
+
};
|
|
63
|
+
// If the property is not explicitly defined, consider it valid
|
|
64
|
+
if (!cssProperties[key])
|
|
65
|
+
return true;
|
|
66
|
+
// Convert number to string for validation
|
|
67
|
+
const stringValue = typeof value === 'number' ? value.toString() : value;
|
|
68
|
+
return cssProperties[key](stringValue);
|
|
69
|
+
}
|
|
70
|
+
// Clean up shorthand and unsupported styles for React Native
|
|
71
|
+
function cleanReactNativeBlockStyles(styles) {
|
|
72
|
+
return Object.entries(styles).reduce((acc, [key, value]) => {
|
|
73
|
+
var _a;
|
|
74
|
+
// Remove unsupported properties
|
|
75
|
+
if (unsupportedProps.includes(key))
|
|
76
|
+
return acc;
|
|
77
|
+
// Handle CSS variables
|
|
78
|
+
if (typeof value === 'string' && value.includes('var(')) {
|
|
79
|
+
value = (_a = (0, extract_css_var_default_value_1.extractCssVarDefaultValue)(value)) !== null && _a !== void 0 ? _a : value;
|
|
80
|
+
}
|
|
81
|
+
// Parse pixel units
|
|
82
|
+
if (typeof value === 'string') {
|
|
83
|
+
const pixelMatch = value.match(/^(-?\d+(\.\d+)?)px$/);
|
|
84
|
+
if (pixelMatch)
|
|
85
|
+
value = parseFloat(pixelMatch[1]);
|
|
86
|
+
}
|
|
87
|
+
// Handle shorthand properties
|
|
88
|
+
if (key === 'margin' || key === 'padding') {
|
|
89
|
+
return { ...acc, ...expandShorthand(key, value) };
|
|
90
|
+
}
|
|
91
|
+
// Convert 'background' to 'backgroundColor'
|
|
92
|
+
if (key === 'background' && typeof value === 'string') {
|
|
93
|
+
acc.backgroundColor = value;
|
|
94
|
+
return { ...acc, backgroundColor: value };
|
|
95
|
+
}
|
|
96
|
+
// Handle borderRadius
|
|
97
|
+
if (key === 'borderRadius' && typeof value === 'string') {
|
|
98
|
+
return { ...acc, ...expandBorderRadius(value) };
|
|
99
|
+
}
|
|
100
|
+
// Handle invalid display values
|
|
101
|
+
if (key === 'display' && value !== 'flex' && value !== 'none') {
|
|
102
|
+
return acc;
|
|
103
|
+
}
|
|
104
|
+
// Validate and add the property
|
|
105
|
+
if (validateReactNativeCssProperty(key, value)) {
|
|
106
|
+
acc[key] = value;
|
|
107
|
+
}
|
|
108
|
+
return acc;
|
|
109
|
+
}, {});
|
|
110
|
+
}
|
|
111
|
+
exports.cleanReactNativeBlockStyles = cleanReactNativeBlockStyles;
|
|
112
|
+
function expandShorthand(property, value) {
|
|
113
|
+
if (typeof value !== 'string')
|
|
114
|
+
return { [property]: value };
|
|
115
|
+
const values = value.split(' ').map((v) => parseFloat(v) || 0);
|
|
116
|
+
const [top, right = top, bottom = top, left = right] = values;
|
|
117
|
+
return {
|
|
118
|
+
[`${property}Top`]: top,
|
|
119
|
+
[`${property}Right`]: right,
|
|
120
|
+
[`${property}Bottom`]: bottom,
|
|
121
|
+
[`${property}Left`]: left,
|
|
122
|
+
};
|
|
123
|
+
}
|
|
124
|
+
function expandBorderRadius(value) {
|
|
125
|
+
const values = value.split(' ').map((v) => parseInt(v, 10));
|
|
126
|
+
const [topLeft, topRight = topLeft, bottomRight = topLeft, bottomLeft = topRight] = values;
|
|
127
|
+
return {
|
|
128
|
+
borderTopLeftRadius: topLeft,
|
|
129
|
+
borderTopRightRadius: topRight,
|
|
130
|
+
borderBottomRightRadius: bottomRight,
|
|
131
|
+
borderBottomLeftRadius: bottomLeft,
|
|
132
|
+
};
|
|
133
|
+
}
|
|
@@ -2,5 +2,6 @@ import { ToReactNativeOptions } from '../../generators/react-native/types';
|
|
|
2
2
|
import { ClassStyleMap } from '../../helpers/styles/helpers';
|
|
3
3
|
import { MitosisComponent } from '../../types/mitosis-component';
|
|
4
4
|
import { TranspilerGenerator } from '../../types/transpiler';
|
|
5
|
-
|
|
5
|
+
import { ToReactOptions } from '../react';
|
|
6
|
+
export declare const collectReactNativeStyles: (json: MitosisComponent, options: ToReactOptions) => ClassStyleMap;
|
|
6
7
|
export declare const componentToReactNative: TranspilerGenerator<Partial<ToReactNativeOptions>>;
|
|
@@ -25,7 +25,7 @@ const sanitizeStyle = (obj) => (key, value) => {
|
|
|
25
25
|
return;
|
|
26
26
|
}
|
|
27
27
|
};
|
|
28
|
-
const collectReactNativeStyles = (json) => {
|
|
28
|
+
const collectReactNativeStyles = (json, options) => {
|
|
29
29
|
const styleMap = {};
|
|
30
30
|
const componentIndexes = {};
|
|
31
31
|
const getStyleSheetName = (item) => {
|
|
@@ -45,7 +45,7 @@ const collectReactNativeStyles = (json) => {
|
|
|
45
45
|
// Style properties like `"20px"` need to be numbers like `20` for react native
|
|
46
46
|
for (const key in cssValue) {
|
|
47
47
|
sanitizeStyle(cssValue)(key, cssValue[key]);
|
|
48
|
-
cssValue = (0, sanitize_react_native_block_styles_1.sanitizeReactNativeBlockStyles)(cssValue);
|
|
48
|
+
cssValue = (0, sanitize_react_native_block_styles_1.sanitizeReactNativeBlockStyles)(cssValue, options);
|
|
49
49
|
}
|
|
50
50
|
}
|
|
51
51
|
try {
|
|
@@ -54,7 +54,7 @@ const collectReactNativeStyles = (json) => {
|
|
|
54
54
|
// Style properties like `"20px"` need to be numbers like `20` for react native
|
|
55
55
|
for (const key in styleValue) {
|
|
56
56
|
sanitizeStyle(styleValue)(key, styleValue[key]);
|
|
57
|
-
styleValue = (0, sanitize_react_native_block_styles_1.sanitizeReactNativeBlockStyles)(styleValue);
|
|
57
|
+
styleValue = (0, sanitize_react_native_block_styles_1.sanitizeReactNativeBlockStyles)(styleValue, options);
|
|
58
58
|
}
|
|
59
59
|
item.bindings.style.code = json5_1.default.stringify(styleValue);
|
|
60
60
|
}
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { ToReactOptions } from '../react/types';
|
|
1
2
|
type Styles = Record<string, string | number>;
|
|
2
|
-
export declare const sanitizeReactNativeBlockStyles: (styles: Styles) => Styles;
|
|
3
|
+
export declare const sanitizeReactNativeBlockStyles: (styles: Styles, options: ToReactOptions) => Styles;
|
|
3
4
|
export {};
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.sanitizeReactNativeBlockStyles = void 0;
|
|
4
|
+
const helpers_1 = require("./helpers");
|
|
4
5
|
const propertiesThatMustBeNumber = new Set(['lineHeight']);
|
|
5
6
|
const displayValues = new Set(['flex', 'none']);
|
|
6
7
|
const normalizeNumber = (value) => {
|
|
@@ -15,10 +16,15 @@ const normalizeNumber = (value) => {
|
|
|
15
16
|
return value;
|
|
16
17
|
}
|
|
17
18
|
};
|
|
18
|
-
const sanitizeReactNativeBlockStyles = (styles) => {
|
|
19
|
+
const sanitizeReactNativeBlockStyles = (styles, options) => {
|
|
20
|
+
if (options.sanitizeReactNative) {
|
|
21
|
+
return (0, helpers_1.cleanReactNativeBlockStyles)(styles);
|
|
22
|
+
}
|
|
19
23
|
return Object.keys(styles).reduce((acc, key) => {
|
|
20
24
|
const propertyValue = styles[key];
|
|
21
|
-
if (
|
|
25
|
+
if (typeof propertyValue === 'string' &&
|
|
26
|
+
key === 'display' &&
|
|
27
|
+
!displayValues.has(propertyValue)) {
|
|
22
28
|
console.warn(`Style value for key "display" must be "flex" or "none" but had ${propertyValue}`);
|
|
23
29
|
return acc;
|
|
24
30
|
}
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { BaseTranspilerOptions } from '../../types/transpiler';
|
|
2
2
|
export interface ToReactNativeOptions extends BaseTranspilerOptions {
|
|
3
|
+
sanitizeReactNative?: boolean;
|
|
3
4
|
stylesType: 'emotion' | 'react-native' | 'twrnc' | 'native-wind';
|
|
4
5
|
stateType: 'useState' | 'mobx' | 'valtio' | 'solid' | 'builder';
|
|
5
6
|
}
|
|
@@ -101,7 +101,10 @@ function mapStateIdentifiers(json) {
|
|
|
101
101
|
const plugin = (0, process_code_1.createCodeProcessorPlugin)(() => (code) => mapStateIdentifiersInExpression(code, stateProperties));
|
|
102
102
|
plugin(json);
|
|
103
103
|
(0, legacy_1.default)(json).forEach(function (item) {
|
|
104
|
-
|
|
104
|
+
// only consolidate bindings for HTML tags, not custom components
|
|
105
|
+
// custom components are always PascalCase, e.g. MyComponent
|
|
106
|
+
// but HTML tags are lowercase, e.g. div
|
|
107
|
+
if ((0, is_mitosis_node_1.isMitosisNode)(item) && item.name.toLowerCase() === item.name) {
|
|
105
108
|
consolidateClassBindings(item);
|
|
106
109
|
}
|
|
107
110
|
});
|
package/package.json
CHANGED
|
@@ -22,7 +22,7 @@
|
|
|
22
22
|
"name": "Builder.io",
|
|
23
23
|
"url": "https://www.builder.io"
|
|
24
24
|
},
|
|
25
|
-
"version": "0.5.
|
|
25
|
+
"version": "0.5.2",
|
|
26
26
|
"homepage": "https://github.com/BuilderIO/mitosis",
|
|
27
27
|
"main": "./dist/src/index.js",
|
|
28
28
|
"exports": {
|
|
@@ -96,8 +96,6 @@
|
|
|
96
96
|
"@types/rollup__plugin-virtual": "^2.0.1",
|
|
97
97
|
"concurrently": "^8.2.2",
|
|
98
98
|
"fs-extra-promise": "^1.0.1",
|
|
99
|
-
"nx": "^19.0.8",
|
|
100
|
-
"nx-cloud": "^19.0.0",
|
|
101
99
|
"rimraf": "^5.0.5",
|
|
102
100
|
"rollup": "^2.70.1",
|
|
103
101
|
"strip-ansi": "^6.0.1",
|