UNPKG

@stencil/react-output-target

Version:

React output target for @stencil/core components.

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