@ionic/vue
Version:
Vue specific wrapper for @ionic/core
1,411 lines (1,399 loc) • 102 kB
JavaScript
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