UNPKG

@stencil/react-output-target

Version:

React output target for @stencil/core components.

272 lines (268 loc) 8.65 kB
import { Project as N, VariableDeclarationKind as R } from "ts-morph"; import v from "node:path"; const O = (o) => o.toLowerCase().split("-").map((r) => r.charAt(0).toUpperCase() + r.slice(1)).join(""), I = (o) => o.replace(/-([_a-z])/g, (r, s) => s.toUpperCase()), P = (o) => o.replace(/\/([a-z])/g, (r, s) => s.toUpperCase()), F = (o) => { const r = P(o); return I(`on-${r}`); }, U = async ({ components: o, project: r, outDir: s }) => { const u = r || new N({ useInMemoryFileSystem: !0 }), f = `/* eslint-disable */ `, d = `/** * This file was automatically generated by the Stencil React Output Target. * Changes to this file may cause incorrect behavior and will be lost if the code is regenerated. */ `, $ = v.join(s || "", "components.ts"), l = u.createSourceFile($, d + f, { overwrite: !0 }); for (const m of o) { const i = m.tagName, e = O(i), a = m.tagName; l.addExportDeclaration({ moduleSpecifier: `./${a}.js`, namedExports: [e] }); } return l.organizeImports(), l.formatText(), await l.save(), l; }, j = ({ components: o, stencilPackageName: r, customElementsDir: s, hydrateModule: u, serializeShadowRoot: f }) => { const d = new N({ useInMemoryFileSystem: !0 }), $ = u ? "" : `'use client'; `, l = `/** * This file was automatically generated by the Stencil React Output Target. * Changes to this file may cause incorrect behavior and will be lost if the code is regenerated. */ `, m = `/* eslint-disable */ `, i = u ? "import { createComponent, type SerializeShadowRootOptions, type HydrateModule } from '@stencil/react-output-target/ssr';" : "import { createComponent } from '@stencil/react-output-target/runtime';", e = d.createSourceFile( "component.ts", `${$}${l}${m} import React from 'react'; ${i} import type { EventName, StencilReactComponent } from '@stencil/react-output-target/runtime'; ` ); u && e.addVariableStatement({ isExported: !0, declarationKind: R.Const, declarations: [ { name: "serializeShadowRoot", type: "SerializeShadowRootOptions", initializer: f ? JSON.stringify(f) : '{ default: "declarative-shadow-dom" }' } ] }); for (const a of o) { const g = a.tagName, c = O(g), n = `${c}Element`, p = `${c}CustomEvent`; e.addImportDeclaration({ moduleSpecifier: `${r}/${s}/${g}.js`, namedImports: [ { name: c, alias: n }, { name: "defineCustomElement", alias: `define${c}` } ] }); const h = (a.events || []).filter((t) => t.internal === !1), y = []; for (const t of h) if (Object.keys(t.complexType.references).length > 0) { for (const _ of Object.keys(t.complexType.references)) t.complexType.references[_].location === "global" || e.addImportDeclaration({ moduleSpecifier: r, namedImports: [ { name: _, isTypeOnly: !0 } ] }); e.addImportDeclaration({ moduleSpecifier: r, namedImports: [ { name: p, isTypeOnly: !0 } ] }), y.push({ originalName: t.name, name: F(t.name), type: `EventName<${p}<${t.complexType.original}>>` }); } else y.push({ originalName: t.name, name: F(t.name), type: `EventName<CustomEvent<${t.complexType.original}>>` }); const T = `${c}Events`; e.addTypeAlias({ isExported: !0, name: T, type: y.length > 0 ? `{ ${y.map((t) => `${t.name}: ${t.type}`).join(`, `)} }` : "NonNullable<unknown>" }); const w = `/*@__PURE__*/ createComponent<${n}, ${T}>({ tagName: '${g}', elementClass: ${n}, // @ts-ignore - ignore potential React type mismatches between the Stencil Output Target and your project. react: React, events: {${y.map((t) => `${t.name}: '${t.originalName}'`).join(`, `)}} as ${T}, defineCustomElement: define${c} })`, S = `/*@__PURE__*/ createComponent<${n}, ${T}>({ tagName: '${g}', properties: {${a.properties.filter((t) => !!t.attribute).map((t) => `${t.name}: '${t.attribute}'`).join(`, `)}}, hydrateModule: import('${u}') as Promise<HydrateModule>, serializeShadowRoot, elementClass: ${n}, // @ts-ignore - ignore potential React type mismatches between the Stencil Output Target and your project. react: React, events: {${y.map((t) => `${t.name}: '${t.originalName}'`).join(`, `)}} as ${T}, defineCustomElement: define${c} })`; e.addVariableStatement({ isExported: !0, declarationKind: R.Const, // React as never is a hack to by-pass a @types/react issue. declarations: [ { name: c, type: `StencilReactComponent<${n}, ${T}>`, initializer: u ? S : w } ] }); } return e.organizeImports(), e.formatText(), e.getFullText(); }, x = async ({ stencilPackageName: o, components: r, outDir: s, esModules: u, customElementsDir: f, excludeComponents: d, project: $, hydrateModule: l, excludeServerSideRenderingFor: m, serializeShadowRoot: i }) => { const e = [], a = r.filter((n) => !(n.internal === !0 || d != null && d.includes(n.tagName))); if (a.length === 0) return []; const g = {}; function c(n, p = "components") { const h = v.join(s, `${p}.ts`), y = j({ components: n, stencilPackageName: o, customElementsDir: f }); if (g[h] = y, l) { const T = v.join(s, `${p}.server.ts`), w = j({ components: n.filter( (S) => !m || !m.includes(S.tagName) ), stencilPackageName: o, customElementsDir: f, hydrateModule: l, serializeShadowRoot: i }); g[T] = w; } } if (u) { for (const p of a) c([p], p.tagName); const n = await U({ components: a, project: $, outDir: s }); e.push(n); } else c(a); return await Promise.all( Object.entries(g).map(async ([n, p]) => { const h = $.createSourceFile(n, p, { overwrite: !0 }); await h.save(), e.push(h); }) ), e; }, C = "react-output-target", D = "dist/components", E = "dist-custom-elements", b = "dist-hydrate-script", L = ({ outDir: o, esModules: r, stencilPackageName: s, excludeComponents: u, customElementsDir: f, hydrateModule: d, excludeServerSideRenderingFor: $, serializeShadowRoot: l }) => { let m = D; return { type: "custom", name: C, validate(i) { if (f) m = f; else { const e = (i.outputTargets || []).find( (a) => a.type === E ); if (e == null) throw new Error( `The '${C}' requires '${E}' output target. Add { type: '${E}' }, to the outputTargets config.` ); if (e.dir !== void 0 && (m = e.dir), e.externalRuntime !== !1) throw new Error( `The '${C}' requires the '${E}' output target to have 'externalRuntime: false' set in its configuration.` ); } if (d && (i.outputTargets || []).find((a) => a.type === b) == null) throw new Error( `The '${C}' requires '${b}' output target when the 'hydrateModule' option is set. Add { type: '${b}' }, to the outputTargets config.` ); if (!o) throw new Error("The 'outDir' option is required."); if (s === void 0) { if (i.sys && i.packageJsonFilePath) { const { name: e } = JSON.parse(i.sys.readFileSync(i.packageJsonFilePath, "utf8")); s = e; } if (!s) throw new Error( `Unable to find the package name in the package.json file: ${i.packageJsonFilePath}. Please provide the stencilPackageName manually to the ${C} output target.` ); } }, async generator(i, e, a) { const g = a.createTimeSpan(`generate ${C} started`, !0), c = a.components, n = new N(), p = await x({ outDir: o, components: c, stencilPackageName: s, customElementsDir: m, excludeComponents: u, esModules: r === !0, project: n, hydrateModule: d, excludeServerSideRenderingFor: $, serializeShadowRoot: l }); await Promise.all( p.map((h) => e.fs.writeFile(h.getFilePath(), h.getFullText())) ), g.finish(`generate ${C} finished`); }, __internal_getCustomElementsDir() { return m; } }; }; export { L as reactOutputTarget }; //# sourceMappingURL=index.js.map