ion-tabs.js 7.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191
  1. /*!
  2. * (C) Ionic http://ionicframework.com - MIT License
  3. */
  4. import { proxyCustomElement, HTMLElement, createEvent, h, Host } from '@stencil/core/internal/client';
  5. import { p as printIonError } from './index4.js';
  6. const tabsCss = ":host{left:0;right:0;top:0;bottom:0;display:-ms-flexbox;display:flex;position:absolute;-ms-flex-direction:column;flex-direction:column;width:100%;height:100%;contain:layout size style;z-index:0}.tabs-inner{position:relative;-ms-flex:1;flex:1;contain:layout size style}";
  7. const IonTabsStyle0 = tabsCss;
  8. const Tabs = /*@__PURE__*/ proxyCustomElement(class Tabs extends HTMLElement {
  9. constructor() {
  10. super();
  11. this.__registerHost();
  12. this.__attachShadow();
  13. this.ionNavWillLoad = createEvent(this, "ionNavWillLoad", 7);
  14. this.ionTabsWillChange = createEvent(this, "ionTabsWillChange", 3);
  15. this.ionTabsDidChange = createEvent(this, "ionTabsDidChange", 3);
  16. this.transitioning = false;
  17. this.onTabClicked = (ev) => {
  18. const { href, tab } = ev.detail;
  19. if (this.useRouter && href !== undefined) {
  20. const router = document.querySelector('ion-router');
  21. if (router) {
  22. router.push(href);
  23. }
  24. }
  25. else {
  26. this.select(tab);
  27. }
  28. };
  29. this.selectedTab = undefined;
  30. this.useRouter = false;
  31. }
  32. async componentWillLoad() {
  33. if (!this.useRouter) {
  34. /**
  35. * JavaScript and StencilJS use `ion-router`, while
  36. * the other frameworks use `ion-router-outlet`.
  37. *
  38. * If either component is present then tabs will not use
  39. * a basic tab-based navigation. It will use the history
  40. * stack or URL updates associated with the router.
  41. */
  42. this.useRouter =
  43. (!!this.el.querySelector('ion-router-outlet') || !!document.querySelector('ion-router')) &&
  44. !this.el.closest('[no-router]');
  45. }
  46. if (!this.useRouter) {
  47. const tabs = this.tabs;
  48. if (tabs.length > 0) {
  49. await this.select(tabs[0]);
  50. }
  51. }
  52. this.ionNavWillLoad.emit();
  53. }
  54. componentWillRender() {
  55. const tabBar = this.el.querySelector('ion-tab-bar');
  56. if (tabBar) {
  57. const tab = this.selectedTab ? this.selectedTab.tab : undefined;
  58. tabBar.selectedTab = tab;
  59. }
  60. }
  61. /**
  62. * Select a tab by the value of its `tab` property or an element reference. This method is only available for vanilla JavaScript projects. The Angular, React, and Vue implementations of tabs are coupled to each framework's router.
  63. *
  64. * @param tab The tab instance to select. If passed a string, it should be the value of the tab's `tab` property.
  65. */
  66. async select(tab) {
  67. const selectedTab = getTab(this.tabs, tab);
  68. if (!this.shouldSwitch(selectedTab)) {
  69. return false;
  70. }
  71. await this.setActive(selectedTab);
  72. await this.notifyRouter();
  73. this.tabSwitch();
  74. return true;
  75. }
  76. /**
  77. * Get a specific tab by the value of its `tab` property or an element reference. This method is only available for vanilla JavaScript projects. The Angular, React, and Vue implementations of tabs are coupled to each framework's router.
  78. *
  79. * @param tab The tab instance to select. If passed a string, it should be the value of the tab's `tab` property.
  80. */
  81. async getTab(tab) {
  82. return getTab(this.tabs, tab);
  83. }
  84. /**
  85. * Get the currently selected tab. This method is only available for vanilla JavaScript projects. The Angular, React, and Vue implementations of tabs are coupled to each framework's router.
  86. */
  87. getSelected() {
  88. return Promise.resolve(this.selectedTab ? this.selectedTab.tab : undefined);
  89. }
  90. /** @internal */
  91. async setRouteId(id) {
  92. const selectedTab = getTab(this.tabs, id);
  93. if (!this.shouldSwitch(selectedTab)) {
  94. return { changed: false, element: this.selectedTab };
  95. }
  96. await this.setActive(selectedTab);
  97. return {
  98. changed: true,
  99. element: this.selectedTab,
  100. markVisible: () => this.tabSwitch(),
  101. };
  102. }
  103. /** @internal */
  104. async getRouteId() {
  105. var _a;
  106. const tabId = (_a = this.selectedTab) === null || _a === void 0 ? void 0 : _a.tab;
  107. return tabId !== undefined ? { id: tabId, element: this.selectedTab } : undefined;
  108. }
  109. setActive(selectedTab) {
  110. if (this.transitioning) {
  111. return Promise.reject('transitioning already happening');
  112. }
  113. this.transitioning = true;
  114. this.leavingTab = this.selectedTab;
  115. this.selectedTab = selectedTab;
  116. this.ionTabsWillChange.emit({ tab: selectedTab.tab });
  117. selectedTab.active = true;
  118. return Promise.resolve();
  119. }
  120. tabSwitch() {
  121. const selectedTab = this.selectedTab;
  122. const leavingTab = this.leavingTab;
  123. this.leavingTab = undefined;
  124. this.transitioning = false;
  125. if (!selectedTab) {
  126. return;
  127. }
  128. if (leavingTab !== selectedTab) {
  129. if (leavingTab) {
  130. leavingTab.active = false;
  131. }
  132. this.ionTabsDidChange.emit({ tab: selectedTab.tab });
  133. }
  134. }
  135. notifyRouter() {
  136. if (this.useRouter) {
  137. const router = document.querySelector('ion-router');
  138. if (router) {
  139. return router.navChanged('forward');
  140. }
  141. }
  142. return Promise.resolve(false);
  143. }
  144. shouldSwitch(selectedTab) {
  145. const leavingTab = this.selectedTab;
  146. return selectedTab !== undefined && selectedTab !== leavingTab && !this.transitioning;
  147. }
  148. get tabs() {
  149. return Array.from(this.el.querySelectorAll('ion-tab'));
  150. }
  151. render() {
  152. return (h(Host, { key: '20b97196d78c1b3f3faf31618a8a2347e087f06b', onIonTabButtonClick: this.onTabClicked }, h("slot", { key: 'b0823fbae6e47743cfd12c376b365ad7e32cec7c', name: "top" }), h("div", { key: 'eaffd7e4d69ab9489a387e3bbb36e3bab72203a0', class: "tabs-inner" }, h("slot", { key: '20bb66a2937e3ec473aa59c4075ce581b5411677' })), h("slot", { key: '1529dd361f050f52074f51c73b3982ba827dc3a5', name: "bottom" })));
  153. }
  154. get el() { return this; }
  155. static get style() { return IonTabsStyle0; }
  156. }, [1, "ion-tabs", {
  157. "useRouter": [1028, "use-router"],
  158. "selectedTab": [32],
  159. "select": [64],
  160. "getTab": [64],
  161. "getSelected": [64],
  162. "setRouteId": [64],
  163. "getRouteId": [64]
  164. }]);
  165. const getTab = (tabs, tab) => {
  166. const tabEl = typeof tab === 'string' ? tabs.find((t) => t.tab === tab) : tab;
  167. if (!tabEl) {
  168. printIonError(`[ion-tabs] - Tab with id: "${tabEl}" does not exist`);
  169. }
  170. return tabEl;
  171. };
  172. function defineCustomElement$1() {
  173. if (typeof customElements === "undefined") {
  174. return;
  175. }
  176. const components = ["ion-tabs"];
  177. components.forEach(tagName => { switch (tagName) {
  178. case "ion-tabs":
  179. if (!customElements.get(tagName)) {
  180. customElements.define(tagName, Tabs);
  181. }
  182. break;
  183. } });
  184. }
  185. const IonTabs = Tabs;
  186. const defineCustomElement = defineCustomElement$1;
  187. export { IonTabs, defineCustomElement };