merge release-6.2.0

Release 6.2.0
This commit is contained in:
Liam DeBeasi
2022-07-27 14:30:00 -04:00
committed by GitHub
441 changed files with 6115 additions and 759 deletions

View File

@ -3,6 +3,27 @@
All notable changes to this project will be documented in this file.
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
# [6.2.0](https://github.com/ionic-team/ionic/compare/v6.1.15...v6.2.0) (2022-07-27)
### Bug Fixes
* **vue:** input v-model accepts numbers ([#25666](https://github.com/ionic-team/ionic/issues/25666)) ([ab65e9a](https://github.com/ionic-team/ionic/commit/ab65e9a7b51c3a3f8c59962d3e1faff1564ab801)), closes [#25575](https://github.com/ionic-team/ionic/issues/25575)
### Features
* **angular, react, vue:** add support for autoMountComponent ([#25552](https://github.com/ionic-team/ionic/issues/25552)) ([805dfa0](https://github.com/ionic-team/ionic/commit/805dfa05663098ef9c02b0745a383b5e7555908b))
* **datetime-button:** add button for displaying datetime in overlays ([#25655](https://github.com/ionic-team/ionic/issues/25655)) ([4997331](https://github.com/ionic-team/ionic/commit/499733105e4be23405e8afeeb26fee5cd2afc25b)), closes [#24316](https://github.com/ionic-team/ionic/issues/24316)
* **datetime:** add multiple date selection ([#25514](https://github.com/ionic-team/ionic/issues/25514)) ([9d31608](https://github.com/ionic-team/ionic/commit/9d31608f2d471f531eb253832c8558d1effaf68a))
* **datetime:** add wheel style picker for dates and times ([#25468](https://github.com/ionic-team/ionic/issues/25468)) ([3d19771](https://github.com/ionic-team/ionic/commit/3d19771185301870a2eb60f1ef4afd6f1c182494))
* **modal:** clicking handle advances to the next breakpoint ([#25540](https://github.com/ionic-team/ionic/issues/25540)) ([7cdc388](https://github.com/ionic-team/ionic/commit/7cdc388b7805cbf23c9e1e928aa977cd77ebc8c4)), closes [#24069](https://github.com/ionic-team/ionic/issues/24069)
* **range:** add reference point for start position of range slider ([#25598](https://github.com/ionic-team/ionic/issues/25598)) ([c2781cc](https://github.com/ionic-team/ionic/commit/c2781cc1c3b7e56a0e6f6c03cfa04fc2c82d6e8a)), closes [#24348](https://github.com/ionic-team/ionic/issues/24348)
## [6.1.15](https://github.com/ionic-team/ionic/compare/v6.1.14...v6.1.15) (2022-07-20)
**Note:** Version bump only for package @ionic/vue

View File

@ -1,15 +1,15 @@
{
"name": "@ionic/vue",
"version": "6.1.15",
"version": "6.2.0",
"lockfileVersion": 2,
"requires": true,
"packages": {
"": {
"name": "@ionic/vue",
"version": "6.1.15",
"version": "6.2.0",
"license": "MIT",
"dependencies": {
"@ionic/core": "^6.1.15",
"@ionic/core": "^6.2.0",
"ionicons": "^6.0.2"
},
"devDependencies": {
@ -59,9 +59,9 @@
}
},
"node_modules/@ionic/core": {
"version": "6.1.15",
"resolved": "https://registry.npmjs.org/@ionic/core/-/core-6.1.15.tgz",
"integrity": "sha512-NvBlHR7O4kfp9KYz6oLsghFzGZImA7hM4qS4tFRUI62R+Q5iCJEY4OmXE5bif5K+SQkMhQY+x1l2Nq20waLzLg==",
"version": "6.2.0",
"resolved": "https://registry.npmjs.org/@ionic/core/-/core-6.2.0.tgz",
"integrity": "sha512-3qUNsVcSAdrjhIhPr5M2RRnh+1xuc9RFaxoeUgI9xQ0YjTmn2FWiH4urDCXuE/rZAwnvHF4X17P0L2EqCPSfWA==",
"dependencies": {
"@stencil/core": "^2.16.0",
"ionicons": "^6.0.2",
@ -768,9 +768,9 @@
}
},
"@ionic/core": {
"version": "6.1.15",
"resolved": "https://registry.npmjs.org/@ionic/core/-/core-6.1.15.tgz",
"integrity": "sha512-NvBlHR7O4kfp9KYz6oLsghFzGZImA7hM4qS4tFRUI62R+Q5iCJEY4OmXE5bif5K+SQkMhQY+x1l2Nq20waLzLg==",
"version": "6.2.0",
"resolved": "https://registry.npmjs.org/@ionic/core/-/core-6.2.0.tgz",
"integrity": "sha512-3qUNsVcSAdrjhIhPr5M2RRnh+1xuc9RFaxoeUgI9xQ0YjTmn2FWiH4urDCXuE/rZAwnvHF4X17P0L2EqCPSfWA==",
"requires": {
"@stencil/core": "^2.16.0",
"ionicons": "^6.0.2",

View File

@ -1,6 +1,6 @@
{
"name": "@ionic/vue",
"version": "6.1.15",
"version": "6.2.0",
"description": "Vue specific wrapper for @ionic/core",
"scripts": {
"prepublishOnly": "npm run build",
@ -61,7 +61,7 @@
"vue-router": "^4.0.16"
},
"dependencies": {
"@ionic/core": "^6.1.15",
"@ionic/core": "^6.2.0",
"ionicons": "^6.0.2"
},
"vetur": {

View File

@ -29,7 +29,7 @@ export const IonPicker = /*@__PURE__*/ defineOverlayContainer<JSX.IonPicker>('io
export const IonToast = /*@__PURE__*/ defineOverlayContainer<JSX.IonToast>('ion-toast', defineIonToastCustomElement, ['animated', 'buttons', 'color', 'cssClass', 'duration', 'enterAnimation', 'header', 'htmlAttributes', 'icon', 'keyboardClose', 'leaveAnimation', 'message', 'mode', 'position', 'translucent'], toastController);
export const IonModal = /*@__PURE__*/ defineOverlayContainer<JSX.IonModal>('ion-modal', defineIonModalCustomElement, ['animated', 'backdropBreakpoint', 'backdropDismiss', 'breakpoints', 'canDismiss', 'enterAnimation', 'handle', 'htmlAttributes', 'initialBreakpoint', 'isOpen', 'keyboardClose', 'leaveAnimation', 'mode', 'presentingElement', 'showBackdrop', 'swipeToClose', 'trigger']);
export const IonModal = /*@__PURE__*/ defineOverlayContainer<JSX.IonModal>('ion-modal', defineIonModalCustomElement, ['animated', 'backdropBreakpoint', 'backdropDismiss', 'breakpoints', 'canDismiss', 'enterAnimation', 'handle', 'handleBehavior', 'htmlAttributes', 'initialBreakpoint', 'isOpen', 'keepContentsMounted', 'keyboardClose', 'leaveAnimation', 'mode', 'presentingElement', 'showBackdrop', 'swipeToClose', 'trigger']);
export const IonPopover = /*@__PURE__*/ defineOverlayContainer<JSX.IonPopover>('ion-popover', defineIonPopoverCustomElement, ['alignment', 'animated', 'arrow', 'backdropDismiss', 'component', 'componentProps', 'dismissOnSelect', 'enterAnimation', 'event', 'htmlAttributes', 'isOpen', 'keyboardClose', 'leaveAnimation', 'mode', 'reference', 'showBackdrop', 'side', 'size', 'translucent', 'trigger', 'triggerAction']);
export const IonPopover = /*@__PURE__*/ defineOverlayContainer<JSX.IonPopover>('ion-popover', defineIonPopoverCustomElement, ['alignment', 'animated', 'arrow', 'backdropDismiss', 'component', 'componentProps', 'dismissOnSelect', 'enterAnimation', 'event', 'htmlAttributes', 'isOpen', 'keepContentsMounted', 'keyboardClose', 'leaveAnimation', 'mode', 'reference', 'showBackdrop', 'side', 'size', 'translucent', 'trigger', 'triggerAction']);

View File

@ -24,6 +24,7 @@ import { defineCustomElement as defineIonChip } from '@ionic/core/components/ion
import { defineCustomElement as defineIonCol } from '@ionic/core/components/ion-col.js';
import { defineCustomElement as defineIonContent } from '@ionic/core/components/ion-content.js';
import { defineCustomElement as defineIonDatetime } from '@ionic/core/components/ion-datetime.js';
import { defineCustomElement as defineIonDatetimeButton } from '@ionic/core/components/ion-datetime-button.js';
import { defineCustomElement as defineIonFab } from '@ionic/core/components/ion-fab.js';
import { defineCustomElement as defineIonFabButton } from '@ionic/core/components/ion-fab-button.js';
import { defineCustomElement as defineIonFabList } from '@ionic/core/components/ion-fab-list.js';
@ -285,6 +286,7 @@ export const IonDatetime = /*@__PURE__*/ defineContainer<JSX.IonDatetime>('ion-d
'minuteValues',
'locale',
'firstDayOfWeek',
'multiple',
'value',
'showDefaultTitle',
'showDefaultButtons',
@ -292,15 +294,24 @@ export const IonDatetime = /*@__PURE__*/ defineContainer<JSX.IonDatetime>('ion-d
'showDefaultTimeLabel',
'hourCycle',
'size',
'preferWheel',
'ionCancel',
'ionChange',
'ionFocus',
'ionBlur',
'ionStyle'
'ionStyle',
'ionRender'
],
'value', 'v-ion-change', 'ionChange');
export const IonDatetimeButton = /*@__PURE__*/ defineContainer<JSX.IonDatetimeButton>('ion-datetime-button', defineIonDatetimeButton, [
'color',
'disabled',
'datetime'
]);
export const IonFab = /*@__PURE__*/ defineContainer<JSX.IonFab>('ion-fab', defineIonFab, [
'horizontal',
'vertical',
@ -586,6 +597,7 @@ export const IonRange = /*@__PURE__*/ defineContainer<JSX.IonRange>('ion-range',
'snaps',
'step',
'ticks',
'activeBarStart',
'disabled',
'value',
'ionChange',
@ -816,6 +828,7 @@ export const IonToggle = /*@__PURE__*/ defineContainer<JSX.IonToggle>('ion-toggl
'checked',
'disabled',
'value',
'enableOnOffLabels',
'ionChange',
'ionFocus',
'ionBlur',

View File

@ -162,7 +162,7 @@ export const defineOverlayContainer = <Props extends object>(name: string, defin
return h(
name,
{ ...restOfProps, ref: elementRef },
(isOpen.value) ? slots : undefined
(isOpen.value || restOfProps.keepContentsMounted) ? slots : undefined
)
}
});

View File

@ -1,7 +1,7 @@
import { VNode, defineComponent, getCurrentInstance, h, inject, ref, Ref } from 'vue';
export interface InputProps {
modelValue?: string | boolean;
export interface InputProps<T> {
modelValue?: T;
}
const UPDATE_VALUE_EVENT = 'update:modelValue';
@ -49,7 +49,7 @@ const getElementClasses = (ref: Ref<HTMLElement | undefined>, componentClasses:
* @prop externalModelUpdateEvent - The external event to fire from your Vue component when modelUpdateEvent fires. This is used for ensuring that v-model references have been
* correctly updated when a user's event callback fires.
*/
export const defineContainer = <Props>(
export const defineContainer = <Props, VModelType=string|number|boolean>(
name: string,
defineCustomElement: any,
componentProps: string[] = [],
@ -67,7 +67,7 @@ export const defineContainer = <Props>(
defineCustomElement();
}
const Container = defineComponent<Props & InputProps>((props: any, { attrs, slots, emit }) => {
const Container = defineComponent<Props & InputProps<VModelType>>((props: any, { attrs, slots, emit }) => {
let modelPropValue = props[modelProp];
const containerRef = ref<HTMLElement>();
const classes = new Set(getComponentClasses(attrs.class));
@ -76,7 +76,7 @@ export const defineContainer = <Props>(
if (vnode.el) {
const eventsNames = Array.isArray(modelUpdateEvent) ? modelUpdateEvent : [modelUpdateEvent];
eventsNames.forEach((eventName: string) => {
vnode.el.addEventListener(eventName.toLowerCase(), (e: Event) => {
vnode.el!.addEventListener(eventName.toLowerCase(), (e: Event) => {
modelPropValue = (e?.target as any)[modelProp];
emit(UPDATE_VALUE_EVENT, modelPropValue);

View File

@ -1,11 +1,16 @@
<template>
<ion-content class="ion-padding">
{{ title }}
<ion-button id="dismiss" @click="dismiss">Dismiss</ion-button> <br />
<div id="title">
{{ title }}
</div>
</ion-content>
</template>
<script lang="ts">
import {
IonButton,
IonContent,
popoverController
} from '@ionic/vue';
@ -16,6 +21,7 @@ export default defineComponent({
title: { type: String, default: 'Default Title' }
},
components: {
IonButton,
IonContent
},
setup() {

View File

@ -25,6 +25,10 @@ const routes: Array<RouteRecordRaw> = [
path: '/overlays',
component: () => import('@/views/Overlays.vue')
},
{
path: '/keep-contents-mounted',
component: () => import('@/views/OverlaysKeepContentsMounted.vue')
},
{
path: '/inputs',
component: () => import('@/views/Inputs.vue')

View File

@ -0,0 +1,80 @@
<template>
<ion-page data-pageid="overlays-automount">
<ion-header :translucent="true">
<ion-toolbar>
<ion-buttons>
<ion-back-button></ion-back-button>
</ion-buttons>
<ion-title>Overlays - Auto Mount</ion-title>
</ion-toolbar>
</ion-header>
<ion-content class="ion-padding" :fullscreen="true">
<ion-button id="open-auto-mount-modal">Open Auto Mount Modal</ion-button>
<ion-button id="open-auto-mount-popover">Open Auto Mount Popover</ion-button>
<br /><br />
<ion-modal
id="auto-mount-modal"
:keep-contents-mounted="true"
trigger="open-auto-mount-modal"
>
<ModalContent :title="overlayProps.title"></ModalContent>
</ion-modal>
<ion-popover
id="auto-mount-popover"
:keep-contents-mounted="true"
trigger="open-auto-mount-popover"
>
<PopoverContent :title="overlayProps.title"></PopoverContent>
</ion-popover>
</ion-content>
</ion-page>
</template>
<script lang="ts">
import {
IonBackButton,
IonButton,
IonButtons,
IonContent,
IonHeader,
IonPage,
IonTitle,
IonToolbar,
IonModal,
IonPopover,
} from '@ionic/vue';
import { defineComponent } from 'vue';
import ModalContent from '@/components/ModalContent.vue';
import PopoverContent from '@/components/PopoverContent.vue';
export default defineComponent({
components: {
ModalContent,
PopoverContent,
IonBackButton,
IonButton,
IonButtons,
IonContent,
IonHeader,
IonPage,
IonTitle,
IonToolbar,
IonModal,
IonPopover,
},
setup() {
const overlayProps = {
title: 'Custom Title'
}
return {
overlayProps
}
}
});
</script>

View File

@ -0,0 +1,52 @@
describe('overlays - keepContentsMounted', () => {
beforeEach(() => {
cy.viewport(1000, 900);
cy.visit('http://localhost:8080/keep-contents-mounted')
})
describe('modal', () => {
it('should not mount component if false', () => {
cy.get('ion-modal#default-modal ion-content').should('not.exist');
});
it('should mount component if true', () => {
cy.get('ion-modal#auto-mount-modal ion-content').should('exist');
});
it('should keep component mounted after dismissing if true', () => {
cy.get('#open-auto-mount-modal').click();
cy.get('ion-modal#auto-mount-modal ion-content').should('exist');
cy.get('ion-modal#auto-mount-modal #dismiss').click();
cy.get('ion-modal#auto-mount-modal')
.should('not.be.visible')
.should('have.class', 'overlay-hidden');
cy.get('ion-modal#auto-mount-modal ion-content').should('exist');
});
})
describe('popover', () => {
it('should not mount component if false', () => {
cy.get('ion-popover#default-popover ion-content').should('not.exist');
});
it('should mount component if true', () => {
cy.get('ion-popover#auto-mount-popover ion-content').should('exist');
});
it('should keep component mounted after dismissing if true', () => {
cy.get('#open-auto-mount-popover').click();
cy.get('ion-popover#auto-mount-popover ion-content').should('exist');
cy.get('ion-popover#auto-mount-popover #dismiss').click();
cy.get('ion-popover#auto-mount-popover')
.should('not.be.visible')
.should('have.class', 'overlay-hidden');
cy.get('ion-popover#auto-mount-popover ion-content').should('exist');
});
})
})

View File

@ -134,7 +134,7 @@ describe('Overlays', () => {
cy.get('ion-button#present-overlay').click();
cy.get('ion-popover.ion-popover-controller').should('exist');
cy.get('ion-popover.ion-popover-controller ion-content').should('have.text', 'Custom Title');
cy.get('ion-popover.ion-popover-controller ion-content #title').should('have.text', 'Custom Title');
});
it('should pass props to popover via component', () => {
@ -144,7 +144,7 @@ describe('Overlays', () => {
cy.get('ion-button#present-overlay').click();
cy.get('ion-popover').should('exist');
cy.get('ion-popover.popover-inline ion-content').should('have.text', 'Custom Title');
cy.get('ion-popover.popover-inline ion-content #title').should('have.text', 'Custom Title');
});
it('should only open one instance at a time when props change quickly on component', () => {