@builder.io/mitosis
Version:
Write components once, run everywhere. Compiles to Vue, React, Solid, and Liquid. Import code from Figma and Builder.io
157 lines (156 loc) • 7.44 kB
JavaScript
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.getDefaultImport = exports.getReactVariantStateString = exports.getReactVariantStateImportString = exports.updateStateSettersInCode = exports.updateStateSetters = exports.getUseStateCode = exports.processHookCode = void 0;
const capitalize_1 = require("../../../helpers/capitalize");
const get_function_string_1 = require("../../../helpers/get-function-string");
const get_state_object_string_1 = require("../../../helpers/get-state-object-string");
const get_typed_function_1 = require("../../../helpers/get-typed-function");
const is_mitosis_node_1 = require("../../../helpers/is-mitosis-node");
const patterns_1 = require("../../../helpers/patterns");
const transform_state_setters_1 = require("../../../helpers/transform-state-setters");
const core_1 = require("@babel/core");
const function_1 = require("fp-ts/lib/function");
const legacy_1 = __importDefault(require("neotraverse/legacy"));
const helpers_1 = require("../helpers");
/**
* Removes all `this.` references.
*/
const stripThisRefs = (str, options) => {
if (options.stateType !== 'useState') {
return str;
}
return str.replace(/this\.([a-zA-Z_\$0-9]+)/g, '$1');
};
const processHookCode = ({ str, options }) => (0, helpers_1.processBinding)((0, exports.updateStateSettersInCode)(str, options), options);
exports.processHookCode = processHookCode;
const valueMapper = (options) => (val) => {
const x = (0, exports.processHookCode)({ str: val, options });
return stripThisRefs(x, options);
};
const getSetStateFnName = (stateName) => `set${(0, capitalize_1.capitalize)(stateName)}`;
const processStateValue = (options) => {
const mapValue = valueMapper(options);
return ([key, stateVal]) => {
if (!stateVal) {
return '';
}
let value = stateVal.code || '';
const type = stateVal.type;
const typeParameter = stateVal.typeParameter;
const stateType = options.typescript && stateVal.typeParameter ? `<${stateVal.typeParameter}>` : '';
let result = '';
if (type === 'getter') {
result = (0, function_1.pipe)(value, patterns_1.replaceGetterWithFunction, mapValue);
}
else if (type === 'function') {
result = mapValue(value);
}
else if (type === 'method') {
result = (0, function_1.pipe)(value, patterns_1.prefixWithFunction, mapValue);
}
else {
return `const [${key}, ${getSetStateFnName(key)}] = useState${stateType}(() => (${mapValue(value)}))`;
}
return (0, get_typed_function_1.getTypedFunction)(result, options.typescript, typeParameter);
};
};
const getUseStateCode = (json, options) => {
const lineItemDelimiter = '\n\n\n';
const stringifiedState = Object.entries(json.state).map(processStateValue(options));
return stringifiedState.join(lineItemDelimiter);
};
exports.getUseStateCode = getUseStateCode;
const updateStateSetters = (json, options) => {
if (options.stateType !== 'useState') {
return;
}
(0, legacy_1.default)(json).forEach(function (item) {
if ((0, is_mitosis_node_1.isMitosisNode)(item)) {
for (const key in item.bindings) {
let values = item.bindings[key];
const newValue = (0, exports.updateStateSettersInCode)(values === null || values === void 0 ? void 0 : values.code, options);
if (newValue !== (values === null || values === void 0 ? void 0 : values.code)) {
item.bindings[key] = {
...values,
code: newValue,
};
}
}
}
});
};
exports.updateStateSetters = updateStateSetters;
const updateStateSettersInCode = (value, options) => {
if (options.stateType !== 'useState') {
return value;
}
return (0, transform_state_setters_1.transformStateSetters)({
value,
transformer: ({ path, propertyName }) => core_1.types.callExpression(core_1.types.identifier(getSetStateFnName(propertyName)), [path.node.right]),
});
};
exports.updateStateSettersInCode = updateStateSettersInCode;
const getReactVariantStateImportString = (hasState, options) => {
return !hasState
? ''
: options.stateType === 'valtio'
? `import { useLocalProxy } from 'valtio/utils';`
: options.stateType === 'solid'
? `import { useMutable } from 'react-solid-state';`
: options.stateType === 'mobx'
? `import { useLocalObservable, observer } from 'mobx-react-lite';`
: '';
};
exports.getReactVariantStateImportString = getReactVariantStateImportString;
const getReactVariantStateString = ({ hasState, options, json, useStateCode, }) => hasState
? options.stateType === 'mobx'
? `const state = useLocalObservable(() => (${(0, get_state_object_string_1.getStateObjectStringFromComponent)(json)}));`
: options.stateType === 'useState'
? useStateCode
: options.stateType === 'solid'
? `const state = useMutable(${(0, get_state_object_string_1.getStateObjectStringFromComponent)(json)});`
: options.stateType === 'builder'
? `const state = useBuilderState(${(0, get_state_object_string_1.getStateObjectStringFromComponent)(json)});`
: options.stateType === 'variables'
? (0, get_state_object_string_1.getStateObjectStringFromComponent)(json, {
format: 'variables',
keyPrefix: 'const',
valueMapper: (code, type, _, key) => {
if (key) {
const constPrefix = !code.startsWith('function') ? `${key} = ` : '';
if (type === 'getter')
return `${constPrefix}${(0, get_function_string_1.getFunctionString)(code.replace('get ', ''))}`;
if (type === 'function')
return code.startsWith('async') ? code : `${constPrefix}${(0, get_function_string_1.getFunctionString)(code)}`;
}
return code;
},
})
: `const state = useLocalProxy(${(0, get_state_object_string_1.getStateObjectStringFromComponent)(json)});`
: '';
exports.getReactVariantStateString = getReactVariantStateString;
const getDefaultImport = (options) => {
const { preact, type } = options;
if (preact) {
return `
/** @jsx h */
import { h, Fragment } from 'preact';
`;
}
if (type === 'native') {
return `
import * as React from 'react';
import { FlatList, ScrollView, View, StyleSheet, Image, Text, Pressable, TextInput, TouchableOpacity, Button, Linking } from 'react-native';
`;
}
if (type === 'taro') {
return `
import * as React from 'react';
`;
}
return "import * as React from 'react';";
};
exports.getDefaultImport = getDefaultImport;
;