Skip to content

Commit

Permalink
Abstract Ionic specifics out of react component lib.
Browse files Browse the repository at this point in the history
  • Loading branch information
jthoms1 committed Jun 3, 2020
1 parent 83817c1 commit 9d385ee
Show file tree
Hide file tree
Showing 12 changed files with 300 additions and 342 deletions.

This file was deleted.

Original file line number Diff line number Diff line change
@@ -1,15 +1,16 @@
import React from 'react';
import { render, waitForElement } from '@testing-library/react';
import { MyPopover } from '../src';
import '@testing-library/jest-dom';

describe('createOverlayComponent - events', () => {
test('should set events on handler', async () => {
const onDismiss = jest.fn();
const { baseElement, container } = render(
<>
<IonActionSheet isOpen={false} onDidDismiss={onDismiss} buttons={[]}>
<MyPopover isOpen={false} onDidDismiss={onDismiss} buttons={[]}>
ButtonNameA
</IonActionSheet>
</MyPopover>
<span>ButtonNameA</span>
</>,
);
Expand All @@ -20,9 +21,9 @@ describe('createOverlayComponent - events', () => {
test('should create component and attach props on opening', async () => {
const onDidDismiss = jest.fn();
const { baseElement, rerender, container } = render(
<IonActionSheet isOpen={false} onDidDismiss={onDidDismiss} buttons={[]}>
<MyPopover isOpen={false} onDidDismiss={onDidDismiss} buttons={[]}>
ButtonNameA
</IonActionSheet>,
</MyPopover>,
);

const [element, presentFunction] = createControllerElement();
Expand All @@ -31,9 +32,9 @@ describe('createOverlayComponent - events', () => {
const attachEventPropsSpy = jest.spyOn(utils, 'attachEventProps');

rerender(
<IonActionSheet isOpen={true} onDidDismiss={onDidDismiss} buttons={[]}>
<MyPopover isOpen={true} onDidDismiss={onDidDismiss} buttons={[]}>
ButtonNameA
</IonActionSheet>,
</MyPopover>,
);

await waitForElement(() => container.querySelector('ion-action-sheet'));
Expand All @@ -42,33 +43,33 @@ describe('createOverlayComponent - events', () => {
expect(presentFunction).toHaveBeenCalled();
expect(attachEventPropsSpy).toHaveBeenCalledWith(element, {
buttons: [],
onIonActionSheetDidDismiss: onDidDismiss,
onMyPopover: onDidDismiss,
});
});

test('should dismiss component on hiding', async () => {
const [element, , dismissFunction] = createControllerElement();

const { baseElement, rerender, container } = render(
<IonActionSheet isOpen={false} onDidDismiss={jest.fn()} buttons={[]}>
<MyPopover isOpen={false} onDidDismiss={jest.fn()} buttons={[]}>
ButtonNameA
</IonActionSheet>,
</MyPopover>,
);

augmentController(baseElement, container, element);

rerender(
<IonActionSheet isOpen={true} onDidDismiss={jest.fn()} buttons={[]}>
<MyPopover isOpen={true} onDidDismiss={jest.fn()} buttons={[]}>
ButtonNameA
</IonActionSheet>,
</MyPopover>,
);

await waitForElement(() => container.querySelector('ion-action-sheet'));

rerender(
<IonActionSheet isOpen={false} onDidDismiss={jest.fn()} buttons={[]}>
<MyPopover isOpen={false} onDidDismiss={jest.fn()} buttons={[]}>
ButtonNameA
</IonActionSheet>,
</MyPopover>,
);

expect(dismissFunction).toHaveBeenCalled();
Expand Down
Original file line number Diff line number Diff line change
@@ -1,61 +1,60 @@
import React from 'react';
import ReactDom from 'react-dom';

import {
attachEventProps,
createForwardRef,
dashToPascalCase,
isCoveredByReact,
} from './utils/index';
import { attachProps, createForwardRef, dashToPascalCase, isCoveredByReact } from './utils';

interface IonicReactInternalProps<ElementType> extends React.HTMLAttributes<ElementType> {
interface StencilReactInternalProps<ElementType> extends React.HTMLAttributes<ElementType> {
forwardedRef?: React.Ref<ElementType>;
ref?: React.Ref<any>;
}
export const NavContext = React.createContext<{}>({});

export const createReactComponent = <PropType, ElementType>(tagName: string) => {
export const createReactComponent = <PropType, ElementType, ContextStateType, ExpandedPropsTypes>(
tagName: string,
reactComponentContext: React.Context<ContextStateType>,
manipulatePropsFunction: (
originalProps: StencilReactInternalProps<PropType>,
propsToPass: any,
) => ExpandedPropsTypes = undefined,
) => {
const displayName = dashToPascalCase(tagName);
const ReactComponent = class extends React.Component<IonicReactInternalProps<ElementType>> {

private ref: React.RefObject<HTMLElement>;

constructor(props: IonicReactInternalProps<ElementType>) {
const ReactComponent = class extends React.Component<StencilReactInternalProps<PropType>> {
context!: React.Context<typeof reactComponentContext>;

constructor(props: StencilReactInternalProps<PropType>) {
super(props);
this.ref = React.createRef<HTMLElement>();
}

componentDidMount() {
this.componentDidUpdate(this.props);
}

componentDidUpdate(prevProps: IonicReactInternalProps<ElementType>) {
const node = this.ref.current;
attachEventProps(node, this.props, prevProps);
componentDidUpdate(prevProps: StencilReactInternalProps<PropType>) {
const node = ReactDom.findDOMNode(this) as HTMLElement;
attachProps(node, this.props, prevProps);
}

render() {
const { children, forwardedRef, style, className, ref, ...cProps } = this.props;

const propsToPass = Object.keys(cProps).reduce((acc, name) => {
const isEventProp = name.indexOf('on') === 0 && name[2] === name[2].toUpperCase();
const isDataProp = name.indexOf('data-') === 0;
const isAriaProp = name.indexOf('aria-') === 0;

if (isEventProp) {
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)) {
if (isCoveredByReact(eventName)) {
(acc as any)[name] = (cProps as any)[name];
}
} else if (isDataProp || isAriaProp) {
(acc as any)[name] = (cProps as any)[name];
}
return acc;
}, {});

const newProps: any = {
if (manipulatePropsFunction) {
propsToPass = manipulatePropsFunction(this.props, propsToPass);
}

let newProps: StencilReactInternalProps<PropType> = {
...propsToPass,
ref: this.ref,
ref: forwardedRef,
style,
className,
};

return React.createElement(tagName, newProps, children);
Expand All @@ -64,6 +63,10 @@ export const createReactComponent = <PropType, ElementType>(tagName: string) =>
static get displayName() {
return displayName;
}

static get contextType() {
return reactComponentContext;
}
};
return createForwardRef<PropType, ElementType>(ReactComponent, displayName);
};

This file was deleted.

0 comments on commit 9d385ee

Please sign in to comment.