UNPKG

45.5 kBJavaScriptView Raw
1import React, { useContext, useRef, useEffect, Fragment } from 'react';
2import { defineCustomElements } from '@ionic/core/loader';
3import { addIcons } from 'ionicons';
4import { arrowBackSharp, caretBackSharp, chevronBack, chevronForward, close, closeCircle, closeSharp, menuOutline, menuSharp, reorderTwoSharp, reorderThreeOutline, searchOutline, searchSharp } from 'ionicons/icons';
5import { isPlatform as isPlatform$1, getPlatforms as getPlatforms$1, alertController, loadingController, toastController as toastController$1, pickerController, actionSheetController as actionSheetController$1, modalController, popoverController, createAnimation } from '@ionic/core';
6export { IonicSafeString, createAnimation, createGesture, iosTransitionAnimation, mdTransitionAnimation, setupConfig } from '@ionic/core';
7import { __rest } from 'tslib';
8import ReactDom from 'react-dom';
9
10const IonLifeCycleContext = /*@__PURE__*/ React.createContext({
11 onIonViewWillEnter: () => { return; },
12 ionViewWillEnter: () => { return; },
13 onIonViewDidEnter: () => { return; },
14 ionViewDidEnter: () => { return; },
15 onIonViewWillLeave: () => { return; },
16 ionViewWillLeave: () => { return; },
17 onIonViewDidLeave: () => { return; },
18 ionViewDidLeave: () => { return; },
19});
20const DefaultIonLifeCycleContext = class {
21 constructor() {
22 this.ionViewWillEnterCallbacks = [];
23 this.ionViewDidEnterCallbacks = [];
24 this.ionViewWillLeaveCallbacks = [];
25 this.ionViewDidLeaveCallbacks = [];
26 }
27 onIonViewWillEnter(callback) {
28 if (callback.id) {
29 const index = this.ionViewWillEnterCallbacks.findIndex(x => x.id === callback.id);
30 if (index > -1) {
31 this.ionViewWillEnterCallbacks[index] = callback;
32 }
33 else {
34 this.ionViewWillEnterCallbacks.push(callback);
35 }
36 }
37 else {
38 this.ionViewWillEnterCallbacks.push(callback);
39 }
40 }
41 ionViewWillEnter() {
42 this.ionViewWillEnterCallbacks.forEach(cb => cb());
43 }
44 onIonViewDidEnter(callback) {
45 if (callback.id) {
46 const index = this.ionViewDidEnterCallbacks.findIndex(x => x.id === callback.id);
47 if (index > -1) {
48 this.ionViewDidEnterCallbacks[index] = callback;
49 }
50 else {
51 this.ionViewDidEnterCallbacks.push(callback);
52 }
53 }
54 else {
55 this.ionViewDidEnterCallbacks.push(callback);
56 }
57 }
58 ionViewDidEnter() {
59 this.ionViewDidEnterCallbacks.forEach(cb => cb());
60 }
61 onIonViewWillLeave(callback) {
62 if (callback.id) {
63 const index = this.ionViewWillLeaveCallbacks.findIndex(x => x.id === callback.id);
64 if (index > -1) {
65 this.ionViewWillLeaveCallbacks[index] = callback;
66 }
67 else {
68 this.ionViewWillLeaveCallbacks.push(callback);
69 }
70 }
71 else {
72 this.ionViewWillLeaveCallbacks.push(callback);
73 }
74 }
75 ionViewWillLeave() {
76 this.ionViewWillLeaveCallbacks.forEach(cb => cb());
77 }
78 onIonViewDidLeave(callback) {
79 if (callback.id) {
80 const index = this.ionViewDidLeaveCallbacks.findIndex(x => x.id === callback.id);
81 if (index > -1) {
82 this.ionViewDidLeaveCallbacks[index] = callback;
83 }
84 else {
85 this.ionViewDidLeaveCallbacks.push(callback);
86 }
87 }
88 else {
89 this.ionViewDidLeaveCallbacks.push(callback);
90 }
91 }
92 ionViewDidLeave() {
93 this.ionViewDidLeaveCallbacks.forEach(cb => cb());
94 this.componentCanBeDestroyed();
95 }
96 onComponentCanBeDestroyed(callback) {
97 this.componentCanBeDestroyedCallback = callback;
98 }
99 componentCanBeDestroyed() {
100 if (this.componentCanBeDestroyedCallback) {
101 this.componentCanBeDestroyedCallback();
102 }
103 }
104};
105
106const withIonLifeCycle = (WrappedComponent) => {
107 return class IonLifeCycle extends React.Component {
108 constructor(props) {
109 super(props);
110 this.componentRef = React.createRef();
111 }
112 componentDidMount() {
113 const element = this.componentRef.current;
114 this.context.onIonViewWillEnter(() => {
115 if (element && element.ionViewWillEnter) {
116 element.ionViewWillEnter();
117 }
118 });
119 this.context.onIonViewDidEnter(() => {
120 if (element && element.ionViewDidEnter) {
121 element.ionViewDidEnter();
122 }
123 });
124 this.context.onIonViewWillLeave(() => {
125 if (element && element.ionViewWillLeave) {
126 element.ionViewWillLeave();
127 }
128 });
129 this.context.onIonViewDidLeave(() => {
130 if (element && element.ionViewDidLeave) {
131 element.ionViewDidLeave();
132 }
133 });
134 }
135 render() {
136 return (React.createElement(IonLifeCycleContext.Consumer, null, context => {
137 this.context = context;
138 return (React.createElement(WrappedComponent, Object.assign({ ref: this.componentRef }, this.props)));
139 }));
140 }
141 };
142};
143
144const useIonViewWillEnter = (callback, deps = []) => {
145 const context = useContext(IonLifeCycleContext);
146 const id = useRef();
147 id.current = id.current || Math.floor(Math.random() * 1000000);
148 useEffect(() => {
149 callback.id = id.current;
150 context.onIonViewWillEnter(callback);
151 }, deps);
152};
153const useIonViewDidEnter = (callback, deps = []) => {
154 const context = useContext(IonLifeCycleContext);
155 const id = useRef();
156 id.current = id.current || Math.floor(Math.random() * 1000000);
157 useEffect(() => {
158 callback.id = id.current;
159 context.onIonViewDidEnter(callback);
160 }, deps);
161};
162const useIonViewWillLeave = (callback, deps = []) => {
163 const context = useContext(IonLifeCycleContext);
164 const id = useRef();
165 id.current = id.current || Math.floor(Math.random() * 1000000);
166 useEffect(() => {
167 callback.id = id.current;
168 context.onIonViewWillLeave(callback);
169 }, deps);
170};
171const useIonViewDidLeave = (callback, deps = []) => {
172 const context = useContext(IonLifeCycleContext);
173 const id = useRef();
174 id.current = id.current || Math.floor(Math.random() * 1000000);
175 useEffect(() => {
176 callback.id = id.current;
177 context.onIonViewDidLeave(callback);
178 }, deps);
179};
180
181const NavContext = /*@__PURE__*/ React.createContext({
182 getPageManager: () => undefined,
183 getStackManager: () => undefined,
184 goBack: (defaultHref) => {
185 if (defaultHref !== undefined) {
186 window.location.pathname = defaultHref;
187 }
188 else {
189 window.history.back();
190 }
191 },
192 navigate: (path) => { window.location.pathname = path; },
193 hasIonicRouter: () => false,
194 registerIonPage: () => undefined,
195 currentPath: undefined
196});
197
198const dashToPascalCase = (str) => str.toLowerCase().split('-').map(segment => segment.charAt(0).toUpperCase() + segment.slice(1)).join('');
199const camelToDashCase = (str) => str.replace(/([A-Z])/g, (m) => `-${m[0].toLowerCase()}`);
200
201const attachProps = (node, newProps, oldProps = {}) => {
202 // some test frameworks don't render DOM elements, so we test here to make sure we are dealing with DOM first
203 if (node instanceof Element) {
204 // add any classes in className to the class list
205 const className = getClassName(node.classList, newProps, oldProps);
206 if (className !== '') {
207 node.className = className;
208 }
209 Object.keys(newProps).forEach(name => {
210 if (name === 'children' || name === 'style' || name === 'ref' || name === 'class' || name === 'className' || name === 'forwardedRef') {
211 return;
212 }
213 if (name.indexOf('on') === 0 && name[2] === name[2].toUpperCase()) {
214 const eventName = name.substring(2);
215 const eventNameLc = eventName[0].toLowerCase() + eventName.substring(1);
216 if (!isCoveredByReact(eventNameLc)) {
217 syncEvent(node, eventNameLc, newProps[name]);
218 }
219 }
220 else {
221 node[name] = newProps[name];
222 const propType = typeof newProps[name];
223 if (propType === 'string') {
224 node.setAttribute(camelToDashCase(name), newProps[name]);
225 }
226 else {
227 node[name] = newProps[name];
228 }
229 }
230 });
231 }
232};
233const getClassName = (classList, newProps, oldProps) => {
234 const newClassProp = newProps.className || newProps.class;
235 const oldClassProp = oldProps.className || oldProps.class;
236 // map the classes to Maps for performance
237 const currentClasses = arrayToMap(classList);
238 const incomingPropClasses = arrayToMap(newClassProp ? newClassProp.split(' ') : []);
239 const oldPropClasses = arrayToMap(oldClassProp ? oldClassProp.split(' ') : []);
240 const finalClassNames = [];
241 // loop through each of the current classes on the component
242 // to see if it should be a part of the classNames added
243 currentClasses.forEach(currentClass => {
244 if (incomingPropClasses.has(currentClass)) {
245 // add it as its already included in classnames coming in from newProps
246 finalClassNames.push(currentClass);
247 incomingPropClasses.delete(currentClass);
248 }
249 else if (!oldPropClasses.has(currentClass)) {
250 // add it as it has NOT been removed by user
251 finalClassNames.push(currentClass);
252 }
253 });
254 incomingPropClasses.forEach(s => finalClassNames.push(s));
255 return finalClassNames.join(' ');
256};
257/**
258 * Checks if an event is supported in the current execution environment.
259 * @license Modernizr 3.0.0pre (Custom Build) | MIT
260 */
261const isCoveredByReact = (eventNameSuffix, doc = document) => {
262 const eventName = 'on' + eventNameSuffix;
263 let isSupported = eventName in doc;
264 if (!isSupported) {
265 const element = doc.createElement('div');
266 element.setAttribute(eventName, 'return;');
267 isSupported = typeof element[eventName] === 'function';
268 }
269 return isSupported;
270};
271const syncEvent = (node, eventName, newEventHandler) => {
272 const eventStore = node.__events || (node.__events = {});
273 const oldEventHandler = eventStore[eventName];
274 // Remove old listener so they don't double up.
275 if (oldEventHandler) {
276 node.removeEventListener(eventName, oldEventHandler);
277 }
278 // Bind new listener.
279 node.addEventListener(eventName, eventStore[eventName] = function handler(e) {
280 if (newEventHandler) {
281 newEventHandler.call(this, e);
282 }
283 });
284};
285const arrayToMap = (arr) => {
286 const map = new Map();
287 arr.forEach((s) => map.set(s, s));
288 return map;
289};
290
291const createForwardRef = (ReactComponent, displayName) => {
292 const forwardRef = (props, ref) => {
293 return React.createElement(ReactComponent, Object.assign({}, props, { forwardedRef: ref }));
294 };
295 forwardRef.displayName = displayName;
296 return React.forwardRef(forwardRef);
297};
298const isPlatform = (platform) => {
299 return isPlatform$1(window, platform);
300};
301const getPlatforms = () => {
302 return getPlatforms$1(window);
303};
304const getConfig = () => {
305 if (typeof window !== 'undefined') {
306 const Ionic = window.Ionic;
307 if (Ionic && Ionic.config) {
308 return Ionic.config;
309 }
310 }
311 return null;
312};
313
314const createReactComponent = (tagName, routerLinkComponent = false) => {
315 const displayName = dashToPascalCase(tagName);
316 const ReactComponent = class extends React.Component {
317 constructor(props) {
318 super(props);
319 this.handleClick = (e) => {
320 const { routerLink, routerDirection } = this.props;
321 if (routerLink !== undefined) {
322 e.preventDefault();
323 this.context.navigate(routerLink, routerDirection);
324 }
325 };
326 }
327 componentDidMount() {
328 this.componentDidUpdate(this.props);
329 }
330 componentDidUpdate(prevProps) {
331 const node = ReactDom.findDOMNode(this);
332 attachProps(node, this.props, prevProps);
333 }
334 render() {
335 const _a = this.props, { children, forwardedRef, style, className, ref } = _a, cProps = __rest(_a, ["children", "forwardedRef", "style", "className", "ref"]);
336 const propsToPass = Object.keys(cProps).reduce((acc, name) => {
337 if (name.indexOf('on') === 0 && name[2] === name[2].toUpperCase()) {
338 const eventName = name.substring(2).toLowerCase();
339 if (isCoveredByReact(eventName)) {
340 acc[name] = cProps[name];
341 }
342 }
343 return acc;
344 }, {});
345 const newProps = Object.assign(Object.assign({}, propsToPass), { ref: forwardedRef, style });
346 if (routerLinkComponent) {
347 if (this.props.routerLink && !this.props.href) {
348 newProps.href = this.props.routerLink;
349 }
350 if (newProps.onClick) {
351 const oldClick = newProps.onClick;
352 newProps.onClick = (e) => {
353 oldClick(e);
354 if (!e.defaultPrevented) {
355 this.handleClick(e);
356 }
357 };
358 }
359 else {
360 newProps.onClick = this.handleClick;
361 }
362 }
363 return React.createElement(tagName, newProps, children);
364 }
365 static get displayName() {
366 return displayName;
367 }
368 static get contextType() {
369 return NavContext;
370 }
371 };
372 return createForwardRef(ReactComponent, displayName);
373};
374
375// ionic/core
376const IonApp = /*@__PURE__*/ createReactComponent('ion-app');
377const IonTab = /*@__PURE__*/ createReactComponent('ion-tab');
378const IonTabButton = /*@__PURE__*/ createReactComponent('ion-tab-button');
379const IonRouterLink = /*@__PURE__*/ createReactComponent('ion-router-link', true);
380const IonAvatar = /*@__PURE__*/ createReactComponent('ion-avatar');
381const IonBackdrop = /*@__PURE__*/ createReactComponent('ion-backdrop');
382const IonBadge = /*@__PURE__*/ createReactComponent('ion-badge');
383const IonButton = /*@__PURE__*/ createReactComponent('ion-button', true);
384const IonButtons = /*@__PURE__*/ createReactComponent('ion-buttons');
385const IonCard = /*@__PURE__*/ createReactComponent('ion-card', true);
386const IonCardContent = /*@__PURE__*/ createReactComponent('ion-card-content');
387const IonCardHeader = /*@__PURE__*/ createReactComponent('ion-card-header');
388const IonCardSubtitle = /*@__PURE__*/ createReactComponent('ion-card-subtitle');
389const IonCardTitle = /*@__PURE__*/ createReactComponent('ion-card-title');
390const IonCheckbox = /*@__PURE__*/ createReactComponent('ion-checkbox');
391const IonCol = /*@__PURE__*/ createReactComponent('ion-col');
392const IonContent = /*@__PURE__*/ createReactComponent('ion-content');
393const IonChip = /*@__PURE__*/ createReactComponent('ion-chip');
394const IonDatetime = /*@__PURE__*/ createReactComponent('ion-datetime');
395const IonFab = /*@__PURE__*/ createReactComponent('ion-fab');
396const IonFabButton = /*@__PURE__*/ createReactComponent('ion-fab-button', true);
397const IonFabList = /*@__PURE__*/ createReactComponent('ion-fab-list');
398const IonFooter = /*@__PURE__*/ createReactComponent('ion-footer');
399const IonGrid = /*@__PURE__*/ createReactComponent('ion-grid');
400const IonHeader = /*@__PURE__*/ createReactComponent('ion-header');
401const IonImg = /*@__PURE__*/ createReactComponent('ion-img');
402const IonInfiniteScroll = /*@__PURE__*/ createReactComponent('ion-infinite-scroll');
403const IonInfiniteScrollContent = /*@__PURE__*/ createReactComponent('ion-infinite-scroll-content');
404const IonInput = /*@__PURE__*/ createReactComponent('ion-input');
405const IonItem = /*@__PURE__*/ createReactComponent('ion-item', true);
406const IonItemDivider = /*@__PURE__*/ createReactComponent('ion-item-divider');
407const IonItemGroup = /*@__PURE__*/ createReactComponent('ion-item-group');
408const IonItemOption = /*@__PURE__*/ createReactComponent('ion-item-option', true);
409const IonItemOptions = /*@__PURE__*/ createReactComponent('ion-item-options');
410const IonItemSliding = /*@__PURE__*/ createReactComponent('ion-item-sliding');
411const IonLabel = /*@__PURE__*/ createReactComponent('ion-label');
412const IonList = /*@__PURE__*/ createReactComponent('ion-list');
413const IonListHeader = /*@__PURE__*/ createReactComponent('ion-list-header');
414const IonMenu = /*@__PURE__*/ createReactComponent('ion-menu');
415const IonMenuButton = /*@__PURE__*/ createReactComponent('ion-menu-button');
416const IonMenuToggle = /*@__PURE__*/ createReactComponent('ion-menu-toggle');
417const IonNote = /*@__PURE__*/ createReactComponent('ion-note');
418const IonPickerColumn = /*@__PURE__*/ createReactComponent('ion-picker-column');
419const IonNav = /*@__PURE__*/ createReactComponent('ion-nav');
420const IonProgressBar = /*@__PURE__*/ createReactComponent('ion-progress-bar');
421const IonRadio = /*@__PURE__*/ createReactComponent('ion-radio');
422const IonRadioGroup = /*@__PURE__*/ createReactComponent('ion-radio-group');
423const IonRange = /*@__PURE__*/ createReactComponent('ion-range');
424const IonRefresher = /*@__PURE__*/ createReactComponent('ion-refresher');
425const IonRefresherContent = /*@__PURE__*/ createReactComponent('ion-refresher-content');
426const IonReorder = /*@__PURE__*/ createReactComponent('ion-reorder');
427const IonReorderGroup = /*@__PURE__*/ createReactComponent('ion-reorder-group');
428const IonRippleEffect = /*@__PURE__*/ createReactComponent('ion-ripple-effect');
429const IonRow = /*@__PURE__*/ createReactComponent('ion-row');
430const IonSearchbar = /*@__PURE__*/ createReactComponent('ion-searchbar');
431const IonSegment = /*@__PURE__*/ createReactComponent('ion-segment');
432const IonSegmentButton = /*@__PURE__*/ createReactComponent('ion-segment-button');
433const IonSelect = /*@__PURE__*/ createReactComponent('ion-select');
434const IonSelectOption = /*@__PURE__*/ createReactComponent('ion-select-option');
435const IonSelectPopover = /*@__PURE__*/ createReactComponent('ion-select-popover');
436const IonSkeletonText = /*@__PURE__*/ createReactComponent('ion-skeleton-text');
437const IonSlide = /*@__PURE__*/ createReactComponent('ion-slide');
438const IonSlides = /*@__PURE__*/ createReactComponent('ion-slides');
439const IonSpinner = /*@__PURE__*/ createReactComponent('ion-spinner');
440const IonSplitPane = /*@__PURE__*/ createReactComponent('ion-split-pane');
441const IonText = /*@__PURE__*/ createReactComponent('ion-text');
442const IonTextarea = /*@__PURE__*/ createReactComponent('ion-textarea');
443const IonThumbnail = /*@__PURE__*/ createReactComponent('ion-thumbnail');
444const IonTitle = /*@__PURE__*/ createReactComponent('ion-title');
445const IonToggle = /*@__PURE__*/ createReactComponent('ion-toggle');
446const IonToolbar = /*@__PURE__*/ createReactComponent('ion-toolbar');
447const IonVirtualScroll = /*@__PURE__*/ createReactComponent('ion-virtual-scroll');
448
449const createControllerComponent = (displayName, controller) => {
450 const didDismissEventName = `on${displayName}DidDismiss`;
451 const didPresentEventName = `on${displayName}DidPresent`;
452 const willDismissEventName = `on${displayName}WillDismiss`;
453 const willPresentEventName = `on${displayName}WillPresent`;
454 class Overlay extends React.Component {
455 constructor(props) {
456 super(props);
457 this.isUnmounted = false;
458 this.handleDismiss = this.handleDismiss.bind(this);
459 }
460 static get displayName() {
461 return displayName;
462 }
463 async componentDidMount() {
464 const { isOpen } = this.props;
465 if (isOpen) {
466 this.present();
467 }
468 }
469 componentWillUnmount() {
470 this.isUnmounted = true;
471 if (this.overlay) {
472 this.overlay.dismiss();
473 }
474 }
475 async componentDidUpdate(prevProps) {
476 if (prevProps.isOpen !== this.props.isOpen && this.props.isOpen === true) {
477 this.present(prevProps);
478 }
479 if (this.overlay && prevProps.isOpen !== this.props.isOpen && this.props.isOpen === false) {
480 await this.overlay.dismiss();
481 }
482 }
483 handleDismiss(event) {
484 if (this.props.onDidDismiss) {
485 this.props.onDidDismiss(event);
486 }
487 if (this.props.forwardedRef) {
488 this.props.forwardedRef.current = undefined;
489 }
490 }
491 async present(prevProps) {
492 const _a = this.props, cProps = __rest(_a, ["isOpen", "onDidDismiss", "onDidPresent", "onWillDismiss", "onWillPresent"]);
493 this.overlay = await controller.create(Object.assign({}, cProps));
494 attachProps(this.overlay, {
495 [didDismissEventName]: this.handleDismiss,
496 [didPresentEventName]: (e) => this.props.onDidPresent && this.props.onDidPresent(e),
497 [willDismissEventName]: (e) => this.props.onWillDismiss && this.props.onWillDismiss(e),
498 [willPresentEventName]: (e) => this.props.onWillPresent && this.props.onWillPresent(e)
499 }, prevProps);
500 // Check isOpen again since the value could have changed during the async call to controller.create
501 // It's also possible for the component to have become unmounted.
502 if (this.props.isOpen === true && this.isUnmounted === false) {
503 if (this.props.forwardedRef) {
504 this.props.forwardedRef.current = this.overlay;
505 }
506 await this.overlay.present();
507 }
508 }
509 render() {
510 return null;
511 }
512 }
513 return React.forwardRef((props, ref) => {
514 return React.createElement(Overlay, Object.assign({}, props, { forwardedRef: ref }));
515 });
516};
517
518const IonAlert = /*@__PURE__*/ createControllerComponent('IonAlert', alertController);
519
520const IonLoading = /*@__PURE__*/ createControllerComponent('IonLoading', loadingController);
521
522const toastController = {
523 create: (options) => toastController$1.create(options),
524 dismiss: (data, role, id) => toastController$1.dismiss(data, role, id),
525 getTop: () => toastController$1.getTop()
526};
527const IonToast = /*@__PURE__*/ createControllerComponent('IonToast', toastController);
528
529const IonPicker = /*@__PURE__*/ createControllerComponent('IonPicker', pickerController);
530
531const createOverlayComponent = (displayName, controller) => {
532 const didDismissEventName = `on${displayName}DidDismiss`;
533 const didPresentEventName = `on${displayName}DidPresent`;
534 const willDismissEventName = `on${displayName}WillDismiss`;
535 const willPresentEventName = `on${displayName}WillPresent`;
536 class Overlay extends React.Component {
537 constructor(props) {
538 super(props);
539 this.el = document.createElement('div');
540 this.handleDismiss = this.handleDismiss.bind(this);
541 }
542 static get displayName() {
543 return displayName;
544 }
545 componentDidMount() {
546 if (this.props.isOpen) {
547 this.present();
548 }
549 }
550 componentWillUnmount() {
551 if (this.overlay) {
552 this.overlay.dismiss();
553 }
554 }
555 handleDismiss(event) {
556 if (this.props.onDidDismiss) {
557 this.props.onDidDismiss(event);
558 }
559 if (this.props.forwardedRef) {
560 this.props.forwardedRef.current = undefined;
561 }
562 }
563 async componentDidUpdate(prevProps) {
564 if (this.overlay) {
565 attachProps(this.overlay, this.props, prevProps);
566 }
567 if (prevProps.isOpen !== this.props.isOpen && this.props.isOpen === true) {
568 this.present(prevProps);
569 }
570 if (this.overlay && prevProps.isOpen !== this.props.isOpen && this.props.isOpen === false) {
571 await this.overlay.dismiss();
572 }
573 }
574 async present(prevProps) {
575 const _a = this.props, cProps = __rest(_a, ["children", "isOpen", "onDidDismiss", "onDidPresent", "onWillDismiss", "onWillPresent"]);
576 const elementProps = Object.assign(Object.assign({}, cProps), { ref: this.props.forwardedRef, [didDismissEventName]: this.handleDismiss, [didPresentEventName]: (e) => this.props.onDidPresent && this.props.onDidPresent(e), [willDismissEventName]: (e) => this.props.onWillDismiss && this.props.onWillDismiss(e), [willPresentEventName]: (e) => this.props.onWillPresent && this.props.onWillPresent(e) });
577 this.overlay = await controller.create(Object.assign(Object.assign({}, elementProps), { component: this.el, componentProps: {} }));
578 if (this.props.forwardedRef) {
579 this.props.forwardedRef.current = this.overlay;
580 }
581 attachProps(this.overlay, elementProps, prevProps);
582 await this.overlay.present();
583 }
584 render() {
585 return ReactDom.createPortal(this.props.isOpen ? this.props.children : null, this.el);
586 }
587 }
588 return React.forwardRef((props, ref) => {
589 return React.createElement(Overlay, Object.assign({}, props, { forwardedRef: ref }));
590 });
591};
592
593const actionSheetController = {
594 create: (options) => actionSheetController$1.create(options),
595 dismiss: (data, role, id) => actionSheetController$1.dismiss(data, role, id),
596 getTop: () => actionSheetController$1.getTop()
597};
598const IonActionSheet = /*@__PURE__*/ createOverlayComponent('IonActionSheet', actionSheetController);
599
600const IonModal = /*@__PURE__*/ createOverlayComponent('IonModal', modalController);
601
602const IonPopover = /*@__PURE__*/ createOverlayComponent('IonPopover', popoverController);
603
604class IonPageInternal extends React.Component {
605 constructor(props) {
606 super(props);
607 this.ref = this.props.forwardedRef || React.createRef();
608 }
609 componentDidMount() {
610 if (this.context && this.ref && this.ref.current) {
611 if (this.context.hasIonicRouter()) {
612 this.context.registerIonPage(this.ref.current);
613 }
614 }
615 }
616 render() {
617 const _a = this.props, { className, children, forwardedRef } = _a, props = __rest(_a, ["className", "children", "forwardedRef"]);
618 return (React.createElement("div", Object.assign({ className: className ? `ion-page ${className}` : 'ion-page', ref: this.ref }, props), children));
619 }
620 static get displayName() {
621 return 'IonPage';
622 }
623 static get contextType() {
624 return NavContext;
625 }
626}
627const IonPage = createForwardRef(IonPageInternal, 'IonPage');
628
629const IonTabsContext = React.createContext({
630 activeTab: undefined,
631 selectTab: () => false
632});
633
634const IonTabBarInner = /*@__PURE__*/ createReactComponent('ion-tab-bar');
635const IonBackButtonInner = /*@__PURE__*/ createReactComponent('ion-back-button');
636const IonRouterOutletInner = /*@__PURE__*/ createReactComponent('ion-router-outlet');
637// ionicons
638const IonIconInner = /*@__PURE__*/ createReactComponent('ion-icon');
639
640const IonRouterOutletContainer = /*@__PURE__*/ (() => class extends React.Component {
641 render() {
642 const StackManager = this.context.getStackManager();
643 return (this.context.hasIonicRouter() ? (React.createElement(StackManager, null,
644 React.createElement(IonRouterOutletInner, Object.assign({ ref: this.props.forwardedRef }, this.props), this.props.children))) : (React.createElement(IonRouterOutletInner, Object.assign({ ref: this.props.forwardedRef }, this.props), this.props.children)));
645 }
646 static get contextType() {
647 return NavContext;
648 }
649})();
650const IonRouterOutlet = createForwardRef(IonRouterOutletContainer, 'IonRouterOutlet');
651
652class IonTabBarUnwrapped extends React.PureComponent {
653 constructor(props) {
654 super(props);
655 this.setActiveTabOnContext = (_tab) => { };
656 const tabs = {};
657 React.Children.forEach(props.children, (child) => {
658 if (child != null && typeof child === 'object' && child.props && child.type === IonTabButton) {
659 tabs[child.props.tab] = {
660 originalHref: child.props.href,
661 currentHref: child.props.href
662 };
663 }
664 });
665 const tabKeys = Object.keys(tabs);
666 const activeTab = tabKeys
667 .find(key => {
668 const href = tabs[key].originalHref;
669 return props.currentPath.startsWith(href);
670 }) || tabKeys[0];
671 this.state = {
672 activeTab,
673 tabs
674 };
675 this.onTabButtonClick = this.onTabButtonClick.bind(this);
676 this.renderTabButton = this.renderTabButton.bind(this);
677 this.setActiveTabOnContext = this.setActiveTabOnContext.bind(this);
678 this.selectTab = this.selectTab.bind(this);
679 }
680 selectTab(tab) {
681 const tabUrl = this.state.tabs[tab];
682 if (tabUrl) {
683 this.onTabButtonClick(new CustomEvent('ionTabButtonClick', {
684 detail: {
685 href: tabUrl.currentHref,
686 tab,
687 selected: tab === this.state.activeTab
688 }
689 }));
690 return true;
691 }
692 return false;
693 }
694 static getDerivedStateFromProps(props, state) {
695 const tabs = Object.assign({}, state.tabs);
696 const activeTab = Object.keys(state.tabs)
697 .find(key => {
698 const href = state.tabs[key].originalHref;
699 return props.currentPath.startsWith(href);
700 });
701 // Check to see if the tab button href has changed, and if so, update it in the tabs state
702 React.Children.forEach(props.children, (child) => {
703 if (child != null && typeof child === 'object' && child.props && child.type === IonTabButton) {
704 const tab = tabs[child.props.tab];
705 if (tab.originalHref !== child.props.href) {
706 tabs[child.props.tab] = {
707 originalHref: child.props.href,
708 currentHref: child.props.href
709 };
710 }
711 }
712 });
713 if (!(activeTab === undefined || (activeTab === state.activeTab && state.tabs[activeTab].currentHref === props.currentPath))) {
714 tabs[activeTab] = {
715 originalHref: tabs[activeTab].originalHref,
716 currentHref: props.currentPath
717 };
718 }
719 return {
720 activeTab,
721 tabs
722 };
723 }
724 onTabButtonClick(e) {
725 const originalHref = this.state.tabs[e.detail.tab].originalHref;
726 const currentHref = e.detail.href;
727 const { activeTab: prevActiveTab } = this.state;
728 // Clicking the current tab will bring you back to the original href
729 if (prevActiveTab === e.detail.tab) {
730 if (originalHref === currentHref) {
731 this.context.navigate(originalHref, 'none');
732 }
733 else {
734 this.context.navigate(originalHref, 'back', 'pop');
735 }
736 }
737 else {
738 if (this.props.onIonTabsWillChange) {
739 this.props.onIonTabsWillChange(new CustomEvent('ionTabWillChange', { detail: { tab: e.detail.tab } }));
740 }
741 if (this.props.onIonTabsDidChange) {
742 this.props.onIonTabsDidChange(new CustomEvent('ionTabDidChange', { detail: { tab: e.detail.tab } }));
743 }
744 this.setActiveTabOnContext(e.detail.tab);
745 this.context.navigate(currentHref, 'none');
746 }
747 }
748 renderTabButton(activeTab) {
749 return (child) => {
750 if (child != null && child.props && child.type === IonTabButton) {
751 const href = (child.props.tab === activeTab) ? this.props.currentPath : (this.state.tabs[child.props.tab].currentHref);
752 return React.cloneElement(child, {
753 href,
754 onIonTabButtonClick: this.onTabButtonClick
755 });
756 }
757 return null;
758 };
759 }
760 render() {
761 const { activeTab } = this.state;
762 return (React.createElement(IonTabBarInner, Object.assign({}, this.props, { selectedTab: activeTab }), React.Children.map(this.props.children, this.renderTabButton(activeTab))));
763 }
764 static get contextType() {
765 return NavContext;
766 }
767}
768const IonTabBarContainer = React.memo((_a) => {
769 var { forwardedRef } = _a, props = __rest(_a, ["forwardedRef"]);
770 const context = useContext(NavContext);
771 return (React.createElement(IonTabBarUnwrapped, Object.assign({ ref: forwardedRef }, props, { currentPath: props.currentPath || context.currentPath }), props.children));
772});
773const IonTabBar = createForwardRef(IonTabBarContainer, 'IonTabBar');
774
775const hostStyles = {
776 display: 'flex',
777 position: 'absolute',
778 top: '0',
779 left: '0',
780 right: '0',
781 bottom: '0',
782 flexDirection: 'column',
783 width: '100%',
784 height: '100%',
785 contain: 'layout size style'
786};
787const tabsInner = {
788 position: 'relative',
789 flex: 1,
790 contain: 'layout size style'
791};
792class IonTabs extends React.Component {
793 constructor(props) {
794 super(props);
795 this.routerOutletRef = React.createRef();
796 this.tabBarRef = React.createRef();
797 this.ionTabContextState = {
798 activeTab: undefined,
799 selectTab: () => false
800 };
801 }
802 componentDidMount() {
803 if (this.tabBarRef.current) {
804 // Grab initial value
805 this.ionTabContextState.activeTab = this.tabBarRef.current.state.activeTab;
806 // Override method
807 this.tabBarRef.current.setActiveTabOnContext = (tab) => {
808 this.ionTabContextState.activeTab = tab;
809 };
810 this.ionTabContextState.selectTab = this.tabBarRef.current.selectTab;
811 }
812 }
813 render() {
814 let outlet;
815 let tabBar;
816 const children = typeof this.props.children === 'function' ?
817 this.props.children(this.ionTabContextState) : this.props.children;
818 React.Children.forEach(children, (child) => {
819 if (child == null || typeof child !== 'object' || !child.hasOwnProperty('type')) {
820 return;
821 }
822 if (child.type === IonRouterOutlet) {
823 outlet = child;
824 }
825 else if (child.type === Fragment && child.props.children[0].type === IonRouterOutlet) {
826 outlet = child.props.children[0];
827 }
828 if (child.type === IonTabBar) {
829 const { onIonTabsDidChange, onIonTabsWillChange } = this.props;
830 tabBar = React.cloneElement(child, {
831 onIonTabsDidChange,
832 onIonTabsWillChange,
833 ref: this.tabBarRef
834 });
835 }
836 else if (child.type === Fragment && child.props.children[1].type === IonTabBar) {
837 const { onIonTabsDidChange, onIonTabsWillChange } = this.props;
838 tabBar = React.cloneElement(child.props.children[1], {
839 onIonTabsDidChange,
840 onIonTabsWillChange,
841 ref: this.tabBarRef
842 });
843 }
844 });
845 if (!outlet) {
846 throw new Error('IonTabs must contain an IonRouterOutlet');
847 }
848 if (!tabBar) {
849 // TODO, this is not required
850 throw new Error('IonTabs needs a IonTabBar');
851 }
852 return (React.createElement(IonTabsContext.Provider, { value: this.ionTabContextState },
853 React.createElement("div", { style: hostStyles },
854 tabBar.props.slot === 'top' ? tabBar : null,
855 React.createElement("div", { style: tabsInner, className: "tabs-inner" }, outlet),
856 tabBar.props.slot === 'bottom' ? tabBar : null)));
857 }
858 static get contextType() {
859 return NavContext;
860 }
861}
862
863const IonBackButton = /*@__PURE__*/ (() => class extends React.Component {
864 constructor() {
865 super(...arguments);
866 this.clickButton = (e) => {
867 const defaultHref = this.props.defaultHref;
868 if (this.context.hasIonicRouter()) {
869 e.stopPropagation();
870 this.context.goBack(defaultHref);
871 }
872 else if (defaultHref !== undefined) {
873 window.location.href = defaultHref;
874 }
875 };
876 }
877 render() {
878 return (React.createElement(IonBackButtonInner, Object.assign({ onClick: this.clickButton }, this.props)));
879 }
880 static get displayName() {
881 return 'IonBackButton';
882 }
883 static get contextType() {
884 return NavContext;
885 }
886})();
887
888const isDevMode = () => {
889 return process && process.env && process.env.NODE_ENV === 'development';
890};
891const warnings = {};
892const deprecationWarning = (key, message) => {
893 if (isDevMode()) {
894 if (!warnings[key]) {
895 console.warn(message);
896 warnings[key] = true;
897 }
898 }
899};
900
901class IonIconContainer extends React.PureComponent {
902 constructor(props) {
903 super(props);
904 if (this.props.name) {
905 deprecationWarning('icon-name', '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.');
906 }
907 }
908 render() {
909 var _a, _b;
910 const _c = this.props, { icon, ios, md } = _c, rest = __rest(_c, ["icon", "ios", "md"]);
911 let iconToUse;
912 if (ios || md) {
913 if (isPlatform('ios')) {
914 iconToUse = (_a = ios !== null && ios !== void 0 ? ios : md) !== null && _a !== void 0 ? _a : icon;
915 }
916 else {
917 iconToUse = (_b = md !== null && md !== void 0 ? md : ios) !== null && _b !== void 0 ? _b : icon;
918 }
919 }
920 else {
921 iconToUse = icon;
922 }
923 return (React.createElement(IonIconInner, Object.assign({ ref: this.props.forwardedRef, icon: iconToUse }, rest), this.props.children));
924 }
925 static get contextType() {
926 return NavContext;
927 }
928}
929const IonIcon = createForwardRef(IonIconContainer, 'IonIcon');
930
931class CreateAnimation extends React.PureComponent {
932 constructor(props) {
933 super(props);
934 this.nodes = new Map();
935 this.animation = createAnimation(props.id);
936 }
937 setupAnimation(props) {
938 const animation = this.animation;
939 if (this.nodes.size > 0) {
940 animation.addElement(Array.from(this.nodes.values()));
941 }
942 checkConfig(animation, props);
943 checkPlayback(animation, props);
944 }
945 componentDidMount() {
946 const props = this.props;
947 this.setupAnimation(props);
948 }
949 componentDidUpdate(prevProps) {
950 const animation = this.animation;
951 const props = this.props;
952 checkConfig(animation, props, prevProps);
953 checkProgress(animation, props, prevProps);
954 checkPlayback(animation, props, prevProps);
955 }
956 render() {
957 const { children } = this.props;
958 return (React.createElement(React.Fragment, null, React.Children.map(children, ((child, id) => React.cloneElement(child, { ref: (el) => this.nodes.set(id, el) })))));
959 }
960}
961const checkConfig = (animation, currentProps = {}, prevProps = {}) => {
962 const reservedProps = ['children', 'progressStart', 'progressStep', 'progressEnd', 'pause', 'stop', 'destroy', 'play', 'from', 'to', 'fromTo', 'onFinish'];
963 for (const key in currentProps) {
964 if (currentProps.hasOwnProperty(key) &&
965 !reservedProps.includes(key) &&
966 currentProps[key] !== prevProps[key]) {
967 animation[key](currentProps[key]);
968 }
969 }
970 const fromValues = currentProps.from;
971 if (fromValues && fromValues !== prevProps.from) {
972 const values = (Array.isArray(fromValues)) ? fromValues : [fromValues];
973 values.forEach(val => animation.from(val.property, val.value));
974 }
975 const toValues = currentProps.to;
976 if (toValues && toValues !== prevProps.to) {
977 const values = (Array.isArray(toValues)) ? toValues : [toValues];
978 values.forEach(val => animation.to(val.property, val.value));
979 }
980 const fromToValues = currentProps.fromTo;
981 if (fromToValues && fromToValues !== prevProps.fromTo) {
982 const values = (Array.isArray(fromToValues)) ? fromToValues : [fromToValues];
983 values.forEach(val => animation.fromTo(val.property, val.fromValue, val.toValue));
984 }
985 const onFinishValues = currentProps.onFinish;
986 if (onFinishValues && onFinishValues !== prevProps.onFinish) {
987 const values = (Array.isArray(onFinishValues)) ? onFinishValues : [onFinishValues];
988 values.forEach(val => animation.onFinish(val.callback, val.opts));
989 }
990};
991const checkProgress = (animation, currentProps = {}, prevProps = {}) => {
992 var _a, _b, _c, _d, _e;
993 const { progressStart, progressStep, progressEnd } = currentProps;
994 if (progressStart && (((_a = prevProps.progressStart) === null || _a === void 0 ? void 0 : _a.forceLinearEasing) !== (progressStart === null || progressStart === void 0 ? void 0 : progressStart.forceLinearEasing) || ((_b = prevProps.progressStart) === null || _b === void 0 ? void 0 : _b.step) !== (progressStart === null || progressStart === void 0 ? void 0 : progressStart.step))) {
995 animation.progressStart(progressStart.forceLinearEasing, progressStart.step);
996 }
997 if (progressStep && ((_c = prevProps.progressStep) === null || _c === void 0 ? void 0 : _c.step) !== (progressStep === null || progressStep === void 0 ? void 0 : progressStep.step)) {
998 animation.progressStep(progressStep.step);
999 }
1000 if (progressEnd && (((_d = prevProps.progressEnd) === null || _d === void 0 ? void 0 : _d.playTo) !== (progressEnd === null || progressEnd === void 0 ? void 0 : progressEnd.playTo) || ((_e = prevProps.progressEnd) === null || _e === void 0 ? void 0 : _e.step) !== (progressEnd === null || progressEnd === void 0 ? void 0 : progressEnd.step) || (prevProps === null || prevProps === void 0 ? void 0 : prevProps.dur) !== (progressEnd === null || progressEnd === void 0 ? void 0 : progressEnd.dur))) {
1001 animation.progressEnd(progressEnd.playTo, progressEnd.step, progressEnd.dur);
1002 }
1003};
1004const checkPlayback = (animation, currentProps = {}, prevProps = {}) => {
1005 if (!prevProps.play && currentProps.play) {
1006 animation.play();
1007 }
1008 if (!prevProps.pause && currentProps.pause) {
1009 animation.pause();
1010 }
1011 if (!prevProps.stop && currentProps.stop) {
1012 animation.stop();
1013 }
1014 if (!prevProps.destroy && currentProps.destroy) {
1015 animation.destroy();
1016 }
1017};
1018
1019// Icons that are used by internal components
1020addIcons({
1021 'arrow-back-sharp': arrowBackSharp,
1022 'caret-back-sharp': caretBackSharp,
1023 'chevron-back': chevronBack,
1024 'chevron-forward': chevronForward,
1025 'close': close,
1026 'close-circle': closeCircle,
1027 'close-sharp': closeSharp,
1028 'menu-outline': menuOutline,
1029 'menu-sharp': menuSharp,
1030 'reorder-two-sharp': reorderTwoSharp,
1031 'reorder-three-outline': reorderThreeOutline,
1032 'search-outline': searchOutline,
1033 'search-sharp': searchSharp,
1034});
1035// TODO: defineCustomElements() is asyncronous
1036// We need to use the promise
1037defineCustomElements(window);
1038
1039export { CreateAnimation, DefaultIonLifeCycleContext, IonActionSheet, IonAlert, IonApp, IonAvatar, IonBackButton, IonBackdrop, IonBadge, IonButton, IonButtons, IonCard, IonCardContent, IonCardHeader, IonCardSubtitle, IonCardTitle, IonCheckbox, IonChip, IonCol, IonContent, IonDatetime, IonFab, IonFabButton, IonFabList, IonFooter, IonGrid, IonHeader, IonIcon, IonImg, IonInfiniteScroll, IonInfiniteScrollContent, IonInput, IonItem, IonItemDivider, IonItemGroup, IonItemOption, IonItemOptions, IonItemSliding, IonLabel, IonLifeCycleContext, IonList, IonListHeader, IonLoading, IonMenu, IonMenuButton, IonMenuToggle, IonModal, IonNav, IonNote, IonPage, IonPicker, IonPickerColumn, IonPopover, IonProgressBar, IonRadio, IonRadioGroup, IonRange, IonRefresher, IonRefresherContent, IonReorder, IonReorderGroup, IonRippleEffect, IonRouterLink, IonRouterOutlet, IonRow, IonSearchbar, IonSegment, IonSegmentButton, IonSelect, IonSelectOption, IonSelectPopover, IonSkeletonText, IonSlide, IonSlides, IonSpinner, IonSplitPane, IonTab, IonTabBar, IonTabButton, IonTabs, IonTabsContext, IonText, IonTextarea, IonThumbnail, IonTitle, IonToast, IonToggle, IonToolbar, IonVirtualScroll, NavContext, getConfig, getPlatforms, isPlatform, useIonViewDidEnter, useIonViewDidLeave, useIonViewWillEnter, useIonViewWillLeave, withIonLifeCycle };
1040//# sourceMappingURL=index.esm.js.map