merge release-4.7.2

Release 4.7.2
This commit is contained in:
Liam DeBeasi
2019-08-07 12:23:03 -04:00
committed by GitHub
188 changed files with 2153 additions and 13722 deletions

View File

@@ -91,6 +91,23 @@ jobs:
paths:
- "*"
build-angular-server:
<<: *defaults
steps:
- checkout
- attach_workspace:
at: /tmp/workspace
- run:
command: npm install
working_directory: /tmp/workspace/packages/angular-server
- run:
command: npm run build.prod
working_directory: /tmp/workspace/packages/angular-server
- persist_to_workspace:
root: /tmp/workspace
paths:
- "*"
test-core-clean-build:
<<: *defaults
steps:
@@ -208,7 +225,11 @@ workflows:
- build-angular:
requires: [build-core]
- build-angular-server:
requires: [build-angular]
- test-angular-lint:
requires: [build-angular]
- test-angular-e2e:
requires: [build-angular]
requires:
- build-angular
- build-angular-server

View File

@@ -37,6 +37,7 @@ assignees: ''
A sample application via GitHub
StackBlitz (https://stackblitz.com)
Ionic Angular StackBlitz: https://stackblitz.com/edit/ionic-v4-angular-tabs
Plunker (http://plnkr.co/edit/cpeRJs?p=preview)

View File

@@ -1,3 +1,18 @@
## [4.7.2](https://github.com/ionic-team/ionic/compare/v4.7.1...v4.7.2) (2019-08-07)
### Bug Fixes
* **angular:** hardware back button subscribeWithPriority triggers change detection ([#18962](https://github.com/ionic-team/ionic/issues/18962)) ([3a22105](https://github.com/ionic-team/ionic/commit/3a22105)), closes [#18959](https://github.com/ionic-team/ionic/issues/18959)
* **angular:** nested inputs no longer conflict with each other ([#18976](https://github.com/ionic-team/ionic/issues/18976)) ([6bbdb80](https://github.com/ionic-team/ionic/commit/6bbdb80)), closes [#18248](https://github.com/ionic-team/ionic/issues/18248)
* **range:** ion-range value now submitted with form ([#19008](https://github.com/ionic-team/ionic/issues/19008)) ([8f7853c](https://github.com/ionic-team/ionic/commit/8f7853c))
* **reorder:** only move item if reorder happens ([#19007](https://github.com/ionic-team/ionic/issues/19007)) ([d237e80](https://github.com/ionic-team/ionic/commit/d237e80))
* **router:** partial swipe to go back gesture no longer breaks view([#18977](https://github.com/ionic-team/ionic/issues/18977)) ([713ea8a](https://github.com/ionic-team/ionic/commit/713ea8a)), closes [#18462](https://github.com/ionic-team/ionic/issues/18462)
* **toast:** allow loading ion-icon from asset path ([#18969](https://github.com/ionic-team/ionic/issues/18969)) ([23f327e](https://github.com/ionic-team/ionic/commit/23f327e))
* **vue:** rename swipeEnable to swipeGesture ([#17346](https://github.com/ionic-team/ionic/issues/17346)) ([c2348f7](https://github.com/ionic-team/ionic/commit/c2348f7)), closes [#16002](https://github.com/ionic-team/ionic/issues/16002)
## [4.7.1](https://github.com/ionic-team/ionic/compare/v4.7.0...v4.7.1) (2019-07-26)
@@ -10,6 +25,31 @@
# [4.7.0 Nitrogen](https://github.com/ionic-team/ionic/compare/v4.6.2...v4.7.0) (2019-07-24)
### Angular 8 Support
With this version comes support for Angular 8! Follow the below steps to update.
1. Update `@ionic/angular` and `@ionic/angular-toolkit` to the latest releases:
```shell
$ npm install @ionic/angular@4.7.0
$ npm install @ionic/angular-toolkit@2.0.0 -D
```
1. Update `@angular/core` and `@angular/cli`:
```shell
$ npx ng update @angular/core @angular/cli
```
1. Update `@angular-devkit` dependencies:
```shell
$ npm i @angular-devkit/architect@latest @angular-devkit/build-angular@latest @angular-devkit/core@latest @angular-devkit/schematics@latest
```
View our [Angular 8 Update Guide](https://docs.google.com/document/d/1QOpQeDifPSg6F9WycDLcbQnpqjN96ew-Ap0_CB7CcCQ/edit?usp=sharing) for tips on potential issues!
### Bug Fixes
* **angular:** copy input form classes to parent ion-item ([#18820](https://github.com/ionic-team/ionic/issues/18820)) ([53179c4](https://github.com/ionic-team/ionic/commit/53179c4)), closes [#18800](https://github.com/ionic-team/ionic/issues/18800)
@@ -19,7 +59,7 @@
* **datetime:** allow AM/PM to be changed ([#18684](https://github.com/ionic-team/ionic/issues/18684)) ([b7761fe](https://github.com/ionic-team/ionic/commit/b7761fe)), closes [#18585](https://github.com/ionic-team/ionic/issues/18585)
* **datetime:** properly apply disabled classes when updating columns ([#18875](https://github.com/ionic-team/ionic/issues/18875)) ([7ba718c](https://github.com/ionic-team/ionic/commit/7ba718c)), closes [#18793](https://github.com/ionic-team/ionic/issues/18793)
* **hardware-back-button:** hardware back button no longer erroneously restarts app ([#18794](https://github.com/ionic-team/ionic/issues/18794)) ([978cc39](https://github.com/ionic-team/ionic/commit/978cc39)), closes [#18792](https://github.com/ionic-team/ionic/issues/18792)
* **ripple-effct:** ensure ripple is removed from components after pointer release ([#18854](https://github.com/ionic-team/ionic/issues/18854)) ([71137a2](https://github.com/ionic-team/ionic/commit/71137a2)), closes [#18836](https://github.com/ionic-team/ionic/issues/18836)
* **ripple-effect:** ensure ripple is removed from components after pointer release ([#18854](https://github.com/ionic-team/ionic/issues/18854)) ([71137a2](https://github.com/ionic-team/ionic/commit/71137a2)), closes [#18836](https://github.com/ionic-team/ionic/issues/18836)
* **searchbar:** add aria and role for improved accessibility ([#18797](https://github.com/ionic-team/ionic/issues/18797)) ([798103b](https://github.com/ionic-team/ionic/commit/798103b)), closes [#18796](https://github.com/ionic-team/ionic/issues/18796)
* **ssr:** avoid window reference ([#18865](https://github.com/ionic-team/ionic/issues/18865)) ([23ce6fa](https://github.com/ionic-team/ionic/commit/23ce6fa))
* **ssr:** check for client runtime method ([#18866](https://github.com/ionic-team/ionic/issues/18866)) ([c52b3b4](https://github.com/ionic-team/ionic/commit/c52b3b4))
@@ -42,7 +82,6 @@
* **angular:** attach entering view before first change detection and detach leaving page ([#18821](https://github.com/ionic-team/ionic/issues/18821)) ([97fec92](https://github.com/ionic-team/ionic/commit/97fec92))
## [4.6.2](https://github.com/ionic-team/ionic/compare/v4.6.1...v4.6.2) (2019-07-10)

View File

@@ -1,6 +1,6 @@
{
"name": "@ionic/angular",
"version": "4.7.1",
"version": "4.7.2",
"description": "Angular specific wrappers for @ionic/core",
"keywords": [
"ionic",
@@ -19,6 +19,10 @@
"type": "git",
"url": "https://github.com/ionic-team/ionic.git"
},
"bugs": {
"url": "https://github.com/ionic-team/ionic/issues"
},
"homepage": "https://ionicframework.com/",
"scripts": {
"build": "npm run clean && npm run build.core && npm run build.ng && npm run clean-generated",
"build.core": "node scripts/build-core.js",
@@ -38,14 +42,14 @@
"validate": "npm i && npm run lint && npm run test && npm run build"
},
"module": "dist/fesm5.js",
"main": "dist/fesm5.js",
"main": "dist/fesm5.cjs.js",
"types": "dist/core.d.ts",
"files": [
"dist/",
"css/"
],
"dependencies": {
"@ionic/core": "4.7.1",
"@ionic/core": "4.7.2",
"tslib": "^1.9.3"
},
"peerDependencies": {
@@ -82,8 +86,8 @@
"tsickle": "^0.34.0",
"tslint": "^5.12.1",
"tslint-ionic-rules": "0.0.21",
"typescript": "3.2.4",
"zone.js": "^0.8.28"
"typescript": "~3.2.2",
"zone.js": "~0.8.26"
},
"schematics": "./dist/schematics/collection.json"
}

View File

@@ -1,12 +1,12 @@
const fs = require('fs-extra');
const path = require('path');
const ROOT_DIR = path.join(__dirname, '..');
const cleanDirs = [
'dist'
path.join(ROOT_DIR, 'dist')
];
cleanDirs.forEach(dir => {
const cleanDir = path.join(__dirname, '../', dir);
fs.removeSync(cleanDir);
fs.emptyDirSync(dir);
});

View File

@@ -2,10 +2,12 @@ import resolve from 'rollup-plugin-node-resolve';
export default {
input: 'build/es2015/core.js',
output: {
file: 'dist/fesm2015.js',
format: 'es'
},
output: [
{
file: 'dist/fesm2015.js',
format: 'es'
}
],
external: (id) => {
// anything else is external
// Windows: C:\xxxxxx\xxx

View File

@@ -4,6 +4,15 @@ const newConfig = {
...config,
input: 'build/es5/core.js',
};
newConfig.output.file = 'dist/fesm5.js';
newConfig.output = [
{
file: 'dist/fesm5.js',
format: 'es'
},
{
file: 'dist/fesm5.cjs.js',
format: 'cjs'
}
];
export { newConfig as default };

View File

@@ -5,7 +5,7 @@ import { Config } from './providers/config';
import { IonicWindow } from './types/interfaces';
import { raf } from './util/util';
export function appInitialize(config: Config, doc: Document, zone: NgZone) {
export const appInitialize = (config: Config, doc: Document, zone: NgZone) => {
return (): any => {
const win: IonicWindow | undefined = doc.defaultView as any;
if (win) {
@@ -36,4 +36,4 @@ export function appInitialize(config: Config, doc: Document, zone: NgZone) {
});
}
};
}
};

View File

@@ -25,8 +25,8 @@ export class BooleanValueAccessor extends ValueAccessor {
setIonicClasses(this.el);
}
@HostListener('ionChange', ['$event.target.checked'])
_handleIonChange(value: any) {
this.handleChangeEvent(value);
@HostListener('ionChange', ['$event.target'])
_handleIonChange(el: any) {
this.handleChangeEvent(el, el.checked);
}
}

View File

@@ -20,9 +20,9 @@ export class NumericValueAccessor extends ValueAccessor {
super(el);
}
@HostListener('ionChange', ['$event.target.value'])
_handleIonChange(value: any) {
this.handleChangeEvent(value);
@HostListener('ionChange', ['$event.target'])
_handleIonChange(el: any) {
this.handleChangeEvent(el, el.value);
}
registerOnChange(fn: (_: number | null) => void) {

View File

@@ -20,8 +20,8 @@ export class RadioValueAccessor extends ValueAccessor {
super(el);
}
@HostListener('ionSelect', ['$event.target.checked'])
_handleIonSelect(value: any) {
this.handleChangeEvent(value);
@HostListener('ionSelect', ['$event.target'])
_handleIonSelect(el: any) {
this.handleChangeEvent(el, el.checked);
}
}

View File

@@ -20,8 +20,8 @@ export class SelectValueAccessor extends ValueAccessor {
super(el);
}
@HostListener('ionChange', ['$event.target.value'])
_handleChangeEvent(value: any) {
this.handleChangeEvent(value);
@HostListener('ionChange', ['$event.target'])
_handleChangeEvent(el: any) {
this.handleChangeEvent(el, el.value);
}
}

View File

@@ -20,8 +20,8 @@ export class TextValueAccessor extends ValueAccessor {
super(el);
}
@HostListener('ionChange', ['$event.target.value'])
_handleInputEvent(value: any) {
this.handleChangeEvent(value);
@HostListener('ionChange', ['$event.target'])
_handleInputEvent(el: any) {
this.handleChangeEvent(el, el.value);
}
}

View File

@@ -16,18 +16,22 @@ export class ValueAccessor implements ControlValueAccessor {
setIonicClasses(this.el);
}
handleChangeEvent(value: any) {
if (value !== this.lastValue) {
this.lastValue = value;
this.onChange(value);
handleChangeEvent(el: HTMLElement, value: any) {
if (el === this.el.nativeElement) {
if (value !== this.lastValue) {
this.lastValue = value;
this.onChange(value);
}
setIonicClasses(this.el);
}
setIonicClasses(this.el);
}
@HostListener('ionBlur')
_handleBlurEvent() {
this.onTouched();
setIonicClasses(this.el);
@HostListener('ionBlur', ['$event.target'])
_handleBlurEvent(el: any) {
if (el === this.el.nativeElement) {
this.onTouched();
setIonicClasses(this.el);
}
}
registerOnChange(fn: (value: any) => void) {
@@ -68,7 +72,7 @@ const getClasses = (element: HTMLElement) => {
return classes;
};
function setClasses(element: HTMLElement, classes: string[]) {
const setClasses = (element: HTMLElement, classes: string[]) => {
const classList = element.classList;
classList.remove(
@@ -80,8 +84,8 @@ function setClasses(element: HTMLElement, classes: string[]) {
'ion-pristine'
);
classList.add(...classes);
}
};
function startsWith(input: string, search: string): boolean {
const startsWith = (input: string, search: string): boolean => {
return input.substr(0, search.length) === search;
}
};

View File

@@ -108,6 +108,14 @@ export class StackController {
// Wait until previous transitions finish
return this.zone.runOutsideAngular(() => {
return this.wait(() => {
// disconnect leaving page from change detection to
// reduce jank during the page transition
if (leavingView) {
leavingView.ref.changeDetectorRef.detach();
}
// In case the enteringView is the same as the leavingPage we need to reattach()
enteringView.ref.changeDetectorRef.reattach();
return this.transition(enteringView, leavingView, animation, this.canGoBack(1), false)
.then(() => cleanupAsync(enteringView, views, viewsSnapshot, this.location))
.then(() => ({
@@ -161,7 +169,7 @@ export class StackController {
enteringView, // entering view
leavingView, // leaving view
'back',
true,
this.canGoBack(2),
true
);
});
@@ -173,6 +181,8 @@ export class StackController {
if (shouldComplete) {
this.skipTransition = true;
this.pop(1);
} else if (this.activeView) {
cleanup(this.activeView, this.views, this.views, this.location);
}
}
@@ -216,16 +226,6 @@ export class StackController {
if (leavingView === enteringView) {
return Promise.resolve(false);
}
// disconnect leaving page from change detection to
// reduce jank during the page transition
if (leavingView) {
leavingView.ref.changeDetectorRef.detach();
}
// In case the enteringView is the same as the leavingPage we need to reattach()
if (enteringView) {
enteringView.ref.changeDetectorRef.reattach();
}
const enteringEl = enteringView ? enteringView.element : undefined;
const leavingEl = leavingView ? leavingView.element : undefined;
const containerEl = this.containerEl;

View File

@@ -206,7 +206,7 @@ export class IonVirtualScroll {
}
}
function getElement(view: EmbeddedViewRef<VirtualContext>): HTMLElement {
const getElement = (view: EmbeddedViewRef<VirtualContext>): HTMLElement => {
const rootNodes = view.rootNodes;
for (let i = 0; i < rootNodes.length; i++) {
if (rootNodes[i].nodeType === 1) {
@@ -214,7 +214,7 @@ function getElement(view: EmbeddedViewRef<VirtualContext>): HTMLElement {
}
}
throw new Error('virtual element was not created');
}
};
proxyInputs(IonVirtualScroll, [
'approxItemHeight',

View File

@@ -65,7 +65,7 @@ export class AngularFrameworkDelegate implements FrameworkDelegate {
}
}
export function attachView(
export const attachView = (
zone: NgZone,
resolver: ComponentFactoryResolver,
injector: Injector,
@@ -74,7 +74,7 @@ export function attachView(
elRefMap: WeakMap<HTMLElement, any>,
elEventsMap: WeakMap<HTMLElement, () => void>,
container: any, component: any, params: any, cssClasses: string[] | undefined
) {
) => {
const factory = resolver.resolveComponentFactory(component);
const childInjector = Injector.create({
providers: getProviders(params),
@@ -104,7 +104,7 @@ export function attachView(
elRefMap.set(hostElement, componentRef);
elEventsMap.set(hostElement, unbindEvents);
return hostElement;
}
};
const LIFECYCLES = [
LIFECYCLE_WILL_ENTER,
@@ -114,7 +114,7 @@ const LIFECYCLES = [
LIFECYCLE_WILL_UNLOAD
];
export function bindLifecycleEvents(zone: NgZone, instance: any, element: HTMLElement) {
export const bindLifecycleEvents = (zone: NgZone, instance: any, element: HTMLElement) => {
return zone.run(() => {
const unregisters = LIFECYCLES
.filter(eventName => typeof instance[eventName] === 'function')
@@ -125,11 +125,11 @@ export function bindLifecycleEvents(zone: NgZone, instance: any, element: HTMLEl
});
return () => unregisters.forEach(fn => fn());
});
}
};
const NavParamsToken = new InjectionToken<any>('NavParamsToken');
function getProviders(params: {[key: string]: any}) {
const getProviders = (params: {[key: string]: any}) => {
return [
{
provide: NavParamsToken, useValue: params
@@ -138,8 +138,8 @@ function getProviders(params: {[key: string]: any}) {
provide: NavParams, useFactory: provideNavParamsInjectable, deps: [NavParamsToken]
}
];
}
};
function provideNavParamsInjectable(params: {[key: string]: any}) {
const provideNavParamsInjectable = (params: {[key: string]: any}) => {
return new NavParams(params);
}
};

View File

@@ -42,7 +42,7 @@ export class Config {
export const ConfigToken = new InjectionToken<any>('USERCONFIG');
function getConfig(): CoreConfig | null {
const getConfig = (): CoreConfig | null => {
if (typeof (window as any) !== 'undefined') {
const Ionic = (window as IonicWindow).Ionic;
if (Ionic && Ionic.config) {
@@ -50,4 +50,4 @@ function getConfig(): CoreConfig | null {
}
}
return null;
}
};

View File

@@ -22,7 +22,7 @@ export class DomController {
}
}
function getQueue() {
const getQueue = () => {
const win = typeof (window as any) !== 'undefined' ? window : null as any;
if (win != null) {
@@ -41,6 +41,6 @@ function getQueue() {
read: (cb: any) => cb(),
write: (cb: any) => cb()
};
}
};
export type RafCallback = (timeStamp?: number) => void;

View File

@@ -213,7 +213,7 @@ export class NavController {
}
}
function getAnimation(direction: RouterDirection, animated: boolean | undefined, animationDirection: 'forward' | 'back' | undefined): NavDirection | undefined {
const getAnimation = (direction: RouterDirection, animated: boolean | undefined, animationDirection: 'forward' | 'back' | undefined): NavDirection | undefined => {
if (animated === false) {
return undefined;
}
@@ -226,7 +226,7 @@ function getAnimation(direction: RouterDirection, animated: boolean | undefined,
return 'forward';
}
return undefined;
}
};
const DEFAULT_DIRECTION = 'auto';
const DEFAULT_ANIMATED = undefined;

View File

@@ -46,9 +46,9 @@ export class Platform {
zone.run(() => {
this.win = doc.defaultView;
this.backButton.subscribeWithPriority = function(priority, callback) {
return this.subscribe(ev => {
ev.register(priority, callback);
});
return this.subscribe(ev => (
ev.register(priority, () => zone.run(callback))
));
};
proxyEvent(this.pause, doc, 'pause');

View File

@@ -0,0 +1 @@
package-lock=false

View File

@@ -13,11 +13,11 @@
"build": {
"builder": "@angular-devkit/build-angular:browser",
"options": {
"outputPath": "dist/test-app",
"outputPath": "dist/browser",
"index": "src/index.html",
"main": "src/main.ts",
"polyfills": "src/polyfills.ts",
"tsConfig": "src/tsconfig.app.json",
"tsConfig": "tsconfig.app.json",
"assets": [
"src/favicon.ico",
{
@@ -31,9 +31,7 @@
"output": "./svg"
}
],
"styles": [
"src/styles.css"
],
"styles": ["src/styles.css"],
"scripts": []
},
"configurations": {
@@ -86,37 +84,13 @@
"options": {
"main": "src/test.ts",
"polyfills": "src/polyfills.ts",
"tsConfig": "src/tsconfig.spec.json",
"karmaConfig": "src/karma.conf.js",
"styles": [
"src/styles.css"
],
"tsConfig": "tsconfig.spec.json",
"karmaConfig": "karma.conf.js",
"styles": ["src/styles.css"],
"scripts": [],
"assets": [
"src/favicon.ico",
"src/assets"
]
"assets": ["src/favicon.ico", "src/assets"]
}
},
"lint": {
"builder": "@angular-devkit/build-angular:tslint",
"options": {
"tsConfig": [
"src/tsconfig.app.json",
"src/tsconfig.spec.json"
],
"exclude": [
"**/node_modules/**"
]
}
}
}
},
"test-app-e2e": {
"root": "e2e/",
"projectType": "application",
"prefix": "",
"architect": {
"e2e": {
"builder": "@angular-devkit/build-angular:protractor",
"options": {
@@ -126,20 +100,39 @@
"configurations": {
"production": {
"devServerTarget": "test-app:serve:production"
},
"ci": {
"devServerTarget": "test-app:serve:ci"
}
}
},
"lint": {
"builder": "@angular-devkit/build-angular:tslint",
"options": {
"tsConfig": "e2e/tsconfig.e2e.json",
"exclude": [
"**/node_modules/**"
]
"tsConfig": ["tsconfig.app.json", "tsconfig.spec.json"],
"exclude": ["**/node_modules/**"]
}
},
"server": {
"builder": "@angular-devkit/build-angular:server",
"options": {
"outputPath": "dist/server",
"main": "src/main.server.ts",
"tsConfig": "tsconfig.server.json"
},
"configurations": {
"production": {
"fileReplacements": [
{
"src": "src/environments/environment.ts",
"replaceWith": "src/environments/environment.prod.ts"
}
]
}
}
}
}
}
},
"defaultProject": "test-app"
}
}

View File

@@ -0,0 +1,12 @@
# This file is used by the build system to adjust CSS and JS output to support the specified browsers below.
# For additional information regarding the format and rule options, please see:
# https://github.com/browserslist/browserslist#queries
# You can see what browsers were selected by your queries by running:
# npx browserslist
> 0.5%
last 2 versions
Firefox ESR
not dead
not IE 9-11 # For IE 9-11 support, remove 'not'.

View File

@@ -1,19 +1,22 @@
// @ts-check
// Protractor configuration file, see link for more information
// https://github.com/angular/protractor/blob/master/lib/config.ts
const { SpecReporter } = require('jasmine-spec-reporter');
/**
* @type { import("protractor").Config }
*/
exports.config = {
allScriptsTimeout: 11000,
specs: [
'./**/*.e2e-spec.ts'
'./src/**/*.e2e-spec.ts'
],
capabilities: {
browserName: 'chrome',
chromeOptions: {
args: [ "--headless", "--disable-gpu", "--window-size=400,1000", "--start-maximized" ]
}
'browserName': 'chrome'
},
chromeOptions: {
args: [ "--headless", "--disable-gpu", "--window-size=400,1000", "--start-maximized" ]
},
directConnect: true,
baseUrl: 'http://localhost:4200/',
@@ -25,8 +28,8 @@ exports.config = {
},
onPrepare() {
require('ts-node').register({
project: require('path').join(__dirname, './tsconfig.e2e.json')
project: require('path').join(__dirname, './tsconfig.json')
});
jasmine.getEnv().addReporter(new SpecReporter({ spec: { displayStacktrace: true } }));
}
};
};

View File

@@ -60,4 +60,10 @@ describe('inputs', () => {
expect(await element(by.css('#select-note')).getText()).toEqual('playstation');
expect(await element(by.css('#range-note')).getText()).toEqual('20');
});
it('nested components should not interfere with NgModel', async () => {
expect(await element(by.css('#range-note')).getText()).toEqual('10');
await element(by.css('#nested-toggle')).click();
expect(await element(by.css('#range-note')).getText()).toEqual('10');
});
});

View File

@@ -7,6 +7,41 @@ describe('navigation', () => {
return handleErrorMessages();
});
// TODO: Fix flaky tests
xit ('should swipe and abort', async () => {
await browser.get('/router-link?ionic:mode=ios');
await waitTime(500);
await element(by.css('#routerLink')).click();
await waitTime(500);
await swipeLeft(5);
await waitTime(500);
const pageHidden = element(by.css('app-router-link'));
expect(await pageHidden.getAttribute('aria-hidden')).toEqual('true');
expect(await pageHidden.getAttribute('class')).toEqual('ion-page ion-page-hidden');
const pageVisible = element(by.css('app-router-link-page'));
expect(await pageVisible.getAttribute('aria-hidden')).toEqual(null);
expect(await pageVisible.getAttribute('class')).toEqual('ion-page can-go-back');
});
xit ('should swipe and go back', async () => {
await browser.get('/router-link?ionic:mode=ios');
await waitTime(500);
await element(by.css('#routerLink')).click();
await waitTime(500);
await testStack('ion-router-outlet', ['app-router-link', 'app-router-link-page']);
await swipeLeft(300);
await waitTime(1000);
await testStack('ion-router-outlet', ['app-router-link']);
const page = element(by.css('app-router-link'));
expect(await page.getAttribute('aria-hidden')).toEqual(null);
expect(await page.getAttribute('class')).toEqual('ion-page');
})
it('should navigate correctly', async () => {
await browser.get('/navigation/page1');
await waitTime(2000);
@@ -22,3 +57,17 @@ describe('navigation', () => {
});
});
function swipeLeft(end: number) {
return browser.driver.touchActions()
.tapAndHold({x: 5, y: 1})
.move({x: 6, y: 1})
.move({x: 7, y: 1})
.move({x: 8, y: 1})
.move({x: 30, y: 1})
.move({x: 300, y: 1})
.move({x: end, y: 1})
.move({x: end, y: 1})
.release({x: end, y: 1})
.perform();
}

View File

File diff suppressed because it is too large Load Diff

View File

@@ -1,50 +1,63 @@
{
"name": "test-app",
"name": "ionic-angular-test-app",
"version": "0.0.0",
"private": true,
"scripts": {
"ng": "ng",
"start": "npm run sync && ng serve",
"sync:build": "sh scripts/build-ionic.sh",
"sync": "sh scripts/sync.sh",
"build": "ng build --prod --no-progress",
"build": "npm run sync && ng build --prod --no-progress",
"test": "ng e2e --prod",
"test.dev": "npm run sync && ng e2e",
"lint": "ng lint"
"lint": "ng lint",
"postinstall": "npm run sync",
"compile:server": "webpack --config webpack.server.config.js --progress --colors",
"serve:ssr": "node dist/server",
"build:ssr": "npm run build:client-and-server-bundles && npm run compile:server",
"build:client-and-server-bundles": "npm run build && ng run test-app:server:production"
},
"private": true,
"dependencies": {
"@angular/animations": "~8.1.2",
"@angular/common": "~8.1.2",
"@angular/compiler": "~8.1.2",
"@angular/core": "~8.1.2",
"@angular/forms": "~8.1.2",
"@angular/platform-browser": "~8.1.2",
"@angular/platform-browser-dynamic": "~8.1.2",
"@angular/router": "~8.1.2",
"@angular/animations": "~8.2.0",
"@angular/common": "~8.2.0",
"@angular/compiler": "~8.2.0",
"@angular/core": "~8.2.0",
"@angular/forms": "~8.2.0",
"@angular/platform-browser": "~8.2.0",
"@angular/platform-browser-dynamic": "~8.2.0",
"@angular/platform-server": "~8.2.0",
"@angular/router": "~8.2.0",
"@ionic/angular": "^4.7.0",
"@ionic/angular-server": "^0.0.2",
"@nguniversal/express-engine": "~8.1.1",
"@nguniversal/module-map-ngfactory-loader": "~8.1.1",
"core-js": "^2.6.2",
"rxjs": "^6.4.0",
"express": "^4.15.2",
"rxjs": "~6.5.2",
"tslib": "^1.9.0",
"zone.js": "~0.9.1"
"zone.js": "~0.10.0"
},
"devDependencies": {
"@angular-devkit/build-angular": "^0.801.2",
"@angular/cli": "~8.1.2",
"@angular/compiler-cli": "~8.1.2",
"@angular/language-service": "~8.1.2",
"@types/jasmine": "~2.8.8",
"@angular-devkit/build-angular": "~0.802.0",
"@angular/cli": "~8.2.0",
"@angular/compiler-cli": "~8.2.0",
"@angular/language-service": "~8.2.0",
"@types/jasmine": "~3.3.16",
"@types/jasminewd2": "~2.0.3",
"@types/node": "~8.9.4",
"@types/node": "~12.6.8",
"codelyzer": "^5.0.1",
"jasmine-core": "~2.99.1",
"jasmine-spec-reporter": "~4.2.1",
"karma": "~3.1.4",
"karma-chrome-launcher": "~2.2.0",
"karma-coverage-istanbul-reporter": "~2.0.1",
"karma-jasmine": "~1.1.2",
"karma-jasmine-html-reporter": "^0.2.2",
"karma": "~4.2.0",
"karma-chrome-launcher": "~3.0.0",
"karma-coverage-istanbul-reporter": "~2.1.0",
"karma-jasmine": "~2.0.1",
"karma-jasmine-html-reporter": "^1.4.2",
"protractor": "~5.4.2",
"ts-node": "~7.0.0",
"tslint": "~5.12.1",
"typescript": "~3.4.0"
"ts-loader": "^5.2.0",
"ts-node": "~8.3.0",
"tslint": "~5.18.0",
"typescript": "~3.5.3",
"webpack-cli": "^3.1.0"
}
}

View File

@@ -10,6 +10,14 @@ popd
pushd angular
npm link @ionic/core
npm run build
npm link
popd
# Build angular-server
pushd packages/angular-server
npm link @ionic/core
npm link @ionic/angular
npm run build
popd
popd

View File

@@ -1,15 +1,25 @@
# Copy angular dist
rm -rf node_modules/@ionic/angular/dist
rm -rf node_modules/@ionic/angular
mkdir node_modules/@ionic/angular
cp -a ../../dist node_modules/@ionic/angular/dist
cp -a ../../css node_modules/@ionic/angular/css
cp -a ../../package.json node_modules/@ionic/angular/package.json
# Copy core dist
rm -rf node_modules/@ionic/core/dist
rm -rf node_modules/@ionic/core/loader
# Copy angular server
rm -rf node_modules/@ionic/angular-server
mkdir node_modules/@ionic/angular-server
cp -a ../../../packages/angular-server/dist node_modules/@ionic/angular-server/dist
cp -a ../../../packages/angular-server/package.json node_modules/@ionic/angular-server/package.json
# # Copy core dist
rm -rf node_modules/@ionic/core
mkdir node_modules/@ionic/core
cp -a ../../../core/css node_modules/@ionic/core/css
cp -a ../../../core/dist node_modules/@ionic/core/dist
cp -a ../../../core/hydrate node_modules/@ionic/core/hydrate
cp -a ../../../core/loader node_modules/@ionic/core/loader
cp -a ../../../core/package.json node_modules/@ionic/core/package.json
# Copy ionicons
# # Copy ionicons
rm -rf node_modules/ionicons
cp -a ../../../core/node_modules/ionicons node_modules/ionicons

View File

@@ -0,0 +1,58 @@
/**
* *** NOTE ON IMPORTING FROM ANGULAR AND NGUNIVERSAL IN THIS FILE ***
*
* If your application uses third-party dependencies, you'll need to
* either use Webpack or the Angular CLI's `bundleDependencies` feature
* in order to adequately package them for use on the server without a
* node_modules directory.
*
* However, due to the nature of the CLI's `bundleDependencies`, importing
* Angular in this file will create a different instance of Angular than
* the version in the compiled application code. This leads to unavoidable
* conflicts. Therefore, please do not explicitly import from @angular or
* @nguniversal in this file. You can export any needed resources
* from your application's main.server.ts file, as seen below with the
* import for `ngExpressEngine`.
*/
import 'zone.js/dist/zone-node';
import * as express from 'express';
import {join} from 'path';
// Express server
const app = express();
const PORT = process.env.PORT || 4000;
const DIST_FOLDER = join(process.cwd(), 'dist/browser');
// * NOTE :: leave this as require() since this file is built Dynamically from webpack
const {AppServerModuleNgFactory, LAZY_MODULE_MAP, ngExpressEngine, provideModuleMap} = require('./dist/server/main');
// Our Universal express-engine (found @ https://github.com/angular/universal/tree/master/modules/express-engine)
app.engine('html', ngExpressEngine({
bootstrap: AppServerModuleNgFactory,
providers: [
provideModuleMap(LAZY_MODULE_MAP)
]
}));
app.set('view engine', 'html');
app.set('views', DIST_FOLDER);
// Example Express Rest API endpoints
// app.get('/api/**', (req, res) => { });
// Serve static files from /browser
app.get('*.*', express.static(DIST_FOLDER, {
maxAge: '1y'
}));
// All regular routes use the Universal engine
app.get('*', (req, res) => {
res.render('index', { req });
});
// Start up the Node server
app.listen(PORT, () => {
console.log(`Node Express server listening on http://localhost:${PORT}`);
});

View File

@@ -47,7 +47,7 @@ const routes: Routes = [
},
{
path: 'tabs',
loadChildren: './tabs/tabs.module#TabsPageModule'
loadChildren: () => import('./tabs/tabs.module').then(m => m.TabsPageModule)
},
{
path: 'nested-outlet',

View File

@@ -59,7 +59,7 @@ import { AlertComponent } from './alert/alert.component';
AlertComponent
],
imports: [
BrowserModule,
BrowserModule.withServerTransition({ appId: 'serverApp' }),
AppRoutingModule,
FormsModule,
ReactiveFormsModule,

View File

@@ -0,0 +1,19 @@
import { NgModule } from '@angular/core';
import { ServerModule } from '@angular/platform-server';
import { IonicServerModule } from '@ionic/angular-server';
import { AppModule } from './app.module';
import { AppComponent } from './app.component';
import { ModuleMapLoaderModule } from '@nguniversal/module-map-ngfactory-loader';
@NgModule({
imports: [
AppModule,
ServerModule,
ModuleMapLoaderModule,
IonicServerModule
],
bootstrap: [AppComponent],
})
export class AppServerModule {}

View File

@@ -20,7 +20,9 @@ export class FormComponent {
input2: ['Default Value'],
checkbox: [false],
range: [5, Validators.min(10)],
}, {updateOn: window.location.hash === '#blur' ? 'blur' : 'change'});
}, {
updateOn: typeof (window as any) !== 'undefined' && window.location.hash === '#blur' ? 'blur' : 'change'
});
}
onSubmit(_ev) {

View File

@@ -93,7 +93,9 @@
<ion-item color="dark">
<ion-label>Range Mirror</ion-label>
<ion-range [(ngModel)]="range"></ion-range>
<ion-range [(ngModel)]="range">
<ion-toggle slot="start" id="nested-toggle" [(ngModel)]="toggle"></ion-toggle>
</ion-range>
<ion-note slot="end">{{range}}</ion-note>
</ion-item>

View File

@@ -1,4 +1,4 @@
import { Component, OnInit, ViewChild, AfterViewInit } from '@angular/core';
import { AfterViewInit, Component, ViewChild } from '@angular/core';
import { IonSlides } from '@ionic/angular';
@Component({
@@ -6,7 +6,7 @@ import { IonSlides } from '@ionic/angular';
templateUrl: './slides.component.html',
})
export class SlidesComponent implements AfterViewInit {
@ViewChild(IonSlides, {static: true}) slides: IonSlides;
@ViewChild(IonSlides, { static: true }) slides: IonSlides;
slideIndex = 0;
slideIndex2 = 0;

View File

@@ -39,7 +39,7 @@ const routes: Routes = [
},
{
path: 'lazy',
loadChildren: '../tabs-lazy/tabs-lazy.module#TabsLazyModule'
loadChildren: () => import('../tabs-lazy/tabs-lazy.module').then(m => m.TabsLazyModule)
}
]
}

View File

@@ -7,11 +7,11 @@ import { IonTabs, IonButton, IonSlides, IonSlide } from '@ionic/angular';
})
export class ViewChildComponent implements AfterViewInit {
@ViewChild(IonSlides, {static: true}) slides: IonSlides;
@ViewChild(IonButton, {static: true}) button: IonButton;
@ViewChild(IonTabs, {static: true}) tabs: IonTabs;
@ViewChild('div', {static: true}) div: ElementRef;
@ViewChild('slide', {static: true}) slide: IonSlide;
@ViewChild(IonSlides, { static: true }) slides: IonSlides;
@ViewChild(IonButton, { static: true }) button: IonButton;
@ViewChild(IonTabs, { static: true }) tabs: IonTabs;
@ViewChild('div', { static: true }) div: ElementRef;
@ViewChild('slide', { static: true }) slide: IonSlide;
ngAfterViewInit() {
const loaded = !!(this.slides && this.button && this.tabs && this.div && this.slide);

View File

@@ -8,7 +8,7 @@ import { IonVirtualScroll } from '@ionic/angular';
})
export class VirtualScrollComponent {
@ViewChild(IonVirtualScroll, {static: true}) virtualScroll: IonVirtualScroll;
@ViewChild(IonVirtualScroll, { static: true }) virtualScroll: IonVirtualScroll;
items = Array.from({length: 100}, (_, i) => ({ name: `${i}`, checked: true}));

View File

@@ -1,11 +0,0 @@
# This file is currently used by autoprefixer to adjust CSS to support the below specified browsers
# For additional information regarding the format and rule options, please see:
# https://github.com/browserslist/browserslist#queries
#
# For IE 9-11 support, please remove 'not' from the last line of the file and adjust as needed
> 0.5%
last 2 versions
Firefox ESR
not dead
not IE 9-11

View File

@@ -0,0 +1,11 @@
import { enableProdMode } from '@angular/core';
import { environment } from './environments/environment';
if (environment.production) {
enableProdMode();
}
export { AppServerModule } from './app/app.server.module';
export { ngExpressEngine } from '@nguniversal/express-engine';
export { provideModuleMap } from '@nguniversal/module-map-ngfactory-loader';

View File

@@ -8,5 +8,8 @@ if (environment.production) {
enableProdMode();
}
platformBrowserDynamic().bootstrapModule(AppModule)
.catch(err => console.error(err));
document.addEventListener('DOMContentLoaded', () => {
platformBrowserDynamic()
.bootstrapModule(AppModule)
.catch(err => console.error(err));
});

View File

@@ -18,57 +18,40 @@
* BROWSER POLYFILLS
*/
/** IE9, IE10 and IE11 requires all of the following polyfills. **/
// import 'core-js/es6/symbol';
// import 'core-js/es6/object';
// import 'core-js/es6/function';
// import 'core-js/es6/parse-int';
// import 'core-js/es6/parse-float';
// import 'core-js/es6/number';
// import 'core-js/es6/math';
// import 'core-js/es6/string';
// import 'core-js/es6/date';
// import 'core-js/es6/array';
// import 'core-js/es6/regexp';
// import 'core-js/es6/map';
// import 'core-js/es6/weak-map';
// import 'core-js/es6/set';
/**
* If the application will be indexed by Google Search, the following is required.
* Googlebot uses a renderer based on Chrome 41.
* https://developers.google.com/search/docs/guides/rendering
**/
// import 'core-js/es6/array';
/** IE10 and IE11 requires the following for NgClass support on SVG elements */
// import 'classlist.js'; // Run `npm install --save classlist.js`.
/** IE10 and IE11 requires the following for the Reflect API. */
// import 'core-js/es6/reflect';
/**
* Web Animations `@angular/platform-browser/animations`
* Only required if AnimationBuilder is used within the application and using IE/Edge or Safari.
* Standard animation support in Angular DOES NOT require any polyfills (as of Angular 6.0).
**/
*/
// import 'web-animations-js'; // Run `npm install --save web-animations-js`.
/**
* By default, zone.js will patch all possible macroTask and DomEvents
* user can disable parts of macroTask/DomEvents patch by setting following flags
* because those flags need to be set before `zone.js` being loaded, and webpack
* will put import in the top of bundle, so user need to create a separate file
* in this directory (for example: zone-flags.ts), and put the following flags
* into that file, and then add the following code before importing zone.js.
* import './zone-flags.ts';
*
* The flags allowed in zone-flags.ts are listed here.
*
* The following flags will work for all browsers.
*
* (window as any).__Zone_disable_requestAnimationFrame = true; // disable patch requestAnimationFrame
* (window as any).__Zone_disable_on_property = true; // disable patch onProperty such as onclick
* (window as any).__zone_symbol__UNPATCHED_EVENTS = ['scroll', 'mousemove']; // disable patch specified eventNames
*
* in IE/Edge developer tools, the addEventListener will also be wrapped by zone.js
* with the following flag, it will bypass `zone.js` patch for IE/Edge
*
* (window as any).__Zone_enable_cross_context_check = true;
*
*/
// (window as any).__Zone_disable_requestAnimationFrame = true; // disable patch requestAnimationFrame
// (window as any).__Zone_disable_on_property = true; // disable patch onProperty such as onclick
// (window as any).__zone_symbol__BLACK_LISTED_EVENTS = ['scroll', 'mousemove']; // disable patch specified eventNames
/*
* in IE/Edge developer tools, the addEventListener will also be wrapped by zone.js
* with the following flag, it will bypass `zone.js` patch for IE/Edge
*/
// (window as any).__Zone_enable_cross_context_check = true;
/***************************************************************************************************
* Zone JS is required by default for Angular itself.
*/

View File

@@ -1,15 +0,0 @@
{
"angularCompilerOptions": {
"fullTemplateTypeCheck": true,
"strictMetadataEmit" : true
},
"extends": "../tsconfig.json",
"compilerOptions": {
"outDir": "../out-tsc/app",
"types": []
},
"exclude": [
"test.ts",
"**/*.spec.ts"
]
}

View File

@@ -1,18 +0,0 @@
{
"extends": "../tsconfig.json",
"compilerOptions": {
"outDir": "../out-tsc/spec",
"types": [
"jasmine",
"node"
]
},
"files": [
"test.ts",
"polyfills.ts"
],
"include": [
"**/*.spec.ts",
"**/*.d.ts"
]
}

View File

@@ -1,17 +0,0 @@
{
"extends": "../tslint.json",
"rules": {
"directive-selector": [
true,
"attribute",
"app",
"camelCase"
],
"component-selector": [
true,
"element",
"app",
"kebab-case"
]
}
}

View File

@@ -0,0 +1,8 @@
{
"extends": "./tsconfig.json",
"compilerOptions": {
"outDir": "./out-tsc/app"
},
"include": ["src/**/*.ts"],
"exclude": ["src/test.ts", "src/**/*.spec.ts"]
}

View File

@@ -1,16 +1,13 @@
{
"compileOnSave": false,
"compilerOptions": {
"baseUrl": "./",
"importHelpers": true,
"outDir": "./dist/out-tsc",
"sourceMap": true,
"declaration": false,
"module": "es2015",
"moduleResolution": "node",
"emitDecoratorMetadata": true,
"experimentalDecorators": true,
"importHelpers": true,
"target": "es5",
"typeRoots": [
"node_modules/@types"
],

View File

@@ -0,0 +1,9 @@
{
"extends": "./tsconfig.app.json",
"compilerOptions": {
"outDir": "../out-tsc/app-server"
},
"angularCompilerOptions": {
"entryModule": "./src/app/app.server.module#AppServerModule"
}
}

View File

@@ -0,0 +1,19 @@
{
"extends": "./tsconfig.json",
"compilerOptions": {
"outDir": "./out-tsc/spec",
"types": [
"jasmine",
"node"
]
},
"files": [
"src/test.ts",
"src/zone-flags.ts",
"src/polyfills.ts"
],
"include": [
"src/**/*.spec.ts",
"src/**/*.d.ts"
]
}

View File

@@ -1,36 +1,16 @@
{
"rulesDirectory": [
"node_modules/codelyzer"
],
"extends": "tslint:recommended",
"rulesDirectory": ["codelyzer"],
"rules": {
"arrow-return-shorthand": true,
"callable-types": true,
"class-name": true,
"comment-format": [
true,
"check-space"
],
"curly": true,
"array-type": false,
"arrow-parens": false,
"deprecation": {
"severity": "warn"
},
"eofline": true,
"forin": true,
"import-blacklist": [
true,
"rxjs/Rx"
],
"import-spacing": true,
"indent": [
true,
"spaces"
],
"interface-over-type-literal": true,
"label-position": true,
"max-line-length": [
true,
140
],
"import-blacklist": [true, "rxjs/Rx"],
"interface-name": false,
"max-classes-per-file": false,
"max-line-length": [true, 140],
"member-access": false,
"member-ordering": [
true,
@@ -43,89 +23,32 @@
]
}
],
"no-arg": true,
"no-bitwise": true,
"no-console": [
true,
"debug",
"info",
"time",
"timeEnd",
"trace"
],
"no-construct": true,
"no-debugger": true,
"no-duplicate-super": true,
"no-consecutive-blank-lines": false,
"no-console": [true, "debug", "info", "time", "timeEnd", "trace"],
"no-empty": false,
"no-empty-interface": true,
"no-eval": true,
"no-inferrable-types": [
true,
"ignore-params"
],
"no-misused-new": true,
"no-inferrable-types": [true, "ignore-params"],
"no-non-null-assertion": true,
"no-redundant-jsdoc": true,
"no-shadowed-variable": true,
"no-string-literal": false,
"no-string-throw": true,
"no-switch-case-fall-through": true,
"no-trailing-whitespace": true,
"no-unnecessary-initializer": true,
"no-unused-expression": true,
"no-use-before-declare": true,
"no-var-keyword": true,
"no-var-requires": false,
"object-literal-key-quotes": [true, "as-needed"],
"object-literal-sort-keys": false,
"one-line": [
true,
"check-open-brace",
"check-catch",
"check-else",
"check-whitespace"
],
"prefer-const": true,
"quotemark": [
true,
"single"
],
"radix": true,
"semicolon": [
true,
"always"
],
"triple-equals": [
true,
"allow-null-check"
],
"typedef-whitespace": [
true,
{
"call-signature": "nospace",
"index-signature": "nospace",
"parameter": "nospace",
"property-declaration": "nospace",
"variable-declaration": "nospace"
}
],
"unified-signatures": true,
"variable-name": false,
"whitespace": [
true,
"check-branch",
"check-decl",
"check-operator",
"check-separator",
"check-type"
],
"ordered-imports": false,
"quotemark": [true, "single"],
"trailing-comma": false,
"no-output-on-prefix": true,
"use-input-property-decorator": true,
"use-output-property-decorator": true,
"use-host-property-decorator": true,
"no-inputs-metadata-property": true,
"no-inputs-metadata-property": true,
"no-host-metadata-property": true,
"no-input-rename": true,
"no-output-rename": true,
"use-life-cycle-interface": true,
"use-lifecycle-interface": true,
"use-pipe-transform-interface": true,
"component-class-suffix": true,
"directive-class-suffix": true
"one-variable-per-declaration": false,
"component-class-suffix": [true, "Page", "Component"],
"directive-class-suffix": true,
"directive-selector": [true, "attribute", "app", "camelCase"],
"component-selector": [true, "element", "app", "page", "kebab-case"]
}
}

View File

@@ -0,0 +1,53 @@
// Work around for https://github.com/angular/angular-cli/issues/7200
const path = require('path');
const webpack = require('webpack');
module.exports = {
mode: 'none',
entry: {
// This is our Express server for Dynamic universal
server: './server.ts'
},
externals: {
'./dist/server/main': 'require("./server/main")'
},
target: 'node',
resolve: {
mainFields: ['module', 'main'],
extensions: ['.ts', '.js']
},
optimization: {
minimize: false
},
output: {
// Puts the output at the root of the dist folder
path: path.join(__dirname, 'dist'),
filename: '[name].js'
},
module: {
rules: [
{ test: /\.ts$/, loader: 'ts-loader' },
{
// Mark files inside `@angular/core` as using SystemJS style dynamic imports.
// Removing this will cause deprecation warnings to appear.
test: /(\\|\/)@angular(\\|\/)core(\\|\/).+\.js$/,
parser: { system: true },
},
]
},
plugins: [
new webpack.ContextReplacementPlugin(
// fixes WARNING Critical dependency: the request of a dependency is an expression
/(.+)?angular(\\|\/)core(.+)?/,
path.join(__dirname, 'src'), // location of your src
{} // a map of your routes
),
new webpack.ContextReplacementPlugin(
// fixes WARNING Critical dependency: the request of a dependency is an expression
/(.+)?express(\\|\/)(.+)?/,
path.join(__dirname, 'src'),
{}
)
]
};

View File

@@ -29,7 +29,16 @@
"importHelpers": true,
"rootDir": "src",
"strictPropertyInitialization": false,
"target": "es2015"
"target": "es2015",
"baseUrl": ".",
"paths": {
"@ionic/core/hydrate": [
"../core/hydrate"
],
"@ionic/core": [
"../core"
]
}
},
"exclude": ["node_modules", "src/schematics"],
"files": ["src/index.ts"]

View File

@@ -18,7 +18,7 @@
"no-floating-promises": false,
"no-invalid-template-strings": true,
"ban-export-const-enum": true,
"only-arrow-functions": true,
"prefer-for-of": false
}
}

View File

@@ -1,6 +1,6 @@
{
"name": "@ionic/core",
"version": "4.7.1",
"version": "4.7.2",
"description": "Base components for Ionic",
"keywords": [
"ionic",
@@ -34,7 +34,7 @@
"tslib": "^1.10.0"
},
"devDependencies": {
"@stencil/core": "1.2.1",
"@stencil/core": "1.2.3",
"@stencil/sass": "1.0.0",
"@types/jest": "24.0.13",
"@types/node": "10.12.18",
@@ -62,13 +62,14 @@
"tslint-react": "^3.6.0"
},
"scripts": {
"build": "npm run clean && npm run build.css && npm run build.vendor && stencil build --docs",
"build": "npm run clean && npm run build.css && npm run build.vendor && stencil build --docs && npm run cdnloader",
"build.vendor": "rollup --config ./scripts/swiper.rollup.config.js",
"build.css": "npm run css.sass && npm run css.minify",
"build.debug": "npm run clean && stencil build --debug",
"build.docs.json": "stencil build --docs-json dist/docs.json",
"changelog": "conventional-changelog -p angular -i CHANGELOG.md -s",
"clean": "node scripts/clean.js",
"cdnloader": "node scripts/copy-cdn-loader.js",
"css.minify": "cleancss -O2 -o ./css/ionic.bundle.css ./css/ionic.bundle.css",
"css.sass": "sass src/css:./css",
"lint": "npm run lint.ts && npm run lint.sass",
@@ -99,7 +100,7 @@
"bugs": {
"url": "https://github.com/ionic-team/ionic/issues"
},
"homepage": "https://github.com/ionic-team/ionic#readme",
"homepage": "https://ionicframework.com/",
"jest": {
"preset": "@stencil/core/testing"
}

View File

@@ -1,24 +1,30 @@
module.exports.applyPolyfills = function() { return Promise.resolve() };
module.exports.defineCustomElements = function(_, opts = {}) {
return new Promise((resolve, reject) => {
const doc = document;
const mod = doc.createElement('script');
mod.setAttribute('type', 'module');
mod['data-opts'] = opts;
mod.src = '__CDN_LOADER_URL__/dist/ionic/ionic.esm.js';
const legacy = doc.createElement('script');
legacy.setAttribute('nomodule', '');
legacy['data-opts'] = opts;
legacy.src = '__CDN_LOADER_URL__/dist/ionic/ionic.js';
exports.applyPolyfills = function() { return Promise.resolve() };
mod.onload = resolve;
mod.onerror = reject;
exports.defineCustomElements = function(_, opts) {
return new Promise(function(resolve, reject) {
if (typeof document !== 'undefined') {
opts = opts || {};
var mod = document.createElement('script');
mod.setAttribute('type', 'module');
mod['data-opts'] = opts;
mod.src = '__CDN_LOADER_URL__/dist/ionic/ionic.esm.js';
legacy.onload = resolve;
legacy.onerror = reject;
var legacy = document.createElement('script');
legacy.setAttribute('nomodule', '');
legacy['data-opts'] = opts;
legacy.src = '__CDN_LOADER_URL__/dist/ionic/ionic.js';
doc.head.appendChild(mod);
doc.head.appendChild(legacy);
mod.onload = resolve;
mod.onerror = reject;
legacy.onload = resolve;
legacy.onerror = reject;
document.head.appendChild(mod);
document.head.appendChild(legacy);
} else {
resolve();
}
});
}

View File

@@ -6,10 +6,12 @@
const fs = require('fs');
const path = require('path');
const version = process.argv[2];
let version = process.argv[2];
if (!version) {
throw new Error('version arg missing');
if (version) {
version = '@' + version;
} else {
version = '';
}
const srcPath = path.join(__dirname, 'cdn-loader.js');
@@ -19,7 +21,7 @@ let scriptContent = fs.readFileSync(srcPath, 'utf-8');
scriptContent = scriptContent.replace(
/__CDN_LOADER_URL__/g,
'https://cdn.jsdelivr.net/npm/@ionic/core@' + version
'https://cdn.jsdelivr.net/npm/@ionic/core' + version
);
fs.writeFileSync(path.join(__dirname, '..', 'loader', 'cdn.js'), scriptContent);

View File

@@ -2685,7 +2685,7 @@ export namespace Components {
*/
'buttons'?: (ToastButton | string)[];
/**
* Text to display in the close button.
* @deprecated Use `buttons` instead. Text to display in the close button.
*/
'closeButtonText'?: string;
/**
@@ -2748,7 +2748,7 @@ export namespace Components {
*/
'present': () => Promise<void>;
/**
* If `true`, the close button will be displayed.
* @deprecated Use `buttons` instead. If `true`, the close button will be displayed.
*/
'showCloseButton': boolean;
/**
@@ -5976,7 +5976,7 @@ declare namespace LocalJSX {
*/
'buttons'?: (ToastButton | string)[];
/**
* Text to display in the close button.
* @deprecated Use `buttons` instead. Text to display in the close button.
*/
'closeButtonText'?: string;
/**
@@ -6036,7 +6036,7 @@ declare namespace LocalJSX {
*/
'position'?: 'top' | 'bottom' | 'middle';
/**
* If `true`, the close button will be displayed.
* @deprecated Use `buttons` instead. If `true`, the close button will be displayed.
*/
'showCloseButton'?: boolean;
/**

View File

@@ -1,4 +1,4 @@
import { Component, ComponentInterface, Element, Event, EventEmitter, Listen, Method, Prop, h } from '@stencil/core';
import { Component, ComponentInterface, Element, Event, EventEmitter, Host, Method, Prop, h } from '@stencil/core';
import { getIonMode } from '../../global/ionic-global';
import { ActionSheetButton, Animation, AnimationBuilder, CssClassMap, OverlayEventDetail, OverlayInterface } from '../../interface';
@@ -105,20 +105,6 @@ export class ActionSheet implements ComponentInterface, OverlayInterface {
*/
@Event({ eventName: 'ionActionSheetDidDismiss' }) didDismiss!: EventEmitter<OverlayEventDetail>;
@Listen('ionBackdropTap')
protected onBackdropTap() {
this.dismiss(undefined, BACKDROP);
}
@Listen('ionActionSheetWillDismiss')
protected dispatchCancelHandler(ev: CustomEvent) {
const role = ev.detail.role;
if (isCancel(role)) {
const cancelButton = this.getButtons().find(b => b.role === 'cancel');
this.callButtonHandler(cancelButton);
}
}
/**
* Present the action sheet overlay after it has been created.
*/
@@ -191,22 +177,16 @@ export class ActionSheet implements ComponentInterface, OverlayInterface {
});
}
hostData() {
const mode = getIonMode(this);
private onBackdropTap = () => {
this.dismiss(undefined, BACKDROP);
}
return {
'role': 'dialog',
'aria-modal': 'true',
style: {
zIndex: 20000 + this.overlayIndex,
},
class: {
[mode]: true,
...getClassMap(this.cssClass),
'action-sheet-translucent': this.translucent
}
};
private dispatchCancelHandler = (ev: CustomEvent) => {
const role = ev.detail.role;
if (isCancel(role)) {
const cancelButton = this.getButtons().find(b => b.role === 'cancel');
this.callButtonHandler(cancelButton);
}
}
render() {
@@ -215,50 +195,66 @@ export class ActionSheet implements ComponentInterface, OverlayInterface {
const cancelButton = allButtons.find(b => b.role === 'cancel');
const buttons = allButtons.filter(b => b.role !== 'cancel');
return [
<ion-backdrop tappable={this.backdropDismiss}/>,
<div class="action-sheet-wrapper" role="dialog">
<div class="action-sheet-container">
<div class="action-sheet-group">
{this.header !== undefined &&
<div class="action-sheet-title">
{this.header}
{this.subHeader && <div class="action-sheet-sub-title">{this.subHeader}</div>}
return (
<Host
role="dialog"
aria-modal="true"
style={{
zIndex: `${20000 + this.overlayIndex}`,
}}
class={{
[mode]: true,
...getClassMap(this.cssClass),
'action-sheet-translucent': this.translucent
}}
onIonActionSheetWillDismiss={this.dispatchCancelHandler}
onIonBackdropTap={this.onBackdropTap}
>
<ion-backdrop tappable={this.backdropDismiss}/>
<div class="action-sheet-wrapper" role="dialog">
<div class="action-sheet-container">
<div class="action-sheet-group">
{this.header !== undefined &&
<div class="action-sheet-title">
{this.header}
{this.subHeader && <div class="action-sheet-sub-title">{this.subHeader}</div>}
</div>
}
{buttons.map(b =>
<button type="button" ion-activatable class={buttonClass(b)} onClick={() => this.buttonClick(b)}>
<span class="action-sheet-button-inner">
{b.icon && <ion-icon icon={b.icon} lazy={false} class="action-sheet-icon" />}
{b.text}
</span>
{mode === 'md' && <ion-ripple-effect></ion-ripple-effect>}
</button>
)}
</div>
{cancelButton &&
<div class="action-sheet-group action-sheet-group-cancel">
<button
type="button"
class={buttonClass(cancelButton)}
onClick={() => this.buttonClick(cancelButton)}
>
<span class="action-sheet-button-inner">
{cancelButton.icon &&
<ion-icon
icon={cancelButton.icon}
lazy={false}
class="action-sheet-icon"
/>}
{cancelButton.text}
</span>
</button>
</div>
}
{buttons.map(b =>
<button type="button" ion-activatable class={buttonClass(b)} onClick={() => this.buttonClick(b)}>
<span class="action-sheet-button-inner">
{b.icon && <ion-icon icon={b.icon} lazy={false} class="action-sheet-icon" />}
{b.text}
</span>
{mode === 'md' && <ion-ripple-effect></ion-ripple-effect>}
</button>
)}
</div>
{cancelButton &&
<div class="action-sheet-group action-sheet-group-cancel">
<button
type="button"
class={buttonClass(cancelButton)}
onClick={() => this.buttonClick(cancelButton)}
>
<span class="action-sheet-button-inner">
{cancelButton.icon &&
<ion-icon
icon={cancelButton.icon}
lazy={false}
class="action-sheet-icon"
/>}
{cancelButton.text}
</span>
</button>
</div>
}
</div>
</div>
];
</Host>
);
}
}

View File

@@ -80,7 +80,6 @@ export class ActionSheetExample {
```javascript
async function presentActionSheet() {
const actionSheetController = document.querySelector('ion-action-sheet-controller');
await actionSheetController.componentOnReady();
const actionSheet = await actionSheetController.create({
header: "Albums",

View File

@@ -60,7 +60,6 @@
const mode = Ionic.mode;
const actionSheetController = document.querySelector('ion-action-sheet-controller');
await actionSheetController.componentOnReady();
const actionSheetElement = await actionSheetController.create({
header: "Albums",
buttons: [{
@@ -103,13 +102,11 @@
async function presentAlert() {
const actionSheetController = document.querySelector('ion-action-sheet-controller');
await actionSheetController.componentOnReady();
const actionSheetElement = await actionSheetController.create({
buttons: [{
text: 'Open Alert',
handler: async () => {
const alertController = document.querySelector('ion-alert-controller');
await alertController.componentOnReady();
const alert = await alertController.create({
header: 'Alert from Action Sheet',
subHeader: 'Subtitle',
@@ -138,7 +135,6 @@
async function presentCancelOnly() {
const actionSheetController = document.querySelector('ion-action-sheet-controller');
await actionSheetController.componentOnReady();
const actionSheetElement = await actionSheetController.create({
buttons: [
{
@@ -155,7 +151,6 @@
async function presentWithCssClass() {
const actionSheetController = document.querySelector('ion-action-sheet-controller');
await actionSheetController.componentOnReady();
const actionSheetElement = await actionSheetController.create({
header: "Custom Css Class",
cssClass: "my-color-class my-custom-class",
@@ -206,7 +201,6 @@
const mode = Ionic.mode;
const actionSheetController = document.querySelector('ion-action-sheet-controller');
await actionSheetController.componentOnReady();
const actionSheetElement = await actionSheetController.create({
header: "Albums",
buttons: [{
@@ -249,7 +243,6 @@
async function presentNoBackdropDismiss() {
const actionSheetController = document.querySelector('ion-action-sheet-controller');
await actionSheetController.componentOnReady();
const actionSheetElement = await actionSheetController.create({
backdropDismiss: false,
buttons: [{
@@ -276,7 +269,6 @@
async function presentScroll() {
const actionSheetController = document.querySelector('ion-action-sheet-controller');
await actionSheetController.componentOnReady();
const actionSheetElement = await actionSheetController.create({
buttons: [
{
@@ -370,7 +362,6 @@
async function presentScrollNoCancel() {
const actionSheetController = document.querySelector('ion-action-sheet-controller');
await actionSheetController.componentOnReady();
const actionSheetElement = await actionSheetController.create({
buttons: [
{

View File

@@ -35,7 +35,6 @@
const mode = Ionic.mode;
const actionSheetController = document.querySelector('ion-action-sheet-controller');
await actionSheetController.componentOnReady();
const actionSheetElement = await actionSheetController.create({
header: "Open in",
buttons: [{

View File

@@ -41,7 +41,6 @@
window.addEventListener('ionActionSheetDidDismiss', function(e){console.log('didDismiss', e)})
async function presentBasic() {
const actionSheetController = document.querySelector('ion-action-sheet-controller');
await actionSheetController.componentOnReady();
const actionSheetElement = await actionSheetController.create({
header: "Albums",
buttons: [{
@@ -85,7 +84,6 @@
const mode = Ionic.mode;
const actionSheetController = document.querySelector('ion-action-sheet-controller');
await actionSheetController.componentOnReady();
const actionSheetElement = await actionSheetController.create({
header: "Albums",
buttons: [{
@@ -127,7 +125,6 @@
async function presentNoBackdropDismiss() {
const actionSheetController = document.querySelector('ion-action-sheet-controller');
await actionSheetController.componentOnReady();
const actionSheetElement = await actionSheetController.create({
buttons: [{
text: 'Archive',
@@ -153,7 +150,6 @@
async function presentAlert() {
const actionSheetController = document.querySelector('ion-action-sheet-controller');
await actionSheetController.componentOnReady();
const actionSheetElement = await actionSheetController.create({
buttons: [{
text: 'Open Alert',
@@ -173,7 +169,6 @@
async function presentScroll() {
const actionSheetController = document.querySelector('ion-action-sheet-controller');
await actionSheetController.componentOnReady();
const actionSheetElement = await actionSheetController.create({
buttons: [
{
@@ -251,7 +246,6 @@
async function presentScrollNoCancel() {
const actionSheetController = document.querySelector('ion-action-sheet-controller');
await actionSheetController.componentOnReady();
const actionSheetElement = await actionSheetController.create({
buttons: [
{
@@ -323,7 +317,6 @@
async function presentCancelOnly() {
const actionSheetController = document.querySelector('ion-action-sheet-controller');
await actionSheetController.componentOnReady();
const actionSheetElement = await actionSheetController.create({
buttons: [
{
@@ -340,7 +333,6 @@
async function presentWithCssClass() {
const actionSheetController = document.querySelector('ion-action-sheet-controller');
await actionSheetController.componentOnReady();
const actionSheetElement = await actionSheetController.create({
header: "Custom Css Class",
cssClass: "my-class my-custom-class",

View File

@@ -53,8 +53,6 @@
var mode = Ionic.mode;
const actionSheetController = document.querySelector('ion-action-sheet-controller');
await actionSheetController.componentOnReady();
const actionSheetElement = await actionSheetController.create({
header: "Albums",
buttons: [{
@@ -97,7 +95,6 @@
async function presentNoBackdropDismiss() {
const actionSheetController = document.querySelector('ion-action-sheet-controller');
await actionSheetController.componentOnReady();
const actionSheetElement = await actionSheetController.create({
backdropDismiss: false,
buttons: [{
@@ -125,7 +122,6 @@
async function presentAlert() {
const actionSheetController = document.querySelector('ion-action-sheet-controller');
await actionSheetController.componentOnReady();
const actionSheetElement = await actionSheetController.create({
buttons: [{
text: 'Open Alert',
@@ -146,7 +142,6 @@
async function presentScroll() {
const actionSheetController = document.querySelector('ion-action-sheet-controller');
await actionSheetController.componentOnReady();
const actionSheetElement = await actionSheetController.create({
buttons: [
{
@@ -227,7 +222,6 @@
async function presentScrollNoCancel() {
const actionSheetController = document.querySelector('ion-action-sheet-controller');
await actionSheetController.componentOnReady();
const actionSheetElement = await actionSheetController.create({
buttons: [
{
@@ -300,7 +294,6 @@
async function presentCancelOnly() {
const actionSheetController = document.querySelector('ion-action-sheet-controller');
await actionSheetController.componentOnReady();
const actionSheetElement = await actionSheetController.create({
buttons: [
{

View File

@@ -1,7 +1,6 @@
```javascript
async function presentActionSheet() {
const actionSheetController = document.querySelector('ion-action-sheet-controller');
await actionSheetController.componentOnReady();
const actionSheet = await actionSheetController.create({
header: "Albums",

View File

@@ -1,4 +1,4 @@
import { Component, ComponentInterface, Element, Event, EventEmitter, Listen, Method, Prop, Watch, h } from '@stencil/core';
import { Component, ComponentInterface, Element, Event, EventEmitter, Host, Method, Prop, Watch, h } from '@stencil/core';
import { getIonMode } from '../../global/ionic-global';
import { AlertButton, AlertInput, Animation, AnimationBuilder, CssClassMap, OverlayEventDetail, OverlayInterface } from '../../interface';
@@ -168,20 +168,6 @@ export class Alert implements ComponentInterface, OverlayInterface {
this.buttonsChanged();
}
@Listen('ionBackdropTap')
protected onBackdropTap() {
this.dismiss(undefined, BACKDROP);
}
@Listen('ionAlertWillDismiss')
protected dispatchCancelHandler(ev: CustomEvent) {
const role = ev.detail.role;
if (isCancel(role)) {
const cancelButton = this.processedButtons.find(b => b.role === 'cancel');
this.callButtonHandler(cancelButton);
}
}
/**
* Present the alert overlay after it has been created.
*/
@@ -391,21 +377,16 @@ export class Alert implements ComponentInterface, OverlayInterface {
);
}
hostData() {
const mode = getIonMode(this);
private onBackdropTap = () => {
this.dismiss(undefined, BACKDROP);
}
return {
'role': 'dialog',
'aria-modal': 'true',
style: {
zIndex: 20000 + this.overlayIndex,
},
class: {
...getClassMap(this.cssClass),
[mode]: true,
'alert-translucent': this.translucent
}
};
private dispatchCancelHandler = (ev: CustomEvent) => {
const role = ev.detail.role;
if (isCancel(role)) {
const cancelButton = this.processedButtons.find(b => b.role === 'cancel');
this.callButtonHandler(cancelButton);
}
}
private renderAlertButtons() {
@@ -430,34 +411,52 @@ export class Alert implements ComponentInterface, OverlayInterface {
}
render() {
const hdrId = `alert-${this.overlayIndex}-hdr`;
const subHdrId = `alert-${this.overlayIndex}-sub-hdr`;
const msgId = `alert-${this.overlayIndex}-msg`;
const { overlayIndex, header, subHeader } = this;
const mode = getIonMode(this);
const hdrId = `alert-${overlayIndex}-hdr`;
const subHdrId = `alert-${overlayIndex}-sub-hdr`;
const msgId = `alert-${overlayIndex}-msg`;
let labelledById: string | undefined;
if (this.header !== undefined) {
if (header !== undefined) {
labelledById = hdrId;
} else if (this.subHeader !== undefined) {
} else if (subHeader !== undefined) {
labelledById = subHdrId;
}
return [
<ion-backdrop tappable={this.backdropDismiss}/>,
return (
<Host
role="dialog"
aria-modal="true"
style={{
zIndex: `${20000 + overlayIndex}`,
}}
class={{
...getClassMap(this.cssClass),
[mode]: true,
'alert-translucent': this.translucent
}}
onIonAlertWillDismiss={this.dispatchCancelHandler}
onIonBackdropTap={this.onBackdropTap}
>
<div class="alert-wrapper">
<ion-backdrop tappable={this.backdropDismiss}/>
<div class="alert-wrapper">
<div class="alert-head">
{header && <h2 id={hdrId} class="alert-title">{header}</h2>}
{subHeader && <h2 id={subHdrId} class="alert-sub-title">{subHeader}</h2>}
</div>
<div id={msgId} class="alert-message" innerHTML={sanitizeDOMString(this.message)}></div>
{this.renderAlertInputs(labelledById)}
{this.renderAlertButtons()}
<div class="alert-head">
{this.header && <h2 id={hdrId} class="alert-title">{this.header}</h2>}
{this.subHeader && <h2 id={subHdrId} class="alert-sub-title">{this.subHeader}</h2>}
</div>
<div id={msgId} class="alert-message" innerHTML={sanitizeDOMString(this.message)}></div>
{this.renderAlertInputs(labelledById)}
{this.renderAlertButtons()}
</div>
];
</Host>
);
}
}

View File

@@ -289,7 +289,6 @@ export class AlertExample {
```javascript
async function presentAlert() {
const alertController = document.querySelector('ion-alert-controller');
await alertController.componentOnReady();
const alert = await alertController.create({
header: 'Alert',
@@ -302,7 +301,6 @@ async function presentAlert() {
async function presentAlertMultipleButtons() {
const alertController = document.querySelector('ion-alert-controller');
await alertController.componentOnReady();
const alert = await alertController.create({
header: 'Alert',
@@ -315,7 +313,6 @@ async function presentAlertMultipleButtons() {
async function presentAlertConfirm() {
const alertController = document.querySelector('ion-alert-controller');
await alertController.componentOnReady();
const alert = await alertController.create({
header: 'Confirm!',
@@ -341,7 +338,6 @@ async function presentAlertConfirm() {
async function presentAlertPrompt() {
const alertController = document.querySelector('ion-alert-controller');
await alertController.componentOnReady();
const alert = await alertController.create({
header: 'Prompt!',
@@ -405,7 +401,6 @@ async function presentAlertPrompt() {
async function presentAlertRadio() {
const alertController = document.querySelector('ion-alert-controller');
await alertController.componentOnReady();
const alert = await alertController.create({
header: 'Radio',
@@ -463,7 +458,6 @@ async function presentAlertRadio() {
async function presentAlertCheckbox() {
const alertController = document.querySelector('ion-alert-controller');
await alertController.componentOnReady();
const alert = await alertController.create({
header: 'Checkbox',

View File

@@ -50,8 +50,6 @@
async function presentAlert() {
const alertController = document.querySelector('ion-alert-controller');
await alertController.componentOnReady();
const alert = await alertController.create({
header: 'Alert',
subHeader: 'Subtitle',
@@ -63,7 +61,6 @@
async function presentAlertLongMessage() {
const alertController = document.querySelector('ion-alert-controller');
await alertController.componentOnReady();
const alert = await alertController.create({
header: 'Alert',
message: 'Lorem ipsum dolor sit amet, consectetur adipiscing elit. Vestibulum hendrerit diam lorem, a faucibus turpis sagittis eu. In finibus augue in dui varius convallis. Donec vulputate nibh gravida odio vulputate commodo. Suspendisse imperdiet consequat egestas. Nulla feugiat consequat urna eu tincidunt. Cras nec blandit turpis, eu auctor nunc. Pellentesque finibus, magna eu vestibulum imperdiet, arcu ex lacinia massa, eget volutpat quam leo a orci. Etiam mauris est, elementum at feugiat at, dictum in sapien. Mauris efficitur eros sodales convallis egestas. Phasellus eu faucibus nisl. In eu diam vitae libero egestas lacinia. Integer sed convallis metus, nec commodo felis. Duis libero augue, ornare at tempus non, posuere vel augue. Cras mattis dui at tristique aliquam. Phasellus fermentum nibh ligula, porta hendrerit ligula elementum eu. Suspendisse sollicitudin enim at libero iaculis pulvinar. Donec ac massa id purus laoreet rutrum quis eu urna. Mauris luctus erat vel magna porttitor, vel varius erat rhoncus. Donec eu turpis vestibulum, feugiat urna id, gravida mauris. Lorem ipsum dolor sit amet, consectetur adipiscing elit. Integer at lobortis tortor. Nam ultrices volutpat elit, sed pharetra nulla suscipit at. Nunc eu accumsan eros, id auctor libero. Suspendisse potenti. Nam vitae dapibus metus. Maecenas nisi dui, sagittis et condimentum eu, bibendum vel eros. Vivamus malesuada, tortor in accumsan iaculis, urna velit consectetur ante, nec semper sem diam a diam. In et semper ante. Lorem ipsum dolor sit amet, consectetur adipiscing elit. Phasellus blandit, velit vel porttitor euismod, neque risus blandit nulla, non laoreet libero dolor et odio. Nulla enim risus, feugiat eu urna sed, ultrices semper felis. Sed blandit mi diam. Nunc quis mi ligula. Pellentesque a elit eu orci volutpat egestas. Aenean fermentum eleifend quam, ut tincidunt eros tristique et. Nam dapibus tincidunt ligula, id faucibus felis sodales quis. Donec tincidunt lectus ipsum, ac semper tellus cursus ac. Vestibulum nec dui a lectus accumsan vestibulum quis et velit. Aliquam finibus justo et odio euismod, viverra condimentum eros tristique. Sed eget luctus risus. Pellentesque lorem magna, dictum non congue sodales, laoreet eget quam. In sagittis vulputate dolor a ultricies. Donec viverra leo sed ex maximus, in finibus elit gravida. Aliquam posuere vulputate mi. Suspendisse potenti. Nunc consectetur congue arcu, at pharetra dui varius non. Etiam vestibulum congue felis, id ullamcorper neque convallis ultrices. Aenean congue, diam a iaculis mollis, nisl eros maximus arcu, nec hendrerit purus felis porta diam. Nullam vitae ultrices dui, ac dictum sapien. Phasellus eu magna luctus, varius urna id, molestie quam. Nulla in semper tellus. Curabitur lacinia tellus sit amet lacinia dapibus. Sed id condimentum tellus, nec aliquam sapien. Vivamus luctus at ante a tincidunt.',
@@ -74,7 +71,6 @@
async function presentAlertMultipleButtons() {
const alertController = document.querySelector('ion-alert-controller');
await alertController.componentOnReady();
const alert = await alertController.create({
header: 'Alert',
subHeader: 'Subtitle',
@@ -86,7 +82,6 @@
async function presentAlertNoMessage() {
const alertController = document.querySelector('ion-alert-controller');
await alertController.componentOnReady();
const alert = await alertController.create({
header: 'Alert',
buttons: ['OK']
@@ -96,7 +91,6 @@
async function presentAlertConfirm() {
const alertController = document.querySelector('ion-alert-controller');
await alertController.componentOnReady();
const alert = await alertController.create({
header: 'Confirm!',
message: 'Message <strong>text</strong>!!!',
@@ -121,7 +115,6 @@
async function presentAlertPrompt() {
const alertController = document.querySelector('ion-alert-controller');
await alertController.componentOnReady();
const alert = await alertController.create({
header: 'Prompt!',
inputs: [
@@ -187,7 +180,6 @@
async function presentAlertRadio() {
const alertController = document.querySelector('ion-alert-controller');
await alertController.componentOnReady();
const alert = await alertController.create({
header: 'Radio',
inputs: [
@@ -243,10 +235,7 @@
}
async function presentAlertCheckbox() {
const alertController = document.querySelector('ion-alert-controller');
await alertController.componentOnReady();
const alert = await alertController.create({
header: 'Checkbox',
inputs: [
@@ -308,7 +297,6 @@
async function presentWithCssClass() {
const alertController = document.querySelector('ion-alert-controller');
await alertController.componentOnReady();
const alert = await alertController.create({
header: 'Alert',
subHeader: 'Subtitle',

View File

@@ -78,8 +78,7 @@
window.addEventListener('ionAlertWillDismiss', function(e){console.log('willDismiss', e)})
async function presentAlert() {
var alertController = document.querySelector('ion-alert-controller');
await alertController.componentOnReady();
const alertController = document.querySelector('ion-alert-controller');
const alert = await alertController.create({
header: 'Alert',
subHeader: 'Subtitle',
@@ -90,8 +89,7 @@
}
async function presentAlertLongMessage() {
var alertController = document.querySelector('ion-alert-controller');
await alertController.componentOnReady();
const alertController = document.querySelector('ion-alert-controller');
const alert = await alertController.create({
header: 'Alert',
message: 'Lorem ipsum dolor sit amet, consectetur adipiscing elit. Vestibulum hendrerit diam lorem, a faucibus turpis sagittis eu. In finibus augue in dui varius convallis. Donec vulputate nibh gravida odio vulputate commodo. Suspendisse imperdiet consequat egestas. Nulla feugiat consequat urna eu tincidunt. Cras nec blandit turpis, eu auctor nunc. Pellentesque finibus, magna eu vestibulum imperdiet, arcu ex lacinia massa, eget volutpat quam leo a orci. Etiam mauris est, elementum at feugiat at, dictum in sapien. Mauris efficitur eros sodales convallis egestas. Phasellus eu faucibus nisl. In eu diam vitae libero egestas lacinia. Integer sed convallis metus, nec commodo felis. Duis libero augue, ornare at tempus non, posuere vel augue. Cras mattis dui at tristique aliquam. Phasellus fermentum nibh ligula, porta hendrerit ligula elementum eu. Suspendisse sollicitudin enim at libero iaculis pulvinar. Donec ac massa id purus laoreet rutrum quis eu urna. Mauris luctus erat vel magna porttitor, vel varius erat rhoncus. Donec eu turpis vestibulum, feugiat urna id, gravida mauris. Lorem ipsum dolor sit amet, consectetur adipiscing elit. Integer at lobortis tortor. Nam ultrices volutpat elit, sed pharetra nulla suscipit at. Nunc eu accumsan eros, id auctor libero. Suspendisse potenti. Nam vitae dapibus metus. Maecenas nisi dui, sagittis et condimentum eu, bibendum vel eros. Vivamus malesuada, tortor in accumsan iaculis, urna velit consectetur ante, nec semper sem diam a diam. In et semper ante. Lorem ipsum dolor sit amet, consectetur adipiscing elit. Phasellus blandit, velit vel porttitor euismod, neque risus blandit nulla, non laoreet libero dolor et odio. Nulla enim risus, feugiat eu urna sed, ultrices semper felis. Sed blandit mi diam. Nunc quis mi ligula. Pellentesque a elit eu orci volutpat egestas. Aenean fermentum eleifend quam, ut tincidunt eros tristique et. Nam dapibus tincidunt ligula, id faucibus felis sodales quis. Donec tincidunt lectus ipsum, ac semper tellus cursus ac. Vestibulum nec dui a lectus accumsan vestibulum quis et velit. Aliquam finibus justo et odio euismod, viverra condimentum eros tristique. Sed eget luctus risus. Pellentesque lorem magna, dictum non congue sodales, laoreet eget quam. In sagittis vulputate dolor a ultricies. Donec viverra leo sed ex maximus, in finibus elit gravida. Aliquam posuere vulputate mi. Suspendisse potenti. Nunc consectetur congue arcu, at pharetra dui varius non. Etiam vestibulum congue felis, id ullamcorper neque convallis ultrices. Aenean congue, diam a iaculis mollis, nisl eros maximus arcu, nec hendrerit purus felis porta diam. Nullam vitae ultrices dui, ac dictum sapien. Phasellus eu magna luctus, varius urna id, molestie quam. Nulla in semper tellus. Curabitur lacinia tellus sit amet lacinia dapibus. Sed id condimentum tellus, nec aliquam sapien. Vivamus luctus at ante a tincidunt.',
@@ -101,8 +99,7 @@
}
async function presentAlertMultipleButtons() {
var alertController = document.querySelector('ion-alert-controller');
await alertController.componentOnReady();
const alertController = document.querySelector('ion-alert-controller');
const alert = await alertController.create({
header: 'Alert',
subHeader: 'Subtitle',
@@ -113,8 +110,7 @@
}
async function presentAlertNoMessage() {
var alertController = document.querySelector('ion-alert-controller');
await alertController.componentOnReady();
const alertController = document.querySelector('ion-alert-controller');
const alert = await alertController.create({
header: 'Alert',
buttons: ['OK']
@@ -123,8 +119,7 @@
}
async function presentAlertConfirm() {
var alertController = document.querySelector('ion-alert-controller');
await alertController.componentOnReady();
const alertController = document.querySelector('ion-alert-controller');
const alert = await alertController.create({
header: 'Confirm!',
message: 'Message <strong>text</strong>!!!',
@@ -148,8 +143,7 @@
}
async function presentAlertPrompt() {
var alertController = document.querySelector('ion-alert-controller');
await alertController.componentOnReady();
const alertController = document.querySelector('ion-alert-controller');
const alert = await alertController.create({
header: 'Prompt!',
inputs: [
@@ -211,8 +205,7 @@
}
async function presentAlertRadio() {
var alertController = document.querySelector('ion-alert-controller');
await alertController.componentOnReady();
const alertController = document.querySelector('ion-alert-controller');
const alert = await alertController.create({
header: 'Radio',
inputs: [
@@ -268,10 +261,7 @@
}
async function presentAlertCheckbox() {
var alertController = document.querySelector('ion-alert-controller');
await alertController.componentOnReady();
const alertController = document.querySelector('ion-alert-controller');
const alert = await alertController.create({
header: 'Checkbox',
inputs: [
@@ -332,8 +322,7 @@
}
async function presentWithCssClass() {
var alertController = document.querySelector('ion-alert-controller');
await alertController.componentOnReady();
const alertController = document.querySelector('ion-alert-controller');
const alert = await alertController.create({
header: 'Alert',
subHeader: 'Subtitle',

View File

@@ -54,8 +54,7 @@
async function presentAlert() {
var alertController = document.querySelector('ion-alert-controller');
await alertController.componentOnReady();
const alertController = document.querySelector('ion-alert-controller');
const alert = await alertController.create({
header: 'Alert',
subHeader: 'Subtitle',
@@ -67,8 +66,7 @@
}
async function presentAlertLongMessage() {
var alertController = document.querySelector('ion-alert-controller');
await alertController.componentOnReady();
const alertController = document.querySelector('ion-alert-controller');
const alert = await alertController.create({
header: 'Alert',
message: 'Lorem ipsum dolor sit amet, consectetur adipiscing elit. Vestibulum hendrerit diam lorem, a faucibus turpis sagittis eu. In finibus augue in dui varius convallis. Donec vulputate nibh gravida odio vulputate commodo. Suspendisse imperdiet consequat egestas. Nulla feugiat consequat urna eu tincidunt. Cras nec blandit turpis, eu auctor nunc. Pellentesque finibus, magna eu vestibulum imperdiet, arcu ex lacinia massa, eget volutpat quam leo a orci. Etiam mauris est, elementum at feugiat at, dictum in sapien. Mauris efficitur eros sodales convallis egestas. Phasellus eu faucibus nisl. In eu diam vitae libero egestas lacinia. Integer sed convallis metus, nec commodo felis. Duis libero augue, ornare at tempus non, posuere vel augue. Cras mattis dui at tristique aliquam. Phasellus fermentum nibh ligula, porta hendrerit ligula elementum eu. Suspendisse sollicitudin enim at libero iaculis pulvinar. Donec ac massa id purus laoreet rutrum quis eu urna. Mauris luctus erat vel magna porttitor, vel varius erat rhoncus. Donec eu turpis vestibulum, feugiat urna id, gravida mauris. Lorem ipsum dolor sit amet, consectetur adipiscing elit. Integer at lobortis tortor. Nam ultrices volutpat elit, sed pharetra nulla suscipit at. Nunc eu accumsan eros, id auctor libero. Suspendisse potenti. Nam vitae dapibus metus. Maecenas nisi dui, sagittis et condimentum eu, bibendum vel eros. Vivamus malesuada, tortor in accumsan iaculis, urna velit consectetur ante, nec semper sem diam a diam. In et semper ante. Lorem ipsum dolor sit amet, consectetur adipiscing elit. Phasellus blandit, velit vel porttitor euismod, neque risus blandit nulla, non laoreet libero dolor et odio. Nulla enim risus, feugiat eu urna sed, ultrices semper felis. Sed blandit mi diam. Nunc quis mi ligula. Pellentesque a elit eu orci volutpat egestas. Aenean fermentum eleifend quam, ut tincidunt eros tristique et. Nam dapibus tincidunt ligula, id faucibus felis sodales quis. Donec tincidunt lectus ipsum, ac semper tellus cursus ac. Vestibulum nec dui a lectus accumsan vestibulum quis et velit. Aliquam finibus justo et odio euismod, viverra condimentum eros tristique. Sed eget luctus risus. Pellentesque lorem magna, dictum non congue sodales, laoreet eget quam. In sagittis vulputate dolor a ultricies. Donec viverra leo sed ex maximus, in finibus elit gravida. Aliquam posuere vulputate mi. Suspendisse potenti. Nunc consectetur congue arcu, at pharetra dui varius non. Etiam vestibulum congue felis, id ullamcorper neque convallis ultrices. Aenean congue, diam a iaculis mollis, nisl eros maximus arcu, nec hendrerit purus felis porta diam. Nullam vitae ultrices dui, ac dictum sapien. Phasellus eu magna luctus, varius urna id, molestie quam. Nulla in semper tellus. Curabitur lacinia tellus sit amet lacinia dapibus. Sed id condimentum tellus, nec aliquam sapien. Vivamus luctus at ante a tincidunt.',
@@ -79,8 +77,7 @@
}
async function presentAlertMultipleButtons() {
var alertController = document.querySelector('ion-alert-controller');
await alertController.componentOnReady();
const alertController = document.querySelector('ion-alert-controller');
const alert = await alertController.create({
header: 'Alert',
subHeader: 'Subtitle',
@@ -92,8 +89,7 @@
}
async function presentAlertNoMessage() {
var alertController = document.querySelector('ion-alert-controller');
await alertController.componentOnReady();
const alertController = document.querySelector('ion-alert-controller');
const alert = await alertController.create({
header: 'Alert',
buttons: ['OK'],
@@ -103,8 +99,7 @@
}
async function presentAlertConfirm() {
var alertController = document.querySelector('ion-alert-controller');
await alertController.componentOnReady();
const alertController = document.querySelector('ion-alert-controller');
const alert = await alertController.create({
header: 'Confirm!',
message: 'Message <strong>text</strong>!!!',
@@ -129,8 +124,7 @@
}
async function presentAlertPrompt() {
var alertController = document.querySelector('ion-alert-controller');
await alertController.componentOnReady();
const alertController = document.querySelector('ion-alert-controller');
const alert = await alertController.create({
header: 'Prompt!',
inputs: [
@@ -193,8 +187,7 @@
}
async function presentAlertRadio() {
var alertController = document.querySelector('ion-alert-controller');
await alertController.componentOnReady();
const alertController = document.querySelector('ion-alert-controller');
const alert = await alertController.create({
header: 'Radio',
inputs: [
@@ -252,9 +245,7 @@
async function presentAlertCheckbox() {
var alertController = document.querySelector('ion-alert-controller');
await alertController.componentOnReady();
const alertController = document.querySelector('ion-alert-controller');
const alert = await alertController.create({
header: 'Checkbox',
inputs: [

View File

@@ -1,7 +1,6 @@
```javascript
async function presentAlert() {
const alertController = document.querySelector('ion-alert-controller');
await alertController.componentOnReady();
const alert = await alertController.create({
header: 'Alert',
@@ -14,7 +13,6 @@ async function presentAlert() {
async function presentAlertMultipleButtons() {
const alertController = document.querySelector('ion-alert-controller');
await alertController.componentOnReady();
const alert = await alertController.create({
header: 'Alert',
@@ -27,7 +25,6 @@ async function presentAlertMultipleButtons() {
async function presentAlertConfirm() {
const alertController = document.querySelector('ion-alert-controller');
await alertController.componentOnReady();
const alert = await alertController.create({
header: 'Confirm!',
@@ -53,7 +50,6 @@ async function presentAlertConfirm() {
async function presentAlertPrompt() {
const alertController = document.querySelector('ion-alert-controller');
await alertController.componentOnReady();
const alert = await alertController.create({
header: 'Prompt!',
@@ -117,7 +113,6 @@ async function presentAlertPrompt() {
async function presentAlertRadio() {
const alertController = document.querySelector('ion-alert-controller');
await alertController.componentOnReady();
const alert = await alertController.create({
header: 'Radio',
@@ -175,7 +170,6 @@ async function presentAlertRadio() {
async function presentAlertCheckbox() {
const alertController = document.querySelector('ion-alert-controller');
await alertController.componentOnReady();
const alert = await alertController.create({
header: 'Checkbox',

View File

@@ -1,4 +1,4 @@
import { Component, ComponentInterface, Element } from '@stencil/core';
import { Component, ComponentInterface, Element, Host, h } from '@stencil/core';
import { config } from '../../global/config';
import { getIonMode } from '../../global/ionic-global';
@@ -33,16 +33,18 @@ export class App implements ComponentInterface {
});
}
hostData() {
render() {
const mode = getIonMode(this);
return {
class: {
[mode]: true,
'ion-page': true,
'force-statusbar-padding': config.getBoolean('_forceStatusbarPadding')
}
};
return (
<Host
class={{
[mode]: true,
'ion-page': true,
'force-statusbar-padding': config.getBoolean('_forceStatusbarPadding')
}}
>
</Host>
);
}
}

View File

@@ -1,4 +1,4 @@
import { Component, ComponentInterface, h } from '@stencil/core';
import { Component, ComponentInterface, Host, h } from '@stencil/core';
import { getIonMode } from '../../global/ionic-global';
@@ -12,18 +12,12 @@ import { getIonMode } from '../../global/ionic-global';
})
export class Avatar implements ComponentInterface {
hostData() {
const mode = getIonMode(this);
return {
class: {
[mode]: true,
}
};
}
render() {
return <slot></slot>;
return (
<Host class={getIonMode(this)}>
<slot></slot>
</Host>
);
}
}

View File

@@ -21,7 +21,6 @@
async function loadFirstPage() {
const nav = document.querySelector('ion-nav');
await nav.componentOnReady();
const firstPage = document.createElement('div');
firstPage.classList.add('first-page');
firstPage.innerHTML = `

View File

@@ -1,4 +1,4 @@
import { Component, ComponentInterface, Event, EventEmitter, Listen, Prop } from '@stencil/core';
import { Component, ComponentInterface, Event, EventEmitter, Host, Listen, Prop, h } from '@stencil/core';
import { getIonMode } from '../../global/ionic-global';
import { GESTURE_CONTROLLER } from '../../utils/gesture';
@@ -73,16 +73,18 @@ export class Backdrop implements ComponentInterface {
}
}
hostData() {
render() {
const mode = getIonMode(this);
return {
tabindex: '-1',
class: {
[mode]: true,
'backdrop-hide': !this.visible,
'backdrop-no-tappable': !this.tappable,
}
};
return (
<Host
tabindex="-1"
class={{
[mode]: true,
'backdrop-hide': !this.visible,
'backdrop-no-tappable': !this.tappable,
}}
>
</Host>
);
}
}

View File

@@ -1,4 +1,4 @@
import { Component, ComponentInterface, Prop, h } from '@stencil/core';
import { Component, ComponentInterface, Host, Prop, h } from '@stencil/core';
import { getIonMode } from '../../global/ionic-global';
import { Color } from '../../interface';
@@ -23,18 +23,17 @@ export class Badge implements ComponentInterface {
*/
@Prop() color?: Color;
hostData() {
const mode = getIonMode(this);
return {
class: {
...createColorClasses(this.color),
[mode]: true
}
};
}
render() {
return <slot></slot>;
const mode = getIonMode(this);
return (
<Host
class={{
...createColorClasses(this.color),
[mode]: true,
}}
>
<slot></slot>
</Host>
);
}
}

View File

@@ -1,4 +1,4 @@
import { Component, ComponentInterface } from '@stencil/core';
import { Component, ComponentInterface, Host, h } from '@stencil/core';
import { getIonMode } from '../../global/ionic-global';
@@ -12,12 +12,10 @@ import { getIonMode } from '../../global/ionic-global';
})
export class Buttons implements ComponentInterface {
hostData() {
const mode = getIonMode(this);
return {
class: {
[mode]: true
}
};
render() {
return (
<Host class={getIonMode(this)}>
</Host>
);
}
}

View File

@@ -1,4 +1,4 @@
import { Component, ComponentInterface } from '@stencil/core';
import { Component, ComponentInterface, Host, h } from '@stencil/core';
import { getIonMode } from '../../global/ionic-global';
@@ -14,15 +14,18 @@ import { getIonMode } from '../../global/ionic-global';
})
export class CardContent implements ComponentInterface {
hostData() {
render() {
const mode = getIonMode(this);
return {
class: {
[mode]: true,
return (
<Host
class={{
[mode]: true,
// Used internally for styling
[`card-content-${mode}`]: true
}
};
// Used internally for styling
[`card-content-${mode}`]: true
}}
>
</Host>
);
}
}

View File

@@ -1,4 +1,4 @@
import { Component, ComponentInterface, Prop, h } from '@stencil/core';
import { Component, ComponentInterface, Host, Prop, h } from '@stencil/core';
import { getIonMode } from '../../global/ionic-global';
import { Color } from '../../interface';
@@ -30,18 +30,19 @@ export class CardHeader implements ComponentInterface {
*/
@Prop() translucent = false;
hostData() {
render() {
const mode = getIonMode(this);
return {
class: {
...createColorClasses(this.color),
'card-header-translucent': this.translucent,
[mode]: true
}
};
return (
<Host
class={{
...createColorClasses(this.color),
'card-header-translucent': this.translucent,
[mode]: true
}}
>
<slot></slot>
</Host>
);
}
render() {
return <slot></slot>;
}
}

View File

@@ -1,4 +1,4 @@
import { Component, ComponentInterface, Prop, h } from '@stencil/core';
import { Component, ComponentInterface, Host, Prop, h } from '@stencil/core';
import { getIonMode } from '../../global/ionic-global';
import { Color } from '../../interface';
@@ -23,19 +23,19 @@ export class CardSubtitle implements ComponentInterface {
*/
@Prop() color?: Color;
hostData() {
const mode = getIonMode(this);
return {
class: {
...createColorClasses(this.color),
[mode]: true
},
'role': 'heading',
'aria-level': '3'
};
}
render() {
return <slot></slot>;
const mode = getIonMode(this);
return (
<Host
role="heading"
aria-level="3"
class={{
...createColorClasses(this.color),
[mode]: true,
}}
>
<slot></slot>
</Host>
);
}
}

View File

@@ -1,4 +1,4 @@
import { Component, ComponentInterface, Prop, h } from '@stencil/core';
import { Component, ComponentInterface, Host, Prop, h } from '@stencil/core';
import { getIonMode } from '../../global/ionic-global';
import { Color } from '../../interface';
@@ -23,19 +23,19 @@ export class CardTitle implements ComponentInterface {
*/
@Prop() color?: Color;
hostData() {
const mode = getIonMode(this);
return {
class: {
...createColorClasses(this.color),
[mode]: true
},
'role': 'heading',
'aria-level': '2'
};
}
render() {
return <slot></slot>;
const mode = getIonMode(this);
return (
<Host
role="heading"
aria-level="2"
class={{
...createColorClasses(this.color),
[mode]: true
}}
>
<slot></slot>;
</Host>
);
}
}

View File

@@ -1,7 +1,7 @@
import { Component, ComponentInterface, Prop, h } from '@stencil/core';
import { Component, ComponentInterface, Host, Prop, h } from '@stencil/core';
import { getIonMode } from '../../global/ionic-global';
import { Color, RouterDirection } from '../../interface';
import { Color, Mode, RouterDirection } from '../../interface';
import { AnchorInterface, ButtonInterface } from '../../utils/element-interface';
import { createColorClasses, openURL } from '../../utils/theme';
@@ -77,20 +77,7 @@ export class Card implements ComponentInterface, AnchorInterface, ButtonInterfac
return (this.href !== undefined || this.button);
}
hostData() {
const mode = getIonMode(this);
return {
class: {
[mode]: true,
...createColorClasses(this.color),
'card-disabled': this.disabled,
'ion-activatable': this.isClickable()
}
};
}
render() {
private renderCard(mode: Mode) {
const clickable = this.isClickable();
if (!clickable) {
@@ -98,7 +85,6 @@ export class Card implements ComponentInterface, AnchorInterface, ButtonInterfac
<slot></slot>
];
}
const mode = getIonMode(this);
const { href, routerDirection } = this;
const TagType = clickable ? (href === undefined ? 'button' : 'a') : 'div' as any;
const attrs = (TagType === 'button')
@@ -122,4 +108,21 @@ export class Card implements ComponentInterface, AnchorInterface, ButtonInterfac
</TagType>
);
}
render() {
const mode = getIonMode(this);
return (
<Host
class={{
[mode]: true,
...createColorClasses(this.color),
'card-disabled': this.disabled,
'ion-activatable': this.isClickable()
}}
>
{this.renderCard(mode)}
</Host>
);
}
}

View File

@@ -1,4 +1,4 @@
import { Component, ComponentInterface, Prop, h } from '@stencil/core';
import { Component, ComponentInterface, Host, Prop, h } from '@stencil/core';
import { getIonMode } from '../../global/ionic-global';
import { Color } from '../../interface';
@@ -28,24 +28,21 @@ export class Chip implements ComponentInterface {
*/
@Prop() outline = false;
hostData() {
const mode = getIonMode(this);
return {
class: {
...createColorClasses(this.color),
[mode]: true,
'chip-outline': this.outline,
'ion-activatable': true,
}
};
}
render() {
const mode = getIonMode(this);
return [
<slot></slot>,
mode === 'md' ? <ion-ripple-effect></ion-ripple-effect> : null
];
return (
<Host
class={{
...createColorClasses(this.color),
[mode]: true,
'chip-outline': this.outline,
'ion-activatable': true,
}}
>
<slot></slot>
{mode === 'md' && <ion-ripple-effect></ion-ripple-effect>}
</Host>
);
}
}

View File

@@ -1,4 +1,4 @@
import { Component, ComponentInterface, Element, Listen, Prop, h } from '@stencil/core';
import { Component, ComponentInterface, Element, Host, Listen, Prop, h } from '@stencil/core';
import { getIonMode } from '../../global/ionic-global';
import { matchBreakpoint } from '../../utils/media';
@@ -244,23 +244,23 @@ export class Col implements ComponentInterface {
return this.calculatePosition('push', isRTL ? 'right' : 'left');
}
hostData() {
render() {
const isRTL = document.dir === 'rtl';
const mode = getIonMode(this);
return {
class: {
[mode]: true
},
style: {
...this.calculateOffset(isRTL),
...this.calculatePull(isRTL),
...this.calculatePush(isRTL),
...this.calculateSize(),
}
};
}
render() {
return <slot></slot>;
return (
<Host
class={{
[mode]: true
}}
style={{
...this.calculateOffset(isRTL),
...this.calculatePull(isRTL),
...this.calculatePush(isRTL),
...this.calculateSize(),
}}
>
<slot></slot>
</Host>
);
}
}

View File

@@ -319,7 +319,7 @@ export class Content implements ComponentInterface {
'--offset-bottom': `${this.cBottom}px`,
}}
>
<div
<main
class={{
'inner-scroll': true,
'scroll-x': scrollX,
@@ -330,13 +330,15 @@ export class Content implements ComponentInterface {
onScroll={ev => this.onScroll(ev)}
>
<slot></slot>
</div>
</main>
{transitionShadow ? (
<div class="transition-effect">
<div class="transition-cover"></div>
<div class="transition-shadow"></div>
</div>
) : null}
<slot name="fixed"></slot>
</Host>
);

View File

@@ -1,4 +1,4 @@
import { Component, ComponentInterface, Element, Event, EventEmitter, Prop, h } from '@stencil/core';
import { Component, ComponentInterface, Element, Event, EventEmitter, Host, Prop, h } from '@stencil/core';
import { getIonMode } from '../../global/ionic-global';
import { Color, RouterDirection } from '../../interface';
@@ -109,57 +109,55 @@ export class FabButton implements ComponentInterface, AnchorInterface, ButtonInt
this.ionBlur.emit();
}
hostData() {
const { el, disabled, color, activated, show, translucent, size } = this;
render() {
const { el, disabled, color, href, activated, show, translucent, size } = this;
const inList = hostContext('ion-fab-list', el);
const mode = getIonMode(this);
return {
'aria-disabled': disabled ? 'true' : null,
class: {
...createColorClasses(color),
[mode]: true,
'fab-button-in-list': inList,
'fab-button-translucent-in-list': inList && translucent,
'fab-button-close-active': activated,
'fab-button-show': show,
'fab-button-disabled': disabled,
'fab-button-translucent': translucent,
'ion-activatable': true,
'ion-focusable': true,
[`fab-button-${size}`]: size !== undefined,
}
};
}
render() {
const mode = getIonMode(this);
const TagType = this.href === undefined ? 'button' : 'a' as any;
const TagType = href === undefined ? 'button' : 'a' as any;
const attrs = (TagType === 'button')
? { type: this.type }
: {
download: this.download,
href: this.href,
href,
rel: this.rel,
target: this.target
};
return (
<TagType
{...attrs}
class="button-native"
disabled={this.disabled}
onFocus={this.onFocus}
onBlur={this.onBlur}
onClick={(ev: Event) => openURL(this.href, ev, this.routerDirection)}
<Host
aria-disabled={disabled ? 'true' : null}
class={{
...createColorClasses(color),
[mode]: true,
'fab-button-in-list': inList,
'fab-button-translucent-in-list': inList && translucent,
'fab-button-close-active': activated,
'fab-button-show': show,
'fab-button-disabled': disabled,
'fab-button-translucent': translucent,
'ion-activatable': true,
'ion-focusable': true,
[`fab-button-${size}`]: size !== undefined,
}}
>
<span class="close-icon">
<ion-icon name="close" lazy={false}></ion-icon>
</span>
<span class="button-inner">
<slot></slot>
</span>
{mode === 'md' && <ion-ripple-effect></ion-ripple-effect>}
</TagType>
<TagType
{...attrs}
class="button-native"
disabled={disabled}
onFocus={this.onFocus}
onBlur={this.onBlur}
onClick={(ev: Event) => openURL(href, ev, this.routerDirection)}
>
<span class="close-icon">
<ion-icon name="close" lazy={false}></ion-icon>
</span>
<span class="button-inner">
<slot></slot>
</span>
{mode === 'md' && <ion-ripple-effect></ion-ripple-effect>}
</TagType>
</Host>
);
}
}

View File

@@ -1,4 +1,4 @@
import { Component, ComponentInterface, Element, Prop, Watch, h } from '@stencil/core';
import { Component, ComponentInterface, Element, Host, Prop, Watch, h } from '@stencil/core';
import { getIonMode } from '../../global/ionic-global';
@@ -32,19 +32,19 @@ export class FabList implements ComponentInterface {
*/
@Prop() side: 'start' | 'end' | 'top' | 'bottom' = 'bottom';
hostData() {
const mode = getIonMode(this);
return {
class: {
[mode]: true,
'fab-list-active': this.activated,
[`fab-list-side-${this.side}`]: true
}
};
}
render() {
return <slot></slot>;
const mode = getIonMode(this);
return (
<Host
class={{
[mode]: true,
'fab-list-active': this.activated,
[`fab-list-side-${this.side}`]: true
}}
>
<slot></slot>
</Host>
);
}
}

View File

@@ -1,4 +1,4 @@
import { Component, ComponentInterface, Prop } from '@stencil/core';
import { Component, ComponentInterface, Host, Prop, h } from '@stencil/core';
import { getIonMode } from '../../global/ionic-global';
@@ -24,18 +24,23 @@ export class Footer implements ComponentInterface {
*/
@Prop() translucent = false;
hostData() {
render() {
const mode = getIonMode(this);
return {
class: {
[mode]: true,
const translucent = this.translucent;
return (
<Host
role="contentinfo"
class={{
[mode]: true,
// Used internally for styling
[`footer-${mode}`]: true,
// Used internally for styling
[`footer-${mode}`]: true,
[`footer-translucent`]: this.translucent,
[`footer-translucent-${mode}`]: this.translucent,
}
};
[`footer-translucent`]: translucent,
[`footer-translucent-${mode}`]: translucent,
}}
>
</Host>
);
}
}

View File

@@ -1,4 +1,4 @@
import { Component, ComponentInterface, Prop, h } from '@stencil/core';
import { Component, ComponentInterface, Host, Prop, h } from '@stencil/core';
import { getIonMode } from '../../global/ionic-global';
@@ -14,17 +14,17 @@ export class Grid implements ComponentInterface {
*/
@Prop() fixed = false;
hostData() {
const mode = getIonMode(this);
return {
class: {
[mode]: true,
'grid-fixed': this.fixed
}
};
}
render() {
return <slot></slot>;
const mode = getIonMode(this);
return (
<Host
class={{
[mode]: true,
'grid-fixed': this.fixed
}}
>
<slot></slot>;
</Host>
);
}
}

View File

@@ -1,4 +1,4 @@
import { Component, ComponentInterface, Prop } from '@stencil/core';
import { Component, ComponentInterface, Host, Prop, h } from '@stencil/core';
import { getIonMode } from '../../global/ionic-global';
@@ -24,18 +24,22 @@ export class Header implements ComponentInterface {
*/
@Prop() translucent = false;
hostData() {
render() {
const mode = getIonMode(this);
return {
class: {
[mode]: true,
return (
<Host
role="banner"
class={{
[mode]: true,
// Used internally for styling
[`header-${mode}`]: true,
// Used internally for styling
[`header-${mode}`]: true,
[`header-translucent`]: this.translucent,
[`header-translucent-${mode}`]: this.translucent,
}
};
[`header-translucent`]: this.translucent,
[`header-translucent-${mode}`]: this.translucent,
}}
>
</Host>
);
}
}

View File

@@ -1,4 +1,4 @@
import { Component, ComponentInterface, Element, Event, EventEmitter, Prop, State, Watch, h } from '@stencil/core';
import { Component, ComponentInterface, Element, Event, EventEmitter, Host, Prop, State, Watch, h } from '@stencil/core';
import { getIonMode } from '../../global/ionic-global';
@@ -90,24 +90,17 @@ export class Img implements ComponentInterface {
}
}
hostData() {
const mode = getIonMode(this);
return {
class: {
[mode]: true,
}
};
}
render() {
return (
<img
src={this.loadSrc}
alt={this.alt}
decoding="async"
onLoad={this.onLoad}
onError={this.loadError}
/>
<Host class={getIonMode(this)}>
<img
decoding="async"
src={this.loadSrc}
alt={this.alt}
onLoad={this.onLoad}
onError={this.loadError}
/>
</Host>
);
}
}

View File

@@ -1,4 +1,4 @@
import { Component, ComponentInterface, Prop, h } from '@stencil/core';
import { Component, ComponentInterface, Host, Prop, h } from '@stencil/core';
import { config } from '../../global/config';
import { getIonMode } from '../../global/ionic-global';
@@ -40,30 +40,28 @@ export class InfiniteScrollContent implements ComponentInterface {
}
}
hostData() {
const mode = getIonMode(this);
return {
class: {
[mode]: true,
// Used internally for styling
[`infinite-scroll-content-${mode}`]: true
}
};
}
render() {
const mode = getIonMode(this);
return (
<div class="infinite-loading">
{this.loadingSpinner && (
<div class="infinite-loading-spinner">
<ion-spinner name={this.loadingSpinner} />
</div>
)}
{this.loadingText && (
<div class="infinite-loading-text" innerHTML={sanitizeDOMString(this.loadingText)} />
)}
</div>
<Host
class={{
[mode]: true,
// Used internally for styling
[`infinite-scroll-content-${mode}`]: true
}}
>
<div class="infinite-loading">
{this.loadingSpinner && (
<div class="infinite-loading-spinner">
<ion-spinner name={this.loadingSpinner} />
</div>
)}
{this.loadingText && (
<div class="infinite-loading-text" innerHTML={sanitizeDOMString(this.loadingText)} />
)}
</div>
</Host>
);
}
}

View File

@@ -79,7 +79,6 @@ export class InfiniteScroll implements ComponentInterface {
async componentDidLoad() {
const contentEl = this.el.closest('ion-content');
if (contentEl) {
await contentEl.componentOnReady();
this.scrollEl = await contentEl.getScrollElement();
}
this.thresholdChanged();

View File

@@ -1,4 +1,4 @@
import { Component, ComponentInterface, Element, Event, EventEmitter, Method, Prop, State, Watch, h } from '@stencil/core';
import { Component, ComponentInterface, Element, Event, EventEmitter, Host, Method, Prop, State, Watch, h } from '@stencil/core';
import { getIonMode } from '../../global/ionic-global';
import { Color, InputChangeEventDetail, StyleEventDetail, TextFieldTypes } from '../../interface';
@@ -335,20 +335,8 @@ export class Input implements ComponentInterface {
return this.getValue().length > 0;
}
hostData() {
const mode = getIonMode(this);
return {
'aria-disabled': this.disabled ? 'true' : null,
class: {
...createColorClasses(this.color),
[mode]: true,
'has-value': this.hasValue(),
'has-focus': this.hasFocus
}
};
}
render() {
const mode = getIonMode(this);
const value = this.getValue();
const labelId = this.inputId + '-lbl';
const label = findItemLabel(this.el);
@@ -356,46 +344,56 @@ export class Input implements ComponentInterface {
label.id = labelId;
}
return [
<input
class="native-input"
ref={input => this.nativeInput = input}
aria-labelledby={labelId}
disabled={this.disabled}
accept={this.accept}
autoCapitalize={this.autocapitalize}
autoComplete={this.autocomplete}
autoCorrect={this.autocorrect}
autoFocus={this.autofocus}
inputMode={this.inputmode}
min={this.min}
max={this.max}
minLength={this.minlength}
maxLength={this.maxlength}
multiple={this.multiple}
name={this.name}
pattern={this.pattern}
placeholder={this.placeholder || ''}
readOnly={this.readonly}
required={this.required}
spellCheck={this.spellcheck}
step={this.step}
size={this.size}
type={this.type}
value={value}
onInput={this.onInput}
onBlur={this.onBlur}
onFocus={this.onFocus}
onKeyDown={this.onKeydown}
/>,
(this.clearInput && !this.readonly && !this.disabled) && <button
type="button"
class="input-clear-icon"
tabindex="-1"
onTouchStart={this.clearTextInput}
onMouseDown={this.clearTextInput}
/>
];
return (
<Host
aria-disabled={this.disabled ? 'true' : null}
class={{
...createColorClasses(this.color),
[mode]: true,
'has-value': this.hasValue(),
'has-focus': this.hasFocus
}}
>
<input
class="native-input"
ref={input => this.nativeInput = input}
aria-labelledby={labelId}
disabled={this.disabled}
accept={this.accept}
autoCapitalize={this.autocapitalize}
autoComplete={this.autocomplete}
autoCorrect={this.autocorrect}
autoFocus={this.autofocus}
inputMode={this.inputmode}
min={this.min}
max={this.max}
minLength={this.minlength}
maxLength={this.maxlength}
multiple={this.multiple}
name={this.name}
pattern={this.pattern}
placeholder={this.placeholder || ''}
readOnly={this.readonly}
required={this.required}
spellCheck={this.spellcheck}
step={this.step}
size={this.size}
type={this.type}
value={value}
onInput={this.onInput}
onBlur={this.onBlur}
onFocus={this.onFocus}
onKeyDown={this.onKeydown}
/>
{(this.clearInput && !this.readonly && !this.disabled) && <button
type="button"
class="input-clear-icon"
tabindex="-1"
onTouchStart={this.clearTextInput}
onMouseDown={this.clearTextInput}
/>}
</Host>
);
}
}

View File

@@ -1,4 +1,4 @@
import { Component, ComponentInterface, Element, Prop, h } from '@stencil/core';
import { Component, ComponentInterface, Element, Host, Prop, h } from '@stencil/core';
import { getIonMode } from '../../global/ionic-global';
import { Color } from '../../interface';
@@ -39,27 +39,25 @@ export class ItemDivider implements ComponentInterface {
*/
@Prop() sticky = false;
hostData() {
const mode = getIonMode(this);
return {
class: {
...createColorClasses(this.color),
[mode]: true,
'item-divider-sticky': this.sticky,
'item': true,
}
};
}
render() {
return [
<slot name="start"></slot>,
<div class="item-divider-inner">
<div class="item-divider-wrapper">
<slot></slot>
const mode = getIonMode(this);
return (
<Host
class={{
...createColorClasses(this.color),
[mode]: true,
'item-divider-sticky': this.sticky,
'item': true,
}}
>
<slot name="start"></slot>
<div class="item-divider-inner">
<div class="item-divider-wrapper">
<slot></slot>
</div>
<slot name="end"></slot>
</div>
<slot name="end"></slot>
</div>
];
</Host>
);
}
}

View File

@@ -1,4 +1,4 @@
import { Component, ComponentInterface } from '@stencil/core';
import { Component, ComponentInterface, Host, h } from '@stencil/core';
import { getIonMode } from '../../global/ionic-global';
@@ -11,18 +11,21 @@ import { getIonMode } from '../../global/ionic-global';
})
export class ItemGroup implements ComponentInterface {
hostData() {
render() {
const mode = getIonMode(this);
return {
'role': 'group',
class: {
[mode]: true,
return (
<Host
role="group"
class={{
[mode]: true,
// Used internally for styling
[`item-group-${mode}`]: true,
// Used internally for styling
[`item-group-${mode}`]: true,
'item': true
}
};
'item': true
}}
>
</Host>
);
}
}

Some files were not shown because too many files have changed in this diff Show More