UNPKG

@ionic/vue

Version:
1,411 lines (1,399 loc) • 102 kB
import { defineComponent, ref, onMounted, getCurrentInstance, inject, h, withDirectives, computed, provide, shallowRef, watch, onUnmounted, Fragment, isVNode, Teleport } from 'vue'; import { defineCustomElement } from '@ionic/core/components/ion-accordion.js'; import { defineCustomElement as defineCustomElement$1 } from '@ionic/core/components/ion-accordion-group.js'; import { defineCustomElement as defineCustomElement$2 } from '@ionic/core/components/ion-avatar.js'; import { defineCustomElement as defineCustomElement$3 } from '@ionic/core/components/ion-backdrop.js'; import { defineCustomElement as defineCustomElement$4 } from '@ionic/core/components/ion-badge.js'; import { defineCustomElement as defineCustomElement$5 } from '@ionic/core/components/ion-breadcrumb.js'; import { defineCustomElement as defineCustomElement$6 } from '@ionic/core/components/ion-breadcrumbs.js'; import { defineCustomElement as defineCustomElement$7 } from '@ionic/core/components/ion-button.js'; import { defineCustomElement as defineCustomElement$8 } from '@ionic/core/components/ion-buttons.js'; import { defineCustomElement as defineCustomElement$9 } from '@ionic/core/components/ion-card.js'; import { defineCustomElement as defineCustomElement$a } from '@ionic/core/components/ion-card-content.js'; import { defineCustomElement as defineCustomElement$b } from '@ionic/core/components/ion-card-header.js'; import { defineCustomElement as defineCustomElement$c } from '@ionic/core/components/ion-card-subtitle.js'; import { defineCustomElement as defineCustomElement$d } from '@ionic/core/components/ion-card-title.js'; import { defineCustomElement as defineCustomElement$e } from '@ionic/core/components/ion-checkbox.js'; import { defineCustomElement as defineCustomElement$f } from '@ionic/core/components/ion-chip.js'; import { defineCustomElement as defineCustomElement$g } from '@ionic/core/components/ion-col.js'; import { defineCustomElement as defineCustomElement$h } from '@ionic/core/components/ion-content.js'; import { defineCustomElement as defineCustomElement$i } from '@ionic/core/components/ion-datetime.js'; import { defineCustomElement as defineCustomElement$j } from '@ionic/core/components/ion-datetime-button.js'; import { defineCustomElement as defineCustomElement$k } from '@ionic/core/components/ion-fab.js'; import { defineCustomElement as defineCustomElement$l } from '@ionic/core/components/ion-fab-button.js'; import { defineCustomElement as defineCustomElement$m } from '@ionic/core/components/ion-fab-list.js'; import { defineCustomElement as defineCustomElement$n } from '@ionic/core/components/ion-footer.js'; import { defineCustomElement as defineCustomElement$o } from '@ionic/core/components/ion-grid.js'; import { defineCustomElement as defineCustomElement$p } from '@ionic/core/components/ion-header.js'; import { defineCustomElement as defineCustomElement$q } from '@ionic/core/components/ion-img.js'; import { defineCustomElement as defineCustomElement$r } from '@ionic/core/components/ion-infinite-scroll.js'; import { defineCustomElement as defineCustomElement$s } from '@ionic/core/components/ion-infinite-scroll-content.js'; import { defineCustomElement as defineCustomElement$t } from '@ionic/core/components/ion-input.js'; import { defineCustomElement as defineCustomElement$u } from '@ionic/core/components/ion-input-otp.js'; import { defineCustomElement as defineCustomElement$v } from '@ionic/core/components/ion-input-password-toggle.js'; import { defineCustomElement as defineCustomElement$w } from '@ionic/core/components/ion-item.js'; import { defineCustomElement as defineCustomElement$x } from '@ionic/core/components/ion-item-divider.js'; import { defineCustomElement as defineCustomElement$y } from '@ionic/core/components/ion-item-group.js'; import { defineCustomElement as defineCustomElement$z } from '@ionic/core/components/ion-item-option.js'; import { defineCustomElement as defineCustomElement$A } from '@ionic/core/components/ion-item-options.js'; import { defineCustomElement as defineCustomElement$B } from '@ionic/core/components/ion-item-sliding.js'; import { defineCustomElement as defineCustomElement$C } from '@ionic/core/components/ion-label.js'; import { defineCustomElement as defineCustomElement$D } from '@ionic/core/components/ion-list.js'; import { defineCustomElement as defineCustomElement$E } from '@ionic/core/components/ion-list-header.js'; import { defineCustomElement as defineCustomElement$F } from '@ionic/core/components/ion-menu.js'; import { defineCustomElement as defineCustomElement$G } from '@ionic/core/components/ion-menu-button.js'; import { defineCustomElement as defineCustomElement$H } from '@ionic/core/components/ion-menu-toggle.js'; import { defineCustomElement as defineCustomElement$1j } from '@ionic/core/components/ion-nav.js'; import { defineCustomElement as defineCustomElement$I } from '@ionic/core/components/ion-nav-link.js'; import { defineCustomElement as defineCustomElement$J } from '@ionic/core/components/ion-note.js'; import { defineCustomElement as defineCustomElement$K } from '@ionic/core/components/ion-picker.js'; import { defineCustomElement as defineCustomElement$L } from '@ionic/core/components/ion-picker-column.js'; import { defineCustomElement as defineCustomElement$M } from '@ionic/core/components/ion-picker-column-option.js'; import { defineCustomElement as defineCustomElement$N } from '@ionic/core/components/ion-progress-bar.js'; import { defineCustomElement as defineCustomElement$O } from '@ionic/core/components/ion-radio.js'; import { defineCustomElement as defineCustomElement$P } from '@ionic/core/components/ion-radio-group.js'; import { defineCustomElement as defineCustomElement$Q } from '@ionic/core/components/ion-range.js'; import { defineCustomElement as defineCustomElement$R } from '@ionic/core/components/ion-refresher.js'; import { defineCustomElement as defineCustomElement$S } from '@ionic/core/components/ion-refresher-content.js'; import { defineCustomElement as defineCustomElement$T } from '@ionic/core/components/ion-reorder.js'; import { defineCustomElement as defineCustomElement$U } from '@ionic/core/components/ion-reorder-group.js'; import { defineCustomElement as defineCustomElement$V } from '@ionic/core/components/ion-ripple-effect.js'; import { defineCustomElement as defineCustomElement$W } from '@ionic/core/components/ion-row.js'; import { defineCustomElement as defineCustomElement$X } from '@ionic/core/components/ion-searchbar.js'; import { defineCustomElement as defineCustomElement$Y } from '@ionic/core/components/ion-segment.js'; import { defineCustomElement as defineCustomElement$Z } from '@ionic/core/components/ion-segment-button.js'; import { defineCustomElement as defineCustomElement$_ } from '@ionic/core/components/ion-segment-content.js'; import { defineCustomElement as defineCustomElement$$ } from '@ionic/core/components/ion-segment-view.js'; import { defineCustomElement as defineCustomElement$10 } from '@ionic/core/components/ion-select.js'; import { defineCustomElement as defineCustomElement$11 } from '@ionic/core/components/ion-select-modal.js'; import { defineCustomElement as defineCustomElement$12 } from '@ionic/core/components/ion-select-option.js'; import { defineCustomElement as defineCustomElement$13 } from '@ionic/core/components/ion-skeleton-text.js'; import { defineCustomElement as defineCustomElement$14 } from '@ionic/core/components/ion-spinner.js'; import { defineCustomElement as defineCustomElement$15 } from '@ionic/core/components/ion-split-pane.js'; import { defineCustomElement as defineCustomElement$16 } from '@ionic/core/components/ion-tab.js'; import { defineCustomElement as defineCustomElement$17 } from '@ionic/core/components/ion-text.js'; import { defineCustomElement as defineCustomElement$18 } from '@ionic/core/components/ion-textarea.js'; import { defineCustomElement as defineCustomElement$19 } from '@ionic/core/components/ion-thumbnail.js'; import { defineCustomElement as defineCustomElement$1a } from '@ionic/core/components/ion-title.js'; import { defineCustomElement as defineCustomElement$1b } from '@ionic/core/components/ion-toggle.js'; import { defineCustomElement as defineCustomElement$1c } from '@ionic/core/components/ion-toolbar.js'; import { LIFECYCLE_WILL_ENTER, LIFECYCLE_DID_ENTER, LIFECYCLE_WILL_LEAVE, LIFECYCLE_DID_LEAVE, initialize, modalController as modalController$1, popoverController as popoverController$1, alertController as alertController$1, actionSheetController as actionSheetController$1, loadingController as loadingController$1, pickerController as pickerController$1, toastController as toastController$1 } from '@ionic/core/components'; export { IonicSafeString, IonicSlides, createAnimation, createGesture, getIonPageElement, getPlatforms, getTimeGivenProgression, iosTransitionAnimation, isPlatform, mdTransitionAnimation, menuController, openURL } from '@ionic/core/components'; import { defineCustomElement as defineCustomElement$1d } from '@ionic/core/components/ion-back-button.js'; import { defineCustomElement as defineCustomElement$1e } from '@ionic/core/components/ion-router-outlet.js'; import { routeLocationKey, useRoute, matchedRouteKey } from 'vue-router'; import { defineCustomElement as defineCustomElement$1f } from '@ionic/core/components/ion-tab-button.js'; import { defineCustomElement as defineCustomElement$1g } from '@ionic/core/components/ion-tabs.js'; import { defineCustomElement as defineCustomElement$1h } from '@ionic/core/components/ion-tab-bar.js'; import { defineCustomElement as defineCustomElement$1i } from '@ionic/core/components/ion-app.js'; import { defineCustomElement as defineCustomElement$1k } from 'ionicons/components/ion-icon.js'; import { defineCustomElement as defineCustomElement$1l } from '@ionic/core/components/ion-action-sheet.js'; import { defineCustomElement as defineCustomElement$1m } from '@ionic/core/components/ion-alert.js'; import { defineCustomElement as defineCustomElement$1n } from '@ionic/core/components/ion-loading.js'; import { defineCustomElement as defineCustomElement$1o } from '@ionic/core/components/ion-modal.js'; import { defineCustomElement as defineCustomElement$1p } from '@ionic/core/components/ion-picker-legacy.js'; import { defineCustomElement as defineCustomElement$1q } from '@ionic/core/components/ion-popover.js'; import { defineCustomElement as defineCustomElement$1r } from '@ionic/core/components/ion-toast.js'; const UPDATE_VALUE_EVENT = 'update:modelValue'; const MODEL_VALUE = 'modelValue'; const ROUTER_LINK_VALUE = 'routerLink'; const NAV_MANAGER = 'navManager'; const ROUTER_PROP_PREFIX = 'router'; const ARIA_PROP_PREFIX = 'aria'; /** * Starting in Vue 3.1.0, all properties are * added as keys to the props object, even if * they are not being used. In order to correctly * account for both value props and v-model props, * we need to check if the key exists for Vue <3.1.0 * and then check if it is not undefined for Vue >= 3.1.0. * See https://github.com/vuejs/vue-next/issues/3889 */ const EMPTY_PROP$1 = Symbol(); const DEFAULT_EMPTY_PROP$1 = { default: EMPTY_PROP$1 }; const getComponentClasses = (classes) => { return classes?.split(' ') || []; }; const getElementClasses = (ref, componentClasses, defaultClasses = []) => { return [...Array.from(ref.value?.classList || []), ...defaultClasses].filter((c, i, self) => !componentClasses.has(c) && self.indexOf(c) === i); }; /** * Create a callback to define a Vue component wrapper around a Web Component. * * @prop name - The component tag name (i.e. `ion-button`) * @prop componentProps - An array of properties on the * component. These usually match up with the @Prop definitions * in each component's TSX file. * @prop emitProps - An array of for event listener on the Component. * these usually match up with the @Event definitions * in each compont's TSX file. * @prop customElement - An option custom element instance to pass * to customElements.define. Only set if `includeImportCustomElements: true` in your config. * @prop modelProp - The prop that v-model binds to (i.e. value) * @prop modelUpdateEvent - The event that is fired from your Web Component when the value changes (i.e. ionChange) */ const defineContainer = (name, defineCustomElement, componentProps = [], emitProps = [], modelProp, modelUpdateEvent) => { /** * Create a Vue component wrapper around a Web Component. * Note: The `props` here are not all properties on a component. * They refer to whatever properties are set on an instance of a component. */ if (defineCustomElement !== undefined) { defineCustomElement(); } const emits = emitProps; const props = [ROUTER_LINK_VALUE, ...componentProps].reduce((acc, prop) => { acc[prop] = DEFAULT_EMPTY_PROP$1; return acc; }, {}); if (modelProp) { emits.push(UPDATE_VALUE_EVENT); props[MODEL_VALUE] = DEFAULT_EMPTY_PROP$1; } return defineComponent((props, { attrs, slots, emit }) => { let modelPropValue = modelProp ? props[modelProp] : undefined; const containerRef = ref(); const classes = new Set(getComponentClasses(attrs.class)); onMounted(() => { /** * we register the event emmiter for @Event definitions * so we can use @event */ emitProps.forEach((eventName) => { containerRef.value?.addEventListener(eventName, (e) => { emit(eventName, e); }); }); }); /** * This directive is responsible for updating any reactive * reference associated with v-model on the component. * This code must be run inside of the "created" callback. * Since the following listener callbacks as well as any potential * event callback defined in the developer's app are set on * the same element, we need to make sure the following callbacks * are set first so they fire first. If the developer's callback fires first * then the reactive reference will not have been updated yet. */ const vModelDirective = { created: (el) => { const eventsNames = (Array.isArray(modelUpdateEvent) ? modelUpdateEvent : [modelUpdateEvent]).map((ev) => ev.replace(/-([a-z])/g, (g) => g[1].toUpperCase())); eventsNames.forEach((eventName) => { el.addEventListener(eventName, (e) => { /** * Only update the v-model binding if the event's target is the element we are * listening on. For example, Component A could emit ionChange, but it could also * have a descendant Component B that also emits ionChange. We only want to update * the v-model for Component A when ionChange originates from that element and not * when ionChange bubbles up from Component B. */ if (e.target.tagName === el.tagName && modelProp) { modelPropValue = (e?.target)[modelProp]; emit(UPDATE_VALUE_EVENT, modelPropValue); } }); }); }, }; const currentInstance = getCurrentInstance(); const hasRouter = currentInstance?.appContext?.provides[NAV_MANAGER]; const navManager = hasRouter ? inject(NAV_MANAGER) : undefined; const handleRouterLink = (ev) => { const { routerLink } = props; if (routerLink === EMPTY_PROP$1) return; if (navManager !== undefined) { /** * This prevents the browser from * performing a page reload when pressing * an Ionic component with routerLink. * The page reload interferes with routing * and causes ion-back-button to disappear * since the local history is wiped on reload. */ ev.preventDefault(); let navigationPayload = { event: ev }; for (const key in props) { const value = props[key]; if (props.hasOwnProperty(key) && key.startsWith(ROUTER_PROP_PREFIX) && value !== EMPTY_PROP$1) { navigationPayload[key] = value; } } navManager.navigate(navigationPayload); } else { console.warn('Tried to navigate, but no router was found. Make sure you have mounted Vue Router.'); } }; return () => { modelPropValue = props[modelProp]; getComponentClasses(attrs.class).forEach((value) => { classes.add(value); }); // @ts-expect-error const oldClick = props.onClick; const handleClick = (ev) => { if (oldClick !== undefined) { oldClick(ev); } if (!ev.defaultPrevented) { handleRouterLink(ev); } }; const propsToAdd = { ref: containerRef, class: getElementClasses(containerRef, classes), onClick: handleClick, }; /** * We can use Object.entries here * to avoid the hasOwnProperty check, * but that would require 2 iterations * where as this only requires 1. */ for (const key in props) { const value = props[key]; if ((props.hasOwnProperty(key) && value !== EMPTY_PROP$1) || key.startsWith(ARIA_PROP_PREFIX)) { propsToAdd[key] = value; } /** * register event handlers on the component */ const eventHandlerKey = 'on' + key.slice(0, 1).toUpperCase() + key.slice(1); const eventHandler = attrs[eventHandlerKey]; if (containerRef.value && attrs.hasOwnProperty(eventHandlerKey) && 'addEventListener' in containerRef.value) { containerRef.value.addEventListener(key, eventHandler); } } if (modelProp) { /** * If form value property was set using v-model * then we should use that value. * Otherwise, check to see if form value property * was set as a static value (i.e. no v-model). */ if (props[MODEL_VALUE] !== EMPTY_PROP$1) { propsToAdd[modelProp] = props[MODEL_VALUE]; } else if (modelPropValue !== EMPTY_PROP$1) { propsToAdd[modelProp] = modelPropValue; } } // If router link is defined, add href to props // in order to properly render an anchor tag inside // of components that should become activatable and // focusable with router link. if (ROUTER_LINK_VALUE in props && props[ROUTER_LINK_VALUE] !== EMPTY_PROP$1) { propsToAdd.href = props[ROUTER_LINK_VALUE]; } /** * vModelDirective is only needed on components that support v-model. * As a result, we conditionally call withDirectives with v-model components. */ const node = h(name, propsToAdd, slots.default && slots.default()); return modelProp === undefined ? node : withDirectives(node, [[vModelDirective]]); }; }, { name, props, emits, }); }; /* eslint-disable */ /* tslint:disable */ /* auto-generated vue proxies */ const IonAccordion = /*@__PURE__*/ defineContainer('ion-accordion', defineCustomElement, [ 'value', 'disabled', 'readonly', 'toggleIcon', 'toggleIconSlot' ]); const IonAccordionGroup = /*@__PURE__*/ defineContainer('ion-accordion-group', defineCustomElement$1, [ 'animated', 'multiple', 'value', 'disabled', 'readonly', 'expand', 'ionChange', 'ionValueChange' ], [ 'ionChange', 'ionValueChange' ], 'value', 'ion-change'); const IonAvatar = /*@__PURE__*/ defineContainer('ion-avatar', defineCustomElement$2); const IonBackdrop = /*@__PURE__*/ defineContainer('ion-backdrop', defineCustomElement$3, [ 'visible', 'tappable', 'stopPropagation', 'ionBackdropTap' ], [ 'ionBackdropTap' ]); const IonBadge = /*@__PURE__*/ defineContainer('ion-badge', defineCustomElement$4, [ 'color' ]); const IonBreadcrumb = /*@__PURE__*/ defineContainer('ion-breadcrumb', defineCustomElement$5, [ 'collapsed', 'last', 'showCollapsedIndicator', 'color', 'active', 'disabled', 'download', 'href', 'rel', 'separator', 'target', 'routerDirection', 'routerAnimation', 'ionFocus', 'ionBlur', 'collapsedClick' ], [ 'ionFocus', 'ionBlur', 'collapsedClick' ]); const IonBreadcrumbs = /*@__PURE__*/ defineContainer('ion-breadcrumbs', defineCustomElement$6, [ 'color', 'maxItems', 'itemsBeforeCollapse', 'itemsAfterCollapse', 'ionCollapsedClick' ], [ 'ionCollapsedClick' ]); const IonButton = /*@__PURE__*/ defineContainer('ion-button', defineCustomElement$7, [ 'color', 'buttonType', 'disabled', 'expand', 'fill', 'routerDirection', 'routerAnimation', 'download', 'href', 'rel', 'shape', 'size', 'strong', 'target', 'type', 'form', 'ionFocus', 'ionBlur' ], [ 'ionFocus', 'ionBlur' ]); const IonButtons = /*@__PURE__*/ defineContainer('ion-buttons', defineCustomElement$8, [ 'collapse' ]); const IonCard = /*@__PURE__*/ defineContainer('ion-card', defineCustomElement$9, [ 'color', 'button', 'type', 'disabled', 'download', 'href', 'rel', 'routerDirection', 'routerAnimation', 'target' ]); const IonCardContent = /*@__PURE__*/ defineContainer('ion-card-content', defineCustomElement$a); const IonCardHeader = /*@__PURE__*/ defineContainer('ion-card-header', defineCustomElement$b, [ 'color', 'translucent' ]); const IonCardSubtitle = /*@__PURE__*/ defineContainer('ion-card-subtitle', defineCustomElement$c, [ 'color' ]); const IonCardTitle = /*@__PURE__*/ defineContainer('ion-card-title', defineCustomElement$d, [ 'color' ]); const IonCheckbox = /*@__PURE__*/ defineContainer('ion-checkbox', defineCustomElement$e, [ 'color', 'name', 'checked', 'indeterminate', 'disabled', 'errorText', 'helperText', 'value', 'labelPlacement', 'justify', 'alignment', 'required', 'ionChange', 'ionFocus', 'ionBlur' ], [ 'ionChange', 'ionFocus', 'ionBlur' ], 'checked', 'ion-change'); const IonChip = /*@__PURE__*/ defineContainer('ion-chip', defineCustomElement$f, [ 'color', 'outline', 'disabled' ]); const IonCol = /*@__PURE__*/ defineContainer('ion-col', defineCustomElement$g, [ 'offset', 'offsetXs', 'offsetSm', 'offsetMd', 'offsetLg', 'offsetXl', 'pull', 'pullXs', 'pullSm', 'pullMd', 'pullLg', 'pullXl', 'push', 'pushXs', 'pushSm', 'pushMd', 'pushLg', 'pushXl', 'size', 'sizeXs', 'sizeSm', 'sizeMd', 'sizeLg', 'sizeXl' ]); const IonContent = /*@__PURE__*/ defineContainer('ion-content', defineCustomElement$h, [ 'color', 'fullscreen', 'fixedSlotPlacement', 'forceOverscroll', 'scrollX', 'scrollY', 'scrollEvents', 'ionScrollStart', 'ionScroll', 'ionScrollEnd' ], [ 'ionScrollStart', 'ionScroll', 'ionScrollEnd' ]); const IonDatetime = /*@__PURE__*/ defineContainer('ion-datetime', defineCustomElement$i, [ 'color', 'name', 'disabled', 'formatOptions', 'readonly', 'isDateEnabled', 'showAdjacentDays', 'min', 'max', 'presentation', 'cancelText', 'doneText', 'clearText', 'yearValues', 'monthValues', 'dayValues', 'hourValues', 'minuteValues', 'locale', 'firstDayOfWeek', 'titleSelectedDatesFormatter', 'multiple', 'highlightedDates', 'value', 'showDefaultTitle', 'showDefaultButtons', 'showClearButton', 'showDefaultTimeLabel', 'hourCycle', 'size', 'preferWheel', 'ionCancel', 'ionChange', 'ionValueChange', 'ionFocus', 'ionBlur', 'ionStyle', 'ionRender' ], [ 'ionCancel', 'ionChange', 'ionValueChange', 'ionFocus', 'ionBlur', 'ionStyle', 'ionRender' ], 'value', 'ion-change'); const IonDatetimeButton = /*@__PURE__*/ defineContainer('ion-datetime-button', defineCustomElement$j, [ 'color', 'disabled', 'datetime' ]); const IonFab = /*@__PURE__*/ defineContainer('ion-fab', defineCustomElement$k, [ 'horizontal', 'vertical', 'edge', 'activated' ]); const IonFabButton = /*@__PURE__*/ defineContainer('ion-fab-button', defineCustomElement$l, [ 'color', 'activated', 'disabled', 'download', 'href', 'rel', 'routerDirection', 'routerAnimation', 'target', 'show', 'translucent', 'type', 'size', 'closeIcon', 'ionFocus', 'ionBlur' ], [ 'ionFocus', 'ionBlur' ]); const IonFabList = /*@__PURE__*/ defineContainer('ion-fab-list', defineCustomElement$m, [ 'activated', 'side' ]); const IonFooter = /*@__PURE__*/ defineContainer('ion-footer', defineCustomElement$n, [ 'collapse', 'translucent' ]); const IonGrid = /*@__PURE__*/ defineContainer('ion-grid', defineCustomElement$o, [ 'fixed' ]); const IonHeader = /*@__PURE__*/ defineContainer('ion-header', defineCustomElement$p, [ 'collapse', 'translucent' ]); const IonImg = /*@__PURE__*/ defineContainer('ion-img', defineCustomElement$q, [ 'alt', 'src', 'ionImgWillLoad', 'ionImgDidLoad', 'ionError' ], [ 'ionImgWillLoad', 'ionImgDidLoad', 'ionError' ]); const IonInfiniteScroll = /*@__PURE__*/ defineContainer('ion-infinite-scroll', defineCustomElement$r, [ 'threshold', 'disabled', 'position', 'ionInfinite' ], [ 'ionInfinite' ]); const IonInfiniteScrollContent = /*@__PURE__*/ defineContainer('ion-infinite-scroll-content', defineCustomElement$s, [ 'loadingSpinner', 'loadingText' ]); const IonInput = /*@__PURE__*/ defineContainer('ion-input', defineCustomElement$t, [ 'color', 'autocapitalize', 'autocomplete', 'autocorrect', 'autofocus', 'clearInput', 'clearInputIcon', 'clearOnEdit', 'counter', 'counterFormatter', 'debounce', 'disabled', 'enterkeyhint', 'errorText', 'fill', 'inputmode', 'helperText', 'label', 'labelPlacement', 'max', 'maxlength', 'min', 'minlength', 'multiple', 'name', 'pattern', 'placeholder', 'readonly', 'required', 'shape', 'spellcheck', 'step', 'type', 'value', 'ionInput', 'ionChange', 'ionBlur', 'ionFocus' ], [ 'ionInput', 'ionChange', 'ionBlur', 'ionFocus' ], 'value', 'ion-input'); const IonInputOtp = /*@__PURE__*/ defineContainer('ion-input-otp', defineCustomElement$u, [ 'autocapitalize', 'color', 'disabled', 'fill', 'inputmode', 'length', 'pattern', 'readonly', 'separators', 'shape', 'size', 'type', 'value', 'ionInput', 'ionChange', 'ionComplete', 'ionBlur', 'ionFocus' ], [ 'ionInput', 'ionChange', 'ionComplete', 'ionBlur', 'ionFocus' ], 'value', 'ion-input'); const IonInputPasswordToggle = /*@__PURE__*/ defineContainer('ion-input-password-toggle', defineCustomElement$v, [ 'color', 'showIcon', 'hideIcon', 'type' ]); const IonItem = /*@__PURE__*/ defineContainer('ion-item', defineCustomElement$w, [ 'color', 'button', 'detail', 'detailIcon', 'disabled', 'download', 'href', 'rel', 'lines', 'routerAnimation', 'routerDirection', 'target', 'type' ]); const IonItemDivider = /*@__PURE__*/ defineContainer('ion-item-divider', defineCustomElement$x, [ 'color', 'sticky' ]); const IonItemGroup = /*@__PURE__*/ defineContainer('ion-item-group', defineCustomElement$y); const IonItemOption = /*@__PURE__*/ defineContainer('ion-item-option', defineCustomElement$z, [ 'color', 'disabled', 'download', 'expandable', 'href', 'rel', 'target', 'type' ]); const IonItemOptions = /*@__PURE__*/ defineContainer('ion-item-options', defineCustomElement$A, [ 'side', 'ionSwipe' ], [ 'ionSwipe' ]); const IonItemSliding = /*@__PURE__*/ defineContainer('ion-item-sliding', defineCustomElement$B, [ 'disabled', 'ionDrag' ], [ 'ionDrag' ]); const IonLabel = /*@__PURE__*/ defineContainer('ion-label', defineCustomElement$C, [ 'color', 'position', 'ionColor', 'ionStyle' ], [ 'ionColor', 'ionStyle' ]); const IonList = /*@__PURE__*/ defineContainer('ion-list', defineCustomElement$D, [ 'lines', 'inset' ]); const IonListHeader = /*@__PURE__*/ defineContainer('ion-list-header', defineCustomElement$E, [ 'color', 'lines' ]); const IonMenu = /*@__PURE__*/ defineContainer('ion-menu', defineCustomElement$F, [ 'contentId', 'menuId', 'type', 'disabled', 'side', 'swipeGesture', 'maxEdgeStart', 'ionWillOpen', 'ionWillClose', 'ionDidOpen', 'ionDidClose', 'ionMenuChange' ], [ 'ionWillOpen', 'ionWillClose', 'ionDidOpen', 'ionDidClose', 'ionMenuChange' ]); const IonMenuButton = /*@__PURE__*/ defineContainer('ion-menu-button', defineCustomElement$G, [ 'color', 'disabled', 'menu', 'autoHide', 'type' ]); const IonMenuToggle = /*@__PURE__*/ defineContainer('ion-menu-toggle', defineCustomElement$H, [ 'menu', 'autoHide' ]); const IonNavLink = /*@__PURE__*/ defineContainer('ion-nav-link', defineCustomElement$I, [ 'component', 'componentProps', 'routerDirection', 'routerAnimation' ]); const IonNote = /*@__PURE__*/ defineContainer('ion-note', defineCustomElement$J, [ 'color' ]); const IonPicker = /*@__PURE__*/ defineContainer('ion-picker', defineCustomElement$K, [ 'ionInputModeChange' ], [ 'ionInputModeChange' ]); const IonPickerColumn = /*@__PURE__*/ defineContainer('ion-picker-column', defineCustomElement$L, [ 'disabled', 'value', 'color', 'numericInput', 'ionChange' ], [ 'ionChange' ]); const IonPickerColumnOption = /*@__PURE__*/ defineContainer('ion-picker-column-option', defineCustomElement$M, [ 'disabled', 'value', 'color' ]); const IonProgressBar = /*@__PURE__*/ defineContainer('ion-progress-bar', defineCustomElement$N, [ 'type', 'reversed', 'value', 'buffer', 'color' ]); const IonRadio = /*@__PURE__*/ defineContainer('ion-radio', defineCustomElement$O, [ 'color', 'name', 'disabled', 'value', 'labelPlacement', 'justify', 'alignment', 'ionFocus', 'ionBlur' ], [ 'ionFocus', 'ionBlur' ], 'value', 'ion-change'); const IonRadioGroup = /*@__PURE__*/ defineContainer('ion-radio-group', defineCustomElement$P, [ 'allowEmptySelection', 'compareWith', 'name', 'value', 'helperText', 'errorText', 'ionChange', 'ionValueChange' ], [ 'ionChange', 'ionValueChange' ], 'value', 'ion-change'); const IonRange = /*@__PURE__*/ defineContainer('ion-range', defineCustomElement$Q, [ 'color', 'debounce', 'name', 'label', 'dualKnobs', 'min', 'max', 'pin', 'pinFormatter', 'snaps', 'step', 'ticks', 'activeBarStart', 'disabled', 'value', 'labelPlacement', 'ionChange', 'ionInput', 'ionFocus', 'ionBlur', 'ionKnobMoveStart', 'ionKnobMoveEnd' ], [ 'ionChange', 'ionInput', 'ionFocus', 'ionBlur', 'ionKnobMoveStart', 'ionKnobMoveEnd' ], 'value', 'ion-input'); const IonRefresher = /*@__PURE__*/ defineContainer('ion-refresher', defineCustomElement$R, [ 'pullMin', 'pullMax', 'closeDuration', 'snapbackDuration', 'pullFactor', 'disabled', 'ionRefresh', 'ionPull', 'ionStart' ], [ 'ionRefresh', 'ionPull', 'ionStart' ]); const IonRefresherContent = /*@__PURE__*/ defineContainer('ion-refresher-content', defineCustomElement$S, [ 'pullingIcon', 'pullingText', 'refreshingSpinner', 'refreshingText' ]); const IonReorder = /*@__PURE__*/ defineContainer('ion-reorder', defineCustomElement$T); const IonReorderGroup = /*@__PURE__*/ defineContainer('ion-reorder-group', defineCustomElement$U, [ 'disabled', 'ionItemReorder', 'ionReorderStart', 'ionReorderMove', 'ionReorderEnd' ], [ 'ionItemReorder', 'ionReorderStart', 'ionReorderMove', 'ionReorderEnd' ]); const IonRippleEffect = /*@__PURE__*/ defineContainer('ion-ripple-effect', defineCustomElement$V, [ 'type' ]); const IonRow = /*@__PURE__*/ defineContainer('ion-row', defineCustomElement$W); const IonSearchbar = /*@__PURE__*/ defineContainer('ion-searchbar', defineCustomElement$X, [ 'color', 'animated', 'autocapitalize', 'autocomplete', 'autocorrect', 'cancelButtonIcon', 'cancelButtonText', 'clearIcon', 'debounce', 'disabled', 'inputmode', 'enterkeyhint', 'maxlength', 'minlength', 'name', 'placeholder', 'searchIcon', 'showCancelButton', 'showClearButton', 'spellcheck', 'type', 'value', 'ionInput', 'ionChange', 'ionCancel', 'ionClear', 'ionBlur', 'ionFocus', 'ionStyle' ], [ 'ionInput', 'ionChange', 'ionCancel', 'ionClear', 'ionBlur', 'ionFocus', 'ionStyle' ], 'value', 'ion-input'); const IonSegment = /*@__PURE__*/ defineContainer('ion-segment', defineCustomElement$Y, [ 'color', 'disabled', 'scrollable', 'swipeGesture', 'value', 'selectOnFocus', 'ionChange', 'ionSelect', 'ionStyle' ], [ 'ionChange', 'ionSelect', 'ionStyle' ], 'value', 'ion-change'); const IonSegmentButton = /*@__PURE__*/ defineContainer('ion-segment-button', defineCustomElement$Z, [ 'contentId', 'disabled', 'layout', 'type', 'value' ], [], 'value', 'ion-change'); const IonSegmentContent = /*@__PURE__*/ defineContainer('ion-segment-content', defineCustomElement$_); const IonSegmentView = /*@__PURE__*/ defineContainer('ion-segment-view', defineCustomElement$$, [ 'disabled', 'ionSegmentViewScroll' ], [ 'ionSegmentViewScroll' ]); const IonSelect = /*@__PURE__*/ defineContainer('ion-select', defineCustomElement$10, [ 'cancelText', 'color', 'compareWith', 'disabled', 'fill', 'errorText', 'helperText', 'interface', 'interfaceOptions', 'justify', 'label', 'labelPlacement', 'multiple', 'name', 'okText', 'placeholder', 'selectedText', 'toggleIcon', 'expandedIcon', 'shape', 'value', 'required', 'ionChange', 'ionCancel', 'ionDismiss', 'ionFocus', 'ionBlur', 'ionStyle' ], [ 'ionChange', 'ionCancel', 'ionDismiss', 'ionFocus', 'ionBlur', 'ionStyle' ], 'value', 'ion-change'); const IonSelectModal = /*@__PURE__*/ defineContainer('ion-select-modal', defineCustomElement$11, [ 'header', 'multiple', 'options' ]); const IonSelectOption = /*@__PURE__*/ defineContainer('ion-select-option', defineCustomElement$12, [ 'disabled', 'value' ]); const IonSkeletonText = /*@__PURE__*/ defineContainer('ion-skeleton-text', defineCustomElement$13, [ 'animated', 'ionStyle' ], [ 'ionStyle' ]); const IonSpinner = /*@__PURE__*/ defineContainer('ion-spinner', defineCustomElement$14, [ 'color', 'duration', 'name', 'paused' ]); const IonSplitPane = /*@__PURE__*/ defineContainer('ion-split-pane', defineCustomElement$15, [ 'contentId', 'disabled', 'when', 'ionSplitPaneVisible' ], [ 'ionSplitPaneVisible' ]); const IonTab = /*@__PURE__*/ defineContainer('ion-tab', defineCustomElement$16, [ 'active', 'delegate', 'tab', 'component' ]); const IonText = /*@__PURE__*/ defineContainer('ion-text', defineCustomElement$17, [ 'color' ]); const IonTextarea = /*@__PURE__*/ defineContainer('ion-textarea', defineCustomElement$18, [ 'color', 'autocapitalize', 'autofocus', 'clearOnEdit', 'debounce', 'disabled', 'fill', 'inputmode', 'enterkeyhint', 'maxlength', 'minlength', 'name', 'placeholder', 'readonly', 'required', 'spellcheck', 'cols', 'rows', 'wrap', 'autoGrow', 'value', 'counter', 'counterFormatter', 'errorText', 'helperText', 'label', 'labelPlacement', 'shape', 'ionChange', 'ionInput', 'ionBlur', 'ionFocus' ], [ 'ionChange', 'ionInput', 'ionBlur', 'ionFocus' ], 'value', 'ion-input'); const IonThumbnail = /*@__PURE__*/ defineContainer('ion-thumbnail', defineCustomElement$19); const IonTitle = /*@__PURE__*/ defineContainer('ion-title', defineCustomElement$1a, [ 'color', 'size', 'ionStyle' ], [ 'ionStyle' ]); const IonToggle = /*@__PURE__*/ defineContainer('ion-toggle', defineCustomElement$1b, [ 'color', 'name', 'checked', 'disabled', 'errorText', 'helperText', 'value', 'enableOnOffLabels', 'labelPlacement', 'justify', 'alignment', 'required', 'ionChange', 'ionFocus', 'ionBlur' ], [ 'ionChange', 'ionFocus', 'ionBlur' ], 'checked', 'ion-change'); const IonToolbar = /*@__PURE__*/ defineContainer('ion-toolbar', defineCustomElement$1c, [ 'color' ]); const useBackButton = (priority, handler) => { const callback = (ev) => ev.detail.register(priority, handler); const unregister = () => document.removeEventListener("ionBackButton", callback); document.addEventListener("ionBackButton", callback); return { unregister }; }; const useKeyboard = () => { const isOpen = ref(false); const keyboardHeight = ref(0); const showCallback = (ev) => { isOpen.value = true; keyboardHeight.value = ev.detail.keyboardHeight; }; const hideCallback = () => { isOpen.value = false; keyboardHeight.value = 0; }; const unregister = () => { if (typeof window !== "undefined") { window.removeEventListener("ionKeyboardDidShow", showCallback); window.removeEventListener("ionKeyboardDidHide", hideCallback); } }; if (typeof window !== "undefined") { window.addEventListener("ionKeyboardDidShow", showCallback); window.addEventListener("ionKeyboardDidHide", hideCallback); } return { isOpen, keyboardHeight, unregister, }; }; // TODO(FW-2969): types var LifecycleHooks; (function (LifecycleHooks) { LifecycleHooks["WillEnter"] = "onIonViewWillEnter"; LifecycleHooks["DidEnter"] = "onIonViewDidEnter"; LifecycleHooks["WillLeave"] = "onIonViewWillLeave"; LifecycleHooks["DidLeave"] = "onIonViewDidLeave"; })(LifecycleHooks || (LifecycleHooks = {})); const hookNames = { [LIFECYCLE_WILL_ENTER]: LifecycleHooks.WillEnter, [LIFECYCLE_DID_ENTER]: LifecycleHooks.DidEnter, [LIFECYCLE_WILL_LEAVE]: LifecycleHooks.WillLeave, [LIFECYCLE_DID_LEAVE]: LifecycleHooks.DidLeave, }; const ids = { main: 0 }; const generateId = (type = "main") => { var _a; const id = ((_a = ids[type]) !== null && _a !== void 0 ? _a : 0) + 1; ids[type] = id; return id.toString(); }; const fireLifecycle = (vueComponent, vueInstance, lifecycle) => { if (vueComponent === null || vueComponent === void 0 ? void 0 : vueComponent[lifecycle]) { vueComponent[lifecycle].bind(vueInstance === null || vueInstance === void 0 ? void 0 : vueInstance.value)(); } const instance = vueInstance === null || vueInstance === void 0 ? void 0 : vueInstance.value; if (instance === null || instance === void 0 ? void 0 : instance[lifecycle]) { instance[lifecycle](); } /** * Fire any Composition API * Ionic Lifecycle hooks */ if (instance) { const hook = hookNames[lifecycle]; const hooks = instance[hook]; if (hooks) { hooks.forEach((hook) => hook()); } } }; const getConfig = () => { if (typeof window !== "undefined") { const Ionic = window.Ionic; if (Ionic && Ionic.config) { return Ionic.config; } } return null; }; /** * Creates an returns a function that * can be used to provide a lifecycle hook. */ const injectHook = (lifecycleType, hook, component) => { if (component) { // Add to public instance so it is accessible to IonRouterOutlet const target = component; const hooks = target.proxy[lifecycleType] || (target.proxy[lifecycleType] = []); /** * Define property on public instances using `setup` syntax in Vue 3.x */ if (target.exposed) { target.exposed[lifecycleType] = hooks; } const wrappedHook = (...args) => { if (target.isUnmounted) { return; } return args ? hook(...args) : hook(); }; hooks.push(wrappedHook); return wrappedHook; } else { console.warn("[@ionic/vue]: Ionic Lifecycle Hooks can only be used during execution of setup()."); } }; const createHook = (lifecycle) => { return (hook, target = getCurrentInstance()) => injectHook(lifecycle, hook, target); }; const onIonViewWillEnter = createHook(LifecycleHooks.WillEnter); const onIonViewDidEnter = createHook(LifecycleHooks.DidEnter); const onIonViewWillLeave = createHook(LifecycleHooks.WillLeave); const onIonViewDidLeave = createHook(LifecycleHooks.DidLeave); /** * Used to navigate within Vue Router * while controlling the animation. */ const useIonRouter = () => { const { canGoBack, goBack, goForward, handleNavigate } = inject("navManager"); const navigate = (location, routerDirection, routerAction, routerAnimation) => handleNavigate(location, routerAction, routerDirection, routerAnimation); const push = (location, routerAnimation) => navigate(location, "forward", "push", routerAnimation); const replace = (location, routerAnimation) => navigate(location, "root", "replace", routerAnimation); const back = (routerAnimation) => goBack(routerAnimation); const forward = (routerAnimation) => goForward(routerAnimation); return { canGoBack, push, replace, back, forward, navigate, }; }; const IonicVue = { async install(_, config = {}) { /** * By default Ionic Framework hides elements that * are not hydrated, but in the CE build there is no * hydration. * TODO FW-2797: Remove when all integrations have been * migrated to CE build. */ if (typeof document !== "undefined") { document.documentElement.classList.add("ion-ce"); } initialize(config); }, }; const IonBackButton = /*@__PURE__*/ defineComponent((_, { attrs, slots }) => { defineCustomElement$1d(); // TODO(FW-2969): type const ionRouter = inject("navManager"); const onClick = () => { /** * When using ion-back-button outside of * a routing context, ionRouter is undefined. */ if (ionRouter === undefined) { return; } const defaultHref = attrs["default-href"] || attrs["defaultHref"]; const routerAnimation = attrs["router-animation"] || attrs["routerAnimation"]; ionRouter.handleNavigateBack(defaultHref, routerAnimation); }; return () => { return h("ion-back-button", Object.assign({ onClick }, attrs), slots.default && slots.default()); }; }, { name: "IonBackButton", }); const IonPage = /*@__PURE__*/ defineComponent({ name: "IonPage", props: { // eslint-disable-next-line @typescript-eslint/no-empty-function registerIonPage: { type: Function, default: () => { } }, }, mounted() { this.$props.registerIonPage(this.$refs.ionPage); }, setup(_, { attrs, slots }) { return () => { return h("div", Object.assign(Object.assign({}, attrs), { ["class"]: "ion-page", ref: "ionPage" }), slots.default && slots.default()); }; }, }); // TODO(FW-2969): types const isViewVisible = (enteringEl) => { return (!enteringEl.classList.contains("ion-page-hidden") && !enteringEl.classList.contains("ion-page-invisible")); }; const viewDepthKey = Symbol(0); const IonRouterOutlet = /*@__PURE__*/ defineComponent({ name: "IonRouterOutlet", setup() { defineCustomElement$1e(); const injectedRoute = inject(routeLocationKey); const route = useRoute(); const depth = inject(viewDepthKey, 0); const matchedRouteRef = computed(() => route.matched[depth]); let previousMatchedRouteRef; let previousMatchedPath; provide(viewDepthKey, (depth + 1)); provide(matchedRouteKey, matchedRouteRef); const ionRouterOutlet = ref(); const id = generateId("ion-router-outlet"); const ionRouter = inject("navManager"); const viewStacks = inject("viewStacks"); const components = shallowRef([]); let skipTransition = false; // The base url for this router outlet let parentOutletPath; /** * Note: Do not listen for matchedRouteRef by itself here * as the callback will not fire for parameterized routes (i.e. /page/:id). * So going from /page/1 to /page/2 would not fire this callback if we * only listened for changes to matchedRouteRef. */ watch(() => [route, matchedRouteRef.value], ([currentRoute, currentMatchedRouteRef]) => { /** * This callback checks whether or not a router outlet * needs to respond to a change in the matched route. * It handles a few cases: * 1. The matched route is undefined. This means that * the matched route is not applicable to this outlet. * For example, a /settings route is not applicable * to a /tabs/... route. * * Note: When going back to a tabs outlet from a non-tabs outlet, * the tabs outlet should NOT attempt a page transition from the * previous tab to the active tab. To do this we compare the current * route with the previous route. Unfortunately, we cannot rely on the * previous value provided by Vue in the watch callback. This is because * when coming back to the tabs context, the previous matched route will * be undefined (because nothing in the tabs context matches /settings) * but the current matched route will be defined and so a transition * will always occur. * * 2. The matched route is defined and is different than * the previously matched route. This is the most * common case such as when you go from /page1 to /page2. * * 3. The matched route is the same but the parameters are different. * This is a special case for parameterized routes (i.e. /page/:id). * When going from /page/1 to /page/2, the matched route object will * be the same, but we still need to perform a page transition. To do this * we check if the parameters are different (i.e. 1 vs 2). To avoid enumerating * all of the keys in the params object, we check the url path to * see if they are different after ensuring we are in a parameterized route. */ if (currentMatchedRouteRef !== undefined) { const matchedDifferentRoutes = currentMatchedRouteRef !== previousMatchedRouteRef; const matchedDifferentParameterRoutes = currentRoute.matched[currentRoute.matched.length - 1] === currentMatchedRouteRef && currentRoute.path !== previousMatchedPath; if (matchedDifferentRoutes || matchedDifferentParameterRoutes) { setupViewItem(matchedRouteRef); } } previousMatchedRouteRef = currentMatchedRouteRef; previousMatchedPath = currentRoute.path; }, /** * Future versions of Vue may default watching nested * reactive objects to "deep: false". * We explicitly set this watcher to "deep: true" to * account for that. * https://github.com/vuejs/core/issues/9965#issuecomment-1875067499 */ { deep: true }); const canStart = () => { const config = getConfig(); const swipeEnabled = config && config.get("swipeBackEnabled", ionRouterOutlet.value.mode === "ios"); if (!swipeEnabled) return false; const stack = viewStacks.getViewStack(id); if (!stack || stack.length <= 1) return false; /** * We only want to outlet of the entering view