@builder.io/mitosis
Version:
Write components once, run everywhere. Compiles to Vue, React, Solid, and Liquid. Import code from Figma and Builder.io
200 lines (191 loc) • 9.09 kB
JavaScript
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.componentToStencil = void 0;
const on_mount_1 = require("../../generators/helpers/on-mount");
const blocks_1 = require("../../generators/stencil/blocks");
const helpers_1 = require("../../generators/stencil/helpers");
const get_code_processor_plugins_1 = require("../../generators/stencil/plugins/get-code-processor-plugins");
const dash_case_1 = require("../../helpers/dash-case");
const dedent_1 = require("../../helpers/dedent");
const event_handlers_1 = require("../../helpers/event-handlers");
const fast_clone_1 = require("../../helpers/fast-clone");
const get_child_components_1 = require("../../helpers/get-child-components");
const get_props_1 = require("../../helpers/get-props");
const get_state_object_string_1 = require("../../helpers/get-state-object-string");
const indent_1 = require("../../helpers/indent");
const map_refs_1 = require("../../helpers/map-refs");
const merge_options_1 = require("../../helpers/merge-options");
const strip_meta_properties_1 = require("../../helpers/strip-meta-properties");
const collect_css_1 = require("../../helpers/styles/collect-css");
const attribute_passing_1 = require("../../helpers/web-components/attribute-passing");
const plugins_1 = require("../../modules/plugins");
const standalone_1 = require("prettier/standalone");
const componentToStencil = (_options = {
typescript: true, // Stencil is uses .tsx always
}) => {
return ({ component }) => {
var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k;
let json = (0, fast_clone_1.fastClone)(component);
const options = (0, merge_options_1.initializeOptions)({
target: 'stencil',
component,
defaults: _options,
});
if (options.plugins) {
json = (0, plugins_1.runPreJsonPlugins)({ json, plugins: options.plugins });
}
(0, map_refs_1.mapRefs)(json, (refName) => `this.${refName}`);
let css = (0, collect_css_1.collectCss)(json);
let props = Array.from((0, get_props_1.getProps)(json));
const events = props.filter((prop) => (0, event_handlers_1.checkIsEvent)(prop));
const defaultProps = json.defaultProps;
const childComponents = (0, get_child_components_1.getChildComponents)(json);
props = props.filter((prop) => {
// Stencil doesn't need children as a prop
return prop !== 'children';
});
const processBindingOptions = { events, props, target: 'stencil' };
options.plugins = (0, get_code_processor_plugins_1.getCodeProcessorPlugins)(json, options, processBindingOptions);
if (options.plugins) {
json = (0, plugins_1.runPostJsonPlugins)({ json, plugins: options.plugins });
}
(0, strip_meta_properties_1.stripMetaProperties)(json);
const dataString = (0, get_state_object_string_1.getStateObjectStringFromComponent)(json, {
format: 'class',
data: true,
functions: false,
getters: false,
keyPrefix: '@State() ',
});
const methodsString = (0, get_state_object_string_1.getStateObjectStringFromComponent)(json, {
format: 'class',
data: false,
functions: true,
getters: true,
});
let refs = json.refs
? Object.entries(json.refs)
.map(([key, value]) => { var _a; return `private ${key}!: ${(_a = value.typeParameter) !== null && _a !== void 0 ? _a : 'HTMLElement'};`; })
.join('\n')
: '';
const wrap = (0, helpers_1.needsWrap)(json.children);
const withAttributePassing = !wrap && (0, attribute_passing_1.shouldAddAttributePassing)(json, options);
const rootRef = (0, attribute_passing_1.getAddAttributePassingRef)(json, options);
if (withAttributePassing && !refs.includes(rootRef)) {
refs += `\nprivate ${rootRef}!: HTMLElement;`;
}
if (options.prettier !== false) {
try {
css = (0, standalone_1.format)(css, {
parser: 'css',
plugins: [require('prettier/parser-postcss')],
});
}
catch (err) {
console.warn('Could not format css', err);
}
}
let tagName = (0, helpers_1.getTagName)(json.name, options);
if ((_a = json.meta.useMetadata) === null || _a === void 0 ? void 0 : _a.tagName) {
// Deprecated option, we shouldn't use this, instead change the name of your Mitosis component
tagName = (_b = json.meta.useMetadata) === null || _b === void 0 ? void 0 : _b.tagName;
}
const noDependencyOnUpdateHooks = (_d = (_c = json.hooks.onUpdate) === null || _c === void 0 ? void 0 : _c.filter((hook) => !hook.deps)) !== null && _d !== void 0 ? _d : [];
/*
* We want to create a function for every onUpdate hook that has dependencies.
* We call the function once in "componentDidLoad"
* And we create "Watch" decorators for every dependency
*/
const dependencyOnUpdateHooks = (_f = (_e = json.hooks.onUpdate) === null || _e === void 0 ? void 0 : _e.filter((hook) => hook.deps)) !== null && _f !== void 0 ? _f : [];
const coreImports = (0, helpers_1.getStencilCoreImportsAsString)({
wrap,
events,
props,
dataString,
watch: Boolean(dependencyOnUpdateHooks === null || dependencyOnUpdateHooks === void 0 ? void 0 : dependencyOnUpdateHooks.length),
});
const propOptions = {
...options.propOptions,
...(_h = (_g = json.meta.useMetadata) === null || _g === void 0 ? void 0 : _g.stencil) === null || _h === void 0 ? void 0 : _h.propOptions,
};
let str = (0, dedent_1.dedent) `
${(0, helpers_1.getImports)(json, options, childComponents)}
import { ${coreImports} } from '@stencil/core';
export class ${json.name} {
${refs}
${(0, helpers_1.getPropsAsCode)({ props, json, defaultProps, propOptions })}
${dataString}
${methodsString}
${(0, helpers_1.getExportsAndLocal)(json)}
${withAttributePassing ? (0, attribute_passing_1.getAttributePassingString)(true) : ''}
${dependencyOnUpdateHooks
.map((hook, index) => {
return `
watch${index}Fn() {
${hook.code}
}
${(0, helpers_1.getDepsAsArray)(hook.deps)
.map((dep) => ` `)
.join('\n')}
watch${index}(){
this.watch${index}Fn();
}
`;
})
.join('\n')}
${`componentDidLoad() {
${withAttributePassing
? `this.enableAttributePassing(this.${rootRef}, "${(0, dash_case_1.dashCase)(json.name)}");`
: ''}
${json.hooks.onMount.length ? (0, on_mount_1.stringifySingleScopeOnMount)(json) : ''}
${dependencyOnUpdateHooks
.map((_, index) => `this.watch${index}Fn();`)
.join('\n')}
}`}
${!((_k = json.hooks.onUnMount) === null || _k === void 0 ? void 0 : _k.code)
? ''
: `disconnectedCallback() { ${json.hooks.onUnMount.code} }`}
${noDependencyOnUpdateHooks.length
? `componentDidUpdate() { ${noDependencyOnUpdateHooks
.map((hook) => hook.code)
.join('\n')} }`
: ''}
render() {
return (${wrap ? '<Host>' : ''}
${json.children
.map((item) => (0, blocks_1.blockToStencil)({
json: item,
options,
insideJsx: true,
childComponents,
rootRef: withAttributePassing && rootRef === attribute_passing_1.ROOT_REF ? rootRef : undefined, // only pass rootRef if it's not the default
}))
.join('\n')}
${wrap ? '</Host>' : ''})
}
}
`;
if (options.plugins) {
str = (0, plugins_1.runPreCodePlugins)({ json, code: str, plugins: options.plugins });
}
if (options.prettier !== false) {
str = (0, standalone_1.format)(str, {
parser: 'typescript',
plugins: [require('prettier/parser-typescript')],
});
}
if (options.plugins) {
str = (0, plugins_1.runPostCodePlugins)({ json, code: str, plugins: options.plugins });
}
return str;
};
};
exports.componentToStencil = componentToStencil;