chore(): sync with main

This commit is contained in:
Liam DeBeasi
2023-01-23 13:38:16 -05:00
377 changed files with 22590 additions and 6878 deletions

View File

@ -1,13 +1,16 @@
import {
import type {
Animation,
AnimationCallbackOptions,
AnimationDirection,
AnimationFill,
AnimationKeyFrames,
AnimationLifecycle,
createAnimation,
} from '@ionic/core/components';
import React, { PropsWithChildren } from 'react';
import { createAnimation } from '@ionic/core/components';
import type { PropsWithChildren } from 'react';
import React from 'react';
// TODO(FW-2959): types
interface PartialPropertyValue {
property: string;
@ -124,6 +127,7 @@ const checkConfig = (animation: Animation, currentProps: any = {}, prevProps: an
];
for (const key in currentProps) {
if (
// eslint-disable-next-line no-prototype-builtins
currentProps.hasOwnProperty(key) &&
!reservedProps.includes(key) &&
currentProps[key] !== prevProps[key]

View File

@ -1,26 +1,10 @@
import {
ActionSheetButton as ActionSheetButtonCore,
ActionSheetOptions as ActionSheetOptionsCore,
JSX
} from '@ionic/core/components';
import type { JSX } from '@ionic/core/components';
import { actionSheetController as actionSheetControllerCore } from '@ionic/core/components';
import { defineCustomElement } from '@ionic/core/components/ion-action-sheet.js';
import { createInlineOverlayComponent } from './createInlineOverlayComponent';
export interface ActionSheetButton extends Omit<ActionSheetButtonCore, 'icon'> {
icon?:
| {
ios: string;
md: string;
}
| string;
}
export interface ActionSheetOptions extends Omit<ActionSheetOptionsCore, 'buttons'> {
buttons?: (ActionSheetButton | string)[];
}
export const IonActionSheet = /*@__PURE__*/ createInlineOverlayComponent<
JSX.IonActionSheet,
HTMLIonActionSheetElement
>('ion-action-sheet', defineCustomElement);
export const IonActionSheet = /*@__PURE__*/ createInlineOverlayComponent<JSX.IonActionSheet, HTMLIonActionSheetElement>(
'ion-action-sheet',
defineCustomElement
);

View File

@ -1,4 +1,4 @@
import { JSX } from '@ionic/core/components';
import type { JSX } from '@ionic/core/components';
import { defineCustomElement } from '@ionic/core/components/ion-alert.js';
import { createInlineOverlayComponent } from './createInlineOverlayComponent';

View File

@ -1,11 +1,12 @@
import { JSX as LocalJSX } from '@ionic/core/components';
import type { JSX as LocalJSX } from '@ionic/core/components';
import React from 'react';
import { IonContext, IonContextInterface } from '../contexts/IonContext';
import { ReactComponentOrElement } from '../models';
import type { IonContextInterface } from '../contexts/IonContext';
import { IonContext } from '../contexts/IonContext';
import type { ReactComponentOrElement } from '../models';
import { IonOverlayManager } from './IonOverlayManager';
import { IonicReactProps } from './IonicReactProps';
import type { IonicReactProps } from './IonicReactProps';
import { IonAppInner } from './inner-proxies';
type Props = LocalJSX.IonApp &
@ -15,7 +16,7 @@ type Props = LocalJSX.IonApp &
export const IonApp = /*@__PURE__*/ (() =>
class extends React.Component<Props> {
addOverlayCallback?: (id: string, overlay: any, containerElement: HTMLDivElement) => void;
addOverlayCallback?: (id: string, overlay: ReactComponentOrElement, containerElement: HTMLDivElement) => void;
removeOverlayCallback?: (id: string) => void;
constructor(props: Props) {
@ -26,11 +27,7 @@ export const IonApp = /*@__PURE__*/ (() =>
Wire up methods to call into IonOverlayManager
*/
ionContext: IonContextInterface = {
addOverlay: (
id: string,
overlay: ReactComponentOrElement,
containerElement: HTMLDivElement
) => {
addOverlay: (id: string, overlay: ReactComponentOrElement, containerElement: HTMLDivElement) => {
if (this.addOverlayCallback) {
this.addOverlayCallback(id, overlay, containerElement);
}

View File

@ -2,7 +2,7 @@ import React from 'react';
import { NavContext } from '../contexts/NavContext';
import { IonicReactProps } from './IonicReactProps';
import type { IonicReactProps } from './IonicReactProps';
import { IonIconInner } from './inner-proxies';
import { createForwardRef, isPlatform } from './utils';
@ -27,7 +27,9 @@ class IonIconContainer extends React.PureComponent<InternalProps> {
constructor(props: InternalProps) {
super(props);
if (this.props.name) {
console.warn('In Ionic React, you import icons from "ionicons/icons" and set the icon you imported to the "icon" property. Setting the "name" property has no effect.');
console.warn(
'In Ionic React, you import icons from "ionicons/icons" and set the icon you imported to the "icon" property. Setting the "name" property has no effect.'
);
}
}

View File

@ -1,9 +1,9 @@
import { JSX } from '@ionic/core/components';
import type { JSX } from '@ionic/core/components';
import { defineCustomElement } from '@ionic/core/components/ion-loading.js';
import { createInlineOverlayComponent } from './createInlineOverlayComponent';
export const IonLoading = /*@__PURE__*/ createInlineOverlayComponent<
JSX.IonLoading,
HTMLIonLoadingElement
>('ion-loading', defineCustomElement);
export const IonLoading = /*@__PURE__*/ createInlineOverlayComponent<JSX.IonLoading, HTMLIonLoadingElement>(
'ion-loading',
defineCustomElement
);

View File

@ -1,9 +1,9 @@
import { JSX } from '@ionic/core/components';
import type { JSX } from '@ionic/core/components';
import { defineCustomElement } from '@ionic/core/components/ion-modal.js';
import { createInlineOverlayComponent } from './createInlineOverlayComponent'
import { createInlineOverlayComponent } from './createInlineOverlayComponent';
export const IonModal = /*@__PURE__*/ createInlineOverlayComponent<
JSX.IonModal,
HTMLIonModalElement
>('ion-modal', defineCustomElement);
export const IonModal = /*@__PURE__*/ createInlineOverlayComponent<JSX.IonModal, HTMLIonModalElement>(
'ion-modal',
defineCustomElement
);

View File

@ -1,15 +1,11 @@
import React, { useEffect, useRef, useState } from 'react';
import ReactDOM from 'react-dom';
import { ReactComponentOrElement } from '../models';
import type { ReactComponentOrElement } from '../models';
interface IonOverlayManagerProps {
onAddOverlay: (
callback: (
id: string,
component: ReactComponentOrElement,
containerElement: HTMLDivElement
) => void
callback: (id: string, component: ReactComponentOrElement, containerElement: HTMLDivElement) => void
) => void;
onRemoveOverlay: (callback: (id: string) => void) => void;
}
@ -21,13 +17,10 @@ interface IonOverlayManagerProps {
* that is set up in <IonApp />, so we register callbacks so when overlays are added to IonContext,
* they ultimately added here.
*/
export const IonOverlayManager: React.FC<IonOverlayManagerProps> = ({
onAddOverlay,
onRemoveOverlay,
}) => {
export const IonOverlayManager: React.FC<IonOverlayManagerProps> = ({ onAddOverlay, onRemoveOverlay }) => {
type OverlaysList = {
[key: string]: {
component: any;
component: any; // TODO(FW-2959): type
containerElement: HTMLDivElement;
};
};
@ -55,11 +48,7 @@ export const IonOverlayManager: React.FC<IonOverlayManagerProps> = ({
onRemoveOverlay(removeOverlay);
}, []);
const addOverlay = (
id: string,
component: ReactComponentOrElement,
containerElement: HTMLDivElement
) => {
const addOverlay = (id: string, component: ReactComponentOrElement, containerElement: HTMLDivElement) => {
const newOverlays = { ...overlaysRef.current };
newOverlays[id] = { component, containerElement };
setOverlays(newOverlays);

View File

@ -3,9 +3,10 @@ import React from 'react';
import { NavContext } from '../contexts/NavContext';
import PageManager from '../routing/PageManager';
import { IonicReactProps } from './IonicReactProps';
import type { IonicReactProps } from './IonicReactProps';
import { createForwardRef } from './utils';
// eslint-disable-next-line @typescript-eslint/no-empty-interface
interface IonPageProps extends IonicReactProps {}
interface IonPageInternalProps extends IonPageProps {
@ -32,11 +33,7 @@ class IonPageInternal extends React.Component<IonPageInternalProps> {
{children}
</PageManager>
) : (
<div
className={className ? `ion-page ${className}` : 'ion-page'}
ref={forwardedRef}
{...props}
>
<div className={className ? `ion-page ${className}` : 'ion-page'} ref={forwardedRef} {...props}>
{children}
</div>
);

View File

@ -1,9 +1,9 @@
import { JSX } from '@ionic/core/components';
import type { JSX } from '@ionic/core/components';
import { defineCustomElement } from '@ionic/core/components/ion-picker.js';
import { createInlineOverlayComponent } from './createInlineOverlayComponent';
export const IonPicker = /*@__PURE__*/ createInlineOverlayComponent<
JSX.IonPicker,
HTMLIonPickerElement
>('ion-picker', defineCustomElement);
export const IonPicker = /*@__PURE__*/ createInlineOverlayComponent<JSX.IonPicker, HTMLIonPickerElement>(
'ion-picker',
defineCustomElement
);

View File

@ -1,9 +1,9 @@
import { JSX } from '@ionic/core/components';
import type { JSX } from '@ionic/core/components';
import { defineCustomElement } from '@ionic/core/components/ion-popover.js';
import { createInlineOverlayComponent } from './createInlineOverlayComponent'
import { createInlineOverlayComponent } from './createInlineOverlayComponent';
export const IonPopover = /*@__PURE__*/ createInlineOverlayComponent<
JSX.IonPopover,
HTMLIonPopoverElement
>('ion-popover', defineCustomElement);
export const IonPopover = /*@__PURE__*/ createInlineOverlayComponent<JSX.IonPopover, HTMLIonPopoverElement>(
'ion-popover',
defineCustomElement
);

View File

@ -9,6 +9,7 @@ export interface IonRedirectProps {
routerOptions?: unknown;
}
// eslint-disable-next-line @typescript-eslint/no-empty-interface
interface IonRedirectState {}
export class IonRedirect extends React.PureComponent<IonRedirectProps, IonRedirectState> {

View File

@ -6,10 +6,11 @@ export interface IonRouteProps {
path?: string;
exact?: boolean;
show?: boolean;
render: (props?: any) => JSX.Element;
render: (props?: any) => JSX.Element; // TODO(FW-2959): type
disableIonPageManagement?: boolean;
}
// eslint-disable-next-line @typescript-eslint/no-empty-interface
interface IonRouteState {}
export class IonRoute extends React.PureComponent<IonRouteProps, IonRouteState> {
@ -19,9 +20,7 @@ export class IonRoute extends React.PureComponent<IonRouteProps, IonRouteState>
const IonRouteInner = this.context.getIonRoute();
if (!this.context.hasIonicRouter() || !IonRoute) {
console.error(
'You either do not have an Ionic Router package, or your router does not support using <IonRoute>'
);
console.error('You either do not have an Ionic Router package, or your router does not support using <IonRoute>');
return null;
}

View File

@ -1,8 +1,8 @@
import { AnimationBuilder } from '@ionic/core/components';
import type { AnimationBuilder } from '@ionic/core/components';
import React, { useContext, useMemo } from 'react';
import { RouteAction, RouterDirection, RouterOptions } from '../models';
import { RouteInfo } from '../models/RouteInfo';
import type { RouteAction, RouterDirection, RouterOptions } from '../models';
import type { RouteInfo } from '../models/RouteInfo';
export interface IonRouterContextState {
routeInfo: RouteInfo;
@ -19,7 +19,7 @@ export interface IonRouterContextState {
}
export const IonRouterContext = React.createContext<IonRouterContextState>({
routeInfo: undefined as any,
routeInfo: undefined as any, // TODO(FW-2959): type
push: () => {
throw new Error('An Ionic Router is required for IonRouterContext');
},

View File

@ -1,10 +1,10 @@
import { JSX as LocalJSX } from '@ionic/core/components';
import type { JSX as LocalJSX } from '@ionic/core/components';
import React from 'react';
import { NavContext } from '../contexts/NavContext';
import OutletPageManager from '../routing/OutletPageManager';
import { IonicReactProps } from './IonicReactProps';
import type { IonicReactProps } from './IonicReactProps';
import { IonRouterOutletInner } from './inner-proxies';
import { createForwardRef } from './utils';
@ -18,6 +18,7 @@ interface InternalProps extends Props {
forwardedRef?: React.ForwardedRef<HTMLIonRouterOutletElement>;
}
// eslint-disable-next-line @typescript-eslint/no-empty-interface
interface InternalState {}
class IonRouterOutletContainer extends React.Component<InternalProps, InternalState> {
@ -33,11 +34,7 @@ class IonRouterOutletContainer extends React.Component<InternalProps, InternalSt
return this.context.hasIonicRouter() ? (
props.ionPage ? (
<OutletPageManager
StackManager={StackManager}
routeInfo={this.context.routeInfo}
{...props}
>
<OutletPageManager StackManager={StackManager} routeInfo={this.context.routeInfo} {...props}>
{children}
</OutletPageManager>
) : (
@ -59,7 +56,7 @@ class IonRouterOutletContainer extends React.Component<InternalProps, InternalSt
}
}
export const IonRouterOutlet = createForwardRef<
Props & IonicReactProps,
HTMLIonRouterOutletElement
>(IonRouterOutletContainer, 'IonRouterOutlet');
export const IonRouterOutlet = createForwardRef<Props & IonicReactProps, HTMLIonRouterOutletElement>(
IonRouterOutletContainer,
'IonRouterOutlet'
);

View File

@ -1,25 +1,8 @@
import {
JSX,
ToastButton as ToastButtonCore,
ToastOptions as ToastOptionsCore
} from '@ionic/core/components';
import type { JSX } from '@ionic/core/components';
import { defineCustomElement } from '@ionic/core/components/ion-toast.js';
import { createInlineOverlayComponent } from './createInlineOverlayComponent';
export interface ToastButton extends Omit<ToastButtonCore, 'icon'> {
icon?:
| {
ios: string;
md: string;
}
| string;
}
export interface ToastOptions extends Omit<ToastOptionsCore, 'buttons'> {
buttons?: (ToastButton | string)[];
}
export const IonToast = /*@__PURE__*/ createInlineOverlayComponent<JSX.IonToast, HTMLIonToastElement>(
'ion-toast',
defineCustomElement

View File

@ -1,11 +1,7 @@
import { OverlayEventDetail } from '@ionic/core/components';
import type { OverlayEventDetail } from '@ionic/core/components';
import React from 'react';
import {
attachProps,
dashToPascalCase,
setRef,
} from './react-component-lib/utils';
import { attachProps, dashToPascalCase, setRef } from './react-component-lib/utils';
interface OverlayBase extends HTMLElement {
present: () => Promise<void>;
@ -20,10 +16,7 @@ export interface ReactControllerProps {
onWillPresent?: (event: CustomEvent<OverlayEventDetail>) => void;
}
export const createControllerComponent = <
OptionsType extends object,
OverlayType extends OverlayBase
>(
export const createControllerComponent = <OptionsType extends object, OverlayType extends OverlayBase>(
tagName: string,
controller: { create: (options: OptionsType) => Promise<OverlayType> },
defineCustomElement?: () => void
@ -95,8 +88,8 @@ export const createControllerComponent = <
}
async present(prevProps?: Props) {
const { isOpen, onDidDismiss, onDidPresent, onWillDismiss, onWillPresent, ...cProps } =
this.props;
// eslint-disable-next-line @typescript-eslint/no-unused-vars
const { isOpen, onDidDismiss, onDidPresent, onWillDismiss, onWillPresent, ...cProps } = this.props;
if (this.overlay) {
this.overlay.remove();
@ -109,12 +102,9 @@ export const createControllerComponent = <
this.overlay,
{
[didDismissEventName]: this.handleDismiss,
[didPresentEventName]: (e: CustomEvent) =>
this.props.onDidPresent && this.props.onDidPresent(e),
[willDismissEventName]: (e: CustomEvent) =>
this.props.onWillDismiss && this.props.onWillDismiss(e),
[willPresentEventName]: (e: CustomEvent) =>
this.props.onWillPresent && this.props.onWillPresent(e),
[didPresentEventName]: (e: CustomEvent) => this.props.onDidPresent && this.props.onDidPresent(e),
[willDismissEventName]: (e: CustomEvent) => this.props.onWillDismiss && this.props.onWillDismiss(e),
[willPresentEventName]: (e: CustomEvent) => this.props.onWillPresent && this.props.onWillPresent(e),
},
prevProps
);

View File

@ -1,4 +1,4 @@
import { OverlayEventDetail } from '@ionic/core/components';
import type { OverlayEventDetail } from '@ionic/core/components';
import React, { createElement } from 'react';
import {
@ -10,6 +10,8 @@ import {
} from './react-component-lib/utils';
import { createForwardRef } from './utils';
// TODO(FW-2959): types
type InlineOverlayState = {
isOpen: boolean;
};
@ -32,10 +34,7 @@ export const createInlineOverlayComponent = <PropType, ElementType>(
defineCustomElement();
}
const displayName = dashToPascalCase(tagName);
const ReactComponent = class extends React.Component<
IonicReactInternalProps<PropType>,
InlineOverlayState
> {
const ReactComponent = class extends React.Component<IonicReactInternalProps<PropType>, InlineOverlayState> {
ref: React.RefObject<HTMLElement>;
wrapperRef: React.RefObject<HTMLElement>;
stableMergedRefs: React.RefCallback<HTMLElement>;
@ -117,6 +116,7 @@ export const createInlineOverlayComponent = <PropType, ElementType>(
}
render() {
// eslint-disable-next-line @typescript-eslint/no-unused-vars
const { children, forwardedRef, style, className, ref, ...cProps } = this.props;
const propsToPass = Object.keys(cProps).reduce((acc, name) => {

View File

@ -1,4 +1,4 @@
import { OverlayEventDetail } from '@ionic/core/components';
import type { OverlayEventDetail } from '@ionic/core/components';
import React from 'react';
import ReactDOM from 'react-dom';
@ -18,10 +18,7 @@ export interface ReactOverlayProps {
onWillPresent?: (event: CustomEvent<OverlayEventDetail>) => void;
}
export const createOverlayComponent = <
OverlayComponent extends object,
OverlayType extends OverlayElement
>(
export const createOverlayComponent = <OverlayComponent extends object, OverlayType extends OverlayElement>(
tagName: string,
controller: { create: (options: any) => Promise<OverlayType> },
defineCustomElement?: () => void
@ -73,7 +70,7 @@ export const createOverlayComponent = <
if (this.props.onDidDismiss) {
this.props.onDidDismiss(event);
}
setRef(this.props.forwardedRef, null)
setRef(this.props.forwardedRef, null);
}
shouldComponentUpdate(nextProps: Props) {
@ -107,26 +104,17 @@ export const createOverlayComponent = <
}
async present(prevProps?: Props) {
const {
children,
isOpen,
onDidDismiss,
onDidPresent,
onWillDismiss,
onWillPresent,
...cProps
} = this.props;
/* eslint-disable @typescript-eslint/no-unused-vars */
const { children, isOpen, onDidDismiss, onDidPresent, onWillDismiss, onWillPresent, ...cProps } = this.props;
const elementProps = {
...cProps,
ref: this.props.forwardedRef,
[didDismissEventName]: this.handleDismiss,
[didPresentEventName]: (e: CustomEvent) =>
this.props.onDidPresent && this.props.onDidPresent(e),
[willDismissEventName]: (e: CustomEvent) =>
this.props.onWillDismiss && this.props.onWillDismiss(e),
[willPresentEventName]: (e: CustomEvent) =>
this.props.onWillPresent && this.props.onWillPresent(e),
[didPresentEventName]: (e: CustomEvent) => this.props.onDidPresent && this.props.onDidPresent(e),
[willDismissEventName]: (e: CustomEvent) => this.props.onWillDismiss && this.props.onWillDismiss(e),
[willPresentEventName]: (e: CustomEvent) => this.props.onWillPresent && this.props.onWillPresent(e),
};
/* eslint-enable @typescript-eslint/no-unused-vars */
this.overlay = await controller.create({
...elementProps,

View File

@ -1,9 +1,9 @@
import { AnimationBuilder } from '@ionic/core/components';
import type { AnimationBuilder } from '@ionic/core/components';
import React, { createElement } from 'react';
import { NavContext } from '../contexts/NavContext';
import { RouterOptions } from '../models';
import { RouterDirection } from '../models/RouterDirection';
import type { RouterOptions } from '../models';
import type { RouterDirection } from '../models/RouterDirection';
import {
attachProps,
@ -15,6 +15,8 @@ import {
} from './react-component-lib/utils';
import { createForwardRef } from './utils';
// TODO(FW-2959): types
interface IonicReactInternalProps<ElementType> extends React.HTMLAttributes<ElementType> {
forwardedRef?: React.ForwardedRef<ElementType>;
href?: string;
@ -25,24 +27,21 @@ interface IonicReactInternalProps<ElementType> extends React.HTMLAttributes<Elem
routerAnimation?: AnimationBuilder;
}
export const createRoutingComponent = <PropType, ElementType>(
tagName: string,
customElement?: any
) => {
export const createRoutingComponent = <PropType, ElementType>(tagName: string, customElement?: any) => {
defineCustomElement(tagName, customElement);
const displayName = dashToPascalCase(tagName);
const ReactComponent = class extends React.Component<IonicReactInternalProps<PropType>> {
context!: React.ContextType<typeof NavContext>;
ref: React.RefObject<HTMLElement>;
stableMergedRefs: React.RefCallback<HTMLElement>
stableMergedRefs: React.RefCallback<HTMLElement>;
constructor(props: IonicReactInternalProps<PropType>) {
super(props);
// Create a local ref to to attach props to the wrapped element.
this.ref = React.createRef();
// React refs must be stable (not created inline).
this.stableMergedRefs = mergeRefs(this.ref, this.props.forwardedRef)
this.stableMergedRefs = mergeRefs(this.ref, this.props.forwardedRef);
}
componentDidMount() {
@ -58,17 +57,12 @@ export const createRoutingComponent = <PropType, ElementType>(
const { routerLink, routerDirection, routerOptions, routerAnimation } = this.props;
if (routerLink !== undefined) {
e.preventDefault();
this.context.navigate(
routerLink,
routerDirection,
undefined,
routerAnimation,
routerOptions
);
this.context.navigate(routerLink, routerDirection, undefined, routerAnimation, routerOptions);
}
};
render() {
// eslint-disable-next-line @typescript-eslint/no-unused-vars
const { children, forwardedRef, style, className, ref, ...cProps } = this.props;
const propsToPass = Object.keys(cProps).reduce((acc, name) => {

View File

@ -1,7 +1,7 @@
import { AnimationBuilder } from '@ionic/core/components';
import type { AnimationBuilder } from '@ionic/core/components';
import { RouterOptions } from '../models';
import { RouterDirection } from '../models/RouterDirection';
import type { RouterOptions } from '../models';
import type { RouterDirection } from '../models/RouterDirection';
export type HrefProps<T> = Omit<T, 'routerDirection'> & {
routerLink?: string;

View File

@ -1,4 +1,5 @@
import { IonicConfig, initialize } from '@ionic/core/components';
import type { IonicConfig } from '@ionic/core/components';
import { initialize } from '@ionic/core/components';
export {
// UTILS
@ -21,93 +22,62 @@ export {
GestureConfig,
GestureDetail,
NavComponentWithProps,
SpinnerTypes,
AccordionGroupCustomEvent,
AccordionGroupChangeEventDetail,
BreadcrumbCustomEvent,
BreadcrumbCollapsedClickEventDetail,
ActionSheetOptions,
ActionSheetButton,
AlertOptions,
AlertInput,
AlertButton,
BackButtonEvent,
CheckboxCustomEvent,
CheckboxChangeEventDetail,
DatetimeCustomEvent,
DatetimeChangeEventDetail,
InfiniteScrollCustomEvent,
InputCustomEvent,
InputChangeEventDetail,
ItemReorderEventDetail,
ItemReorderCustomEvent,
ItemSlidingCustomEvent,
IonicSafeString,
LoadingOptions,
MenuCustomEvent,
ModalOptions,
NavCustomEvent,
PickerOptions,
PickerButton,
PickerColumn,
PickerColumnOption,
PopoverOptions,
RadioGroupCustomEvent,
RadioGroupChangeEventDetail,
RangeCustomEvent,
RangeChangeEventDetail,
RangeKnobMoveStartEventDetail,
RangeKnobMoveEndEventDetail,
RefresherCustomEvent,
RefresherEventDetail,
RouterEventDetail,
RouterCustomEvent,
ScrollBaseCustomEvent,
ScrollBaseDetail,
ScrollDetail,
ScrollCustomEvent,
SearchbarCustomEvent,
SearchbarChangeEventDetail,
SegmentChangeEventDetail,
SegmentCustomEvent,
SelectChangeEventDetail,
SelectCustomEvent,
TabsCustomEvent,
TextareaChangeEventDetail,
TextareaCustomEvent,
ToastOptions,
ToastButton,
ToggleChangeEventDetail,
ToggleCustomEvent,
} from '@ionic/core/components';
@ -170,6 +140,6 @@ export const setupIonicReact = (config: IonicConfig = {}) => {
}
initialize({
...config
...config,
});
}
};

View File

@ -1,10 +1,10 @@
import { JSX } from '@ionic/core/components';
import type { JSX } from '@ionic/core/components';
import { defineCustomElement as defineIonApp } from '@ionic/core/components/ion-app.js';
import { defineCustomElement as defineIonBackButton } from '@ionic/core/components/ion-back-button.js';
import { defineCustomElement as defineIonRouterOutlet } from '@ionic/core/components/ion-router-outlet.js';
import { defineCustomElement as defineIonTabBar } from '@ionic/core/components/ion-tab-bar.js';
import { defineCustomElement as defineIonTabButton } from '@ionic/core/components/ion-tab-button.js';
import { JSX as IoniconsJSX } from 'ionicons';
import type { JSX as IoniconsJSX } from 'ionicons';
import { defineCustomElement as defineIonIcon } from 'ionicons/components/ion-icon.js';
import { /*@__PURE__*/ createReactComponent } from './react-component-lib';
@ -13,10 +13,12 @@ export const IonTabButtonInner = /*@__PURE__*/ createReactComponent<
JSX.IonTabButton & { onIonTabButtonClick?: (e: CustomEvent) => void },
HTMLIonTabButtonElement
>('ion-tab-button', undefined, undefined, defineIonTabButton);
export const IonTabBarInner = /*@__PURE__*/ createReactComponent<
JSX.IonTabBar,
HTMLIonTabBarElement
>('ion-tab-bar', undefined, undefined, defineIonTabBar);
export const IonTabBarInner = /*@__PURE__*/ createReactComponent<JSX.IonTabBar, HTMLIonTabBarElement>(
'ion-tab-bar',
undefined,
undefined,
defineIonTabBar
);
export const IonBackButtonInner = /*@__PURE__*/ createReactComponent<
Omit<JSX.IonBackButton, 'icon'>,
HTMLIonBackButtonElement
@ -37,7 +39,9 @@ export const IonAppInner = /*@__PURE__*/ createReactComponent<JSX.IonApp, HTMLIo
);
// ionicons
export const IonIconInner = /*@__PURE__*/ createReactComponent<
IoniconsJSX.IonIcon,
HTMLIonIconElement
>('ion-icon', undefined, undefined, defineIonIcon);
export const IonIconInner = /*@__PURE__*/ createReactComponent<IoniconsJSX.IonIcon, HTMLIonIconElement>(
'ion-icon',
undefined,
undefined,
defineIonIcon
);

View File

@ -1,8 +1,8 @@
import { JSX as LocalJSX } from '@ionic/core/components';
import type { JSX as LocalJSX } from '@ionic/core/components';
import React from 'react';
import { NavContext } from '../../contexts/NavContext';
import { IonicReactProps } from '../IonicReactProps';
import type { IonicReactProps } from '../IonicReactProps';
import { IonBackButtonInner } from '../inner-proxies';
type Props = Omit<LocalJSX.IonBackButton, 'icon'> &
@ -26,7 +26,9 @@ export const IonBackButton = /*@__PURE__*/ (() =>
* of ion-nav then we should not interact with
* the router.
*/
if (e.target && (e.target as HTMLElement).closest('ion-nav') !== null) { return; }
if (e.target && (e.target as HTMLElement).closest('ion-nav') !== null) {
return;
}
const { defaultHref, routerAnimation } = this.props;

View File

@ -6,15 +6,18 @@ import { ReactDelegate } from '../../framework-delegate';
import { createReactComponent } from '../react-component-lib';
import { createForwardRef } from '../utils';
const IonNavInner = createReactComponent<
JSX.IonNav & { delegate: FrameworkDelegate },
HTMLIonNavElement
>('ion-nav', undefined, undefined, defineCustomElement);
const IonNavInner = createReactComponent<JSX.IonNav & { delegate: FrameworkDelegate }, HTMLIonNavElement>(
'ion-nav',
undefined,
undefined,
defineCustomElement
);
type IonNavProps = JSX.IonNav & {
forwardedRef?: React.ForwardedRef<HTMLIonNavElement>;
};
// eslint-disable-next-line @typescript-eslint/no-unused-vars
const IonNavInternal: React.FC<IonNavProps> = ({ children, forwardedRef, ...restOfProps }) => {
const [views, setViews] = useState<React.ReactElement[]>([]);

View File

@ -1,9 +1,9 @@
import { JSX as LocalJSX } from '@ionic/core/components';
import type { JSX as LocalJSX } from '@ionic/core/components';
import React, { useContext } from 'react';
import { NavContext } from '../../contexts/NavContext';
import { RouteInfo } from '../../models';
import { IonicReactProps } from '../IonicReactProps';
import type { RouteInfo } from '../../models';
import type { IonicReactProps } from '../IonicReactProps';
import { IonTabBarInner } from '../inner-proxies';
import { createForwardRef } from '../utils';
@ -35,6 +35,8 @@ interface IonTabBarState {
tabs: { [key: string]: TabUrls };
}
// TODO(FW-2959): types
class IonTabBarUnwrapped extends React.PureComponent<InternalProps, IonTabBarState> {
context!: React.ContextType<typeof NavContext>;
@ -52,13 +54,9 @@ class IonTabBarUnwrapped extends React.PureComponent<InternalProps, IonTabBarSta
originalHref: child.props.href,
currentHref: child.props.href,
originalRouteOptions:
child.props.href === props.routeInfo?.pathname
? props.routeInfo?.routeOptions
: undefined,
child.props.href === props.routeInfo?.pathname ? props.routeInfo?.routeOptions : undefined,
currentRouteOptions:
child.props.href === props.routeInfo?.pathname
? props.routeInfo?.routeOptions
: undefined,
child.props.href === props.routeInfo?.pathname ? props.routeInfo?.routeOptions : undefined,
};
}
});
@ -94,6 +92,7 @@ class IonTabBarUnwrapped extends React.PureComponent<InternalProps, IonTabBarSta
}
}
// eslint-disable-next-line
setActiveTabOnContext = (_tab: string) => {};
selectTab(tab: string) {
@ -202,14 +201,10 @@ class IonTabBarUnwrapped extends React.PureComponent<InternalProps, IonTabBarSta
}
} else {
if (this.props.onIonTabsWillChange) {
this.props.onIonTabsWillChange(
new CustomEvent('ionTabWillChange', { detail: { tab: e.detail.tab } })
);
this.props.onIonTabsWillChange(new CustomEvent('ionTabWillChange', { detail: { tab: e.detail.tab } }));
}
if (this.props.onIonTabsDidChange) {
this.props.onIonTabsDidChange(
new CustomEvent('ionTabDidChange', { detail: { tab: e.detail.tab } })
);
this.props.onIonTabsDidChange(new CustomEvent('ionTabDidChange', { detail: { tab: e.detail.tab } }));
}
this.setActiveTabOnContext(e.detail.tab);
this.context.changeTab(e.detail.tab, currentHref, e.detail.routeOptions);
@ -219,17 +214,11 @@ class IonTabBarUnwrapped extends React.PureComponent<InternalProps, IonTabBarSta
private renderTabButton(activeTab: string | null | undefined) {
return (
child:
| React.ReactElement<
LocalJSX.IonTabButton & { onClick: (e: any) => void; routeOptions?: unknown }
>
| React.ReactElement<LocalJSX.IonTabButton & { onClick: (e: any) => void; routeOptions?: unknown }>
| null
| undefined
) => {
if (
child != null &&
child.props &&
(child.type === IonTabButton || (child as any).type.isTabButton)
) {
if (child != null && child.props && (child.type === IonTabButton || (child as any).type.isTabButton)) {
const href =
child.props.tab === activeTab
? this.props.routeInfo?.pathname
@ -263,23 +252,18 @@ class IonTabBarUnwrapped extends React.PureComponent<InternalProps, IonTabBarSta
}
}
const IonTabBarContainer: React.FC<InternalProps> = React.memo<InternalProps>(
({ forwardedRef, ...props }) => {
const context = useContext(NavContext);
return (
<IonTabBarUnwrapped
ref={forwardedRef}
{...(props as any)}
routeInfo={props.routeInfo || context.routeInfo || { pathname: window.location.pathname }}
onSetCurrentTab={context.setCurrentTab}
>
{props.children}
</IonTabBarUnwrapped>
);
}
);
const IonTabBarContainer: React.FC<InternalProps> = React.memo<InternalProps>(({ forwardedRef, ...props }) => {
const context = useContext(NavContext);
return (
<IonTabBarUnwrapped
ref={forwardedRef}
{...(props as any)}
routeInfo={props.routeInfo || context.routeInfo || { pathname: window.location.pathname }}
onSetCurrentTab={context.setCurrentTab}
>
{props.children}
</IonTabBarUnwrapped>
);
});
export const IonTabBar = createForwardRef<IonTabBarProps, HTMLIonTabBarElement>(
IonTabBarContainer,
'IonTabBar'
);
export const IonTabBar = createForwardRef<IonTabBarProps, HTMLIonTabBarElement>(IonTabBarContainer, 'IonTabBar');

View File

@ -1,15 +1,15 @@
import { JSX as LocalJSX } from '@ionic/core/components';
import type { JSX as LocalJSX } from '@ionic/core/components';
import React from 'react';
import { RouterOptions } from '../../models';
import { IonicReactProps } from '../IonicReactProps';
import type { RouterOptions } from '../../models';
import type { IonicReactProps } from '../IonicReactProps';
import { IonTabButtonInner } from '../inner-proxies';
type Props = LocalJSX.IonTabButton &
IonicReactProps & {
routerOptions?: RouterOptions;
ref?: React.Ref<HTMLIonTabButtonElement>;
onClick?: (e: any) => void;
onClick?: (e: Event) => void;
};
export const IonTabButton = /*@__PURE__*/ (() =>
@ -39,13 +39,9 @@ export const IonTabButton = /*@__PURE__*/ (() =>
* implementation within IonTabBar.tsx. Calling onClick within this
* component would result in duplicate handler calls.
*/
// eslint-disable-next-line @typescript-eslint/no-unused-vars
const { onClick, ...rest } = this.props;
return (
<IonTabButtonInner
onIonTabButtonClick={this.handleIonTabButtonClick}
{...rest}
></IonTabButtonInner>
);
return <IonTabButtonInner onIonTabButtonClick={this.handleIonTabButtonClick} {...rest}></IonTabButtonInner>;
}
static get displayName() {

View File

@ -1,4 +1,4 @@
import { JSX as LocalJSX } from '@ionic/core/components';
import type { JSX as LocalJSX } from '@ionic/core/components';
import React, { Fragment } from 'react';
import { NavContext } from '../../contexts/NavContext';
@ -7,7 +7,8 @@ import { HTMLElementSSR } from '../../utils/HTMLElementSSR';
import { IonRouterOutlet } from '../IonRouterOutlet';
import { IonTabBar } from './IonTabBar';
import { IonTabsContext, IonTabsContextState } from './IonTabsContext';
import type { IonTabsContextState } from './IonTabsContext';
import { IonTabsContext } from './IonTabsContext';
class IonTabsElement extends HTMLElementSSR {
constructor() {
@ -15,6 +16,8 @@ class IonTabsElement extends HTMLElementSSR {
}
}
// TODO(FW-2959): types
if (typeof (window as any) !== 'undefined' && window.customElements) {
const element = window.customElements.get('ion-tabs');
if (!element) {
@ -23,6 +26,7 @@ if (typeof (window as any) !== 'undefined' && window.customElements) {
}
declare global {
// eslint-disable-next-line @typescript-eslint/no-namespace
namespace JSX {
interface IntrinsicElements {
'ion-tabs': any;
@ -95,6 +99,7 @@ export const IonTabs = /*@__PURE__*/ (() =>
: this.props.children;
React.Children.forEach(children, (child: any) => {
// eslint-disable-next-line no-prototype-builtins
if (child == null || typeof child !== 'object' || !child.hasOwnProperty('type')) {
return;
}
@ -105,8 +110,8 @@ export const IonTabs = /*@__PURE__*/ (() =>
}
let childProps: any = {
ref: this.tabBarRef
}
ref: this.tabBarRef,
};
/**
* Only pass these props
@ -118,15 +123,15 @@ export const IonTabs = /*@__PURE__*/ (() =>
if (onIonTabsDidChange !== undefined) {
childProps = {
...childProps,
onIonTabsDidChange
}
onIonTabsDidChange,
};
}
if (onIonTabsWillChange !== undefined) {
childProps = {
...childProps,
onIonTabsWillChange
}
onIonTabsWillChange,
};
}
if (child.type === IonTabBar || child.type.isTabBar) {
@ -149,11 +154,7 @@ export const IonTabs = /*@__PURE__*/ (() =>
return (
<IonTabsContext.Provider value={this.ionTabContextState}>
{this.context.hasIonicRouter() ? (
<PageManager
className={className ? `${className}` : ''}
routeInfo={this.context.routeInfo}
{...props}
>
<PageManager className={className ? `${className}` : ''} routeInfo={this.context.routeInfo} {...props}>
<ion-tabs className="ion-tabs" style={hostStyles}>
{tabBar.props.slot === 'top' ? tabBar : null}
<div style={tabsInner} className="tabs-inner">

View File

@ -8,32 +8,32 @@ import { IonItem as IonItemCmp } from '@ionic/core/components/ion-item.js';
import { IonRouterLink as IonRouterLinkCmp } from '@ionic/core/components/ion-router-link.js';
import { createRoutingComponent } from './createRoutingComponent';
import { HrefProps } from './hrefprops';
import type { HrefProps } from './hrefprops';
export const IonRouterLink = /*@__PURE__*/ createRoutingComponent<
HrefProps<JSX.IonRouterLink>,
HTMLIonRouterLinkElement
>('ion-router-link', IonRouterLinkCmp);
export const IonButton = /*@__PURE__*/ createRoutingComponent<
HrefProps<JSX.IonButton>,
HTMLIonButtonElement
>('ion-button', IonButtonCmp);
export const IonButton = /*@__PURE__*/ createRoutingComponent<HrefProps<JSX.IonButton>, HTMLIonButtonElement>(
'ion-button',
IonButtonCmp
);
export const IonCard = /*@__PURE__*/ createRoutingComponent<
HrefProps<JSX.IonCard>,
HTMLIonCardElement
>('ion-card', IonCardCmp);
export const IonCard = /*@__PURE__*/ createRoutingComponent<HrefProps<JSX.IonCard>, HTMLIonCardElement>(
'ion-card',
IonCardCmp
);
export const IonFabButton = /*@__PURE__*/ createRoutingComponent<
HrefProps<JSX.IonFabButton>,
HTMLIonFabButtonElement
>('ion-fab-button', IonFabButtonCmp);
export const IonFabButton = /*@__PURE__*/ createRoutingComponent<HrefProps<JSX.IonFabButton>, HTMLIonFabButtonElement>(
'ion-fab-button',
IonFabButtonCmp
);
export const IonItem = /*@__PURE__*/ createRoutingComponent<
HrefProps<JSX.IonItem>,
HTMLIonItemElement
>('ion-item', IonItemCmp);
export const IonItem = /*@__PURE__*/ createRoutingComponent<HrefProps<JSX.IonItem>, HTMLIonItemElement>(
'ion-item',
IonItemCmp
);
export const IonItemOption = /*@__PURE__*/ createRoutingComponent<
HrefProps<JSX.IonItemOption>,

View File

@ -1,25 +1,18 @@
import {
Config as CoreConfig,
Platforms,
getPlatforms as getPlatformsCore,
isPlatform as isPlatformCore,
} from '@ionic/core/components';
import type { Config as CoreConfig, Platforms } from '@ionic/core/components';
import { getPlatforms as getPlatformsCore, isPlatform as isPlatformCore } from '@ionic/core/components';
import React from 'react';
import { IonicReactProps } from '../IonicReactProps';
import type { IonicReactProps } from '../IonicReactProps';
export type IonicReactExternalProps<PropType, ElementType> = PropType &
Omit<React.HTMLAttributes<ElementType>, 'style'> &
IonicReactProps;
export const createForwardRef = <PropType, ElementType>(
ReactComponent: any,
ReactComponent: any, // TODO(FW-2959): type
displayName: string
) => {
const forwardRef = (
props: IonicReactExternalProps<PropType, ElementType>,
ref: React.ForwardedRef<ElementType>
) => {
const forwardRef = (props: IonicReactExternalProps<PropType, ElementType>, ref: React.ForwardedRef<ElementType>) => {
return <ReactComponent {...props} forwardedRef={ref} />;
};
forwardRef.displayName = displayName;

View File

@ -1,10 +1,7 @@
import { SerializeDocumentOptions, renderToString } from '@ionic/core/hydrate';
import type { SerializeDocumentOptions } from '@ionic/core/hydrate';
import { renderToString } from '@ionic/core/hydrate';
export async function ionRenderToString(
html: string,
userAgent: string,
options: SerializeDocumentOptions = {}
) {
export async function ionRenderToString(html: string, userAgent: string, options: SerializeDocumentOptions = {}) {
const renderToStringOptions = Object.assign(
{},
{