@ionic/react 8.3.3-dev.11728573902.1ddf07ff → 8.3.3-dev.11728940158.168f11a2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.js CHANGED
@@ -1260,8 +1260,6 @@ const IonNav = createForwardRef(IonNavInternal, 'IonNav');
1260
1260
  const IonTabsContext = React.createContext({
1261
1261
  activeTab: undefined,
1262
1262
  selectTab: () => false,
1263
- hasRouterOutlet: false,
1264
- tabBarProps: { ref: React.createRef() },
1265
1263
  });
1266
1264
 
1267
1265
  const HTMLElementSSR = (typeof HTMLElement !== 'undefined' ? HTMLElement : class {
@@ -1349,134 +1347,6 @@ class IonRouterOutletContainer extends React.Component {
1349
1347
  }
1350
1348
  const IonRouterOutlet = createForwardRef(IonRouterOutletContainer, 'IonRouterOutlet');
1351
1349
 
1352
- class IonTabsElement extends HTMLElementSSR {
1353
- constructor() {
1354
- super();
1355
- }
1356
- }
1357
- // TODO(FW-2959): types
1358
- if (typeof window !== 'undefined' && window.customElements) {
1359
- const element = window.customElements.get('ion-tabs');
1360
- if (!element) {
1361
- window.customElements.define('ion-tabs', IonTabsElement);
1362
- }
1363
- }
1364
- const IonTabs = /*@__PURE__*/ (() => class extends React.Component {
1365
- constructor(props) {
1366
- super(props);
1367
- this.routerOutletRef = React.createRef();
1368
- this.tabBarRef = React.createRef();
1369
- this.ionTabContextState = {
1370
- activeTab: undefined,
1371
- selectTab: () => false,
1372
- hasRouterOutlet: false,
1373
- /**
1374
- * Tab bar can be used as a standalone component,
1375
- * so the props can not be passed directly to the
1376
- * tab bar component. Instead, props will be
1377
- * passed through the context.
1378
- */
1379
- tabBarProps: { ref: this.tabBarRef },
1380
- };
1381
- }
1382
- componentDidMount() {
1383
- if (this.tabBarRef.current) {
1384
- // Grab initial value
1385
- this.ionTabContextState.activeTab = this.tabBarRef.current.state.activeTab;
1386
- // Override method
1387
- this.tabBarRef.current.setActiveTabOnContext = (tab) => {
1388
- this.ionTabContextState.activeTab = tab;
1389
- };
1390
- this.ionTabContextState.selectTab = this.tabBarRef.current.selectTab;
1391
- }
1392
- }
1393
- renderTabsInner(children, outlet) {
1394
- return (React.createElement(IonTabsInner, Object.assign({}, this.props), React.Children.map(children, (child) => {
1395
- if (React.isValidElement(child)) {
1396
- const isRouterOutlet = child.type === IonRouterOutlet ||
1397
- child.type.isRouterOutlet ||
1398
- (child.type === Fragment && child.props.children[0].type === IonRouterOutlet);
1399
- if (isRouterOutlet) {
1400
- /**
1401
- * The modified outlet needs to be returned to include
1402
- * the ref.
1403
- */
1404
- return outlet;
1405
- }
1406
- }
1407
- return child;
1408
- })));
1409
- }
1410
- render() {
1411
- let outlet;
1412
- // Check if IonTabs has any IonTab children
1413
- let hasTab = false;
1414
- const _a = this.props, { className, onIonTabsDidChange, onIonTabsWillChange } = _a, props = __rest(_a, ["className", "onIonTabsDidChange", "onIonTabsWillChange"]);
1415
- const children = typeof this.props.children === 'function'
1416
- ? this.props.children(this.ionTabContextState)
1417
- : this.props.children;
1418
- React.Children.forEach(children, (child) => {
1419
- // eslint-disable-next-line no-prototype-builtins
1420
- if (child == null || typeof child !== 'object' || !child.hasOwnProperty('type')) {
1421
- return;
1422
- }
1423
- if (child.type === IonRouterOutlet || child.type.isRouterOutlet) {
1424
- outlet = React.cloneElement(child);
1425
- }
1426
- else if (child.type === Fragment && child.props.children[0].type === IonRouterOutlet) {
1427
- outlet = React.cloneElement(child.props.children[0]);
1428
- }
1429
- else if (child.type === IonTab) {
1430
- /**
1431
- * This indicates that IonTabs will be using a basic tab-based navigation
1432
- * without the history stack or URL updates associated with the router.
1433
- */
1434
- hasTab = true;
1435
- }
1436
- this.ionTabContextState.hasRouterOutlet = !!outlet;
1437
- let childProps = Object.assign({}, this.ionTabContextState.tabBarProps);
1438
- /**
1439
- * Only pass these props
1440
- * down from IonTabs to IonTabBar
1441
- * if they are defined, otherwise
1442
- * if you have a handler set on
1443
- * IonTabBar it will be overridden.
1444
- */
1445
- if (onIonTabsDidChange !== undefined) {
1446
- childProps = Object.assign(Object.assign({}, childProps), { onIonTabsDidChange });
1447
- }
1448
- if (onIonTabsWillChange !== undefined) {
1449
- childProps = Object.assign(Object.assign({}, childProps), { onIonTabsWillChange });
1450
- }
1451
- this.ionTabContextState.tabBarProps = childProps;
1452
- });
1453
- if (!outlet && !hasTab) {
1454
- throw new Error('IonTabs must contain an IonRouterOutlet or an IonTab');
1455
- }
1456
- if (outlet && hasTab) {
1457
- throw new Error('IonTabs cannot contain an IonRouterOutlet and an IonTab at the same time');
1458
- }
1459
- if (hasTab) {
1460
- return React.createElement(IonTabsInner, Object.assign({}, this.props));
1461
- }
1462
- /**
1463
- * TODO(ROU-11051)
1464
- *
1465
- * There is no error handling for the case where there
1466
- * is no associated Route for the given IonTabButton.
1467
- *
1468
- * More investigation is needed to determine how to
1469
- * handle this to prevent any overwriting of the
1470
- * IonTabButton's onClick handler and how the routing
1471
- * is handled.
1472
- */
1473
- return (React.createElement(IonTabsContext.Provider, { value: this.ionTabContextState }, this.context.hasIonicRouter() ? (React.createElement(PageManager, Object.assign({ className: className ? `${className}` : '', routeInfo: this.context.routeInfo }, props), this.renderTabsInner(children, outlet))) : (this.renderTabsInner(children, outlet))));
1474
- }
1475
- static get contextType() {
1476
- return NavContext;
1477
- }
1478
- })();
1479
-
1480
1350
  const IonTabButton = /*@__PURE__*/ (() => class extends React.Component {
1481
1351
  constructor(props) {
1482
1352
  super(props);
@@ -1626,16 +1496,15 @@ class IonTabBarUnwrapped extends React.PureComponent {
1626
1496
  };
1627
1497
  }
1628
1498
  onTabButtonClick(e, onClickFn) {
1629
- var _a;
1499
+ var _a, _b;
1630
1500
  const tappedTab = this.state.tabs[e.detail.tab];
1631
1501
  const originalHref = tappedTab.originalHref;
1632
- const hasRouterOutlet = (_a = this.props.tabsContext) === null || _a === void 0 ? void 0 : _a.hasRouterOutlet;
1633
1502
  /**
1634
1503
  * If the router outlet is not defined, then the tabs is being used
1635
1504
  * as a basic tab navigation without the router. In this case, we
1636
1505
  * don't want to update the href else the URL will change.
1637
1506
  */
1638
- const currentHref = hasRouterOutlet ? e.detail.href : '';
1507
+ const currentHref = ((_a = this.props.routerOutletRef) === null || _a === void 0 ? void 0 : _a.current) ? e.detail.href : '';
1639
1508
  const { activeTab: prevActiveTab } = this.state;
1640
1509
  if (onClickFn) {
1641
1510
  /**
@@ -1658,7 +1527,7 @@ class IonTabBarUnwrapped extends React.PureComponent {
1658
1527
  if (this.props.onIonTabsDidChange) {
1659
1528
  this.props.onIonTabsDidChange(new CustomEvent('ionTabDidChange', { detail: { tab: e.detail.tab } }));
1660
1529
  }
1661
- if (hasRouterOutlet) {
1530
+ if ((_b = this.props.routerOutletRef) === null || _b === void 0 ? void 0 : _b.current) {
1662
1531
  this.setActiveTabOnContext(e.detail.tab);
1663
1532
  this.context.changeTab(e.detail.tab, currentHref, e.detail.routeOptions);
1664
1533
  }
@@ -1694,20 +1563,171 @@ class IonTabBarUnwrapped extends React.PureComponent {
1694
1563
  const IonTabBarContainer = React.memo((_a) => {
1695
1564
  var { forwardedRef } = _a, props = __rest(_a, ["forwardedRef"]);
1696
1565
  const context = useContext(NavContext);
1697
- const tabsContext = useContext(IonTabsContext);
1698
- const tabBarRef = forwardedRef || tabsContext.tabBarProps.ref;
1699
- const updatedTabBarProps = Object.assign(Object.assign({}, tabsContext.tabBarProps), { ref: tabBarRef });
1700
- return (React.createElement(IonTabBarUnwrapped, Object.assign({ ref: tabBarRef }, props, { routeInfo: props.routeInfo || context.routeInfo || { pathname: window.location.pathname }, onSetCurrentTab: context.setCurrentTab,
1701
- /**
1702
- * Tab bar can be used as a standalone component,
1703
- * so it cannot be modified directly through
1704
- * IonTabs. Instead, props will be passed through
1705
- * the context.
1706
- */
1707
- tabsContext: Object.assign(Object.assign({}, tabsContext), { tabBarProps: updatedTabBarProps }) }), props.children));
1566
+ return (React.createElement(IonTabBarUnwrapped, Object.assign({ ref: forwardedRef }, props, { routeInfo: props.routeInfo || context.routeInfo || { pathname: window.location.pathname }, onSetCurrentTab: context.setCurrentTab }), props.children));
1708
1567
  });
