@builder.io/mitosis
Version:
Write components once, run everywhere. Compiles to Vue, React, Solid, and Liquid. Import code from Figma and Builder.io
171 lines (170 loc) • 8.07 kB
JavaScript
Object.defineProperty(exports, "__esModule", { value: true });
exports.addCommonStyles = exports.renderUseLexicalScope = exports.addComponent = exports.createFileSet = void 0;
const compile_away_builder_components_1 = require("../../plugins/compile-away-builder-components");
const on_mount_1 = require("../helpers/on-mount");
const directives_1 = require("./directives");
const handlers_1 = require("./helpers/handlers");
const stable_serialize_1 = require("./helpers/stable-serialize");
const styles_1 = require("./helpers/styles");
const jsx_1 = require("./jsx");
const src_generator_1 = require("./src-generator");
function createFileSet(options = {}) {
const opts = {
qwikLib: '@builder.io/qwik',
qrlPrefix: './',
output: 'ts',
minify: false,
jsx: true,
...options,
};
const extension = (opts.output == 'mjs' ? 'js' : opts.output) + (opts.jsx ? 'x' : '');
const srcOptions = {
isPretty: !opts.minify,
isModule: opts.output != 'cjs',
isTypeScript: opts.output == 'ts',
isJSX: opts.jsx,
isBuilder: true,
};
const fileSet = {
high: new src_generator_1.File('high.' + extension, srcOptions, opts.qwikLib, opts.qrlPrefix),
med: new src_generator_1.File('med.' + extension, srcOptions, opts.qwikLib, opts.qrlPrefix),
low: new src_generator_1.File('low.' + extension, srcOptions, opts.qwikLib, opts.qrlPrefix),
};
Object.defineProperty(fileSet, 'CommonStyles', {
enumerable: false,
value: { styles: new Map(), symbolName: null },
});
return fileSet;
}
exports.createFileSet = createFileSet;
function getCommonStyles(fileSet) {
return fileSet['CommonStyles'];
}
function addComponent(fileSet, component, opts = {}) {
const _opts = { isRoot: false, shareStyles: false, ...opts };
(0, compile_away_builder_components_1.compileAwayBuilderComponentsFromTree)(component, {
...compile_away_builder_components_1.components,
// A set of components that should not be compiled away because they are implemented as runtime components.
Image: undefined,
CoreButton: undefined,
});
addBuilderBlockClass(component.children);
const componentName = component.name;
const handlers = (0, handlers_1.renderHandlers)(fileSet.high, componentName, component.children);
// If the component has no handlers, than it is probably static
// and so it is unlikely to be re-rendered on the client, therefore
// put it in a low priority bucket.
const isStatic = Array.from(handlers.keys()).reduce((p, v) => p && v.indexOf('state') == -1, true);
const onRenderFile = isStatic ? fileSet.low : fileSet.med;
const componentFile = fileSet.med;
const styles = _opts.shareStyles ? getCommonStyles(fileSet).styles : new Map();
(0, styles_1.collectStyles)(component.children, styles);
let useStyles = () => null;
if (styles.size) {
if (_opts.shareStyles) {
if (_opts.isRoot) {
const symbolName = componentName + 'Styles';
getCommonStyles(fileSet).symbolName = symbolName;
useStyles = generateStyles(onRenderFile, fileSet.low, symbolName, false);
}
}
else {
const symbolName = componentName + 'Styles';
onRenderFile.exportConst(symbolName, (0, styles_1.renderStyles)(styles));
useStyles = generateStyles(onRenderFile, onRenderFile, symbolName, true);
}
}
if (component.meta.cssCode) {
const symbolName = componentName + 'UsrStyles';
onRenderFile.exportConst(symbolName, (0, stable_serialize_1.stableJSONserialize)(component.meta.cssCode));
useStyles = ((fns) => function () {
fns.forEach((fn) => fn.apply(this));
})([useStyles, generateStyles(onRenderFile, onRenderFile, symbolName, false)]);
}
const directives = new Map();
let rootChildren = component.children;
addComponentOnMount(onRenderFile, function () {
return this.emit('return ', (0, jsx_1.renderJSXNodes)(onRenderFile, directives, handlers, rootChildren, styles, null, {}), ';');
}, componentName, component, useStyles);
componentFile.exportConst(componentName, (0, src_generator_1.invoke)(componentFile.import(componentFile.qwikModule, 'componentQrl'), [generateQrl(componentFile, onRenderFile, componentName + 'OnMount')], ['any', 'any']));
directives.forEach((code, name) => {
fileSet.med.import(fileSet.med.qwikModule, 'h');
fileSet.med.exportConst(name, code, true);
});
fileSet.low.exportConst('__proxyMerge__', directives_1.DIRECTIVES['__proxyMerge__'], true);
fileSet.med.exportConst('__proxyMerge__', directives_1.DIRECTIVES['__proxyMerge__'], true);
fileSet.high.exportConst('__proxyMerge__', directives_1.DIRECTIVES['__proxyMerge__'], true);
}
exports.addComponent = addComponent;
function generateStyles(fromFile, dstFile, symbol, scoped) {
return function () {
if (this.file.options.isPretty) {
this.emit('\n\n');
}
this.emit((0, src_generator_1.invoke)(fromFile.import(fromFile.qwikModule, scoped ? 'useStylesScopedQrl' : 'useStylesQrl'), [
generateQrl(fromFile, dstFile, symbol),
]), ';');
if (this.file.options.isPretty) {
this.emit('\n\n');
}
};
}
function addBuilderBlockClass(children) {
children.forEach((child) => {
const props = child.properties;
if (props['builder-id']) {
props.class = (props.class ? props.class + ' ' : '') + 'builder-block';
}
});
}
function renderUseLexicalScope(file) {
return function () {
if (this.file.options.isBuilder) {
return this.emit('const [s,l]=', file.import(file.qwikModule, 'useLexicalScope').localName, '();', 'const state=__proxyMerge__(s,l);');
}
else {
return this.emit('const state=', file.import(file.qwikModule, 'useLexicalScope').localName, '()[0]');
}
};
}
exports.renderUseLexicalScope = renderUseLexicalScope;
function addCommonStyles(fileSet) {
const { styles, symbolName } = getCommonStyles(fileSet);
const onRenderFile = fileSet.low;
if (symbolName) {
onRenderFile.exportConst(symbolName, (0, styles_1.renderStyles)(styles));
}
}
exports.addCommonStyles = addCommonStyles;
function addComponentOnMount(componentFile, onRenderEmit, componentName, component, useStyles) {
const inputInitializer = [];
if (component.inputs) {
component.inputs.forEach((input) => {
input.defaultValue !== undefined &&
inputInitializer.push('if(!state.hasOwnProperty("', input.name, '"))state.', input.name, '=', (0, stable_serialize_1.stableJSONserialize)(input.defaultValue), ';');
});
}
componentFile.exportConst(componentName + 'OnMount', function () {
this.emit((0, src_generator_1.arrowFnValue)(['p'], () => this.emit('{', 'const s=', componentFile.import(componentFile.qwikModule, 'useStore').localName, '(()=>{', 'const state=Object.assign({},structuredClone(typeof __STATE__==="object"&&__STATE__[p.serverStateId]),p);', ...inputInitializer, inlineCode((0, on_mount_1.stringifySingleScopeOnMount)(component)), 'return state;', '},{deep:true});', 'const l={};', 'const state=__proxyMerge__(s,l);', useStyles, onRenderEmit, ';}')));
});
}
function inlineCode(code) {
return function () {
if (code) {
// HACK: remove the return value as it is not the state we are creating.
code = code
.trim()
.replace(/return main\(\);?$/, '')
.trim();
this.emit(code, ';');
}
};
}
function generateQrl(fromFile, dstFile, componentName, capture = []) {
return (0, src_generator_1.invoke)(fromFile.import(fromFile.qwikModule, 'qrl'), [
dstFile.toQrlChunk(),
(0, src_generator_1.quote)(componentName),
`[${capture.join(',')}]`,
]);
}
;