/
githubmirror
/
ionic
Обзор
Документация
Войти
/
githubmirror
/
ionic
Код
Запросы
0
Пакеты
0
Релизы
0
Аналитика
Безопасность
main
packages/react/src/components/react-component-lib/createComponent.tsx
106 строк
3 KB
Liam DeBeasi
chore(deps): update to stencil v3 (#26663)
01 фев 2023, 02:07
Не верифицирован
01 фев 2023, 02:07
1a8bd6d
Код
Авторство
О чём код?
import React, { createElement } from 'react'; import { attachProps, camelToDashCase, createForwardRef, dashToPascalCase, isCoveredByReact, mergeRefs } from './utils'; export interface HTMLStencilElement extends HTMLElement { componentOnReady(): Promise<this>; } interface StencilReactInternalProps<ElementType> extends React.HTMLAttributes<ElementType> { forwardedRef: React.RefObject<ElementType>; ref?: React.Ref<any>; } export const createReactComponent = < PropType, ElementType extends HTMLStencilElement, ContextStateType = {}, ExpandedPropsTypes = {} >( tagName: string, ReactComponentContext?: React.Context<ContextStateType>, manipulatePropsFunction?: ( originalProps: StencilReactInternalProps<ElementType>, propsToPass: any ) => ExpandedPropsTypes, defineCustomElement?: () => void ) => { if (defineCustomElement !== undefined) { defineCustomElement(); } const displayName = dashToPascalCase(tagName); const ReactComponent = class extends React.Component<StencilReactInternalProps<ElementType>> { componentEl!: ElementType; setComponentElRef = (element: ElementType) => { this.componentEl = element; }; constructor(props: StencilReactInternalProps<ElementType>) { super(props); } componentDidMount() { this.componentDidUpdate(this.props); } componentDidUpdate(prevProps: StencilReactInternalProps<ElementType>) { attachProps(this.componentEl, this.props, prevProps); } render() { const { children, forwardedRef, style, className, ref, ...cProps } = this.props; let propsToPass = Object.keys(cProps).reduce((acc: any, name) => { const value = (cProps as any)[name]; if (name.indexOf('on') === 0 && name[2] === name[2].toUpperCase()) { const eventName = name.substring(2).toLowerCase(); if (typeof document !== 'undefined' && isCoveredByReact(eventName)) { acc[name] = value; } } else { // we should only render strings, booleans, and numbers as attrs in html. // objects, functions, arrays etc get synced via properties on mount. const type = typeof value; if (type === 'string' || type === 'boolean' || type === 'number') { acc[camelToDashCase(name)] = value; } } return acc; }, {} as ExpandedPropsTypes); if (manipulatePropsFunction) { propsToPass = manipulatePropsFunction(this.props, propsToPass); } const newProps: Omit<StencilReactInternalProps<ElementType>, 'forwardedRef'> = { ...propsToPass, ref: mergeRefs(forwardedRef, this.setComponentElRef), style, }; /** * We use createElement here instead of * React.createElement to work around a * bug in Vite (https://github.com/vitejs/vite/issues/6104). * React.createElement causes all elements to be rendered * as <tagname> instead of the actual Web Component. */ return createElement(tagName, newProps, children); } static get displayName() { return displayName; } }; // If context was passed to createReactComponent then conditionally add it to the Component Class if (ReactComponentContext) { ReactComponent.contextType = ReactComponentContext; } return createForwardRef<PropType, ElementType>(ReactComponent, displayName); };