mirror of
https://github.com/ionic-team/ionic-framework.git
synced 2025-08-16 10:01:59 +08:00
refactor(react): transition to Stencil React bindings (#23826)
This commit is contained in:
@ -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);
|
||||
};
|
Reference in New Issue
Block a user