@stencil/react-output-target
Version:
React output target for @stencil/core components.
1 lines • 6.69 kB
Source Map (JSON)
{"version":3,"file":"create-component-CKOVldUI.cjs","sources":["../src/runtime/create-component.ts"],"sourcesContent":["import type { EventName, Options } from '@lit/react';\nimport { createComponent as createComponentWrapper } from '@lit/react';\nimport React from 'react';\n\n// A key value map matching React prop names to event names.\ntype EventNames = Record<string, EventName | string>;\n\n// Type that's compatible with both React 18 and 19\ntype StencilProps<I extends HTMLElement, E extends EventNames, C, R extends keyof C = never> = Omit<\n React.HTMLAttributes<I>,\n keyof E\n> &\n Partial<{ [K in keyof E]: E[K] extends EventName<infer T> ? (event: T) => void : (event: any) => void }> &\n Required<Pick<C, R>> &\n Partial<Omit<C, R>> &\n React.RefAttributes<I>;\n\nexport type StencilReactComponent<\n I extends HTMLElement,\n E extends EventNames = {},\n C = Omit<I, keyof HTMLElement>,\n R extends keyof C = never,\n> = React.FunctionComponent<StencilProps<I, E, C, R>>;\n\nconst splitClassName = (className: string | undefined): string[] =>\n className ? className.split(/\\s+/).filter(Boolean) : [];\n\n/**\n * Merge the app's `className`/`class` with the classes the Stencil runtime\n * manages on the host. `@lit/react` maps `className` to `class` and rewrites it\n * wholesale on every render, which wipes runtime-added classes like `hydrated`,\n * `sc-*` scope classes, and state classes a design system relies on.\n */\nexport const mergeClassNames = (\n currentClasses: Iterable<string>,\n newClassName: string | undefined,\n oldClassName: string | undefined\n): string => {\n const incoming = new Set(splitClassName(newClassName));\n const previous = new Set(splitClassName(oldClassName));\n const finalClassNames: string[] = [];\n\n for (const className of currentClasses) {\n if (incoming.has(className)) {\n finalClassNames.push(className);\n incoming.delete(className);\n } else if (!previous.has(className)) {\n // Runtime-managed class the app never set, so keep it.\n finalClassNames.push(className);\n }\n // Anything else was set by the app last render and dropped now, so drop it.\n }\n\n // Whatever's left in `incoming` isn't on the element yet.\n for (const className of incoming) {\n finalClassNames.push(className);\n }\n\n return finalClassNames.join(' ');\n};\n\n// `useLayoutEffect` warns during server rendering and the reconciliation is\n// client-only anyway, so fall back to `useEffect` on the server.\nconst useIsomorphicLayoutEffect = typeof window !== 'undefined' ? React.useLayoutEffect : React.useEffect;\n\n/**\n * Defines a custom element and creates a React component.\n * @public\n */\nexport const createComponent = <\n I extends HTMLElement,\n E extends EventNames = {},\n C = Omit<I, keyof HTMLElement>,\n R extends keyof C = never,\n>({\n defineCustomElement,\n tagName,\n transformTag,\n ...options\n}: Options<I, E> & {\n defineCustomElement: () => void;\n transformTag?: (tagName: string) => string;\n}): StencilReactComponent<I, E, C, R> => {\n if (typeof defineCustomElement !== 'undefined') {\n defineCustomElement();\n }\n const finalTagName = transformTag ? transformTag(tagName) : tagName;\n const ReactComponent = createComponentWrapper<I, E>({ ...options, tagName: finalTagName });\n\n /**\n * Withhold `className`/`class` from `@lit/react` so React never writes the\n * `class` attribute, then reconcile it against the live host in a layout\n * effect. See `mergeClassNames`.\n */\n const WrappedComponent = React.forwardRef<I, StencilProps<I, E, C, R>>((props, ref) => {\n const {\n className,\n class: classProp,\n ...restProps\n } = props as StencilProps<I, E, C, R> & {\n className?: string;\n class?: string;\n };\n const incomingClassName = className ?? classProp ?? '';\n\n const elementRef = React.useRef<I | null>(null);\n const previousClassName = React.useRef<string>('');\n\n useIsomorphicLayoutEffect(() => {\n const element = elementRef.current;\n if (element === null || incomingClassName === previousClassName.current) {\n return;\n }\n element.className = mergeClassNames(Array.from(element.classList), incomingClassName, previousClassName.current);\n previousClassName.current = incomingClassName;\n });\n\n const setRef = React.useCallback(\n (node: I | null) => {\n elementRef.current = node;\n if (typeof ref === 'function') {\n ref(node);\n } else if (ref !== null && ref !== undefined) {\n (ref as React.MutableRefObject<I | null>).current = node;\n }\n },\n [ref]\n );\n\n return React.createElement(ReactComponent, { ...restProps, ref: setRef } as any);\n });\n\n WrappedComponent.displayName = options.displayName ?? finalTagName;\n\n return WrappedComponent as unknown as StencilReactComponent<I, E, C, R>;\n};\n"],"names":["splitClassName","className","mergeClassNames","currentClasses","newClassName","oldClassName","incoming","previous","finalClassNames","useIsomorphicLayoutEffect","React","createComponent","defineCustomElement","tagName","transformTag","options","finalTagName","ReactComponent","createComponentWrapper","WrappedComponent","props","ref","classProp","restProps","incomingClassName","elementRef","previousClassName","element","setRef","node"],"mappings":"8DAwBMA,EAAkBC,GACtBA,EAAYA,EAAU,MAAM,KAAK,EAAE,OAAO,OAAO,EAAI,CAAA,EAQ1CC,EAAkB,CAC7BC,EACAC,EACAC,IACW,CACX,MAAMC,EAAW,IAAI,IAAIN,EAAeI,CAAY,CAAC,EAC/CG,EAAW,IAAI,IAAIP,EAAeK,CAAY,CAAC,EAC/CG,EAA4B,CAAA,EAElC,UAAWP,KAAaE,EAClBG,EAAS,IAAIL,CAAS,GACxBO,EAAgB,KAAKP,CAAS,EAC9BK,EAAS,OAAOL,CAAS,GACfM,EAAS,IAAIN,CAAS,GAEhCO,EAAgB,KAAKP,CAAS,EAMlC,UAAWA,KAAaK,EACtBE,EAAgB,KAAKP,CAAS,EAGhC,OAAOO,EAAgB,KAAK,GAAG,CACjC,EAIMC,EAA4B,OAAO,OAAW,IAAcC,EAAM,gBAAkBA,EAAM,UAMnFC,EAAkB,CAK7B,CACA,oBAAAC,EACA,QAAAC,EACA,aAAAC,EACA,GAAGC,CACL,IAGyC,CACnC,OAAOH,EAAwB,KACjCA,EAAA,EAEF,MAAMI,EAAeF,EAAeA,EAAaD,CAAO,EAAIA,EACtDI,EAAiBC,EAAAA,gBAA6B,CAAE,GAAGH,EAAS,QAASC,EAAc,EAOnFG,EAAmBT,EAAM,WAAwC,CAACU,EAAOC,IAAQ,CACrF,KAAM,CACJ,UAAApB,EACA,MAAOqB,EACP,GAAGC,CAAA,EACDH,EAIEI,EAAoBvB,GAAaqB,GAAa,GAE9CG,EAAaf,EAAM,OAAiB,IAAI,EACxCgB,EAAoBhB,EAAM,OAAe,EAAE,EAEjDD,EAA0B,IAAM,CAC9B,MAAMkB,EAAUF,EAAW,QACvBE,IAAY,MAAQH,IAAsBE,EAAkB,UAGhEC,EAAQ,UAAYzB,EAAgB,MAAM,KAAKyB,EAAQ,SAAS,EAAGH,EAAmBE,EAAkB,OAAO,EAC/GA,EAAkB,QAAUF,EAC9B,CAAC,EAED,MAAMI,EAASlB,EAAM,YAClBmB,GAAmB,CAClBJ,EAAW,QAAUI,EACjB,OAAOR,GAAQ,WACjBA,EAAIQ,CAAI,EACCR,GAAQ,OAChBA,EAAyC,QAAUQ,EAExD,EACA,CAACR,CAAG,CAAA,EAGN,OAAOX,EAAM,cAAcO,EAAgB,CAAE,GAAGM,EAAW,IAAKK,EAAe,CACjF,CAAC,EAED,OAAAT,EAAiB,YAAcJ,EAAQ,aAAeC,EAE/CG,CACT"}