Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
42 changes: 42 additions & 0 deletions packages/react/src/hooks/__tests__/overlay-hook-types.spec.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
import type React from 'react';

import type { useIonModal } from '../useIonModal';
import type { useIonPopover } from '../useIonPopover';

type OverlayComponentProps = {
title: string;
count?: number;
};

declare const ModalComponent: React.FC<OverlayComponentProps>;
declare const PopoverComponent: React.ComponentClass<OverlayComponentProps>;
declare const modalElement: JSX.Element;
declare const useIonModalForTypeTest: typeof useIonModal;
declare const useIonPopoverForTypeTest: typeof useIonPopover;

function expectOverlayHookTypes() {
useIonModalForTypeTest(ModalComponent, { title: 'Modal', count: 1 });
useIonPopoverForTypeTest(PopoverComponent, { title: 'Popover', count: 1 });

useIonModalForTypeTest(ModalComponent);
useIonPopoverForTypeTest(PopoverComponent);

useIonModalForTypeTest(modalElement, { anything: true });

// @ts-expect-error component props should match the modal component
useIonModalForTypeTest(ModalComponent, { count: 1 });

// @ts-expect-error component props should match the popover component
useIonPopoverForTypeTest(PopoverComponent, { count: 1 });

// @ts-expect-error unknown props should not be accepted for typed components
useIonModalForTypeTest(ModalComponent, { title: 'Modal', unknown: true });
}

void expectOverlayHookTypes;

describe('overlay hook types', () => {
it('type checks component props', () => {
expect(true).toBe(true);
});
});
4 changes: 3 additions & 1 deletion packages/react/src/hooks/useIonModal.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import { modalController } from '@ionic/core/components';
import { defineCustomElement } from '@ionic/core/components/ion-modal.js';
import { useCallback } from 'react';

import type { ReactComponentOrElement } from '../models/ReactComponentOrElement';
import type { ReactComponent, ReactComponentOrElement } from '../models/ReactComponentOrElement';

import type { HookOverlayOptions } from './HookOverlayOptions';
import { useOverlay } from './useOverlay';
Expand All @@ -16,6 +16,8 @@ import { useOverlay } from './useOverlay';
* @param componentProps The props that will be passed to the component, if required
* @returns Returns the present and dismiss methods in an array
*/
export function useIonModal<Props = any>(component: ReactComponent<Props>, componentProps?: Props): UseIonModalResult;
export function useIonModal(component: JSX.Element, componentProps?: any): UseIonModalResult;
export function useIonModal(component: ReactComponentOrElement, componentProps?: any): UseIonModalResult {
const controller = useOverlay<ModalOptions, HTMLIonModalElement>(
'IonModal',
Expand Down
7 changes: 6 additions & 1 deletion packages/react/src/hooks/useIonPopover.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import { popoverController } from '@ionic/core/components';
import { defineCustomElement } from '@ionic/core/components/ion-popover.js';
import { useCallback } from 'react';

import type { ReactComponentOrElement } from '../models/ReactComponentOrElement';
import type { ReactComponent, ReactComponentOrElement } from '../models/ReactComponentOrElement';

import type { HookOverlayOptions } from './HookOverlayOptions';
import { useOverlay } from './useOverlay';
Expand All @@ -16,6 +16,11 @@ import { useOverlay } from './useOverlay';
* @param componentProps The props that will be passed to the component, if required
* @returns Returns the present and dismiss methods in an array
*/
export function useIonPopover<Props = any>(
component: ReactComponent<Props>,
componentProps?: Props
): UseIonPopoverResult;
export function useIonPopover(component: JSX.Element, componentProps?: any): UseIonPopoverResult;
export function useIonPopover(component: ReactComponentOrElement, componentProps?: any): UseIonPopoverResult {
const controller = useOverlay<PopoverOptions, HTMLIonPopoverElement>(
'IonPopover',
Expand Down
3 changes: 2 additions & 1 deletion packages/react/src/models/ReactComponentOrElement.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import type React from 'react';

export type ReactComponentOrElement = React.ComponentClass<any, any> | React.FC<any> | JSX.Element;
export type ReactComponent<Props = any> = React.ComponentClass<Props, any> | React.FC<Props>;
export type ReactComponentOrElement<Props = any> = ReactComponent<Props> | JSX.Element;