chore(): sync with main:
9
.github/workflows/release.yml
vendored
@@ -32,9 +32,14 @@ jobs:
|
||||
with:
|
||||
node-version: 16
|
||||
- name: Configure Identity
|
||||
# Commits from github-actions do not
|
||||
# trigger other GitHub Actions. As a result,
|
||||
# we publish releases from Ionitron instead
|
||||
# so actions run when merging the release branch
|
||||
# back into main.
|
||||
run: |
|
||||
git config user.name github-actions
|
||||
git config user.email github-actions@github.com
|
||||
git config user.name ionitron
|
||||
git config user.email hi@ionicframework.com
|
||||
shell: bash
|
||||
- name: Install Dependencies
|
||||
run: npm ci --no-package-lock && lerna bootstrap --ignore-scripts -- --legacy-peer-deps
|
||||
|
||||
21
CHANGELOG.md
@@ -3,6 +3,27 @@
|
||||
All notable changes to this project will be documented in this file.
|
||||
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
|
||||
|
||||
# [6.3.0](https://github.com/ionic-team/ionic-framework/compare/v6.2.9...v6.3.0) (2022-10-05)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* **list:** remove extra border in md inset list items ([#25972](https://github.com/ionic-team/ionic-framework/issues/25972)) ([3eb3dd5](https://github.com/ionic-team/ionic-framework/commit/3eb3dd5afa02f7257e2594f56efe570be83719b6)), closes [#25278](https://github.com/ionic-team/ionic-framework/issues/25278)
|
||||
* **range:** indication when range knob is focused ([#25827](https://github.com/ionic-team/ionic-framework/issues/25827)) ([2c815cf](https://github.com/ionic-team/ionic-framework/commit/2c815cff139a0061883d3eef47816aea8801dcf4))
|
||||
|
||||
|
||||
### Features
|
||||
|
||||
* **alert:** accept Promise for button handler ([#25702](https://github.com/ionic-team/ionic-framework/issues/25702)) ([8e4783c](https://github.com/ionic-team/ionic-framework/commit/8e4783c17298e8f7654590108430e80f22ed6a7a)), closes [#25700](https://github.com/ionic-team/ionic-framework/issues/25700)
|
||||
* **angular:** use standalone components with routing ([#25589](https://github.com/ionic-team/ionic-framework/issues/25589)) ([3c84d48](https://github.com/ionic-team/ionic-framework/commit/3c84d48cfa87810896364cb7ca16efcbdd7e8b07)), closes [#25404](https://github.com/ionic-team/ionic-framework/issues/25404)
|
||||
* **button:** submit from outside of form ([#25913](https://github.com/ionic-team/ionic-framework/issues/25913)) ([b139838](https://github.com/ionic-team/ionic-framework/commit/b13983848c9ea7387062953412eaae744c001ec7)), closes [#21194](https://github.com/ionic-team/ionic-framework/issues/21194)
|
||||
* **datetime-button:** support multiple date selection ([#25971](https://github.com/ionic-team/ionic-framework/issues/25971)) ([a56a4a9](https://github.com/ionic-team/ionic-framework/commit/a56a4a9c0528fe77859963f5b801a3d645be0b23))
|
||||
* **datetime:** add header text to multiple selection; improve header consistency between modes ([#25817](https://github.com/ionic-team/ionic-framework/issues/25817)) ([8a1b3c5](https://github.com/ionic-team/ionic-framework/commit/8a1b3c5f300a1ec953d406b65601f84fa49aa807))
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
## [6.2.9](https://github.com/ionic-team/ionic-framework/compare/v6.2.8...v6.2.9) (2022-09-28)
|
||||
|
||||
|
||||
|
||||
@@ -3,6 +3,19 @@
|
||||
All notable changes to this project will be documented in this file.
|
||||
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
|
||||
|
||||
# [6.3.0 Manganese](https://github.com/ionic-team/ionic/compare/v6.2.9...v6.3.0) (2022-10-05)
|
||||
|
||||
|
||||
### Features
|
||||
|
||||
* **angular:** use standalone components with routing ([#25589](https://github.com/ionic-team/ionic/issues/25589)) ([3c84d48](https://github.com/ionic-team/ionic/commit/3c84d48cfa87810896364cb7ca16efcbdd7e8b07)), closes [#25404](https://github.com/ionic-team/ionic/issues/25404)
|
||||
* **button:** submit from outside of form ([#25913](https://github.com/ionic-team/ionic/issues/25913)) ([b139838](https://github.com/ionic-team/ionic/commit/b13983848c9ea7387062953412eaae744c001ec7)), closes [#21194](https://github.com/ionic-team/ionic/issues/21194)
|
||||
* **datetime:** add header text to multiple selection; improve header consistency between modes ([#25817](https://github.com/ionic-team/ionic/issues/25817)) ([8a1b3c5](https://github.com/ionic-team/ionic/commit/8a1b3c5f300a1ec953d406b65601f84fa49aa807))
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
## [6.2.9](https://github.com/ionic-team/ionic/compare/v6.2.8...v6.2.9) (2022-09-28)
|
||||
|
||||
**Note:** Version bump only for package @ionic/angular
|
||||
|
||||
18
angular/package-lock.json
generated
@@ -1,15 +1,15 @@
|
||||
{
|
||||
"name": "@ionic/angular",
|
||||
"version": "6.2.9",
|
||||
"version": "6.3.0",
|
||||
"lockfileVersion": 2,
|
||||
"requires": true,
|
||||
"packages": {
|
||||
"": {
|
||||
"name": "@ionic/angular",
|
||||
"version": "6.2.9",
|
||||
"version": "6.3.0",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@ionic/core": "^6.2.9",
|
||||
"@ionic/core": "^6.3.0",
|
||||
"jsonc-parser": "^3.0.0",
|
||||
"tslib": "^2.0.0"
|
||||
},
|
||||
@@ -1023,9 +1023,9 @@
|
||||
"dev": true
|
||||
},
|
||||
"node_modules/@ionic/core": {
|
||||
"version": "6.2.9",
|
||||
"resolved": "https://registry.npmjs.org/@ionic/core/-/core-6.2.9.tgz",
|
||||
"integrity": "sha512-d2KBXYUKBND2AD8aMgash3O/t04IDc/DHHMshcOydfNJ5qqAxwJYzZR7hs96UknCcIlhHk1pb5C29epkv7gOcQ==",
|
||||
"version": "6.3.0",
|
||||
"resolved": "https://registry.npmjs.org/@ionic/core/-/core-6.3.0.tgz",
|
||||
"integrity": "sha512-6MR0hOdIM6sQyZyXez3/jWAnHScrZKaQxzGT2XiXXIpBrKztNdeAhqDLXoxbDU1PLyDnXXPWBzT6xZ698gG67g==",
|
||||
"dependencies": {
|
||||
"@stencil/core": "^2.18.0",
|
||||
"ionicons": "^6.0.3",
|
||||
@@ -7951,9 +7951,9 @@
|
||||
"dev": true
|
||||
},
|
||||
"@ionic/core": {
|
||||
"version": "6.2.9",
|
||||
"resolved": "https://registry.npmjs.org/@ionic/core/-/core-6.2.9.tgz",
|
||||
"integrity": "sha512-d2KBXYUKBND2AD8aMgash3O/t04IDc/DHHMshcOydfNJ5qqAxwJYzZR7hs96UknCcIlhHk1pb5C29epkv7gOcQ==",
|
||||
"version": "6.3.0",
|
||||
"resolved": "https://registry.npmjs.org/@ionic/core/-/core-6.3.0.tgz",
|
||||
"integrity": "sha512-6MR0hOdIM6sQyZyXez3/jWAnHScrZKaQxzGT2XiXXIpBrKztNdeAhqDLXoxbDU1PLyDnXXPWBzT6xZ698gG67g==",
|
||||
"requires": {
|
||||
"@stencil/core": "^2.18.0",
|
||||
"ionicons": "^6.0.3",
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@ionic/angular",
|
||||
"version": "6.2.9",
|
||||
"version": "6.3.0",
|
||||
"description": "Angular specific wrappers for @ionic/core",
|
||||
"keywords": [
|
||||
"ionic",
|
||||
@@ -46,7 +46,7 @@
|
||||
"validate": "npm i && npm run lint && npm run test && npm run build"
|
||||
},
|
||||
"dependencies": {
|
||||
"@ionic/core": "^6.2.9",
|
||||
"@ionic/core": "^6.3.0",
|
||||
"jsonc-parser": "^3.0.0",
|
||||
"tslib": "^2.0.0"
|
||||
},
|
||||
|
||||
@@ -30,5 +30,5 @@ export abstract class EnvironmentInjector implements Injector {
|
||||
/**
|
||||
* @internal
|
||||
*/
|
||||
abstract onDestroy(callback: () => void): void;
|
||||
abstract onDestroy?(callback: () => void): void;
|
||||
}
|
||||
|
||||
@@ -14,6 +14,7 @@ import {
|
||||
Optional,
|
||||
Output,
|
||||
SkipSelf,
|
||||
Input,
|
||||
} from '@angular/core';
|
||||
import { OutletContext, Router, ActivatedRoute, ChildrenOutletContexts, PRIMARY_OUTLET } from '@angular/router';
|
||||
import { componentOnReady } from '@ionic/core';
|
||||
@@ -55,6 +56,16 @@ export class IonRouterOutlet implements OnDestroy, OnInit {
|
||||
|
||||
tabsPrefix: string | undefined;
|
||||
|
||||
/**
|
||||
* @experimental
|
||||
*
|
||||
* The `EnvironmentInjector` provider instance from the parent component.
|
||||
* Required for using standalone components with `ion-router-outlet`.
|
||||
*
|
||||
* Will be deprecated and removed when Angular 13 support is dropped.
|
||||
*/
|
||||
@Input() environmentInjector: EnvironmentInjector;
|
||||
|
||||
@Output() stackEvents = new EventEmitter<any>();
|
||||
// eslint-disable-next-line @angular-eslint/no-output-rename
|
||||
@Output('activate') activateEvents = new EventEmitter<any>();
|
||||
@@ -88,7 +99,6 @@ export class IonRouterOutlet implements OnDestroy, OnInit {
|
||||
@Optional() @Attribute('tabs') tabs: string,
|
||||
private config: Config,
|
||||
private navCtrl: NavController,
|
||||
@Optional() private environmentInjector: EnvironmentInjector,
|
||||
@Optional() private componentFactoryResolver: ComponentFactoryResolver,
|
||||
commonLocation: Location,
|
||||
elementRef: ElementRef,
|
||||
@@ -234,20 +244,24 @@ export class IonRouterOutlet implements OnDestroy, OnInit {
|
||||
} else {
|
||||
const snapshot = (activatedRoute as any)._futureSnapshot;
|
||||
|
||||
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
|
||||
const component = snapshot.routeConfig!.component as any;
|
||||
|
||||
/**
|
||||
* Angular 14 introduces a new `loadComponent` property to the route config,
|
||||
* that assigns the component to load to the `component` property of
|
||||
* the route snapshot. We can check for the presence of this property
|
||||
* to determine if the route is using standalone components.
|
||||
*
|
||||
* TODO: FW-1631: Remove this check when supporting standalone components
|
||||
* Angular 14 introduces a new `loadComponent` property to the route config.
|
||||
* This function will assign a `component` property to the route snapshot.
|
||||
* We check for the presence of this property to determine if the route is
|
||||
* using standalone components.
|
||||
*/
|
||||
if (component == null && snapshot.component) {
|
||||
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
|
||||
if (snapshot.routeConfig!.component == null && this.environmentInjector == null) {
|
||||
console.warn(
|
||||
'[Ionic Warning]: Standalone components are not currently supported with ion-router-outlet. You can track this feature request at https://github.com/ionic-team/ionic-framework/issues/25404'
|
||||
'[Ionic Warning]: You must supply an environmentInjector to use standalone components with routing:\n\n' +
|
||||
'In your component class, add:\n\n' +
|
||||
` import { EnvironmentInjector } from '@angular/core';\n` +
|
||||
' constructor(public environmentInjector: EnvironmentInjector) {}\n' +
|
||||
'\n' +
|
||||
'In your router outlet template, add:\n\n' +
|
||||
' <ion-router-outlet [environmentInjector]="environmentInjector"></ion-router-outlet>\n\n' +
|
||||
'Alternatively, if you are routing within ion-tabs:\n\n' +
|
||||
' <ion-tabs [environmentInjector]="environmentInjector"></ion-tabs>'
|
||||
);
|
||||
return;
|
||||
}
|
||||
@@ -267,6 +281,9 @@ export class IonRouterOutlet implements OnDestroy, OnInit {
|
||||
*/
|
||||
resolverOrInjector = resolverOrInjector || this.componentFactoryResolver;
|
||||
|
||||
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
|
||||
const component = snapshot.routeConfig!.component ?? snapshot.component;
|
||||
|
||||
if (resolverOrInjector && isComponentFactoryResolver(resolverOrInjector)) {
|
||||
// Backwards compatibility for Angular 13 and lower
|
||||
const factory = resolverOrInjector.resolveComponentFactory(component);
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
import { Component, ContentChild, EventEmitter, HostListener, Output, ViewChild } from '@angular/core';
|
||||
import { Component, ContentChild, EventEmitter, HostListener, Input, Output, ViewChild } from '@angular/core';
|
||||
|
||||
import { EnvironmentInjector } from '../../di/r3_injector';
|
||||
import { NavController } from '../../providers/nav-controller';
|
||||
import { IonTabBar } from '../proxies';
|
||||
|
||||
@@ -10,7 +11,12 @@ import { StackEvent } from './stack-utils';
|
||||
selector: 'ion-tabs',
|
||||
template: ` <ng-content select="[slot=top]"></ng-content>
|
||||
<div class="tabs-inner">
|
||||
<ion-router-outlet #outlet tabs="true" (stackEvents)="onPageSelected($event)"></ion-router-outlet>
|
||||
<ion-router-outlet
|
||||
#outlet
|
||||
tabs="true"
|
||||
[environmentInjector]="environmentInjector"
|
||||
(stackEvents)="onPageSelected($event)"
|
||||
></ion-router-outlet>
|
||||
</div>
|
||||
<ng-content></ng-content>`,
|
||||
styles: [
|
||||
@@ -46,6 +52,16 @@ export class IonTabs {
|
||||
@ViewChild('outlet', { read: IonRouterOutlet, static: false }) outlet: IonRouterOutlet;
|
||||
@ContentChild(IonTabBar, { static: false }) tabBar: IonTabBar | undefined;
|
||||
|
||||
/**
|
||||
* @experimental
|
||||
*
|
||||
* The `EnvironmentInjector` provider instance from the parent component.
|
||||
* Required for using standalone components with `ion-router-outlet`.
|
||||
*
|
||||
* Will be deprecated and removed when Angular 13 support is dropped.
|
||||
*/
|
||||
@Input() environmentInjector: EnvironmentInjector;
|
||||
|
||||
@Output() ionTabsWillChange = new EventEmitter<{ tab: string }>();
|
||||
@Output() ionTabsDidChange = new EventEmitter<{ tab: string }>();
|
||||
|
||||
|
||||
@@ -242,13 +242,13 @@ export declare interface IonButton extends Components.IonButton {
|
||||
|
||||
@ProxyCmp({
|
||||
defineCustomElementFn: undefined,
|
||||
inputs: ['buttonType', 'color', 'disabled', 'download', 'expand', 'fill', 'href', 'mode', 'rel', 'routerAnimation', 'routerDirection', 'shape', 'size', 'strong', 'target', 'type']
|
||||
inputs: ['buttonType', 'color', 'disabled', 'download', 'expand', 'fill', 'form', 'href', 'mode', 'rel', 'routerAnimation', 'routerDirection', 'shape', 'size', 'strong', 'target', 'type']
|
||||
})
|
||||
@Component({
|
||||
selector: 'ion-button',
|
||||
changeDetection: ChangeDetectionStrategy.OnPush,
|
||||
template: '<ng-content></ng-content>',
|
||||
inputs: ['buttonType', 'color', 'disabled', 'download', 'expand', 'fill', 'href', 'mode', 'rel', 'routerAnimation', 'routerDirection', 'shape', 'size', 'strong', 'target', 'type']
|
||||
inputs: ['buttonType', 'color', 'disabled', 'download', 'expand', 'fill', 'form', 'href', 'mode', 'rel', 'routerAnimation', 'routerDirection', 'shape', 'size', 'strong', 'target', 'type']
|
||||
})
|
||||
export class IonButton {
|
||||
protected el: HTMLElement;
|
||||
@@ -530,14 +530,14 @@ export declare interface IonDatetime extends Components.IonDatetime {
|
||||
|
||||
@ProxyCmp({
|
||||
defineCustomElementFn: undefined,
|
||||
inputs: ['cancelText', 'clearText', 'color', 'dayValues', 'disabled', 'doneText', 'firstDayOfWeek', 'hourCycle', 'hourValues', 'isDateEnabled', 'locale', 'max', 'min', 'minuteValues', 'mode', 'monthValues', 'multiple', 'name', 'preferWheel', 'presentation', 'readonly', 'showClearButton', 'showDefaultButtons', 'showDefaultTimeLabel', 'showDefaultTitle', 'size', 'value', 'yearValues'],
|
||||
inputs: ['cancelText', 'clearText', 'color', 'dayValues', 'disabled', 'doneText', 'firstDayOfWeek', 'hourCycle', 'hourValues', 'isDateEnabled', 'locale', 'max', 'min', 'minuteValues', 'mode', 'monthValues', 'multiple', 'name', 'preferWheel', 'presentation', 'readonly', 'showClearButton', 'showDefaultButtons', 'showDefaultTimeLabel', 'showDefaultTitle', 'size', 'titleSelectedDatesFormatter', 'value', 'yearValues'],
|
||||
methods: ['confirm', 'reset', 'cancel']
|
||||
})
|
||||
@Component({
|
||||
selector: 'ion-datetime',
|
||||
changeDetection: ChangeDetectionStrategy.OnPush,
|
||||
template: '<ng-content></ng-content>',
|
||||
inputs: ['cancelText', 'clearText', 'color', 'dayValues', 'disabled', 'doneText', 'firstDayOfWeek', 'hourCycle', 'hourValues', 'isDateEnabled', 'locale', 'max', 'min', 'minuteValues', 'mode', 'monthValues', 'multiple', 'name', 'preferWheel', 'presentation', 'readonly', 'showClearButton', 'showDefaultButtons', 'showDefaultTimeLabel', 'showDefaultTitle', 'size', 'value', 'yearValues']
|
||||
inputs: ['cancelText', 'clearText', 'color', 'dayValues', 'disabled', 'doneText', 'firstDayOfWeek', 'hourCycle', 'hourValues', 'isDateEnabled', 'locale', 'max', 'min', 'minuteValues', 'mode', 'monthValues', 'multiple', 'name', 'preferWheel', 'presentation', 'readonly', 'showClearButton', 'showDefaultButtons', 'showDefaultTimeLabel', 'showDefaultTitle', 'size', 'titleSelectedDatesFormatter', 'value', 'yearValues']
|
||||
})
|
||||
export class IonDatetime {
|
||||
protected el: HTMLElement;
|
||||
|
||||
@@ -0,0 +1,9 @@
|
||||
describe('Routing with Standalone Components', () => {
|
||||
beforeEach(() => {
|
||||
cy.visit('/version-test/standalone');
|
||||
});
|
||||
|
||||
it('should render the component', () => {
|
||||
cy.get('ion-content').contains('This is a standalone component rendered from a route.');
|
||||
});
|
||||
});
|
||||
3
angular/test/apps/ng14/src/app/app.component.html
Normal file
@@ -0,0 +1,3 @@
|
||||
<ion-app>
|
||||
<ion-router-outlet [environmentInjector]="environmentInjector"></ion-router-outlet>
|
||||
</ion-app>
|
||||
11
angular/test/apps/ng14/src/app/app.component.ts
Normal file
@@ -0,0 +1,11 @@
|
||||
import { Component, EnvironmentInjector } from '@angular/core';
|
||||
|
||||
@Component({
|
||||
selector: 'app-root',
|
||||
templateUrl: './app.component.html',
|
||||
styleUrls: ['./app.component.css']
|
||||
})
|
||||
export class AppComponent {
|
||||
|
||||
constructor(public environmentInjector: EnvironmentInjector) { }
|
||||
}
|
||||
@@ -0,0 +1,4 @@
|
||||
<ion-content>
|
||||
<p>This is a standalone component rendered from a route.</p>
|
||||
<ion-button routerLink="/">Return home</ion-button>
|
||||
</ion-content>
|
||||
@@ -0,0 +1,12 @@
|
||||
import { Component } from "@angular/core";
|
||||
import { RouterModule } from "@angular/router";
|
||||
|
||||
import { IonicModule } from '@ionic/angular';
|
||||
|
||||
@Component({
|
||||
selector: 'app-standalone',
|
||||
templateUrl: './standalone.component.html',
|
||||
standalone: true,
|
||||
imports: [IonicModule, RouterModule]
|
||||
})
|
||||
export class StandaloneComponent { }
|
||||
@@ -0,0 +1,15 @@
|
||||
import { NgModule } from "@angular/core";
|
||||
import { RouterModule } from "@angular/router";
|
||||
|
||||
@NgModule({
|
||||
imports: [
|
||||
RouterModule.forChild([
|
||||
{
|
||||
path: 'standalone',
|
||||
loadComponent: () => import('./standalone/standalone.component').then(m => m.StandaloneComponent)
|
||||
}
|
||||
])
|
||||
],
|
||||
exports: [RouterModule]
|
||||
})
|
||||
export class VersionTestRoutingModule { }
|
||||
@@ -1,7 +0,0 @@
|
||||
# Ionic Angular Test App
|
||||
|
||||
```
|
||||
npm install
|
||||
npm run sync:build
|
||||
npm start
|
||||
```
|
||||
@@ -1,6 +1,6 @@
|
||||
import { NgModule } from "@angular/core";
|
||||
import { RouterModule } from "@angular/router";
|
||||
import { VersionTestComponent } from ".";
|
||||
import { VersionTestComponent } from "./version-test.component";
|
||||
|
||||
@NgModule({
|
||||
imports: [
|
||||
|
||||
21
angular/test/base/tsconfig.json
Normal file
@@ -0,0 +1,21 @@
|
||||
{
|
||||
"compileOnSave": false,
|
||||
"compilerOptions": {
|
||||
"importHelpers": true,
|
||||
"outDir": "./dist/out-tsc",
|
||||
"sourceMap": true,
|
||||
"declaration": false,
|
||||
"moduleResolution": "node",
|
||||
"module": "es2020",
|
||||
"target": "es2020",
|
||||
"emitDecoratorMetadata": true,
|
||||
"experimentalDecorators": true,
|
||||
"typeRoots": ["node_modules/@types"],
|
||||
"lib": ["es2018", "dom"],
|
||||
"plugins": [
|
||||
{
|
||||
"name": "typescript-eslint-language-service"
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
@@ -31,3 +31,5 @@ cp -R $FULL_BASE_DIR $BUILD_APP_DIR
|
||||
# Then we can copy the specific app which
|
||||
# will override any files in the base application.
|
||||
cp -R $FULL_APP_DIR $BUILD_APP_DIR
|
||||
|
||||
echo "Copied test app files for ${APP_DIR}"
|
||||
|
||||
35
angular/test/sync-e2e.sh
Executable file
@@ -0,0 +1,35 @@
|
||||
#!/bin/bash
|
||||
|
||||
# The directory where the source
|
||||
# for each specific application is.
|
||||
APPS_DIR="apps"
|
||||
|
||||
# The directory where the
|
||||
# base application logic is
|
||||
BASE_DIR="base"
|
||||
BUILD_DIR="build"
|
||||
|
||||
# The specific application
|
||||
# we are building
|
||||
APP_DIR="${1}"
|
||||
|
||||
# The full path to the specific application.
|
||||
FULL_APP_DIR="${APPS_DIR}/${APP_DIR}/e2e"
|
||||
|
||||
# The full path to the base application.
|
||||
FULL_BASE_DIR="${BASE_DIR}/e2e"
|
||||
|
||||
# The full path to the built application.
|
||||
BUILD_APP_DIR="${BUILD_DIR}/${APP_DIR}/"
|
||||
|
||||
# Make the build directory if it does not already exist.
|
||||
mkdir -p $BUILD_DIR
|
||||
|
||||
# First we need to copy the base application
|
||||
cp -R $FULL_BASE_DIR $BUILD_APP_DIR
|
||||
|
||||
# Then we can copy the specific app which
|
||||
# will override any files in the base application.
|
||||
cp -R $FULL_APP_DIR $BUILD_APP_DIR
|
||||
|
||||
echo "Synced e2e tests for ${APP_DIR}"
|
||||
@@ -1,2 +1,5 @@
|
||||
src/components/slides/swiper/swiper.bundle.js
|
||||
src/components.d.ts
|
||||
**/test/**/*.spec.ts
|
||||
**/test/**/*.spec.tsx
|
||||
**/test/**/e2e.ts
|
||||
@@ -13,7 +13,8 @@ module.exports = {
|
||||
"parser": "@typescript-eslint/parser",
|
||||
"parserOptions": {
|
||||
"ecmaVersion": "latest",
|
||||
"sourceType": "module"
|
||||
"sourceType": "module",
|
||||
"project": "tsconfig.json"
|
||||
},
|
||||
"plugins": [
|
||||
"@typescript-eslint",
|
||||
@@ -31,6 +32,14 @@ module.exports = {
|
||||
"no-useless-catch": "off",
|
||||
"@typescript-eslint/no-non-null-assertion": "off",
|
||||
"no-case-declarations": "off",
|
||||
"@typescript-eslint/strict-boolean-expressions": [
|
||||
"error",
|
||||
{
|
||||
"allowNullableBoolean": true,
|
||||
"allowNullableString": true,
|
||||
"allowAny": true
|
||||
}
|
||||
],
|
||||
"custom-rules/no-component-on-ready-method": "error"
|
||||
}
|
||||
};
|
||||
|
||||
@@ -3,6 +3,26 @@
|
||||
All notable changes to this project will be documented in this file.
|
||||
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
|
||||
|
||||
# [6.3.0](https://github.com/ionic-team/ionic/compare/v6.2.9...v6.3.0) (2022-10-05)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* **list:** remove extra border in md inset list items ([#25972](https://github.com/ionic-team/ionic/issues/25972)) ([3eb3dd5](https://github.com/ionic-team/ionic/commit/3eb3dd5afa02f7257e2594f56efe570be83719b6)), closes [#25278](https://github.com/ionic-team/ionic/issues/25278)
|
||||
* **range:** indication when range knob is focused ([#25827](https://github.com/ionic-team/ionic/issues/25827)) ([2c815cf](https://github.com/ionic-team/ionic/commit/2c815cff139a0061883d3eef47816aea8801dcf4))
|
||||
|
||||
|
||||
### Features
|
||||
|
||||
* **alert:** accept Promise for button handler ([#25702](https://github.com/ionic-team/ionic/issues/25702)) ([8e4783c](https://github.com/ionic-team/ionic/commit/8e4783c17298e8f7654590108430e80f22ed6a7a)), closes [#25700](https://github.com/ionic-team/ionic/issues/25700)
|
||||
* **button:** submit from outside of form ([#25913](https://github.com/ionic-team/ionic/issues/25913)) ([b139838](https://github.com/ionic-team/ionic/commit/b13983848c9ea7387062953412eaae744c001ec7)), closes [#21194](https://github.com/ionic-team/ionic/issues/21194)
|
||||
* **datetime-button:** support multiple date selection ([#25971](https://github.com/ionic-team/ionic/issues/25971)) ([a56a4a9](https://github.com/ionic-team/ionic/commit/a56a4a9c0528fe77859963f5b801a3d645be0b23))
|
||||
* **datetime:** add header text to multiple selection; improve header consistency between modes ([#25817](https://github.com/ionic-team/ionic/issues/25817)) ([8a1b3c5](https://github.com/ionic-team/ionic/commit/8a1b3c5f300a1ec953d406b65601f84fa49aa807))
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
## [6.2.9](https://github.com/ionic-team/ionic/compare/v6.2.8...v6.2.9) (2022-09-28)
|
||||
|
||||
|
||||
|
||||
@@ -203,6 +203,7 @@ ion-button,prop,disabled,boolean,false,false,true
|
||||
ion-button,prop,download,string | undefined,undefined,false,false
|
||||
ion-button,prop,expand,"block" | "full" | undefined,undefined,false,true
|
||||
ion-button,prop,fill,"clear" | "default" | "outline" | "solid" | undefined,undefined,false,true
|
||||
ion-button,prop,form,HTMLFormElement | string | undefined,undefined,false,false
|
||||
ion-button,prop,href,string | undefined,undefined,false,false
|
||||
ion-button,prop,mode,"ios" | "md",undefined,false,false
|
||||
ion-button,prop,rel,string | undefined,undefined,false,false
|
||||
@@ -397,6 +398,7 @@ ion-datetime,prop,showDefaultButtons,boolean,false,false,false
|
||||
ion-datetime,prop,showDefaultTimeLabel,boolean,true,false,false
|
||||
ion-datetime,prop,showDefaultTitle,boolean,false,false,false
|
||||
ion-datetime,prop,size,"cover" | "fixed",'fixed',false,false
|
||||
ion-datetime,prop,titleSelectedDatesFormatter,((selectedDates: string[]) => string) | undefined,undefined,false,false
|
||||
ion-datetime,prop,value,null | string | string[] | undefined,undefined,false,false
|
||||
ion-datetime,prop,yearValues,number | number[] | string | undefined,undefined,false,false
|
||||
ion-datetime,method,cancel,cancel(closeOverlay?: boolean) => Promise<void>
|
||||
@@ -1306,7 +1308,7 @@ ion-textarea,method,setFocus,setFocus() => Promise<void>
|
||||
ion-textarea,event,ionBlur,FocusEvent,true
|
||||
ion-textarea,event,ionChange,TextareaChangeEventDetail,true
|
||||
ion-textarea,event,ionFocus,FocusEvent,true
|
||||
ion-textarea,event,ionInput,InputEvent | null,true
|
||||
ion-textarea,event,ionInput,InputEvent,true
|
||||
ion-textarea,css-prop,--background
|
||||
ion-textarea,css-prop,--border-radius
|
||||
ion-textarea,css-prop,--color
|
||||
|
||||
4
core/package-lock.json
generated
@@ -1,12 +1,12 @@
|
||||
{
|
||||
"name": "@ionic/core",
|
||||
"version": "6.2.9",
|
||||
"version": "6.3.0",
|
||||
"lockfileVersion": 2,
|
||||
"requires": true,
|
||||
"packages": {
|
||||
"": {
|
||||
"name": "@ionic/core",
|
||||
"version": "6.2.9",
|
||||
"version": "6.3.0",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@stencil/core": "^2.18.0",
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@ionic/core",
|
||||
"version": "6.2.9",
|
||||
"version": "6.3.0",
|
||||
"description": "Base components for Ionic",
|
||||
"keywords": [
|
||||
"ionic",
|
||||
|
||||
22
core/src/components.d.ts
vendored
@@ -5,7 +5,7 @@
|
||||
* It contains typing information for all components that exist in this project.
|
||||
*/
|
||||
import { HTMLStencilElement, JSXBase } from "@stencil/core/internal";
|
||||
import { AccordionGroupChangeEventDetail, ActionSheetAttributes, ActionSheetButton, AlertButton, AlertInput, AnimationBuilder, AutocompleteTypes, BreadcrumbCollapsedClickEventDetail, CheckboxChangeEventDetail, Color, ComponentProps, ComponentRef, DatetimeChangeEventDetail, DatetimePresentation, FrameworkDelegate, InputChangeEventDetail, InputInputEventDetail, ItemReorderEventDetail, LoadingAttributes, MenuChangeEventDetail, ModalAttributes, ModalBreakpointChangeEventDetail, ModalHandleBehavior, NavComponent, NavComponentWithProps, NavOptions, OverlayEventDetail, PickerAttributes, PickerButton, PickerColumn, PopoverAttributes, PopoverSize, PositionAlign, PositionReference, PositionSide, RadioGroupChangeEventDetail, RangeChangeEventDetail, RangeKnobMoveEndEventDetail, RangeKnobMoveStartEventDetail, RangeValue, RefresherEventDetail, RouteID, RouterDirection, RouterEventDetail, RouterOutletOptions, RouteWrite, ScrollBaseDetail, ScrollDetail, SearchbarChangeEventDetail, SegmentButtonLayout, SegmentChangeEventDetail, SelectChangeEventDetail, SelectInterface, SelectPopoverOption, Side, SpinnerTypes, StyleEventDetail, SwipeGestureHandler, TabBarChangedEventDetail, TabButtonClickEventDetail, TabButtonLayout, TextareaChangeEventDetail, TextFieldTypes, ToastButton, ToggleChangeEventDetail, TransitionDoneFn, TransitionInstruction, TriggerAction, ViewController } from "./interface";
|
||||
import { AccordionGroupChangeEventDetail, ActionSheetAttributes, ActionSheetButton, AlertButton, AlertInput, AnimationBuilder, AutocompleteTypes, BreadcrumbCollapsedClickEventDetail, CheckboxChangeEventDetail, Color, ComponentProps, ComponentRef, DatetimeChangeEventDetail, DatetimePresentation, FrameworkDelegate, InputChangeEventDetail, InputInputEventDetail, ItemReorderEventDetail, LoadingAttributes, MenuChangeEventDetail, ModalAttributes, ModalBreakpointChangeEventDetail, ModalHandleBehavior, NavComponent, NavComponentWithProps, NavOptions, OverlayEventDetail, PickerAttributes, PickerButton, PickerColumn, PopoverAttributes, PopoverSize, PositionAlign, PositionReference, PositionSide, RadioGroupChangeEventDetail, RangeChangeEventDetail, RangeKnobMoveEndEventDetail, RangeKnobMoveStartEventDetail, RangeValue, RefresherEventDetail, RouteID, RouterDirection, RouterEventDetail, RouterOutletOptions, RouteWrite, ScrollBaseDetail, ScrollDetail, SearchbarChangeEventDetail, SegmentButtonLayout, SegmentChangeEventDetail, SelectChangeEventDetail, SelectInterface, SelectPopoverOption, Side, SpinnerTypes, StyleEventDetail, SwipeGestureHandler, TabBarChangedEventDetail, TabButtonClickEventDetail, TabButtonLayout, TextareaChangeEventDetail, TextFieldTypes, TitleSelectedDatesFormatter, ToastButton, ToggleChangeEventDetail, TransitionDoneFn, TransitionInstruction, TriggerAction, ViewController } from "./interface";
|
||||
import { IonicSafeString } from "./utils/sanitization";
|
||||
import { AlertAttributes } from "./components/alert/alert-interface";
|
||||
import { CounterFormatter } from "./components/item/item-interface";
|
||||
@@ -382,6 +382,10 @@ export namespace Components {
|
||||
* Set to `"clear"` for a transparent button that resembles a flat button, to `"outline"` for a transparent button with a border, or to `"solid"` for a button with a filled background. The default fill is `"solid"` except inside of a toolbar, where the default is `"clear"`.
|
||||
*/
|
||||
"fill"?: 'clear' | 'outline' | 'solid' | 'default';
|
||||
/**
|
||||
* The HTML form element or form element id. Used to submit a form when the button is not a child of the form.
|
||||
*/
|
||||
"form"?: string | HTMLFormElement;
|
||||
/**
|
||||
* Contains a URL or a URL fragment that the hyperlink points to. If this property is set, an anchor tag will be rendered.
|
||||
*/
|
||||
@@ -829,13 +833,17 @@ export namespace Components {
|
||||
*/
|
||||
"showDefaultTimeLabel": boolean;
|
||||
/**
|
||||
* If `true`, a header will be shown above the calendar picker. On `ios` mode this will include the slotted title, and on `md` mode this will include the slotted title and the selected date.
|
||||
* If `true`, a header will be shown above the calendar picker. This will include both the slotted title, and the selected date.
|
||||
*/
|
||||
"showDefaultTitle": boolean;
|
||||
/**
|
||||
* If `cover`, the `ion-datetime` will expand to cover the full width of its container. If `fixed`, the `ion-datetime` will have a fixed width.
|
||||
*/
|
||||
"size": 'cover' | 'fixed';
|
||||
/**
|
||||
* A callback used to format the header text that shows how many dates are selected. Only used if there are 0 or more than 1 selected (i.e. unused for exactly 1). By default, the header text is set to "numberOfDates days".
|
||||
*/
|
||||
"titleSelectedDatesFormatter"?: TitleSelectedDatesFormatter;
|
||||
/**
|
||||
* The value of the datetime as a valid ISO 8601 datetime string. Should be an array of strings if `multiple="true"`.
|
||||
*/
|
||||
@@ -4138,6 +4146,10 @@ declare namespace LocalJSX {
|
||||
* Set to `"clear"` for a transparent button that resembles a flat button, to `"outline"` for a transparent button with a border, or to `"solid"` for a button with a filled background. The default fill is `"solid"` except inside of a toolbar, where the default is `"clear"`.
|
||||
*/
|
||||
"fill"?: 'clear' | 'outline' | 'solid' | 'default';
|
||||
/**
|
||||
* The HTML form element or form element id. Used to submit a form when the button is not a child of the form.
|
||||
*/
|
||||
"form"?: string | HTMLFormElement;
|
||||
/**
|
||||
* Contains a URL or a URL fragment that the hyperlink points to. If this property is set, an anchor tag will be rendered.
|
||||
*/
|
||||
@@ -4601,13 +4613,17 @@ declare namespace LocalJSX {
|
||||
*/
|
||||
"showDefaultTimeLabel"?: boolean;
|
||||
/**
|
||||
* If `true`, a header will be shown above the calendar picker. On `ios` mode this will include the slotted title, and on `md` mode this will include the slotted title and the selected date.
|
||||
* If `true`, a header will be shown above the calendar picker. This will include both the slotted title, and the selected date.
|
||||
*/
|
||||
"showDefaultTitle"?: boolean;
|
||||
/**
|
||||
* If `cover`, the `ion-datetime` will expand to cover the full width of its container. If `fixed`, the `ion-datetime` will have a fixed width.
|
||||
*/
|
||||
"size"?: 'cover' | 'fixed';
|
||||
/**
|
||||
* A callback used to format the header text that shows how many dates are selected. Only used if there are 0 or more than 1 selected (i.e. unused for exactly 1). By default, the header text is set to "numberOfDates days".
|
||||
*/
|
||||
"titleSelectedDatesFormatter"?: TitleSelectedDatesFormatter;
|
||||
/**
|
||||
* The value of the datetime as a valid ISO 8601 datetime string. Should be an array of strings if `multiple="true"`.
|
||||
*/
|
||||
|
||||
@@ -216,7 +216,7 @@ export class AccordionGroup implements ComponentInterface {
|
||||
* to the array.
|
||||
*/
|
||||
if (multiple) {
|
||||
const groupValue = value || [];
|
||||
const groupValue = value ?? [];
|
||||
const processedValue = Array.isArray(groupValue) ? groupValue : [groupValue];
|
||||
const valueExists = processedValue.find((v) => v === accordionValue);
|
||||
if (valueExists === undefined && accordionValue !== undefined) {
|
||||
@@ -231,7 +231,7 @@ export class AccordionGroup implements ComponentInterface {
|
||||
* out of the values array or unset the value.
|
||||
*/
|
||||
if (multiple) {
|
||||
const groupValue = value || [];
|
||||
const groupValue = value ?? [];
|
||||
const processedValue = Array.isArray(groupValue) ? groupValue : [groupValue];
|
||||
this.setValue(processedValue.filter((v) => v !== accordionValue));
|
||||
} else {
|
||||
|
||||
@@ -157,11 +157,9 @@ export class Accordion implements ComponentInterface {
|
||||
}
|
||||
|
||||
// This is not defined in unit tests
|
||||
const ionItem =
|
||||
slot.assignedElements &&
|
||||
(slot.assignedElements().find((el) => el.tagName === 'ION-ITEM') as HTMLIonItemElement | undefined);
|
||||
if (slot.assignedElements === undefined) return;
|
||||
|
||||
return ionItem;
|
||||
return slot.assignedElements().find((el) => el.tagName === 'ION-ITEM') as HTMLIonItemElement | undefined;
|
||||
};
|
||||
|
||||
private setAria = (expanded = false) => {
|
||||
|
||||
@@ -53,10 +53,12 @@ export type AlertTextareaAttributes = { [key: string]: any };
|
||||
*/
|
||||
export type AlertInputAttributes = { [key: string]: any };
|
||||
|
||||
type AlertButtonOverlayHandler = boolean | void | { [key: string]: any };
|
||||
|
||||
export interface AlertButton {
|
||||
text: string;
|
||||
role?: 'cancel' | 'destructive' | string;
|
||||
cssClass?: string | string[];
|
||||
id?: string;
|
||||
handler?: (value: any) => boolean | void | { [key: string]: any };
|
||||
handler?: (value: any) => AlertButtonOverlayHandler | Promise<AlertButtonOverlayHandler>;
|
||||
}
|
||||
|
||||
@@ -241,7 +241,7 @@ export class Alert implements ComponentInterface, OverlayInterface {
|
||||
handler: i.handler,
|
||||
min: i.min,
|
||||
max: i.max,
|
||||
cssClass: i.cssClass || '',
|
||||
cssClass: i.cssClass ?? '',
|
||||
attributes: i.attributes || {},
|
||||
tabindex: i.type === 'radio' && i !== focusable ? -1 : 0,
|
||||
} as AlertInput)
|
||||
@@ -335,24 +335,24 @@ export class Alert implements ComponentInterface, OverlayInterface {
|
||||
forceUpdate(this);
|
||||
}
|
||||
|
||||
private buttonClick(button: AlertButton) {
|
||||
private async buttonClick(button: AlertButton) {
|
||||
const role = button.role;
|
||||
const values = this.getValues();
|
||||
if (isCancel(role)) {
|
||||
return this.dismiss({ values }, role);
|
||||
}
|
||||
const returnData = this.callButtonHandler(button, values);
|
||||
const returnData = await this.callButtonHandler(button, values);
|
||||
if (returnData !== false) {
|
||||
return this.dismiss({ values, ...returnData }, button.role);
|
||||
}
|
||||
return Promise.resolve(false);
|
||||
return false;
|
||||
}
|
||||
|
||||
private callButtonHandler(button: AlertButton | undefined, data?: any) {
|
||||
private async callButtonHandler(button: AlertButton | undefined, data?: any) {
|
||||
if (button?.handler) {
|
||||
// a handler has been provided, execute it
|
||||
// pass the handler the values from the inputs
|
||||
const returnData = safeCall(button.handler, data);
|
||||
const returnData = await safeCall(button.handler, data);
|
||||
if (returnData === false) {
|
||||
// if the return value of the handler is false then do not dismiss
|
||||
return false;
|
||||
@@ -596,7 +596,7 @@ export class Alert implements ComponentInterface, OverlayInterface {
|
||||
role={role}
|
||||
aria-modal="true"
|
||||
aria-labelledby={ariaLabelledBy}
|
||||
aria-describedby={message ? msgId : null}
|
||||
aria-describedby={message !== undefined ? msgId : null}
|
||||
tabindex="-1"
|
||||
{...(htmlAttributes as any)}
|
||||
style={{
|
||||
|
||||
@@ -54,6 +54,29 @@ test.describe('alert: basic', () => {
|
||||
expect(alert).toHaveAttribute('data-testid', 'basic-alert');
|
||||
});
|
||||
|
||||
test('should dismiss when async handler resolves', async ({ page, skip }) => {
|
||||
skip.rtl();
|
||||
await page.goto(`/src/components/alert/test/basic`);
|
||||
|
||||
const ionAlertDidPresent = await page.spyOnEvent('ionAlertDidPresent');
|
||||
const ionAlertDidDismiss = await page.spyOnEvent('ionAlertDidDismiss');
|
||||
const ionLoadingDidDismiss = await page.spyOnEvent('ionLoadingDidDismiss');
|
||||
|
||||
const alert = page.locator('ion-alert');
|
||||
|
||||
await page.click('#asyncHandler');
|
||||
await ionAlertDidPresent.next();
|
||||
|
||||
await page.click('.alert-button');
|
||||
|
||||
await expect(alert).toBeVisible();
|
||||
|
||||
await ionLoadingDidDismiss.next();
|
||||
await ionAlertDidDismiss.next();
|
||||
|
||||
await expect(alert).toBeHidden();
|
||||
});
|
||||
|
||||
test.describe('should not have visual regressions', () => {
|
||||
test('header, subheader, message', async ({ page }) => {
|
||||
await testAlert(page, 'basic');
|
||||
|
||||
|
Before Width: | Height: | Size: 72 KiB After Width: | Height: | Size: 80 KiB |
|
Before Width: | Height: | Size: 30 KiB After Width: | Height: | Size: 33 KiB |
|
Before Width: | Height: | Size: 72 KiB After Width: | Height: | Size: 76 KiB |
|
Before Width: | Height: | Size: 72 KiB After Width: | Height: | Size: 80 KiB |
|
Before Width: | Height: | Size: 30 KiB After Width: | Height: | Size: 33 KiB |
|
Before Width: | Height: | Size: 72 KiB After Width: | Height: | Size: 76 KiB |
|
Before Width: | Height: | Size: 89 KiB After Width: | Height: | Size: 96 KiB |
|
Before Width: | Height: | Size: 39 KiB After Width: | Height: | Size: 42 KiB |
|
Before Width: | Height: | Size: 81 KiB After Width: | Height: | Size: 87 KiB |
|
Before Width: | Height: | Size: 89 KiB After Width: | Height: | Size: 96 KiB |
|
Before Width: | Height: | Size: 39 KiB After Width: | Height: | Size: 42 KiB |
|
Before Width: | Height: | Size: 81 KiB After Width: | Height: | Size: 87 KiB |
|
Before Width: | Height: | Size: 104 KiB After Width: | Height: | Size: 107 KiB |
|
Before Width: | Height: | Size: 36 KiB After Width: | Height: | Size: 37 KiB |
|
Before Width: | Height: | Size: 92 KiB After Width: | Height: | Size: 96 KiB |
|
Before Width: | Height: | Size: 104 KiB After Width: | Height: | Size: 107 KiB |
|
Before Width: | Height: | Size: 36 KiB After Width: | Height: | Size: 37 KiB |
|
Before Width: | Height: | Size: 92 KiB After Width: | Height: | Size: 96 KiB |
|
Before Width: | Height: | Size: 78 KiB After Width: | Height: | Size: 85 KiB |
|
Before Width: | Height: | Size: 32 KiB After Width: | Height: | Size: 35 KiB |
|
Before Width: | Height: | Size: 76 KiB After Width: | Height: | Size: 80 KiB |
|
Before Width: | Height: | Size: 78 KiB After Width: | Height: | Size: 85 KiB |
|
Before Width: | Height: | Size: 32 KiB After Width: | Height: | Size: 35 KiB |
|
Before Width: | Height: | Size: 76 KiB After Width: | Height: | Size: 80 KiB |
|
Before Width: | Height: | Size: 90 KiB After Width: | Height: | Size: 98 KiB |
|
Before Width: | Height: | Size: 39 KiB After Width: | Height: | Size: 43 KiB |
|
Before Width: | Height: | Size: 91 KiB After Width: | Height: | Size: 100 KiB |
|
Before Width: | Height: | Size: 90 KiB After Width: | Height: | Size: 98 KiB |
|
Before Width: | Height: | Size: 39 KiB After Width: | Height: | Size: 43 KiB |
|
Before Width: | Height: | Size: 91 KiB After Width: | Height: | Size: 100 KiB |
|
Before Width: | Height: | Size: 269 KiB After Width: | Height: | Size: 272 KiB |
|
Before Width: | Height: | Size: 51 KiB After Width: | Height: | Size: 52 KiB |
|
Before Width: | Height: | Size: 154 KiB After Width: | Height: | Size: 158 KiB |
|
Before Width: | Height: | Size: 269 KiB After Width: | Height: | Size: 272 KiB |
|
Before Width: | Height: | Size: 51 KiB After Width: | Height: | Size: 52 KiB |
|
Before Width: | Height: | Size: 154 KiB After Width: | Height: | Size: 158 KiB |
|
Before Width: | Height: | Size: 79 KiB After Width: | Height: | Size: 83 KiB |
|
Before Width: | Height: | Size: 32 KiB After Width: | Height: | Size: 34 KiB |
|
Before Width: | Height: | Size: 71 KiB After Width: | Height: | Size: 78 KiB |
|
Before Width: | Height: | Size: 79 KiB After Width: | Height: | Size: 83 KiB |
|
Before Width: | Height: | Size: 32 KiB After Width: | Height: | Size: 34 KiB |
|
Before Width: | Height: | Size: 71 KiB After Width: | Height: | Size: 78 KiB |
|
Before Width: | Height: | Size: 75 KiB After Width: | Height: | Size: 78 KiB |
|
Before Width: | Height: | Size: 75 KiB After Width: | Height: | Size: 78 KiB |
|
Before Width: | Height: | Size: 67 KiB After Width: | Height: | Size: 73 KiB |
|
Before Width: | Height: | Size: 29 KiB After Width: | Height: | Size: 31 KiB |
|
Before Width: | Height: | Size: 66 KiB After Width: | Height: | Size: 70 KiB |
|
Before Width: | Height: | Size: 67 KiB After Width: | Height: | Size: 73 KiB |
|
Before Width: | Height: | Size: 29 KiB After Width: | Height: | Size: 31 KiB |
|
Before Width: | Height: | Size: 66 KiB After Width: | Height: | Size: 71 KiB |
|
Before Width: | Height: | Size: 81 KiB After Width: | Height: | Size: 88 KiB |
|
Before Width: | Height: | Size: 36 KiB After Width: | Height: | Size: 40 KiB |
|
Before Width: | Height: | Size: 82 KiB After Width: | Height: | Size: 88 KiB |
|
Before Width: | Height: | Size: 81 KiB After Width: | Height: | Size: 88 KiB |
|
Before Width: | Height: | Size: 36 KiB After Width: | Height: | Size: 40 KiB |
|
Before Width: | Height: | Size: 82 KiB After Width: | Height: | Size: 88 KiB |
|
Before Width: | Height: | Size: 80 KiB After Width: | Height: | Size: 83 KiB |
|
Before Width: | Height: | Size: 30 KiB After Width: | Height: | Size: 31 KiB |
|
Before Width: | Height: | Size: 67 KiB After Width: | Height: | Size: 70 KiB |
|
Before Width: | Height: | Size: 80 KiB After Width: | Height: | Size: 83 KiB |
|
Before Width: | Height: | Size: 30 KiB After Width: | Height: | Size: 31 KiB |
|
Before Width: | Height: | Size: 67 KiB After Width: | Height: | Size: 70 KiB |
@@ -14,8 +14,9 @@
|
||||
<script type="module" src="../../../../../dist/ionic/ionic.esm.js"></script>
|
||||
</head>
|
||||
<script type="module">
|
||||
import { alertController } from '../../../../dist/ionic/index.esm.js';
|
||||
import { alertController, loadingController } from '../../../../dist/ionic/index.esm.js';
|
||||
window.alertController = alertController;
|
||||
window.loadingController = loadingController;
|
||||
</script>
|
||||
|
||||
<body>
|
||||
@@ -30,9 +31,12 @@
|
||||
<ion-button id="basic" expand="block" onclick="presentAlert()">Alert</ion-button>
|
||||
<ion-button id="longMessage" expand="block" onclick="presentAlertLongMessage()">Alert Long Message</ion-button>
|
||||
<ion-button id="multipleButtons" expand="block" onclick="presentAlertMultipleButtons()"
|
||||
>Multiple Buttons (>2)</ion-button
|
||||
>
|
||||
>Multiple Buttons (>2)
|
||||
</ion-button>
|
||||
<ion-button id="noMessage" expand="block" onclick="presentAlertNoMessage()">Alert No Message</ion-button>
|
||||
<ion-button id="asyncHandler" expand="block" onclick="presentAlertAsyncHandler()"
|
||||
>Alert Async Handler</ion-button
|
||||
>
|
||||
<ion-button id="confirm" expand="block" onclick="presentAlertConfirm()">Confirm</ion-button>
|
||||
<ion-button id="prompt" expand="block" onclick="presentAlertPrompt()">Prompt</ion-button>
|
||||
<ion-button id="radio" expand="block" onclick="presentAlertRadio()">Radio</ion-button>
|
||||
@@ -46,6 +50,7 @@
|
||||
--min-width: 0;
|
||||
--max-width: 200px;
|
||||
}
|
||||
|
||||
#delete-button {
|
||||
color: #eb445a;
|
||||
}
|
||||
@@ -346,6 +351,30 @@
|
||||
],
|
||||
});
|
||||
}
|
||||
|
||||
function presentAlertAsyncHandler() {
|
||||
openAlert({
|
||||
header: 'Alert',
|
||||
message: 'This is an alert with async handlers',
|
||||
buttons: [
|
||||
{
|
||||
text: 'Confirm',
|
||||
handler: () => {
|
||||
return new Promise(async (resolve) => {
|
||||
const loading = await loadingController.create({
|
||||
message: 'Please wait...',
|
||||
});
|
||||
await loading.present();
|
||||
setTimeout(async () => {
|
||||
await loading.dismiss();
|
||||
resolve();
|
||||
}, 1000);
|
||||
});
|
||||
},
|
||||
},
|
||||
],
|
||||
});
|
||||
}
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
|
||||