mirror of
https://github.com/ionic-team/ionic-framework.git
synced 2026-03-13 10:22:08 +08:00
Compare commits
20 Commits
rd/dynamic
...
fix/transl
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
cefcd02fb9 | ||
|
|
a296ca875c | ||
|
|
c52f3ad2c2 | ||
|
|
8424210049 | ||
|
|
c35077884d | ||
|
|
df71a0e625 | ||
|
|
2909b080b7 | ||
|
|
a8fd2d9199 | ||
|
|
9e84ef7f91 | ||
|
|
63842a25c3 | ||
|
|
0d0740161f | ||
|
|
43ac6ac471 | ||
|
|
02b7baf6a6 | ||
|
|
66e125bc5e | ||
|
|
fc0d7282f5 | ||
|
|
babe7d63ef | ||
|
|
8a97f6b5c9 | ||
|
|
4534c8bc0b | ||
|
|
d46e1e8506 | ||
|
|
981eeba0e1 |
27
CHANGELOG.md
27
CHANGELOG.md
@@ -3,6 +3,33 @@
|
||||
All notable changes to this project will be documented in this file.
|
||||
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
|
||||
|
||||
## [6.0.13](https://github.com/ionic-team/ionic-framework/compare/v6.0.12...v6.0.13) (2022-03-23)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* **angular:** ngOnDestroy runs inside angular zone ([#24949](https://github.com/ionic-team/ionic-framework/issues/24949)) ([a8fd2d9](https://github.com/ionic-team/ionic-framework/commit/a8fd2d9199ca92d62bce6abf8caccc7709fa5ca1)), closes [#22571](https://github.com/ionic-team/ionic-framework/issues/22571)
|
||||
* **datetime:** presentation time emits ionChange once ([#24968](https://github.com/ionic-team/ionic-framework/issues/24968)) ([2909b08](https://github.com/ionic-team/ionic-framework/commit/2909b080b7020299a4554c1459b4b190ff739085)), closes [#24967](https://github.com/ionic-team/ionic-framework/issues/24967)
|
||||
* **popover:** dismissing nested popover via backdrop now works ([#24957](https://github.com/ionic-team/ionic-framework/issues/24957)) ([9e84ef7](https://github.com/ionic-team/ionic-framework/commit/9e84ef7f91d76ca5a1ecaffc7592287267d5368b)), closes [#24954](https://github.com/ionic-team/ionic-framework/issues/24954)
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
## [6.0.12](https://github.com/ionic-team/ionic-framework/compare/v6.0.11...v6.0.12) (2022-03-16)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* **datetime:** reinit behavior on presentation change ([#24828](https://github.com/ionic-team/ionic-framework/issues/24828)) ([d46e1e8](https://github.com/ionic-team/ionic-framework/commit/d46e1e8506ca5095817b421e9edb37d41451e885))
|
||||
* **tabs:** angular, fire willChange event before selected tab changes ([#24910](https://github.com/ionic-team/ionic-framework/issues/24910)) ([d5efa11](https://github.com/ionic-team/ionic-framework/commit/d5efa113317eaf874712134dc9b8e4502aa4760f))
|
||||
* **toast:** screen readers now announce toasts when presented ([#24937](https://github.com/ionic-team/ionic-framework/issues/24937)) ([8a97f6b](https://github.com/ionic-team/ionic-framework/commit/8a97f6b5c9ca1e77c1790abd1e924955b6b6ea27)), closes [#22333](https://github.com/ionic-team/ionic-framework/issues/22333)
|
||||
* **vue:** tapping the active tab button now correctly resets the tab stack ([#24935](https://github.com/ionic-team/ionic-framework/issues/24935)) ([4534c8b](https://github.com/ionic-team/ionic-framework/commit/4534c8bc0b2bca7ab6eecd9886243116e9a039b7)), closes [#24934](https://github.com/ionic-team/ionic-framework/issues/24934)
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
## [6.0.11](https://github.com/ionic-team/ionic-framework/compare/v6.0.10...v6.0.11) (2022-03-09)
|
||||
|
||||
|
||||
|
||||
@@ -3,6 +3,28 @@
|
||||
All notable changes to this project will be documented in this file.
|
||||
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
|
||||
|
||||
## [6.0.13](https://github.com/ionic-team/ionic/compare/v6.0.12...v6.0.13) (2022-03-23)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* **angular:** ngOnDestroy runs inside angular zone ([#24949](https://github.com/ionic-team/ionic/issues/24949)) ([a8fd2d9](https://github.com/ionic-team/ionic/commit/a8fd2d9199ca92d62bce6abf8caccc7709fa5ca1)), closes [#22571](https://github.com/ionic-team/ionic/issues/22571)
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
## [6.0.12](https://github.com/ionic-team/ionic/compare/v6.0.11...v6.0.12) (2022-03-16)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* **tabs:** angular, fire willChange event before selected tab changes ([#24910](https://github.com/ionic-team/ionic/issues/24910)) ([d5efa11](https://github.com/ionic-team/ionic/commit/d5efa113317eaf874712134dc9b8e4502aa4760f))
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
## [6.0.11](https://github.com/ionic-team/ionic/compare/v6.0.10...v6.0.11) (2022-03-09)
|
||||
|
||||
**Note:** Version bump only for package @ionic/angular
|
||||
|
||||
2
angular/package-lock.json
generated
2
angular/package-lock.json
generated
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@ionic/angular",
|
||||
"version": "6.0.11",
|
||||
"version": "6.0.13",
|
||||
"lockfileVersion": 2,
|
||||
"requires": true,
|
||||
"packages": {
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@ionic/angular",
|
||||
"version": "6.0.11",
|
||||
"version": "6.0.13",
|
||||
"description": "Angular specific wrappers for @ionic/core",
|
||||
"keywords": [
|
||||
"ionic",
|
||||
@@ -44,7 +44,7 @@
|
||||
"validate": "npm i && npm run lint && npm run test && npm run build"
|
||||
},
|
||||
"dependencies": {
|
||||
"@ionic/core": "^6.0.11",
|
||||
"@ionic/core": "^6.0.13",
|
||||
"jsonc-parser": "^3.0.0",
|
||||
"tslib": "^2.0.0"
|
||||
},
|
||||
|
||||
@@ -1,17 +1,14 @@
|
||||
import { LocationStrategy } from '@angular/common';
|
||||
import { ElementRef, OnChanges, OnDestroy, OnInit, Directive, HostListener, Input, Optional } from '@angular/core';
|
||||
import { ElementRef, OnChanges, OnInit, Directive, HostListener, Input, Optional } from '@angular/core';
|
||||
import { Router, RouterLink } from '@angular/router';
|
||||
import { AnimationBuilder, RouterDirection } from '@ionic/core';
|
||||
import { Subscription } from 'rxjs';
|
||||
|
||||
import { NavController } from '../../providers/nav-controller';
|
||||
|
||||
@Directive({
|
||||
selector: '[routerLink]',
|
||||
})
|
||||
export class RouterLinkDelegateDirective implements OnInit, OnChanges, OnDestroy {
|
||||
private subscription?: Subscription;
|
||||
|
||||
export class RouterLinkDelegateDirective implements OnInit, OnChanges {
|
||||
@Input()
|
||||
routerDirection: RouterDirection = 'forward';
|
||||
|
||||
@@ -34,12 +31,6 @@ export class RouterLinkDelegateDirective implements OnInit, OnChanges, OnDestroy
|
||||
this.updateTargetUrlAndHref();
|
||||
}
|
||||
|
||||
ngOnDestroy(): void {
|
||||
if (this.subscription) {
|
||||
this.subscription.unsubscribe();
|
||||
}
|
||||
}
|
||||
|
||||
private updateTargetUrlAndHref() {
|
||||
if (this.routerLink?.urlTree) {
|
||||
const href = this.locationStrategy.prepareExternalUrl(this.router.serializeUrl(this.routerLink.urlTree));
|
||||
|
||||
@@ -139,7 +139,7 @@ export class StackController {
|
||||
enteringView.ref.changeDetectorRef.reattach();
|
||||
|
||||
return this.transition(enteringView, leavingView, animation, this.canGoBack(1), false, animationBuilder)
|
||||
.then(() => cleanupAsync(enteringView, views, viewsSnapshot, this.location))
|
||||
.then(() => cleanupAsync(enteringView, views, viewsSnapshot, this.location, this.zone))
|
||||
.then(() => ({
|
||||
enteringView,
|
||||
direction,
|
||||
@@ -201,7 +201,7 @@ export class StackController {
|
||||
this.skipTransition = true;
|
||||
this.pop(1);
|
||||
} else if (this.activeView) {
|
||||
cleanup(this.activeView, this.views, this.views, this.location);
|
||||
cleanup(this.activeView, this.views, this.views, this.location, this.zone);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -294,11 +294,17 @@ export class StackController {
|
||||
}
|
||||
}
|
||||
|
||||
const cleanupAsync = (activeRoute: RouteView, views: RouteView[], viewsSnapshot: RouteView[], location: Location) => {
|
||||
const cleanupAsync = (
|
||||
activeRoute: RouteView,
|
||||
views: RouteView[],
|
||||
viewsSnapshot: RouteView[],
|
||||
location: Location,
|
||||
zone: NgZone
|
||||
) => {
|
||||
if (typeof (requestAnimationFrame as any) === 'function') {
|
||||
return new Promise<void>((resolve) => {
|
||||
requestAnimationFrame(() => {
|
||||
cleanup(activeRoute, views, viewsSnapshot, location);
|
||||
cleanup(activeRoute, views, viewsSnapshot, location, zone);
|
||||
resolve();
|
||||
});
|
||||
});
|
||||
@@ -306,8 +312,18 @@ const cleanupAsync = (activeRoute: RouteView, views: RouteView[], viewsSnapshot:
|
||||
return Promise.resolve();
|
||||
};
|
||||
|
||||
const cleanup = (activeRoute: RouteView, views: RouteView[], viewsSnapshot: RouteView[], location: Location) => {
|
||||
viewsSnapshot.filter((view) => !views.includes(view)).forEach(destroyView);
|
||||
const cleanup = (
|
||||
activeRoute: RouteView,
|
||||
views: RouteView[],
|
||||
viewsSnapshot: RouteView[],
|
||||
location: Location,
|
||||
zone: NgZone
|
||||
) => {
|
||||
/**
|
||||
* Re-enter the Angular zone when destroying page components. This will allow
|
||||
* lifecycle events (`ngOnDestroy`) to be run inside the Angular zone.
|
||||
*/
|
||||
zone.run(() => viewsSnapshot.filter((view) => !views.includes(view)).forEach(destroyView));
|
||||
|
||||
views.forEach((view) => {
|
||||
/**
|
||||
|
||||
@@ -10,6 +10,7 @@ describe('Modals', () => {
|
||||
|
||||
cy.get('app-modal-example h2').should('have.text', '123');
|
||||
cy.get('app-modal-example h3').should('have.text', '321');
|
||||
cy.get('#modalInstance').should('have.text', 'true');
|
||||
|
||||
cy.get('#onWillDismiss').should('have.text', 'false');
|
||||
cy.get('#onDidDismiss').should('have.text', 'false');
|
||||
|
||||
@@ -20,6 +20,12 @@ describe('Nested Outlet', () => {
|
||||
cy.ionPageVisible('app-nested-outlet-page2');
|
||||
|
||||
cy.get('ion-router-outlet ion-router-outlet app-nested-outlet-page2 h1').should('have.text', 'Nested page 2');
|
||||
|
||||
cy.get('#goto-nested-page1').click();
|
||||
cy.ionPageVisible('app-nested-outlet-page');
|
||||
|
||||
cy.get('#goto-nested-page2').click();
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
|
||||
159
angular/test/test-app/package-lock.json
generated
159
angular/test/test-app/package-lock.json
generated
@@ -18,8 +18,8 @@
|
||||
"@angular/platform-browser-dynamic": "^13.1.3",
|
||||
"@angular/platform-server": "^13.1.3",
|
||||
"@angular/router": "^13.1.3",
|
||||
"@ionic/angular": "^5.3.1",
|
||||
"@ionic/angular-server": "^5.3.1",
|
||||
"@ionic/angular": "^6.0.12",
|
||||
"@ionic/angular-server": "^6.0.12",
|
||||
"@nguniversal/express-engine": "^12.1.1",
|
||||
"angular-in-memory-web-api": "^0.11.0",
|
||||
"core-js": "^2.6.11",
|
||||
@@ -3242,53 +3242,44 @@
|
||||
"dev": true
|
||||
},
|
||||
"node_modules/@ionic/angular": {
|
||||
"version": "5.8.2",
|
||||
"resolved": "https://registry.npmjs.org/@ionic/angular/-/angular-5.8.2.tgz",
|
||||
"integrity": "sha512-m2dE8QcWyCkv4yB+6+9j9Qu6hI28+chWT7A6nmbD7A360bm26LjdvKiJaCEQUxIXH7CpFuYcURZvRrn9gMscNg==",
|
||||
"version": "6.0.12",
|
||||
"resolved": "https://registry.npmjs.org/@ionic/angular/-/angular-6.0.12.tgz",
|
||||
"integrity": "sha512-gWY92k6tPefj2OG1ogOALfqEQah78l1OGUwjs3rOg3pliWH4aV0dq3CzgmJJwIBSnvAdW+iSSOfEoMbEVV0b7A==",
|
||||
"dependencies": {
|
||||
"@ionic/core": "5.8.2",
|
||||
"tslib": "^1.9.3"
|
||||
"@ionic/core": "^6.0.12",
|
||||
"jsonc-parser": "^3.0.0",
|
||||
"tslib": "^2.0.0"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"@angular/core": ">=8.2.7",
|
||||
"@angular/forms": ">=8.2.7",
|
||||
"@angular/router": ">=8.2.7",
|
||||
"rxjs": ">=6.2.0",
|
||||
"zone.js": ">=0.8.26"
|
||||
"@angular/core": ">=12.0.0",
|
||||
"@angular/forms": ">=12.0.0",
|
||||
"@angular/router": ">=12.0.0",
|
||||
"rxjs": ">=6.6.0",
|
||||
"zone.js": ">=0.11.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@ionic/angular-server": {
|
||||
"version": "5.8.2",
|
||||
"resolved": "https://registry.npmjs.org/@ionic/angular-server/-/angular-server-5.8.2.tgz",
|
||||
"integrity": "sha512-N141OZOmJZ0N6ASQelBSZnEzxHG8zoaVjwIgT41Q7mlEDC19jD0TtzyTzk8Ac4X/dFulKF2u6H32JG75oSEdhg==",
|
||||
"version": "6.0.12",
|
||||
"resolved": "https://registry.npmjs.org/@ionic/angular-server/-/angular-server-6.0.12.tgz",
|
||||
"integrity": "sha512-A5vqoePVfo0bxyTKHEtagJpu8OEFMOzv/zWG4FastDsWu1K3Vx/EBnwdoq9WPQ0upbMOAWf1R4SUuNny5ZSdJA==",
|
||||
"dependencies": {
|
||||
"tslib": "^1.9.0"
|
||||
"tslib": "^2.2.0"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"@angular/core": ">=8.2.7",
|
||||
"@angular/platform-server": ">=8.2.7",
|
||||
"@ionic/angular": "*",
|
||||
"rxjs": ">=6.2.0",
|
||||
"zone.js": ">=0.8.26"
|
||||
"@angular/core": ">=12.0.0",
|
||||
"@angular/platform-server": ">=12.0.0",
|
||||
"@ionic/angular": "^6.0.2",
|
||||
"rxjs": ">=6.6.0",
|
||||
"zone.js": ">=0.11.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@ionic/angular-server/node_modules/tslib": {
|
||||
"version": "1.14.1",
|
||||
"resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz",
|
||||
"integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg=="
|
||||
},
|
||||
"node_modules/@ionic/angular/node_modules/tslib": {
|
||||
"version": "1.14.1",
|
||||
"resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz",
|
||||
"integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg=="
|
||||
},
|
||||
"node_modules/@ionic/core": {
|
||||
"version": "5.8.2",
|
||||
"resolved": "https://registry.npmjs.org/@ionic/core/-/core-5.8.2.tgz",
|
||||
"integrity": "sha512-BWIh6hyhq+tzVvebPMfRa+IhTV5/yXh4wO3a0U3Qo4PL4KDzWyBJfoiPi6bOEc+BAlFnCtOooTTXTumgXXOojg==",
|
||||
"version": "6.0.12",
|
||||
"resolved": "https://registry.npmjs.org/@ionic/core/-/core-6.0.12.tgz",
|
||||
"integrity": "sha512-WpcVzSXBuvdHUZuNg1NTdnF4Ur7AGNCpgc4t4lyjPcEr0j//E855gd6GtUD7imNFERdtrvVC86JTpj5t0L+OMg==",
|
||||
"dependencies": {
|
||||
"@stencil/core": "^2.4.0",
|
||||
"ionicons": "^5.5.3",
|
||||
"@stencil/core": "^2.14.1",
|
||||
"ionicons": "^6.0.0",
|
||||
"tslib": "^2.1.0"
|
||||
}
|
||||
},
|
||||
@@ -4320,9 +4311,9 @@
|
||||
"dev": true
|
||||
},
|
||||
"node_modules/@stencil/core": {
|
||||
"version": "2.8.1",
|
||||
"resolved": "https://registry.npmjs.org/@stencil/core/-/core-2.8.1.tgz",
|
||||
"integrity": "sha512-iv9J6oLO/lv7/aO45M05yw3pp1J7olY400vlOZgdMVs3s5zHfalY1ZPYM0KyqU4+7DZuadKYbd0aQZ/g2PInZw==",
|
||||
"version": "2.14.2",
|
||||
"resolved": "https://registry.npmjs.org/@stencil/core/-/core-2.14.2.tgz",
|
||||
"integrity": "sha512-NMC5Xi8sPFJxaO4rz6CbMHuD6PteE/RJWtjrbkusmpjKRtMXkfZJPIgOrleZ4xO+vXcNyL535Ru7vUADqEsTiQ==",
|
||||
"bin": {
|
||||
"stencil": "bin/stencil"
|
||||
},
|
||||
@@ -11231,11 +11222,23 @@
|
||||
}
|
||||
},
|
||||
"node_modules/ionicons": {
|
||||
"version": "5.5.3",
|
||||
"resolved": "https://registry.npmjs.org/ionicons/-/ionicons-5.5.3.tgz",
|
||||
"integrity": "sha512-L71djrMi8pAad66tpwdnO1vwcyluCFvehzxU1PpH1k/HpYBZhZ5IaYhqXipmqUvu5aEbd4cbRguYyI5Fd4bxTw==",
|
||||
"version": "6.0.1",
|
||||
"resolved": "https://registry.npmjs.org/ionicons/-/ionicons-6.0.1.tgz",
|
||||
"integrity": "sha512-xQekOJsxH82O7oB+3F60zeRggCdND9pJ/k0E6IJDVUGGlCj5mlyFqNgxUimytKgstPGv3S+3EmCxjefvtGgWUg==",
|
||||
"dependencies": {
|
||||
"@stencil/core": "^2.5.0"
|
||||
"@stencil/core": "~2.12.0"
|
||||
}
|
||||
},
|
||||
"node_modules/ionicons/node_modules/@stencil/core": {
|
||||
"version": "2.12.1",
|
||||
"resolved": "https://registry.npmjs.org/@stencil/core/-/core-2.12.1.tgz",
|
||||
"integrity": "sha512-u24TZ+FEvjnZt5ZgIkLjLpUNsO6Ml3mUZqwmqk81w6RWWz75hgB5p4RFI5rvuErFeh2xvMIGo+pNdG24XUBz1A==",
|
||||
"bin": {
|
||||
"stencil": "bin/stencil"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=12.10.0",
|
||||
"npm": ">=6.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/ip": {
|
||||
@@ -11882,8 +11885,7 @@
|
||||
"node_modules/jsonc-parser": {
|
||||
"version": "3.0.0",
|
||||
"resolved": "https://registry.npmjs.org/jsonc-parser/-/jsonc-parser-3.0.0.tgz",
|
||||
"integrity": "sha512-fQzRfAbIBnR0IQvftw9FJveWiHp72Fg20giDrHz6TdfB12UH/uue0D3hm57UB5KgAVuniLMCaS8P1IMj9NR7cA==",
|
||||
"dev": true
|
||||
"integrity": "sha512-fQzRfAbIBnR0IQvftw9FJveWiHp72Fg20giDrHz6TdfB12UH/uue0D3hm57UB5KgAVuniLMCaS8P1IMj9NR7cA=="
|
||||
},
|
||||
"node_modules/jsonfile": {
|
||||
"version": "3.0.1",
|
||||
@@ -20944,43 +20946,30 @@
|
||||
"dev": true
|
||||
},
|
||||
"@ionic/angular": {
|
||||
"version": "5.8.2",
|
||||
"resolved": "https://registry.npmjs.org/@ionic/angular/-/angular-5.8.2.tgz",
|
||||
"integrity": "sha512-m2dE8QcWyCkv4yB+6+9j9Qu6hI28+chWT7A6nmbD7A360bm26LjdvKiJaCEQUxIXH7CpFuYcURZvRrn9gMscNg==",
|
||||
"version": "6.0.12",
|
||||
"resolved": "https://registry.npmjs.org/@ionic/angular/-/angular-6.0.12.tgz",
|
||||
"integrity": "sha512-gWY92k6tPefj2OG1ogOALfqEQah78l1OGUwjs3rOg3pliWH4aV0dq3CzgmJJwIBSnvAdW+iSSOfEoMbEVV0b7A==",
|
||||
"requires": {
|
||||
"@ionic/core": "5.8.2",
|
||||
"tslib": "^1.9.3"
|
||||
},
|
||||
"dependencies": {
|
||||
"tslib": {
|
||||
"version": "1.14.1",
|
||||
"resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz",
|
||||
"integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg=="
|
||||
}
|
||||
"@ionic/core": "^6.0.12",
|
||||
"jsonc-parser": "^3.0.0",
|
||||
"tslib": "^2.0.0"
|
||||
}
|
||||
},
|
||||
"@ionic/angular-server": {
|
||||
"version": "5.8.2",
|
||||
"resolved": "https://registry.npmjs.org/@ionic/angular-server/-/angular-server-5.8.2.tgz",
|
||||
"integrity": "sha512-N141OZOmJZ0N6ASQelBSZnEzxHG8zoaVjwIgT41Q7mlEDC19jD0TtzyTzk8Ac4X/dFulKF2u6H32JG75oSEdhg==",
|
||||
"version": "6.0.12",
|
||||
"resolved": "https://registry.npmjs.org/@ionic/angular-server/-/angular-server-6.0.12.tgz",
|
||||
"integrity": "sha512-A5vqoePVfo0bxyTKHEtagJpu8OEFMOzv/zWG4FastDsWu1K3Vx/EBnwdoq9WPQ0upbMOAWf1R4SUuNny5ZSdJA==",
|
||||
"requires": {
|
||||
"tslib": "^1.9.0"
|
||||
},
|
||||
"dependencies": {
|
||||
"tslib": {
|
||||
"version": "1.14.1",
|
||||
"resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz",
|
||||
"integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg=="
|
||||
}
|
||||
"tslib": "^2.2.0"
|
||||
}
|
||||
},
|
||||
"@ionic/core": {
|
||||
"version": "5.8.2",
|
||||
"resolved": "https://registry.npmjs.org/@ionic/core/-/core-5.8.2.tgz",
|
||||
"integrity": "sha512-BWIh6hyhq+tzVvebPMfRa+IhTV5/yXh4wO3a0U3Qo4PL4KDzWyBJfoiPi6bOEc+BAlFnCtOooTTXTumgXXOojg==",
|
||||
"version": "6.0.12",
|
||||
"resolved": "https://registry.npmjs.org/@ionic/core/-/core-6.0.12.tgz",
|
||||
"integrity": "sha512-WpcVzSXBuvdHUZuNg1NTdnF4Ur7AGNCpgc4t4lyjPcEr0j//E855gd6GtUD7imNFERdtrvVC86JTpj5t0L+OMg==",
|
||||
"requires": {
|
||||
"@stencil/core": "^2.4.0",
|
||||
"ionicons": "^5.5.3",
|
||||
"@stencil/core": "^2.14.1",
|
||||
"ionicons": "^6.0.0",
|
||||
"tslib": "^2.1.0"
|
||||
}
|
||||
},
|
||||
@@ -21745,9 +21734,9 @@
|
||||
"dev": true
|
||||
},
|
||||
"@stencil/core": {
|
||||
"version": "2.8.1",
|
||||
"resolved": "https://registry.npmjs.org/@stencil/core/-/core-2.8.1.tgz",
|
||||
"integrity": "sha512-iv9J6oLO/lv7/aO45M05yw3pp1J7olY400vlOZgdMVs3s5zHfalY1ZPYM0KyqU4+7DZuadKYbd0aQZ/g2PInZw=="
|
||||
"version": "2.14.2",
|
||||
"resolved": "https://registry.npmjs.org/@stencil/core/-/core-2.14.2.tgz",
|
||||
"integrity": "sha512-NMC5Xi8sPFJxaO4rz6CbMHuD6PteE/RJWtjrbkusmpjKRtMXkfZJPIgOrleZ4xO+vXcNyL535Ru7vUADqEsTiQ=="
|
||||
},
|
||||
"@tootallnate/once": {
|
||||
"version": "1.1.2",
|
||||
@@ -27057,11 +27046,18 @@
|
||||
"dev": true
|
||||
},
|
||||
"ionicons": {
|
||||
"version": "5.5.3",
|
||||
"resolved": "https://registry.npmjs.org/ionicons/-/ionicons-5.5.3.tgz",
|
||||
"integrity": "sha512-L71djrMi8pAad66tpwdnO1vwcyluCFvehzxU1PpH1k/HpYBZhZ5IaYhqXipmqUvu5aEbd4cbRguYyI5Fd4bxTw==",
|
||||
"version": "6.0.1",
|
||||
"resolved": "https://registry.npmjs.org/ionicons/-/ionicons-6.0.1.tgz",
|
||||
"integrity": "sha512-xQekOJsxH82O7oB+3F60zeRggCdND9pJ/k0E6IJDVUGGlCj5mlyFqNgxUimytKgstPGv3S+3EmCxjefvtGgWUg==",
|
||||
"requires": {
|
||||
"@stencil/core": "^2.5.0"
|
||||
"@stencil/core": "~2.12.0"
|
||||
},
|
||||
"dependencies": {
|
||||
"@stencil/core": {
|
||||
"version": "2.12.1",
|
||||
"resolved": "https://registry.npmjs.org/@stencil/core/-/core-2.12.1.tgz",
|
||||
"integrity": "sha512-u24TZ+FEvjnZt5ZgIkLjLpUNsO6Ml3mUZqwmqk81w6RWWz75hgB5p4RFI5rvuErFeh2xvMIGo+pNdG24XUBz1A=="
|
||||
}
|
||||
}
|
||||
},
|
||||
"ip": {
|
||||
@@ -27555,8 +27551,7 @@
|
||||
"jsonc-parser": {
|
||||
"version": "3.0.0",
|
||||
"resolved": "https://registry.npmjs.org/jsonc-parser/-/jsonc-parser-3.0.0.tgz",
|
||||
"integrity": "sha512-fQzRfAbIBnR0IQvftw9FJveWiHp72Fg20giDrHz6TdfB12UH/uue0D3hm57UB5KgAVuniLMCaS8P1IMj9NR7cA==",
|
||||
"dev": true
|
||||
"integrity": "sha512-fQzRfAbIBnR0IQvftw9FJveWiHp72Fg20giDrHz6TdfB12UH/uue0D3hm57UB5KgAVuniLMCaS8P1IMj9NR7cA=="
|
||||
},
|
||||
"jsonfile": {
|
||||
"version": "3.0.1",
|
||||
|
||||
@@ -29,8 +29,8 @@
|
||||
"@angular/platform-browser-dynamic": "^13.1.3",
|
||||
"@angular/platform-server": "^13.1.3",
|
||||
"@angular/router": "^13.1.3",
|
||||
"@ionic/angular": "^5.3.1",
|
||||
"@ionic/angular-server": "^5.3.1",
|
||||
"@ionic/angular": "^6.0.12",
|
||||
"@ionic/angular-server": "^6.0.12",
|
||||
"@nguniversal/express-engine": "^12.1.1",
|
||||
"angular-in-memory-web-api": "^0.11.0",
|
||||
"core-js": "^2.6.11",
|
||||
|
||||
@@ -12,6 +12,7 @@
|
||||
<h1>Value</h1>
|
||||
<h2>{{value}}</h2>
|
||||
<h3>{{valueFromParams}}</h3>
|
||||
<p>modal is defined: <span id="modalInstance">{{ !!modal }}</span></p>
|
||||
<p>ngOnInit: <span id="ngOnInit">{{onInit}}</span></p>
|
||||
<p>ionViewWillEnter: <span id="ionViewWillEnter">{{willEnter}}</span></p>
|
||||
<p>ionViewDidEnter: <span id="ionViewDidEnter">{{didEnter}}</span></p>
|
||||
|
||||
@@ -16,6 +16,8 @@ export class ModalExampleComponent implements OnInit, ViewWillLeave, ViewDidEnte
|
||||
willLeave = 0;
|
||||
didLeave = 0;
|
||||
|
||||
modal: HTMLElement;
|
||||
|
||||
constructor(
|
||||
private modalCtrl: ModalController,
|
||||
@Optional() public nav: IonNav,
|
||||
|
||||
@@ -1,8 +1,16 @@
|
||||
import { Component } from '@angular/core';
|
||||
import { Component, NgZone, OnDestroy, OnInit } from '@angular/core';
|
||||
|
||||
@Component({
|
||||
selector: 'app-nested-outlet-page',
|
||||
templateUrl: './nested-outlet-page.component.html',
|
||||
})
|
||||
export class NestedOutletPageComponent {
|
||||
export class NestedOutletPageComponent implements OnDestroy, OnInit {
|
||||
|
||||
ngOnInit() {
|
||||
NgZone.assertInAngularZone();
|
||||
}
|
||||
|
||||
ngOnDestroy() {
|
||||
NgZone.assertInAngularZone();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
<ion-content>
|
||||
<h1>Nested page 2</h1>
|
||||
<p>
|
||||
<ion-button routerLink="/nested-outlet/page">Go To FIRST</ion-button>
|
||||
</p>
|
||||
</ion-content>
|
||||
<h1>Nested page 2</h1>
|
||||
<p>
|
||||
<ion-button routerLink="/nested-outlet/page" id="goto-nested-page1">Go To FIRST</ion-button>
|
||||
</p>
|
||||
</ion-content>
|
||||
|
||||
@@ -1,8 +1,16 @@
|
||||
import { Component } from '@angular/core';
|
||||
import { Component, NgZone, OnDestroy, OnInit } from '@angular/core';
|
||||
|
||||
@Component({
|
||||
selector: 'app-nested-outlet-page2',
|
||||
templateUrl: './nested-outlet-page2.component.html',
|
||||
})
|
||||
export class NestedOutletPage2Component {
|
||||
export class NestedOutletPage2Component implements OnDestroy, OnInit {
|
||||
|
||||
ngOnInit() {
|
||||
NgZone.assertInAngularZone();
|
||||
}
|
||||
|
||||
ngOnDestroy() {
|
||||
NgZone.assertInAngularZone();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3,6 +3,30 @@
|
||||
All notable changes to this project will be documented in this file.
|
||||
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
|
||||
|
||||
## [6.0.13](https://github.com/ionic-team/ionic/compare/v6.0.12...v6.0.13) (2022-03-23)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* **datetime:** presentation time emits ionChange once ([#24968](https://github.com/ionic-team/ionic/issues/24968)) ([2909b08](https://github.com/ionic-team/ionic/commit/2909b080b7020299a4554c1459b4b190ff739085)), closes [#24967](https://github.com/ionic-team/ionic/issues/24967)
|
||||
* **popover:** dismissing nested popover via backdrop now works ([#24957](https://github.com/ionic-team/ionic/issues/24957)) ([9e84ef7](https://github.com/ionic-team/ionic/commit/9e84ef7f91d76ca5a1ecaffc7592287267d5368b)), closes [#24954](https://github.com/ionic-team/ionic/issues/24954)
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
## [6.0.12](https://github.com/ionic-team/ionic/compare/v6.0.11...v6.0.12) (2022-03-16)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* **datetime:** reinit behavior on presentation change ([#24828](https://github.com/ionic-team/ionic/issues/24828)) ([d46e1e8](https://github.com/ionic-team/ionic/commit/d46e1e8506ca5095817b421e9edb37d41451e885))
|
||||
* **toast:** screen readers now announce toasts when presented ([#24937](https://github.com/ionic-team/ionic/issues/24937)) ([8a97f6b](https://github.com/ionic-team/ionic/commit/8a97f6b5c9ca1e77c1790abd1e924955b6b6ea27)), closes [#22333](https://github.com/ionic-team/ionic/issues/22333)
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
## [6.0.11](https://github.com/ionic-team/ionic/compare/v6.0.10...v6.0.11) (2022-03-09)
|
||||
|
||||
|
||||
|
||||
18
core/package-lock.json
generated
18
core/package-lock.json
generated
@@ -1,15 +1,15 @@
|
||||
{
|
||||
"name": "@ionic/core",
|
||||
"version": "6.0.11",
|
||||
"version": "6.0.13",
|
||||
"lockfileVersion": 2,
|
||||
"requires": true,
|
||||
"packages": {
|
||||
"": {
|
||||
"name": "@ionic/core",
|
||||
"version": "6.0.10",
|
||||
"version": "6.0.12",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@stencil/core": "^2.14.1",
|
||||
"@stencil/core": "^2.14.2",
|
||||
"ionicons": "^6.0.0",
|
||||
"tslib": "^2.1.0"
|
||||
},
|
||||
@@ -1366,9 +1366,9 @@
|
||||
}
|
||||
},
|
||||
"node_modules/@stencil/core": {
|
||||
"version": "2.14.1",
|
||||
"resolved": "https://registry.npmjs.org/@stencil/core/-/core-2.14.1.tgz",
|
||||
"integrity": "sha512-G58fJeDbi58+7uQnyaGInnehfub9tJikFZ4PkT/FuelMV9wGq2FKB0fxKctKQ3mhhHAiFDuGNzRD1isZZQvUCg==",
|
||||
"version": "2.14.2",
|
||||
"resolved": "https://registry.npmjs.org/@stencil/core/-/core-2.14.2.tgz",
|
||||
"integrity": "sha512-NMC5Xi8sPFJxaO4rz6CbMHuD6PteE/RJWtjrbkusmpjKRtMXkfZJPIgOrleZ4xO+vXcNyL535Ru7vUADqEsTiQ==",
|
||||
"bin": {
|
||||
"stencil": "bin/stencil"
|
||||
},
|
||||
@@ -15055,9 +15055,9 @@
|
||||
"dev": true
|
||||
},
|
||||
"@stencil/core": {
|
||||
"version": "2.14.1",
|
||||
"resolved": "https://registry.npmjs.org/@stencil/core/-/core-2.14.1.tgz",
|
||||
"integrity": "sha512-G58fJeDbi58+7uQnyaGInnehfub9tJikFZ4PkT/FuelMV9wGq2FKB0fxKctKQ3mhhHAiFDuGNzRD1isZZQvUCg=="
|
||||
"version": "2.14.2",
|
||||
"resolved": "https://registry.npmjs.org/@stencil/core/-/core-2.14.2.tgz",
|
||||
"integrity": "sha512-NMC5Xi8sPFJxaO4rz6CbMHuD6PteE/RJWtjrbkusmpjKRtMXkfZJPIgOrleZ4xO+vXcNyL535Ru7vUADqEsTiQ=="
|
||||
},
|
||||
"@stencil/react-output-target": {
|
||||
"version": "0.2.1",
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@ionic/core",
|
||||
"version": "6.0.11",
|
||||
"version": "6.0.13",
|
||||
"description": "Base components for Ionic",
|
||||
"keywords": [
|
||||
"ionic",
|
||||
@@ -31,7 +31,7 @@
|
||||
"loader/"
|
||||
],
|
||||
"dependencies": {
|
||||
"@stencil/core": "^2.14.1",
|
||||
"@stencil/core": "^2.14.2",
|
||||
"ionicons": "^6.0.0",
|
||||
"tslib": "^2.1.0"
|
||||
},
|
||||
|
||||
15
core/src/components.d.ts
vendored
15
core/src/components.d.ts
vendored
@@ -1254,11 +1254,11 @@ export namespace Components {
|
||||
}
|
||||
interface IonItemSliding {
|
||||
/**
|
||||
* Close the sliding item. Items can also be closed from the [List](../list).
|
||||
* Close the sliding item. Items can also be closed from the [List](./list).
|
||||
*/
|
||||
"close": () => Promise<void>;
|
||||
/**
|
||||
* Close all of the sliding items in the list. Items can also be closed from the [List](../list).
|
||||
* Close all of the sliding items in the list. Items can also be closed from the [List](./list).
|
||||
*/
|
||||
"closeOpened": () => Promise<boolean>;
|
||||
/**
|
||||
@@ -2425,7 +2425,7 @@ export namespace Components {
|
||||
*/
|
||||
"interface": SelectInterface;
|
||||
/**
|
||||
* Any additional options that the `alert`, `action-sheet` or `popover` interface can take. See the [ion-alert docs](../alert), the [ion-action-sheet docs](../action-sheet) and the [ion-popover docs](../popover) for the create options for each interface. Note: `interfaceOptions` will not override `inputs` or `buttons` with the `alert` interface.
|
||||
* Any additional options that the `alert`, `action-sheet` or `popover` interface can take. See the [ion-alert docs](./alert), the [ion-action-sheet docs](./action-sheet) and the [ion-popover docs](./popover) for the create options for each interface. Note: `interfaceOptions` will not override `inputs` or `buttons` with the `alert` interface.
|
||||
*/
|
||||
"interfaceOptions": any;
|
||||
/**
|
||||
@@ -2512,7 +2512,7 @@ export namespace Components {
|
||||
*/
|
||||
"getPreviousIndex": () => Promise<number>;
|
||||
/**
|
||||
* Get the Swiper instance. Use this to access the full Swiper API. See https://idangero.us/swiper/api/ for all API options.
|
||||
* Get the Swiper instance. Use this to access the full Swiper API. See https://swiperjs.com/swiper-api for all API options.
|
||||
*/
|
||||
"getSwiper": () => Promise<any>;
|
||||
/**
|
||||
@@ -2547,7 +2547,7 @@ export namespace Components {
|
||||
*/
|
||||
"mode"?: "ios" | "md";
|
||||
/**
|
||||
* Options to pass to the swiper instance. See http://idangero.us/swiper/api/ for valid options
|
||||
* Options to pass to the swiper instance. See https://swiperjs.com/swiper-api for valid options
|
||||
*/
|
||||
"options": any;
|
||||
/**
|
||||
@@ -6128,7 +6128,7 @@ declare namespace LocalJSX {
|
||||
*/
|
||||
"interface"?: SelectInterface;
|
||||
/**
|
||||
* Any additional options that the `alert`, `action-sheet` or `popover` interface can take. See the [ion-alert docs](../alert), the [ion-action-sheet docs](../action-sheet) and the [ion-popover docs](../popover) for the create options for each interface. Note: `interfaceOptions` will not override `inputs` or `buttons` with the `alert` interface.
|
||||
* Any additional options that the `alert`, `action-sheet` or `popover` interface can take. See the [ion-alert docs](./alert), the [ion-action-sheet docs](./action-sheet) and the [ion-popover docs](./popover) for the create options for each interface. Note: `interfaceOptions` will not override `inputs` or `buttons` with the `alert` interface.
|
||||
*/
|
||||
"interfaceOptions"?: any;
|
||||
/**
|
||||
@@ -6290,7 +6290,7 @@ declare namespace LocalJSX {
|
||||
*/
|
||||
"onIonSlidesDidLoad"?: (event: CustomEvent<void>) => void;
|
||||
/**
|
||||
* Options to pass to the swiper instance. See http://idangero.us/swiper/api/ for valid options
|
||||
* Options to pass to the swiper instance. See https://swiperjs.com/swiper-api for valid options
|
||||
*/
|
||||
"options"?: any;
|
||||
/**
|
||||
@@ -6359,6 +6359,7 @@ declare namespace LocalJSX {
|
||||
* The mode determines which platform styles to use.
|
||||
*/
|
||||
"mode"?: "ios" | "md";
|
||||
"onIonStyle"?: (event: CustomEvent<StyleEventDetail>) => void;
|
||||
"onIonTabBarChanged"?: (event: CustomEvent<TabBarChangedEventDetail>) => void;
|
||||
/**
|
||||
* The selected tab component
|
||||
|
||||
@@ -94,9 +94,13 @@ export class Datetime implements ComponentInterface {
|
||||
|
||||
private destroyCalendarIO?: () => void;
|
||||
private destroyKeyboardMO?: () => void;
|
||||
private destroyOverlayListener?: () => void;
|
||||
|
||||
private minParts?: any;
|
||||
private maxParts?: any;
|
||||
private todayParts = parseDate(getToday());
|
||||
|
||||
private prevPresentation: string | null = null;
|
||||
|
||||
/**
|
||||
* Duplicate reference to `activeParts` that does not trigger a re-render of the component.
|
||||
@@ -124,8 +128,6 @@ export class Datetime implements ComponentInterface {
|
||||
ampm: 'pm'
|
||||
}
|
||||
|
||||
private todayParts = parseDate(getToday())
|
||||
|
||||
@Element() el!: HTMLIonDatetimeElement;
|
||||
|
||||
@State() isPresented = false;
|
||||
@@ -483,8 +485,18 @@ export class Datetime implements ComponentInterface {
|
||||
this.confirm();
|
||||
}
|
||||
|
||||
/**
|
||||
* Stencil sometimes sets calendarBodyRef to null on rerender, even though
|
||||
* the element is present. Query for it manually as a fallback.
|
||||
*
|
||||
* TODO(FW-901) Remove when issue is resolved: https://github.com/ionic-team/stencil/issues/3253
|
||||
*/
|
||||
private getCalendarBodyEl = () => {
|
||||
return this.calendarBodyRef || this.el.shadowRoot?.querySelector('.calendar-body');
|
||||
};
|
||||
|
||||
private initializeKeyboardListeners = () => {
|
||||
const { calendarBodyRef } = this;
|
||||
const calendarBodyRef = this.getCalendarBodyEl();
|
||||
if (!calendarBodyRef) { return; }
|
||||
|
||||
const root = this.el!.shadowRoot!;
|
||||
@@ -530,7 +542,7 @@ export class Datetime implements ComponentInterface {
|
||||
* We must use keydown not keyup as we want
|
||||
* to prevent scrolling when using the arrow keys.
|
||||
*/
|
||||
this.calendarBodyRef!.addEventListener('keydown', (ev: KeyboardEvent) => {
|
||||
calendarBodyRef.addEventListener('keydown', (ev: KeyboardEvent) => {
|
||||
const activeElement = root.activeElement;
|
||||
if (!activeElement || !activeElement.classList.contains('calendar-day')) { return; }
|
||||
|
||||
@@ -657,7 +669,7 @@ export class Datetime implements ComponentInterface {
|
||||
}
|
||||
|
||||
private initializeCalendarIOListeners = () => {
|
||||
const { calendarBodyRef } = this;
|
||||
const calendarBodyRef = this.getCalendarBodyEl();
|
||||
if (!calendarBodyRef) { return; }
|
||||
|
||||
const mode = getIonMode(this);
|
||||
@@ -873,7 +885,7 @@ export class Datetime implements ComponentInterface {
|
||||
* listener. This is so that we can re-create the listeners
|
||||
* if the datetime has been hidden/presented by a modal or popover.
|
||||
*/
|
||||
private destroyListeners = () => {
|
||||
private destroyInteractionListeners = () => {
|
||||
const { destroyCalendarIO, destroyKeyboardMO } = this;
|
||||
|
||||
if (destroyCalendarIO !== undefined) {
|
||||
@@ -885,6 +897,12 @@ export class Datetime implements ComponentInterface {
|
||||
}
|
||||
}
|
||||
|
||||
private initializeListeners() {
|
||||
this.initializeCalendarIOListeners();
|
||||
this.initializeKeyboardListeners();
|
||||
this.initializeOverlayListener();
|
||||
}
|
||||
|
||||
componentDidLoad() {
|
||||
/**
|
||||
* If a scrollable element is hidden using `display: none`,
|
||||
@@ -898,9 +916,7 @@ export class Datetime implements ComponentInterface {
|
||||
const ev = entries[0];
|
||||
if (!ev.isIntersecting) { return; }
|
||||
|
||||
this.initializeCalendarIOListeners();
|
||||
this.initializeKeyboardListeners();
|
||||
this.initializeOverlayListener();
|
||||
this.initializeListeners();
|
||||
|
||||
/**
|
||||
* TODO: Datetime needs a frame to ensure that it
|
||||
@@ -936,7 +952,7 @@ export class Datetime implements ComponentInterface {
|
||||
const ev = entries[0];
|
||||
if (ev.isIntersecting) { return; }
|
||||
|
||||
this.destroyListeners();
|
||||
this.destroyInteractionListeners();
|
||||
|
||||
writeTask(() => {
|
||||
this.el.classList.remove('datetime-ready');
|
||||
@@ -959,6 +975,29 @@ export class Datetime implements ComponentInterface {
|
||||
root.addEventListener('ionBlur', (ev: Event) => ev.stopPropagation());
|
||||
}
|
||||
|
||||
/**
|
||||
* When the presentation is changed, all calendar content is recreated,
|
||||
* so we need to re-init behavior with the new elements.
|
||||
*/
|
||||
componentDidRender() {
|
||||
const { presentation, prevPresentation } = this;
|
||||
|
||||
if (prevPresentation === null) {
|
||||
this.prevPresentation = presentation;
|
||||
return;
|
||||
}
|
||||
|
||||
if (presentation === prevPresentation) { return; }
|
||||
this.prevPresentation = presentation;
|
||||
|
||||
this.destroyInteractionListeners();
|
||||
if (this.destroyOverlayListener !== undefined) {
|
||||
this.destroyOverlayListener();
|
||||
}
|
||||
|
||||
this.initializeListeners();
|
||||
}
|
||||
|
||||
/**
|
||||
* When doing subsequent presentations of an inline
|
||||
* overlay, the IO callback will fire again causing
|
||||
@@ -970,9 +1009,15 @@ export class Datetime implements ComponentInterface {
|
||||
const overlay = this.el.closest('ion-popover, ion-modal');
|
||||
if (overlay === null) { return; }
|
||||
|
||||
overlay.addEventListener('willPresent', () => {
|
||||
const overlayListener = () => {
|
||||
this.overlayIsPresenting = true;
|
||||
});
|
||||
};
|
||||
|
||||
overlay.addEventListener('willPresent', overlayListener);
|
||||
|
||||
this.destroyOverlayListener = () => {
|
||||
overlay.removeEventListener('willPresent', overlayListener);
|
||||
};
|
||||
}
|
||||
|
||||
private processValue = (value?: string | null) => {
|
||||
@@ -1034,7 +1079,7 @@ export class Datetime implements ComponentInterface {
|
||||
}
|
||||
|
||||
private nextMonth = () => {
|
||||
const { calendarBodyRef } = this;
|
||||
const calendarBodyRef = this.getCalendarBodyEl();
|
||||
if (!calendarBodyRef) { return; }
|
||||
|
||||
const nextMonth = calendarBodyRef.querySelector('.calendar-month:last-of-type');
|
||||
@@ -1050,7 +1095,7 @@ export class Datetime implements ComponentInterface {
|
||||
}
|
||||
|
||||
private prevMonth = () => {
|
||||
const { calendarBodyRef } = this;
|
||||
const calendarBodyRef = this.getCalendarBodyEl();
|
||||
if (!calendarBodyRef) { return; }
|
||||
|
||||
const prevMonth = calendarBodyRef.querySelector('.calendar-month:first-of-type');
|
||||
|
||||
@@ -52,3 +52,41 @@ test('display', async () => {
|
||||
expect(screenshotCompare).toMatchScreenshot();
|
||||
}
|
||||
});
|
||||
|
||||
test('month selection should work after changing presentation', async () => {
|
||||
const page = await newE2EPage({
|
||||
url: '/src/components/datetime/test/display?ionic:_testing=true'
|
||||
});
|
||||
const ionWorkingPartsDidChange = await page.spyOnEvent('ionWorkingPartsDidChange', 'document');
|
||||
let calendarMonthYear;
|
||||
|
||||
await page.select('#presentation', 'date-time');
|
||||
await page.waitForChanges();
|
||||
|
||||
await page.select('#presentation', 'time-date');
|
||||
await page.waitForChanges();
|
||||
|
||||
const nextMonthButton = await page.find('ion-datetime >>> .calendar-next-prev ion-button + ion-button');
|
||||
await nextMonthButton.click();
|
||||
await page.waitForChanges();
|
||||
|
||||
await ionWorkingPartsDidChange.next();
|
||||
|
||||
calendarMonthYear = await page.find('ion-datetime >>> .calendar-month-year');
|
||||
|
||||
expect(calendarMonthYear.textContent).toContain('March 2022');
|
||||
|
||||
// ensure it still works if presentation is changed more than once
|
||||
await page.select('#presentation', 'date-time');
|
||||
await page.waitForChanges();
|
||||
|
||||
const prevMonthButton = await page.find('ion-datetime >>> .calendar-next-prev ion-button:first-child');
|
||||
await prevMonthButton.click();
|
||||
await page.waitForChanges();
|
||||
|
||||
await ionWorkingPartsDidChange.next();
|
||||
|
||||
calendarMonthYear = await page.find('ion-datetime >>> .calendar-month-year');
|
||||
|
||||
expect(calendarMonthYear.textContent).toContain('February 2022');
|
||||
});
|
||||
|
||||
@@ -1,52 +1,80 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="en" dir="ltr">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<title>Datetime - Standalone</title>
|
||||
<meta name="viewport"
|
||||
content="width=device-width, initial-scale=1.0, minimum-scale=1.0">
|
||||
<link href="../../../../../css/ionic.bundle.css" rel="stylesheet">
|
||||
<link href="../../../../../scripts/testing/styles.css" rel="stylesheet">
|
||||
<script src="../../../../../scripts/testing/scripts.js"></script>
|
||||
<script type="module" src="../../../../../dist/ionic/ionic.esm.js"></script>
|
||||
<style>
|
||||
body {
|
||||
padding: 20px;
|
||||
}
|
||||
ion-datetime {
|
||||
border: 1px solid black;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<label for="presentation">Presentation</label>
|
||||
<select id="presentation" onchange="changePresentation(event)">
|
||||
<option value="date-time" selected>date-time</option>
|
||||
<option value="time-date">time-date</option>
|
||||
<option value="date">date</option>
|
||||
<option value="time">time</option>
|
||||
</select>
|
||||
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<title>Datetime - Standalone</title>
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0, minimum-scale=1.0">
|
||||
<link href="../../../../../css/ionic.bundle.css" rel="stylesheet">
|
||||
<link href="../../../../../scripts/testing/styles.css" rel="stylesheet">
|
||||
<script src="../../../../../scripts/testing/scripts.js"></script>
|
||||
<script type="module" src="../../../../../dist/ionic/ionic.esm.js"></script>
|
||||
<style>
|
||||
body {
|
||||
padding: 20px;
|
||||
}
|
||||
|
||||
ion-datetime {
|
||||
border: 1px solid black;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<label for="presentation">Presentation</label>
|
||||
<select id="presentation" onchange="changePresentation(event)">
|
||||
<option value="date-time" selected>date-time</option>
|
||||
<option value="time-date">time-date</option>
|
||||
<option value="date">date</option>
|
||||
<option value="time">time</option>
|
||||
</select>
|
||||
|
||||
|
||||
<label for="size">Size</label>
|
||||
<select id="size" onchange="changeSize(event)">
|
||||
<option value="fixed" selected>fixed</option>
|
||||
<option value="cover">cover</option>
|
||||
</select>
|
||||
<label for="size">Size</label>
|
||||
<select id="size" onchange="changeSize(event)">
|
||||
<option value="fixed" selected>fixed</option>
|
||||
<option value="cover">cover</option>
|
||||
</select>
|
||||
|
||||
<br /><br />
|
||||
<br /><br />
|
||||
|
||||
<ion-datetime></ion-datetime>
|
||||
<ion-datetime value="2022-02-22"></ion-datetime>
|
||||
|
||||
<script>
|
||||
const datetime = document.querySelector('ion-datetime');
|
||||
<script>
|
||||
const datetime = document.querySelector('ion-datetime');
|
||||
|
||||
const mutationObserver = new MutationObserver(() => {
|
||||
document.dispatchEvent(new CustomEvent('ionWorkingPartsDidChange'));
|
||||
});
|
||||
|
||||
const initCalendarMonthChangeObserver = async () => {
|
||||
if (!datetime.componentOnReady) return;
|
||||
await datetime.componentOnReady();
|
||||
|
||||
// We have to requestAnimationFrame to allow the datetime to render completely.
|
||||
requestAnimationFrame(() => {
|
||||
const calendarBody = datetime.shadowRoot.querySelector('.calendar-body');
|
||||
if (calendarBody) {
|
||||
mutationObserver.observe(calendarBody, {
|
||||
childList: true,
|
||||
subtree: true
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
const changePresentation = (ev) => {
|
||||
mutationObserver.disconnect();
|
||||
datetime.presentation = ev.target.value;
|
||||
initCalendarMonthChangeObserver();
|
||||
};
|
||||
|
||||
const changeSize = (ev) => {
|
||||
datetime.size = ev.target.value;
|
||||
};
|
||||
|
||||
initCalendarMonthChangeObserver();
|
||||
</script>
|
||||
</body>
|
||||
|
||||
const changePresentation = (ev) => {
|
||||
datetime.presentation = ev.target.value;
|
||||
}
|
||||
const changeSize = (ev) => {
|
||||
datetime.size = ev.target.value;
|
||||
}
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { newE2EPage } from '@stencil/core/testing';
|
||||
import { newE2EPage, E2EPage } from '@stencil/core/testing';
|
||||
|
||||
test('presentation', async () => {
|
||||
const page = await newE2EPage({
|
||||
@@ -13,3 +13,37 @@ test('presentation', async () => {
|
||||
expect(screenshotCompare).toMatchScreenshot();
|
||||
}
|
||||
});
|
||||
|
||||
describe('presentation: time', () => {
|
||||
|
||||
let page: E2EPage;
|
||||
|
||||
beforeEach(async () => {
|
||||
page = await newE2EPage({
|
||||
url: '/src/components/datetime/test/presentation?ionic:_testing=true'
|
||||
});
|
||||
});
|
||||
|
||||
describe('when the time picker is visible in the view', () => {
|
||||
|
||||
it('manually setting the value should emit ionChange once', async () => {
|
||||
const datetime = await page.find('ion-datetime[presentation="time"]');
|
||||
const didChange = await datetime.spyOnEvent('ionChange');
|
||||
|
||||
await page.$eval('ion-datetime[presentation="time"]', (el: any) => {
|
||||
el.scrollIntoView();
|
||||
});
|
||||
|
||||
await page.$eval('ion-datetime[presentation="time"]', (el: any) => {
|
||||
el.value = '06:02:40';
|
||||
});
|
||||
|
||||
await page.waitForChanges();
|
||||
|
||||
expect(didChange).toHaveReceivedEventTimes(1);
|
||||
expect(didChange).toHaveReceivedEventDetail({ value: '06:02:40' });
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
@@ -44,7 +44,7 @@
|
||||
|
||||
|
||||
:host(.fab-vertical-bottom) {
|
||||
bottom: $fab-content-margin;
|
||||
bottom: var(--tab-translucent-safe-area, $fab-content-margin);
|
||||
}
|
||||
|
||||
:host(.fab-vertical-bottom.fab-edge) {
|
||||
|
||||
@@ -15,5 +15,5 @@ ion-footer {
|
||||
}
|
||||
|
||||
ion-footer ion-toolbar:last-of-type {
|
||||
padding-bottom: var(--ion-safe-area-bottom, 0);
|
||||
}
|
||||
padding-bottom: calc(var(--ion-safe-area-bottom, 0) + var(--tab-translucent-safe-area, 0));
|
||||
}
|
||||
|
||||
@@ -168,7 +168,7 @@ export class ItemSliding implements ComponentInterface {
|
||||
}
|
||||
|
||||
/**
|
||||
* Close the sliding item. Items can also be closed from the [List](../list).
|
||||
* Close the sliding item. Items can also be closed from the [List](./list).
|
||||
*/
|
||||
@Method()
|
||||
async close() {
|
||||
@@ -176,7 +176,7 @@ export class ItemSliding implements ComponentInterface {
|
||||
}
|
||||
|
||||
/**
|
||||
* Close all of the sliding items in the list. Items can also be closed from the [List](../list).
|
||||
* Close all of the sliding items in the list. Items can also be closed from the [List](./list).
|
||||
*/
|
||||
@Method()
|
||||
async closeOpened(): Promise<boolean> {
|
||||
|
||||
@@ -250,9 +250,10 @@ import { ModalPage } from '../modal/modal.page';
|
||||
styleUrls: ['./modal-example.css']
|
||||
})
|
||||
export class ModalExample {
|
||||
constructor(public modalController: ModalController) {
|
||||
// The `ion-modal` element reference.
|
||||
modal: HTMLElement;
|
||||
|
||||
}
|
||||
constructor(public modalController: ModalController) {}
|
||||
|
||||
async presentModal() {
|
||||
const modal = await this.modalController.create({
|
||||
@@ -337,6 +338,22 @@ const { data } = await modal.onWillDismiss();
|
||||
console.log(data);
|
||||
```
|
||||
|
||||
#### Accessing the Modal Element
|
||||
|
||||
When opening a modal with the modal controller, Ionic will assign the modal HTML element reference to the `modal` property on your component's class instance.
|
||||
|
||||
You can use this property to directly access the `ion-modal` element to add or remove classes or handle additional checks.
|
||||
|
||||
```ts
|
||||
export class ModalPage implements OnInit {
|
||||
// The `ion-modal` element reference.
|
||||
modal: HTMLElement;
|
||||
|
||||
ngOnInit() {
|
||||
console.log('The HTML ion-modal element', this.modal); // <ion-modal></ion-modal>
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
#### Lazy Loading
|
||||
|
||||
|
||||
@@ -73,9 +73,10 @@ import { ModalPage } from '../modal/modal.page';
|
||||
styleUrls: ['./modal-example.css']
|
||||
})
|
||||
export class ModalExample {
|
||||
constructor(public modalController: ModalController) {
|
||||
// The `ion-modal` element reference.
|
||||
modal: HTMLElement;
|
||||
|
||||
}
|
||||
constructor(public modalController: ModalController) {}
|
||||
|
||||
async presentModal() {
|
||||
const modal = await this.modalController.create({
|
||||
@@ -160,6 +161,22 @@ const { data } = await modal.onWillDismiss();
|
||||
console.log(data);
|
||||
```
|
||||
|
||||
#### Accessing the Modal Element
|
||||
|
||||
When opening a modal with the modal controller, Ionic will assign the modal HTML element reference to the `modal` property on your component's class instance.
|
||||
|
||||
You can use this property to directly access the `ion-modal` element to add or remove classes or handle additional checks.
|
||||
|
||||
```ts
|
||||
export class ModalPage implements OnInit {
|
||||
// The `ion-modal` element reference.
|
||||
modal: HTMLElement;
|
||||
|
||||
ngOnInit() {
|
||||
console.log('The HTML ion-modal element', this.modal); // <ion-modal></ion-modal>
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
#### Lazy Loading
|
||||
|
||||
|
||||
@@ -67,16 +67,10 @@ export class PickerColumnInternal implements ComponentInterface {
|
||||
valueChange() {
|
||||
if (this.isColumnVisible) {
|
||||
/**
|
||||
* Only scroll the active item into view and emit the value
|
||||
* change, when the picker column is actively visible to the user.
|
||||
* Only scroll the active item into view when the picker column
|
||||
* is actively visible to the user.
|
||||
*/
|
||||
const { items, value } = this;
|
||||
this.scrollActiveItemIntoView();
|
||||
|
||||
const findItem = items.find(item => item.value === value);
|
||||
if (findItem) {
|
||||
this.ionChange.emit(findItem);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -133,7 +127,7 @@ export class PickerColumnInternal implements ComponentInterface {
|
||||
* first item to match the scroll position of the column.
|
||||
*
|
||||
*/
|
||||
this.value = items[0].value;
|
||||
this.setValue(items[0].value);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -148,6 +142,15 @@ export class PickerColumnInternal implements ComponentInterface {
|
||||
}
|
||||
}
|
||||
|
||||
private setValue(value?: string | number) {
|
||||
const { items } = this;
|
||||
this.value = value;
|
||||
const findItem = items.find(item => item.value === value);
|
||||
if (findItem) {
|
||||
this.ionChange.emit(findItem);
|
||||
}
|
||||
}
|
||||
|
||||
private centerPickerItemInView = (target: HTMLElement, smooth = true) => {
|
||||
const { el, isColumnVisible } = this;
|
||||
if (isColumnVisible) {
|
||||
@@ -250,7 +253,7 @@ export class PickerColumnInternal implements ComponentInterface {
|
||||
const selectedItem = this.items[index];
|
||||
|
||||
if (selectedItem.value !== this.value) {
|
||||
this.value = selectedItem.value;
|
||||
this.setValue(selectedItem.value);
|
||||
hapticSelectionEnd();
|
||||
this.hapticsStarted = false;
|
||||
}
|
||||
|
||||
@@ -51,6 +51,30 @@ describe('picker-column-internal', () => {
|
||||
expect(activeColumn.innerText).toEqual('23');
|
||||
});
|
||||
|
||||
it('should not emit ionChange when the value is modified externally', async () => {
|
||||
const pickerColumn = await page.find('#default');
|
||||
const ionChangeSpy = await pickerColumn.spyOnEvent('ionChange');
|
||||
|
||||
await page.$eval('#default', (el: any) => {
|
||||
el.value = '12';
|
||||
});
|
||||
|
||||
expect(ionChangeSpy).not.toHaveReceivedEvent();
|
||||
});
|
||||
|
||||
it('should emit ionChange when the picker is scrolled', async () => {
|
||||
const pickerColumn = await page.find('#default');
|
||||
const ionChangeSpy = await pickerColumn.spyOnEvent('ionChange');
|
||||
|
||||
await page.$eval('#default', (el: any) => {
|
||||
el.scrollTo(0, 300);
|
||||
});
|
||||
|
||||
await ionChangeSpy.next();
|
||||
|
||||
expect(ionChangeSpy).toHaveReceivedEvent();
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
@@ -44,6 +44,25 @@
|
||||
z-index: $z-index-overlay;
|
||||
}
|
||||
|
||||
/**
|
||||
* With nested popovers, only the popover that
|
||||
* was first presented has a popover. This is the
|
||||
* parent popover and allows us to easily
|
||||
* track all nested popovers from a single backdrop.
|
||||
* As a result, nested popovers do not have backdrops
|
||||
* and their container should not be clickable.
|
||||
* This ensures that users can click the parent backdrop
|
||||
* while still interacting with the nested popover inner
|
||||
* content.
|
||||
*/
|
||||
:host(.popover-nested) {
|
||||
pointer-events: none;
|
||||
}
|
||||
|
||||
:host(.popover-nested) .popover-wrapper {
|
||||
pointer-events: auto;
|
||||
}
|
||||
|
||||
:host(.overlay-hidden) {
|
||||
display: none;
|
||||
}
|
||||
|
||||
180
core/src/components/popover/test/nested/e2e.ts
Normal file
180
core/src/components/popover/test/nested/e2e.ts
Normal file
@@ -0,0 +1,180 @@
|
||||
import type { E2EPage } from '@stencil/core/testing';
|
||||
import { newE2EPage } from '@stencil/core/testing';
|
||||
|
||||
describe('nested popovers', () => {
|
||||
let page: E2EPage;
|
||||
|
||||
beforeEach(async () => {
|
||||
page = await newE2EPage({ url: '/src/components/popover/test/nested?ionic:_testing=true' });
|
||||
});
|
||||
|
||||
test('nested popover should render correctly', async () => {
|
||||
const screenshotCompares = [];
|
||||
|
||||
const ionPopoverDidPresent = await page.spyOnEvent('ionPopoverDidPresent');
|
||||
|
||||
await page.click('#first-trigger');
|
||||
|
||||
await ionPopoverDidPresent.next();
|
||||
|
||||
const parentPopover = await page.find('.parent-popover');
|
||||
expect(parentPopover).not.toHaveClass('overlay-hidden');
|
||||
|
||||
await page.click('#open-with-popover');
|
||||
|
||||
await ionPopoverDidPresent.next();
|
||||
|
||||
const nestedPopover = await page.find('.child-popover-one');
|
||||
expect(nestedPopover).not.toHaveClass('overlay-hidden');
|
||||
|
||||
screenshotCompares.push(await page.compareScreenshot());
|
||||
|
||||
for (const screenshotCompare of screenshotCompares) {
|
||||
expect(screenshotCompare).toMatchScreenshot();
|
||||
}
|
||||
});
|
||||
|
||||
test('nested popover should dismiss when clicking backdrop', async () => {
|
||||
const screenshotCompares = [];
|
||||
|
||||
const ionPopoverDidPresent = await page.spyOnEvent('ionPopoverDidPresent');
|
||||
const ionPopoverDidDismiss = await page.spyOnEvent('ionPopoverDidDismiss');
|
||||
|
||||
await page.click('#first-trigger');
|
||||
|
||||
await ionPopoverDidPresent.next();
|
||||
|
||||
const parentPopover = await page.find('.parent-popover');
|
||||
expect(parentPopover).not.toHaveClass('overlay-hidden');
|
||||
|
||||
await page.click('#open-with-popover');
|
||||
|
||||
await ionPopoverDidPresent.next();
|
||||
|
||||
const nestedPopover = await page.find('.child-popover-one');
|
||||
expect(nestedPopover).not.toHaveClass('overlay-hidden');
|
||||
|
||||
screenshotCompares.push(await page.compareScreenshot());
|
||||
|
||||
const backdrop = await page.find('.parent-popover >>> ion-backdrop');
|
||||
await backdrop.click();
|
||||
|
||||
await ionPopoverDidDismiss.next();
|
||||
|
||||
const nestedPopoverAgain = await page.find('.child-popover-one');
|
||||
expect(nestedPopoverAgain).toHaveClass('overlay-hidden');
|
||||
|
||||
screenshotCompares.push(await page.compareScreenshot());
|
||||
|
||||
for (const screenshotCompare of screenshotCompares) {
|
||||
expect(screenshotCompare).toMatchScreenshot();
|
||||
}
|
||||
});
|
||||
|
||||
test('nested popover should be interactive', async () => {
|
||||
const screenshotCompares = [];
|
||||
|
||||
const ionPopoverDidPresent = await page.spyOnEvent('ionPopoverDidPresent');
|
||||
|
||||
await page.click('#first-trigger');
|
||||
|
||||
await ionPopoverDidPresent.next();
|
||||
|
||||
await page.click('#share-popover');
|
||||
|
||||
await ionPopoverDidPresent.next();
|
||||
|
||||
await page.click('#share-other-popover');
|
||||
|
||||
await ionPopoverDidPresent.next();
|
||||
|
||||
const nestedPopover = await page.find('.child-popover-three');
|
||||
expect(nestedPopover).not.toHaveClass('overlay-hidden');
|
||||
|
||||
screenshotCompares.push(await page.compareScreenshot());
|
||||
|
||||
for (const screenshotCompare of screenshotCompares) {
|
||||
expect(screenshotCompare).toMatchScreenshot();
|
||||
}
|
||||
});
|
||||
|
||||
test('clicking backdrop should dismiss multiple levels of popover', async () => {
|
||||
const screenshotCompares = [];
|
||||
|
||||
const ionPopoverDidPresent = await page.spyOnEvent('ionPopoverDidPresent');
|
||||
const ionPopoverDidDismiss = await page.spyOnEvent('ionPopoverDidDismiss');
|
||||
|
||||
await page.click('#first-trigger');
|
||||
|
||||
await ionPopoverDidPresent.next();
|
||||
|
||||
await page.click('#share-popover');
|
||||
|
||||
await ionPopoverDidPresent.next();
|
||||
|
||||
await page.click('#share-other-popover');
|
||||
|
||||
await ionPopoverDidPresent.next();
|
||||
|
||||
const backdrop = await page.find('.parent-popover >>> ion-backdrop');
|
||||
await backdrop.click();
|
||||
|
||||
await ionPopoverDidDismiss.next();
|
||||
|
||||
const nestedPopoverOne = await page.find('.child-popover-one');
|
||||
expect(nestedPopoverOne).toHaveClass('overlay-hidden');
|
||||
|
||||
const nestedPopoverTwo = await page.find('.child-popover-three');
|
||||
expect(nestedPopoverTwo).toHaveClass('overlay-hidden');
|
||||
|
||||
screenshotCompares.push(await page.compareScreenshot());
|
||||
|
||||
for (const screenshotCompare of screenshotCompares) {
|
||||
expect(screenshotCompare).toMatchScreenshot();
|
||||
}
|
||||
});
|
||||
|
||||
test('should dismiss sibling nested popover when another sibling popover is opened', async () => {
|
||||
const screenshotCompares = [];
|
||||
|
||||
const ionPopoverDidPresent = await page.spyOnEvent('ionPopoverDidPresent');
|
||||
const ionPopoverDidDismiss = await page.spyOnEvent('ionPopoverDidDismiss');
|
||||
|
||||
await page.click('#first-trigger');
|
||||
|
||||
await ionPopoverDidPresent.next();
|
||||
|
||||
await page.click('#open-with-popover');
|
||||
|
||||
await ionPopoverDidPresent.next();
|
||||
|
||||
const openWithPopover = await page.find('.child-popover-one');
|
||||
expect(openWithPopover).not.toHaveClass('overlay-hidden');
|
||||
|
||||
await page.click('#share-popover');
|
||||
|
||||
await ionPopoverDidPresent.next();
|
||||
await ionPopoverDidDismiss.next();
|
||||
|
||||
const openWithPopoverAgain = await page.find('.child-popover-one');
|
||||
const sharePopover = await page.find('.child-popover-two');
|
||||
expect(openWithPopoverAgain).toHaveClass('overlay-hidden');
|
||||
expect(sharePopover).not.toHaveClass('overlay-hidden');
|
||||
|
||||
screenshotCompares.push(await page.compareScreenshot());
|
||||
|
||||
const backdrop = await page.find('.parent-popover >>> ion-backdrop');
|
||||
await backdrop.click();
|
||||
|
||||
await ionPopoverDidDismiss.next();
|
||||
|
||||
const nestedPopoverAgain = await page.find('.child-popover-one');
|
||||
expect(nestedPopoverAgain).toHaveClass('overlay-hidden');
|
||||
|
||||
screenshotCompares.push(await page.compareScreenshot());
|
||||
|
||||
for (const screenshotCompare of screenshotCompares) {
|
||||
expect(screenshotCompare).toMatchScreenshot();
|
||||
}
|
||||
})
|
||||
});
|
||||
@@ -35,203 +35,6 @@
|
||||
ion-item-divider {
|
||||
min-height: 1px;
|
||||
}
|
||||
|
||||
|
||||
/* Ionic Variables and Theming. For more info, please see:
|
||||
http://ionicframework.com/docs/theming/ */
|
||||
|
||||
/** Ionic CSS Variables **/
|
||||
:root {
|
||||
/** primary **/
|
||||
--ion-color-primary: #3880ff;
|
||||
--ion-color-primary-rgb: 56, 128, 255;
|
||||
--ion-color-primary-contrast: #ffffff;
|
||||
--ion-color-primary-contrast-rgb: 255, 255, 255;
|
||||
--ion-color-primary-shade: #3171e0;
|
||||
--ion-color-primary-tint: #4c8dff;
|
||||
|
||||
/** secondary **/
|
||||
--ion-color-secondary: #3dc2ff;
|
||||
--ion-color-secondary-rgb: 61, 194, 255;
|
||||
--ion-color-secondary-contrast: #ffffff;
|
||||
--ion-color-secondary-contrast-rgb: 255, 255, 255;
|
||||
--ion-color-secondary-shade: #36abe0;
|
||||
--ion-color-secondary-tint: #50c8ff;
|
||||
|
||||
/** tertiary **/
|
||||
--ion-color-tertiary: #5260ff;
|
||||
--ion-color-tertiary-rgb: 82, 96, 255;
|
||||
--ion-color-tertiary-contrast: #ffffff;
|
||||
--ion-color-tertiary-contrast-rgb: 255, 255, 255;
|
||||
--ion-color-tertiary-shade: #4854e0;
|
||||
--ion-color-tertiary-tint: #6370ff;
|
||||
|
||||
/** success **/
|
||||
--ion-color-success: #2dd36f;
|
||||
--ion-color-success-rgb: 45, 211, 111;
|
||||
--ion-color-success-contrast: #ffffff;
|
||||
--ion-color-success-contrast-rgb: 255, 255, 255;
|
||||
--ion-color-success-shade: #28ba62;
|
||||
--ion-color-success-tint: #42d77d;
|
||||
|
||||
/** warning **/
|
||||
--ion-color-warning: #ffc409;
|
||||
--ion-color-warning-rgb: 255, 196, 9;
|
||||
--ion-color-warning-contrast: #000000;
|
||||
--ion-color-warning-contrast-rgb: 0, 0, 0;
|
||||
--ion-color-warning-shade: #e0ac08;
|
||||
--ion-color-warning-tint: #ffca22;
|
||||
|
||||
/** danger **/
|
||||
--ion-color-danger: #eb445a;
|
||||
--ion-color-danger-rgb: 235, 68, 90;
|
||||
--ion-color-danger-contrast: #ffffff;
|
||||
--ion-color-danger-contrast-rgb: 255, 255, 255;
|
||||
--ion-color-danger-shade: #cf3c4f;
|
||||
--ion-color-danger-tint: #ed576b;
|
||||
|
||||
/** dark **/
|
||||
--ion-color-dark: #222428;
|
||||
--ion-color-dark-rgb: 34, 36, 40;
|
||||
--ion-color-dark-contrast: #ffffff;
|
||||
--ion-color-dark-contrast-rgb: 255, 255, 255;
|
||||
--ion-color-dark-shade: #1e2023;
|
||||
--ion-color-dark-tint: #383a3e;
|
||||
|
||||
/** medium **/
|
||||
--ion-color-medium: #92949c;
|
||||
--ion-color-medium-rgb: 146, 148, 156;
|
||||
--ion-color-medium-contrast: #ffffff;
|
||||
--ion-color-medium-contrast-rgb: 255, 255, 255;
|
||||
--ion-color-medium-shade: #808289;
|
||||
--ion-color-medium-tint: #9d9fa6;
|
||||
|
||||
/** light **/
|
||||
--ion-color-light: #f4f5f8;
|
||||
--ion-color-light-rgb: 244, 245, 248;
|
||||
--ion-color-light-contrast: #000000;
|
||||
--ion-color-light-contrast-rgb: 0, 0, 0;
|
||||
--ion-color-light-shade: #d7d8da;
|
||||
--ion-color-light-tint: #f5f6f9;
|
||||
}
|
||||
/*
|
||||
@media (prefers-color-scheme: dark) {
|
||||
body {
|
||||
--ion-color-primary: #428cff;
|
||||
--ion-color-primary-rgb: 66,140,255;
|
||||
--ion-color-primary-contrast: #ffffff;
|
||||
--ion-color-primary-contrast-rgb: 255,255,255;
|
||||
--ion-color-primary-shade: #3a7be0;
|
||||
--ion-color-primary-tint: #5598ff;
|
||||
--ion-color-secondary: #50c8ff;
|
||||
--ion-color-secondary-rgb: 80,200,255;
|
||||
--ion-color-secondary-contrast: #ffffff;
|
||||
--ion-color-secondary-contrast-rgb: 255,255,255;
|
||||
--ion-color-secondary-shade: #46b0e0;
|
||||
--ion-color-secondary-tint: #62ceff;
|
||||
--ion-color-tertiary: #6a64ff;
|
||||
--ion-color-tertiary-rgb: 106,100,255;
|
||||
--ion-color-tertiary-contrast: #ffffff;
|
||||
--ion-color-tertiary-contrast-rgb: 255,255,255;
|
||||
--ion-color-tertiary-shade: #5d58e0;
|
||||
--ion-color-tertiary-tint: #7974ff;
|
||||
--ion-color-success: #2fdf75;
|
||||
--ion-color-success-rgb: 47,223,117;
|
||||
--ion-color-success-contrast: #000000;
|
||||
--ion-color-success-contrast-rgb: 0,0,0;
|
||||
--ion-color-success-shade: #29c467;
|
||||
--ion-color-success-tint: #44e283;
|
||||
--ion-color-warning: #ffd534;
|
||||
--ion-color-warning-rgb: 255,213,52;
|
||||
--ion-color-warning-contrast: #000000;
|
||||
--ion-color-warning-contrast-rgb: 0,0,0;
|
||||
--ion-color-warning-shade: #e0bb2e;
|
||||
--ion-color-warning-tint: #ffd948;
|
||||
--ion-color-danger: #ff4961;
|
||||
--ion-color-danger-rgb: 255,73,97;
|
||||
--ion-color-danger-contrast: #ffffff;
|
||||
--ion-color-danger-contrast-rgb: 255,255,255;
|
||||
--ion-color-danger-shade: #e04055;
|
||||
--ion-color-danger-tint: #ff5b71;
|
||||
--ion-color-dark: #f4f5f8;
|
||||
--ion-color-dark-rgb: 244,245,248;
|
||||
--ion-color-dark-contrast: #000000;
|
||||
--ion-color-dark-contrast-rgb: 0,0,0;
|
||||
--ion-color-dark-shade: #d7d8da;
|
||||
--ion-color-dark-tint: #f5f6f9;
|
||||
--ion-color-medium: #989aa2;
|
||||
--ion-color-medium-rgb: 152,154,162;
|
||||
--ion-color-medium-contrast: #000000;
|
||||
--ion-color-medium-contrast-rgb: 0,0,0;
|
||||
--ion-color-medium-shade: #86888f;
|
||||
--ion-color-medium-tint: #a2a4ab;
|
||||
--ion-color-light: #222428;
|
||||
--ion-color-light-rgb: 34,36,40;
|
||||
--ion-color-light-contrast: #ffffff;
|
||||
--ion-color-light-contrast-rgb: 255,255,255;
|
||||
--ion-color-light-shade: #1e2023;
|
||||
--ion-color-light-tint: #383a3e;
|
||||
}
|
||||
.ios body {
|
||||
--ion-background-color: #000000;
|
||||
--ion-background-color-rgb: 0,0,0;
|
||||
--ion-text-color: #ffffff;
|
||||
--ion-text-color-rgb: 255,255,255;
|
||||
--ion-color-step-50: #0d0d0d;
|
||||
--ion-color-step-100: #1a1a1a;
|
||||
--ion-color-step-150: #262626;
|
||||
--ion-color-step-200: #333333;
|
||||
--ion-color-step-250: #404040;
|
||||
--ion-color-step-300: #4d4d4d;
|
||||
--ion-color-step-350: #595959;
|
||||
--ion-color-step-400: #666666;
|
||||
--ion-color-step-450: #737373;
|
||||
--ion-color-step-500: #808080;
|
||||
--ion-color-step-550: #8c8c8c;
|
||||
--ion-color-step-600: #999999;
|
||||
--ion-color-step-650: #a6a6a6;
|
||||
--ion-color-step-700: #b3b3b3;
|
||||
--ion-color-step-750: #bfbfbf;
|
||||
--ion-color-step-800: #cccccc;
|
||||
--ion-color-step-850: #d9d9d9;
|
||||
--ion-color-step-900: #e6e6e6;
|
||||
--ion-color-step-950: #f2f2f2;
|
||||
--ion-toolbar-background: #0d0d0d;
|
||||
--ion-item-background: #000000;
|
||||
--ion-card-background: #1c1c1d;
|
||||
}
|
||||
.md body {
|
||||
--ion-background-color: #121212;
|
||||
--ion-background-color-rgb: 18,18,18;
|
||||
--ion-text-color: #ffffff;
|
||||
--ion-text-color-rgb: 255,255,255;
|
||||
--ion-border-color: #222222;
|
||||
--ion-color-step-50: #1e1e1e;
|
||||
--ion-color-step-100: #2a2a2a;
|
||||
--ion-color-step-150: #363636;
|
||||
--ion-color-step-200: #414141;
|
||||
--ion-color-step-250: #4d4d4d;
|
||||
--ion-color-step-300: #595959;
|
||||
--ion-color-step-350: #656565;
|
||||
--ion-color-step-400: #717171;
|
||||
--ion-color-step-450: #7d7d7d;
|
||||
--ion-color-step-500: #898989;
|
||||
--ion-color-step-550: #949494;
|
||||
--ion-color-step-600: #a0a0a0;
|
||||
--ion-color-step-650: #acacac;
|
||||
--ion-color-step-700: #b8b8b8;
|
||||
--ion-color-step-750: #c4c4c4;
|
||||
--ion-color-step-800: #d0d0d0;
|
||||
--ion-color-step-850: #dbdbdb;
|
||||
--ion-color-step-900: #e7e7e7;
|
||||
--ion-color-step-950: #f3f3f3;
|
||||
--ion-item-background: #1e1e1e;
|
||||
--ion-toolbar-background: #1f1f1f;
|
||||
--ion-tab-bar-background: #1f1f1f;
|
||||
--ion-card-background: #1e1e1e;
|
||||
}
|
||||
}
|
||||
*/
|
||||
</style>
|
||||
<body>
|
||||
<ion-app>
|
||||
@@ -243,10 +46,10 @@
|
||||
<ion-icon name="ellipsis-horizontal"></ion-icon>
|
||||
</ion-button>
|
||||
<ion-popover
|
||||
id="liam-was-here"
|
||||
animated="true"
|
||||
trigger="first-trigger"
|
||||
side="end"
|
||||
class="parent-popover"
|
||||
>
|
||||
<ion-content>
|
||||
<ion-list lines="none">
|
||||
@@ -262,6 +65,7 @@
|
||||
trigger-action="click"
|
||||
trigger="open-with-popover"
|
||||
side="end"
|
||||
class="child-popover-one"
|
||||
>
|
||||
|
||||
<ion-list lines="none">
|
||||
@@ -318,6 +122,7 @@
|
||||
trigger-action="click"
|
||||
trigger="share-popover"
|
||||
side="end"
|
||||
class="child-popover-two"
|
||||
>
|
||||
<ion-list lines="none">
|
||||
<ion-item button detail="false">
|
||||
@@ -337,6 +142,32 @@
|
||||
<ion-item button detail="false">
|
||||
<ion-label>AirDrop</ion-label>
|
||||
</ion-item>
|
||||
|
||||
<ion-item button detail="true" id="share-other-popover">
|
||||
<ion-label>Other</ion-label>
|
||||
</ion-item>
|
||||
|
||||
<ion-popover
|
||||
animated="true"
|
||||
trigger-action="click"
|
||||
trigger="share-other-popover"
|
||||
side="end"
|
||||
class="child-popover-three"
|
||||
>
|
||||
<ion-list lines="none">
|
||||
<ion-item button detail="false">
|
||||
<ion-label>Facebook</ion-label>
|
||||
</ion-item>
|
||||
|
||||
<ion-item button detail="false">
|
||||
<ion-label>Twitter</ion-label>
|
||||
</ion-item>
|
||||
|
||||
<ion-item button detail="false">
|
||||
<ion-label>LinkedIn</ion-label>
|
||||
</ion-item>
|
||||
</ion-list>
|
||||
</ion-popover>
|
||||
</ion-list>
|
||||
</ion-popover>
|
||||
</ion-list>
|
||||
|
||||
@@ -78,9 +78,9 @@ export class Select implements ComponentInterface {
|
||||
|
||||
/**
|
||||
* Any additional options that the `alert`, `action-sheet` or `popover` interface
|
||||
* can take. See the [ion-alert docs](../alert), the
|
||||
* [ion-action-sheet docs](../action-sheet) and the
|
||||
* [ion-popover docs](../popover) for the
|
||||
* can take. See the [ion-alert docs](./alert), the
|
||||
* [ion-action-sheet docs](./action-sheet) and the
|
||||
* [ion-popover docs](./popover) for the
|
||||
* create options for each interface.
|
||||
*
|
||||
* Note: `interfaceOptions` will not override `inputs` or `buttons` with the `alert` interface.
|
||||
|
||||
@@ -498,7 +498,7 @@ import { Component } from '@angular/core';
|
||||
})
|
||||
export class SlideExample {
|
||||
// Optional parameters to pass to the swiper instance.
|
||||
// See http://idangero.us/swiper/api/ for valid options.
|
||||
// See https://swiperjs.com/swiper-api for valid options.
|
||||
slideOpts = {
|
||||
initialSlide: 1,
|
||||
speed: 400
|
||||
@@ -539,7 +539,7 @@ ion-slides {
|
||||
var slides = document.querySelector('ion-slides');
|
||||
|
||||
// Optional parameters to pass to the swiper instance.
|
||||
// See http://idangero.us/swiper/api/ for valid options.
|
||||
// See https://swiperjs.com/swiper-api for valid options.
|
||||
slides.options = {
|
||||
initialSlide: 1,
|
||||
speed: 400
|
||||
@@ -561,7 +561,7 @@ import React from 'react';
|
||||
import { IonSlides, IonSlide, IonContent } from '@ionic/react';
|
||||
|
||||
// Optional parameters to pass to the swiper instance.
|
||||
// See http://idangero.us/swiper/api/ for valid options.
|
||||
// See https://swiperjs.com/swiper-api for valid options.
|
||||
const slideOpts = {
|
||||
initialSlide: 1,
|
||||
speed: 400
|
||||
@@ -603,7 +603,7 @@ import { Component, h } from '@stencil/core';
|
||||
})
|
||||
export class SlidesExample {
|
||||
// Optional parameters to pass to the swiper instance.
|
||||
// See http://idangero.us/swiper/api/ for valid options.
|
||||
// See https://swiperjs.com/swiper-api for valid options.
|
||||
private slideOpts = {
|
||||
initialSlide: 1,
|
||||
speed: 400
|
||||
@@ -664,7 +664,7 @@ import { defineComponent } from 'vue';
|
||||
export default defineComponent({
|
||||
components: { IonSlides, IonSlide },
|
||||
setup() {
|
||||
// Optional parameters to pass to the swiper instance. See http://idangero.us/swiper/api/ for valid options.
|
||||
// Optional parameters to pass to the swiper instance. See https://swiperjs.com/swiper-api for valid options.
|
||||
const slideOpts = {
|
||||
initialSlide: 1,
|
||||
speed: 400
|
||||
@@ -679,12 +679,12 @@ export default defineComponent({
|
||||
|
||||
## Properties
|
||||
|
||||
| Property | Attribute | Description | Type | Default |
|
||||
| ----------- | ----------- | -------------------------------------------------------------------------------------------- | --------------- | ----------- |
|
||||
| `mode` | `mode` | The mode determines which platform styles to use. | `"ios" \| "md"` | `undefined` |
|
||||
| `options` | `options` | Options to pass to the swiper instance. See http://idangero.us/swiper/api/ for valid options | `any` | `{}` |
|
||||
| `pager` | `pager` | If `true`, show the pagination. | `boolean` | `false` |
|
||||
| `scrollbar` | `scrollbar` | If `true`, show the scrollbar. | `boolean` | `false` |
|
||||
| Property | Attribute | Description | Type | Default |
|
||||
| ----------- | ----------- | --------------------------------------------------------------------------------------------- | --------------- | ----------- |
|
||||
| `mode` | `mode` | The mode determines which platform styles to use. | `"ios" \| "md"` | `undefined` |
|
||||
| `options` | `options` | Options to pass to the swiper instance. See https://swiperjs.com/swiper-api for valid options | `any` | `{}` |
|
||||
| `pager` | `pager` | If `true`, show the pagination. | `boolean` | `false` |
|
||||
| `scrollbar` | `scrollbar` | If `true`, show the scrollbar. | `boolean` | `false` |
|
||||
|
||||
|
||||
## Events
|
||||
@@ -735,7 +735,7 @@ Type: `Promise<number>`
|
||||
|
||||
Get the Swiper instance.
|
||||
Use this to access the full Swiper API.
|
||||
See https://idangero.us/swiper/api/ for all API options.
|
||||
See https://swiperjs.com/swiper-api for all API options.
|
||||
|
||||
#### Returns
|
||||
|
||||
|
||||
@@ -29,7 +29,7 @@ export class Slides implements ComponentInterface {
|
||||
|
||||
/**
|
||||
* Options to pass to the swiper instance.
|
||||
* See http://idangero.us/swiper/api/ for valid options
|
||||
* See https://swiperjs.com/swiper-api for valid options
|
||||
*/
|
||||
@Prop() options: any = {}; // SwiperOptions; // TODO
|
||||
|
||||
@@ -330,7 +330,7 @@ export class Slides implements ComponentInterface {
|
||||
/**
|
||||
* Get the Swiper instance.
|
||||
* Use this to access the full Swiper API.
|
||||
* See https://idangero.us/swiper/api/ for all API options.
|
||||
* See https://swiperjs.com/swiper-api for all API options.
|
||||
*/
|
||||
@Method()
|
||||
async getSwiper(): Promise<any> {
|
||||
|
||||
@@ -21,7 +21,7 @@ import { Component } from '@angular/core';
|
||||
})
|
||||
export class SlideExample {
|
||||
// Optional parameters to pass to the swiper instance.
|
||||
// See http://idangero.us/swiper/api/ for valid options.
|
||||
// See https://swiperjs.com/swiper-api for valid options.
|
||||
slideOpts = {
|
||||
initialSlide: 1,
|
||||
speed: 400
|
||||
|
||||
@@ -20,7 +20,7 @@
|
||||
var slides = document.querySelector('ion-slides');
|
||||
|
||||
// Optional parameters to pass to the swiper instance.
|
||||
// See http://idangero.us/swiper/api/ for valid options.
|
||||
// See https://swiperjs.com/swiper-api for valid options.
|
||||
slides.options = {
|
||||
initialSlide: 1,
|
||||
speed: 400
|
||||
|
||||
@@ -3,7 +3,7 @@ import React from 'react';
|
||||
import { IonSlides, IonSlide, IonContent } from '@ionic/react';
|
||||
|
||||
// Optional parameters to pass to the swiper instance.
|
||||
// See http://idangero.us/swiper/api/ for valid options.
|
||||
// See https://swiperjs.com/swiper-api for valid options.
|
||||
const slideOpts = {
|
||||
initialSlide: 1,
|
||||
speed: 400
|
||||
|
||||
@@ -7,7 +7,7 @@ import { Component, h } from '@stencil/core';
|
||||
})
|
||||
export class SlidesExample {
|
||||
// Optional parameters to pass to the swiper instance.
|
||||
// See http://idangero.us/swiper/api/ for valid options.
|
||||
// See https://swiperjs.com/swiper-api for valid options.
|
||||
private slideOpts = {
|
||||
initialSlide: 1,
|
||||
speed: 400
|
||||
|
||||
@@ -21,7 +21,7 @@ import { defineComponent } from 'vue';
|
||||
export default defineComponent({
|
||||
components: { IonSlides, IonSlide },
|
||||
setup() {
|
||||
// Optional parameters to pass to the swiper instance. See http://idangero.us/swiper/api/ for valid options.
|
||||
// Optional parameters to pass to the swiper instance. See https://swiperjs.com/swiper-api for valid options.
|
||||
const slideOpts = {
|
||||
initialSlide: 1,
|
||||
speed: 400
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import { Component, ComponentInterface, Element, Event, EventEmitter, Host, Prop, State, Watch, h } from '@stencil/core';
|
||||
|
||||
import { getIonMode } from '../../global/ionic-global';
|
||||
import { Color, TabBarChangedEventDetail } from '../../interface';
|
||||
import { Color, StyleEventDetail, TabBarChangedEventDetail } from '../../interface';
|
||||
import { createColorClasses } from '../../utils/theme';
|
||||
|
||||
/**
|
||||
@@ -30,6 +30,8 @@ export class TabBar implements ComponentInterface {
|
||||
*/
|
||||
@Prop({ reflect: true }) color?: Color;
|
||||
|
||||
@Event() ionStyle!: EventEmitter<StyleEventDetail>;
|
||||
|
||||
/**
|
||||
* The selected tab component
|
||||
*/
|
||||
@@ -50,11 +52,28 @@ export class TabBar implements ComponentInterface {
|
||||
*/
|
||||
@Prop() translucent = false;
|
||||
|
||||
@Watch('translucent')
|
||||
translucentChanged() {
|
||||
// Find all tabs
|
||||
const tabs = Array.from(this.el.closest('ion-tabs')?.querySelectorAll('ion-tab') ?? []);
|
||||
for (const tab of tabs) {
|
||||
if (this.translucent) {
|
||||
tab.classList.add('tab-bar-translucent');
|
||||
} else {
|
||||
tab.classList.remove('tab-bar-translucent');
|
||||
}
|
||||
}
|
||||
this.ionStyle.emit({
|
||||
'tab-bar-translucent': this.translucent
|
||||
})
|
||||
}
|
||||
|
||||
/** @internal */
|
||||
@Event() ionTabBarChanged!: EventEmitter<TabBarChangedEventDetail>;
|
||||
|
||||
componentWillLoad() {
|
||||
this.selectedTabChanged();
|
||||
this.translucentChanged();
|
||||
}
|
||||
|
||||
connectedCallback() {
|
||||
|
||||
@@ -2,3 +2,9 @@
|
||||
/* stylelint-disable-next-line declaration-no-important */
|
||||
display: none !important;
|
||||
}
|
||||
|
||||
|
||||
:host(.tab-bar-translucent) ::slotted(ion-content) {
|
||||
/* stylelint-disable-next-line declaration-no-important */
|
||||
--padding-bottom: 50px !important;
|
||||
}
|
||||
|
||||
11
core/src/components/tabs/tabs.ios.scss
Normal file
11
core/src/components/tabs/tabs.ios.scss
Normal file
@@ -0,0 +1,11 @@
|
||||
@import './tabs';
|
||||
|
||||
:host(.tab-bar-translucent) {
|
||||
--tab-translucent-safe-area: 60px;
|
||||
}
|
||||
|
||||
slot[name='bottom']::slotted([translucent]) {
|
||||
position: absolute;
|
||||
bottom: 0;
|
||||
width: 100%;
|
||||
}
|
||||
1
core/src/components/tabs/tabs.md.scss
Normal file
1
core/src/components/tabs/tabs.md.scss
Normal file
@@ -0,0 +1 @@
|
||||
@import './tabs';
|
||||
@@ -9,7 +9,10 @@ import { NavOutlet, RouteID, RouteWrite, TabButtonClickEventDetail } from '../..
|
||||
*/
|
||||
@Component({
|
||||
tag: 'ion-tabs',
|
||||
styleUrl: 'tabs.scss',
|
||||
styleUrls: {
|
||||
ios: 'tabs.ios.scss',
|
||||
md: 'tabs.md.scss'
|
||||
},
|
||||
shadow: true
|
||||
})
|
||||
export class Tabs implements NavOutlet {
|
||||
@@ -21,6 +24,8 @@ export class Tabs implements NavOutlet {
|
||||
|
||||
@State() selectedTab?: HTMLIonTabElement;
|
||||
|
||||
@State() private tabCustomClasses: { [key: string]: boolean } = {};
|
||||
|
||||
/** @internal */
|
||||
@Prop({ mutable: true }) useRouter = false;
|
||||
|
||||
@@ -182,10 +187,21 @@ export class Tabs implements NavOutlet {
|
||||
}
|
||||
}
|
||||
|
||||
private onIonStyle = (ev: any) => {
|
||||
if (ev.target.tagName === 'ION-TAB-BAR') {
|
||||
for (const key of Object.keys(ev.detail)) {
|
||||
this.tabCustomClasses[key] = ev.detail[key];
|
||||
}
|
||||
this.tabCustomClasses = {...this.tabCustomClasses};
|
||||
}
|
||||
}
|
||||
|
||||
render() {
|
||||
return (
|
||||
<Host
|
||||
onIonTabButtonClick={this.onTabClicked}
|
||||
onIonStyle={this.onIonStyle}
|
||||
class={this.tabCustomClasses}
|
||||
>
|
||||
<slot name="top"></slot>
|
||||
<div class="tabs-inner">
|
||||
|
||||
204
core/src/components/tabs/test/translucent/index.html
Normal file
204
core/src/components/tabs/test/translucent/index.html
Normal file
@@ -0,0 +1,204 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="en" dir="ltr">
|
||||
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<title>Tab - Translucent</title>
|
||||
<meta name="viewport"
|
||||
content="width=device-width, initial-scale=1.0, minimum-scale=1.0, maximum-scale=1.0, user-scalable=no, viewport-fit=cover">
|
||||
<link href="../../../../../css/ionic.bundle.css" rel="stylesheet">
|
||||
<link href="../../../../../scripts/testing/styles.css" rel="stylesheet">
|
||||
<script src="../../../../../scripts/testing/scripts.js"></script>
|
||||
<script nomodule src="../../../../../dist/ionic/ionic.js"></script>
|
||||
<script type="module" src="../../../../../dist/ionic/ionic.esm.js"></script>
|
||||
<style>
|
||||
.scrollable-area {
|
||||
height: 1400px;
|
||||
background: red;
|
||||
color: white;
|
||||
}
|
||||
|
||||
.images {
|
||||
display: grid;
|
||||
gap: 4px;
|
||||
grid-template-columns: 1fr 1fr;
|
||||
}
|
||||
|
||||
.images img {
|
||||
height: 100%;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
|
||||
<body>
|
||||
|
||||
<ion-app>
|
||||
<ion-tabs>
|
||||
|
||||
<ion-tab tab="tab-one">
|
||||
<ion-header>
|
||||
<ion-toolbar>
|
||||
<ion-title>Tab One</ion-title>
|
||||
</ion-toolbar>
|
||||
</ion-header>
|
||||
<ion-content class="ion-padding">
|
||||
<h1>Tab One</h1>
|
||||
|
||||
<div class="images">
|
||||
<img src="https://cdn.pixabay.com/photo/2018/01/14/23/12/nature-3082832__480.jpg" />
|
||||
<img src="https://images.pexels.com/photos/844297/pexels-photo-844297.jpeg" />
|
||||
<img src="https://images.unsplash.com/photo-1607791330831-d3dcf312e2d1" />
|
||||
<img src="https://images.template.net/wp-content/uploads/2016/04/25103502/HD-Featured-Image.jpg" />
|
||||
<img src="https://wallpaper.dog/large/20435883.jpg" />
|
||||
<img src="https://cdn.pixabay.com/photo/2018/01/14/23/12/nature-3082832__480.jpg" />
|
||||
<img src="https://images.pexels.com/photos/844297/pexels-photo-844297.jpeg" />
|
||||
<img src="https://images.unsplash.com/photo-1607791330831-d3dcf312e2d1" />
|
||||
<img src="https://images.template.net/wp-content/uploads/2016/04/25103502/HD-Featured-Image.jpg" />
|
||||
<img src="https://wallpaper.dog/large/20435883.jpg" />
|
||||
<img src="https://cdn.pixabay.com/photo/2018/01/14/23/12/nature-3082832__480.jpg" />
|
||||
<img src="https://images.pexels.com/photos/844297/pexels-photo-844297.jpeg" />
|
||||
<img src="https://images.unsplash.com/photo-1607791330831-d3dcf312e2d1" />
|
||||
<img src="https://images.template.net/wp-content/uploads/2016/04/25103502/HD-Featured-Image.jpg" />
|
||||
<img src="https://wallpaper.dog/large/20435883.jpg" />
|
||||
<img src="https://cdn.pixabay.com/photo/2018/01/14/23/12/nature-3082832__480.jpg" />
|
||||
<img src="https://images.pexels.com/photos/844297/pexels-photo-844297.jpeg" />
|
||||
<img src="https://images.unsplash.com/photo-1607791330831-d3dcf312e2d1" />
|
||||
<img src="https://images.template.net/wp-content/uploads/2016/04/25103502/HD-Featured-Image.jpg" />
|
||||
<img src="https://wallpaper.dog/large/20435883.jpg" />
|
||||
<img src="https://cdn.pixabay.com/photo/2018/01/14/23/12/nature-3082832__480.jpg" />
|
||||
<img src="https://images.pexels.com/photos/844297/pexels-photo-844297.jpeg" />
|
||||
<img src="https://images.unsplash.com/photo-1607791330831-d3dcf312e2d1" />
|
||||
<img src="https://images.template.net/wp-content/uploads/2016/04/25103502/HD-Featured-Image.jpg" />
|
||||
<img src="https://wallpaper.dog/large/20435883.jpg" />
|
||||
<img src="https://cdn.pixabay.com/photo/2018/01/14/23/12/nature-3082832__480.jpg" />
|
||||
<img src="https://images.pexels.com/photos/844297/pexels-photo-844297.jpeg" />
|
||||
<img src="https://images.unsplash.com/photo-1607791330831-d3dcf312e2d1" />
|
||||
<img src="https://images.template.net/wp-content/uploads/2016/04/25103502/HD-Featured-Image.jpg" />
|
||||
<img src="https://wallpaper.dog/large/20435883.jpg" />
|
||||
</div>
|
||||
|
||||
<div style="text-align: center;padding: 8px 0;">This is the end of the content</div>
|
||||
|
||||
<ion-fab slot="fixed" horizontal="end" vertical="bottom">
|
||||
<ion-fab-button class="custom-white">
|
||||
<ion-icon name="add"></ion-icon>
|
||||
</ion-fab-button>
|
||||
</ion-fab>
|
||||
</ion-content>
|
||||
</ion-tab>
|
||||
|
||||
<ion-tab tab="schedule">
|
||||
<ion-header>
|
||||
<ion-toolbar>
|
||||
<ion-title>Tab Two</ion-title>
|
||||
</ion-toolbar>
|
||||
</ion-header>
|
||||
<ion-content class="ion-padding">
|
||||
<h1>Tab Two</h1>
|
||||
|
||||
<div class="images">
|
||||
<img src="https://cdn.pixabay.com/photo/2018/01/14/23/12/nature-3082832__480.jpg" />
|
||||
<img src="https://images.pexels.com/photos/844297/pexels-photo-844297.jpeg" />
|
||||
<img src="https://images.unsplash.com/photo-1607791330831-d3dcf312e2d1" />
|
||||
<img src="https://images.template.net/wp-content/uploads/2016/04/25103502/HD-Featured-Image.jpg" />
|
||||
<img src="https://wallpaper.dog/large/20435883.jpg" />
|
||||
<img src="https://cdn.pixabay.com/photo/2018/01/14/23/12/nature-3082832__480.jpg" />
|
||||
<img src="https://images.pexels.com/photos/844297/pexels-photo-844297.jpeg" />
|
||||
<img src="https://images.unsplash.com/photo-1607791330831-d3dcf312e2d1" />
|
||||
<img src="https://images.template.net/wp-content/uploads/2016/04/25103502/HD-Featured-Image.jpg" />
|
||||
<img src="https://wallpaper.dog/large/20435883.jpg" />
|
||||
<img src="https://cdn.pixabay.com/photo/2018/01/14/23/12/nature-3082832__480.jpg" />
|
||||
<img src="https://images.pexels.com/photos/844297/pexels-photo-844297.jpeg" />
|
||||
<img src="https://images.unsplash.com/photo-1607791330831-d3dcf312e2d1" />
|
||||
<img src="https://images.template.net/wp-content/uploads/2016/04/25103502/HD-Featured-Image.jpg" />
|
||||
<img src="https://wallpaper.dog/large/20435883.jpg" />
|
||||
<img src="https://cdn.pixabay.com/photo/2018/01/14/23/12/nature-3082832__480.jpg" />
|
||||
<img src="https://images.pexels.com/photos/844297/pexels-photo-844297.jpeg" />
|
||||
<img src="https://images.unsplash.com/photo-1607791330831-d3dcf312e2d1" />
|
||||
<img src="https://images.template.net/wp-content/uploads/2016/04/25103502/HD-Featured-Image.jpg" />
|
||||
<img src="https://wallpaper.dog/large/20435883.jpg" />
|
||||
<img src="https://cdn.pixabay.com/photo/2018/01/14/23/12/nature-3082832__480.jpg" />
|
||||
<img src="https://images.pexels.com/photos/844297/pexels-photo-844297.jpeg" />
|
||||
<img src="https://images.unsplash.com/photo-1607791330831-d3dcf312e2d1" />
|
||||
<img src="https://images.template.net/wp-content/uploads/2016/04/25103502/HD-Featured-Image.jpg" />
|
||||
<img src="https://wallpaper.dog/large/20435883.jpg" />
|
||||
<img src="https://cdn.pixabay.com/photo/2018/01/14/23/12/nature-3082832__480.jpg" />
|
||||
<img src="https://images.pexels.com/photos/844297/pexels-photo-844297.jpeg" />
|
||||
<img src="https://images.unsplash.com/photo-1607791330831-d3dcf312e2d1" />
|
||||
<img src="https://images.template.net/wp-content/uploads/2016/04/25103502/HD-Featured-Image.jpg" />
|
||||
<img src="https://wallpaper.dog/large/20435883.jpg" />
|
||||
</div>
|
||||
</ion-content>
|
||||
<ion-footer>
|
||||
<ion-toolbar>
|
||||
<ion-title>Tab Two Footer</ion-title>
|
||||
</ion-toolbar>
|
||||
</ion-footer>
|
||||
</ion-tab>
|
||||
|
||||
<ion-tab tab="tab-three">
|
||||
<ion-header>
|
||||
<ion-toolbar>
|
||||
<ion-title>Tab Three</ion-title>
|
||||
</ion-toolbar>
|
||||
</ion-header>
|
||||
<ion-content class="ion-padding">
|
||||
<h1>Tab Three</h1>
|
||||
</ion-content>
|
||||
</ion-tab>
|
||||
|
||||
|
||||
<ion-tab tab="tab-four">
|
||||
<ion-header>
|
||||
<ion-toolbar>
|
||||
<ion-title>Tab Three</ion-title>
|
||||
</ion-toolbar>
|
||||
</ion-header>
|
||||
<ion-content class="ion-padding">
|
||||
<h1>Tab Three</h1>
|
||||
</ion-content>
|
||||
</ion-tab>
|
||||
|
||||
<ion-tab-bar slot="bottom" translucent="true">
|
||||
<ion-tab-button href="" tab="tab-one">
|
||||
<ion-label>Tab One</ion-label>
|
||||
<ion-icon name="star"></ion-icon>
|
||||
</ion-tab-button>
|
||||
|
||||
<ion-tab-button tab="schedule">
|
||||
<ion-label>Tab Two</ion-label>
|
||||
<ion-icon name="globe"></ion-icon>
|
||||
<ion-badge color="danger">6</ion-badge>
|
||||
</ion-tab-button>
|
||||
|
||||
<ion-tab-button tab="tab-three">
|
||||
<ion-label>Tab Three</ion-label>
|
||||
<ion-icon name="logo-facebook"></ion-icon>
|
||||
<ion-badge color="primary">6</ion-badge>
|
||||
</ion-tab-button>
|
||||
|
||||
<ion-tab-button tab="tab-four" class="e2eTabFourButton">
|
||||
<ion-label>Tab Four</ion-label>
|
||||
<ion-icon name="chatbox"></ion-icon>
|
||||
</ion-tab-button>
|
||||
|
||||
</ion-tab-bar>
|
||||
</ion-tabs>
|
||||
</ion-app>
|
||||
|
||||
<style>
|
||||
.custom-white {
|
||||
--background: white;
|
||||
--background-hover: #888;
|
||||
--background-focused: #444;
|
||||
|
||||
--color: #3880ff;
|
||||
}
|
||||
|
||||
.ios .custom-white {
|
||||
--background-activated: #ddd;
|
||||
}
|
||||
</style>
|
||||
</body>
|
||||
|
||||
</html>
|
||||
@@ -59,6 +59,30 @@ interface ToastOptions {
|
||||
interface ToastAttributes extends JSXBase.HTMLAttributes<HTMLElement> {}
|
||||
```
|
||||
|
||||
## Accessibility
|
||||
|
||||
### Focus Management
|
||||
|
||||
Toasts are intended to be subtle notifications and are not intended to interrupt the user. User interaction should not be required to dismiss the toast. As a result, focus is not automatically moved to a toast when one is presented.
|
||||
|
||||
### Screen Readers
|
||||
|
||||
`ion-toast` has `aria-live="polite"` and `aria-atomic="true"` set by default.
|
||||
|
||||
`aria-live` causes screen readers to announce the content of the toast when it is presented. However, since the attribute is set to `'polite'`, screen readers generally do not interrupt the current task. Developers can customize this behavior by using the `htmlAttributes` property to set `aria-live` to `'assertive'`. This will cause screen readers to immediately notify the user when a toast is presented, potentially interrupting any previous updates.
|
||||
|
||||
`aria-atomic="true"` is set to ensure that the entire toast is announced as a single unit. This is useful when dynamically updating the content of the toast as it prevents screen readers from announcing only the content that has changed.
|
||||
|
||||
### Tips
|
||||
|
||||
While this is not a complete list, here are some guidelines to follow when using toasts.
|
||||
|
||||
* Do not require user interaction to dismiss toasts. For example, having a "Dismiss" button in the toast is fine, but the toast should also automatically dismiss on its own after a timeout period. If you need user interaction for a notification, consider using [ion-alert](./alert) instead.
|
||||
|
||||
* Avoid opening multiple toasts in quick succession. If `aria-live` is set to `'assertive'`, screen readers may interrupt the reading of the current task to announce the new toast, causing the context of the previous toast to be lost.
|
||||
|
||||
* For toasts with long messages, consider adjusting the `duration` property to allow users enough time to read the content of the toast.
|
||||
|
||||
<!-- Auto Generated Below -->
|
||||
|
||||
|
||||
|
||||
33
core/src/components/toast/test/a11y/index.html
Normal file
33
core/src/components/toast/test/a11y/index.html
Normal file
@@ -0,0 +1,33 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="en" dir="ltr">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<title>Toast - a11y</title>
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0, minimum-scale=1.0, viewport-fit=cover">
|
||||
<link href="../../../../../css/ionic.bundle.css" rel="stylesheet">
|
||||
<link href="../../../../../scripts/testing/styles.css" rel="stylesheet">
|
||||
<script src="../../../../../scripts/testing/scripts.js"></script>
|
||||
<script type="module" src="../../../../../dist/ionic/ionic.esm.js"></script>
|
||||
<script type="module">
|
||||
import { toastController } from '../../../../dist/ionic/index.esm.js';
|
||||
window.toastController = toastController;
|
||||
</script>
|
||||
</head>
|
||||
<body>
|
||||
<ion-app>
|
||||
<main>
|
||||
<h1 style="background-color: white">Toast - a11y</h1>
|
||||
|
||||
<button id="polite" onclick="presentToast({ message: 'This is a toast message' })">Present Toast</button>
|
||||
<button id="assertive" onclick="presentToast({ message: 'This is an assertive toast message', htmlAttributes: { 'aria-live': 'assertive' } })">Present Assertive Toast</button>
|
||||
</main>
|
||||
</ion-app>
|
||||
<script>
|
||||
const presentToast = async (opts) => {
|
||||
const toast = await toastController.create(opts);
|
||||
|
||||
await toast.present();
|
||||
}
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
48
core/src/components/toast/test/a11y/toast.e2e.ts
Normal file
48
core/src/components/toast/test/a11y/toast.e2e.ts
Normal file
@@ -0,0 +1,48 @@
|
||||
import { newE2EPage } from '@stencil/core/testing';
|
||||
import { AxePuppeteer } from '@axe-core/puppeteer';
|
||||
|
||||
describe('toast accessibility tests', () => {
|
||||
test('it should not have any axe violations with polite toasts', async () => {
|
||||
const page = await newE2EPage({
|
||||
url: '/src/components/toast/test/a11y?ionic:_testing=true'
|
||||
});
|
||||
|
||||
const ionToastDidPresent = await page.spyOnEvent('ionToastDidPresent');
|
||||
|
||||
await page.click('#polite');
|
||||
|
||||
await ionToastDidPresent.next();
|
||||
|
||||
/**
|
||||
* IonToast overlays the entire screen, so
|
||||
* Axe will be unable to verify color contrast
|
||||
* on elements under the toast.
|
||||
*/
|
||||
const results = await new AxePuppeteer(page)
|
||||
.disableRules('color-contrast')
|
||||
.analyze();
|
||||
expect(results.violations.length).toEqual(0);
|
||||
});
|
||||
|
||||
test('it should not have any axe violations with assertive toasts', async () => {
|
||||
const page = await newE2EPage({
|
||||
url: '/src/components/toast/test/a11y?ionic:_testing=true'
|
||||
});
|
||||
|
||||
const ionToastDidPresent = await page.spyOnEvent('ionToastDidPresent');
|
||||
|
||||
await page.click('#assertive');
|
||||
|
||||
await ionToastDidPresent.next();
|
||||
|
||||
/**
|
||||
* IonToast overlays the entire screen, so
|
||||
* Axe will be unable to verify color contrast
|
||||
* on elements under the toast.
|
||||
*/
|
||||
const results = await new AxePuppeteer(page)
|
||||
.disableRules('color-contrast')
|
||||
.analyze();
|
||||
expect(results.violations.length).toEqual(0);
|
||||
});
|
||||
});
|
||||
@@ -280,6 +280,8 @@ export class Toast implements ComponentInterface, OverlayInterface {
|
||||
|
||||
return (
|
||||
<Host
|
||||
aria-live="polite"
|
||||
aria-atomic="true"
|
||||
role={role}
|
||||
tabindex="-1"
|
||||
{...this.htmlAttributes as any}
|
||||
|
||||
@@ -3,6 +3,22 @@
|
||||
All notable changes to this project will be documented in this file.
|
||||
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
|
||||
|
||||
## [6.0.13](https://github.com/ionic-team/ionic-docs/compare/v6.0.12...v6.0.13) (2022-03-23)
|
||||
|
||||
**Note:** Version bump only for package @ionic/docs
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
## [6.0.12](https://github.com/ionic-team/ionic-docs/compare/v6.0.11...v6.0.12) (2022-03-16)
|
||||
|
||||
**Note:** Version bump only for package @ionic/docs
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
## [6.0.11](https://github.com/ionic-team/ionic-docs/compare/v6.0.10...v6.0.11) (2022-03-09)
|
||||
|
||||
**Note:** Version bump only for package @ionic/docs
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@ionic/docs",
|
||||
"version": "6.0.11",
|
||||
"version": "6.0.13",
|
||||
"description": "Pre-packaged API documentation for the Ionic docs.",
|
||||
"main": "core.json",
|
||||
"types": "core.d.ts",
|
||||
|
||||
@@ -5,5 +5,5 @@
|
||||
"angular",
|
||||
"packages/*"
|
||||
],
|
||||
"version": "6.0.11"
|
||||
"version": "6.0.13"
|
||||
}
|
||||
|
||||
@@ -3,6 +3,22 @@
|
||||
All notable changes to this project will be documented in this file.
|
||||
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
|
||||
|
||||
## [6.0.13](https://github.com/ionic-team/ionic/compare/v6.0.12...v6.0.13) (2022-03-23)
|
||||
|
||||
**Note:** Version bump only for package @ionic/angular-server
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
## [6.0.12](https://github.com/ionic-team/ionic/compare/v6.0.11...v6.0.12) (2022-03-16)
|
||||
|
||||
**Note:** Version bump only for package @ionic/angular-server
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
## [6.0.11](https://github.com/ionic-team/ionic/compare/v6.0.10...v6.0.11) (2022-03-09)
|
||||
|
||||
**Note:** Version bump only for package @ionic/angular-server
|
||||
|
||||
2
packages/angular-server/package-lock.json
generated
2
packages/angular-server/package-lock.json
generated
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@ionic/angular-server",
|
||||
"version": "6.0.11",
|
||||
"version": "6.0.13",
|
||||
"lockfileVersion": 2,
|
||||
"requires": true,
|
||||
"packages": {
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@ionic/angular-server",
|
||||
"version": "6.0.11",
|
||||
"version": "6.0.13",
|
||||
"description": "Angular SSR Module for Ionic",
|
||||
"keywords": [
|
||||
"ionic",
|
||||
@@ -56,7 +56,7 @@
|
||||
"@angular/platform-browser": "^12.0.0",
|
||||
"@angular/platform-browser-dynamic": "^12.2.10",
|
||||
"@angular/platform-server": "^12.0.0",
|
||||
"@ionic/core": "^6.0.11",
|
||||
"@ionic/core": "^6.0.13",
|
||||
"@ionic/eslint-config": "^0.3.0",
|
||||
"@ionic/prettier-config": "^2.0.0",
|
||||
"@typescript-eslint/eslint-plugin": "^5.2.0",
|
||||
|
||||
@@ -3,6 +3,22 @@
|
||||
All notable changes to this project will be documented in this file.
|
||||
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
|
||||
|
||||
## [6.0.13](https://github.com/ionic-team/ionic/compare/v6.0.12...v6.0.13) (2022-03-23)
|
||||
|
||||
**Note:** Version bump only for package @ionic/react-router
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
## [6.0.12](https://github.com/ionic-team/ionic/compare/v6.0.11...v6.0.12) (2022-03-16)
|
||||
|
||||
**Note:** Version bump only for package @ionic/react-router
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
## [6.0.11](https://github.com/ionic-team/ionic/compare/v6.0.10...v6.0.11) (2022-03-09)
|
||||
|
||||
**Note:** Version bump only for package @ionic/react-router
|
||||
|
||||
2
packages/react-router/package-lock.json
generated
2
packages/react-router/package-lock.json
generated
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@ionic/react-router",
|
||||
"version": "6.0.11",
|
||||
"version": "6.0.13",
|
||||
"lockfileVersion": 2,
|
||||
"requires": true,
|
||||
"packages": {
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@ionic/react-router",
|
||||
"version": "6.0.11",
|
||||
"version": "6.0.13",
|
||||
"description": "React Router wrapper for @ionic/react",
|
||||
"keywords": [
|
||||
"ionic",
|
||||
@@ -37,7 +37,7 @@
|
||||
"dist/"
|
||||
],
|
||||
"dependencies": {
|
||||
"@ionic/react": "^6.0.11",
|
||||
"@ionic/react": "^6.0.13",
|
||||
"tslib": "*"
|
||||
},
|
||||
"peerDependencies": {
|
||||
|
||||
@@ -3,6 +3,22 @@
|
||||
All notable changes to this project will be documented in this file.
|
||||
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
|
||||
|
||||
## [6.0.13](https://github.com/ionic-team/ionic/compare/v6.0.12...v6.0.13) (2022-03-23)
|
||||
|
||||
**Note:** Version bump only for package @ionic/react
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
## [6.0.12](https://github.com/ionic-team/ionic/compare/v6.0.11...v6.0.12) (2022-03-16)
|
||||
|
||||
**Note:** Version bump only for package @ionic/react
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
## [6.0.11](https://github.com/ionic-team/ionic/compare/v6.0.10...v6.0.11) (2022-03-09)
|
||||
|
||||
**Note:** Version bump only for package @ionic/react
|
||||
|
||||
2
packages/react/package-lock.json
generated
2
packages/react/package-lock.json
generated
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@ionic/react",
|
||||
"version": "6.0.11",
|
||||
"version": "6.0.13",
|
||||
"lockfileVersion": 2,
|
||||
"requires": true,
|
||||
"packages": {
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@ionic/react",
|
||||
"version": "6.0.11",
|
||||
"version": "6.0.13",
|
||||
"description": "React specific wrapper for @ionic/core",
|
||||
"keywords": [
|
||||
"ionic",
|
||||
@@ -41,7 +41,7 @@
|
||||
"css/"
|
||||
],
|
||||
"dependencies": {
|
||||
"@ionic/core": "^6.0.11",
|
||||
"@ionic/core": "^6.0.13",
|
||||
"ionicons": "^6.0.0",
|
||||
"tslib": "*"
|
||||
},
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { componentOnReady } from '@ionic/core';
|
||||
import { componentOnReady } from '@ionic/core/components';
|
||||
import React from 'react';
|
||||
|
||||
import { IonRouterOutletInner } from '../components/inner-proxies';
|
||||
|
||||
@@ -1,10 +0,0 @@
|
||||
import { CapacitorConfig } from '@capacitor/cli';
|
||||
|
||||
const config: CapacitorConfig = {
|
||||
appId: 'io.ionic.starter',
|
||||
appName: 'test-app',
|
||||
webDir: 'build',
|
||||
bundledWebRuntime: false
|
||||
};
|
||||
|
||||
export default config;
|
||||
35344
packages/react/test-app/package-lock.json
generated
35344
packages/react/test-app/package-lock.json
generated
File diff suppressed because it is too large
Load Diff
@@ -3,43 +3,18 @@
|
||||
"version": "0.0.1",
|
||||
"private": true,
|
||||
"dependencies": {
|
||||
"@capacitor/app": "1.0.3",
|
||||
"@capacitor/core": "3.2.4",
|
||||
"@capacitor/haptics": "1.1.0",
|
||||
"@capacitor/keyboard": "1.1.0",
|
||||
"@capacitor/status-bar": "1.0.3",
|
||||
"@ionic/react": "^5.8.3",
|
||||
"@ionic/react-router": "^5.8.3",
|
||||
"@testing-library/jest-dom": "^5.11.9",
|
||||
"@testing-library/react": "^11.2.5",
|
||||
"@testing-library/user-event": "^12.6.3",
|
||||
"@types/jest": "^26.0.20",
|
||||
"@types/node": "^12.19.15",
|
||||
"@ionic/react": "^6.0.12",
|
||||
"@ionic/react-router": "^6.0.12",
|
||||
"@types/react": "^16.14.3",
|
||||
"@types/react-dom": "^16.9.10",
|
||||
"@types/react-router": "^5.1.11",
|
||||
"@types/react-router-dom": "^5.1.7",
|
||||
"cypress": "^8.5.0",
|
||||
"ionicons": "^5.4.0",
|
||||
"react": "^17.0.1",
|
||||
"react-dom": "^17.0.1",
|
||||
"react-router": "^5.2.0",
|
||||
"react-router-dom": "^5.2.0",
|
||||
"react-scripts": "^4.0.3",
|
||||
"typescript": "^4.1.3",
|
||||
"web-vitals": "^0.2.4",
|
||||
"workbox-background-sync": "^5.1.4",
|
||||
"workbox-broadcast-update": "^5.1.4",
|
||||
"workbox-cacheable-response": "^5.1.4",
|
||||
"workbox-core": "^5.1.4",
|
||||
"workbox-expiration": "^5.1.4",
|
||||
"workbox-google-analytics": "^5.1.4",
|
||||
"workbox-navigation-preload": "^5.1.4",
|
||||
"workbox-precaching": "^5.1.4",
|
||||
"workbox-range-requests": "^5.1.4",
|
||||
"workbox-routing": "^5.1.4",
|
||||
"workbox-strategies": "^5.1.4",
|
||||
"workbox-streams": "^5.1.4"
|
||||
"react-scripts": "^5.0.0",
|
||||
"typescript": "^4.1.3"
|
||||
},
|
||||
"scripts": {
|
||||
"start": "react-scripts start",
|
||||
@@ -69,8 +44,13 @@
|
||||
]
|
||||
},
|
||||
"devDependencies": {
|
||||
"@capacitor/cli": "3.2.4",
|
||||
"@testing-library/jest-dom": "^5.16.2",
|
||||
"@testing-library/react": "^12.1.4",
|
||||
"@testing-library/user-event": "^13.5.0",
|
||||
"@types/jest": "^27.4.1",
|
||||
"@types/node": "^17.0.21",
|
||||
"concurrently": "^6.3.0",
|
||||
"cypress": "^9.5.2",
|
||||
"serve": "^13.0.2",
|
||||
"wait-on": "^6.0.0",
|
||||
"webpack-cli": "^4.9.1"
|
||||
|
||||
@@ -1,8 +1,6 @@
|
||||
import React from 'react';
|
||||
import ReactDOM from 'react-dom';
|
||||
import App from './App';
|
||||
import * as serviceWorkerRegistration from './serviceWorkerRegistration';
|
||||
import reportWebVitals from './reportWebVitals';
|
||||
|
||||
ReactDOM.render(
|
||||
<React.StrictMode>
|
||||
@@ -10,13 +8,3 @@ ReactDOM.render(
|
||||
</React.StrictMode>,
|
||||
document.getElementById('root')
|
||||
);
|
||||
|
||||
// If you want your app to work offline and load faster, you can change
|
||||
// unregister() to register() below. Note this comes with some pitfalls.
|
||||
// Learn more about service workers: https://cra.link/PWA
|
||||
serviceWorkerRegistration.unregister();
|
||||
|
||||
// If you want to start measuring performance in your app, pass a function
|
||||
// to log results (for example: reportWebVitals(console.log))
|
||||
// or send to an analytics endpoint. Learn more: https://bit.ly/CRA-vitals
|
||||
reportWebVitals();
|
||||
|
||||
@@ -1,15 +0,0 @@
|
||||
import { ReportHandler } from 'web-vitals';
|
||||
|
||||
const reportWebVitals = (onPerfEntry?: ReportHandler) => {
|
||||
if (onPerfEntry && onPerfEntry instanceof Function) {
|
||||
import('web-vitals').then(({ getCLS, getFID, getFCP, getLCP, getTTFB }) => {
|
||||
getCLS(onPerfEntry);
|
||||
getFID(onPerfEntry);
|
||||
getFCP(onPerfEntry);
|
||||
getLCP(onPerfEntry);
|
||||
getTTFB(onPerfEntry);
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
export default reportWebVitals;
|
||||
@@ -1,80 +0,0 @@
|
||||
/// <reference lib="webworker" />
|
||||
/* eslint-disable no-restricted-globals */
|
||||
|
||||
// This service worker can be customized!
|
||||
// See https://developers.google.com/web/tools/workbox/modules
|
||||
// for the list of available Workbox modules, or add any other
|
||||
// code you'd like.
|
||||
// You can also remove this file if you'd prefer not to use a
|
||||
// service worker, and the Workbox build step will be skipped.
|
||||
|
||||
import { clientsClaim } from 'workbox-core';
|
||||
import { ExpirationPlugin } from 'workbox-expiration';
|
||||
import { precacheAndRoute, createHandlerBoundToURL } from 'workbox-precaching';
|
||||
import { registerRoute } from 'workbox-routing';
|
||||
import { StaleWhileRevalidate } from 'workbox-strategies';
|
||||
|
||||
declare const self: ServiceWorkerGlobalScope;
|
||||
|
||||
clientsClaim();
|
||||
|
||||
// Precache all of the assets generated by your build process.
|
||||
// Their URLs are injected into the manifest variable below.
|
||||
// This variable must be present somewhere in your service worker file,
|
||||
// even if you decide not to use precaching. See https://cra.link/PWA
|
||||
precacheAndRoute(self.__WB_MANIFEST);
|
||||
|
||||
// Set up App Shell-style routing, so that all navigation requests
|
||||
// are fulfilled with your index.html shell. Learn more at
|
||||
// https://developers.google.com/web/fundamentals/architecture/app-shell
|
||||
const fileExtensionRegexp = new RegExp('/[^/?]+\\.[^/]+$');
|
||||
registerRoute(
|
||||
// Return false to exempt requests from being fulfilled by index.html.
|
||||
({ request, url }: { request: Request; url: URL }) => {
|
||||
// If this isn't a navigation, skip.
|
||||
if (request.mode !== 'navigate') {
|
||||
return false;
|
||||
}
|
||||
|
||||
// If this is a URL that starts with /_, skip.
|
||||
if (url.pathname.startsWith('/_')) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// If this looks like a URL for a resource, because it contains
|
||||
// a file extension, skip.
|
||||
if (url.pathname.match(fileExtensionRegexp)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Return true to signal that we want to use the handler.
|
||||
return true;
|
||||
},
|
||||
createHandlerBoundToURL(process.env.PUBLIC_URL + '/index.html')
|
||||
);
|
||||
|
||||
// An example runtime caching route for requests that aren't handled by the
|
||||
// precache, in this case same-origin .png requests like those from in public/
|
||||
registerRoute(
|
||||
// Add in any other file extensions or routing criteria as needed.
|
||||
({ url }) => url.origin === self.location.origin && url.pathname.endsWith('.png'),
|
||||
// Customize this strategy as needed, e.g., by changing to CacheFirst.
|
||||
new StaleWhileRevalidate({
|
||||
cacheName: 'images',
|
||||
plugins: [
|
||||
// Ensure that once this runtime cache reaches a maximum size the
|
||||
// least-recently used images are removed.
|
||||
new ExpirationPlugin({ maxEntries: 50 }),
|
||||
],
|
||||
})
|
||||
);
|
||||
|
||||
// This allows the web app to trigger skipWaiting via
|
||||
// registration.waiting.postMessage({type: 'SKIP_WAITING'})
|
||||
self.addEventListener('message', (event) => {
|
||||
if (event.data && event.data.type === 'SKIP_WAITING') {
|
||||
self.skipWaiting();
|
||||
}
|
||||
});
|
||||
|
||||
// Any other custom service worker logic can go here.
|
||||
@@ -1,142 +0,0 @@
|
||||
// This optional code is used to register a service worker.
|
||||
// register() is not called by default.
|
||||
|
||||
// This lets the app load faster on subsequent visits in production, and gives
|
||||
// it offline capabilities. However, it also means that developers (and users)
|
||||
// will only see deployed updates on subsequent visits to a page, after all the
|
||||
// existing tabs open on the page have been closed, since previously cached
|
||||
// resources are updated in the background.
|
||||
|
||||
// To learn more about the benefits of this model and instructions on how to
|
||||
// opt-in, read https://cra.link/PWA
|
||||
|
||||
const isLocalhost = Boolean(
|
||||
window.location.hostname === 'localhost' ||
|
||||
// [::1] is the IPv6 localhost address.
|
||||
window.location.hostname === '[::1]' ||
|
||||
// 127.0.0.0/8 are considered localhost for IPv4.
|
||||
window.location.hostname.match(/^127(?:\.(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)){3}$/)
|
||||
);
|
||||
|
||||
type Config = {
|
||||
onSuccess?: (registration: ServiceWorkerRegistration) => void;
|
||||
onUpdate?: (registration: ServiceWorkerRegistration) => void;
|
||||
};
|
||||
|
||||
export function register(config?: Config) {
|
||||
if (process.env.NODE_ENV === 'production' && 'serviceWorker' in navigator) {
|
||||
// The URL constructor is available in all browsers that support SW.
|
||||
const publicUrl = new URL(process.env.PUBLIC_URL, window.location.href);
|
||||
if (publicUrl.origin !== window.location.origin) {
|
||||
// Our service worker won't work if PUBLIC_URL is on a different origin
|
||||
// from what our page is served on. This might happen if a CDN is used to
|
||||
// serve assets; see https://github.com/facebook/create-react-app/issues/2374
|
||||
return;
|
||||
}
|
||||
|
||||
window.addEventListener('load', () => {
|
||||
const swUrl = `${process.env.PUBLIC_URL}/service-worker.js`;
|
||||
|
||||
if (isLocalhost) {
|
||||
// This is running on localhost. Let's check if a service worker still exists or not.
|
||||
checkValidServiceWorker(swUrl, config);
|
||||
|
||||
// Add some additional logging to localhost, pointing developers to the
|
||||
// service worker/PWA documentation.
|
||||
navigator.serviceWorker.ready.then(() => {
|
||||
console.log(
|
||||
'This web app is being served cache-first by a service ' +
|
||||
'worker. To learn more, visit https://cra.link/PWA'
|
||||
);
|
||||
});
|
||||
} else {
|
||||
// Is not localhost. Just register service worker
|
||||
registerValidSW(swUrl, config);
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
function registerValidSW(swUrl: string, config?: Config) {
|
||||
navigator.serviceWorker
|
||||
.register(swUrl)
|
||||
.then((registration) => {
|
||||
registration.onupdatefound = () => {
|
||||
const installingWorker = registration.installing;
|
||||
if (installingWorker == null) {
|
||||
return;
|
||||
}
|
||||
installingWorker.onstatechange = () => {
|
||||
if (installingWorker.state === 'installed') {
|
||||
if (navigator.serviceWorker.controller) {
|
||||
// At this point, the updated precached content has been fetched,
|
||||
// but the previous service worker will still serve the older
|
||||
// content until all client tabs are closed.
|
||||
console.log(
|
||||
'New content is available and will be used when all ' +
|
||||
'tabs for this page are closed. See https://cra.link/PWA.'
|
||||
);
|
||||
|
||||
// Execute callback
|
||||
if (config && config.onUpdate) {
|
||||
config.onUpdate(registration);
|
||||
}
|
||||
} else {
|
||||
// At this point, everything has been precached.
|
||||
// It's the perfect time to display a
|
||||
// "Content is cached for offline use." message.
|
||||
console.log('Content is cached for offline use.');
|
||||
|
||||
// Execute callback
|
||||
if (config && config.onSuccess) {
|
||||
config.onSuccess(registration);
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
};
|
||||
})
|
||||
.catch((error) => {
|
||||
console.error('Error during service worker registration:', error);
|
||||
});
|
||||
}
|
||||
|
||||
function checkValidServiceWorker(swUrl: string, config?: Config) {
|
||||
// Check if the service worker can be found. If it can't reload the page.
|
||||
fetch(swUrl, {
|
||||
headers: { 'Service-Worker': 'script' },
|
||||
})
|
||||
.then((response) => {
|
||||
// Ensure service worker exists, and that we really are getting a JS file.
|
||||
const contentType = response.headers.get('content-type');
|
||||
if (
|
||||
response.status === 404 ||
|
||||
(contentType != null && contentType.indexOf('javascript') === -1)
|
||||
) {
|
||||
// No service worker found. Probably a different app. Reload the page.
|
||||
navigator.serviceWorker.ready.then((registration) => {
|
||||
registration.unregister().then(() => {
|
||||
window.location.reload();
|
||||
});
|
||||
});
|
||||
} else {
|
||||
// Service worker found. Proceed as normal.
|
||||
registerValidSW(swUrl, config);
|
||||
}
|
||||
})
|
||||
.catch(() => {
|
||||
console.log('No internet connection found. App is running in offline mode.');
|
||||
});
|
||||
}
|
||||
|
||||
export function unregister() {
|
||||
if ('serviceWorker' in navigator) {
|
||||
navigator.serviceWorker.ready
|
||||
.then((registration) => {
|
||||
registration.unregister();
|
||||
})
|
||||
.catch((error) => {
|
||||
console.error(error.message);
|
||||
});
|
||||
}
|
||||
}
|
||||
@@ -3,6 +3,25 @@
|
||||
All notable changes to this project will be documented in this file.
|
||||
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
|
||||
|
||||
## [6.0.13](https://github.com/ionic-team/ionic/compare/v6.0.12...v6.0.13) (2022-03-23)
|
||||
|
||||
**Note:** Version bump only for package @ionic/vue-router
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
## [6.0.12](https://github.com/ionic-team/ionic/compare/v6.0.11...v6.0.12) (2022-03-16)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* **vue:** tapping the active tab button now correctly resets the tab stack ([#24935](https://github.com/ionic-team/ionic/issues/24935)) ([4534c8b](https://github.com/ionic-team/ionic/commit/4534c8bc0b2bca7ab6eecd9886243116e9a039b7)), closes [#24934](https://github.com/ionic-team/ionic/issues/24934)
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
## [6.0.11](https://github.com/ionic-team/ionic/compare/v6.0.10...v6.0.11) (2022-03-09)
|
||||
|
||||
**Note:** Version bump only for package @ionic/vue-router
|
||||
|
||||
2
packages/vue-router/package-lock.json
generated
2
packages/vue-router/package-lock.json
generated
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@ionic/vue-router",
|
||||
"version": "6.0.11",
|
||||
"version": "6.0.13",
|
||||
"lockfileVersion": 2,
|
||||
"requires": true,
|
||||
"packages": {
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@ionic/vue-router",
|
||||
"version": "6.0.11",
|
||||
"version": "6.0.13",
|
||||
"description": "Vue Router integration for @ionic/vue",
|
||||
"scripts": {
|
||||
"prepublishOnly": "npm run build",
|
||||
@@ -44,7 +44,7 @@
|
||||
},
|
||||
"homepage": "https://github.com/ionic-team/ionic#readme",
|
||||
"dependencies": {
|
||||
"@ionic/vue": "^6.0.11"
|
||||
"@ionic/vue": "^6.0.13"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@types/jest": "^26.0.13",
|
||||
|
||||
@@ -92,16 +92,39 @@ export const createLocationHistory = () => {
|
||||
* and every entry that appears after it.
|
||||
*/
|
||||
const clearHistory = (routeInfo?: RouteInfo) => {
|
||||
Object.keys(tabsHistory).forEach(key => {
|
||||
tabsHistory[key] = [];
|
||||
});
|
||||
|
||||
if (routeInfo) {
|
||||
|
||||
/**
|
||||
* If there is no route index in locationHistory
|
||||
* then there will not be any route index in
|
||||
* tabs either.
|
||||
*/
|
||||
const existingRouteIndex = locationHistory.findIndex(r => r.position === routeInfo.position);
|
||||
if (existingRouteIndex === -1) return;
|
||||
|
||||
locationHistory.splice(existingRouteIndex);
|
||||
|
||||
/**
|
||||
* We also need to search the current tab
|
||||
* to correctly reset the individual tab
|
||||
* stack. We should not clear the entire
|
||||
* tab stack as that means we will lose
|
||||
* a reference to the root tab route.
|
||||
*/
|
||||
const { tab } = routeInfo;
|
||||
const tabHistory = tabsHistory[tab];
|
||||
if (tab && tabHistory) {
|
||||
const existingTabRouteIndex = tabHistory.findIndex(r => r.position === routeInfo.position);
|
||||
if (existingTabRouteIndex === -1) return;
|
||||
|
||||
tabsHistory[tab].splice(existingTabRouteIndex);
|
||||
}
|
||||
|
||||
} else {
|
||||
Object.keys(tabsHistory).forEach(key => {
|
||||
tabsHistory[key] = [];
|
||||
});
|
||||
|
||||
locationHistory.length = 0;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -409,13 +409,22 @@ export const createIonRouter = (opts: IonicVueRouterOptions, router: Router) =>
|
||||
router.push(routerLink);
|
||||
}
|
||||
|
||||
const resetTab = (tab: string, originalHref: string) => {
|
||||
const resetTab = (tab: string) => {
|
||||
/**
|
||||
* Resetting the tab should go back
|
||||
* to the initial view in the tab stack.
|
||||
* It should not push a new instance of the
|
||||
* root tab page onto the stack.
|
||||
*
|
||||
* To do this, we get the initial view in the
|
||||
* tab stack and subtract the position of that
|
||||
* entry from our current position. From there
|
||||
* we call router.go() to move us back the
|
||||
* appropriate number of positions.
|
||||
*/
|
||||
const routeInfo = locationHistory.getFirstRouteInfoForTab(tab);
|
||||
if (routeInfo) {
|
||||
const newRouteInfo = { ...routeInfo };
|
||||
newRouteInfo.pathname = originalHref;
|
||||
incomingRouteParams = { ...newRouteInfo, routerAction: 'pop', routerDirection: 'back' };
|
||||
router.push({ path: newRouteInfo.pathname, query: parseQuery(newRouteInfo.search) });
|
||||
router.go(routeInfo.position - currentHistoryPosition);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -3,6 +3,25 @@
|
||||
All notable changes to this project will be documented in this file.
|
||||
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
|
||||
|
||||
## [6.0.13](https://github.com/ionic-team/ionic/compare/v6.0.12...v6.0.13) (2022-03-23)
|
||||
|
||||
**Note:** Version bump only for package @ionic/vue
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
## [6.0.12](https://github.com/ionic-team/ionic/compare/v6.0.11...v6.0.12) (2022-03-16)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* **vue:** tapping the active tab button now correctly resets the tab stack ([#24935](https://github.com/ionic-team/ionic/issues/24935)) ([4534c8b](https://github.com/ionic-team/ionic/commit/4534c8bc0b2bca7ab6eecd9886243116e9a039b7)), closes [#24934](https://github.com/ionic-team/ionic/issues/24934)
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
## [6.0.11](https://github.com/ionic-team/ionic/compare/v6.0.10...v6.0.11) (2022-03-09)
|
||||
|
||||
**Note:** Version bump only for package @ionic/vue
|
||||
|
||||
2
packages/vue/package-lock.json
generated
2
packages/vue/package-lock.json
generated
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@ionic/vue",
|
||||
"version": "6.0.11",
|
||||
"version": "6.0.13",
|
||||
"lockfileVersion": 2,
|
||||
"requires": true,
|
||||
"packages": {
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@ionic/vue",
|
||||
"version": "6.0.11",
|
||||
"version": "6.0.13",
|
||||
"description": "Vue specific wrapper for @ionic/core",
|
||||
"scripts": {
|
||||
"prepublishOnly": "npm run build",
|
||||
@@ -60,7 +60,7 @@
|
||||
"vue-router": "^4.0.0-rc.4"
|
||||
},
|
||||
"dependencies": {
|
||||
"@ionic/core": "^6.0.11",
|
||||
"@ionic/core": "^6.0.13",
|
||||
"ionicons": "^6.0.0"
|
||||
},
|
||||
"vetur": {
|
||||
|
||||
@@ -47,7 +47,7 @@ export const IonTabButton = /*@__PURE__*/ defineComponent({
|
||||
*/
|
||||
if (prevActiveTab === tab) {
|
||||
if (originalHref !== currentHref) {
|
||||
ionRouter.resetTab(tab, originalHref);
|
||||
ionRouter.resetTab(tab);
|
||||
}
|
||||
} else {
|
||||
ionRouter.changeTab(tab, currentHref)
|
||||
|
||||
@@ -9,13 +9,15 @@ module.exports = {
|
||||
'@vue/typescript/recommended'
|
||||
],
|
||||
parserOptions: {
|
||||
ecmaVersion: 2020
|
||||
ecmaVersion: 2020,
|
||||
parser: '@typescript-eslint/parser'
|
||||
},
|
||||
rules: {
|
||||
'no-console': process.env.NODE_ENV === 'production' ? 'warn' : 'off',
|
||||
'no-debugger': process.env.NODE_ENV === 'production' ? 'warn' : 'off',
|
||||
'vue/no-deprecated-slot-attribute': 'off',
|
||||
'@typescript-eslint/no-explicit-any': 'off',
|
||||
'vue/multi-word-component-names': 'off'
|
||||
},
|
||||
overrides: [
|
||||
{
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
module.exports = {
|
||||
preset: "@vue/cli-plugin-unit-jest/presets/typescript-and-babel",
|
||||
transform: {
|
||||
"^.+\\.vue$": "vue-jest"
|
||||
"^.+\\.vue$": "@vue/vue3-jest"
|
||||
},
|
||||
transformIgnorePatterns: ['/node_modules/(?!ionicons|@stencil/core|@ionic/core|@ionic/vue|@ionic/vue-router)'],
|
||||
globals: {
|
||||
|
||||
40962
packages/vue/test-app/package-lock.json
generated
40962
packages/vue/test-app/package-lock.json
generated
File diff suppressed because it is too large
Load Diff
@@ -13,30 +13,32 @@
|
||||
"sync": "sh ./scripts/sync.sh"
|
||||
},
|
||||
"dependencies": {
|
||||
"@ionic/vue": "5.6.3",
|
||||
"@ionic/vue-router": "5.6.3",
|
||||
"vue": "^3.2.22",
|
||||
"vue-router": "^4.0.12"
|
||||
"@ionic/vue": "^6.0.12",
|
||||
"@ionic/vue-router": "^6.0.12",
|
||||
"vue": "^3.2.31",
|
||||
"vue-router": "^4.0.14"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@types/jest": "^24.0.19",
|
||||
"@typescript-eslint/eslint-plugin": "^2.33.0",
|
||||
"@typescript-eslint/parser": "^2.33.0",
|
||||
"@vue/cli-plugin-babel": "~4.5.15",
|
||||
"@vue/cli-plugin-e2e-cypress": "^5.0.0-alpha.7",
|
||||
"@vue/cli-plugin-eslint": "~4.5.15",
|
||||
"@vue/cli-plugin-router": "~4.5.15",
|
||||
"@vue/cli-plugin-typescript": "~4.5.15",
|
||||
"@vue/cli-plugin-unit-jest": "~4.5.15",
|
||||
"@vue/cli-service": "~4.5.15",
|
||||
"@vue/compiler-sfc": "^3.0.0-0",
|
||||
"@vue/eslint-config-typescript": "^5.0.2",
|
||||
"@typescript-eslint/eslint-plugin": "^5.4.0",
|
||||
"@typescript-eslint/parser": "^5.4.0",
|
||||
"@vue/cli-plugin-babel": "~5.0.3",
|
||||
"@vue/cli-plugin-e2e-cypress": "~5.0.3",
|
||||
"@vue/cli-plugin-eslint": "~5.0.3",
|
||||
"@vue/cli-plugin-router": "~5.0.3",
|
||||
"@vue/cli-plugin-typescript": "~5.0.3",
|
||||
"@vue/cli-plugin-unit-jest": "~5.0.3",
|
||||
"@vue/cli-service": "~5.0.3",
|
||||
"@vue/eslint-config-typescript": "^9.1.0",
|
||||
"@vue/test-utils": "^2.0.0-rc.18",
|
||||
"@vue/vue3-jest": "^27.0.0-alpha.4",
|
||||
"concurrently": "^6.0.0",
|
||||
"eslint": "^6.7.2",
|
||||
"eslint-plugin-vue": "^7.0.0-0",
|
||||
"typescript": "~4.1.5",
|
||||
"vue-jest": "^5.0.0-0",
|
||||
"cypress": "^8.3.0",
|
||||
"eslint": "^7.32.0",
|
||||
"eslint-plugin-vue": "^8.0.3",
|
||||
"jest": "^27.1.0",
|
||||
"ts-jest": "^27.0.4",
|
||||
"typescript": "~4.5.5",
|
||||
"wait-on": "^5.3.0"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -9,7 +9,6 @@ import { IonApp, IonRouterOutlet, useIonRouter } from '@ionic/vue';
|
||||
import { defineComponent } from 'vue';
|
||||
|
||||
export default defineComponent({
|
||||
name: 'App',
|
||||
components: {
|
||||
IonApp,
|
||||
IonRouterOutlet
|
||||
|
||||
@@ -8,7 +8,6 @@
|
||||
<script lang="ts">
|
||||
|
||||
export default {
|
||||
name: 'ExploreContainer',
|
||||
props: {
|
||||
name: String
|
||||
}
|
||||
@@ -40,4 +39,4 @@ export default {
|
||||
#container a {
|
||||
text-decoration: none;
|
||||
}
|
||||
</style>
|
||||
</style>
|
||||
|
||||
@@ -28,7 +28,6 @@ import {
|
||||
import { defineComponent } from 'vue';
|
||||
|
||||
export default defineComponent({
|
||||
name: 'ModalContent',
|
||||
props: {
|
||||
title: { type: String, default: 'Default Title' }
|
||||
},
|
||||
|
||||
@@ -12,7 +12,6 @@ import {
|
||||
import { defineComponent } from 'vue';
|
||||
|
||||
export default defineComponent({
|
||||
name: 'PopoverContent',
|
||||
props: {
|
||||
title: { type: String, default: 'Default Title' }
|
||||
},
|
||||
|
||||
@@ -23,17 +23,14 @@ const routes: Array<RouteRecordRaw> = [
|
||||
},
|
||||
{
|
||||
path: '/overlays',
|
||||
name: 'Overlays',
|
||||
component: () => import('@/views/Overlays.vue')
|
||||
},
|
||||
{
|
||||
path: '/inputs',
|
||||
name: 'Inputs',
|
||||
component: () => import('@/views/Inputs.vue')
|
||||
},
|
||||
{
|
||||
path: '/slides',
|
||||
name: 'Slides',
|
||||
component: () => import('@/views/Slides.vue')
|
||||
},
|
||||
{
|
||||
@@ -63,7 +60,6 @@ const routes: Array<RouteRecordRaw> = [
|
||||
},
|
||||
{
|
||||
path: '/nested',
|
||||
name: 'RouterOutlet',
|
||||
component: () => import('@/views/RouterOutlet.vue'),
|
||||
children: [
|
||||
{
|
||||
|
||||
@@ -28,7 +28,6 @@
|
||||
import { IonButtons, IonContent, IonHeader, IonMenuButton, IonPage, IonTitle, IonToolbar } from '@ionic/vue';
|
||||
|
||||
export default {
|
||||
name: 'Folder',
|
||||
components: {
|
||||
IonButtons,
|
||||
IonContent,
|
||||
|
||||
@@ -64,7 +64,6 @@ import { IonButtons, IonBackButton, IonContent, IonHeader, IonItem, IonLabel, Io
|
||||
import { defineComponent } from 'vue';
|
||||
|
||||
export default defineComponent({
|
||||
name: 'Home',
|
||||
components: {
|
||||
IonButtons,
|
||||
IonBackButton,
|
||||
|
||||
@@ -132,7 +132,6 @@ import {
|
||||
import { defineComponent, ref } from 'vue';
|
||||
|
||||
export default defineComponent({
|
||||
name: 'Home',
|
||||
components: {
|
||||
IonBackButton,
|
||||
IonButton,
|
||||
|
||||
@@ -38,7 +38,6 @@ import {
|
||||
import { defineComponent } from 'vue';
|
||||
|
||||
export default defineComponent({
|
||||
name: 'NestedChild',
|
||||
components: {
|
||||
IonBackButton,
|
||||
IonButton,
|
||||
|
||||
@@ -32,7 +32,6 @@ import {
|
||||
import { defineComponent } from 'vue';
|
||||
|
||||
export default defineComponent({
|
||||
name: 'NestedChildTwo',
|
||||
components: {
|
||||
IonBackButton,
|
||||
IonButtons,
|
||||
|
||||
@@ -164,7 +164,6 @@ import ModalContent from '@/components/ModalContent.vue';
|
||||
import PopoverContent from '@/components/PopoverContent.vue';
|
||||
|
||||
export default defineComponent({
|
||||
name: 'Overlays',
|
||||
components: {
|
||||
ModalContent,
|
||||
PopoverContent,
|
||||
|
||||
@@ -30,7 +30,6 @@ import {
|
||||
import { defineComponent } from 'vue';
|
||||
|
||||
export default defineComponent({
|
||||
name: 'RouterOutlet',
|
||||
components: {
|
||||
IonHeader,
|
||||
IonButtons,
|
||||
|
||||
@@ -50,7 +50,6 @@ import {
|
||||
import { defineComponent, ref } from 'vue';
|
||||
|
||||
export default defineComponent({
|
||||
name: 'Home',
|
||||
components: {
|
||||
IonBackButton,
|
||||
IonButton,
|
||||
|
||||
@@ -44,7 +44,6 @@ import { IonButtons, IonBackButton, IonPage, IonHeader, IonItem, IonLabel, IonTo
|
||||
import ExploreContainer from '@/components/ExploreContainer.vue';
|
||||
|
||||
export default {
|
||||
name: 'Tab1',
|
||||
components: { IonButtons, IonBackButton, ExploreContainer, IonHeader, IonItem, IonLabel, IonToolbar, IonTitle, IonContent, IonPage }
|
||||
}
|
||||
</script>
|
||||
|
||||
@@ -22,7 +22,6 @@ import { IonPage, IonHeader, IonToolbar, IonTitle, IonContent } from '@ionic/vue
|
||||
import ExploreContainer from '@/components/ExploreContainer.vue';
|
||||
|
||||
export default {
|
||||
name: 'Tab3',
|
||||
components: { ExploreContainer, IonHeader, IonToolbar, IonTitle, IonContent, IonPage }
|
||||
}
|
||||
</script>
|
||||
|
||||
@@ -28,7 +28,6 @@ import { useRouter } from 'vue-router';
|
||||
import { ref, defineComponent } from 'vue';
|
||||
|
||||
export default defineComponent({
|
||||
name: 'Tabs',
|
||||
components: { IonButton, IonContent, IonLabel, IonTabs, IonTabBar, IonTabButton, IonIcon, IonPage, IonRouterOutlet },
|
||||
setup() {
|
||||
const tabs = ref([
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user