@ionic/react
Advanced tools
Comparing version 0.0.8-0 to 0.0.8-1
import { defineCustomElements } from '@ionic/core/loader'; | ||
import React from 'react'; | ||
import React, { useContext } from 'react'; | ||
import { __rest } from 'tslib'; | ||
import ReactDom from 'react-dom'; | ||
import { NavContext, IonLifeCycleContext } from '@ionic/react-core'; | ||
import { isPlatform, getPlatforms, alertController, loadingController, toastController, actionSheetController, modalController, popoverController } from '@ionic/core'; | ||
import { withRouter } from 'react-router'; | ||
import { matchPath, Route, Redirect, Switch, withRouter as withRouter$1, BrowserRouter } from 'react-router-dom'; | ||
import { addIcons } from 'ionicons'; | ||
@@ -107,3 +106,3 @@ import { close, reorder, menu, arrowForward, arrowBack, arrowDown, search, closeCircle } from 'ionicons/icons'; | ||
function createReactComponent(tagName, attributeValues = []) { | ||
function createReactComponent(tagName, attributeValues = [], hrefComponent = false) { | ||
const displayName = dashToPascalCase(tagName); | ||
@@ -113,2 +112,3 @@ class ReactComponent extends React.Component { | ||
super(props); | ||
this.handleClick = this.handleClick.bind(this); | ||
} | ||
@@ -125,2 +125,9 @@ static get displayName() { | ||
} | ||
handleClick(e) { | ||
const { href, target, routerDirection } = this.props; | ||
if ((href && this.context.hasIonicRouter()) && !target) { | ||
e.preventDefault(); | ||
this.context.navigate(href, routerDirection); | ||
} | ||
} | ||
render() { | ||
@@ -134,5 +141,21 @@ const _a = this.props, { children, forwardedRef } = _a, cProps = __rest(_a, ["children", "forwardedRef"]); | ||
}, {}); | ||
return React.createElement(tagName, Object.assign({}, propsWithoutAttributeValues, { ref: forwardedRef }), children); | ||
const newProps = Object.assign({}, propsWithoutAttributeValues, { ref: forwardedRef }); | ||
if (hrefComponent) { | ||
if (newProps.onClick) { | ||
const oldClick = newProps.onClick; | ||
newProps.onClick = (e) => { | ||
oldClick(e); | ||
if (!e.defaultPrevented) { | ||
this.handleClick(e); | ||
} | ||
}; | ||
} | ||
else { | ||
newProps.onClick = this.handleClick; | ||
} | ||
} | ||
return React.createElement(tagName, newProps, children); | ||
} | ||
} | ||
ReactComponent.contextType = NavContext; | ||
function forwardRef(props, ref) { | ||
@@ -147,6 +170,4 @@ return React.createElement(ReactComponent, Object.assign({}, props, { forwardedRef: ref })); | ||
const IonTabBarInner = /*@__PURE__*/ createReactComponent('ion-tab-bar'); | ||
const IonRouterOutletInner = /*@__PURE__*/ createReactComponent('ion-router-outlet'); | ||
const IonBackButtonInner = /*@__PURE__*/ createReactComponent('ion-back-button'); | ||
const IonAppInner = /*@__PURE__*/ createReactComponent('ion-app'); | ||
const IonItemInner = /*@__PURE__*/ createReactComponent('ion-item'); | ||
@@ -326,5 +347,5 @@ class Platform { | ||
const IonBadge = /*@__PURE__*/ createReactComponent('ion-badge'); | ||
const IonButton = /*@__PURE__*/ createReactComponent('ion-button'); | ||
const IonButton = /*@__PURE__*/ createReactComponent('ion-button', [], true); | ||
const IonButtons = /*@__PURE__*/ createReactComponent('ion-buttons'); | ||
const IonCard = /*@__PURE__*/ createReactComponent('ion-card'); | ||
const IonCard = /*@__PURE__*/ createReactComponent('ion-card', [], true); | ||
const IonCardContent = /*@__PURE__*/ createReactComponent('ion-card-content'); | ||
@@ -340,3 +361,3 @@ const IonCardHeader = /*@__PURE__*/ createReactComponent('ion-card-header'); | ||
const IonFab = /*@__PURE__*/ createReactComponent('ion-fab'); | ||
const IonFabButton = /*@__PURE__*/ createReactComponent('ion-fab-button'); | ||
const IonFabButton = /*@__PURE__*/ createReactComponent('ion-fab-button', [], true); | ||
const IonFabList = /*@__PURE__*/ createReactComponent('ion-fab-list'); | ||
@@ -349,5 +370,6 @@ const IonFooter = /*@__PURE__*/ createReactComponent('ion-footer'); | ||
const IonInput = /*@__PURE__*/ createReactComponent('ion-input'); | ||
const IonItem = /*@__PURE__*/ createReactComponent('ion-item', [], true); | ||
const IonItemDivider = /*@__PURE__*/ createReactComponent('ion-item-divider'); | ||
const IonItemGroup = /*@__PURE__*/ createReactComponent('ion-item-group'); | ||
const IonItemOption = /*@__PURE__*/ createReactComponent('ion-item-option'); | ||
const IonItemOption = /*@__PURE__*/ createReactComponent('ion-item-option', [], true); | ||
const IonItemOptions = /*@__PURE__*/ createReactComponent('ion-item-options'); | ||
@@ -374,2 +396,3 @@ const IonItemSliding = /*@__PURE__*/ createReactComponent('ion-item-sliding'); | ||
const IonRippleEffect = /*@__PURE__*/ createReactComponent('ion-ripple-effect'); | ||
const IonRouterOutlet = /*@__PURE__*/ createReactComponent('ion-router-outlet'); | ||
const IonRow = /*@__PURE__*/ createReactComponent('ion-row'); | ||
@@ -490,3 +513,3 @@ const IonSearchbar = /*@__PURE__*/ createReactComponent('ion-searchbar'); | ||
class TabBar extends React.Component { | ||
class IonTabBarUnwrapped extends React.Component { | ||
constructor(props) { | ||
@@ -498,7 +521,7 @@ super(props); | ||
this.state.tabs[e.detail.tab].currentHref; | ||
this.props.history.push(targetUrl); | ||
this.props.navigate(targetUrl); | ||
}; | ||
this.renderChild = (activeTab) => (child) => { | ||
if (child != null && typeof child === 'object' && child.props && child.type === IonTabButton) { | ||
const href = (child.props.tab === activeTab) ? this.props.location.pathname : (this.state.tabs[child.props.tab].currentHref); | ||
const href = (child.props.tab === activeTab) ? this.props.currentPath : (this.state.tabs[child.props.tab].currentHref); | ||
return React.cloneElement(child, { | ||
@@ -529,5 +552,5 @@ href, | ||
const href = state.tabs[key].originalHref; | ||
return props.location.pathname.startsWith(href); | ||
return props.currentPath.startsWith(href); | ||
}); | ||
if (!activeTab || (activeTab === state.activeTab && state.tabs[activeTab].currentHref === props.location.pathname)) { | ||
if (!activeTab || (activeTab === state.activeTab && state.tabs[activeTab].currentHref === props.currentPath)) { | ||
return null; | ||
@@ -539,3 +562,3 @@ } | ||
originalHref: state.tabs[activeTab].originalHref, | ||
currentHref: props.location.pathname | ||
currentHref: props.currentPath | ||
} }) | ||
@@ -548,251 +571,9 @@ }; | ||
} | ||
const IonTabBar = /*@__PURE__*/ withRouter(TabBar); | ||
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({ | ||
onIonViewWillEnter: () => { }, | ||
ionViewWillEnter: () => { }, | ||
onIonViewDidEnter: () => { }, | ||
ionViewDidEnter: () => { }, | ||
onIonViewWillLeave: () => { }, | ||
ionViewWillLeave: () => { }, | ||
onIonViewDidLeave: () => { }, | ||
ionViewDidLeave: () => { } | ||
}); | ||
class DefaultIonLifeCycleContext { | ||
onIonViewWillEnter(callback) { | ||
this.ionViewWillEnterCallback = callback; | ||
} | ||
ionViewWillEnter() { | ||
if (this.ionViewWillEnterCallback) { | ||
this.ionViewWillEnterCallback(); | ||
} | ||
} | ||
onIonViewDidEnter(callback) { | ||
this.ionViewDidEnterCallback = callback; | ||
} | ||
ionViewDidEnter() { | ||
if (this.ionViewDidEnterCallback) { | ||
this.ionViewDidEnterCallback(); | ||
} | ||
} | ||
onIonViewWillLeave(callback) { | ||
this.ionViewWillLeaveCallback = callback; | ||
} | ||
ionViewWillLeave() { | ||
if (this.ionViewWillLeaveCallback) { | ||
this.ionViewWillLeaveCallback(); | ||
} | ||
} | ||
onIonViewDidLeave(callback) { | ||
this.ionViewDidLeaveCallback = callback; | ||
} | ||
ionViewDidLeave() { | ||
if (this.ionViewDidLeaveCallback) { | ||
this.ionViewDidLeaveCallback(); | ||
} | ||
this.componentCanBeDestroyed(); | ||
} | ||
onComponentCanBeDestroyed(callback) { | ||
this.componentCanBeDestroyedCallback = callback; | ||
} | ||
componentCanBeDestroyed() { | ||
if (this.componentCanBeDestroyedCallback) { | ||
this.componentCanBeDestroyedCallback(); | ||
} | ||
} | ||
} | ||
class ViewInternal extends React.Component { | ||
constructor(props) { | ||
super(props); | ||
this.state = { | ||
ref: null | ||
}; | ||
} | ||
componentDidMount() { | ||
const { forwardedRef } = this.props; | ||
this.setState({ ref: forwardedRef }); | ||
if (forwardedRef && forwardedRef.current) { | ||
forwardedRef.current.addEventListener('ionViewWillEnter', this.ionViewWillEnterHandler.bind(this)); | ||
forwardedRef.current.addEventListener('ionViewDidEnter', this.ionViewDidEnterHandler.bind(this)); | ||
forwardedRef.current.addEventListener('ionViewWillLeave', this.ionViewWillLeaveHandler.bind(this)); | ||
forwardedRef.current.addEventListener('ionViewDidLeave', this.ionViewDidLeaveHandler.bind(this)); | ||
} | ||
} | ||
componentWillUnmount() { | ||
const { forwardedRef } = this.props; | ||
if (forwardedRef && forwardedRef.current) { | ||
forwardedRef.current.removeEventListener('ionViewWillEnter', this.ionViewWillEnterHandler.bind(this)); | ||
forwardedRef.current.removeEventListener('ionViewDidEnter', this.ionViewDidEnterHandler.bind(this)); | ||
forwardedRef.current.removeEventListener('ionViewWillLeave', this.ionViewWillLeaveHandler.bind(this)); | ||
forwardedRef.current.removeEventListener('ionViewDidLeave', this.ionViewDidLeaveHandler.bind(this)); | ||
} | ||
} | ||
ionViewWillEnterHandler() { | ||
this.context.ionViewWillEnter(); | ||
} | ||
ionViewDidEnterHandler() { | ||
this.context.ionViewDidEnter(); | ||
} | ||
ionViewWillLeaveHandler() { | ||
this.context.ionViewWillLeave(); | ||
} | ||
ionViewDidLeaveHandler() { | ||
this.context.ionViewDidLeave(); | ||
} | ||
render() { | ||
const _a = this.props, { className, children, forwardedRef } = _a, rest = __rest(_a, ["className", "children", "forwardedRef"]); | ||
const { ref } = this.state; | ||
return (React.createElement("div", Object.assign({ className: className ? `ion-page ${className}` : 'ion-page', ref: forwardedRef }, rest), ref && children)); | ||
} | ||
} | ||
ViewInternal.contextType = IonLifeCycleContext; | ||
function forwardRef$1(props, ref) { | ||
return React.createElement(ViewInternal, Object.assign({ forwardedRef: ref }, props)); | ||
} | ||
forwardRef$1.displayName = 'View'; | ||
const View = /*@__PURE__*/ React.forwardRef(forwardRef$1); | ||
const NavContext = /*@__PURE__*/ React.createContext({ | ||
viewStacks: {}, | ||
hideView: () => { navContextNotFoundError(); }, | ||
goBack: () => { navContextNotFoundError(); }, | ||
setupIonRouter: () => { navContextNotFoundError(); }, | ||
removeViewStack: () => { navContextNotFoundError(); }, | ||
renderChild: () => { navContextNotFoundError(); }, | ||
transitionView: () => { navContextNotFoundError(); }, | ||
navigate: () => { navContextNotFoundError(); }, | ||
hasIonicRouter: () => false | ||
}); | ||
function navContextNotFoundError() { | ||
console.error('IonReactRouter not found, did you add it to the app?'); | ||
} | ||
const withIonLifeCycle = (WrappedComponent) => { | ||
return class IonLifeCycle extends React.Component { | ||
constructor(props) { | ||
super(props); | ||
this.componentRef = React.createRef(); | ||
} | ||
componentDidMount() { | ||
this.context.onIonViewWillEnter(() => { | ||
if (this.componentRef.current.ionViewWillEnter) { | ||
this.componentRef.current.ionViewWillEnter(); | ||
} | ||
}); | ||
this.context.onIonViewDidEnter(() => { | ||
if (this.componentRef.current.ionViewDidEnter) { | ||
this.componentRef.current.ionViewDidEnter(); | ||
} | ||
}); | ||
this.context.onIonViewWillLeave(() => { | ||
if (this.componentRef.current.ionViewWillLeave) { | ||
this.componentRef.current.ionViewWillLeave(); | ||
} | ||
}); | ||
this.context.onIonViewDidLeave(() => { | ||
if (this.componentRef.current.ionViewDidLeave) { | ||
this.componentRef.current.ionViewDidLeave(); | ||
} | ||
}); | ||
} | ||
render() { | ||
return (React.createElement(IonLifeCycleContext.Consumer, null, context => { | ||
this.context = context; | ||
return (React.createElement(WrappedComponent, Object.assign({ ref: this.componentRef }, this.props))); | ||
})); | ||
} | ||
}; | ||
const IonTabBar = (props) => { | ||
const context = useContext(NavContext); | ||
return (React.createElement(IonTabBarUnwrapped, Object.assign({}, props, { navigate: (path) => { | ||
context.navigate(path); | ||
}, currentPath: context.getLocation().pathname }), props.children)); | ||
}; | ||
const useIonViewWillEnter = (callback) => { | ||
const value = React.useContext(IonLifeCycleContext); | ||
value.onIonViewWillEnter(callback); | ||
}; | ||
const useIonViewDidEnter = (callback) => { | ||
const value = React.useContext(IonLifeCycleContext); | ||
value.onIonViewDidEnter(callback); | ||
}; | ||
const useIonViewWillLeave = (callback) => { | ||
const value = React.useContext(IonLifeCycleContext); | ||
value.onIonViewWillLeave(callback); | ||
}; | ||
const useIonViewDidLeave = (callback) => { | ||
const value = React.useContext(IonLifeCycleContext); | ||
value.onIonViewDidLeave(callback); | ||
}; | ||
class ViewItemManager extends React.Component { | ||
constructor(props) { | ||
super(props); | ||
this.ionLifeCycleContext = new DefaultIonLifeCycleContext(); | ||
this._isMounted = false; | ||
this.state = { | ||
show: true | ||
}; | ||
this.ionLifeCycleContext.onComponentCanBeDestroyed(() => { | ||
if (!this.props.mount) { | ||
if (this._isMounted) { | ||
this.setState({ | ||
show: false | ||
}, () => { | ||
this.context.hideView(this.props.id); | ||
}); | ||
} | ||
} | ||
}); | ||
} | ||
componentDidMount() { | ||
this._isMounted = true; | ||
} | ||
componentWillUnmount() { | ||
this._isMounted = false; | ||
} | ||
render() { | ||
const { show } = this.state; | ||
return (React.createElement(IonLifeCycleContext.Provider, { value: this.ionLifeCycleContext }, show && this.props.children)); | ||
} | ||
} | ||
// TODO: treeshake | ||
ViewItemManager.contextType = NavContext; | ||
class IonRouterOutlet extends React.Component { | ||
constructor(props) { | ||
super(props); | ||
this.containerEl = React.createRef(); | ||
this.id = this.props.id || generateUniqueId$1(); | ||
} | ||
componentDidMount() { | ||
this.context.setupIonRouter(this.id, this.props.children, this.containerEl.current); | ||
} | ||
componentWillUnmount() { | ||
this.context.removeViewStack(this.id); | ||
} | ||
render() { | ||
return (React.createElement(NavContext.Consumer, null, context => { | ||
this.context = context; | ||
const viewStack = context.viewStacks[this.id]; | ||
const activeId = viewStack ? viewStack.activeId : ''; | ||
const views = (viewStack || { views: [] }).views.filter(x => x.show); | ||
return (React.createElement(IonRouterOutletInner, { "data-id": this.id, ref: this.containerEl }, views.map((item) => { | ||
let props = {}; | ||
if (item.id === activeId) { | ||
props = { | ||
'className': ' ion-page-invisible' | ||
}; | ||
} | ||
return (React.createElement(ViewItemManager, { id: item.id, key: item.key, mount: item.mount }, | ||
React.createElement(View, Object.assign({ ref: item.ref }, props), this.context.renderChild(item)))); | ||
}))); | ||
})); | ||
} | ||
} | ||
const hostStyles = { | ||
@@ -816,2 +597,6 @@ display: 'flex', | ||
class IonTabs extends React.Component { | ||
constructor(props) { | ||
super(props); | ||
this.routerOutletRef = React.createRef(); | ||
} | ||
render() { | ||
@@ -831,8 +616,10 @@ let outlet; | ||
}); | ||
const NavManager = this.context.getViewManager(); | ||
return (React.createElement("div", { style: hostStyles }, | ||
tabBar.props.slot === 'top' ? tabBar : null, | ||
React.createElement("div", { style: tabsInner, className: "tabs-inner" }, outlet), | ||
React.createElement("div", { style: tabsInner, className: "tabs-inner" }, this.context.hasIonicRouter() ? (React.createElement(NavManager, null, outlet)) : (React.createElement(React.Fragment, null, outlet))), | ||
tabBar.props.slot === 'bottom' ? tabBar : null)); | ||
} | ||
} | ||
IonTabs.contextType = NavContext; | ||
@@ -858,318 +645,2 @@ class IonBackButton extends React.Component { | ||
class IonItemInternal extends React.Component { | ||
constructor(props) { | ||
super(props); | ||
this.handleClick = this.handleClick.bind(this); | ||
} | ||
handleClick(e) { | ||
if ((this.props.href && this.context.hasIonicRouter()) && !this.props.target) { | ||
e.preventDefault(); | ||
this.context.navigate(this.props.href, this.props.routerDirection); | ||
} | ||
} | ||
render() { | ||
const props = __rest(this.props, []); | ||
return (React.createElement(IonItemInner, Object.assign({ onClick: this.handleClick }, props), this.props.children)); | ||
} | ||
} | ||
IonItemInternal.contextType = NavContext; | ||
function forwardRef$2(props, ref) { | ||
return React.createElement(IonItemInternal, Object.assign({ forwardedRef: ref }, props)); | ||
} | ||
forwardRef$2.displayName = 'IonItem'; | ||
const IonItem = /*@__PURE__*/ React.forwardRef(forwardRef$2); | ||
class IonNavManager extends React.Component { | ||
constructor(props) { | ||
super(props); | ||
this.goBack = (defaultHref) => { | ||
const { view: leavingView } = this.findViewInfoByLocation(this.props.location, this.state.viewStacks); | ||
if (leavingView) { | ||
const { view: enteringView } = this.findViewInfoById(leavingView.prevId, this.state.viewStacks); | ||
if (enteringView) { | ||
this.props.history.replace(enteringView.routeData.match.url, { direction: 'back' }); | ||
} | ||
else { | ||
this.props.history.replace(defaultHref, { direction: 'back' }); | ||
} | ||
} | ||
else { | ||
this.props.history.replace(defaultHref, { direction: 'back' }); | ||
} | ||
}; | ||
this.state = { | ||
viewStacks: {}, | ||
hideView: this.hideView.bind(this), | ||
setupIonRouter: this.setupIonRouter.bind(this), | ||
removeViewStack: this.removeViewStack.bind(this), | ||
renderChild: this.renderChild.bind(this), | ||
goBack: this.goBack.bind(this), | ||
transitionView: this.transitionView.bind(this), | ||
navigate: this.navigate.bind(this), | ||
hasIonicRouter: () => true | ||
}; | ||
} | ||
componentWillMount() { | ||
this.listenUnregisterCallback = this.props.history.listen(this.historyChange.bind(this)); | ||
} | ||
hideView(viewId) { | ||
const viewStacks = Object.assign({}, this.state.viewStacks); | ||
const { view } = this.findViewInfoById(viewId, viewStacks); | ||
if (view) { | ||
view.show = false; | ||
view.key = generateUniqueId(); | ||
this.setState({ | ||
viewStacks | ||
}); | ||
} | ||
} | ||
historyChange(location, action) { | ||
this.setActiveView(location, action); | ||
} | ||
findViewInfoByLocation(location, viewStacks) { | ||
let view; | ||
let match; | ||
let viewStack; | ||
const keys = Object.keys(viewStacks); | ||
keys.some(key => { | ||
const vs = viewStacks[key]; | ||
return vs.views.some(x => { | ||
const matchProps = { | ||
exact: x.routeData.childProps.exact, | ||
path: x.routeData.childProps.path || x.routeData.childProps.from, | ||
component: x.routeData.childProps.component | ||
}; | ||
match = matchPath(location.pathname, matchProps); | ||
if (match) { | ||
view = x; | ||
viewStack = vs; | ||
return true; | ||
} | ||
return false; | ||
}); | ||
}); | ||
const result = { view, viewStack, match }; | ||
return result; | ||
} | ||
findViewInfoById(id, viewStacks) { | ||
let view; | ||
let viewStack; | ||
const keys = Object.keys(viewStacks); | ||
keys.some(key => { | ||
const vs = viewStacks[key]; | ||
view = vs.views.find(x => x.id === id); | ||
if (view) { | ||
viewStack = vs; | ||
return true; | ||
} | ||
else { | ||
return false; | ||
} | ||
}); | ||
return { view, viewStack }; | ||
} | ||
setActiveView(location, action) { | ||
const viewStacks = Object.assign({}, this.state.viewStacks); | ||
const { view: enteringView, viewStack: enteringViewStack, match } = this.findViewInfoByLocation(location, viewStacks); | ||
let direction = location.state && location.state.direction; | ||
if (!enteringViewStack) { | ||
return; | ||
} | ||
const { view: leavingView } = this.findViewInfoById(this.activeViewId, viewStacks); | ||
if (leavingView && leavingView.routeData.match.url === location.pathname) { | ||
return; | ||
} | ||
if (enteringView) { | ||
/** | ||
* If the page is being pushed into the stack by another view, | ||
* record the view that originally directed to the new view for back button purposes. | ||
*/ | ||
if (!enteringView.show && action === 'PUSH') { | ||
enteringView.prevId = leavingView && leavingView.id; | ||
} | ||
enteringView.show = true; | ||
enteringView.mount = true; | ||
enteringView.routeData.match = match; | ||
enteringViewStack.activeId = enteringView.id; | ||
this.activeViewId = enteringView.id; | ||
if (leavingView) { | ||
this.prevViewId = leavingView.id; | ||
if (leavingView.routeData.match.params.tab === enteringView.routeData.match.params.tab) { | ||
if (action === 'PUSH') { | ||
direction = direction || 'forward'; | ||
} | ||
else { | ||
direction = direction || 'back'; | ||
leavingView.mount = false; | ||
} | ||
} | ||
/** | ||
* If the leaving view is a Redirect, take it out of the rendering phase. | ||
*/ | ||
if (leavingView.element.type === Route && leavingView.element.props.render) { | ||
if (leavingView.element.props.render().type === Redirect) { | ||
leavingView.mount = false; | ||
leavingView.show = false; | ||
} | ||
} | ||
else if (leavingView.element.type === Redirect) { | ||
leavingView.mount = false; | ||
leavingView.show = false; | ||
} | ||
} | ||
this.setState({ | ||
viewStacks | ||
}, () => { | ||
const enteringEl = enteringView.ref && enteringView.ref.current ? enteringView.ref.current : undefined; | ||
const leavingEl = leavingView && leavingView.ref && leavingView.ref.current ? leavingView.ref.current : undefined; | ||
this.transitionView(enteringEl, leavingEl, enteringViewStack.routerOutlet, leavingEl && leavingEl.innerHTML !== '' ? direction : undefined); // Don't animate from an empty view | ||
}); | ||
} | ||
} | ||
componentWillUnmount() { | ||
this.listenUnregisterCallback(); | ||
} | ||
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 matchProps = { | ||
exact: child.props.exact, | ||
path: child.props.path || child.props.from, | ||
component: child.props.component | ||
}; | ||
const match = matchPath(location.pathname, matchProps); | ||
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; | ||
} | ||
} | ||
navigate(path, direction) { | ||
this.props.history.push(path, { direction }); | ||
} | ||
registerViewStack(stack, activeId, stackItems, routerOutlet, location) { | ||
this.setState((prevState) => { | ||
const prevViewStacks = Object.assign({}, prevState.viewStacks); | ||
prevViewStacks[stack] = { | ||
activeId: activeId, | ||
views: stackItems, | ||
routerOutlet | ||
}; | ||
return { | ||
viewStacks: prevViewStacks | ||
}; | ||
}, () => { | ||
const { view: activeView } = this.findViewInfoById(activeId, this.state.viewStacks); | ||
if (activeView) { | ||
this.prevViewId = this.activeViewId; | ||
this.activeViewId = activeView.id; | ||
const direction = location.state && location.state.direction; | ||
const { view: prevView } = this.findViewInfoById(this.prevViewId, this.state.viewStacks); | ||
this.transitionView(activeView.ref.current, prevView && prevView.ref.current || undefined, routerOutlet, direction); | ||
} | ||
}); | ||
} | ||
; | ||
removeViewStack(stack) { | ||
const viewStacks = Object.assign({}, this.state.viewStacks); | ||
delete viewStacks[stack]; | ||
this.setState({ | ||
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(this.props.location.pathname, x.routeData.childProps); | ||
if (match) { | ||
view = x; | ||
return true; | ||
} | ||
return false; | ||
}); | ||
return view; | ||
} | ||
transitionView(enteringEl, leavingEl, ionRouterOuter, direction) { | ||
/** | ||
* Super hacky workaround to make sure ionRouterOutlet is available | ||
* since transitionView might be called before IonRouterOutlet is fully mounted | ||
*/ | ||
if (ionRouterOuter && ionRouterOuter.componentOnReady) { | ||
this.commitView(enteringEl, leavingEl, ionRouterOuter, direction); | ||
} | ||
else { | ||
setTimeout(() => { | ||
this.transitionView(enteringEl, leavingEl, ionRouterOuter, direction); | ||
}, 10); | ||
} | ||
} | ||
async commitView(enteringEl, leavingEl, ionRouterOuter, direction) { | ||
await ionRouterOuter.componentOnReady(); | ||
await ionRouterOuter.commit(enteringEl, leavingEl, { | ||
deepWait: true, | ||
duration: direction === undefined ? 0 : undefined, | ||
direction: direction, | ||
showGoBack: direction === 'forward', | ||
progressAnimation: false | ||
}); | ||
if (leavingEl && (enteringEl !== leavingEl)) { | ||
/** | ||
* add hidden attributes | ||
*/ | ||
leavingEl.classList.add('ion-page-hidden'); | ||
leavingEl.setAttribute('aria-hidden', 'true'); | ||
} | ||
} | ||
render() { | ||
return (React.createElement(NavContext.Provider, { value: this.state }, this.props.children)); | ||
} | ||
} | ||
const IonNavManagerWithRouter = withRouter$1(IonNavManager); | ||
IonNavManagerWithRouter.displayName = 'IonNavManager'; | ||
class IonReactRouter extends React.Component { | ||
render() { | ||
const _a = this.props, { children } = _a, props = __rest(_a, ["children"]); | ||
return (React.createElement(BrowserRouter, Object.assign({}, props), | ||
React.createElement(IonNavManagerWithRouter, null, children))); | ||
} | ||
} | ||
defineCustomElements(window); | ||
@@ -1196,2 +667,56 @@ // Icons that are used by internal components | ||
export { IonActionSheet, IonAlert, IonAnchor, 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, 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, IonReactRouter, IonRefresher, IonRefresherContent, IonReorder, IonReorderGroup, IonRippleEffect, IonRouterOutlet, IonRow, IonSearchbar, IonSegment, IonSegmentButton, IonSelect, IonSelectOption, IonSelectPopover, IonSkeletonText, IonSlide, IonSlides, IonSpinner, IonSplitPane, IonTab, IonTabBar, IonTabButton, IonTabs, IonText, IonTextarea, IonThumbnail, IonTitle, IonToast, IonToggle, IonToolbar, IonVirtualScroll, IonicContext, useIonViewDidEnter, useIonViewDidLeave, useIonViewWillEnter, useIonViewWillLeave, useIonicConfig, withIonLifeCycle }; | ||
const withIonLifeCycle = (WrappedComponent) => { | ||
return class IonLifeCycle extends React.Component { | ||
constructor(props) { | ||
super(props); | ||
this.componentRef = React.createRef(); | ||
} | ||
componentDidMount() { | ||
this.context.onIonViewWillEnter(() => { | ||
if (this.componentRef.current.ionViewWillEnter) { | ||
this.componentRef.current.ionViewWillEnter(); | ||
} | ||
}); | ||
this.context.onIonViewDidEnter(() => { | ||
if (this.componentRef.current.ionViewDidEnter) { | ||
this.componentRef.current.ionViewDidEnter(); | ||
} | ||
}); | ||
this.context.onIonViewWillLeave(() => { | ||
if (this.componentRef.current.ionViewWillLeave) { | ||
this.componentRef.current.ionViewWillLeave(); | ||
} | ||
}); | ||
this.context.onIonViewDidLeave(() => { | ||
if (this.componentRef.current.ionViewDidLeave) { | ||
this.componentRef.current.ionViewDidLeave(); | ||
} | ||
}); | ||
} | ||
render() { | ||
return (React.createElement(IonLifeCycleContext.Consumer, null, context => { | ||
this.context = context; | ||
return (React.createElement(WrappedComponent, Object.assign({ ref: this.componentRef }, this.props))); | ||
})); | ||
} | ||
}; | ||
}; | ||
const useIonViewWillEnter = (callback) => { | ||
const value = React.useContext(IonLifeCycleContext); | ||
value.onIonViewWillEnter(callback); | ||
}; | ||
const useIonViewDidEnter = (callback) => { | ||
const value = React.useContext(IonLifeCycleContext); | ||
value.onIonViewDidEnter(callback); | ||
}; | ||
const useIonViewWillLeave = (callback) => { | ||
const value = React.useContext(IonLifeCycleContext); | ||
value.onIonViewWillLeave(callback); | ||
}; | ||
const useIonViewDidLeave = (callback) => { | ||
const value = React.useContext(IonLifeCycleContext); | ||
value.onIonViewDidLeave(callback); | ||
}; | ||
export { IonActionSheet, IonAlert, IonAnchor, 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, IonInput, IonItem, IonItemDivider, IonItemGroup, IonItemOption, IonItemOptions, IonItemSliding, IonLabel, IonList, IonListHeader, IonLoading, IonMenu, IonMenuButton, IonMenuToggle, IonModal, IonNav, IonNote, IonPage, IonPicker, IonPickerColumn, IonPopover, IonProgressBar, IonRadio, IonRadioGroup, IonRange, IonRefresher, IonRefresherContent, IonReorder, IonReorderGroup, IonRippleEffect, IonRouterOutlet, IonRow, IonSearchbar, IonSegment, IonSegmentButton, IonSelect, IonSelectOption, IonSelectPopover, IonSkeletonText, IonSlide, IonSlides, IonSpinner, IonSplitPane, IonTab, IonTabBar, IonTabButton, IonTabs, IonText, IonTextarea, IonThumbnail, IonTitle, IonToast, IonToggle, IonToolbar, IonVirtualScroll, IonicContext, useIonViewDidEnter, useIonViewDidLeave, useIonViewWillEnter, useIonViewWillLeave, useIonicConfig, withIonLifeCycle }; |
@@ -8,8 +8,8 @@ 'use strict'; | ||
var loader = require('@ionic/core/loader'); | ||
var React = _interopDefault(require('react')); | ||
var React = require('react'); | ||
var React__default = _interopDefault(React); | ||
var tslib_1 = require('tslib'); | ||
var ReactDom = _interopDefault(require('react-dom')); | ||
var reactCore = require('@ionic/react-core'); | ||
var core = require('@ionic/core'); | ||
var reactRouter = require('react-router'); | ||
var reactRouterDom = require('react-router-dom'); | ||
var ionicons = require('ionicons'); | ||
@@ -93,3 +93,3 @@ var icons = require('ionicons/icons'); | ||
const IonicContext = /*@__PURE__*/ React.createContext({ | ||
const IonicContext = /*@__PURE__*/ React__default.createContext({ | ||
getConfig: () => { }, | ||
@@ -101,3 +101,3 @@ setConfig: () => { }, | ||
const useIonicConfig = () => { | ||
const value = React.useContext(IonicContext); | ||
const value = React__default.useContext(IonicContext); | ||
const config = value.getConfig() || {}; | ||
@@ -116,7 +116,8 @@ const hook = [config, value.setConfig]; | ||
function createReactComponent(tagName, attributeValues = []) { | ||
function createReactComponent(tagName, attributeValues = [], hrefComponent = false) { | ||
const displayName = dashToPascalCase(tagName); | ||
class ReactComponent extends React.Component { | ||
class ReactComponent extends React__default.Component { | ||
constructor(props) { | ||
super(props); | ||
this.handleClick = this.handleClick.bind(this); | ||
} | ||
@@ -133,2 +134,9 @@ static get displayName() { | ||
} | ||
handleClick(e) { | ||
const { href, target, routerDirection } = this.props; | ||
if ((href && this.context.hasIonicRouter()) && !target) { | ||
e.preventDefault(); | ||
this.context.navigate(href, routerDirection); | ||
} | ||
} | ||
render() { | ||
@@ -142,10 +150,26 @@ const _a = this.props, { children, forwardedRef } = _a, cProps = tslib_1.__rest(_a, ["children", "forwardedRef"]); | ||
}, {}); | ||
return React.createElement(tagName, Object.assign({}, propsWithoutAttributeValues, { ref: forwardedRef }), children); | ||
const newProps = Object.assign({}, propsWithoutAttributeValues, { ref: forwardedRef }); | ||
if (hrefComponent) { | ||
if (newProps.onClick) { | ||
const oldClick = newProps.onClick; | ||
newProps.onClick = (e) => { | ||
oldClick(e); | ||
if (!e.defaultPrevented) { | ||
this.handleClick(e); | ||
} | ||
}; | ||
} | ||
else { | ||
newProps.onClick = this.handleClick; | ||
} | ||
} | ||
return React__default.createElement(tagName, newProps, children); | ||
} | ||
} | ||
ReactComponent.contextType = reactCore.NavContext; | ||
function forwardRef(props, ref) { | ||
return React.createElement(ReactComponent, Object.assign({}, props, { forwardedRef: ref })); | ||
return React__default.createElement(ReactComponent, Object.assign({}, props, { forwardedRef: ref })); | ||
} | ||
forwardRef.displayName = displayName; | ||
return React.forwardRef(forwardRef); | ||
return React__default.forwardRef(forwardRef); | ||
} | ||
@@ -155,6 +179,4 @@ | ||
const IonTabBarInner = /*@__PURE__*/ createReactComponent('ion-tab-bar'); | ||
const IonRouterOutletInner = /*@__PURE__*/ createReactComponent('ion-router-outlet'); | ||
const IonBackButtonInner = /*@__PURE__*/ createReactComponent('ion-back-button'); | ||
const IonAppInner = /*@__PURE__*/ createReactComponent('ion-app'); | ||
const IonItemInner = /*@__PURE__*/ createReactComponent('ion-item'); | ||
@@ -309,3 +331,3 @@ class Platform { | ||
class IonApp extends React.Component { | ||
class IonApp extends React__default.Component { | ||
constructor(props) { | ||
@@ -321,4 +343,4 @@ super(props); | ||
render() { | ||
return (React.createElement(IonicContext.Provider, { value: this.state }, | ||
React.createElement(IonAppInner, null, this.props.children))); | ||
return (React__default.createElement(IonicContext.Provider, { value: this.state }, | ||
React__default.createElement(IonAppInner, null, this.props.children))); | ||
} | ||
@@ -336,5 +358,5 @@ } | ||
const IonBadge = /*@__PURE__*/ createReactComponent('ion-badge'); | ||
const IonButton = /*@__PURE__*/ createReactComponent('ion-button'); | ||
const IonButton = /*@__PURE__*/ createReactComponent('ion-button', [], true); | ||
const IonButtons = /*@__PURE__*/ createReactComponent('ion-buttons'); | ||
const IonCard = /*@__PURE__*/ createReactComponent('ion-card'); | ||
const IonCard = /*@__PURE__*/ createReactComponent('ion-card', [], true); | ||
const IonCardContent = /*@__PURE__*/ createReactComponent('ion-card-content'); | ||
@@ -350,3 +372,3 @@ const IonCardHeader = /*@__PURE__*/ createReactComponent('ion-card-header'); | ||
const IonFab = /*@__PURE__*/ createReactComponent('ion-fab'); | ||
const IonFabButton = /*@__PURE__*/ createReactComponent('ion-fab-button'); | ||
const IonFabButton = /*@__PURE__*/ createReactComponent('ion-fab-button', [], true); | ||
const IonFabList = /*@__PURE__*/ createReactComponent('ion-fab-list'); | ||
@@ -359,5 +381,6 @@ const IonFooter = /*@__PURE__*/ createReactComponent('ion-footer'); | ||
const IonInput = /*@__PURE__*/ createReactComponent('ion-input'); | ||
const IonItem = /*@__PURE__*/ createReactComponent('ion-item', [], true); | ||
const IonItemDivider = /*@__PURE__*/ createReactComponent('ion-item-divider'); | ||
const IonItemGroup = /*@__PURE__*/ createReactComponent('ion-item-group'); | ||
const IonItemOption = /*@__PURE__*/ createReactComponent('ion-item-option'); | ||
const IonItemOption = /*@__PURE__*/ createReactComponent('ion-item-option', [], true); | ||
const IonItemOptions = /*@__PURE__*/ createReactComponent('ion-item-options'); | ||
@@ -384,2 +407,3 @@ const IonItemSliding = /*@__PURE__*/ createReactComponent('ion-item-sliding'); | ||
const IonRippleEffect = /*@__PURE__*/ createReactComponent('ion-ripple-effect'); | ||
const IonRouterOutlet = /*@__PURE__*/ createReactComponent('ion-router-outlet'); | ||
const IonRow = /*@__PURE__*/ createReactComponent('ion-row'); | ||
@@ -407,3 +431,3 @@ const IonSearchbar = /*@__PURE__*/ createReactComponent('ion-searchbar'); | ||
const dismissEventName = `on${displayName}DidDismiss`; | ||
return class ReactControllerComponent extends React.Component { | ||
return class ReactControllerComponent extends React__default.Component { | ||
constructor(props) { | ||
@@ -451,3 +475,3 @@ super(props); | ||
const dismissEventName = `on${displayName}DidDismiss`; | ||
return class ReactOverlayComponent extends React.Component { | ||
return class ReactOverlayComponent extends React__default.Component { | ||
constructor(props) { | ||
@@ -494,11 +518,11 @@ super(props); | ||
var { children, forwardedRef, className } = _a, props = tslib_1.__rest(_a, ["children", "forwardedRef", "className"]); | ||
return (React.createElement("div", Object.assign({ className: className ? `ion-page ${className}` : 'ion-page', ref: forwardedRef }, props), children)); | ||
return (React__default.createElement("div", Object.assign({ className: className ? `ion-page ${className}` : 'ion-page', ref: forwardedRef }, props), children)); | ||
}; | ||
function forwardRef(props, ref) { | ||
return React.createElement(IonPageInternal, Object.assign({}, props, { forwardedRef: ref })); | ||
return React__default.createElement(IonPageInternal, Object.assign({}, props, { forwardedRef: ref })); | ||
} | ||
forwardRef.displayName = 'IonPage'; | ||
const IonPage = /*@__PURE__*/ React.forwardRef(forwardRef); | ||
const IonPage = /*@__PURE__*/ React__default.forwardRef(forwardRef); | ||
class TabBar extends React.Component { | ||
class IonTabBarUnwrapped extends React__default.Component { | ||
constructor(props) { | ||
@@ -510,8 +534,8 @@ super(props); | ||
this.state.tabs[e.detail.tab].currentHref; | ||
this.props.history.push(targetUrl); | ||
this.props.navigate(targetUrl); | ||
}; | ||
this.renderChild = (activeTab) => (child) => { | ||
if (child != null && typeof child === 'object' && child.props && child.type === IonTabButton) { | ||
const href = (child.props.tab === activeTab) ? this.props.location.pathname : (this.state.tabs[child.props.tab].currentHref); | ||
return React.cloneElement(child, { | ||
const href = (child.props.tab === activeTab) ? this.props.currentPath : (this.state.tabs[child.props.tab].currentHref); | ||
return React__default.cloneElement(child, { | ||
href, | ||
@@ -524,3 +548,3 @@ onIonTabButtonClick: this.onTabButtonClick | ||
const tabActiveUrls = {}; | ||
React.Children.forEach(this.props.children, (child) => { | ||
React__default.Children.forEach(this.props.children, (child) => { | ||
if (child != null && typeof child === 'object' && child.props && child.type === IonTabButton) { | ||
@@ -542,5 +566,5 @@ tabActiveUrls[child.props.tab] = { | ||
const href = state.tabs[key].originalHref; | ||
return props.location.pathname.startsWith(href); | ||
return props.currentPath.startsWith(href); | ||
}); | ||
if (!activeTab || (activeTab === state.activeTab && state.tabs[activeTab].currentHref === props.location.pathname)) { | ||
if (!activeTab || (activeTab === state.activeTab && state.tabs[activeTab].currentHref === props.currentPath)) { | ||
return null; | ||
@@ -552,3 +576,3 @@ } | ||
originalHref: state.tabs[activeTab].originalHref, | ||
currentHref: props.location.pathname | ||
currentHref: props.currentPath | ||
} }) | ||
@@ -558,254 +582,12 @@ }; | ||
render() { | ||
return (React.createElement(IonTabBarInner, Object.assign({}, this.props, { selectedTab: this.state.activeTab }), React.Children.map(this.props.children, this.renderChild(this.state.activeTab)))); | ||
return (React__default.createElement(IonTabBarInner, Object.assign({}, this.props, { selectedTab: this.state.activeTab }), React__default.Children.map(this.props.children, this.renderChild(this.state.activeTab)))); | ||
} | ||
} | ||
const IonTabBar = /*@__PURE__*/ reactRouter.withRouter(TabBar); | ||
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({ | ||
onIonViewWillEnter: () => { }, | ||
ionViewWillEnter: () => { }, | ||
onIonViewDidEnter: () => { }, | ||
ionViewDidEnter: () => { }, | ||
onIonViewWillLeave: () => { }, | ||
ionViewWillLeave: () => { }, | ||
onIonViewDidLeave: () => { }, | ||
ionViewDidLeave: () => { } | ||
}); | ||
class DefaultIonLifeCycleContext { | ||
onIonViewWillEnter(callback) { | ||
this.ionViewWillEnterCallback = callback; | ||
} | ||
ionViewWillEnter() { | ||
if (this.ionViewWillEnterCallback) { | ||
this.ionViewWillEnterCallback(); | ||
} | ||
} | ||
onIonViewDidEnter(callback) { | ||
this.ionViewDidEnterCallback = callback; | ||
} | ||
ionViewDidEnter() { | ||
if (this.ionViewDidEnterCallback) { | ||
this.ionViewDidEnterCallback(); | ||
} | ||
} | ||
onIonViewWillLeave(callback) { | ||
this.ionViewWillLeaveCallback = callback; | ||
} | ||
ionViewWillLeave() { | ||
if (this.ionViewWillLeaveCallback) { | ||
this.ionViewWillLeaveCallback(); | ||
} | ||
} | ||
onIonViewDidLeave(callback) { | ||
this.ionViewDidLeaveCallback = callback; | ||
} | ||
ionViewDidLeave() { | ||
if (this.ionViewDidLeaveCallback) { | ||
this.ionViewDidLeaveCallback(); | ||
} | ||
this.componentCanBeDestroyed(); | ||
} | ||
onComponentCanBeDestroyed(callback) { | ||
this.componentCanBeDestroyedCallback = callback; | ||
} | ||
componentCanBeDestroyed() { | ||
if (this.componentCanBeDestroyedCallback) { | ||
this.componentCanBeDestroyedCallback(); | ||
} | ||
} | ||
} | ||
class ViewInternal extends React.Component { | ||
constructor(props) { | ||
super(props); | ||
this.state = { | ||
ref: null | ||
}; | ||
} | ||
componentDidMount() { | ||
const { forwardedRef } = this.props; | ||
this.setState({ ref: forwardedRef }); | ||
if (forwardedRef && forwardedRef.current) { | ||
forwardedRef.current.addEventListener('ionViewWillEnter', this.ionViewWillEnterHandler.bind(this)); | ||
forwardedRef.current.addEventListener('ionViewDidEnter', this.ionViewDidEnterHandler.bind(this)); | ||
forwardedRef.current.addEventListener('ionViewWillLeave', this.ionViewWillLeaveHandler.bind(this)); | ||
forwardedRef.current.addEventListener('ionViewDidLeave', this.ionViewDidLeaveHandler.bind(this)); | ||
} | ||
} | ||
componentWillUnmount() { | ||
const { forwardedRef } = this.props; | ||
if (forwardedRef && forwardedRef.current) { | ||
forwardedRef.current.removeEventListener('ionViewWillEnter', this.ionViewWillEnterHandler.bind(this)); | ||
forwardedRef.current.removeEventListener('ionViewDidEnter', this.ionViewDidEnterHandler.bind(this)); | ||
forwardedRef.current.removeEventListener('ionViewWillLeave', this.ionViewWillLeaveHandler.bind(this)); | ||
forwardedRef.current.removeEventListener('ionViewDidLeave', this.ionViewDidLeaveHandler.bind(this)); | ||
} | ||
} | ||
ionViewWillEnterHandler() { | ||
this.context.ionViewWillEnter(); | ||
} | ||
ionViewDidEnterHandler() { | ||
this.context.ionViewDidEnter(); | ||
} | ||
ionViewWillLeaveHandler() { | ||
this.context.ionViewWillLeave(); | ||
} | ||
ionViewDidLeaveHandler() { | ||
this.context.ionViewDidLeave(); | ||
} | ||
render() { | ||
const _a = this.props, { className, children, forwardedRef } = _a, rest = tslib_1.__rest(_a, ["className", "children", "forwardedRef"]); | ||
const { ref } = this.state; | ||
return (React.createElement("div", Object.assign({ className: className ? `ion-page ${className}` : 'ion-page', ref: forwardedRef }, rest), ref && children)); | ||
} | ||
} | ||
ViewInternal.contextType = IonLifeCycleContext; | ||
function forwardRef$1(props, ref) { | ||
return React.createElement(ViewInternal, Object.assign({ forwardedRef: ref }, props)); | ||
} | ||
forwardRef$1.displayName = 'View'; | ||
const View = /*@__PURE__*/ React.forwardRef(forwardRef$1); | ||
const NavContext = /*@__PURE__*/ React.createContext({ | ||
viewStacks: {}, | ||
hideView: () => { navContextNotFoundError(); }, | ||
goBack: () => { navContextNotFoundError(); }, | ||
setupIonRouter: () => { navContextNotFoundError(); }, | ||
removeViewStack: () => { navContextNotFoundError(); }, | ||
renderChild: () => { navContextNotFoundError(); }, | ||
transitionView: () => { navContextNotFoundError(); }, | ||
navigate: () => { navContextNotFoundError(); }, | ||
hasIonicRouter: () => false | ||
}); | ||
function navContextNotFoundError() { | ||
console.error('IonReactRouter not found, did you add it to the app?'); | ||
} | ||
const withIonLifeCycle = (WrappedComponent) => { | ||
return class IonLifeCycle extends React.Component { | ||
constructor(props) { | ||
super(props); | ||
this.componentRef = React.createRef(); | ||
} | ||
componentDidMount() { | ||
this.context.onIonViewWillEnter(() => { | ||
if (this.componentRef.current.ionViewWillEnter) { | ||
this.componentRef.current.ionViewWillEnter(); | ||
} | ||
}); | ||
this.context.onIonViewDidEnter(() => { | ||
if (this.componentRef.current.ionViewDidEnter) { | ||
this.componentRef.current.ionViewDidEnter(); | ||
} | ||
}); | ||
this.context.onIonViewWillLeave(() => { | ||
if (this.componentRef.current.ionViewWillLeave) { | ||
this.componentRef.current.ionViewWillLeave(); | ||
} | ||
}); | ||
this.context.onIonViewDidLeave(() => { | ||
if (this.componentRef.current.ionViewDidLeave) { | ||
this.componentRef.current.ionViewDidLeave(); | ||
} | ||
}); | ||
} | ||
render() { | ||
return (React.createElement(IonLifeCycleContext.Consumer, null, context => { | ||
this.context = context; | ||
return (React.createElement(WrappedComponent, Object.assign({ ref: this.componentRef }, this.props))); | ||
})); | ||
} | ||
}; | ||
const IonTabBar = (props) => { | ||
const context = React.useContext(reactCore.NavContext); | ||
return (React__default.createElement(IonTabBarUnwrapped, Object.assign({}, props, { navigate: (path) => { | ||
context.navigate(path); | ||
}, currentPath: context.getLocation().pathname }), props.children)); | ||
}; | ||
const useIonViewWillEnter = (callback) => { | ||
const value = React.useContext(IonLifeCycleContext); | ||
value.onIonViewWillEnter(callback); | ||
}; | ||
const useIonViewDidEnter = (callback) => { | ||
const value = React.useContext(IonLifeCycleContext); | ||
value.onIonViewDidEnter(callback); | ||
}; | ||
const useIonViewWillLeave = (callback) => { | ||
const value = React.useContext(IonLifeCycleContext); | ||
value.onIonViewWillLeave(callback); | ||
}; | ||
const useIonViewDidLeave = (callback) => { | ||
const value = React.useContext(IonLifeCycleContext); | ||
value.onIonViewDidLeave(callback); | ||
}; | ||
class ViewItemManager extends React.Component { | ||
constructor(props) { | ||
super(props); | ||
this.ionLifeCycleContext = new DefaultIonLifeCycleContext(); | ||
this._isMounted = false; | ||
this.state = { | ||
show: true | ||
}; | ||
this.ionLifeCycleContext.onComponentCanBeDestroyed(() => { | ||
if (!this.props.mount) { | ||
if (this._isMounted) { | ||
this.setState({ | ||
show: false | ||
}, () => { | ||
this.context.hideView(this.props.id); | ||
}); | ||
} | ||
} | ||
}); | ||
} | ||
componentDidMount() { | ||
this._isMounted = true; | ||
} | ||
componentWillUnmount() { | ||
this._isMounted = false; | ||
} | ||
render() { | ||
const { show } = this.state; | ||
return (React.createElement(IonLifeCycleContext.Provider, { value: this.ionLifeCycleContext }, show && this.props.children)); | ||
} | ||
} | ||
// TODO: treeshake | ||
ViewItemManager.contextType = NavContext; | ||
class IonRouterOutlet extends React.Component { | ||
constructor(props) { | ||
super(props); | ||
this.containerEl = React.createRef(); | ||
this.id = this.props.id || generateUniqueId$1(); | ||
} | ||
componentDidMount() { | ||
this.context.setupIonRouter(this.id, this.props.children, this.containerEl.current); | ||
} | ||
componentWillUnmount() { | ||
this.context.removeViewStack(this.id); | ||
} | ||
render() { | ||
return (React.createElement(NavContext.Consumer, null, context => { | ||
this.context = context; | ||
const viewStack = context.viewStacks[this.id]; | ||
const activeId = viewStack ? viewStack.activeId : ''; | ||
const views = (viewStack || { views: [] }).views.filter(x => x.show); | ||
return (React.createElement(IonRouterOutletInner, { "data-id": this.id, ref: this.containerEl }, views.map((item) => { | ||
let props = {}; | ||
if (item.id === activeId) { | ||
props = { | ||
'className': ' ion-page-invisible' | ||
}; | ||
} | ||
return (React.createElement(ViewItemManager, { id: item.id, key: item.key, mount: item.mount }, | ||
React.createElement(View, Object.assign({ ref: item.ref }, props), this.context.renderChild(item)))); | ||
}))); | ||
})); | ||
} | ||
} | ||
const hostStyles = { | ||
@@ -828,7 +610,11 @@ display: 'flex', | ||
}; | ||
class IonTabs extends React.Component { | ||
class IonTabs extends React__default.Component { | ||
constructor(props) { | ||
super(props); | ||
this.routerOutletRef = React__default.createRef(); | ||
} | ||
render() { | ||
let outlet; | ||
let tabBar; | ||
React.Children.forEach(this.props.children, (child) => { | ||
React__default.Children.forEach(this.props.children, (child) => { | ||
if (child == null || typeof child !== 'object' || !child.hasOwnProperty('type')) { | ||
@@ -844,10 +630,12 @@ return; | ||
}); | ||
return (React.createElement("div", { style: hostStyles }, | ||
const NavManager = this.context.getViewManager(); | ||
return (React__default.createElement("div", { style: hostStyles }, | ||
tabBar.props.slot === 'top' ? tabBar : null, | ||
React.createElement("div", { style: tabsInner, className: "tabs-inner" }, outlet), | ||
React__default.createElement("div", { style: tabsInner, className: "tabs-inner" }, this.context.hasIonicRouter() ? (React__default.createElement(NavManager, null, outlet)) : (React__default.createElement(React__default.Fragment, null, outlet))), | ||
tabBar.props.slot === 'bottom' ? tabBar : null)); | ||
} | ||
} | ||
IonTabs.contextType = reactCore.NavContext; | ||
class IonBackButton extends React.Component { | ||
class IonBackButton extends React__default.Component { | ||
constructor() { | ||
@@ -866,323 +654,7 @@ super(...arguments); | ||
render() { | ||
return (React.createElement(IonBackButtonInner, Object.assign({ onClick: this.clickButton }, this.props))); | ||
return (React__default.createElement(IonBackButtonInner, Object.assign({ onClick: this.clickButton }, this.props))); | ||
} | ||
} | ||
IonBackButton.contextType = NavContext; | ||
IonBackButton.contextType = reactCore.NavContext; | ||
class IonItemInternal extends React.Component { | ||
constructor(props) { | ||
super(props); | ||
this.handleClick = this.handleClick.bind(this); | ||
} | ||
handleClick(e) { | ||
if ((this.props.href && this.context.hasIonicRouter()) && !this.props.target) { | ||
e.preventDefault(); | ||
this.context.navigate(this.props.href, this.props.routerDirection); | ||
} | ||
} | ||
render() { | ||
const props = tslib_1.__rest(this.props, []); | ||
return (React.createElement(IonItemInner, Object.assign({ onClick: this.handleClick }, props), this.props.children)); | ||
} | ||
} | ||
IonItemInternal.contextType = NavContext; | ||
function forwardRef$2(props, ref) { | ||
return React.createElement(IonItemInternal, Object.assign({ forwardedRef: ref }, props)); | ||
} | ||
forwardRef$2.displayName = 'IonItem'; | ||
const IonItem = /*@__PURE__*/ React.forwardRef(forwardRef$2); | ||
class IonNavManager extends React.Component { | ||
constructor(props) { | ||
super(props); | ||
this.goBack = (defaultHref) => { | ||
const { view: leavingView } = this.findViewInfoByLocation(this.props.location, this.state.viewStacks); | ||
if (leavingView) { | ||
const { view: enteringView } = this.findViewInfoById(leavingView.prevId, this.state.viewStacks); | ||
if (enteringView) { | ||
this.props.history.replace(enteringView.routeData.match.url, { direction: 'back' }); | ||
} | ||
else { | ||
this.props.history.replace(defaultHref, { direction: 'back' }); | ||
} | ||
} | ||
else { | ||
this.props.history.replace(defaultHref, { direction: 'back' }); | ||
} | ||
}; | ||
this.state = { | ||
viewStacks: {}, | ||
hideView: this.hideView.bind(this), | ||
setupIonRouter: this.setupIonRouter.bind(this), | ||
removeViewStack: this.removeViewStack.bind(this), | ||
renderChild: this.renderChild.bind(this), | ||
goBack: this.goBack.bind(this), | ||
transitionView: this.transitionView.bind(this), | ||
navigate: this.navigate.bind(this), | ||
hasIonicRouter: () => true | ||
}; | ||
} | ||
componentWillMount() { | ||
this.listenUnregisterCallback = this.props.history.listen(this.historyChange.bind(this)); | ||
} | ||
hideView(viewId) { | ||
const viewStacks = Object.assign({}, this.state.viewStacks); | ||
const { view } = this.findViewInfoById(viewId, viewStacks); | ||
if (view) { | ||
view.show = false; | ||
view.key = generateUniqueId(); | ||
this.setState({ | ||
viewStacks | ||
}); | ||
} | ||
} | ||
historyChange(location, action) { | ||
this.setActiveView(location, action); | ||
} | ||
findViewInfoByLocation(location, viewStacks) { | ||
let view; | ||
let match; | ||
let viewStack; | ||
const keys = Object.keys(viewStacks); | ||
keys.some(key => { | ||
const vs = viewStacks[key]; | ||
return vs.views.some(x => { | ||
const matchProps = { | ||
exact: x.routeData.childProps.exact, | ||
path: x.routeData.childProps.path || x.routeData.childProps.from, | ||
component: x.routeData.childProps.component | ||
}; | ||
match = reactRouterDom.matchPath(location.pathname, matchProps); | ||
if (match) { | ||
view = x; | ||
viewStack = vs; | ||
return true; | ||
} | ||
return false; | ||
}); | ||
}); | ||
const result = { view, viewStack, match }; | ||
return result; | ||
} | ||
findViewInfoById(id, viewStacks) { | ||
let view; | ||
let viewStack; | ||
const keys = Object.keys(viewStacks); | ||
keys.some(key => { | ||
const vs = viewStacks[key]; | ||
view = vs.views.find(x => x.id === id); | ||
if (view) { | ||
viewStack = vs; | ||
return true; | ||
} | ||
else { | ||
return false; | ||
} | ||
}); | ||
return { view, viewStack }; | ||
} | ||
setActiveView(location, action) { | ||
const viewStacks = Object.assign({}, this.state.viewStacks); | ||
const { view: enteringView, viewStack: enteringViewStack, match } = this.findViewInfoByLocation(location, viewStacks); | ||
let direction = location.state && location.state.direction; | ||
if (!enteringViewStack) { | ||
return; | ||
} | ||
const { view: leavingView } = this.findViewInfoById(this.activeViewId, viewStacks); | ||
if (leavingView && leavingView.routeData.match.url === location.pathname) { | ||
return; | ||
} | ||
if (enteringView) { | ||
/** | ||
* If the page is being pushed into the stack by another view, | ||
* record the view that originally directed to the new view for back button purposes. | ||
*/ | ||
if (!enteringView.show && action === 'PUSH') { | ||
enteringView.prevId = leavingView && leavingView.id; | ||
} | ||
enteringView.show = true; | ||
enteringView.mount = true; | ||
enteringView.routeData.match = match; | ||
enteringViewStack.activeId = enteringView.id; | ||
this.activeViewId = enteringView.id; | ||
if (leavingView) { | ||
this.prevViewId = leavingView.id; | ||
if (leavingView.routeData.match.params.tab === enteringView.routeData.match.params.tab) { | ||
if (action === 'PUSH') { | ||
direction = direction || 'forward'; | ||
} | ||
else { | ||
direction = direction || 'back'; | ||
leavingView.mount = false; | ||
} | ||
} | ||
/** | ||
* If the leaving view is a Redirect, take it out of the rendering phase. | ||
*/ | ||
if (leavingView.element.type === reactRouterDom.Route && leavingView.element.props.render) { | ||
if (leavingView.element.props.render().type === reactRouterDom.Redirect) { | ||
leavingView.mount = false; | ||
leavingView.show = false; | ||
} | ||
} | ||
else if (leavingView.element.type === reactRouterDom.Redirect) { | ||
leavingView.mount = false; | ||
leavingView.show = false; | ||
} | ||
} | ||
this.setState({ | ||
viewStacks | ||
}, () => { | ||
const enteringEl = enteringView.ref && enteringView.ref.current ? enteringView.ref.current : undefined; | ||
const leavingEl = leavingView && leavingView.ref && leavingView.ref.current ? leavingView.ref.current : undefined; | ||
this.transitionView(enteringEl, leavingEl, enteringViewStack.routerOutlet, leavingEl && leavingEl.innerHTML !== '' ? direction : undefined); // Don't animate from an empty view | ||
}); | ||
} | ||
} | ||
componentWillUnmount() { | ||
this.listenUnregisterCallback(); | ||
} | ||
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 matchProps = { | ||
exact: child.props.exact, | ||
path: child.props.path || child.props.from, | ||
component: child.props.component | ||
}; | ||
const match = reactRouterDom.matchPath(location.pathname, matchProps); | ||
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; | ||
} | ||
} | ||
navigate(path, direction) { | ||
this.props.history.push(path, { direction }); | ||
} | ||
registerViewStack(stack, activeId, stackItems, routerOutlet, location) { | ||
this.setState((prevState) => { | ||
const prevViewStacks = Object.assign({}, prevState.viewStacks); | ||
prevViewStacks[stack] = { | ||
activeId: activeId, | ||
views: stackItems, | ||
routerOutlet | ||
}; | ||
return { | ||
viewStacks: prevViewStacks | ||
}; | ||
}, () => { | ||
const { view: activeView } = this.findViewInfoById(activeId, this.state.viewStacks); | ||
if (activeView) { | ||
this.prevViewId = this.activeViewId; | ||
this.activeViewId = activeView.id; | ||
const direction = location.state && location.state.direction; | ||
const { view: prevView } = this.findViewInfoById(this.prevViewId, this.state.viewStacks); | ||
this.transitionView(activeView.ref.current, prevView && prevView.ref.current || undefined, routerOutlet, direction); | ||
} | ||
}); | ||
} | ||
; | ||
removeViewStack(stack) { | ||
const viewStacks = Object.assign({}, this.state.viewStacks); | ||
delete viewStacks[stack]; | ||
this.setState({ | ||
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.routeData.childProps); | ||
if (match) { | ||
view = x; | ||
return true; | ||
} | ||
return false; | ||
}); | ||
return view; | ||
} | ||
transitionView(enteringEl, leavingEl, ionRouterOuter, direction) { | ||
/** | ||
* Super hacky workaround to make sure ionRouterOutlet is available | ||
* since transitionView might be called before IonRouterOutlet is fully mounted | ||
*/ | ||
if (ionRouterOuter && ionRouterOuter.componentOnReady) { | ||
this.commitView(enteringEl, leavingEl, ionRouterOuter, direction); | ||
} | ||
else { | ||
setTimeout(() => { | ||
this.transitionView(enteringEl, leavingEl, ionRouterOuter, direction); | ||
}, 10); | ||
} | ||
} | ||
async commitView(enteringEl, leavingEl, ionRouterOuter, direction) { | ||
await ionRouterOuter.componentOnReady(); | ||
await ionRouterOuter.commit(enteringEl, leavingEl, { | ||
deepWait: true, | ||
duration: direction === undefined ? 0 : undefined, | ||
direction: direction, | ||
showGoBack: direction === 'forward', | ||
progressAnimation: false | ||
}); | ||
if (leavingEl && (enteringEl !== leavingEl)) { | ||
/** | ||
* add hidden attributes | ||
*/ | ||
leavingEl.classList.add('ion-page-hidden'); | ||
leavingEl.setAttribute('aria-hidden', 'true'); | ||
} | ||
} | ||
render() { | ||
return (React.createElement(NavContext.Provider, { value: this.state }, this.props.children)); | ||
} | ||
} | ||
const IonNavManagerWithRouter = reactRouterDom.withRouter(IonNavManager); | ||
IonNavManagerWithRouter.displayName = 'IonNavManager'; | ||
class IonReactRouter extends React.Component { | ||
render() { | ||
const _a = this.props, { children } = _a, props = tslib_1.__rest(_a, ["children"]); | ||
return (React.createElement(reactRouterDom.BrowserRouter, Object.assign({}, props), | ||
React.createElement(IonNavManagerWithRouter, null, children))); | ||
} | ||
} | ||
loader.defineCustomElements(window); | ||
@@ -1209,2 +681,56 @@ // Icons that are used by internal components | ||
const withIonLifeCycle = (WrappedComponent) => { | ||
return class IonLifeCycle extends React__default.Component { | ||
constructor(props) { | ||
super(props); | ||
this.componentRef = React__default.createRef(); | ||
} | ||
componentDidMount() { | ||
this.context.onIonViewWillEnter(() => { | ||
if (this.componentRef.current.ionViewWillEnter) { | ||
this.componentRef.current.ionViewWillEnter(); | ||
} | ||
}); | ||
this.context.onIonViewDidEnter(() => { | ||
if (this.componentRef.current.ionViewDidEnter) { | ||
this.componentRef.current.ionViewDidEnter(); | ||
} | ||
}); | ||
this.context.onIonViewWillLeave(() => { | ||
if (this.componentRef.current.ionViewWillLeave) { | ||
this.componentRef.current.ionViewWillLeave(); | ||
} | ||
}); | ||
this.context.onIonViewDidLeave(() => { | ||
if (this.componentRef.current.ionViewDidLeave) { | ||
this.componentRef.current.ionViewDidLeave(); | ||
} | ||
}); | ||
} | ||
render() { | ||
return (React__default.createElement(reactCore.IonLifeCycleContext.Consumer, null, context => { | ||
this.context = context; | ||
return (React__default.createElement(WrappedComponent, Object.assign({ ref: this.componentRef }, this.props))); | ||
})); | ||
} | ||
}; | ||
}; | ||
const useIonViewWillEnter = (callback) => { | ||
const value = React__default.useContext(reactCore.IonLifeCycleContext); | ||
value.onIonViewWillEnter(callback); | ||
}; | ||
const useIonViewDidEnter = (callback) => { | ||
const value = React__default.useContext(reactCore.IonLifeCycleContext); | ||
value.onIonViewDidEnter(callback); | ||
}; | ||
const useIonViewWillLeave = (callback) => { | ||
const value = React__default.useContext(reactCore.IonLifeCycleContext); | ||
value.onIonViewWillLeave(callback); | ||
}; | ||
const useIonViewDidLeave = (callback) => { | ||
const value = React__default.useContext(reactCore.IonLifeCycleContext); | ||
value.onIonViewDidLeave(callback); | ||
}; | ||
exports.IonActionSheet = IonActionSheet; | ||
@@ -1247,3 +773,2 @@ exports.IonAlert = IonAlert; | ||
exports.IonLabel = IonLabel; | ||
exports.IonLifeCycleContext = IonLifeCycleContext; | ||
exports.IonList = IonList; | ||
@@ -1266,3 +791,2 @@ exports.IonListHeader = IonListHeader; | ||
exports.IonRange = IonRange; | ||
exports.IonReactRouter = IonReactRouter; | ||
exports.IonRefresher = IonRefresher; | ||
@@ -1269,0 +793,0 @@ exports.IonRefresherContent = IonRefresherContent; |
import React from 'react'; | ||
export declare function createReactComponent<PropType, ElementType>(tagName: string, attributeValues?: string[]): React.ForwardRefExoticComponent<React.PropsWithoutRef<PropType & { | ||
export declare function createReactComponent<PropType, ElementType>(tagName: string, attributeValues?: string[], hrefComponent?: boolean): React.ForwardRefExoticComponent<React.PropsWithoutRef<PropType & { | ||
ref?: React.RefObject<ElementType>; | ||
children?: React.ReactNode; | ||
}> & React.RefAttributes<ElementType>>; |
@@ -14,6 +14,3 @@ export { AlertButton, AlertInput } from '@ionic/core'; | ||
export { IonBackButton } from './navigation/IonBackButton'; | ||
export { IonItem } from './IonItem'; | ||
export { IonRouterOutlet } from './navigation/routing/IonRouterOutlet'; | ||
export { IonReactRouter } from './navigation/routing/ReactRouter/IonReactRouter'; | ||
export { IonicContext } from './utils/IonicContext'; | ||
export { useIonicConfig } from './utils/utilHooks'; |
@@ -8,6 +8,2 @@ /// <reference types="react" /> | ||
}, "hidden" | "dir" | "slot" | "style" | "title" | "contextmenu" | "mode" | "accessKey" | "autocapitalize" | "draggable" | "lang" | "spellcheck" | "className" | "id" | "prefix" | "children" | "innerHTML" | "contentEditable" | "inputMode" | "tabIndex" | "color" | "key" | "selectedTab" | "translucent" | "class" | "contenteditable" | "contextMenu" | "spellCheck" | "tabindex" | "inputmode" | "is" | "radioGroup" | "radiogroup" | "part" | "role" | "about" | "datatype" | "inlist" | "property" | "resource" | "typeof" | "vocab" | "autoCapitalize" | "autoCorrect" | "autocorrect" | "autoSave" | "autosave" | "itemProp" | "itemprop" | "itemScope" | "itemscope" | "itemType" | "itemtype" | "itemID" | "itemid" | "itemRef" | "itemref" | "results" | "security" | "unselectable" | "onCopy" | "onCopyCapture" | "onCut" | "onCutCapture" | "onPaste" | "onPasteCapture" | "onCompositionEnd" | "onCompositionEndCapture" | "onCompositionStart" | "onCompositionStartCapture" | "onCompositionUpdate" | "onCompositionUpdateCapture" | "onFocus" | "onFocusCapture" | "onBlur" | "onBlurCapture" | "onChange" | "onChangeCapture" | "onInput" | "onInputCapture" | "onReset" | "onResetCapture" | "onSubmit" | "onSubmitCapture" | "onInvalid" | "onInvalidCapture" | "onLoad" | "onLoadCapture" | "onError" | "onErrorCapture" | "onKeyDown" | "onKeyDownCapture" | "onKeyPress" | "onKeyPressCapture" | "onKeyUp" | "onKeyUpCapture" | "onAuxClick" | "onClick" | "onClickCapture" | "onContextMenu" | "onContextMenuCapture" | "onDblClick" | "onDblClickCapture" | "onDrag" | "onDragCapture" | "onDragEnd" | "onDragEndCapture" | "onDragEnter" | "onDragEnterCapture" | "onDragExit" | "onDragExitCapture" | "onDragLeave" | "onDragLeaveCapture" | "onDragOver" | "onDragOverCapture" | "onDragStart" | "onDragStartCapture" | "onDrop" | "onDropCapture" | "onMouseDown" | "onMouseDownCapture" | "onMouseEnter" | "onMouseLeave" | "onMouseMove" | "onMouseMoveCapture" | "onMouseOut" | "onMouseOutCapture" | "onMouseOver" | "onMouseOverCapture" | "onMouseUp" | "onMouseUpCapture" | "onTouchCancel" | "onTouchCancelCapture" | "onTouchEnd" | "onTouchEndCapture" | "onTouchMove" | "onTouchMoveCapture" | "onTouchStart" | "onTouchStartCapture" | "onPointerDown" | "onPointerDownCapture" | "onPointerMove" | "onPointerMoveCapture" | "onPointerUp" | "onPointerUpCapture" | "onPointerCancel" | "onPointerCancelCapture" | "onPointerEnter" | "onPointerEnterCapture" | "onPointerLeave" | "onPointerLeaveCapture" | "onPointerOver" | "onPointerOverCapture" | "onPointerOut" | "onPointerOutCapture" | "onGotPointerCapture" | "onGotPointerCaptureCapture" | "onLostPointerCapture" | "onLostPointerCaptureCapture" | "onScroll" | "onScrollCapture" | "onWheel" | "onWheelCapture" | "onAnimationStart" | "onAnimationStartCapture" | "onAnimationEnd" | "onAnimationEndCapture" | "onAnimationIteration" | "onAnimationIterationCapture" | "onTransitionEnd" | "onTransitionEndCapture"> & import("react").RefAttributes<HTMLIonTabBarElement>>; | ||
export declare const IonRouterOutletInner: import("react").ForwardRefExoticComponent<Pick<JSX.IonRouterOutlet & ReactProps & { | ||
ref?: import("react").RefObject<HTMLIonRouterOutletElement>; | ||
children?: import("react").ReactNode; | ||
}, "hidden" | "dir" | "slot" | "style" | "title" | "contextmenu" | "mode" | "animated" | "accessKey" | "autocapitalize" | "draggable" | "lang" | "spellcheck" | "className" | "id" | "prefix" | "children" | "innerHTML" | "contentEditable" | "inputMode" | "tabIndex" | "color" | "key" | "class" | "contenteditable" | "contextMenu" | "spellCheck" | "tabindex" | "inputmode" | "is" | "radioGroup" | "radiogroup" | "part" | "role" | "about" | "datatype" | "inlist" | "property" | "resource" | "typeof" | "vocab" | "autoCapitalize" | "autoCorrect" | "autocorrect" | "autoSave" | "autosave" | "itemProp" | "itemprop" | "itemScope" | "itemscope" | "itemType" | "itemtype" | "itemID" | "itemid" | "itemRef" | "itemref" | "results" | "security" | "unselectable" | "onCopy" | "onCopyCapture" | "onCut" | "onCutCapture" | "onPaste" | "onPasteCapture" | "onCompositionEnd" | "onCompositionEndCapture" | "onCompositionStart" | "onCompositionStartCapture" | "onCompositionUpdate" | "onCompositionUpdateCapture" | "onFocus" | "onFocusCapture" | "onBlur" | "onBlurCapture" | "onChange" | "onChangeCapture" | "onInput" | "onInputCapture" | "onReset" | "onResetCapture" | "onSubmit" | "onSubmitCapture" | "onInvalid" | "onInvalidCapture" | "onLoad" | "onLoadCapture" | "onError" | "onErrorCapture" | "onKeyDown" | "onKeyDownCapture" | "onKeyPress" | "onKeyPressCapture" | "onKeyUp" | "onKeyUpCapture" | "onAuxClick" | "onClick" | "onClickCapture" | "onContextMenu" | "onContextMenuCapture" | "onDblClick" | "onDblClickCapture" | "onDrag" | "onDragCapture" | "onDragEnd" | "onDragEndCapture" | "onDragEnter" | "onDragEnterCapture" | "onDragExit" | "onDragExitCapture" | "onDragLeave" | "onDragLeaveCapture" | "onDragOver" | "onDragOverCapture" | "onDragStart" | "onDragStartCapture" | "onDrop" | "onDropCapture" | "onMouseDown" | "onMouseDownCapture" | "onMouseEnter" | "onMouseLeave" | "onMouseMove" | "onMouseMoveCapture" | "onMouseOut" | "onMouseOutCapture" | "onMouseOver" | "onMouseOverCapture" | "onMouseUp" | "onMouseUpCapture" | "onTouchCancel" | "onTouchCancelCapture" | "onTouchEnd" | "onTouchEndCapture" | "onTouchMove" | "onTouchMoveCapture" | "onTouchStart" | "onTouchStartCapture" | "onPointerDown" | "onPointerDownCapture" | "onPointerMove" | "onPointerMoveCapture" | "onPointerUp" | "onPointerUpCapture" | "onPointerCancel" | "onPointerCancelCapture" | "onPointerEnter" | "onPointerEnterCapture" | "onPointerLeave" | "onPointerLeaveCapture" | "onPointerOver" | "onPointerOverCapture" | "onPointerOut" | "onPointerOutCapture" | "onGotPointerCapture" | "onGotPointerCaptureCapture" | "onLostPointerCapture" | "onLostPointerCaptureCapture" | "onScroll" | "onScrollCapture" | "onWheel" | "onWheelCapture" | "onAnimationStart" | "onAnimationStartCapture" | "onAnimationEnd" | "onAnimationEndCapture" | "onAnimationIteration" | "onAnimationIterationCapture" | "onTransitionEnd" | "onTransitionEndCapture" | "animation"> & import("react").RefAttributes<HTMLIonRouterOutletElement>>; | ||
export declare const IonBackButtonInner: import("react").ForwardRefExoticComponent<Pick<JSX.IonBackButton & ReactProps & { | ||
@@ -21,5 +17,1 @@ ref?: import("react").RefObject<HTMLIonBackButtonElement>; | ||
}, "hidden" | "dir" | "slot" | "style" | "title" | "contextmenu" | "accessKey" | "autocapitalize" | "draggable" | "lang" | "spellcheck" | "className" | "id" | "prefix" | "children" | "innerHTML" | "contentEditable" | "inputMode" | "tabIndex" | "color" | "key" | "class" | "contenteditable" | "contextMenu" | "spellCheck" | "tabindex" | "inputmode" | "is" | "radioGroup" | "radiogroup" | "part" | "role" | "about" | "datatype" | "inlist" | "property" | "resource" | "typeof" | "vocab" | "autoCapitalize" | "autoCorrect" | "autocorrect" | "autoSave" | "autosave" | "itemProp" | "itemprop" | "itemScope" | "itemscope" | "itemType" | "itemtype" | "itemID" | "itemid" | "itemRef" | "itemref" | "results" | "security" | "unselectable" | "onCopy" | "onCopyCapture" | "onCut" | "onCutCapture" | "onPaste" | "onPasteCapture" | "onCompositionEnd" | "onCompositionEndCapture" | "onCompositionStart" | "onCompositionStartCapture" | "onCompositionUpdate" | "onCompositionUpdateCapture" | "onFocus" | "onFocusCapture" | "onBlur" | "onBlurCapture" | "onChange" | "onChangeCapture" | "onInput" | "onInputCapture" | "onReset" | "onResetCapture" | "onSubmit" | "onSubmitCapture" | "onInvalid" | "onInvalidCapture" | "onLoad" | "onLoadCapture" | "onError" | "onErrorCapture" | "onKeyDown" | "onKeyDownCapture" | "onKeyPress" | "onKeyPressCapture" | "onKeyUp" | "onKeyUpCapture" | "onAuxClick" | "onClick" | "onClickCapture" | "onContextMenu" | "onContextMenuCapture" | "onDblClick" | "onDblClickCapture" | "onDrag" | "onDragCapture" | "onDragEnd" | "onDragEndCapture" | "onDragEnter" | "onDragEnterCapture" | "onDragExit" | "onDragExitCapture" | "onDragLeave" | "onDragLeaveCapture" | "onDragOver" | "onDragOverCapture" | "onDragStart" | "onDragStartCapture" | "onDrop" | "onDropCapture" | "onMouseDown" | "onMouseDownCapture" | "onMouseEnter" | "onMouseLeave" | "onMouseMove" | "onMouseMoveCapture" | "onMouseOut" | "onMouseOutCapture" | "onMouseOver" | "onMouseOverCapture" | "onMouseUp" | "onMouseUpCapture" | "onTouchCancel" | "onTouchCancelCapture" | "onTouchEnd" | "onTouchEndCapture" | "onTouchMove" | "onTouchMoveCapture" | "onTouchStart" | "onTouchStartCapture" | "onPointerDown" | "onPointerDownCapture" | "onPointerMove" | "onPointerMoveCapture" | "onPointerUp" | "onPointerUpCapture" | "onPointerCancel" | "onPointerCancelCapture" | "onPointerEnter" | "onPointerEnterCapture" | "onPointerLeave" | "onPointerLeaveCapture" | "onPointerOver" | "onPointerOverCapture" | "onPointerOut" | "onPointerOutCapture" | "onGotPointerCapture" | "onGotPointerCaptureCapture" | "onLostPointerCapture" | "onLostPointerCaptureCapture" | "onScroll" | "onScrollCapture" | "onWheel" | "onWheelCapture" | "onAnimationStart" | "onAnimationStartCapture" | "onAnimationEnd" | "onAnimationEndCapture" | "onAnimationIteration" | "onAnimationIterationCapture" | "onTransitionEnd" | "onTransitionEndCapture"> & import("react").RefAttributes<HTMLIonAppElement>>; | ||
export declare const IonItemInner: import("react").ForwardRefExoticComponent<Pick<JSX.IonItem & ReactProps & { | ||
ref?: import("react").RefObject<HTMLIonItemElement>; | ||
children?: import("react").ReactNode; | ||
}, "disabled" | "hidden" | "button" | "dir" | "slot" | "style" | "title" | "contextmenu" | "lines" | "mode" | "accessKey" | "autocapitalize" | "draggable" | "lang" | "spellcheck" | "className" | "id" | "prefix" | "children" | "innerHTML" | "contentEditable" | "inputMode" | "tabIndex" | "color" | "key" | "class" | "contenteditable" | "contextMenu" | "spellCheck" | "tabindex" | "inputmode" | "is" | "radioGroup" | "radiogroup" | "part" | "role" | "about" | "datatype" | "inlist" | "property" | "resource" | "typeof" | "vocab" | "autoCapitalize" | "autoCorrect" | "autocorrect" | "autoSave" | "autosave" | "itemProp" | "itemprop" | "itemScope" | "itemscope" | "itemType" | "itemtype" | "itemID" | "itemid" | "itemRef" | "itemref" | "results" | "security" | "unselectable" | "onCopy" | "onCopyCapture" | "onCut" | "onCutCapture" | "onPaste" | "onPasteCapture" | "onCompositionEnd" | "onCompositionEndCapture" | "onCompositionStart" | "onCompositionStartCapture" | "onCompositionUpdate" | "onCompositionUpdateCapture" | "onFocus" | "onFocusCapture" | "onBlur" | "onBlurCapture" | "onChange" | "onChangeCapture" | "onInput" | "onInputCapture" | "onReset" | "onResetCapture" | "onSubmit" | "onSubmitCapture" | "onInvalid" | "onInvalidCapture" | "onLoad" | "onLoadCapture" | "onError" | "onErrorCapture" | "onKeyDown" | "onKeyDownCapture" | "onKeyPress" | "onKeyPressCapture" | "onKeyUp" | "onKeyUpCapture" | "onAuxClick" | "onClick" | "onClickCapture" | "onContextMenu" | "onContextMenuCapture" | "onDblClick" | "onDblClickCapture" | "onDrag" | "onDragCapture" | "onDragEnd" | "onDragEndCapture" | "onDragEnter" | "onDragEnterCapture" | "onDragExit" | "onDragExitCapture" | "onDragLeave" | "onDragLeaveCapture" | "onDragOver" | "onDragOverCapture" | "onDragStart" | "onDragStartCapture" | "onDrop" | "onDropCapture" | "onMouseDown" | "onMouseDownCapture" | "onMouseEnter" | "onMouseLeave" | "onMouseMove" | "onMouseMoveCapture" | "onMouseOut" | "onMouseOutCapture" | "onMouseOver" | "onMouseOverCapture" | "onMouseUp" | "onMouseUpCapture" | "onTouchCancel" | "onTouchCancelCapture" | "onTouchEnd" | "onTouchEndCapture" | "onTouchMove" | "onTouchMoveCapture" | "onTouchStart" | "onTouchStartCapture" | "onPointerDown" | "onPointerDownCapture" | "onPointerMove" | "onPointerMoveCapture" | "onPointerUp" | "onPointerUpCapture" | "onPointerCancel" | "onPointerCancelCapture" | "onPointerEnter" | "onPointerEnterCapture" | "onPointerLeave" | "onPointerLeaveCapture" | "onPointerOver" | "onPointerOverCapture" | "onPointerOut" | "onPointerOutCapture" | "onGotPointerCapture" | "onGotPointerCaptureCapture" | "onLostPointerCapture" | "onLostPointerCaptureCapture" | "onScroll" | "onScrollCapture" | "onWheel" | "onWheelCapture" | "onAnimationStart" | "onAnimationStartCapture" | "onAnimationEnd" | "onAnimationEndCapture" | "onAnimationIteration" | "onAnimationIterationCapture" | "onTransitionEnd" | "onTransitionEndCapture" | "type" | "detail" | "detailIcon" | "download" | "href" | "rel" | "routerDirection" | "target"> & import("react").RefAttributes<HTMLIonItemElement>>; |
import { JSX as LocalJSX } from '@ionic/core'; | ||
import React from 'react'; | ||
import { NavContext } from './routing/NavContext'; | ||
import { NavContext } from '@ionic/react-core'; | ||
declare type BackButtonProps = LocalJSX.IonBackButton & {}; | ||
@@ -5,0 +5,0 @@ export declare class IonBackButton extends React.Component<BackButtonProps> { |
import React from 'react'; | ||
import { RouteComponentProps } from 'react-router'; | ||
import { JSX } from '@ionic/core'; | ||
declare type Props = RouteComponentProps & JSX.IonTabBar & { | ||
children: React.ReactNode; | ||
}; | ||
export declare const IonTabBar: React.ComponentClass<Pick<Props, "hidden" | "dir" | "slot" | "style" | "title" | "contextmenu" | "mode" | "accessKey" | "autocapitalize" | "draggable" | "lang" | "spellcheck" | "id" | "prefix" | "children" | "innerHTML" | "contentEditable" | "inputMode" | "tabIndex" | "color" | "key" | "ref" | "selectedTab" | "translucent" | "class" | "contenteditable" | "contextMenu" | "spellCheck" | "tabindex" | "inputmode" | "is" | "radioGroup" | "radiogroup" | "part" | "role" | "about" | "datatype" | "inlist" | "property" | "resource" | "typeof" | "vocab" | "autoCapitalize" | "autoCorrect" | "autocorrect" | "autoSave" | "autosave" | "itemProp" | "itemprop" | "itemScope" | "itemscope" | "itemType" | "itemtype" | "itemID" | "itemid" | "itemRef" | "itemref" | "results" | "security" | "unselectable" | "onCopy" | "onCopyCapture" | "onCut" | "onCutCapture" | "onPaste" | "onPasteCapture" | "onCompositionEnd" | "onCompositionEndCapture" | "onCompositionStart" | "onCompositionStartCapture" | "onCompositionUpdate" | "onCompositionUpdateCapture" | "onFocus" | "onFocusCapture" | "onBlur" | "onBlurCapture" | "onChange" | "onChangeCapture" | "onInput" | "onInputCapture" | "onReset" | "onResetCapture" | "onSubmit" | "onSubmitCapture" | "onInvalid" | "onInvalidCapture" | "onLoad" | "onLoadCapture" | "onError" | "onErrorCapture" | "onKeyDown" | "onKeyDownCapture" | "onKeyPress" | "onKeyPressCapture" | "onKeyUp" | "onKeyUpCapture" | "onAuxClick" | "onClick" | "onClickCapture" | "onContextMenu" | "onContextMenuCapture" | "onDblClick" | "onDblClickCapture" | "onDrag" | "onDragCapture" | "onDragEnd" | "onDragEndCapture" | "onDragEnter" | "onDragEnterCapture" | "onDragExit" | "onDragExitCapture" | "onDragLeave" | "onDragLeaveCapture" | "onDragOver" | "onDragOverCapture" | "onDragStart" | "onDragStartCapture" | "onDrop" | "onDropCapture" | "onMouseDown" | "onMouseDownCapture" | "onMouseEnter" | "onMouseLeave" | "onMouseMove" | "onMouseMoveCapture" | "onMouseOut" | "onMouseOutCapture" | "onMouseOver" | "onMouseOverCapture" | "onMouseUp" | "onMouseUpCapture" | "onTouchCancel" | "onTouchCancelCapture" | "onTouchEnd" | "onTouchEndCapture" | "onTouchMove" | "onTouchMoveCapture" | "onTouchStart" | "onTouchStartCapture" | "onPointerDown" | "onPointerDownCapture" | "onPointerMove" | "onPointerMoveCapture" | "onPointerUp" | "onPointerUpCapture" | "onPointerCancel" | "onPointerCancelCapture" | "onPointerEnter" | "onPointerEnterCapture" | "onPointerLeave" | "onPointerLeaveCapture" | "onPointerOver" | "onPointerOverCapture" | "onPointerOut" | "onPointerOutCapture" | "onGotPointerCapture" | "onGotPointerCaptureCapture" | "onLostPointerCapture" | "onLostPointerCaptureCapture" | "onScroll" | "onScrollCapture" | "onWheel" | "onWheelCapture" | "onAnimationStart" | "onAnimationStartCapture" | "onAnimationEnd" | "onAnimationEndCapture" | "onAnimationIteration" | "onAnimationIterationCapture" | "onTransitionEnd" | "onTransitionEndCapture">, any>; | ||
export {}; | ||
import { JSX as LocalJSX } from '@ionic/core'; | ||
export declare const IonTabBar: React.FC<LocalJSX.IonTabBar>; |
import React from 'react'; | ||
import { NavContext } from '@ionic/react-core'; | ||
declare type Props = { | ||
children: React.ReactNode; | ||
}; | ||
export declare class IonTabs extends React.Component<Props> { | ||
declare type State = {}; | ||
export declare class IonTabs extends React.Component<Props, State> { | ||
context: React.ContextType<typeof NavContext>; | ||
routerOutletRef: React.RefObject<HTMLIonRouterOutletElement>; | ||
constructor(props: Props); | ||
render(): JSX.Element; | ||
} | ||
export {}; |
export declare const dashToPascalCase: (str: string) => string; | ||
export declare function generateUniqueId(): string; |
export { withIonLifeCycle } from './IonLifeCycleHOC'; | ||
export { IonLifeCycleContext, IonLifeCycleContextInterface } from './IonLifeCycleContext'; | ||
export { useIonViewDidEnter, useIonViewDidLeave, useIonViewWillEnter, useIonViewWillLeave } from './hooks'; |
import React from 'react'; | ||
export declare const withIonLifeCycle: (WrappedComponent: React.ComponentType<any>) => { | ||
new (props: any): { | ||
context: import("./IonLifeCycleContext").IonLifeCycleContextInterface; | ||
context: import("@ionic/react-core").IonLifeCycleContextInterface; | ||
componentRef: React.RefObject<any>; | ||
@@ -6,0 +6,0 @@ componentDidMount(): void; |
{ | ||
"name": "@ionic/react", | ||
"version": "0.0.8-0", | ||
"version": "0.0.8-1", | ||
"description": "React specific wrapper for @ionic/core", | ||
@@ -28,3 +28,3 @@ "keywords": [ | ||
"compile:dev": "npm run tsc && rollup -c rollup.config.dev.js", | ||
"release": "np --any-branch --no-cleanup --yolo", | ||
"release": "np --any-branch --no-cleanup", | ||
"tsc": "tsc -p .", | ||
@@ -40,3 +40,4 @@ "test": "jest" | ||
"dependencies": { | ||
"@ionic/core": "4.7.0-dev.201907181900.97fec92", | ||
"@ionic/core": "^4.6.0", | ||
"@ionic/react-core": "0.0.8-1", | ||
"tslib": "^1.10.0" | ||
@@ -47,4 +48,2 @@ }, | ||
"react-dom": "^16.8.6", | ||
"react-router": "^5.0.1", | ||
"react-router-dom": "^5.0.1", | ||
"ionicons": "^4.6.2-0" | ||
@@ -66,4 +65,2 @@ }, | ||
"react-dom": "^16.8.6", | ||
"react-router": "^5.0.1", | ||
"react-router-dom": "^5.0.1", | ||
"react-testing-library": "^7.0.0", | ||
@@ -70,0 +67,0 @@ "rollup": "^1.14.6", |
Sorry, the diff of this file is too big to display
6
19
428345
36
3685
+ Added@ionic/react-core@0.0.8-1
+ Added@ionic/core@4.11.13(transitive)
+ Added@ionic/react-core@0.0.8-1(transitive)
- Removed@babel/runtime@7.24.7(transitive)
- Removed@ionic/core@4.7.0-dev.201907181900.97fec92(transitive)
- Removedhistory@4.10.1(transitive)
- Removedhoist-non-react-statics@3.3.2(transitive)
- Removedionicons@4.6.1(transitive)
- Removedisarray@0.0.1(transitive)
- Removedpath-to-regexp@1.8.0(transitive)
- Removedreact-router@5.3.4(transitive)
- Removedreact-router-dom@5.3.4(transitive)
- Removedregenerator-runtime@0.14.1(transitive)
- Removedresolve-pathname@3.0.0(transitive)
- Removedtiny-invariant@1.3.3(transitive)
- Removedtiny-warning@1.0.3(transitive)
- Removedvalue-equal@1.0.1(transitive)
Updated@ionic/core@^4.6.0