@ionic/react
Advanced tools
Comparing version 0.0.6-5 to 0.0.6-6
import { defineCustomElements } from '@ionic/core/loader'; | ||
import React from 'react'; | ||
import { __rest } from 'tslib'; | ||
import React from 'react'; | ||
import ReactDom from 'react-dom'; | ||
import { alertController, loadingController, toastController, actionSheetController, modalController, popoverController } from '@ionic/core'; | ||
export { setupConfig } from '@ionic/core'; | ||
import { withRouter, Switch, matchPath } from 'react-router'; | ||
import { matchPath as matchPath$1, Redirect, withRouter as withRouter$1 } from 'react-router-dom'; | ||
import { isPlatform, getPlatforms, setupConfig, alertController, loadingController, toastController, actionSheetController, modalController, popoverController } from '@ionic/core'; | ||
import { arrowBack } from 'ionicons/icons'; | ||
import { withRouter } from 'react-router'; | ||
import { matchPath, Redirect, Switch, withRouter as withRouter$1 } from 'react-router-dom'; | ||
@@ -85,2 +85,15 @@ function attachEventProps(node, newProps, oldProps = {}) { | ||
const IonicContext = /*@__PURE__*/ React.createContext({ | ||
getConfig: () => { }, | ||
setConfig: () => { }, | ||
platform: undefined | ||
}); | ||
const useIonicConfig = () => { | ||
const value = React.useContext(IonicContext); | ||
const config = value.getConfig() || {}; | ||
const hook = [config, value.setConfig]; | ||
return hook; | ||
}; | ||
const dashToPascalCase = (str) => str.toLowerCase().split('-').map(segment => segment.charAt(0).toUpperCase() + segment.slice(1)).join(''); | ||
@@ -104,5 +117,5 @@ function generateUniqueId() { | ||
componentDidMount() { | ||
this.componentDidUpdate(this.props); | ||
this.componentWillReceiveProps(this.props); | ||
} | ||
componentDidUpdate(props) { | ||
componentWillReceiveProps(props) { | ||
const node = ReactDom.findDOMNode(this); | ||
@@ -138,3 +151,3 @@ attachEventProps(node, props, this.props); | ||
const IonAnchor = /*@__PURE__*/ createReactComponent('ion-anchor'); | ||
const IonApp = /*@__PURE__*/ createReactComponent('ion-app'); | ||
const IonAppInner = /*@__PURE__*/ createReactComponent('ion-app'); | ||
const IonAvatar = /*@__PURE__*/ createReactComponent('ion-avatar'); | ||
@@ -209,2 +222,170 @@ const IonBackdrop = /*@__PURE__*/ createReactComponent('ion-backdrop'); | ||
class Platform { | ||
constructor() { } | ||
/** | ||
* @returns returns true/false based on platform. | ||
* @description | ||
* Depending on the platform the user is on, `is(platformName)` will | ||
* return `true` or `false`. Note that the same app can return `true` | ||
* for more than one platform name. For example, an app running from | ||
* an iPad would return `true` for the platform names: `mobile`, | ||
* `ios`, `ipad`, and `tablet`. Additionally, if the app was running | ||
* from Cordova then `cordova` would be true, and if it was running | ||
* from a web browser on the iPad then `mobileweb` would be `true`. | ||
* | ||
* ``` | ||
* import { Platform } from 'ionic-angular'; | ||
* | ||
* @Component({...}) | ||
* export MyPage { | ||
* constructor(public platform: Platform) { | ||
* if (this.platform.is('ios')) { | ||
* // This will only print when on iOS | ||
* console.log('I am an iOS device!'); | ||
* } | ||
* } | ||
* } | ||
* ``` | ||
* | ||
* | Platform Name | Description | | ||
* |-----------------|------------------------------------| | ||
* | android | on a device running Android. | | ||
* | cordova | on a device running Cordova. | | ||
* | ios | on a device running iOS. | | ||
* | ipad | on an iPad device. | | ||
* | iphone | on an iPhone device. | | ||
* | phablet | on a phablet device. | | ||
* | tablet | on a tablet device. | | ||
* | electron | in Electron on a desktop device. | | ||
* | pwa | as a PWA app. | | ||
* | mobile | on a mobile device. | | ||
* | mobileweb | on a mobile device in a browser. | | ||
* | desktop | on a desktop device. | | ||
* | hybrid | is a cordova or capacitor app. | | ||
* | ||
*/ | ||
is(platformName) { | ||
return isPlatform(window, platformName); | ||
} | ||
/** | ||
* @returns the array of platforms | ||
* @description | ||
* Depending on what device you are on, `platforms` can return multiple values. | ||
* Each possible value is a hierarchy of platforms. For example, on an iPhone, | ||
* it would return `mobile`, `ios`, and `iphone`. | ||
* | ||
* ``` | ||
* import { Platform } from 'ionic-angular'; | ||
* | ||
* @Component({...}) | ||
* export MyPage { | ||
* constructor(public platform: Platform) { | ||
* // This will print an array of the current platforms | ||
* console.log(this.platform.platforms()); | ||
* } | ||
* } | ||
* ``` | ||
*/ | ||
platforms() { | ||
return getPlatforms(window); | ||
} | ||
/** | ||
* Returns if this app is using right-to-left language direction or not. | ||
* We recommend the app's `index.html` file already has the correct `dir` | ||
* attribute value set, such as `<html dir="ltr">` or `<html dir="rtl">`. | ||
* [W3C: Structural markup and right-to-left text in HTML](http://www.w3.org/International/questions/qa-html-dir) | ||
*/ | ||
get isRTL() { | ||
return document.dir === 'rtl'; | ||
} | ||
/** | ||
* Get the query string parameter | ||
*/ | ||
getQueryParam(key) { | ||
return readQueryParam(window.location.href, key); | ||
} | ||
/** | ||
* Returns `true` if the app is in landscape mode. | ||
*/ | ||
isLandscape() { | ||
return !this.isPortrait(); | ||
} | ||
/** | ||
* Returns `true` if the app is in portait mode. | ||
*/ | ||
isPortrait() { | ||
return window.matchMedia && window.matchMedia('(orientation: portrait)').matches; | ||
} | ||
testUserAgent(expression) { | ||
const nav = window.navigator; | ||
return !!(nav && nav.userAgent && nav.userAgent.indexOf(expression) >= 0); | ||
} | ||
/** | ||
* Get the current url. | ||
*/ | ||
url() { | ||
return window.location.href; | ||
} | ||
/** | ||
* Gets the width of the platform's viewport using `window.innerWidth`. | ||
*/ | ||
width() { | ||
return window.innerWidth; | ||
} | ||
/** | ||
* Gets the height of the platform's viewport using `window.innerHeight`. | ||
*/ | ||
height() { | ||
return window.innerHeight; | ||
} | ||
} | ||
const readQueryParam = (url, key) => { | ||
key = key.replace(/[\[]/, '\\[').replace(/[\]]/, '\\]'); | ||
const regex = new RegExp('[\\?&]' + key + '=([^&#]*)'); | ||
const results = regex.exec(url); | ||
return results ? decodeURIComponent(results[1].replace(/\+/g, ' ')) : null; | ||
}; | ||
function getConfig() { | ||
const coreConfig = getCoreConfig(); | ||
const config = Array.from(coreConfig.m).reduce((obj, [key, value]) => { | ||
obj[key] = value; | ||
return obj; | ||
}, {}); | ||
return config; | ||
} | ||
function setConfig(config) { | ||
const coreConfig = getCoreConfig(); | ||
coreConfig.reset(config); | ||
} | ||
function getCoreConfig() { | ||
if (typeof window !== 'undefined') { | ||
const Ionic = window.Ionic; | ||
if (Ionic && Ionic.config) { | ||
return window.Ionic.config; | ||
} | ||
} | ||
return null; | ||
} | ||
class IonApp extends React.Component { | ||
constructor(props) { | ||
super(props); | ||
const { initialConfig: config = {} } = this.props; | ||
if (config) { | ||
setupConfig(Object.assign({ backButtonIcon: arrowBack }, config)); | ||
} | ||
const ionicPlatform = new Platform(); | ||
this.state = { | ||
getConfig: getConfig, | ||
setConfig: setConfig, | ||
platform: ionicPlatform | ||
}; | ||
} | ||
render() { | ||
return (React.createElement(IonicContext.Provider, { value: this.state }, | ||
React.createElement(IonAppInner, null, this.props.children))); | ||
} | ||
} | ||
function createControllerComponent(displayName, controller) { | ||
@@ -361,2 +542,9 @@ const dismissEventName = `on${displayName}DidDismiss`; | ||
function generateUniqueId$1() { | ||
return ([1e7].toString() + -1e3.toString() + -4e3.toString() + -8e3.toString() + -1e11.toString()).replace(/[018]/g, function (c) { | ||
const random = crypto.getRandomValues(new Uint8Array(1)); | ||
return (c ^ random[0] & 15 >> c / 4).toString(16); | ||
}); | ||
} | ||
const IonLifeCycleContext = React.createContext({ | ||
@@ -471,4 +659,5 @@ onIonViewWillEnter: () => { }, | ||
goBack: () => { navContextNotFoundError(); }, | ||
registerViewStack: () => { navContextNotFoundError(); }, | ||
setupIonRouter: () => { navContextNotFoundError(); }, | ||
removeViewStack: () => { navContextNotFoundError(); }, | ||
renderChild: () => { navContextNotFoundError(); }, | ||
transitionView: () => { navContextNotFoundError(); } | ||
@@ -568,47 +757,10 @@ }); | ||
class IonRouterOutletUnWrapped extends React.Component { | ||
class IonRouterOutlet extends React.Component { | ||
constructor(props) { | ||
super(props); | ||
this.containerEl = React.createRef(); | ||
this.id = this.props.id || generateUniqueId(); | ||
this.id = this.props.id || generateUniqueId$1(); | ||
} | ||
componentDidMount() { | ||
const views = []; | ||
let activeId; | ||
React.Children.forEach(this.props.children, (child) => { | ||
if (child.type === Switch) { | ||
/** | ||
* If the first child is a Switch, loop through its children to build the viewStack | ||
*/ | ||
React.Children.forEach(child.props.children, (grandChild) => { | ||
addView.call(this, grandChild); | ||
}); | ||
} | ||
else { | ||
addView.call(this, child); | ||
} | ||
}); | ||
this.context.registerViewStack(this.id, activeId, views, this.containerEl.current, this.props.location); | ||
function addView(child) { | ||
const location = this.props.history.location; | ||
const viewId = generateUniqueId(); | ||
const key = generateUniqueId(); | ||
const element = child; | ||
const match = matchPath(location.pathname, child.props); | ||
const view = { | ||
id: viewId, | ||
key, | ||
match, | ||
element, | ||
mount: true, | ||
show: !!match, | ||
ref: React.createRef(), | ||
childProps: child.props | ||
}; | ||
if (!!match) { | ||
activeId = viewId; | ||
} | ||
views.push(view); | ||
return activeId; | ||
} | ||
this.context.setupIonRouter(this.id, this.props.children, this.containerEl.current); | ||
} | ||
@@ -618,8 +770,2 @@ componentWillUnmount() { | ||
} | ||
renderChild(item) { | ||
const component = React.cloneElement(item.element, { | ||
computedMatch: item.match | ||
}); | ||
return component; | ||
} | ||
render() { | ||
@@ -645,3 +791,3 @@ return (React.createElement(NavContext.Consumer, null, context => { | ||
return (React.createElement(ViewItemManager, { id: item.id, key: item.key, mount: item.mount }, | ||
React.createElement(View, Object.assign({ ref: item.ref }, props), this.renderChild(item)))); | ||
React.createElement(View, Object.assign({ ref: item.ref }, props), this.context.renderChild(item)))); | ||
}))); | ||
@@ -651,3 +797,2 @@ })); | ||
} | ||
const IonRouterOutlet = /*@__PURE__*/ withRouter(IonRouterOutletUnWrapped); | ||
@@ -707,3 +852,3 @@ const hostStyles = { | ||
class IonRouter extends React.Component { | ||
class IonReactRouter extends React.Component { | ||
constructor(props) { | ||
@@ -716,3 +861,3 @@ super(props); | ||
if (enteringView) { | ||
this.props.history.replace(enteringView.match.url, { direction: 'back' }); | ||
this.props.history.replace(enteringView.routeData.match.url, { direction: 'back' }); | ||
} | ||
@@ -730,4 +875,5 @@ else { | ||
hideView: this.hideView.bind(this), | ||
registerViewStack: this.registerView.bind(this), | ||
setupIonRouter: this.setupIonRouter.bind(this), | ||
removeViewStack: this.removeViewStack.bind(this), | ||
renderChild: this.renderChild.bind(this), | ||
goBack: this.goBack.bind(this), | ||
@@ -762,3 +908,3 @@ transitionView: this.transitionView.bind(this) | ||
return vs.views.some(x => { | ||
match = matchPath$1(location.pathname, x.childProps); | ||
match = matchPath(location.pathname, x.routeData.childProps); | ||
if (match) { | ||
@@ -800,3 +946,3 @@ view = x; | ||
const { view: leavingView } = this.findViewInfoById(this.activeViewId, viewStacks); | ||
if (leavingView && leavingView.match.url === location.pathname) { | ||
if (leavingView && leavingView.routeData.match.url === location.pathname) { | ||
return; | ||
@@ -814,3 +960,3 @@ } | ||
enteringView.mount = true; | ||
enteringView.match = match; | ||
enteringView.routeData.match = match; | ||
enteringViewStack.activeId = enteringView.id; | ||
@@ -820,3 +966,3 @@ this.activeViewId = enteringView.id; | ||
this.prevViewId = leavingView.id; | ||
if (leavingView.match.params.tab === enteringView.match.params.tab) { | ||
if (leavingView.routeData.match.params.tab === enteringView.routeData.match.params.tab) { | ||
if (action === 'PUSH') { | ||
@@ -853,3 +999,45 @@ direction = direction || 'forward'; | ||
} | ||
registerView(stack, activeId, stackItems, routerOutlet, location) { | ||
setupIonRouter(id, children, routerOutlet) { | ||
const views = []; | ||
let activeId; | ||
React.Children.forEach(children, (child) => { | ||
if (child.type === Switch) { | ||
/** | ||
* If the first child is a Switch, loop through its children to build the viewStack | ||
*/ | ||
React.Children.forEach(child.props.children, (grandChild) => { | ||
addView.call(this, grandChild); | ||
}); | ||
} | ||
else { | ||
addView.call(this, child); | ||
} | ||
}); | ||
this.registerViewStack(id, activeId, views, routerOutlet, this.props.location); | ||
function addView(child) { | ||
const location = this.props.history.location; | ||
const viewId = generateUniqueId(); | ||
const key = generateUniqueId(); | ||
const element = child; | ||
const match = matchPath(location.pathname, child.props); | ||
const view = { | ||
id: viewId, | ||
key, | ||
routeData: { | ||
match, | ||
childProps: child.props | ||
}, | ||
element, | ||
mount: true, | ||
show: !!match, | ||
ref: React.createRef() | ||
}; | ||
if (!!match) { | ||
activeId = viewId; | ||
} | ||
views.push(view); | ||
return activeId; | ||
} | ||
} | ||
registerViewStack(stack, activeId, stackItems, routerOutlet, location) { | ||
this.setState((prevState) => { | ||
@@ -884,6 +1072,12 @@ const prevViewStacks = Object.assign({}, prevState.viewStacks); | ||
} | ||
renderChild(item) { | ||
const component = React.cloneElement(item.element, { | ||
computedMatch: item.routeData.match | ||
}); | ||
return component; | ||
} | ||
findActiveView(views) { | ||
let view; | ||
views.some(x => { | ||
const match = matchPath$1(this.props.location.pathname, x.childProps); | ||
const match = matchPath(this.props.location.pathname, x.routeData.childProps); | ||
if (match) { | ||
@@ -932,6 +1126,6 @@ view = x; | ||
} | ||
const IonRouterWrapped = withRouter$1(IonRouter); | ||
const IonReactRouterWrapped = withRouter$1(IonReactRouter); | ||
defineCustomElements(window); | ||
export { IonActionSheet, IonAlert, IonAnchor, IonApp, IonAvatar, IonBackButton, IonBackButtonInner, IonBackdrop, IonBadge, IonButton, IonButtons, IonCard, IonCardContent, IonCardHeader, IonCardSubtitle, IonCardTitle, IonCheckbox, IonChip, IonCol, IonContent, IonDatetime, IonFab, IonFabButton, IonFabList, IonFooter, IonGrid, IonHeader, IonIcon, IonImg, IonInfiniteScroll, 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, IonRouterWrapped as IonRouter, IonRouterOutlet, IonRouterOutletInner, IonRow, IonSearchbar, IonSegment, IonSegmentButton, IonSelect, IonSelectOption, IonSelectPopover, IonSkeletonText, IonSlide, IonSlides, IonSpinner, IonSplitPane, IonTab, IonTabBar, IonTabBarInner, IonTabButton, IonTabs, IonText, IonTextarea, IonThumbnail, IonTitle, IonToast, IonToggle, IonToolbar, IonVirtualScroll, useIonViewDidEnter, useIonViewDidLeave, useIonViewWillEnter, useIonViewWillLeave, withIonLifeCycle }; | ||
export { IonActionSheet, IonAlert, IonAnchor, IonApp, IonAppInner, IonAvatar, IonBackButton, IonBackButtonInner, IonBackdrop, IonBadge, IonButton, IonButtons, IonCard, IonCardContent, IonCardHeader, IonCardSubtitle, IonCardTitle, IonCheckbox, IonChip, IonCol, IonContent, IonDatetime, IonFab, IonFabButton, IonFabList, IonFooter, IonGrid, IonHeader, IonIcon, IonImg, IonInfiniteScroll, 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, IonReactRouterWrapped as IonReactRouter, IonRefresher, IonRefresherContent, IonReorder, IonReorderGroup, IonRippleEffect, IonRouterOutlet, IonRouterOutletInner, IonRow, IonSearchbar, IonSegment, IonSegmentButton, IonSelect, IonSelectOption, IonSelectPopover, IonSkeletonText, IonSlide, IonSlides, IonSpinner, IonSplitPane, IonTab, IonTabBar, IonTabBarInner, IonTabButton, IonTabs, IonText, IonTextarea, IonThumbnail, IonTitle, IonToast, IonToggle, IonToolbar, IonVirtualScroll, IonicContext, useIonViewDidEnter, useIonViewDidLeave, useIonViewWillEnter, useIonViewWillLeave, useIonicConfig, withIonLifeCycle }; |
@@ -8,6 +8,7 @@ 'use strict'; | ||
var loader = require('@ionic/core/loader'); | ||
var React = _interopDefault(require('react')); | ||
var tslib_1 = require('tslib'); | ||
var React = _interopDefault(require('react')); | ||
var ReactDom = _interopDefault(require('react-dom')); | ||
var core = require('@ionic/core'); | ||
var icons = require('ionicons/icons'); | ||
var reactRouter = require('react-router'); | ||
@@ -91,2 +92,15 @@ var reactRouterDom = require('react-router-dom'); | ||
const IonicContext = /*@__PURE__*/ React.createContext({ | ||
getConfig: () => { }, | ||
setConfig: () => { }, | ||
platform: undefined | ||
}); | ||
const useIonicConfig = () => { | ||
const value = React.useContext(IonicContext); | ||
const config = value.getConfig() || {}; | ||
const hook = [config, value.setConfig]; | ||
return hook; | ||
}; | ||
const dashToPascalCase = (str) => str.toLowerCase().split('-').map(segment => segment.charAt(0).toUpperCase() + segment.slice(1)).join(''); | ||
@@ -110,5 +124,5 @@ function generateUniqueId() { | ||
componentDidMount() { | ||
this.componentDidUpdate(this.props); | ||
this.componentWillReceiveProps(this.props); | ||
} | ||
componentDidUpdate(props) { | ||
componentWillReceiveProps(props) { | ||
const node = ReactDom.findDOMNode(this); | ||
@@ -144,3 +158,3 @@ attachEventProps(node, props, this.props); | ||
const IonAnchor = /*@__PURE__*/ createReactComponent('ion-anchor'); | ||
const IonApp = /*@__PURE__*/ createReactComponent('ion-app'); | ||
const IonAppInner = /*@__PURE__*/ createReactComponent('ion-app'); | ||
const IonAvatar = /*@__PURE__*/ createReactComponent('ion-avatar'); | ||
@@ -215,2 +229,170 @@ const IonBackdrop = /*@__PURE__*/ createReactComponent('ion-backdrop'); | ||
class Platform { | ||
constructor() { } | ||
/** | ||
* @returns returns true/false based on platform. | ||
* @description | ||
* Depending on the platform the user is on, `is(platformName)` will | ||
* return `true` or `false`. Note that the same app can return `true` | ||
* for more than one platform name. For example, an app running from | ||
* an iPad would return `true` for the platform names: `mobile`, | ||
* `ios`, `ipad`, and `tablet`. Additionally, if the app was running | ||
* from Cordova then `cordova` would be true, and if it was running | ||
* from a web browser on the iPad then `mobileweb` would be `true`. | ||
* | ||
* ``` | ||
* import { Platform } from 'ionic-angular'; | ||
* | ||
* @Component({...}) | ||
* export MyPage { | ||
* constructor(public platform: Platform) { | ||
* if (this.platform.is('ios')) { | ||
* // This will only print when on iOS | ||
* console.log('I am an iOS device!'); | ||
* } | ||
* } | ||
* } | ||
* ``` | ||
* | ||
* | Platform Name | Description | | ||
* |-----------------|------------------------------------| | ||
* | android | on a device running Android. | | ||
* | cordova | on a device running Cordova. | | ||
* | ios | on a device running iOS. | | ||
* | ipad | on an iPad device. | | ||
* | iphone | on an iPhone device. | | ||
* | phablet | on a phablet device. | | ||
* | tablet | on a tablet device. | | ||
* | electron | in Electron on a desktop device. | | ||
* | pwa | as a PWA app. | | ||
* | mobile | on a mobile device. | | ||
* | mobileweb | on a mobile device in a browser. | | ||
* | desktop | on a desktop device. | | ||
* | hybrid | is a cordova or capacitor app. | | ||
* | ||
*/ | ||
is(platformName) { | ||
return core.isPlatform(window, platformName); | ||
} | ||
/** | ||
* @returns the array of platforms | ||
* @description | ||
* Depending on what device you are on, `platforms` can return multiple values. | ||
* Each possible value is a hierarchy of platforms. For example, on an iPhone, | ||
* it would return `mobile`, `ios`, and `iphone`. | ||
* | ||
* ``` | ||
* import { Platform } from 'ionic-angular'; | ||
* | ||
* @Component({...}) | ||
* export MyPage { | ||
* constructor(public platform: Platform) { | ||
* // This will print an array of the current platforms | ||
* console.log(this.platform.platforms()); | ||
* } | ||
* } | ||
* ``` | ||
*/ | ||
platforms() { | ||
return core.getPlatforms(window); | ||
} | ||
/** | ||
* Returns if this app is using right-to-left language direction or not. | ||
* We recommend the app's `index.html` file already has the correct `dir` | ||
* attribute value set, such as `<html dir="ltr">` or `<html dir="rtl">`. | ||
* [W3C: Structural markup and right-to-left text in HTML](http://www.w3.org/International/questions/qa-html-dir) | ||
*/ | ||
get isRTL() { | ||
return document.dir === 'rtl'; | ||
} | ||
/** | ||
* Get the query string parameter | ||
*/ | ||
getQueryParam(key) { | ||
return readQueryParam(window.location.href, key); | ||
} | ||
/** | ||
* Returns `true` if the app is in landscape mode. | ||
*/ | ||
isLandscape() { | ||
return !this.isPortrait(); | ||
} | ||
/** | ||
* Returns `true` if the app is in portait mode. | ||
*/ | ||
isPortrait() { | ||
return window.matchMedia && window.matchMedia('(orientation: portrait)').matches; | ||
} | ||
testUserAgent(expression) { | ||
const nav = window.navigator; | ||
return !!(nav && nav.userAgent && nav.userAgent.indexOf(expression) >= 0); | ||
} | ||
/** | ||
* Get the current url. | ||
*/ | ||
url() { | ||
return window.location.href; | ||
} | ||
/** | ||
* Gets the width of the platform's viewport using `window.innerWidth`. | ||
*/ | ||
width() { | ||
return window.innerWidth; | ||
} | ||
/** | ||
* Gets the height of the platform's viewport using `window.innerHeight`. | ||
*/ | ||
height() { | ||
return window.innerHeight; | ||
} | ||
} | ||
const readQueryParam = (url, key) => { | ||
key = key.replace(/[\[]/, '\\[').replace(/[\]]/, '\\]'); | ||
const regex = new RegExp('[\\?&]' + key + '=([^&#]*)'); | ||
const results = regex.exec(url); | ||
return results ? decodeURIComponent(results[1].replace(/\+/g, ' ')) : null; | ||
}; | ||
function getConfig() { | ||
const coreConfig = getCoreConfig(); | ||
const config = Array.from(coreConfig.m).reduce((obj, [key, value]) => { | ||
obj[key] = value; | ||
return obj; | ||
}, {}); | ||
return config; | ||
} | ||
function setConfig(config) { | ||
const coreConfig = getCoreConfig(); | ||
coreConfig.reset(config); | ||
} | ||
function getCoreConfig() { | ||
if (typeof window !== 'undefined') { | ||
const Ionic = window.Ionic; | ||
if (Ionic && Ionic.config) { | ||
return window.Ionic.config; | ||
} | ||
} | ||
return null; | ||
} | ||
class IonApp extends React.Component { | ||
constructor(props) { | ||
super(props); | ||
const { initialConfig: config = {} } = this.props; | ||
if (config) { | ||
core.setupConfig(Object.assign({ backButtonIcon: icons.arrowBack }, config)); | ||
} | ||
const ionicPlatform = new Platform(); | ||
this.state = { | ||
getConfig: getConfig, | ||
setConfig: setConfig, | ||
platform: ionicPlatform | ||
}; | ||
} | ||
render() { | ||
return (React.createElement(IonicContext.Provider, { value: this.state }, | ||
React.createElement(IonAppInner, null, this.props.children))); | ||
} | ||
} | ||
function createControllerComponent(displayName, controller) { | ||
@@ -367,2 +549,9 @@ const dismissEventName = `on${displayName}DidDismiss`; | ||
function generateUniqueId$1() { | ||
return ([1e7].toString() + -1e3.toString() + -4e3.toString() + -8e3.toString() + -1e11.toString()).replace(/[018]/g, function (c) { | ||
const random = crypto.getRandomValues(new Uint8Array(1)); | ||
return (c ^ random[0] & 15 >> c / 4).toString(16); | ||
}); | ||
} | ||
const IonLifeCycleContext = React.createContext({ | ||
@@ -477,4 +666,5 @@ onIonViewWillEnter: () => { }, | ||
goBack: () => { navContextNotFoundError(); }, | ||
registerViewStack: () => { navContextNotFoundError(); }, | ||
setupIonRouter: () => { navContextNotFoundError(); }, | ||
removeViewStack: () => { navContextNotFoundError(); }, | ||
renderChild: () => { navContextNotFoundError(); }, | ||
transitionView: () => { navContextNotFoundError(); } | ||
@@ -574,47 +764,10 @@ }); | ||
class IonRouterOutletUnWrapped extends React.Component { | ||
class IonRouterOutlet extends React.Component { | ||
constructor(props) { | ||
super(props); | ||
this.containerEl = React.createRef(); | ||
this.id = this.props.id || generateUniqueId(); | ||
this.id = this.props.id || generateUniqueId$1(); | ||
} | ||
componentDidMount() { | ||
const views = []; | ||
let activeId; | ||
React.Children.forEach(this.props.children, (child) => { | ||
if (child.type === reactRouter.Switch) { | ||
/** | ||
* If the first child is a Switch, loop through its children to build the viewStack | ||
*/ | ||
React.Children.forEach(child.props.children, (grandChild) => { | ||
addView.call(this, grandChild); | ||
}); | ||
} | ||
else { | ||
addView.call(this, child); | ||
} | ||
}); | ||
this.context.registerViewStack(this.id, activeId, views, this.containerEl.current, this.props.location); | ||
function addView(child) { | ||
const location = this.props.history.location; | ||
const viewId = generateUniqueId(); | ||
const key = generateUniqueId(); | ||
const element = child; | ||
const match = reactRouter.matchPath(location.pathname, child.props); | ||
const view = { | ||
id: viewId, | ||
key, | ||
match, | ||
element, | ||
mount: true, | ||
show: !!match, | ||
ref: React.createRef(), | ||
childProps: child.props | ||
}; | ||
if (!!match) { | ||
activeId = viewId; | ||
} | ||
views.push(view); | ||
return activeId; | ||
} | ||
this.context.setupIonRouter(this.id, this.props.children, this.containerEl.current); | ||
} | ||
@@ -624,8 +777,2 @@ componentWillUnmount() { | ||
} | ||
renderChild(item) { | ||
const component = React.cloneElement(item.element, { | ||
computedMatch: item.match | ||
}); | ||
return component; | ||
} | ||
render() { | ||
@@ -651,3 +798,3 @@ return (React.createElement(NavContext.Consumer, null, context => { | ||
return (React.createElement(ViewItemManager, { id: item.id, key: item.key, mount: item.mount }, | ||
React.createElement(View, Object.assign({ ref: item.ref }, props), this.renderChild(item)))); | ||
React.createElement(View, Object.assign({ ref: item.ref }, props), this.context.renderChild(item)))); | ||
}))); | ||
@@ -657,3 +804,2 @@ })); | ||
} | ||
const IonRouterOutlet = /*@__PURE__*/ reactRouter.withRouter(IonRouterOutletUnWrapped); | ||
@@ -713,3 +859,3 @@ const hostStyles = { | ||
class IonRouter extends React.Component { | ||
class IonReactRouter extends React.Component { | ||
constructor(props) { | ||
@@ -722,3 +868,3 @@ super(props); | ||
if (enteringView) { | ||
this.props.history.replace(enteringView.match.url, { direction: 'back' }); | ||
this.props.history.replace(enteringView.routeData.match.url, { direction: 'back' }); | ||
} | ||
@@ -736,4 +882,5 @@ else { | ||
hideView: this.hideView.bind(this), | ||
registerViewStack: this.registerView.bind(this), | ||
setupIonRouter: this.setupIonRouter.bind(this), | ||
removeViewStack: this.removeViewStack.bind(this), | ||
renderChild: this.renderChild.bind(this), | ||
goBack: this.goBack.bind(this), | ||
@@ -768,3 +915,3 @@ transitionView: this.transitionView.bind(this) | ||
return vs.views.some(x => { | ||
match = reactRouterDom.matchPath(location.pathname, x.childProps); | ||
match = reactRouterDom.matchPath(location.pathname, x.routeData.childProps); | ||
if (match) { | ||
@@ -806,3 +953,3 @@ view = x; | ||
const { view: leavingView } = this.findViewInfoById(this.activeViewId, viewStacks); | ||
if (leavingView && leavingView.match.url === location.pathname) { | ||
if (leavingView && leavingView.routeData.match.url === location.pathname) { | ||
return; | ||
@@ -820,3 +967,3 @@ } | ||
enteringView.mount = true; | ||
enteringView.match = match; | ||
enteringView.routeData.match = match; | ||
enteringViewStack.activeId = enteringView.id; | ||
@@ -826,3 +973,3 @@ this.activeViewId = enteringView.id; | ||
this.prevViewId = leavingView.id; | ||
if (leavingView.match.params.tab === enteringView.match.params.tab) { | ||
if (leavingView.routeData.match.params.tab === enteringView.routeData.match.params.tab) { | ||
if (action === 'PUSH') { | ||
@@ -859,3 +1006,45 @@ direction = direction || 'forward'; | ||
} | ||
registerView(stack, activeId, stackItems, routerOutlet, location) { | ||
setupIonRouter(id, children, routerOutlet) { | ||
const views = []; | ||
let activeId; | ||
React.Children.forEach(children, (child) => { | ||
if (child.type === reactRouterDom.Switch) { | ||
/** | ||
* If the first child is a Switch, loop through its children to build the viewStack | ||
*/ | ||
React.Children.forEach(child.props.children, (grandChild) => { | ||
addView.call(this, grandChild); | ||
}); | ||
} | ||
else { | ||
addView.call(this, child); | ||
} | ||
}); | ||
this.registerViewStack(id, activeId, views, routerOutlet, this.props.location); | ||
function addView(child) { | ||
const location = this.props.history.location; | ||
const viewId = generateUniqueId(); | ||
const key = generateUniqueId(); | ||
const element = child; | ||
const match = reactRouterDom.matchPath(location.pathname, child.props); | ||
const view = { | ||
id: viewId, | ||
key, | ||
routeData: { | ||
match, | ||
childProps: child.props | ||
}, | ||
element, | ||
mount: true, | ||
show: !!match, | ||
ref: React.createRef() | ||
}; | ||
if (!!match) { | ||
activeId = viewId; | ||
} | ||
views.push(view); | ||
return activeId; | ||
} | ||
} | ||
registerViewStack(stack, activeId, stackItems, routerOutlet, location) { | ||
this.setState((prevState) => { | ||
@@ -890,6 +1079,12 @@ const prevViewStacks = Object.assign({}, prevState.viewStacks); | ||
} | ||
renderChild(item) { | ||
const component = React.cloneElement(item.element, { | ||
computedMatch: item.routeData.match | ||
}); | ||
return component; | ||
} | ||
findActiveView(views) { | ||
let view; | ||
views.some(x => { | ||
const match = reactRouterDom.matchPath(this.props.location.pathname, x.childProps); | ||
const match = reactRouterDom.matchPath(this.props.location.pathname, x.routeData.childProps); | ||
if (match) { | ||
@@ -938,12 +1133,6 @@ view = x; | ||
} | ||
const IonRouterWrapped = reactRouterDom.withRouter(IonRouter); | ||
const IonReactRouterWrapped = reactRouterDom.withRouter(IonReactRouter); | ||
loader.defineCustomElements(window); | ||
Object.defineProperty(exports, 'setupConfig', { | ||
enumerable: true, | ||
get: function () { | ||
return core.setupConfig; | ||
} | ||
}); | ||
exports.IonActionSheet = IonActionSheet; | ||
@@ -953,2 +1142,3 @@ exports.IonAlert = IonAlert; | ||
exports.IonApp = IonApp; | ||
exports.IonAppInner = IonAppInner; | ||
exports.IonAvatar = IonAvatar; | ||
@@ -1006,2 +1196,3 @@ exports.IonBackButton = IonBackButton; | ||
exports.IonRange = IonRange; | ||
exports.IonReactRouter = IonReactRouterWrapped; | ||
exports.IonRefresher = IonRefresher; | ||
@@ -1012,3 +1203,2 @@ exports.IonRefresherContent = IonRefresherContent; | ||
exports.IonRippleEffect = IonRippleEffect; | ||
exports.IonRouter = IonRouterWrapped; | ||
exports.IonRouterOutlet = IonRouterOutlet; | ||
@@ -1041,2 +1231,3 @@ exports.IonRouterOutletInner = IonRouterOutletInner; | ||
exports.IonVirtualScroll = IonVirtualScroll; | ||
exports.IonicContext = IonicContext; | ||
exports.useIonViewDidEnter = useIonViewDidEnter; | ||
@@ -1046,2 +1237,3 @@ exports.useIonViewDidLeave = useIonViewDidLeave; | ||
exports.useIonViewWillLeave = useIonViewWillLeave; | ||
exports.useIonicConfig = useIonicConfig; | ||
exports.withIonLifeCycle = withIonLifeCycle; |
export { AlertButton, AlertInput } from '@ionic/core'; | ||
export { IonApp } from './IonApp'; | ||
export * from './proxies'; | ||
@@ -12,4 +13,6 @@ export { IonAlert } from './IonAlert'; | ||
export { IonTabBar } from './navigation/IonTabBar'; | ||
export { IonRouterOutlet } from './navigation/IonRouterOutlet'; | ||
export { IonBackButton } from './navigation/IonBackButton'; | ||
export { IonRouterWrapped as IonRouter } from './navigation/IonRouter'; | ||
export { IonRouterOutlet } from './navigation/routing/IonRouterOutlet'; | ||
export { IonReactRouterWrapped as IonReactRouter } from './navigation/routing/ReactRouter/IonReactRouter'; | ||
export { IonicContext } from './utils/IonicContext'; | ||
export { useIonicConfig } from './utils/utilHooks'; |
import { JSX as LocalJSX } from '@ionic/core'; | ||
import React from 'react'; | ||
import { NavContext } from './NavContext'; | ||
import { NavContext } from './routing/NavContext'; | ||
declare type BackButtonProps = LocalJSX.IonBackButton & {}; | ||
@@ -5,0 +5,0 @@ export declare class IonBackButton extends React.Component<BackButtonProps> { |
import React from 'react'; | ||
import { DefaultIonLifeCycleContext } from '../../lifecycle/IonLifeCycleContext'; | ||
import { NavContext } from './NavContext'; | ||
import { NavContext } from './routing/NavContext'; | ||
interface StackItemManagerProps { | ||
@@ -5,0 +5,0 @@ id: string; |
export declare const dashToPascalCase: (str: string) => string; | ||
export declare function generateUniqueId(): string; | ||
export * from './attachEventProps'; | ||
export * from './IonicContext'; | ||
export * from './utilHooks'; |
export * from './components'; | ||
export * from './types'; | ||
export * from './lifecycle'; | ||
export { setupConfig } from '@ionic/core'; |
{ | ||
"name": "@ionic/react", | ||
"version": "0.0.6-5", | ||
"version": "0.0.6-6", | ||
"description": "React specific wrapper for @ionic/core", | ||
@@ -5,0 +5,0 @@ "keywords": [ |
Sorry, the diff of this file is too big to display
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
471019
42
4629