1709
1568
  const IonTabBar = createForwardRef(IonTabBarContainer, 'IonTabBar');
1710
1569
 
1570
+ class IonTabsElement extends HTMLElementSSR {
1571
+ constructor() {
1572
+ super();
1573
+ }
1574
+ }
1575
+ // TODO(FW-2959): types
1576
+ if (typeof window !== 'undefined' && window.customElements) {
1577
+ const element = window.customElements.get('ion-tabs');
1578
+ if (!element) {
1579
+ window.customElements.define('ion-tabs', IonTabsElement);
1580
+ }
1581
+ }
1582
+ const hostStyles = {
1583
+ display: 'flex',
1584
+ position: 'absolute',
1585
+ top: '0',
1586
+ left: '0',
1587
+ right: '0',
1588
+ bottom: '0',
1589
+ flexDirection: 'column',
1590
+ width: '100%',
1591
+ height: '100%',
1592
+ contain: 'layout size style',
1593
+ };
1594
+ const tabsInner = {
1595
+ position: 'relative',
1596
+ flex: 1,
1597
+ contain: 'layout size style',
1598
+ };
1599
+ const IonTabs = /*@__PURE__*/ (() => class extends React.Component {
1600
+ constructor(props) {
1601
+ super(props);
1602
+ this.routerOutletRef = React.createRef();
1603
+ this.tabBarRef = React.createRef();
1604
+ this.ionTabContextState = {
1605
+ activeTab: undefined,
1606
+ selectTab: () => false,
1607
+ };
1608
+ }
1609
+ componentDidMount() {
1610
+ if (this.tabBarRef.current) {
1611
+ // Grab initial value
1612
+ this.ionTabContextState.activeTab = this.tabBarRef.current.state.activeTab;
1613
+ // Override method
1614
+ this.tabBarRef.current.setActiveTabOnContext = (tab) => {
1615
+ this.ionTabContextState.activeTab = tab;
1616
+ };
1617
+ this.ionTabContextState.selectTab = this.tabBarRef.current.selectTab;
1618
+ }
1619
+ }
1620
+ render() {
1621
+ let outlet;
1622
+ let tabBar;
1623
+ // Check if IonTabs has any IonTab children
1624
+ let hasTab = false;
1625
+ const _a = this.props, { className, onIonTabsDidChange, onIonTabsWillChange } = _a, props = __rest(_a, ["className", "onIonTabsDidChange", "onIonTabsWillChange"]);
1626
+ const children = typeof this.props.children === 'function'
1627
+ ? this.props.children(this.ionTabContextState)
1628
+ : this.props.children;
1629
+ const outletProps = {
1630
+ ref: this.routerOutletRef,
1631
+ };
1632
+ React.Children.forEach(children, (child) => {
1633
+ // eslint-disable-next-line no-prototype-builtins
1634
+ if (child == null || typeof child !== 'object' || !child.hasOwnProperty('type')) {
1635
+ return;
1636
+ }
1637
+ if (child.type === IonRouterOutlet || child.type.isRouterOutlet) {
1638
+ outlet = React.cloneElement(child, outletProps);
1639
+ }
1640
+ else if (child.type === Fragment && child.props.children[0].type === IonRouterOutlet) {
1641
+ outlet = React.cloneElement(child.props.children[0], outletProps);
1642
+ }
1643
+ else if (child.type === IonTab) {
1644
+ /**
1645
+ * This indicates that IonTabs will be using a basic tab-based navigation
1646
+ * without the history stack or URL updates associated with the router.
1647
+ */
1648
+ hasTab = true;
1649
+ }
1650
+ let childProps = {
1651
+ ref: this.tabBarRef,
1652
+ routerOutletRef: this.routerOutletRef,
1653
+ };
1654
+ /**
1655
+ * Only pass these props
1656
+ * down from IonTabs to IonTabBar
1657
+ * if they are defined, otherwise
1658
+ * if you have a handler set on
1659
+ * IonTabBar it will be overridden.
1660
+ */
1661
+ if (onIonTabsDidChange !== undefined) {
1662
+ childProps = Object.assign(Object.assign({}, childProps), { onIonTabsDidChange });
1663
+ }
1664
+ if (onIonTabsWillChange !== undefined) {
1665
+ childProps = Object.assign(Object.assign({}, childProps), { onIonTabsWillChange });
1666
+ }
1667
+ if (child.type === IonTabBar || child.type.isTabBar) {
1668
+ tabBar = React.cloneElement(child, childProps);
1669
+ }
1670
+ else if (child.type === Fragment &&
1671
+ (child.props.children[1].type === IonTabBar || child.props.children[1].type.isTabBar)) {
1672
+ tabBar = React.cloneElement(child.props.children[1], childProps);
1673
+ }
1674
+ });
1675
+ if (!outlet && !hasTab) {
1676
+ throw new Error('IonTabs must contain an IonRouterOutlet or an IonTab');
1677
+ }
1678
+ if (outlet && hasTab) {
1679
+ throw new Error('IonTabs cannot contain an IonRouterOutlet and an IonTab at the same time');
1680
+ }
1681
+ if (hasTab) {
1682
+ return React.createElement(IonTabsInner, Object.assign({}, this.props));
1683
+ }
1684
+ /**
1685
+ * TODO(ROU-11051)
1686
+ *
1687
+ * There is no error handling for the case where there
1688
+ * is no associated Route for the given IonTabButton.
1689
+ *
1690
+ * More investigation is needed to determine how to
1691
+ * handle this to prevent any overwriting of the
1692
+ * IonTabButton's onClick handler and how the routing
1693
+ * is handled.
1694
+ */
1695
+ return (React.createElement(IonTabsContext.Provider, { value: this.ionTabContextState }, this.context.hasIonicRouter() ? (React.createElement(PageManager, Object.assign({ className: className ? `${className}` : '', routeInfo: this.context.routeInfo }, props),
1696
+ React.createElement(IonTabsInner, Object.assign({}, this.props), React.Children.map(children, (child) => {
1697
+ if (React.isValidElement(child)) {
1698
+ const isTabBar = child.type === IonTabBar ||
1699
+ child.type.isTabBar ||
1700
+ (child.type === Fragment &&
1701
+ (child.props.children[1].type === IonTabBar || child.props.children[1].type.isTabBar));
1702
+ const isRouterOutlet = child.type === IonRouterOutlet ||
1703
+ child.type.isRouterOutlet ||
1704
+ (child.type === Fragment && child.props.children[0].type === IonRouterOutlet);
1705
+ if (isTabBar) {
1706
+ /**
1707
+ * The modified tabBar needs to be returned to include
1708
+ * the context and the overridden methods.
1709
+ */
1710
+ return tabBar;
1711
+ }
1712
+ if (isRouterOutlet) {
1713
+ /**
1714
+ * The modified outlet needs to be returned to include
1715
+ * the ref.
1716
+ */
1717
+ return outlet;
1718
+ }
1719
+ }
1720
+ return child;
1721
+ })))) : (React.createElement("div", Object.assign({ className: className ? `${className}` : 'ion-tabs' }, props, { style: hostStyles }),
1722
+ (tabBar === null || tabBar === void 0 ? void 0 : tabBar.props.slot) === 'top' ? tabBar : null,
1723
+ React.createElement("div", { style: tabsInner, className: "tabs-inner" }, outlet),
1724
+ (tabBar === null || tabBar === void 0 ? void 0 : tabBar.props.slot) === 'bottom' ? tabBar : null))));
1725
+ }
1726
+ static get contextType() {
1727
+ return NavContext;
1728
+ }
1729
+ })();
1730
+
1711
1731
  const IonBackButton = /*@__PURE__*/ (() => class extends React.Component {
1712
1732
  constructor() {
1713
1733
  super(...arguments);