refactor(react): transition to Stencil React bindings (#23826)

This commit is contained in:
William Martin
2021-08-31 17:29:59 -04:00
committed by GitHub
parent 5ca2ce9197
commit 1680b0ce9f
28 changed files with 530 additions and 314 deletions

View File

@ -0,0 +1,93 @@
import React from 'react';
import {
attachProps,
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,
) => {
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, name) => {
if (name.indexOf('on') === 0 && name[2] === name[2].toUpperCase()) {
const eventName = name.substring(2).toLowerCase();
if (typeof document !== 'undefined' && isCoveredByReact(eventName)) {
(acc as any)[name] = (cProps as any)[name];
}
} else {
(acc as any)[name] = (cProps as any)[name];
}
return acc;
}, {});
if (manipulatePropsFunction) {
propsToPass = manipulatePropsFunction(this.props, propsToPass);
}
const newProps: Omit<StencilReactInternalProps<ElementType>, 'forwardedRef'> = {
...propsToPass,
ref: mergeRefs(forwardedRef, this.setComponentElRef),
style,
};
return React.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);
};