UNPKG

@ionic/react

Version:
1,003 lines (982 loc) • 112 kB
import { jsx, Fragment, jsxs } from 'react/jsx-runtime'; import React, { useContext, useRef, useEffect, createElement, useState, useMemo, Fragment as Fragment$1, useCallback } from 'react'; import { isPlatform as isPlatform$1, getPlatforms as getPlatforms$1, componentOnReady, createAnimation, actionSheetController, alertController, toastController, modalController, popoverController, pickerController, loadingController, initialize } from '@ionic/core/components'; export { IonicSafeString, IonicSlides, createAnimation, createGesture, getIonPageElement, getTimeGivenProgression, iosTransitionAnimation, mdTransitionAnimation, openURL } from '@ionic/core/components'; import ReactDOM, { createPortal } from 'react-dom'; import { defineCustomElement as defineCustomElement$1 } from '@ionic/core/components/ion-accordion.js'; import { defineCustomElement as defineCustomElement$2 } from '@ionic/core/components/ion-accordion-group.js'; import { defineCustomElement as defineCustomElement$3 } from '@ionic/core/components/ion-avatar.js'; import { defineCustomElement as defineCustomElement$4 } from '@ionic/core/components/ion-backdrop.js'; import { defineCustomElement as defineCustomElement$5 } from '@ionic/core/components/ion-badge.js'; import { defineCustomElement as defineCustomElement$6 } from '@ionic/core/components/ion-breadcrumbs.js'; import { defineCustomElement as defineCustomElement$7 } from '@ionic/core/components/ion-buttons.js'; import { defineCustomElement as defineCustomElement$8 } from '@ionic/core/components/ion-card-content.js'; import { defineCustomElement as defineCustomElement$9 } from '@ionic/core/components/ion-card-header.js'; import { defineCustomElement as defineCustomElement$a } from '@ionic/core/components/ion-card-subtitle.js'; import { defineCustomElement as defineCustomElement$b } from '@ionic/core/components/ion-card-title.js'; import { defineCustomElement as defineCustomElement$c } from '@ionic/core/components/ion-checkbox.js'; import { defineCustomElement as defineCustomElement$d } from '@ionic/core/components/ion-chip.js'; import { defineCustomElement as defineCustomElement$e } from '@ionic/core/components/ion-col.js'; import { defineCustomElement as defineCustomElement$f } from '@ionic/core/components/ion-content.js'; import { defineCustomElement as defineCustomElement$g } from '@ionic/core/components/ion-datetime.js'; import { defineCustomElement as defineCustomElement$h } from '@ionic/core/components/ion-datetime-button.js'; import { defineCustomElement as defineCustomElement$i } from '@ionic/core/components/ion-fab.js'; import { defineCustomElement as defineCustomElement$j } from '@ionic/core/components/ion-fab-list.js'; import { defineCustomElement as defineCustomElement$k } from '@ionic/core/components/ion-footer.js'; import { defineCustomElement as defineCustomElement$l } from '@ionic/core/components/ion-grid.js'; import { defineCustomElement as defineCustomElement$m } from '@ionic/core/components/ion-header.js'; import { defineCustomElement as defineCustomElement$n } from '@ionic/core/components/ion-img.js'; import { defineCustomElement as defineCustomElement$o } from '@ionic/core/components/ion-infinite-scroll.js'; import { defineCustomElement as defineCustomElement$p } from '@ionic/core/components/ion-infinite-scroll-content.js'; import { defineCustomElement as defineCustomElement$q } from '@ionic/core/components/ion-input.js'; import { defineCustomElement as defineCustomElement$r } from '@ionic/core/components/ion-input-otp.js'; import { defineCustomElement as defineCustomElement$s } from '@ionic/core/components/ion-input-password-toggle.js'; import { defineCustomElement as defineCustomElement$t } from '@ionic/core/components/ion-item-divider.js'; import { defineCustomElement as defineCustomElement$u } from '@ionic/core/components/ion-item-group.js'; import { defineCustomElement as defineCustomElement$v } from '@ionic/core/components/ion-item-options.js'; import { defineCustomElement as defineCustomElement$w } from '@ionic/core/components/ion-item-sliding.js'; import { defineCustomElement as defineCustomElement$x } from '@ionic/core/components/ion-label.js'; import { defineCustomElement as defineCustomElement$y } from '@ionic/core/components/ion-list.js'; import { defineCustomElement as defineCustomElement$z } from '@ionic/core/components/ion-list-header.js'; import { defineCustomElement as defineCustomElement$A } from '@ionic/core/components/ion-menu.js'; import { defineCustomElement as defineCustomElement$B } from '@ionic/core/components/ion-menu-button.js'; import { defineCustomElement as defineCustomElement$C } from '@ionic/core/components/ion-menu-toggle.js'; import { defineCustomElement as defineCustomElement$1m } from '@ionic/core/components/ion-nav.js'; import { defineCustomElement as defineCustomElement$D } from '@ionic/core/components/ion-nav-link.js'; import { defineCustomElement as defineCustomElement$E } from '@ionic/core/components/ion-note.js'; import { defineCustomElement as defineCustomElement$F } from '@ionic/core/components/ion-picker.js'; import { defineCustomElement as defineCustomElement$G } from '@ionic/core/components/ion-picker-column.js'; import { defineCustomElement as defineCustomElement$H } from '@ionic/core/components/ion-picker-column-option.js'; import { defineCustomElement as defineCustomElement$I } from '@ionic/core/components/ion-progress-bar.js'; import { defineCustomElement as defineCustomElement$J } from '@ionic/core/components/ion-radio.js'; import { defineCustomElement as defineCustomElement$K } from '@ionic/core/components/ion-radio-group.js'; import { defineCustomElement as defineCustomElement$L } from '@ionic/core/components/ion-range.js'; import { defineCustomElement as defineCustomElement$M } from '@ionic/core/components/ion-refresher.js'; import { defineCustomElement as defineCustomElement$N } from '@ionic/core/components/ion-refresher-content.js'; import { defineCustomElement as defineCustomElement$O } from '@ionic/core/components/ion-reorder.js'; import { defineCustomElement as defineCustomElement$P } from '@ionic/core/components/ion-reorder-group.js'; import { defineCustomElement as defineCustomElement$Q } from '@ionic/core/components/ion-ripple-effect.js'; import { defineCustomElement as defineCustomElement$R } from '@ionic/core/components/ion-row.js'; import { defineCustomElement as defineCustomElement$S } from '@ionic/core/components/ion-searchbar.js'; import { defineCustomElement as defineCustomElement$T } from '@ionic/core/components/ion-segment.js'; import { defineCustomElement as defineCustomElement$U } from '@ionic/core/components/ion-segment-button.js'; import { defineCustomElement as defineCustomElement$V } from '@ionic/core/components/ion-segment-content.js'; import { defineCustomElement as defineCustomElement$W } from '@ionic/core/components/ion-segment-view.js'; import { defineCustomElement as defineCustomElement$X } from '@ionic/core/components/ion-select.js'; import { defineCustomElement as defineCustomElement$Y } from '@ionic/core/components/ion-select-modal.js'; import { defineCustomElement as defineCustomElement$Z } from '@ionic/core/components/ion-select-option.js'; import { defineCustomElement as defineCustomElement$_ } from '@ionic/core/components/ion-skeleton-text.js'; import { defineCustomElement as defineCustomElement$$ } from '@ionic/core/components/ion-spinner.js'; import { defineCustomElement as defineCustomElement$10 } from '@ionic/core/components/ion-split-pane.js'; import { defineCustomElement as defineCustomElement$11 } from '@ionic/core/components/ion-tab.js'; import { defineCustomElement as defineCustomElement$12 } from '@ionic/core/components/ion-text.js'; import { defineCustomElement as defineCustomElement$13 } from '@ionic/core/components/ion-textarea.js'; import { defineCustomElement as defineCustomElement$14 } from '@ionic/core/components/ion-thumbnail.js'; import { defineCustomElement as defineCustomElement$15 } from '@ionic/core/components/ion-title.js'; import { defineCustomElement as defineCustomElement$16 } from '@ionic/core/components/ion-toggle.js'; import { defineCustomElement as defineCustomElement$17 } from '@ionic/core/components/ion-toolbar.js'; import { IonBreadcrumb as IonBreadcrumb$1 } from '@ionic/core/components/ion-breadcrumb.js'; import { IonButton as IonButton$1 } from '@ionic/core/components/ion-button.js'; import { IonCard as IonCard$1 } from '@ionic/core/components/ion-card.js'; import { IonFabButton as IonFabButton$1 } from '@ionic/core/components/ion-fab-button.js'; import { IonItemOption as IonItemOption$1 } from '@ionic/core/components/ion-item-option.js'; import { IonItem as IonItem$1 } from '@ionic/core/components/ion-item.js'; import { IonRouterLink as IonRouterLink$1 } from '@ionic/core/components/ion-router-link.js'; import { defineCustomElement as defineCustomElement$18 } from '@ionic/core/components/ion-alert.js'; import { defineCustomElement as defineCustomElement$19 } from '@ionic/core/components/ion-loading.js'; import { defineCustomElement as defineCustomElement$1a } from '@ionic/core/components/ion-toast.js'; import { defineCustomElement as defineCustomElement$1b } from '@ionic/core/components/ion-picker-legacy.js'; import { defineCustomElement as defineCustomElement$1c } from '@ionic/core/components/ion-action-sheet.js'; import { defineCustomElement as defineCustomElement$1d } from '@ionic/core/components/ion-modal.js'; import { defineCustomElement as defineCustomElement$1e } from '@ionic/core/components/ion-popover.js'; import { defineCustomElement as defineCustomElement$1k } from '@ionic/core/components/ion-app.js'; import { defineCustomElement as defineCustomElement$1i } from '@ionic/core/components/ion-back-button.js'; import { defineCustomElement as defineCustomElement$1j } from '@ionic/core/components/ion-router-outlet.js'; import { defineCustomElement as defineCustomElement$1g } from '@ionic/core/components/ion-tab-bar.js'; import { defineCustomElement as defineCustomElement$1f } from '@ionic/core/components/ion-tab-button.js'; import { defineCustomElement as defineCustomElement$1h } from '@ionic/core/components/ion-tabs.js'; import { defineCustomElement as defineCustomElement$1l } from 'ionicons/components/ion-icon.js'; const IonLifeCycleContext = /*@__PURE__*/ React.createContext({ onIonViewWillEnter: () => { return; }, ionViewWillEnter: () => { return; }, onIonViewDidEnter: () => { return; }, ionViewDidEnter: () => { return; }, onIonViewWillLeave: () => { return; }, ionViewWillLeave: () => { return; }, onIonViewDidLeave: () => { return; }, ionViewDidLeave: () => { return; }, cleanupIonViewWillEnter: () => { return; }, cleanupIonViewDidEnter: () => { return; }, cleanupIonViewWillLeave: () => { return; }, cleanupIonViewDidLeave: () => { return; }, }); const DefaultIonLifeCycleContext = class { constructor() { this.ionViewWillEnterCallbacks = []; this.ionViewDidEnterCallbacks = []; this.ionViewWillLeaveCallbacks = []; this.ionViewDidLeaveCallbacks = []; this.ionViewWillEnterDestructorCallbacks = []; this.ionViewDidEnterDestructorCallbacks = []; this.ionViewWillLeaveDestructorCallbacks = []; this.ionViewDidLeaveDestructorCallbacks = []; } onIonViewWillEnter(callback) { if (callback.id) { const index = this.ionViewWillEnterCallbacks.findIndex((x) => x.id === callback.id); if (index > -1) { this.ionViewWillEnterCallbacks[index] = callback; } else { this.ionViewWillEnterCallbacks.push(callback); } } else { this.ionViewWillEnterCallbacks.push(callback); } } teardownCallback(callback, callbacks) { // Find any destructors that have been registered for the callback const matches = callbacks.filter((x) => x.id === callback.id); if (matches.length !== 0) { // Execute the destructor for each matching item matches.forEach((match) => { if (match && typeof match.destructor === 'function') { match.destructor(); } }); // Remove all matching items from the array callbacks = callbacks.filter((x) => x.id !== callback.id); } } /** * Tears down the user-provided ionViewWillEnter lifecycle callback. * This is the same behavior as React's useEffect hook. The callback * is invoked when the component is unmounted. */ cleanupIonViewWillEnter(callback) { this.teardownCallback(callback, this.ionViewWillEnterDestructorCallbacks); } /** * Tears down the user-provided ionViewDidEnter lifecycle callback. * This is the same behavior as React's useEffect hook. The callback * is invoked when the component is unmounted. */ cleanupIonViewDidEnter(callback) { this.teardownCallback(callback, this.ionViewDidEnterDestructorCallbacks); } /** * Tears down the user-provided ionViewWillLeave lifecycle callback. * This is the same behavior as React's useEffect hook. The callback * is invoked when the component is unmounted. */ cleanupIonViewWillLeave(callback) { this.teardownCallback(callback, this.ionViewWillLeaveDestructorCallbacks); } /** * Tears down the user-provided ionViewDidLeave lifecycle callback. * This is the same behavior as React's useEffect hook. The callback * is invoked when the component is unmounted. */ cleanupIonViewDidLeave(callback) { this.teardownCallback(callback, this.ionViewDidLeaveDestructorCallbacks); } ionViewWillEnter() { this.ionViewWillEnterCallbacks.forEach((cb) => { const destructor = cb(); if (cb.id) { this.ionViewWillEnterDestructorCallbacks.push({ id: cb.id, destructor }); } }); } onIonViewDidEnter(callback) { if (callback.id) { const index = this.ionViewDidEnterCallbacks.findIndex((x) => x.id === callback.id); if (index > -1) { this.ionViewDidEnterCallbacks[index] = callback; } else { this.ionViewDidEnterCallbacks.push(callback); } } else { this.ionViewDidEnterCallbacks.push(callback); } } ionViewDidEnter() { this.ionViewDidEnterCallbacks.forEach((cb) => { const destructor = cb(); if (cb.id) { this.ionViewDidEnterDestructorCallbacks.push({ id: cb.id, destructor }); } }); } onIonViewWillLeave(callback) { if (callback.id) { const index = this.ionViewWillLeaveCallbacks.findIndex((x) => x.id === callback.id); if (index > -1) { this.ionViewWillLeaveCallbacks[index] = callback; } else { this.ionViewWillLeaveCallbacks.push(callback); } } else { this.ionViewWillLeaveCallbacks.push(callback); } } ionViewWillLeave() { this.ionViewWillLeaveCallbacks.forEach((cb) => { const destructor = cb(); if (cb.id) { this.ionViewWillLeaveDestructorCallbacks.push({ id: cb.id, destructor }); } }); } onIonViewDidLeave(callback) { if (callback.id) { const index = this.ionViewDidLeaveCallbacks.findIndex((x) => x.id === callback.id); if (index > -1) { this.ionViewDidLeaveCallbacks[index] = callback; } else { this.ionViewDidLeaveCallbacks.push(callback); } } else { this.ionViewDidLeaveCallbacks.push(callback); } } ionViewDidLeave() { this.ionViewDidLeaveCallbacks.forEach((cb) => { const destructor = cb(); if (cb.id) { this.ionViewDidLeaveDestructorCallbacks.push({ id: cb.id, destructor }); } }); this.componentCanBeDestroyed(); } onComponentCanBeDestroyed(callback) { this.componentCanBeDestroyedCallback = callback; } componentCanBeDestroyed() { if (this.componentCanBeDestroyedCallback) { this.componentCanBeDestroyedCallback(); } } }; // TODO(FW-2959): types const withIonLifeCycle = (WrappedComponent) => { return class IonLifeCycle extends React.Component { constructor(props) { super(props); this.componentRef = React.createRef(); } componentDidMount() { const element = this.componentRef.current; this.context.onIonViewWillEnter(() => { if (element && element.ionViewWillEnter) { element.ionViewWillEnter(); } }); this.context.onIonViewDidEnter(() => { if (element && element.ionViewDidEnter) { element.ionViewDidEnter(); } }); this.context.onIonViewWillLeave(() => { if (element && element.ionViewWillLeave) { element.ionViewWillLeave(); } }); this.context.onIonViewDidLeave(() => { if (element && element.ionViewDidLeave) { element.ionViewDidLeave(); } }); } render() { return (jsx(IonLifeCycleContext.Consumer, { children: (context) => { this.context = context; return jsx(WrappedComponent, { ref: this.componentRef, ...this.props }); } })); } }; }; const useIonViewWillEnter = (callback, deps = []) => { const context = useContext(IonLifeCycleContext); const id = useRef(); id.current = id.current || Math.floor(Math.random() * 1000000); useEffect(() => { callback.id = id.current; context.onIonViewWillEnter(callback); return () => { context.cleanupIonViewWillEnter(callback); }; }, deps); }; const useIonViewDidEnter = (callback, deps = []) => { const context = useContext(IonLifeCycleContext); const id = useRef(); id.current = id.current || Math.floor(Math.random() * 1000000); useEffect(() => { callback.id = id.current; context.onIonViewDidEnter(callback); return () => { context.cleanupIonViewDidEnter(callback); }; }, deps); }; const useIonViewWillLeave = (callback, deps = []) => { const context = useContext(IonLifeCycleContext); const id = useRef(); id.current = id.current || Math.floor(Math.random() * 1000000); useEffect(() => { callback.id = id.current; context.onIonViewWillLeave(callback); return () => { context.cleanupIonViewWillLeave(callback); }; }, deps); }; const useIonViewDidLeave = (callback, deps = []) => { const context = useContext(IonLifeCycleContext); const id = useRef(); id.current = id.current || Math.floor(Math.random() * 1000000); useEffect(() => { callback.id = id.current; context.onIonViewDidLeave(callback); return () => { context.cleanupIonViewDidLeave(callback); }; }, deps); }; const NavContext = /*@__PURE__*/ React.createContext({ getIonRedirect: () => undefined, getIonRoute: () => undefined, getPageManager: () => undefined, getStackManager: () => undefined, goBack: (route) => { if (typeof window !== 'undefined') { if (typeof route === 'string') { window.location.pathname = route; } else { window.history.back(); } } }, navigate: (path) => { if (typeof window !== 'undefined') { window.location.pathname = path; } }, hasIonicRouter: () => false, routeInfo: undefined, setCurrentTab: () => undefined, changeTab: (_tab, path) => { if (typeof window !== 'undefined') { window.location.pathname = path; } }, resetTab: (_tab, path) => { if (typeof window !== 'undefined') { window.location.pathname = path; } }, }); const dashToPascalCase = (str) => str .toLowerCase() .split('-') .map((segment) => segment.charAt(0).toUpperCase() + segment.slice(1)) .join(''); const camelToDashCase = (str) => str.replace(/([A-Z])/g, (m) => `-${m[0].toLowerCase()}`); const attachProps = (node, newProps, oldProps = {}) => { // some test frameworks don't render DOM elements, so we test here to make sure we are dealing with DOM first if (node instanceof Element) { // add any classes in className to the class list const className = getClassName(node.classList, newProps, oldProps); if (className !== '') { node.className = className; } Object.keys(newProps).forEach((name) => { if (name === 'children' || name === 'style' || name === 'ref' || name === 'class' || name === 'className' || name === 'forwardedRef') { return; } if (name.indexOf('on') === 0 && name[2] === name[2].toUpperCase()) { const eventName = name.substring(2); const eventNameLc = eventName[0].toLowerCase() + eventName.substring(1); if (!isCoveredByReact(eventNameLc)) { syncEvent(node, eventNameLc, newProps[name]); } } else { node[name] = newProps[name]; const propType = typeof newProps[name]; if (propType === 'string') { node.setAttribute(camelToDashCase(name), newProps[name]); } } }); } }; const getClassName = (classList, newProps, oldProps) => { const newClassProp = newProps.className || newProps.class; const oldClassProp = oldProps.className || oldProps.class; // map the classes to Maps for performance const currentClasses = arrayToMap(classList); const incomingPropClasses = arrayToMap(newClassProp ? newClassProp.split(' ') : []); const oldPropClasses = arrayToMap(oldClassProp ? oldClassProp.split(' ') : []); const finalClassNames = []; // loop through each of the current classes on the component // to see if it should be a part of the classNames added currentClasses.forEach((currentClass) => { if (incomingPropClasses.has(currentClass)) { // add it as its already included in classnames coming in from newProps finalClassNames.push(currentClass); incomingPropClasses.delete(currentClass); } else if (!oldPropClasses.has(currentClass)) { // add it as it has NOT been removed by user finalClassNames.push(currentClass); } }); incomingPropClasses.forEach((s) => finalClassNames.push(s)); return finalClassNames.join(' '); }; /** * Transforms a React event name to a browser event name. */ const transformReactEventName = (eventNameSuffix) => { switch (eventNameSuffix) { case 'doubleclick': return 'dblclick'; } return eventNameSuffix; }; /** * Checks if an event is supported in the current execution environment. * @license Modernizr 3.0.0pre (Custom Build) | MIT */ const isCoveredByReact = (eventNameSuffix) => { if (typeof document === 'undefined') { return true; } else { const eventName = 'on' + transformReactEventName(eventNameSuffix); let isSupported = eventName in document; if (!isSupported) { const element = document.createElement('div'); element.setAttribute(eventName, 'return;'); isSupported = typeof element[eventName] === 'function'; } return isSupported; } }; const syncEvent = (node, eventName, newEventHandler) => { const eventStore = node.__events || (node.__events = {}); const oldEventHandler = eventStore[eventName]; // Remove old listener so they don't double up. if (oldEventHandler) { node.removeEventListener(eventName, oldEventHandler); } // Bind new listener. node.addEventListener(eventName, (eventStore[eventName] = function handler(e) { if (newEventHandler) { newEventHandler.call(this, e); } })); }; const arrayToMap = (arr) => { const map = new Map(); arr.forEach((s) => map.set(s, s)); return map; }; const setRef = (ref, value) => { if (typeof ref === 'function') { ref(value); } else if (ref != null) { // Cast as a MutableRef so we can assign current ref.current = value; } }; const mergeRefs = (...refs) => { return (value) => { refs.forEach((ref) => { setRef(ref, value); }); }; }; const createForwardRef$1 = (ReactComponent, displayName) => { const forwardRef = (props, ref) => { return jsx(ReactComponent, { ...props, forwardedRef: ref }); }; forwardRef.displayName = displayName; return React.forwardRef(forwardRef); }; const defineCustomElement = (tagName, customElement) => { if (customElement !== undefined && typeof customElements !== 'undefined' && !customElements.get(tagName)) { customElements.define(tagName, customElement); } }; const createReactComponent = (tagName, ReactComponentContext, manipulatePropsFunction, defineCustomElement) => { if (defineCustomElement !== undefined) { defineCustomElement(); } const displayName = dashToPascalCase(tagName); const ReactComponent = class extends React.Component { constructor(props) { super(props); this.setComponentElRef = (element) => { this.componentEl = element; }; } componentDidMount() { this.componentDidUpdate(this.props); } componentDidUpdate(prevProps) { attachProps(this.componentEl, this.props, prevProps); } render() { const { children, forwardedRef, style, className, ref, ...cProps } = this.props; let propsToPass = Object.keys(cProps).reduce((acc, name) => { const value = cProps[name]; if (name.indexOf('on') === 0 && name[2] === name[2].toUpperCase()) { const eventName = name.substring(2).toLowerCase(); if (typeof document !== 'undefined' && isCoveredByReact(eventName)) { acc[name] = value; } } else { // we should only render strings, booleans, and numbers as attrs in html. // objects, functions, arrays etc get synced via properties on mount. const type = typeof value; if (type === 'string' || type === 'boolean' || type === 'number') { acc[camelToDashCase(name)] = value; } } return acc; }, {}); if (manipulatePropsFunction) { propsToPass = manipulatePropsFunction(this.props, propsToPass); } const newProps = { ...propsToPass, ref: mergeRefs(forwardedRef, this.setComponentElRef), style, }; /** * We use createElement here instead of * React.createElement to work around a * bug in Vite (https://github.com/vitejs/vite/issues/6104). * React.createElement causes all elements to be rendered * as <tagname> instead of the actual Web Component. */ return 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$1(ReactComponent, displayName); }; /* eslint-disable */ /* tslint:disable */ /* auto-generated react proxies */ const IonAccordion = /*@__PURE__*/ createReactComponent('ion-accordion', undefined, undefined, defineCustomElement$1); const IonAccordionGroup = /*@__PURE__*/ createReactComponent('ion-accordion-group', undefined, undefined, defineCustomElement$2); const IonAvatar = /*@__PURE__*/ createReactComponent('ion-avatar', undefined, undefined, defineCustomElement$3); const IonBackdrop = /*@__PURE__*/ createReactComponent('ion-backdrop', undefined, undefined, defineCustomElement$4); const IonBadge = /*@__PURE__*/ createReactComponent('ion-badge', undefined, undefined, defineCustomElement$5); const IonBreadcrumbs = /*@__PURE__*/ createReactComponent('ion-breadcrumbs', undefined, undefined, defineCustomElement$6); const IonButtons = /*@__PURE__*/ createReactComponent('ion-buttons', undefined, undefined, defineCustomElement$7); const IonCardContent = /*@__PURE__*/ createReactComponent('ion-card-content', undefined, undefined, defineCustomElement$8); const IonCardHeader = /*@__PURE__*/ createReactComponent('ion-card-header', undefined, undefined, defineCustomElement$9); const IonCardSubtitle = /*@__PURE__*/ createReactComponent('ion-card-subtitle', undefined, undefined, defineCustomElement$a); const IonCardTitle = /*@__PURE__*/ createReactComponent('ion-card-title', undefined, undefined, defineCustomElement$b); const IonCheckbox = /*@__PURE__*/ createReactComponent('ion-checkbox', undefined, undefined, defineCustomElement$c); const IonChip = /*@__PURE__*/ createReactComponent('ion-chip', undefined, undefined, defineCustomElement$d); const IonCol = /*@__PURE__*/ createReactComponent('ion-col', undefined, undefined, defineCustomElement$e); const IonContent = /*@__PURE__*/ createReactComponent('ion-content', undefined, undefined, defineCustomElement$f); const IonDatetime = /*@__PURE__*/ createReactComponent('ion-datetime', undefined, undefined, defineCustomElement$g); const IonDatetimeButton = /*@__PURE__*/ createReactComponent('ion-datetime-button', undefined, undefined, defineCustomElement$h); const IonFab = /*@__PURE__*/ createReactComponent('ion-fab', undefined, undefined, defineCustomElement$i); const IonFabList = /*@__PURE__*/ createReactComponent('ion-fab-list', undefined, undefined, defineCustomElement$j); const IonFooter = /*@__PURE__*/ createReactComponent('ion-footer', undefined, undefined, defineCustomElement$k); const IonGrid = /*@__PURE__*/ createReactComponent('ion-grid', undefined, undefined, defineCustomElement$l); const IonHeader = /*@__PURE__*/ createReactComponent('ion-header', undefined, undefined, defineCustomElement$m); const IonImg = /*@__PURE__*/ createReactComponent('ion-img', undefined, undefined, defineCustomElement$n); const IonInfiniteScroll = /*@__PURE__*/ createReactComponent('ion-infinite-scroll', undefined, undefined, defineCustomElement$o); const IonInfiniteScrollContent = /*@__PURE__*/ createReactComponent('ion-infinite-scroll-content', undefined, undefined, defineCustomElement$p); const IonInput = /*@__PURE__*/ createReactComponent('ion-input', undefined, undefined, defineCustomElement$q); const IonInputOtp = /*@__PURE__*/ createReactComponent('ion-input-otp', undefined, undefined, defineCustomElement$r); const IonInputPasswordToggle = /*@__PURE__*/ createReactComponent('ion-input-password-toggle', undefined, undefined, defineCustomElement$s); const IonItemDivider = /*@__PURE__*/ createReactComponent('ion-item-divider', undefined, undefined, defineCustomElement$t); const IonItemGroup = /*@__PURE__*/ createReactComponent('ion-item-group', undefined, undefined, defineCustomElement$u); const IonItemOptions = /*@__PURE__*/ createReactComponent('ion-item-options', undefined, undefined, defineCustomElement$v); const IonItemSliding = /*@__PURE__*/ createReactComponent('ion-item-sliding', undefined, undefined, defineCustomElement$w); const IonLabel = /*@__PURE__*/ createReactComponent('ion-label', undefined, undefined, defineCustomElement$x); const IonList = /*@__PURE__*/ createReactComponent('ion-list', undefined, undefined, defineCustomElement$y); const IonListHeader = /*@__PURE__*/ createReactComponent('ion-list-header', undefined, undefined, defineCustomElement$z); const IonMenu = /*@__PURE__*/ createReactComponent('ion-menu', undefined, undefined, defineCustomElement$A); const IonMenuButton = /*@__PURE__*/ createReactComponent('ion-menu-button', undefined, undefined, defineCustomElement$B); const IonMenuToggle = /*@__PURE__*/ createReactComponent('ion-menu-toggle', undefined, undefined, defineCustomElement$C); const IonNavLink = /*@__PURE__*/ createReactComponent('ion-nav-link', undefined, undefined, defineCustomElement$D); const IonNote = /*@__PURE__*/ createReactComponent('ion-note', undefined, undefined, defineCustomElement$E); const IonPicker = /*@__PURE__*/ createReactComponent('ion-picker', undefined, undefined, defineCustomElement$F); const IonPickerColumn = /*@__PURE__*/ createReactComponent('ion-picker-column', undefined, undefined, defineCustomElement$G); const IonPickerColumnOption = /*@__PURE__*/ createReactComponent('ion-picker-column-option', undefined, undefined, defineCustomElement$H); const IonProgressBar = /*@__PURE__*/ createReactComponent('ion-progress-bar', undefined, undefined, defineCustomElement$I); const IonRadio = /*@__PURE__*/ createReactComponent('ion-radio', undefined, undefined, defineCustomElement$J); const IonRadioGroup = /*@__PURE__*/ createReactComponent('ion-radio-group', undefined, undefined, defineCustomElement$K); const IonRange = /*@__PURE__*/ createReactComponent('ion-range', undefined, undefined, defineCustomElement$L); const IonRefresher = /*@__PURE__*/ createReactComponent('ion-refresher', undefined, undefined, defineCustomElement$M); const IonRefresherContent = /*@__PURE__*/ createReactComponent('ion-refresher-content', undefined, undefined, defineCustomElement$N); const IonReorder = /*@__PURE__*/ createReactComponent('ion-reorder', undefined, undefined, defineCustomElement$O); const IonReorderGroup = /*@__PURE__*/ createReactComponent('ion-reorder-group', undefined, undefined, defineCustomElement$P); const IonRippleEffect = /*@__PURE__*/ createReactComponent('ion-ripple-effect', undefined, undefined, defineCustomElement$Q); const IonRow = /*@__PURE__*/ createReactComponent('ion-row', undefined, undefined, defineCustomElement$R); const IonSearchbar = /*@__PURE__*/ createReactComponent('ion-searchbar', undefined, undefined, defineCustomElement$S); const IonSegment = /*@__PURE__*/ createReactComponent('ion-segment', undefined, undefined, defineCustomElement$T); const IonSegmentButton = /*@__PURE__*/ createReactComponent('ion-segment-button', undefined, undefined, defineCustomElement$U); const IonSegmentContent = /*@__PURE__*/ createReactComponent('ion-segment-content', undefined, undefined, defineCustomElement$V); const IonSegmentView = /*@__PURE__*/ createReactComponent('ion-segment-view', undefined, undefined, defineCustomElement$W); const IonSelect = /*@__PURE__*/ createReactComponent('ion-select', undefined, undefined, defineCustomElement$X); const IonSelectModal = /*@__PURE__*/ createReactComponent('ion-select-modal', undefined, undefined, defineCustomElement$Y); const IonSelectOption = /*@__PURE__*/ createReactComponent('ion-select-option', undefined, undefined, defineCustomElement$Z); const IonSkeletonText = /*@__PURE__*/ createReactComponent('ion-skeleton-text', undefined, undefined, defineCustomElement$_); const IonSpinner = /*@__PURE__*/ createReactComponent('ion-spinner', undefined, undefined, defineCustomElement$$); const IonSplitPane = /*@__PURE__*/ createReactComponent('ion-split-pane', undefined, undefined, defineCustomElement$10); const IonTab = /*@__PURE__*/ createReactComponent('ion-tab', undefined, undefined, defineCustomElement$11); const IonText = /*@__PURE__*/ createReactComponent('ion-text', undefined, undefined, defineCustomElement$12); const IonTextarea = /*@__PURE__*/ createReactComponent('ion-textarea', undefined, undefined, defineCustomElement$13); const IonThumbnail = /*@__PURE__*/ createReactComponent('ion-thumbnail', undefined, undefined, defineCustomElement$14); const IonTitle = /*@__PURE__*/ createReactComponent('ion-title', undefined, undefined, defineCustomElement$15); const IonToggle = /*@__PURE__*/ createReactComponent('ion-toggle', undefined, undefined, defineCustomElement$16); const IonToolbar = /*@__PURE__*/ createReactComponent('ion-toolbar', undefined, undefined, defineCustomElement$17); const createForwardRef = (ReactComponent, // TODO(FW-2959): type displayName) => { const forwardRef = (props, ref) => { return jsx(ReactComponent, { ...props, forwardedRef: ref }); }; forwardRef.displayName = displayName; return React.forwardRef(forwardRef); }; const isPlatform = (platform) => { return isPlatform$1(window, platform); }; const getPlatforms = () => { return getPlatforms$1(window); }; const getConfig = () => { if (typeof window !== 'undefined') { const Ionic = window.Ionic; if (Ionic && Ionic.config) { return Ionic.config; } } return null; }; const createRoutingComponent = (tagName, customElement) => { defineCustomElement(tagName, customElement); const displayName = dashToPascalCase(tagName); const ReactComponent = class extends React.Component { constructor(props) { super(props); this.handleClick = (e) => { const { routerLink, routerDirection, routerOptions, routerAnimation } = this.props; if (routerLink !== undefined) { e.preventDefault(); this.context.navigate(routerLink, routerDirection, undefined, routerAnimation, routerOptions); } }; // 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); } componentDidMount() { this.componentDidUpdate(this.props); } componentDidUpdate(prevProps) { const node = this.ref.current; attachProps(node, this.props, prevProps); } 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) => { if (name.indexOf('on') === 0 && name[2] === name[2].toUpperCase()) { const eventName = name.substring(2).toLowerCase(); if (isCoveredByReact(eventName)) { acc[name] = cProps[name]; } } else if (['string', 'boolean', 'number'].includes(typeof cProps[name])) { acc[camelToDashCase(name)] = cProps[name]; } return acc; }, {}); const newProps = { ...propsToPass, ref: this.stableMergedRefs, style, }; if (this.props.routerLink && !this.props.href) { newProps.href = this.props.routerLink; } if (newProps.onClick) { const oldClick = newProps.onClick; newProps.onClick = (e) => { oldClick(e); if (!e.defaultPrevented) { this.handleClick(e); } }; } else { newProps.onClick = this.handleClick; } return createElement(tagName, newProps, children); } static get displayName() { return displayName; } static get contextType() { return NavContext; } }; return createForwardRef(ReactComponent, displayName); }; const IonRouterLink = /*@__PURE__*/ createRoutingComponent('ion-router-link', IonRouterLink$1); const IonButton = /*@__PURE__*/ createRoutingComponent('ion-button', IonButton$1); const IonCard = /*@__PURE__*/ createRoutingComponent('ion-card', IonCard$1); const IonFabButton = /*@__PURE__*/ createRoutingComponent('ion-fab-button', IonFabButton$1); const IonItem = /*@__PURE__*/ createRoutingComponent('ion-item', IonItem$1); const IonItemOption = /*@__PURE__*/ createRoutingComponent('ion-item-option', IonItemOption$1); const IonBreadcrumb = /*@__PURE__*/ createRoutingComponent('ion-breadcrumb', IonBreadcrumb$1); /** * The @stencil/react-output-target will bind event listeners for any * attached props that use the `on` prefix. This function will remove * those event listeners when the component is unmounted. * * This prevents memory leaks and React state updates on unmounted components. */ const detachProps = (node, props) => { if (node instanceof Element) { Object.keys(props).forEach((name) => { if (name.indexOf('on') === 0 && name[2] === name[2].toUpperCase()) { const eventName = name.substring(2); const eventNameLc = eventName[0].toLowerCase() + eventName.substring(1); if (!isCoveredByReact(eventNameLc)) { /** * Detach custom event bindings (not built-in React events) * that were added by the @stencil/react-output-target attachProps function. */ detachEvent(node, eventNameLc); } } }); } }; const detachEvent = (node, eventName) => { const eventStore = node.__events || (node.__events = {}); /** * If the event listener was added by attachProps, it will * be stored in the __events object. */ const eventHandler = eventStore[eventName]; if (eventHandler) { node.removeEventListener(eventName, eventHandler); eventStore[eventName] = undefined; } }; const createInlineOverlayComponent = (tagName, defineCustomElement, hasDelegateHost) => { if (defineCustomElement) { defineCustomElement(); } const displayName = dashToPascalCase(tagName); const ReactComponent = class extends React.Component { constructor(props) { super(props); this.handleIonMount = () => { /** * Mount the inner component when the * overlay is about to open. * * For ion-popover, this is when `ionMount` is emitted. * For other overlays, this is when `willPresent` is emitted. */ this.setState({ isOpen: true }); }; this.handleWillPresent = (evt) => { this.setState({ isOpen: true }); /** * Manually call the onWillPresent * handler if present as setState will * cause the event handlers to be * destroyed and re-created. */ this.props.onWillPresent && this.props.onWillPresent(evt); }; this.handleDidDismiss = (evt) => { const wrapper = this.wrapperRef.current; const el = this.ref.current; /** * This component might be unmounted already, if the containing * element was removed while the overlay was still open. (For * example, if an item contains an inline overlay with a button * that removes the item.) */ if (wrapper && el) { el.append(wrapper); this.setState({ isOpen: false }); } this.props.onDidDismiss && this.props.onDidDismiss(evt); }; // 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); // Component is hidden by default this.state = { isOpen: false }; // Create a local ref to the inner child element. this.wrapperRef = React.createRef(); } componentDidMount() { this.componentDidUpdate(this.props); this.ref.current?.addEventListener('ionMount', this.handleIonMount); this.ref.current?.addEventListener('willPresent', this.handleWillPresent); this.ref.current?.addEventListener('didDismiss', this.handleDidDismiss); } componentDidUpdate(prevProps) { const node = this.ref.current; /** * onDidDismiss and onWillPresent have manual implementations that * will invoke the original handler. We need to filter those out * so they don't get attached twice and called twice. */ // eslint-disable-next-line @typescript-eslint/no-unused-vars const { onDidDismiss, onWillPresent, ...cProps } = this.props; attachProps(node, cProps, prevProps); } componentWillUnmount() { const node = this.ref.current; /** * If the overlay is being unmounted, but is still * open, this means the unmount was triggered outside * of the overlay being dismissed. * * This can happen with: * - The parent component being unmounted * - The overlay being conditionally rendered * - A route change (push/pop/replace) * * Unmounting the overlay at this stage should skip * the dismiss lifecycle, including skipping the transition. * */ if (node && this.state.isOpen) { /** * Detach the local event listener that performs the state updates, * before dismissing the overlay, to prevent the callback handlers * executing after the component has been unmounted. This is to * avoid memory leaks. */ node.removeEventListener('didDismiss', this.handleDidDismiss); node.remove(); detachProps(node, this.props); } } 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) => { if (name.indexOf('on') === 0 && name[2] === name[2].toUpperCase()) { const eventName = name.substring(2).toLowerCase(); if (isCoveredByReact(eventName)) { acc[name] = cProps[name]; } } else if (['string', 'boolean', 'number'].includes(typeof cProps[name])) { acc[camelToDashCase(name)] = cProps[name]; } return acc; }, {}); const newProps = { ...propsToPass, ref: this.stableMergedRefs, style, }; /** * Some overlays need `.ion-page` so content * takes up the full size of the parent overlay. */ const getWrapperClasses = () => { if (hasDelegateHost) { return `${DELEGATE_HOST} ion-page`; } return DELEGATE_HOST; }; return createElement('template', {}, createElement(tagName, newProps, /** * We only want the inner component * to be mounted if the overlay is open, * so conditionally render the component * based on the isOpen state. */ this.state.isOpen || this.props.keepContentsMounted ? createElement('div', { ref: this.wrapperRef, className: getWrapperClasses(), }, children) : null)); } static get displayName() { return displayName; } }; return createForwardRef(ReactComponent, displayName); }; const DELEGATE_HOST = 'ion-delegate-host'; const IonAlert = /*@__PURE__*/ createInlineOverlayComponent('ion-alert', defineCustomElement$18); const IonLoading = /*@__PURE__*/ createInlineOverlayComponent('ion-loading', defineCustomElement$19); const IonToast = /*@__PURE__*/ createInlineOverlayComponent('ion-toast', defineCustomElement$1a); const IonPickerLegacy = /*@__PURE__*/ createInlineOverlayComponent('ion-picker-legacy', defineCustomElement$1b); const IonActionSheet = /*@__PURE__*/ createInlineOverlayComponent('ion-action-sheet', defineCustomElement$1c); const IonModal = /*@__PURE__*/ createInlineOverlayComponent('ion-modal', defineCustomElement$1d, true); const IonPopover