mirror of
https://github.com/ionic-team/ionic-framework.git
synced 2026-03-13 10:22:08 +08:00
Compare commits
24 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
02ef5ae179 | ||
|
|
4aab72b061 | ||
|
|
9c9e28ccc9 | ||
|
|
1c2875044a | ||
|
|
d665ace5c4 | ||
|
|
351c30ce42 | ||
|
|
3b9b9082b8 | ||
|
|
0774cca2cd | ||
|
|
6c366aaf87 | ||
|
|
6876fd089f | ||
|
|
22a8842ac2 | ||
|
|
2d5faa75db | ||
|
|
cab2a5103f | ||
|
|
d36050918a | ||
|
|
64f128be07 | ||
|
|
87999e3c7a | ||
|
|
bb4554211d | ||
|
|
f71109b088 | ||
|
|
44e18bd795 | ||
|
|
f4d265eb60 | ||
|
|
1e8dfb7d85 | ||
|
|
9f023c92c4 | ||
|
|
694d47b794 | ||
|
|
b87c555a6e |
15
.github/CODEOWNERS
vendored
15
.github/CODEOWNERS
vendored
@@ -1,15 +0,0 @@
|
||||
# Lines starting with '#' are comments.
|
||||
# Each line is a file pattern followed by one or more owners.
|
||||
|
||||
# More details are here: https://help.github.com/articles/about-codeowners/
|
||||
|
||||
# The '*' pattern is global owners.
|
||||
|
||||
# Order is important. The last matching pattern has the most precedence.
|
||||
# The folders are ordered as follows:
|
||||
|
||||
# In each subsection folders are ordered first by depth, then alphabetically.
|
||||
# This should make it easy to add new rules without breaking existing ones.
|
||||
|
||||
# Global owners
|
||||
* @ionic-team/framework-core
|
||||
14
.github/COMPONENT-GUIDE.md
vendored
14
.github/COMPONENT-GUIDE.md
vendored
@@ -12,7 +12,6 @@
|
||||
- [Accessibility](#accessibility)
|
||||
* [Checkbox](#checkbox)
|
||||
* [Switch](#switch)
|
||||
* [Accordion](#accordion)
|
||||
- [Rendering Anchor or Button](#rendering-anchor-or-button)
|
||||
* [Example Components](#example-components-1)
|
||||
* [Component Structure](#component-structure-1)
|
||||
@@ -625,19 +624,6 @@ You are currently on a switch. To select or deselect this checkbox, press Contro
|
||||
|
||||
There is a WebKit bug open for this: https://bugs.webkit.org/show_bug.cgi?id=196354
|
||||
|
||||
### Accordion
|
||||
|
||||
#### Example Components
|
||||
|
||||
- [ion-accordion](https://github.com/ionic-team/ionic/tree/master/core/src/components/accordion)
|
||||
- [ion-accordion-group](https://github.com/ionic-team/ionic/tree/master/core/src/components/accordion-group)
|
||||
|
||||
#### NVDA
|
||||
|
||||
In order to use the arrow keys to navigate the accordions, users must be in "Focus Mode". Typically, NVDA automatically switches between Browse and Focus modes when inside of a form, but not every accordion needs a form.
|
||||
|
||||
You can either wrap your `ion-accordion-group` in a form, or manually toggle Focus Mode using NVDA's keyboard shortcut.
|
||||
|
||||
|
||||
## Rendering Anchor or Button
|
||||
|
||||
|
||||
BIN
.github/assets/logo.png
vendored
BIN
.github/assets/logo.png
vendored
Binary file not shown.
|
Before Width: | Height: | Size: 10 KiB |
@@ -13,14 +13,14 @@ runs:
|
||||
cache-name: core-node-modules
|
||||
with:
|
||||
path: ./core/node_modules
|
||||
key: ${{ runner.os }}-build-${{ env.cache-name }}-${{ hashFiles('./core/package-lock.json')}}-v2
|
||||
key: ${{ runner.os }}-build-${{ env.cache-name }}-${{ hashFiles('./core/package-lock.json')}}-v1
|
||||
- name: Cache Angular Node Modules
|
||||
uses: actions/cache@v2
|
||||
env:
|
||||
cache-name: angular-node-modules
|
||||
with:
|
||||
path: ./angular/node_modules
|
||||
key: ${{ runner.os }}-build-${{ env.cache-name }}-${{ hashFiles('./angular/package-lock.json')}}-v2
|
||||
key: ${{ runner.os }}-build-${{ env.cache-name }}-${{ hashFiles('./angular/package-lock.json')}}-v1
|
||||
- uses: ./.github/workflows/actions/download-archive
|
||||
with:
|
||||
name: ionic-core
|
||||
|
||||
@@ -14,7 +14,7 @@ runs:
|
||||
cache-name: core-node-modules
|
||||
with:
|
||||
path: ./core/node_modules
|
||||
key: ${{ runner.os }}-build-${{ env.cache-name }}-${{ hashFiles('./core/package-lock.json') }}-v2
|
||||
key: ${{ runner.os }}-build-${{ env.cache-name }}-${{ hashFiles('./core/package-lock.json') }}-v1
|
||||
- name: Install Dependencies
|
||||
run: npm install
|
||||
working-directory: ./core
|
||||
|
||||
@@ -13,16 +13,7 @@ runs:
|
||||
cache-name: core-node-modules
|
||||
with:
|
||||
path: ./core/node_modules
|
||||
key: ${{ runner.os }}-build-${{ env.cache-name }}-${{ hashFiles('./core/package-lock.json') }}-v2
|
||||
- name: Install Dependencies
|
||||
run: npm install --legacy-peer-deps
|
||||
shell: bash
|
||||
working-directory: ./packages/react-router
|
||||
- uses: ./.github/workflows/actions/download-archive
|
||||
with:
|
||||
name: ionic-react
|
||||
path: ./packages/react
|
||||
filename: ReactBuild.zip
|
||||
key: ${{ runner.os }}-build-${{ env.cache-name }}-${{ hashFiles('./core/package-lock.json') }}-v1
|
||||
- uses: ./.github/workflows/actions/download-archive
|
||||
with:
|
||||
name: ionic-core
|
||||
@@ -49,6 +40,10 @@ runs:
|
||||
run: npm run build
|
||||
shell: bash
|
||||
working-directory: ./packages/react-router
|
||||
- name: Test Spec
|
||||
run: npm run test.spec
|
||||
shell: bash
|
||||
working-directory: ./packages/react-router
|
||||
- uses: ./.github/workflows/actions/upload-archive
|
||||
with:
|
||||
name: ionic-react-router
|
||||
|
||||
@@ -13,7 +13,7 @@ runs:
|
||||
cache-name: core-node-modules
|
||||
with:
|
||||
path: ./core/node_modules
|
||||
key: ${{ runner.os }}-build-${{ env.cache-name }}-${{ hashFiles('./core/package-lock.json') }}-v2
|
||||
key: ${{ runner.os }}-build-${{ env.cache-name }}-${{ hashFiles('./core/package-lock.json') }}-v1
|
||||
- uses: ./.github/workflows/actions/download-archive
|
||||
with:
|
||||
name: ionic-core
|
||||
|
||||
@@ -13,7 +13,7 @@ runs:
|
||||
cache-name: core-node-modules
|
||||
with:
|
||||
path: ./core/node_modules
|
||||
key: ${{ runner.os }}-build-${{ env.cache-name }}-${{ hashFiles('./core/package-lock.json') }}-v2
|
||||
key: ${{ runner.os }}-build-${{ env.cache-name }}-${{ hashFiles('./core/package-lock.json') }}-v1
|
||||
- uses: ./.github/workflows/actions/download-archive
|
||||
with:
|
||||
name: ionic-core
|
||||
|
||||
@@ -13,7 +13,7 @@ runs:
|
||||
cache-name: core-node-modules
|
||||
with:
|
||||
path: ./core/node_modules
|
||||
key: ${{ runner.os }}-build-${{ env.cache-name }}-${{ hashFiles('./core/package-lock.json') }}-v2
|
||||
key: ${{ runner.os }}-build-${{ env.cache-name }}-${{ hashFiles('./core/package-lock.json') }}-v1
|
||||
- uses: ./.github/workflows/actions/download-archive
|
||||
with:
|
||||
name: ionic-core
|
||||
|
||||
@@ -13,7 +13,7 @@ runs:
|
||||
cache-name: core-node-modules
|
||||
with:
|
||||
path: ./core/node_modules
|
||||
key: ${{ runner.os }}-build-${{ env.cache-name }}-${{ hashFiles('./core/package-lock.json') }}-v2
|
||||
key: ${{ runner.os }}-build-${{ env.cache-name }}-${{ hashFiles('./core/package-lock.json') }}-v1
|
||||
- uses: ./.github/workflows/actions/download-archive
|
||||
with:
|
||||
name: ionic-core
|
||||
@@ -30,7 +30,7 @@ runs:
|
||||
path: ./packages/angular-server
|
||||
filename: AngularServerBuild.zip
|
||||
- name: Install Dependencies
|
||||
run: npm install
|
||||
run: npm install --legacy-peer-deps
|
||||
shell: bash
|
||||
working-directory: ./angular/test/test-app
|
||||
- name: Run Tests
|
||||
|
||||
@@ -13,7 +13,7 @@ runs:
|
||||
cache-name: core-node-modules
|
||||
with:
|
||||
path: ./core/node_modules
|
||||
key: ${{ runner.os }}-build-${{ env.cache-name }}-${{ hashFiles('./core/package-lock.json') }}-v2
|
||||
key: ${{ runner.os }}-build-${{ env.cache-name }}-${{ hashFiles('./core/package-lock.json') }}-v1
|
||||
- uses: ./.github/workflows/actions/download-archive
|
||||
with:
|
||||
name: ionic-core
|
||||
|
||||
@@ -13,7 +13,7 @@ runs:
|
||||
cache-name: core-node-modules
|
||||
with:
|
||||
path: ./core/node_modules
|
||||
key: ${{ runner.os }}-build-${{ env.cache-name }}-${{ hashFiles('./core/package-lock.json') }}-v2
|
||||
key: ${{ runner.os }}-build-${{ env.cache-name }}-${{ hashFiles('./core/package-lock.json') }}-v1
|
||||
- name: Lint
|
||||
run: npm run lint
|
||||
shell: bash
|
||||
|
||||
@@ -18,7 +18,7 @@ runs:
|
||||
cache-name: core-node-modules
|
||||
with:
|
||||
path: ./core/node_modules
|
||||
key: ${{ runner.os }}-build-${{ env.cache-name }}-${{ hashFiles('./core/package-lock.json') }}-v2
|
||||
key: ${{ runner.os }}-build-${{ env.cache-name }}-${{ hashFiles('./core/package-lock.json') }}-v1
|
||||
- uses: ./.github/workflows/actions/download-archive
|
||||
with:
|
||||
name: ionic-core
|
||||
|
||||
@@ -18,7 +18,7 @@ runs:
|
||||
cache-name: core-node-modules
|
||||
with:
|
||||
path: ./core/node_modules
|
||||
key: ${{ runner.os }}-build-${{ env.cache-name }}-${{ hashFiles('./core/package-lock.json') }}-v2
|
||||
key: ${{ runner.os }}-build-${{ env.cache-name }}-${{ hashFiles('./core/package-lock.json') }}-v1
|
||||
- uses: ./.github/workflows/actions/download-archive
|
||||
with:
|
||||
name: ionic-core
|
||||
|
||||
@@ -13,7 +13,7 @@ runs:
|
||||
cache-name: core-node-modules
|
||||
with:
|
||||
path: ./core/node_modules
|
||||
key: ${{ runner.os }}-build-${{ env.cache-name }}-${{ hashFiles('./core/package-lock.json') }}-v2
|
||||
key: ${{ runner.os }}-build-${{ env.cache-name }}-${{ hashFiles('./core/package-lock.json') }}-v1
|
||||
- uses: ./.github/workflows/actions/download-archive
|
||||
with:
|
||||
name: ionic-core
|
||||
|
||||
@@ -13,7 +13,7 @@ runs:
|
||||
cache-name: core-node-modules
|
||||
with:
|
||||
path: ./core/node_modules
|
||||
key: ${{ runner.os }}-build-${{ env.cache-name }}-${{ hashFiles('./core/package-lock.json') }}-v2
|
||||
key: ${{ runner.os }}-build-${{ env.cache-name }}-${{ hashFiles('./core/package-lock.json') }}-v1
|
||||
- uses: ./.github/workflows/actions/download-archive
|
||||
with:
|
||||
name: ionic-core
|
||||
|
||||
@@ -13,7 +13,7 @@ runs:
|
||||
cache-name: core-node-modules
|
||||
with:
|
||||
path: ./core/node_modules
|
||||
key: ${{ runner.os }}-build-${{ env.cache-name }}-${{ hashFiles('./core/package-lock.json') }}-v2
|
||||
key: ${{ runner.os }}-build-${{ env.cache-name }}-${{ hashFiles('./core/package-lock.json') }}-v1
|
||||
- uses: ./.github/workflows/actions/download-archive
|
||||
with:
|
||||
name: ionic-core
|
||||
|
||||
@@ -13,7 +13,7 @@ runs:
|
||||
cache-name: core-node-modules
|
||||
with:
|
||||
path: ./core/node_modules
|
||||
key: ${{ runner.os }}-build-${{ env.cache-name }}-${{ hashFiles('./core/package-lock.json') }}-v2
|
||||
key: ${{ runner.os }}-build-${{ env.cache-name }}-${{ hashFiles('./core/package-lock.json') }}-v1
|
||||
- uses: ./.github/workflows/actions/download-archive
|
||||
with:
|
||||
name: ionic-core
|
||||
|
||||
32
.github/workflows/dev-build.yml
vendored
32
.github/workflows/dev-build.yml
vendored
@@ -6,37 +6,13 @@ on:
|
||||
jobs:
|
||||
dev-build:
|
||||
runs-on: ubuntu-latest
|
||||
outputs:
|
||||
version: ${{ steps.dev-build.outputs.version }}
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
- uses: actions/setup-node@v2
|
||||
- uses: actions/setup-node@v1
|
||||
with:
|
||||
node-version: 16
|
||||
- name: Install Dependencies
|
||||
run: npm ci --no-package-lock && lerna bootstrap --ignore-scripts -- --legacy-peer-deps
|
||||
shell: bash
|
||||
- name: Prepare NPM Token
|
||||
run: echo //registry.npmjs.org/:_authToken=${NPM_TOKEN} > .npmrc
|
||||
node-version: 15.x
|
||||
- name: Create Dev Build
|
||||
run: npm run release.dev -- --skip-prompt
|
||||
shell: bash
|
||||
env:
|
||||
NPM_TOKEN: ${{ secrets.NPM_TOKEN }}
|
||||
- name: Create Dev Hash
|
||||
run: |
|
||||
echo "HASH=$(git log -1 --format=%H | cut -c 1-7)" >> $GITHUB_ENV
|
||||
echo "TIMESTAMP=$(date +%s)" >> $GITHUB_ENV
|
||||
echo "CURRENT_VERSION=$(node -p -e "require('./core/package.json').version")" >> $GITHUB_ENV
|
||||
shell: bash
|
||||
- name: Create Dev Build
|
||||
run: |
|
||||
HUSKY_SKIP_HOOKS=1 lerna publish $(echo "${{ env.CURRENT_VERSION }}")-dev.$(echo "${{ env.TIMESTAMP }}").$(echo "${{ env.HASH }}") --no-verify-access --yes --force-publish='*' --dist-tag dev --no-git-tag-version --no-push
|
||||
shell: bash
|
||||
- id: dev-build
|
||||
run: echo "::set-output name=version::$(echo "${{ env.CURRENT_VERSION }}")-dev.$(echo "${{ env.TIMESTAMP }}").$(echo "${{ env.HASH }}")"
|
||||
get-build:
|
||||
name: Get your dev build!
|
||||
runs-on: ubuntu-latest
|
||||
needs: dev-build
|
||||
steps:
|
||||
- run: echo ${{ needs.dev-build.outputs.version }}
|
||||
|
||||
|
||||
48
.github/workflows/pre-release.yml
vendored
48
.github/workflows/pre-release.yml
vendored
@@ -1,48 +0,0 @@
|
||||
name: 'Ionic Pre-Release'
|
||||
|
||||
on:
|
||||
workflow_dispatch:
|
||||
inputs:
|
||||
version:
|
||||
required: true
|
||||
type: choice
|
||||
description: Which version should be published?
|
||||
options:
|
||||
- prepatch
|
||||
- preminor
|
||||
- premajor
|
||||
prefix:
|
||||
required: true
|
||||
type: choice
|
||||
description: What kind of pre-release is this?
|
||||
default: beta
|
||||
options:
|
||||
- alpha
|
||||
- beta
|
||||
- rc
|
||||
|
||||
jobs:
|
||||
build-ionic:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
- uses: actions/setup-node@v2
|
||||
with:
|
||||
node-version: 16
|
||||
- name: Configure Identity
|
||||
run: |
|
||||
git config user.name github-actions
|
||||
git config user.email github-actions@github.com
|
||||
shell: bash
|
||||
- name: Install Dependencies
|
||||
run: npm ci --no-package-lock && lerna bootstrap --ignore-scripts -- --legacy-peer-deps
|
||||
shell: bash
|
||||
- name: Prepare NPM Token
|
||||
run: echo //registry.npmjs.org/:_authToken=${NPM_TOKEN} > .npmrc
|
||||
shell: bash
|
||||
env:
|
||||
NPM_TOKEN: ${{ secrets.NPM_TOKEN }}
|
||||
- name: Release
|
||||
run: |
|
||||
HUSKY_SKIP_HOOKS=1 lerna publish $(echo "${{ github.event.inputs.version }}") --no-verify-access --yes --force-publish='*' --dist-tag next --no-git-tag-version --no-push --skip-npm --preid $(echo "${{ github.events.inputs.prefix }}")
|
||||
shell: bash
|
||||
51
.github/workflows/release.yml
vendored
51
.github/workflows/release.yml
vendored
@@ -1,51 +0,0 @@
|
||||
name: 'Ionic Production Release'
|
||||
|
||||
on:
|
||||
workflow_dispatch:
|
||||
inputs:
|
||||
version:
|
||||
required: true
|
||||
type: choice
|
||||
description: Which version should be published?
|
||||
options:
|
||||
- patch
|
||||
- minor
|
||||
- major
|
||||
tag:
|
||||
required: true
|
||||
type: choice
|
||||
description: Which npm tag should this be published to?
|
||||
options:
|
||||
- latest
|
||||
- v5-lts
|
||||
- v4-lts
|
||||
|
||||
jobs:
|
||||
build-ionic:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
with:
|
||||
fetch-depth: 0
|
||||
- uses: actions/setup-node@v2
|
||||
with:
|
||||
node-version: 16
|
||||
- name: Configure Identity
|
||||
run: |
|
||||
git config user.name github-actions
|
||||
git config user.email github-actions@github.com
|
||||
shell: bash
|
||||
- name: Install Dependencies
|
||||
run: npm ci --no-package-lock && lerna bootstrap --ignore-scripts -- --legacy-peer-deps
|
||||
shell: bash
|
||||
- name: Prepare NPM Token
|
||||
run: echo //registry.npmjs.org/:_authToken=${NPM_TOKEN} > .npmrc
|
||||
shell: bash
|
||||
env:
|
||||
NPM_TOKEN: ${{ secrets.NPM_TOKEN }}
|
||||
- name: Release
|
||||
run: |
|
||||
HUSKY_SKIP_HOOKS=1 lerna publish $(echo "${{ github.event.inputs.version }}") --no-verify-access --yes --force-publish='*' --dist-tag $(echo "${{ github.event.inputs.tag }}") --conventional-commits --create-release github
|
||||
env:
|
||||
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
shell: bash
|
||||
2
.gitignore
vendored
2
.gitignore
vendored
@@ -66,5 +66,3 @@ core/loader/
|
||||
core/www/
|
||||
.stencil/
|
||||
angular/build/
|
||||
|
||||
.npmrc
|
||||
|
||||
@@ -8,15 +8,15 @@ const fs = require('fs');
|
||||
// core
|
||||
{
|
||||
files: [
|
||||
'../core/css/core.css',
|
||||
'../core/css/core.css.map',
|
||||
'../core/css/normalize.css',
|
||||
'../core/css/normalize.css.map',
|
||||
'../core/components/index.js',
|
||||
'../core/components/index.d.ts',
|
||||
'../core/css/core.css',
|
||||
'../core/css/core.css.map',
|
||||
'../core/css/normalize.css',
|
||||
'../core/css/normalize.css.map',
|
||||
'../core/components/index.js',
|
||||
'../core/components/index.d.ts',
|
||||
'../core/components/package.json',
|
||||
'../core/dist/index.js',
|
||||
'../core/dist/ionic/index.esm.js',
|
||||
'../core/dist/index.js',
|
||||
'../core/dist/ionic/index.esm.js',
|
||||
]
|
||||
},
|
||||
// hydrate
|
||||
@@ -31,17 +31,19 @@ const fs = require('fs');
|
||||
{
|
||||
files: [
|
||||
'../angular/dist/schematics/collection.json',
|
||||
'../angular/dist/fesm5/ionic-angular.js',
|
||||
'../angular/dist/fesm2015/ionic-angular.js',
|
||||
'../angular/dist/esm2015/ionic-angular.js',
|
||||
'../angular/dist/ionic-angular.d.ts'
|
||||
'../angular/dist/ionic-angular.d.ts',
|
||||
'../angular/dist/ionic-angular.metadata.json'
|
||||
]
|
||||
},
|
||||
// angular-server
|
||||
{
|
||||
files: [
|
||||
'../packages/angular-server/dist/esm2015/ionic-angular-server.js',
|
||||
'../packages/angular-server/dist/fesm5/ionic-angular-server.js',
|
||||
'../packages/angular-server/dist/fesm2015/ionic-angular-server.js',
|
||||
'../packages/angular-server/dist/ionic-angular-server.d.ts'
|
||||
'../packages/angular-server/dist/ionic-angular-server.d.ts',
|
||||
'../packages/angular-server/dist/ionic-angular-server.metadata.json'
|
||||
]
|
||||
},
|
||||
// react
|
||||
|
||||
107
BETA.md
107
BETA.md
@@ -1,107 +0,0 @@
|
||||
# Ionic Framework v6 Beta
|
||||
|
||||
Thanks for your interest in trying out the Framework v6 beta! We are looking for developers to help test our new changes and provide feedback so that we can make Framework v6 the best release yet! Follow this guide to get setup with the beta.
|
||||
|
||||
## Installation
|
||||
|
||||
We have worked to make the Framework v6 migration as easy as possible, so the upgrade process should be a breeze!
|
||||
|
||||
Developers can follow the guide below to begin updating their existing apps to Framework v6. If you want to try out Framework v6 in a new app, you can create a starter application using `ionic start` with the Ionic CLI and then follow the guide below. See https://ionicframework.com/docs/intro/cli for information on how to get started with a new Ionic Framework application.
|
||||
|
||||
> Note: Framework v6 is currently in beta, so do not push any apps running v6 to production!
|
||||
|
||||
### Ionic Vue
|
||||
|
||||
Ionic Vue developers should first begin by upgrading to the latest version of `vue` and `vue-router`. As of Framework v6, `vue@3.0.6+` is required.
|
||||
|
||||
```shell
|
||||
npm install vue@next vue-router@4
|
||||
```
|
||||
|
||||
Ionic Vue users have access to the new Custom Elements build of Framework v6. To make the most out of this improvement, we recommend using Webpack 5. To do this, developers should first install the latest version of the Vue CLI:
|
||||
|
||||
```shell
|
||||
npm install -g @vue/cli@next
|
||||
```
|
||||
|
||||
From there, they can upgrade all Vue CLI plugins which will automatically migrate them to Webpack 5:
|
||||
|
||||
```shell
|
||||
vue upgrade --next
|
||||
```
|
||||
|
||||
The new Vue CLI will automatically generate two different bundles based on your `browserslist` configuration: one for modern browsers and one for legacy browsers. New Ionic Vue starter apps will only generate the bundle for modern browsers, but some older starter apps may need to have their `.browserslistrc` file updated. You can ensure your app only builds for modern browsers by setting `.browserlistrc` to have the following content:
|
||||
|
||||
```
|
||||
> 1%, last 2 versions, not dead, not ie 11
|
||||
```
|
||||
|
||||
From there, developers can install the Framework v6 beta:
|
||||
|
||||
```shell
|
||||
npm install @ionic/vue@next @ionic/vue-router@next
|
||||
```
|
||||
|
||||
Next, developers should review the breaking changes and make any changes necessary in their apps: https://github.com/ionic-team/ionic-framework/blob/next/BREAKING.md
|
||||
|
||||
After that, you should be good to go! Check out https://beta.ionicframework.com/docs for the Framework v6 documentation.
|
||||
|
||||
### Ionic React
|
||||
|
||||
Ionic React developers should first begin by upgrading to the latest version of `react` and `react-dom`. As of Framework v6, `react@17+` is required:
|
||||
|
||||
```shell
|
||||
npm install react@latest react-dom@latest
|
||||
```
|
||||
|
||||
From there, developers can install the Framework v6 beta:
|
||||
|
||||
```shell
|
||||
npm install @ionic/react@next @ionic/react-router@next
|
||||
```
|
||||
|
||||
Next, developers should review the breaking changes and make any changes necessary in their apps: https://github.com/ionic-team/ionic-framework/blob/next/BREAKING.md
|
||||
|
||||
After that, you should be good to go! Be sure to review the other breaking changes: https://github.com/ionic-team/ionic-framework/blob/next/BREAKING.md
|
||||
|
||||
Check out https://beta.ionicframework.com/docs for the Framework v6 documentation.
|
||||
|
||||
### Ionic Angular
|
||||
|
||||
Ionic Angular developers should first begin by upgrading to the latest version of Angular. As of Framework v6, Angular 11+ is required.
|
||||
|
||||
Please see https://update.angular.io/ for a guide on how to update to the latest version of Angular.
|
||||
|
||||
From there, developers can install the Framework v6 beta:
|
||||
|
||||
```shell
|
||||
npm install @ionic/angular@next
|
||||
```
|
||||
|
||||
Next, developers should review the breaking changes and make any changes necessary in their apps: https://github.com/ionic-team/ionic-framework/blob/next/BREAKING.md
|
||||
|
||||
After that, you should be good to go! Check out https://beta.ionicframework.com/docs for the Framework v6 documentation.
|
||||
|
||||
### Ionic Core
|
||||
|
||||
Developers using `@ionic/core` directly should install the Framework v6 beta directly:
|
||||
|
||||
```shell
|
||||
npm install @ionic/core@next
|
||||
```
|
||||
|
||||
If you are using Ionic Framework in a Stencil app, be sure to update to the latest version of Stencil as well:
|
||||
|
||||
```shell
|
||||
npm install @stencil/core@latest
|
||||
```
|
||||
|
||||
Next, developers should review the breaking changes and make any changes necessary in their apps: https://github.com/ionic-team/ionic-framework/blob/next/BREAKING.md
|
||||
|
||||
After that, you should be good to go! Check out https://beta.ionicframework.com/docs for the Framework v6 documentation.
|
||||
|
||||
## Providing Feedback
|
||||
|
||||
Feedback should be provided on our GitHub repo by creating a new issue: https://github.com/ionic-team/ionic-framework/issues/new/choose
|
||||
|
||||
Please note in the issue title that you are using the Framework v6 beta!
|
||||
391
BREAKING.md
391
BREAKING.md
@@ -4,402 +4,11 @@ This is a comprehensive list of the breaking changes introduced in the major ver
|
||||
|
||||
## Versions
|
||||
|
||||
- [Version 6.x](#version-6x)
|
||||
- [Version 5.x](#version-5x)
|
||||
- [Version 4.x](#version-4x)
|
||||
- [Legacy](#legacy)
|
||||
|
||||
|
||||
## Version 6.x
|
||||
|
||||
- [Components](#components)
|
||||
* [Datetime](#datetime)
|
||||
* [Header](#header)
|
||||
* [Icons](#icons)
|
||||
* [Input](#input)
|
||||
* [Modal](#modal)
|
||||
* [Popover](#popover)
|
||||
* [Radio](#radio)
|
||||
* [Searchbar](#searchbar)
|
||||
* [Select](#select)
|
||||
* [Tab Bar](#tab-bar)
|
||||
* [Textarea](#textarea)
|
||||
* [Toast](#toast)
|
||||
* [Toolbar](#toolbar)
|
||||
- [Config](#config)
|
||||
* [Transition Shadow](#transition-shadow)
|
||||
- [Angular](#angular)
|
||||
* [Config](#config-1)
|
||||
- [Vue](#vue)
|
||||
* [Config](#config-2)
|
||||
* [Tabs Config](#tabs-config)
|
||||
* [Tabs Router Outlet](#tabs-router-outlet)
|
||||
* [Overlay Events](#overlay-events)
|
||||
* [Utility Function Types](#utility-function-types)
|
||||
- [React](#react)
|
||||
* [Config](#config-3)
|
||||
- [Browser and Platform Support](#browser-and-platform-support)
|
||||
|
||||
|
||||
### Components
|
||||
|
||||
#### Datetime
|
||||
|
||||
The `ion-datetime` component has undergone a complete rewrite and uses a new calendar style. As a result, some of the properties no longer apply and have been removed.
|
||||
|
||||
- `ion-datetime` now displays the calendar inline by default, allowing for more flexibility in presentation. As a result, the `placeholder` property has been removed. Additionally, the `text` and `placeholder` Shadow Parts have been removed.
|
||||
|
||||
- The `--padding-bottom`, `--padding-end`, `--padding-start`, `--padding-top`, and `--placeholder-color` CSS Variables have been removed since `ion-datetime` now displays inline by default.
|
||||
|
||||
- The `displayFormat` and `displayTimezone` properties have been removed since `ion-datetime` now displays inline with a calendar picker. To parse the UTC string provided in the payload of the `ionChange` event, we recommend using a 3rd-party date library like [date-fns](https://date-fns.org/). Here is an example of how you can take the UTC string from `ion-datetime` and format it to whatever style you prefer:
|
||||
|
||||
```typescript
|
||||
import { format, parseISO } from 'date-fns';
|
||||
|
||||
/**
|
||||
* This is provided in the event
|
||||
* payload from the `ionChange` event.
|
||||
*/
|
||||
const dateFromIonDatetime = '2021-06-04T14:23:00-04:00';
|
||||
const formattedString = format(parseISO(dateFromIonDatetime), 'MMM d, yyyy');
|
||||
|
||||
console.log(formattedString); // Jun 4, 2021
|
||||
```
|
||||
|
||||
- The `pickerOptions` and `pickerFormat` properties have been removed since `ion-datetime` now uses a calendar style rather than a wheel picker style.
|
||||
|
||||
- The `monthNames`, `monthShortNames`, `dayNames`, and `dayShortNames` properties have been removed. `ion-datetime` can now automatically format these values according to your devices locale thanks to the [Intl.DateTimeFormat API](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Intl/DateTimeFormat). If you wish to force a specific locale, you can use the new `locale` property:
|
||||
|
||||
```html
|
||||
<ion-datetime locale="fr-FR"></ion-datetime>
|
||||
```
|
||||
|
||||
- The `open` method has been removed. To present the datetime in an overlay, you can pass it into an `ion-modal` or `ion-popover` component and call the `present` method on the overlay instance. Alternatively, you can use the `trigger` property on `ion-modal` or `ion-popover` to present the overlay on a button click:
|
||||
|
||||
```html
|
||||
<ion-button id="open-modal">Open Datetime Modal</ion-button>
|
||||
<ion-modal trigger="open-modal">
|
||||
<ion-datetime></ion-datetime>
|
||||
</ion-modal>
|
||||
```
|
||||
|
||||
#### Header
|
||||
|
||||
When using a collapsible large title, the last toolbar in the header with `collapse="condense"` no longer has a border. This does not affect the toolbar when the large title is collapsed.
|
||||
|
||||
To get the old style back, add the following CSS to your global stylesheet:
|
||||
|
||||
```css
|
||||
ion-header.header-collapse-condense ion-toolbar:last-of-type {
|
||||
--border-width: 0 0 0.55px;
|
||||
}
|
||||
```
|
||||
|
||||
#### Icons
|
||||
|
||||
Ionic 6 now ships with Ionicons 6. Please be sure to review the [Ionicons 6.0.0 Changelog](https://github.com/ionic-team/ionicons/releases/tag/v6.0.0) and make any necessary changes.
|
||||
|
||||
#### Input
|
||||
|
||||
The `placeholder` property now has a type of `string | undefined` rather than `null | string | undefined`.
|
||||
|
||||
#### Modal
|
||||
|
||||
Converted `ion-modal` to use [Shadow DOM](https://developer.mozilla.org/en-US/docs/Web/Web_Components/Using_shadow_DOM).
|
||||
|
||||
If you were targeting the internals of `ion-modal` in your CSS, you will need to target the `backdrop` or `content` [Shadow Parts](https://ionicframework.com/docs/theming/css-shadow-parts) instead, or use the provided CSS Variables.
|
||||
|
||||
Developers dynamically creating modals using `document.createElement('ion-modal')` will now need to call `modal.remove()` after the modal has been dismissed if they want the modal to be removed from the DOM.
|
||||
|
||||
#### Popover
|
||||
|
||||
Converted `ion-popover` to use [Shadow DOM](https://developer.mozilla.org/en-US/docs/Web/Web_Components/Using_shadow_DOM).
|
||||
|
||||
If you were targeting the internals of `ion-popover` in your CSS, you will need to target the `backdrop`, `arrow`, or `content` [Shadow Parts](https://ionicframework.com/docs/theming/css-shadow-parts) instead, or use the provided CSS Variables.
|
||||
|
||||
Developers dynamically creating popovers using `document.createElement('ion-popover')` will now need to call `popover.remove()` after the popover has been dismissed if they want the popover to be removed from the DOM.
|
||||
|
||||
#### Radio
|
||||
|
||||
The `RadioChangeEventDetail` interface has been removed. Instead, listen for the `ionChange` event on `ion-radio-group` and use the `RadioGroupChangeEventDetail` interface.
|
||||
|
||||
#### Searchbar
|
||||
|
||||
The `showClearButton` property now defaults to `'always'` for improved usability with screen readers.
|
||||
|
||||
To get the old behavior, set `showClearButton` to `'focus'`.
|
||||
|
||||
#### Select
|
||||
|
||||
The `placeholder` property now has a type of `string | undefined` rather than `null | string | undefined`.
|
||||
|
||||
#### Tab Bar
|
||||
|
||||
The default iOS tab bar background color has been updated to better reflect the latest iOS styles. The new default value is:
|
||||
|
||||
```css
|
||||
var(--ion-tab-bar-background, var(--ion-color-step-50, #f7f7f7));
|
||||
```
|
||||
|
||||
#### Textarea
|
||||
|
||||
The `placeholder` property now has a type of `string | undefined` rather than `null | string | undefined`.
|
||||
|
||||
#### Toast
|
||||
|
||||
The `--white-space` CSS variable now defaults to `normal` instead of `pre-wrap`.
|
||||
|
||||
#### Toolbar
|
||||
|
||||
The default iOS toolbar background color has been updated to better reflect the latest iOS styles. The new default value is:
|
||||
|
||||
```css
|
||||
var(--ion-toolbar-background, var(--ion-color-step-50, #f7f7f7));
|
||||
```
|
||||
|
||||
|
||||
### Config
|
||||
|
||||
#### Transition Shadow
|
||||
|
||||
The `experimentalTransitionShadow` config option has been removed. The transition shadow is now enabled when running in `ios` mode.
|
||||
|
||||
|
||||
### Angular
|
||||
|
||||
#### Config
|
||||
|
||||
The `Config.set()` method has been removed. See https://ionicframework.com/docs/angular/config for examples on how to set config globally, per-component, and per-platform.
|
||||
|
||||
Additionally, the `setupConfig` function is no longer exported from `@ionic/angular`. Developers should use `IonicModule.forRoot` to set the config instead. See https://ionicframework.com/docs/angular/config for more information.
|
||||
|
||||
### React
|
||||
|
||||
#### Config
|
||||
|
||||
All Ionic React applications must now import `setupIonicReact` from `@ionic/react` and call it. If you are setting a custom config with `setupConfig`, pass your config directly to `setupIonicReact` instead:
|
||||
|
||||
**Old**
|
||||
```javascript
|
||||
import { setupConfig } from '@ionic/react';
|
||||
|
||||
setupConfig({
|
||||
mode: 'md'
|
||||
})
|
||||
```
|
||||
|
||||
**New**
|
||||
```javascript
|
||||
import { setupIonicReact } from '@ionic/react';
|
||||
|
||||
setupIonicReact({
|
||||
mode: 'md'
|
||||
})
|
||||
```
|
||||
|
||||
Note that all Ionic React applications must call `setupIonicReact` even if they are not setting custom configuration.
|
||||
|
||||
Additionally, the `setupConfig` function is no longer exported from `@ionic/react`.
|
||||
|
||||
### Vue
|
||||
|
||||
#### Config
|
||||
|
||||
The `setupConfig` function is no longer exported from `@ionic/vue`. Developers should pass their config into the `IonicVue` plugin. See https://ionicframework.com/docs/vue/config for more information.
|
||||
|
||||
#### Tabs Config
|
||||
|
||||
Support for child routes nested inside of tabs has been removed to better conform to Vue Router's best practices. Additional routes should be written as sibling routes with the parent tab as the path prefix:
|
||||
|
||||
**Old**
|
||||
```typescript
|
||||
const routes: Array<RouteRecordRaw> = [
|
||||
{
|
||||
path: '/',
|
||||
redirect: '/tabs/tab1'
|
||||
},
|
||||
{
|
||||
path: '/tabs/',
|
||||
component: Tabs,
|
||||
children: [
|
||||
{
|
||||
path: '',
|
||||
redirect: 'tab1'
|
||||
},
|
||||
{
|
||||
path: 'tab1',
|
||||
component: () => import('@/views/Tab1.vue'),
|
||||
children: {
|
||||
{
|
||||
path: 'view',
|
||||
component: () => import('@/views/Tab1View.vue')
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
path: 'tab2',
|
||||
component: () => import('@/views/Tab2.vue')
|
||||
},
|
||||
{
|
||||
path: 'tab3',
|
||||
component: () => import('@/views/Tab3.vue')
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
```
|
||||
|
||||
**New**
|
||||
```typescript
|
||||
const routes: Array<RouteRecordRaw> = [
|
||||
{
|
||||
path: '/',
|
||||
redirect: '/tabs/tab1'
|
||||
},
|
||||
{
|
||||
path: '/tabs/',
|
||||
component: Tabs,
|
||||
children: [
|
||||
{
|
||||
path: '',
|
||||
redirect: 'tab1'
|
||||
},
|
||||
{
|
||||
path: 'tab1',
|
||||
component: () => import('@/views/Tab1.vue')
|
||||
},
|
||||
{
|
||||
path: 'tab1/view',
|
||||
component: () => import('@/views/Tab1View.vue')
|
||||
},
|
||||
{
|
||||
path: 'tab2',
|
||||
component: () => import('@/views/Tab2.vue')
|
||||
},
|
||||
{
|
||||
path: 'tab3',
|
||||
component: () => import('@/views/Tab3.vue')
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
```
|
||||
|
||||
In the example above `tabs/tab1/view` has been rewritten has a sibling route to `tabs/tab1`. The `path` field now includes the `tab1` prefix.
|
||||
|
||||
#### Tabs Router Outlet
|
||||
|
||||
Developers must now provide an `ion-router-outlet` inside of `ion-tabs`. Previously one was generated automatically, but this made it difficult for developers to access the properties on the generated `ion-router-outlet`.
|
||||
|
||||
**Old**
|
||||
```html
|
||||
<ion-tabs>
|
||||
<ion-tab-bar slot="bottom">
|
||||
...
|
||||
</ion-tab-bar>
|
||||
</ion-tabs>
|
||||
|
||||
<script>
|
||||
import { IonTabs, IonTabBar } from '@ionic/vue';
|
||||
import { defineComponent } from 'vue';
|
||||
|
||||
export default defineComponent({
|
||||
components: { IonTabs, IonTabBar }
|
||||
});
|
||||
</script>
|
||||
```
|
||||
|
||||
**New**
|
||||
```html
|
||||
<ion-tabs>
|
||||
<ion-router-outlet></ion-router-outlet>
|
||||
<ion-tab-bar slot="bottom">
|
||||
...
|
||||
</ion-tab-bar>
|
||||
</ion-tabs>
|
||||
|
||||
<script>
|
||||
import { IonTabs, IonTabBar, IonRouterOutlet } from '@ionic/vue';
|
||||
import { defineComponent } from 'vue';
|
||||
|
||||
export default defineComponent({
|
||||
components: { IonTabs, IonTabBar, IonRouterOutlet }
|
||||
});
|
||||
</script>
|
||||
```
|
||||
|
||||
#### Overlay Events
|
||||
|
||||
Overlay events `onWillPresent`, `onDidPresent`, `onWillDismiss`, and `onDidDismiss` have been removed in favor of `willPresent`, `didPresent`, `willDismiss`, and `didDismiss`.
|
||||
|
||||
This applies to the following components: `ion-action-sheet`, `ion-alert`, `ion-loading`, `ion-modal`, `ion-picker`, `ion-popover`, and `ion-toast`.
|
||||
|
||||
**Old**
|
||||
```html
|
||||
<ion-modal
|
||||
:is-open="modalOpenRef"
|
||||
@onWillPresent="onModalWillPresentHandler"
|
||||
@onDidPresent="onModalDidPresentHandler"
|
||||
@onWillDismiss="onModalWillDismissHandler"
|
||||
@onDidDismiss="onModalDidDismissHandler"
|
||||
>
|
||||
...
|
||||
</ion-modal>
|
||||
```
|
||||
|
||||
**New**
|
||||
```html
|
||||
<ion-modal
|
||||
:is-open="modalOpenRef"
|
||||
@willPresent="onModalWillPresentHandler"
|
||||
@didPresent="onModalDidPresentHandler"
|
||||
@willDismiss="onModalWillDismissHandler"
|
||||
@didDismiss="onModalDidDismissHandler"
|
||||
>
|
||||
...
|
||||
</ion-modal>
|
||||
```
|
||||
|
||||
#### Utility Function Types
|
||||
|
||||
- The `IonRouter` type for `useIonRouter` has been renamed to `UseIonRouterResult`.
|
||||
|
||||
- The `IonKeyboardRef` type for `useKeyboard` has been renamed to `UseKeyboardResult`.
|
||||
|
||||
|
||||
### Browser and Platform Support
|
||||
|
||||
This section details the desktop browser, JavaScript framework, and mobile platform versions that are supported by Ionic Framework v6.
|
||||
|
||||
**Minimum Browser Versions**
|
||||
| Desktop Browser | Supported Versions |
|
||||
| --------------- | ----------------- |
|
||||
| Chrome | 60+ |
|
||||
| Safari | 13+ |
|
||||
| Firefox | 63+ |
|
||||
| Edge | 79+ |
|
||||
|
||||
**Minimum JavaScript Framework Versions**
|
||||
|
||||
| Framework | Supported Version |
|
||||
| --------- | --------------------- |
|
||||
| Angular | 12+ |
|
||||
| React | 17+ |
|
||||
| Vue | 3.0.6+ |
|
||||
|
||||
**Minimum Mobile Platform Versions**
|
||||
|
||||
| Platform | Supported Version |
|
||||
| -------- | --------------------------------------- |
|
||||
| iOS | 13+ |
|
||||
| Android | 5.0+ with Chromium 60+ (See note below) |
|
||||
|
||||
Starting with Android 5.0, the webview was moved to a separate application that can be updated independently of Android. This means that most Android 5.0+ devices are going to be running a modern version of Chromium. However, there are a still a subset of Android devices whose manufacturer has locked the webview version and does not allow the webview to update. These webviews are typically stuck at the version that was available when the device initially shipped.
|
||||
|
||||
As a result, Ionic Framework only supports Android devices and emulators running Android 5.0+ with a webview of Chromium 60 or newer. For context, this is the version that Stencil can support with no polyfills: https://stenciljs.com/docs/browser-support
|
||||
|
||||
|
||||
|
||||
## Version 5.x
|
||||
|
||||
- [CSS](#css)
|
||||
|
||||
615
CHANGELOG.md
615
CHANGELOG.md
@@ -1,55 +1,3 @@
|
||||
# Change Log
|
||||
|
||||
All notable changes to this project will be documented in this file.
|
||||
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
|
||||
|
||||
## [6.0.2](https://github.com/ionic-team/ionic-framework/compare/v6.0.1...v6.0.2) (2022-01-11)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* **angular:** attach change detector ref for inline overlays ([#24521](https://github.com/ionic-team/ionic-framework/issues/24521)) ([5c54593](https://github.com/ionic-team/ionic-framework/commit/5c54593dde64ae61347568405ebf74502cfff370)), closes [#24502](https://github.com/ionic-team/ionic-framework/issues/24502)
|
||||
* **angular:** popover will respect side attribute value ([#24470](https://github.com/ionic-team/ionic-framework/issues/24470)) ([e6955a2](https://github.com/ionic-team/ionic-framework/commit/e6955a26b92fc536c5c73b60b5943881c7d58ee1)), closes [#24466](https://github.com/ionic-team/ionic-framework/issues/24466)
|
||||
* **breadcrumb:** support routerLink on breadcrumb ([#24509](https://github.com/ionic-team/ionic-framework/issues/24509)) ([5bb1414](https://github.com/ionic-team/ionic-framework/commit/5bb1414f7fa04ea07954cb3f68883ee2f162586a)), closes [#24493](https://github.com/ionic-team/ionic-framework/issues/24493)
|
||||
* **css:** inline css source in source maps ([#24514](https://github.com/ionic-team/ionic-framework/issues/24514)) ([987d46c](https://github.com/ionic-team/ionic-framework/commit/987d46cfa6e48a932330f04f2e8eb7054b11baf8)), closes [#24441](https://github.com/ionic-team/ionic-framework/issues/24441)
|
||||
* **datetime:** add top padding to MD calendar month grid ([#24522](https://github.com/ionic-team/ionic-framework/issues/24522)) ([bd82b5d](https://github.com/ionic-team/ionic-framework/commit/bd82b5dc1d06ba22a5410858802d57735fdcf450)), closes [#24408](https://github.com/ionic-team/ionic-framework/issues/24408)
|
||||
* **datetime:** RTL will no longer infinitely scroll ([#24475](https://github.com/ionic-team/ionic-framework/issues/24475)) ([8f00008](https://github.com/ionic-team/ionic-framework/commit/8f000089c2986f292147c7f501f23c8c7d1df457)), closes [#24472](https://github.com/ionic-team/ionic-framework/issues/24472)
|
||||
* **datetime:** time picker format with hourCycle h23 ([#24476](https://github.com/ionic-team/ionic-framework/issues/24476)) ([a3724e6](https://github.com/ionic-team/ionic-framework/commit/a3724e6a5662c5bc1b724d80540530472827506e)), closes [#24474](https://github.com/ionic-team/ionic-framework/issues/24474)
|
||||
* **datetime:** update active day styling when day is selected ([#24454](https://github.com/ionic-team/ionic-framework/issues/24454)) ([4304391](https://github.com/ionic-team/ionic-framework/commit/430439191dba824c11290d7f8622fea10ced6c40)), closes [#24414](https://github.com/ionic-team/ionic-framework/issues/24414) [#24451](https://github.com/ionic-team/ionic-framework/issues/24451)
|
||||
* **datetime:** wheel picker shows correct column order in rtl ([#24546](https://github.com/ionic-team/ionic-framework/issues/24546)) ([c90ce31](https://github.com/ionic-team/ionic-framework/commit/c90ce311a86ccb7c06b1cde91a4659f6682df04d)), closes [#24378](https://github.com/ionic-team/ionic-framework/issues/24378)
|
||||
* **overlays:** define custom element children ([#24439](https://github.com/ionic-team/ionic-framework/issues/24439)) ([4715b83](https://github.com/ionic-team/ionic-framework/commit/4715b83abb30ec5930710d16e5bfe8fc88a940ce)), closes [#24393](https://github.com/ionic-team/ionic-framework/issues/24393)
|
||||
* **popover:** allow arrow configuration with controller approach ([#24512](https://github.com/ionic-team/ionic-framework/issues/24512)) ([b39003a](https://github.com/ionic-team/ionic-framework/commit/b39003a4c67cd7e01d09be012c9e12d99ca1730a)), closes [#24487](https://github.com/ionic-team/ionic-framework/issues/24487)
|
||||
* **radio:** fix radio not showing checked state when not in a group ([#24423](https://github.com/ionic-team/ionic-framework/issues/24423)) ([94a781c](https://github.com/ionic-team/ionic-framework/commit/94a781cb6a3d92c5e6cab1a7603bfe25826a753c))
|
||||
* **react,vue:** backdrop for inline modal/popover overlay ([#24453](https://github.com/ionic-team/ionic-framework/issues/24453)) ([77f8412](https://github.com/ionic-team/ionic-framework/commit/77f8412b746222793cd9d17f12f50d512ab5e886)), closes [#24449](https://github.com/ionic-team/ionic-framework/issues/24449)
|
||||
* **react:** building app for production now works correctly with vite ([#24515](https://github.com/ionic-team/ionic-framework/issues/24515)) ([32fad3d](https://github.com/ionic-team/ionic-framework/commit/32fad3d02cb6b012a772de03eafe3e3a6b1300e0)), closes [#24229](https://github.com/ionic-team/ionic-framework/issues/24229)
|
||||
* **react:** scrolling to bottom of modal contents ([#24510](https://github.com/ionic-team/ionic-framework/issues/24510)) ([1462cef](https://github.com/ionic-team/ionic-framework/commit/1462cef69225e20582e2f9a0b8fd655ca2066b79)), closes [#24478](https://github.com/ionic-team/ionic-framework/issues/24478)
|
||||
* **refresher:** import icons to avoid errors in react and vue ([#24525](https://github.com/ionic-team/ionic-framework/issues/24525)) ([388622f](https://github.com/ionic-team/ionic-framework/commit/388622f9734b7b832bca3ede99820a7124faa618)), closes [#24480](https://github.com/ionic-team/ionic-framework/issues/24480)
|
||||
* **vue:** correct route is replaced when using router.replace ([#24533](https://github.com/ionic-team/ionic-framework/issues/24533)) ([90458da](https://github.com/ionic-team/ionic-framework/commit/90458da406e2f7a6675be185409ea78595a35128)), closes [#24226](https://github.com/ionic-team/ionic-framework/issues/24226)
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
## [6.0.1](https://github.com/ionic-team/ionic/compare/v6.0.0...v6.0.1) (2021-12-15)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* **datetime:** datetime now appears correctly when presented in modal ([#24385](https://github.com/ionic-team/ionic/issues/24385)) ([e7d0674](https://github.com/ionic-team/ionic/commit/e7d06743ae2e09864510940bf8a97bc312ef1cf8)), closes [#24112](https://github.com/ionic-team/ionic-framework/issues/24112)
|
||||
* **item:** remove empty padding space for item bottom ([#24323](https://github.com/ionic-team/ionic/issues/24323)) ([500985c](https://github.com/ionic-team/ionic/commit/500985ce04783f502a1f5c50fbd8b4c5e93294d7)), closes [#23892](https://github.com/ionic-team/ionic/issues/23892)
|
||||
* **modal:** fix timing issue when rapidly closing and opening controller modal ([#24380](https://github.com/ionic-team/ionic/issues/24380)) ([732f8e1](https://github.com/ionic-team/ionic/commit/732f8e10ce604f1a3e98518ae9c3a4afd7803e9a)), closes [#24230](https://github.com/ionic-team/ionic-framework/issues/24230)
|
||||
* **overlays:** define children custom elements for picker ([#24372](https://github.com/ionic-team/ionic/issues/24372)) ([7c700b4](https://github.com/ionic-team/ionic/commit/7c700b4caa35d7eb50c877d794f9db9fad6ed88b)), closes [#24366](https://github.com/ionic-team/ionic/issues/24366)
|
||||
* **vue:** improve query params handling in tabs ([#24355](https://github.com/ionic-team/ionic/issues/24355)) ([6309d5d](https://github.com/ionic-team/ionic/commit/6309d5ddbaa7da5e37eda4e19866baf380069578)), closes [#24353](https://github.com/ionic-team/ionic/issues/24353)
|
||||
* **vue:** strongly typed controller methods ([#24388](https://github.com/ionic-team/ionic/issues/24388)) ([a5d56b3](https://github.com/ionic-team/ionic/commit/a5d56b3d5a0a64fd4c62f4beab69a3a1681c0b70)), closes [#24387](https://github.com/ionic-team/ionic/issues/24387)
|
||||
* **vue:** tabs no longer get unmounted when navigating back to a tabs context ([#24337](https://github.com/ionic-team/ionic/issues/24337)) ([bf8e436](https://github.com/ionic-team/ionic/commit/bf8e436ee3f7441ebbc7eaf53ec8d04545dab476)), closes [#24332](https://github.com/ionic-team/ionic/issues/24332)
|
||||
|
||||
|
||||
### Performance Improvements
|
||||
|
||||
* **content:** remove global click listener to improve interaction performance ([#24360](https://github.com/ionic-team/ionic/issues/24360)) ([1bfac52](https://github.com/ionic-team/ionic/commit/1bfac52331d3f296e5721b2a6c3fd94a97450a1d)), closes [#24359](https://github.com/ionic-team/ionic/issues/24359)
|
||||
|
||||
|
||||
|
||||
## [5.9.3](https://github.com/ionic-team/ionic/compare/v5.9.2...v5.9.3) (2021-12-15)
|
||||
|
||||
|
||||
@@ -65,34 +13,6 @@ See [Conventional Commits](https://conventionalcommits.org) for commit guideline
|
||||
|
||||
|
||||
|
||||
# [6.0.0 Titanium](https://github.com/ionic-team/ionic/compare/v6.0.0-rc.4...v6.0.0) (2021-12-08)
|
||||
|
||||
Enjoy! 🚀
|
||||
|
||||
> We recommend updating to version `5.9.2` before updating to version `6.0.0` in order to see deprecation warnings related to your app [in the developer console](https://javascript.info/devtools).
|
||||
|
||||
Please see the [Ionic 6 Upgrade Guide](https://ionicframework.com/docs/next/intro/upgrading-to-ionic-6) for a step-by-step list of what you need to do to get started with Ionic 6.
|
||||
|
||||
# [6.0.0-rc.4](https://github.com/ionic-team/ionic/compare/v6.0.0-rc.3...v6.0.0-rc.4) (2021-12-07)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* **accordion:** improve functionality with nested accordions ([#24302](https://github.com/ionic-team/ionic/issues/24302)) ([0920797](https://github.com/ionic-team/ionic/commit/0920797612a5ee3aac1c38d8bffe4fd1e80b6987))
|
||||
* **content:** ensure scrollEl is always available in scroll methods ([#24255](https://github.com/ionic-team/ionic/issues/24255)) ([36a096c](https://github.com/ionic-team/ionic/commit/36a096c9b60bd6b3b086f2c966a1cd40dbc54473)), closes [#24168](https://github.com/ionic-team/ionic-framework/issues/24168)
|
||||
* **datetime:** keyboard navigation now works in time picker ([#24251](https://github.com/ionic-team/ionic/issues/24251)) ([8bdcd3c](https://github.com/ionic-team/ionic/commit/8bdcd3c6c99d84a0a46b0f08dceca6b6929fd8f8)), closes [#24070](https://github.com/ionic-team/ionic-framework/issues/24070)
|
||||
* **datetime:** prevent multiple items from being highlighted at once in month/year and time pickers ([#24268](https://github.com/ionic-team/ionic/issues/24268)) ([c2bef8d](https://github.com/ionic-team/ionic/commit/c2bef8df14111dc00c382a3ab36c27a08a92f0b7)), closes [#24067](https://github.com/ionic-team/ionic-framework/issues/24067)
|
||||
* **datetime:** update active calendar display when value changes ([#24244](https://github.com/ionic-team/ionic/issues/24244)) ([ec3bc52](https://github.com/ionic-team/ionic/commit/ec3bc52ff194f1e4db4ce49548c1418c259b8795)), closes [#24241](https://github.com/ionic-team/ionic-framework/issues/24241)
|
||||
* **item:** counter property now defaults to false to make upgrade easier ([#24263](https://github.com/ionic-team/ionic/issues/24263)) ([f61f356](https://github.com/ionic-team/ionic/commit/f61f35600072c5df069a24c3b24eb8f283d586f8))
|
||||
* **react, vue:** remove side effects to improve treeshaking ([#24313](https://github.com/ionic-team/ionic/issues/24313)) ([13d4418](https://github.com/ionic-team/ionic/commit/13d4418588b98d301b05ebd94e0eac670163a553)), closes [#24280](https://github.com/ionic-team/ionic-framework/issues/24280)
|
||||
|
||||
|
||||
### Features
|
||||
|
||||
* **react:** add setupIonicReact function ([#24254](https://github.com/ionic-team/ionic/issues/24254)) ([55db38d](https://github.com/ionic-team/ionic/commit/55db38ddc541c2632c7d3e4e4c9400ff5b5dfe8c)), closes [#24139](https://github.com/ionic-team/ionic/issues/24139)
|
||||
|
||||
|
||||
|
||||
## [5.9.2](https://github.com/ionic-team/ionic/compare/v5.9.1...v5.9.2) (2021-12-07)
|
||||
|
||||
|
||||
@@ -110,285 +30,6 @@ Please see the [Ionic 6 Upgrade Guide](https://ionicframework.com/docs/next/intr
|
||||
|
||||
|
||||
|
||||
# [6.0.0-rc.3](https://github.com/ionic-team/ionic/compare/v6.0.0-rc.2...v6.0.0-rc.3) (2021-11-17)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* **all:** Ionic components that use child Ionic components are now correctly defined ([#24191](https://github.com/ionic-team/ionic/issues/24191)) ([5a2a335](https://github.com/ionic-team/ionic/commit/5a2a335784aab581cda90448193e48f687df6b15)), closes [#23571](https://github.com/ionic-team/ionic/issues/23571) [#24116](https://github.com/ionic-team/ionic/issues/24116) [#24129](https://github.com/ionic-team/ionic/issues/24129)
|
||||
* **angular:** prevent duplicate event emissions ([#24200](https://github.com/ionic-team/ionic/issues/24200)) ([fc1eae9](https://github.com/ionic-team/ionic/commit/fc1eae982d7493f5b69fb18829f9c796f05a0d47))
|
||||
* **icon:** update to ionicons 6 to resolve typescript 4.4 errors ([#24185](https://github.com/ionic-team/ionic/issues/24185)) ([118c606](https://github.com/ionic-team/ionic/commit/118c606703f792f830d92f1148882b5daa3f180f))
|
||||
* **input:** date type in ion-input now aligns correctly on iOS 15 ([#24213](https://github.com/ionic-team/ionic/issues/24213)) ([9cf7c89](https://github.com/ionic-team/ionic/commit/9cf7c897043854a9d0db81d18ad6c016eb964de8))
|
||||
* **input:** ionInput event emits with type of InputEvent ([#24111](https://github.com/ionic-team/ionic/issues/24111)) ([52cd5d0](https://github.com/ionic-team/ionic/commit/52cd5d0ccedb8013c860198fc69f6bc0d4e6d386))
|
||||
* **item:** allow click targets inside of label ([#24225](https://github.com/ionic-team/ionic/issues/24225)) ([3949a94](https://github.com/ionic-team/ionic/commit/3949a949dfe112668c69a36d64e5f01a5aef1435))
|
||||
* **label:** apply error appearance when control is touched ([#24072](https://github.com/ionic-team/ionic/issues/24072)) ([009dff5](https://github.com/ionic-team/ionic/commit/009dff5584fea6398bb99aa55760d25dafd7fbcc))
|
||||
* **modal, popover:** opening modal and popover now works even if overlay was added to ion-app directly ([#24174](https://github.com/ionic-team/ionic/issues/24174)) ([da339a8](https://github.com/ionic-team/ionic/commit/da339a8a743548f9bde8b5a22f1a9d6b191f6e7b)), closes [#23728](https://github.com/ionic-team/ionic/issues/23728)
|
||||
* **modal:** border radius is now correctly applied to card modals ([#24204](https://github.com/ionic-team/ionic/issues/24204)) ([1f4f8eb](https://github.com/ionic-team/ionic/commit/1f4f8eb6ca2b8adb543ade83c309177ac7f2044d))
|
||||
* **modal:** card modal shadow now shows up correctly on ipad ([#24203](https://github.com/ionic-team/ionic/issues/24203)) ([5d4f5af](https://github.com/ionic-team/ionic/commit/5d4f5af36083eafcf7de91b22749ff307701087f))
|
||||
* **overlays:** declarative modals now work properly with the hardware back button ([#24165](https://github.com/ionic-team/ionic/issues/24165)) ([b3759ae](https://github.com/ionic-team/ionic/commit/b3759aed5bd1ec6a7c744af03d0dac9c8055c5af))
|
||||
* **react:** improve component compatibility with preact ([#24132](https://github.com/ionic-team/ionic/issues/24132)) ([15fc293](https://github.com/ionic-team/ionic/commit/15fc293d75aa21426616459c2596b46e2d460f49)), closes [#23516](https://github.com/ionic-team/ionic/issues/23516)
|
||||
* **textarea:** floating label layout is correct with autogrow textareas ([#24202](https://github.com/ionic-team/ionic/issues/24202)) ([713f0f5](https://github.com/ionic-team/ionic/commit/713f0f55261205d3f7e25874939cb1f998f38d4a))
|
||||
|
||||
|
||||
|
||||
# [6.0.0-rc.2](https://github.com/ionic-team/ionic/compare/v6.0.0-rc.1...v6.0.0-rc.2) (2021-11-03)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* **datetime:** resolve month and year jumping issue on ios ([#24142](https://github.com/ionic-team/ionic/issues/24142)) ([27aef93](https://github.com/ionic-team/ionic/commit/27aef9343cada9a83adec8fe00e8bc3bafa8e049)), closes [#23910](https://github.com/ionic-team/ionic/issues/23910)
|
||||
|
||||
|
||||
|
||||
# [6.0.0-rc.1](https://github.com/ionic-team/ionic/compare/v5.8.5...v6.0.0-rc.1) (2021-10-27)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* **accordion-group:** ionChange is now fired properly in vue ([#24063](https://github.com/ionic-team/ionic/issues/24063)) ([61b99d1](https://github.com/ionic-team/ionic/commit/61b99d13bfab5c57617cbcdc7e54e43f88885f66)), closes [#23762](https://github.com/ionic-team/ionic/issues/23762)
|
||||
* **datetime:** clear button is now rendered even if showDefaultButtons is false ([#24075](https://github.com/ionic-team/ionic/issues/24075)) ([e3996cf](https://github.com/ionic-team/ionic/commit/e3996cfbd50f5e9ae54ffcbe2594124e3b9969b0))
|
||||
* **datetime:** default sizing preserves shape of datetime ([#24104](https://github.com/ionic-team/ionic/issues/24104)) ([71fab0f](https://github.com/ionic-team/ionic/commit/71fab0fa124254f8cdc3b513627aa7b045993f4e))
|
||||
* **infinite-scroll:** infinite scroll event now fired with custom elements build ([#24043](https://github.com/ionic-team/ionic/issues/24043)) ([8a86cfb](https://github.com/ionic-team/ionic/commit/8a86cfb7050989e914fa85ccc1ea755d73f58c90)), closes [#24034](https://github.com/ionic-team/ionic/issues/24034)
|
||||
* **modal:** fix backdrop animation for sheets with off-center backdropBreakpoint ([#24061](https://github.com/ionic-team/ionic/issues/24061)) ([49db6d0](https://github.com/ionic-team/ionic/commit/49db6d02883b11b5f179300e2eaa298002a381e8))
|
||||
* **react:** overlays shown with useIonModal and useIonPopover no longer render outside of main react tree ([f3e492c](https://github.com/ionic-team/ionic/commit/f3e492c897c8cda2b98050156f130654f4d7014a)), closes [#23516](https://github.com/ionic-team/ionic/issues/23516) [#23516](https://github.com/ionic-team/ionic/issues/23516)
|
||||
|
||||
|
||||
### Features
|
||||
|
||||
* **angular:** build for angular 12.0 ([#23970](https://github.com/ionic-team/ionic/issues/23970)) ([3451a34](https://github.com/ionic-team/ionic/commit/3451a34ad0c893be0b6c17dc91ac9a75d2b9b52c))
|
||||
|
||||
|
||||
|
||||
# [6.0.0-rc.0](https://github.com/ionic-team/ionic/compare/v6.0.0-beta.7...v6.0.0-rc.0) (2021-10-07)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* **angular:** setup config properly ([#24028](https://github.com/ionic-team/ionic/issues/24028)) ([907996c](https://github.com/ionic-team/ionic/commit/907996ce16446d0dc12939da325b7b5dae09ebd9))
|
||||
|
||||
|
||||
|
||||
# [6.0.0-beta.7](https://github.com/ionic-team/ionic/compare/v5.8.2...v6.0.0-beta.7) (2021-10-06)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* **datetime:** add ionBlur/ionFocus events to whole component ([#23980](https://github.com/ionic-team/ionic/issues/23980)) ([86a77bd](https://github.com/ionic-team/ionic/commit/86a77bd379c6dca57d5feb9694d18afe6d82934d))
|
||||
* **datetime:** change now emitted when picker is typed into ([#24018](https://github.com/ionic-team/ionic/issues/24018)) ([0320164](https://github.com/ionic-team/ionic/commit/03201643ba9ae34fa969c1542742d9cd95298c81))
|
||||
* **datetime:** ionChange is no longer called for out of range dates ([#23940](https://github.com/ionic-team/ionic/issues/23940)) ([ea39c6e](https://github.com/ionic-team/ionic/commit/ea39c6e5b3781ceb4c87277cf4a5e0be9c75bc20)), closes [#23939](https://github.com/ionic-team/ionic/issues/23939)
|
||||
* **datetime:** time picker uses new iOS 15 style ([#23996](https://github.com/ionic-team/ionic/issues/23996)) ([0ab37b5](https://github.com/ionic-team/ionic/commit/0ab37b5061728bd60fd42781645b96add130a79f)), closes [#23768](https://github.com/ionic-team/ionic/issues/23768)
|
||||
* **modal:** backdropBreakpoint is now an exclusive value ([#23954](https://github.com/ionic-team/ionic/issues/23954)) ([ed455ab](https://github.com/ionic-team/ionic/commit/ed455ab4c6df73f801a3c941da21261c205c9634))
|
||||
* **react:** ensure inline modal content is visible ([#23968](https://github.com/ionic-team/ionic/issues/23968)) ([285a371](https://github.com/ionic-team/ionic/commit/285a371101e714e74d6df68701cbee9dfe23605e))
|
||||
* **reorder-group:** wait for content to render before getting scroll position ([#24007](https://github.com/ionic-team/ionic/issues/24007)) ([225a278](https://github.com/ionic-team/ionic/commit/225a2787407c5ce68a953ee3448647d00af26517)), closes [#23875](https://github.com/ionic-team/ionic/issues/23875)
|
||||
* **select:** ensure popover options with number values are searched for correctly ([#23998](https://github.com/ionic-team/ionic/issues/23998)) ([c204083](https://github.com/ionic-team/ionic/commit/c20408369bd332b5e225a3d50ec94978f6f5ec97))
|
||||
* **select:** focus selected item in popovers ([#23991](https://github.com/ionic-team/ionic/issues/23991)) ([2497a53](https://github.com/ionic-team/ionic/commit/2497a53255dc43052755bba842dfcf556d930dcd))
|
||||
|
||||
|
||||
### Features
|
||||
|
||||
* **all:** add CustomEvents types to components that emit events ([#23956](https://github.com/ionic-team/ionic/issues/23956)) ([8708095](https://github.com/ionic-team/ionic/commit/87080951112a409893a4bac2def1deca06642b16)), closes [#22925](https://github.com/ionic-team/ionic/issues/22925)
|
||||
* **header, footer:** add ios fading header style ([#24011](https://github.com/ionic-team/ionic/issues/24011)) ([7ce3959](https://github.com/ionic-team/ionic/commit/7ce3959b66a08e980c7dac3bb7d7df6bf0ae874e))
|
||||
|
||||
|
||||
### BREAKING CHANGES
|
||||
|
||||
* **all:** The `RadioChangeEventDetail` interface has been removed in favor of `RadioGroupChangeEventDetail`.
|
||||
|
||||
|
||||
|
||||
# [6.0.0-beta.6](https://github.com/ionic-team/ionic/compare/v5.8.0...v6.0.0-beta.6) (2021-09-15)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* **modal:** add sheet modal properties for angular ([#23899](https://github.com/ionic-team/ionic/issues/23899)) ([d1763fc](https://github.com/ionic-team/ionic/commit/d1763fc8b56c8cb5272224ae0faaebfe3e516fdb))
|
||||
* **modal:** expose breakpoint props in ModalOptions interface ([#23867](https://github.com/ionic-team/ionic/issues/23867)) ([5fd80fd](https://github.com/ionic-team/ionic/commit/5fd80fd43885a5d0cd65f0eef4e0ff15e82c4fe0)), closes [#23866](https://github.com/ionic-team/ionic/issues/23866)
|
||||
* **modal:** handle on sheet modal can now be turned off ([#23900](https://github.com/ionic-team/ionic/issues/23900)) ([e2d2ad6](https://github.com/ionic-team/ionic/commit/e2d2ad6f8eaf798c6f4b4a69f2b8176f0ac22d32))
|
||||
* **modal:** modal displays in middle of screen on desktop ([#23911](https://github.com/ionic-team/ionic/issues/23911)) ([9d87028](https://github.com/ionic-team/ionic/commit/9d87028e81723a0f1498c8cf231319676078eda0))
|
||||
* **modal:** sheet animation works correctly if breakpoints value does not include 1 ([#23927](https://github.com/ionic-team/ionic/issues/23927)) ([414f246](https://github.com/ionic-team/ionic/commit/414f24685cbc67a7fff142b7786d33ce1cd67a0c))
|
||||
* **modal:** sheet modal handle is now positioned correctly ([#23901](https://github.com/ionic-team/ionic/issues/23901)) ([58a4ba2](https://github.com/ionic-team/ionic/commit/58a4ba285389e45276df49a0b4a3412daa95e92c))
|
||||
* **modal:** sheet modal now accounts for safe area ([#23884](https://github.com/ionic-team/ionic/issues/23884)) ([195d817](https://github.com/ionic-team/ionic/commit/195d8179676155315f8532636b6371dd2a63e4b9)), closes [#23874](https://github.com/ionic-team/ionic/issues/23874)
|
||||
|
||||
|
||||
### Features
|
||||
|
||||
* **datetime:** add ability to select only month, year, or month and year ([#23913](https://github.com/ionic-team/ionic/issues/23913)) ([4ae44b7](https://github.com/ionic-team/ionic/commit/4ae44b7a236004738d593406d7b1236600bc6d95))
|
||||
* **datetime:** add clear button ([#23920](https://github.com/ionic-team/ionic/issues/23920)) ([18765e7](https://github.com/ionic-team/ionic/commit/18765e7e39b9f205f47f394d26d6ecc4b53e17ef)), closes [#17482](https://github.com/ionic-team/ionic/issues/17482)
|
||||
* **menu:** add console error for incorrect usage of contentId ([#23871](https://github.com/ionic-team/ionic/issues/23871)) ([879ab8e](https://github.com/ionic-team/ionic/commit/879ab8ebdacc1468ed206701c00b60100dbab9e4)), closes [#23810](https://github.com/ionic-team/ionic/issues/23810)
|
||||
* **platform:** add ability to override platform detection methods ([#23915](https://github.com/ionic-team/ionic/issues/23915)) ([45cabae](https://github.com/ionic-team/ionic/commit/45cabae04bf9236cd069793fbf2ac8f68c372cc3)), closes [#19737](https://github.com/ionic-team/ionic/issues/19737)
|
||||
* **react:** add custom elements bundle ([#23896](https://github.com/ionic-team/ionic/issues/23896)) ([c50d895](https://github.com/ionic-team/ionic/commit/c50d895370a56d0809019dc59fe32ec840b72f03))
|
||||
|
||||
|
||||
|
||||
# [6.0.0-beta.5](https://github.com/ionic-team/ionic/compare/v5.7.0...v6.0.0-beta.5) (2021-09-01)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* **angular:** overlay interfaces are now properly exported ([#23847](https://github.com/ionic-team/ionic/issues/23847)) ([c925274](https://github.com/ionic-team/ionic/commit/c925274c3bb22532a323b2a07771d7448f7de542)), closes [#23846](https://github.com/ionic-team/ionic/issues/23846)
|
||||
* **datetime:** prevent vertical page scroll on interaction ([#23780](https://github.com/ionic-team/ionic/issues/23780)) ([950350a](https://github.com/ionic-team/ionic/commit/950350a948320f889589a0c9d2ec9045637215e5)), closes [#23554](https://github.com/ionic-team/ionic/issues/23554)
|
||||
* **item:** form validation states are now properly shown ([#23853](https://github.com/ionic-team/ionic/issues/23853)) ([5ca2ce9](https://github.com/ionic-team/ionic/commit/5ca2ce91971408218d7bdc52509ce61a6ebb46aa)), closes [#23733](https://github.com/ionic-team/ionic/issues/23733) [#23850](https://github.com/ionic-team/ionic/issues/23850)
|
||||
* **overlays:** thrown errors are no longer suppressed ([#23831](https://github.com/ionic-team/ionic/issues/23831)) ([a212eb5](https://github.com/ionic-team/ionic/commit/a212eb52599e35d3706e2d3cef751e490e3a7259)), closes [#22724](https://github.com/ionic-team/ionic/issues/22724)
|
||||
|
||||
|
||||
### Features
|
||||
|
||||
* **modal:** add bottom sheet functionality ([#23828](https://github.com/ionic-team/ionic/issues/23828)) ([12216d3](https://github.com/ionic-team/ionic/commit/12216d378df091e16fd77d271b107e819278481c)), closes [#21039](https://github.com/ionic-team/ionic/issues/21039)
|
||||
* **popover:** add ability to pass event to present method ([#23827](https://github.com/ionic-team/ionic/issues/23827)) ([1d2ee92](https://github.com/ionic-team/ionic/commit/1d2ee92ca01b77bcf87c7783b50d59efcf0a402a)), closes [#23813](https://github.com/ionic-team/ionic/issues/23813)
|
||||
|
||||
|
||||
|
||||
# [6.0.0-beta.4](https://github.com/ionic-team/ionic/compare/v5.6.14...v6.0.0-beta.4) (2021-08-18)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* **datetime:** reduce time presentation min height ([#23771](https://github.com/ionic-team/ionic/issues/23771)) ([bc4e826](https://github.com/ionic-team/ionic/commit/bc4e8267aa00e7f162cd01579d8d3adbf3cd7a83)), closes [#23690](https://github.com/ionic-team/ionic/issues/23690)
|
||||
* **datetime:** text color on ios mode now accounts for color contrast ([#23729](https://github.com/ionic-team/ionic/issues/23729)) ([5980db4](https://github.com/ionic-team/ionic/commit/5980db44e5a765d15e681471325e916d566eca8d)), closes [#23723](https://github.com/ionic-team/ionic/issues/23723)
|
||||
* **item:** highlight now appears above helper/error text ([#23763](https://github.com/ionic-team/ionic/issues/23763)) ([2995e33](https://github.com/ionic-team/ionic/commit/2995e337c8b4612a87eb7111224ec702494fd1d7)), closes [#23510](https://github.com/ionic-team/ionic/issues/23510)
|
||||
* **toast:** ToastOptions interface now contains icon prop ([#23737](https://github.com/ionic-team/ionic/issues/23737)) ([fbd32ff](https://github.com/ionic-team/ionic/commit/fbd32ffb2633b17d71a34a8760386a319f2e2bca)), closes [#23736](https://github.com/ionic-team/ionic/issues/23736)
|
||||
* **vue:** custom element internal properties are no longer overridden in vue 3.1.0 ([#23738](https://github.com/ionic-team/ionic/issues/23738)) ([ea39c70](https://github.com/ionic-team/ionic/commit/ea39c70b3ec78b2ea5ef64263e8528b543378784)), closes [#23539](https://github.com/ionic-team/ionic/issues/23539)
|
||||
* **vue:** modal and popover components now correctly pass properties ([#23761](https://github.com/ionic-team/ionic/issues/23761)) ([578b906](https://github.com/ionic-team/ionic/commit/578b9062dd793c8526b80a769d94aa7aad8fe368)), closes [#23698](https://github.com/ionic-team/ionic/issues/23698)
|
||||
|
||||
|
||||
### Features
|
||||
|
||||
* **action-sheet:** add data property to ActionSheetButton ([#23744](https://github.com/ionic-team/ionic/issues/23744)) ([30f8508](https://github.com/ionic-team/ionic/commit/30f8508296cfc8f8b1c03d04b24abfa184624200)), closes [#23700](https://github.com/ionic-team/ionic/issues/23700)
|
||||
* **datetime:** add firstDayOfWeek property ([#23692](https://github.com/ionic-team/ionic/issues/23692)) ([ea348f0](https://github.com/ionic-team/ionic/commit/ea348f005aef7b2fda581a99338139f6fefcda63)), closes [#23556](https://github.com/ionic-team/ionic/issues/23556)
|
||||
* **datetime:** add hourCycle property ([#23686](https://github.com/ionic-team/ionic/issues/23686)) ([6342fde](https://github.com/ionic-team/ionic/commit/6342fde56c7687703edd212b8383536c8b9a6400)), closes [#23661](https://github.com/ionic-team/ionic/issues/23661)
|
||||
|
||||
|
||||
|
||||
# [6.0.0-beta.3](https://github.com/ionic-team/ionic/compare/v5.6.13...v6.0.0-beta.3) (2021-08-04)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* **list:** change inset border radius to match iOS 15 ([#23711](https://github.com/ionic-team/ionic/issues/23711)) ([fe2810b](https://github.com/ionic-team/ionic/commit/fe2810b227abc482e663b210cd89f29b76119ff5))
|
||||
* **popover:** fix keyboard arrow navigation ([#23709](https://github.com/ionic-team/ionic/issues/23709)) ([f2e7a26](https://github.com/ionic-team/ionic/commit/f2e7a267973a06b50a0f6dcbba0a204930bccf69)), closes [#23512](https://github.com/ionic-team/ionic/issues/23512)
|
||||
* **vue:** popover positioning is now correct with custom elements build ([#23680](https://github.com/ionic-team/ionic/issues/23680)) ([3a1a9cb](https://github.com/ionic-team/ionic/commit/3a1a9cbce45ad128c9ba87940535dabfa167fb9e))
|
||||
|
||||
|
||||
### Features
|
||||
|
||||
* **toast:** add icon property to show icon at start of toast content ([#23596](https://github.com/ionic-team/ionic/issues/23596)) ([df24c8c](https://github.com/ionic-team/ionic/commit/df24c8c5ae0b493841c07c05e0d620fa4a90c05a)), closes [#23524](https://github.com/ionic-team/ionic/issues/23524)
|
||||
|
||||
|
||||
|
||||
# [6.0.0-beta.2](https://github.com/ionic-team/ionic/compare/v5.6.12...v6.0.0-beta.2) (2021-07-21)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* **accordion:** value can now be set as string when using multiple is true ([#23581](https://github.com/ionic-team/ionic/issues/23581)) ([8f172de](https://github.com/ionic-team/ionic/commit/8f172de355bc7c910d600ce4d8446b04a6212545)), closes [#23550](https://github.com/ionic-team/ionic/issues/23550)
|
||||
* **angular:** modal and popover now have correct props defined on angular component ([#23565](https://github.com/ionic-team/ionic/issues/23565)) ([e5a7b34](https://github.com/ionic-team/ionic/commit/e5a7b342623b159d41cc83e0a418fb3984ceb3a7))
|
||||
* **datetime:** add keyboard year navigation ([#23585](https://github.com/ionic-team/ionic/issues/23585)) ([55bd1f7](https://github.com/ionic-team/ionic/commit/55bd1f749bac01cc691e16283728c42e755cc706)), closes [#21553](https://github.com/ionic-team/ionic/issues/21553) [#18122](https://github.com/ionic-team/ionic/issues/18122)
|
||||
* **datetime:** selecting time now works correctly on firefox ([#23583](https://github.com/ionic-team/ionic/issues/23583)) ([4188964](https://github.com/ionic-team/ionic/commit/4188964dc8da2c46494245b81864ca6e305611f5)), closes [#23545](https://github.com/ionic-team/ionic/issues/23545)
|
||||
* **datetime:** years displayed now more consistent with v5 datetime, max and min are now accounted for in MD mode ([#23616](https://github.com/ionic-team/ionic/issues/23616)) ([be219a2](https://github.com/ionic-team/ionic/commit/be219a2814800927e6328ff105616713003340b7)), closes [#23615](https://github.com/ionic-team/ionic/issues/23615)
|
||||
|
||||
|
||||
### Features
|
||||
|
||||
* **breadcrumbs:** ionCollapsedClick event payload now contains references to collapsed breadcrumb elements ([#23611](https://github.com/ionic-team/ionic/issues/23611)) ([9ce57d2](https://github.com/ionic-team/ionic/commit/9ce57d2efb84130895a37e22e0fd7e5d713a9fa5)), closes [#23552](https://github.com/ionic-team/ionic/issues/23552)
|
||||
* **datetime:** add showDefaultTimeLabel property and time-label slot ([#23577](https://github.com/ionic-team/ionic/issues/23577)) ([7ac0109](https://github.com/ionic-team/ionic/commit/7ac010943b2c9ad42a1833153ea16ccffd169b91)), closes [#23555](https://github.com/ionic-team/ionic/issues/23555)
|
||||
* **datetime:** add size property ([#23649](https://github.com/ionic-team/ionic/issues/23649)) ([321341d](https://github.com/ionic-team/ionic/commit/321341d97dff98b76b69a1efce58923a80e92bc4)), closes [#23518](https://github.com/ionic-team/ionic/issues/23518)
|
||||
* **range:** add support for customizing pin format ([#22972](https://github.com/ionic-team/ionic/issues/22972)) ([8f2c4f7](https://github.com/ionic-team/ionic/commit/8f2c4f73db167503cdf60222f42bcaadf905b401))
|
||||
* **segment:** add keyboard navigation, add selectOnFocus property to control selection follow focus behavior ([#23590](https://github.com/ionic-team/ionic/issues/23590)) ([b6c53e5](https://github.com/ionic-team/ionic/commit/b6c53e539b0855fa95b0fe02e5fa74ce403b68b8)), closes [#23520](https://github.com/ionic-team/ionic/issues/23520)
|
||||
* **select:** update popover interface to match MD spec on desktop, allow multiple values in popover interface ([#23474](https://github.com/ionic-team/ionic/issues/23474)) ([2c07a15](https://github.com/ionic-team/ionic/commit/2c07a1566b6f8570f7e12a55ca8f86d8fb8a968e)), closes [#23657](https://github.com/ionic-team/ionic/issues/23657) [#15500](https://github.com/ionic-team/ionic/issues/15500) [#12310](https://github.com/ionic-team/ionic/issues/12310)
|
||||
|
||||
|
||||
### Performance Improvements
|
||||
|
||||
* remove shims for legacy browsers no longer supported in v6 ([#23592](https://github.com/ionic-team/ionic/issues/23592)) ([259b135](https://github.com/ionic-team/ionic/commit/259b1359dbd20d4f85036ae46901a051cd8fc98b))
|
||||
|
||||
|
||||
|
||||
# [6.0.0-beta.1](https://github.com/ionic-team/ionic/compare/v5.6.11...v6.0.0-beta.1) (2021-07-01)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* **accordion:** improved reliability of accordion animations ([#23531](https://github.com/ionic-team/ionic/issues/23531)) ([6fbd60b](https://github.com/ionic-team/ionic/commit/6fbd60b0df56dc927226474a1ffa322d979c563e)), closes [#23504](https://github.com/ionic-team/ionic/issues/23504)
|
||||
* **content:** add touch-action manipulation for a11y zoom and pan ([#23534](https://github.com/ionic-team/ionic/issues/23534)) ([6ca1780](https://github.com/ionic-team/ionic/commit/6ca17805b8b1ea38d7fc16d091324da16a4193c6)), closes [#22805](https://github.com/ionic-team/ionic/issues/22805)
|
||||
* **datetime:** scroll position no longer gets reset when using datetime in overlay ([#23543](https://github.com/ionic-team/ionic/issues/23543)) ([b735b58](https://github.com/ionic-team/ionic/commit/b735b587cda777ac481bb580c883d9734145f31e))
|
||||
* **input, select, textarea:** change type of placeholder prop to string only ([#23500](https://github.com/ionic-team/ionic/issues/23500)) ([f3ae431](https://github.com/ionic-team/ionic/commit/f3ae4319bb64debab304973856a33e422ac910a1)), closes [#22976](https://github.com/ionic-team/ionic/issues/22976)
|
||||
* **popover:** size property now works when providing only event ([#23532](https://github.com/ionic-team/ionic/issues/23532)) ([bdc1f23](https://github.com/ionic-team/ionic/commit/bdc1f2360d7795472cc242a86eb4376d05fa0bb7)), closes [#23528](https://github.com/ionic-team/ionic/issues/23528)
|
||||
* **popover:** update animation to better match MD spec ([#23541](https://github.com/ionic-team/ionic/issues/23541)) ([bdb95b7](https://github.com/ionic-team/ionic/commit/bdb95b7b6dd798cbc6d1786ae54fa95ac1dfd096))
|
||||
* **react:** export accordion and accordion group components ([#23497](https://github.com/ionic-team/ionic/issues/23497)) ([a664d42](https://github.com/ionic-team/ionic/commit/a664d4268dea8e84ab9e3b150043ac8f87fb53c7))
|
||||
* **vue:** navigating between parameterized pages now results in page transition ([#23525](https://github.com/ionic-team/ionic/issues/23525)) ([e30b17c](https://github.com/ionic-team/ionic/commit/e30b17c5bbd1af6936a8d7a98d1f7a115073e029)), closes [#22662](https://github.com/ionic-team/ionic/issues/22662)
|
||||
|
||||
|
||||
### Features
|
||||
|
||||
* **accordion-group:** add animated property to disable animations ([#23530](https://github.com/ionic-team/ionic/issues/23530)) ([9a60dd0](https://github.com/ionic-team/ionic/commit/9a60dd0ea7c55acf0fdd1161433e5b4ed40778f2))
|
||||
* **action-sheet, alert:** add id to AlertButton and ActionSheetButton ([#18992](https://github.com/ionic-team/ionic/issues/18992)) ([9e24a0b](https://github.com/ionic-team/ionic/commit/9e24a0b49357a3a39ca89f026ff23271a365d935)), closes [#22959](https://github.com/ionic-team/ionic/issues/22959)
|
||||
* **vue:** extend useIonRouter hook for programmatic navigation with animation control ([#23499](https://github.com/ionic-team/ionic/issues/23499)) ([fc9e1b4](https://github.com/ionic-team/ionic/commit/fc9e1b4b361938e5644683c395a565be2de1eab9)), closes [#23450](https://github.com/ionic-team/ionic/issues/23450)
|
||||
|
||||
|
||||
### BREAKING CHANGES
|
||||
|
||||
* **input, select, textarea:** Updated the `placeholder` property on `ion-input`, `ion-textarea`, and `ion-select` to have a type of `string | undefined`.
|
||||
|
||||
|
||||
|
||||
# [6.0.0-beta.0](https://github.com/ionic-team/ionic/compare/v5.6.10...v6.0.0-beta.0) (2021-06-23)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* **accordion:** toggle icon now shows up in vue and react ([#23426](https://github.com/ionic-team/ionic/issues/23426)) ([c716617](https://github.com/ionic-team/ionic/commit/c7166179457a8e2c7e1702c5761bc6368dbd156f))
|
||||
* **datetime:** changing time emits ionChange ([#23463](https://github.com/ionic-team/ionic/issues/23463)) ([b0cce36](https://github.com/ionic-team/ionic/commit/b0cce360c83ac564e053523cc31b32d1deaeda0c))
|
||||
* **modal, popover:** overlays now automatically determine if they are inline ([#23434](https://github.com/ionic-team/ionic/issues/23434)) ([8dbe8ba](https://github.com/ionic-team/ionic/commit/8dbe8ba7bc26792c5024f81cf4752f5b78317492))
|
||||
* **modal:** add additional padding to toolbars in iOS modal ([#23262](https://github.com/ionic-team/ionic/issues/23262)) ([a037b65](https://github.com/ionic-team/ionic/commit/a037b65aad5cfc0477322a8f36105b9009366ec2)), closes [#22778](https://github.com/ionic-team/ionic/issues/22778)
|
||||
* **modal:** border radius is correctly set on card style modal ([#23461](https://github.com/ionic-team/ionic/issues/23461)) ([bccb8ad](https://github.com/ionic-team/ionic/commit/bccb8ad5fb5ec7f98a6cbfa62a403ecaca7fbdb6))
|
||||
* **popover:** shadow parts now correctly added ([#23446](https://github.com/ionic-team/ionic/issues/23446)) ([e1a9613](https://github.com/ionic-team/ionic/commit/e1a96130ebab1e481e880f0f3876f421976f08d5))
|
||||
* **popover:** update prop defaults, use correct delegate ([#23340](https://github.com/ionic-team/ionic/issues/23340)) ([960778a](https://github.com/ionic-team/ionic/commit/960778a36f6eb6318cc740c4f7a255107723b8fd))
|
||||
* **searchbar:** showClearButton now defaults to 'always' for improved usability with screen readers ([#23475](https://github.com/ionic-team/ionic/issues/23475)) ([80f181d](https://github.com/ionic-team/ionic/commit/80f181d4846507ee6bd4150bb568fca9b6660428))
|
||||
* **vue:** ensure webpack does not eliminate core css ([#23465](https://github.com/ionic-team/ionic/issues/23465)) ([ee3a00f](https://github.com/ionic-team/ionic/commit/ee3a00fde61b4d1d3168d34b3d23bb97dd154154))
|
||||
|
||||
|
||||
### Code Refactoring
|
||||
|
||||
* **all:** update required browser, framework, and mobile platform versions for v6 ([#23443](https://github.com/ionic-team/ionic/issues/23443)) ([c842dd8](https://github.com/ionic-team/ionic/commit/c842dd88c98888b2afab08ac5e8bc57c2a4c2fbd))
|
||||
* **angular:** remove Config.set() method ([#22918](https://github.com/ionic-team/ionic/issues/22918)) ([9e05891](https://github.com/ionic-team/ionic/commit/9e0589173607b3c0eff7794079123354c2eeaa1a))
|
||||
* **header:** removed border from last toolbar when using collapsible large title ([#22891](https://github.com/ionic-team/ionic/issues/22891)) ([c72bc5d](https://github.com/ionic-team/ionic/commit/c72bc5dbd76cd3ce622a4b3cedcb7446a2819384)), closes [#22777](https://github.com/ionic-team/ionic/issues/22777)
|
||||
* **ios:** update toolbar and tabbar default background colors ([#22852](https://github.com/ionic-team/ionic/issues/22852)) ([3d615cb](https://github.com/ionic-team/ionic/commit/3d615cb3c7b233b08b9da6ac04096e16bbb60bfc)), closes [#22780](https://github.com/ionic-team/ionic/issues/22780)
|
||||
* **toast:** whitespace variable now defaults to normal ([#22866](https://github.com/ionic-team/ionic/issues/22866)) ([9b78689](https://github.com/ionic-team/ionic/commit/9b786899e550c391b9395c669f9bba8f39ac98aa))
|
||||
* **vue:** drop support for "on" prefixed overlay events and bump minimum required version of vue to 3.0.6 ([#23229](https://github.com/ionic-team/ionic/issues/23229)) ([6fcb3a6](https://github.com/ionic-team/ionic/commit/6fcb3a62b1b12c5ded11179e83854592d4309bdf))
|
||||
* **vue:** remove support for child routes nested inside of tabs ([#22919](https://github.com/ionic-team/ionic/issues/22919)) ([75458ac](https://github.com/ionic-team/ionic/commit/75458ac7fb95f56a6ec460f85cf7d7720ce0c070))
|
||||
|
||||
|
||||
### Features
|
||||
|
||||
* **accordion:** add accordion and accordion-group components ([#22865](https://github.com/ionic-team/ionic/issues/22865)) ([073883a](https://github.com/ionic-team/ionic/commit/073883a0987149e9f6258ca43c46f5ed4bce0dc5)), closes [#17094](https://github.com/ionic-team/ionic/issues/17094)
|
||||
* **breadcrumbs:** add breadcrumbs component ([#22701](https://github.com/ionic-team/ionic/issues/22701)) ([2f6b1e4](https://github.com/ionic-team/ionic/commit/2f6b1e4eea307c6f14345704e5824378ef079acb)), closes [#22770](https://github.com/ionic-team/ionic/issues/22770)
|
||||
* **datetime:** add calendar picker ([#23416](https://github.com/ionic-team/ionic/issues/23416)) ([932d3ca](https://github.com/ionic-team/ionic/commit/932d3ca62f3e3ef08acb065ce6ec46faa3811f96)), closes [#19423](https://github.com/ionic-team/ionic/issues/19423)
|
||||
* **item:** add helper text, error text, counter, shape, and fill mode ([#23354](https://github.com/ionic-team/ionic/issues/23354)) ([faefe97](https://github.com/ionic-team/ionic/commit/faefe97da6a9d5beff1183d10efd0df9c4e3ebd7)), closes [#19619](https://github.com/ionic-team/ionic/issues/19619)
|
||||
* **modal:** modals can now be used inline ([#23341](https://github.com/ionic-team/ionic/issues/23341)) ([3be1c3d](https://github.com/ionic-team/ionic/commit/3be1c3dcd73e6039a89b19b409e63877cda37f6e)), closes [#20117](https://github.com/ionic-team/ionic/issues/20117) [#20263](https://github.com/ionic-team/ionic/issues/20263)
|
||||
* **popover:** account for ionShadowTarget elements ([#23436](https://github.com/ionic-team/ionic/issues/23436)) ([0e38d42](https://github.com/ionic-team/ionic/commit/0e38d4276110dcd94db5adc3b6aee3b5b0befc5c))
|
||||
* **popover:** add desktop support ([#23258](https://github.com/ionic-team/ionic/issues/23258)) ([a67a0fa](https://github.com/ionic-team/ionic/commit/a67a0fabb8249685bbe93ed862839e2b2e76cd5a)), closes [#21599](https://github.com/ionic-team/ionic/issues/21599)
|
||||
* **popover:** popover can now be used inline ([#23231](https://github.com/ionic-team/ionic/issues/23231)) ([308fa1c](https://github.com/ionic-team/ionic/commit/308fa1c0dd054cfc2ea54d2edc99e7a4b549f6f0))
|
||||
* **slides:** add IonicSwiper modules, deprecate ion-slides, and add link to migration ([#23447](https://github.com/ionic-team/ionic/issues/23447)) ([623c84a](https://github.com/ionic-team/ionic/commit/623c84ab082668a996c654e18ffc9768f68b85dd))
|
||||
* **spinner:** add lines-sharp, lines-sharp-small, update styles for ios 14 ([#22397](https://github.com/ionic-team/ionic/issues/22397)) ([2a5b272](https://github.com/ionic-team/ionic/commit/2a5b272a329bbad1ca07705f84f0fd06e3ef32ad))
|
||||
* **vue:** add custom elements bundle ([#23458](https://github.com/ionic-team/ionic/issues/23458)) ([dc48a9f](https://github.com/ionic-team/ionic/commit/dc48a9f1a2dff8a2d644112bbe1df8b0b6811848))
|
||||
|
||||
|
||||
### BREAKING CHANGES
|
||||
|
||||
* **searchbar:** The `showClearButton` property on `ion-searchbar` now defaults to `'always'`.
|
||||
* **datetime:** The `ion-datetime` component has been revamped to use a new calendar style. As a result, some APIs have been removed. See https://github.com/ionic-team/ionic-framework/blob/master/BREAKING.md for more details.
|
||||
* **all:** Browser, JS Framework, and mobile platform minimum required versions have been updated.
|
||||
* **popover:** Converted `ion-popover` to use the Shadow DOM.
|
||||
* **vue:** - Dropped support for prefixed overlay events in favor of non prefixed events (I.e. `@onDidDismiss` becomes `@didDismiss`).
|
||||
- Minimum required version of Vue is now Vue v3.0.6 or newer.
|
||||
* **vue:** Support for child routes nested inside of tabs has been removed to better conform to Vue Router's best practices. Additional routes should be written as sibling routes with the parent tab as the path prefix.
|
||||
* **angular:** The `Config.set()` method has been removed. See https://ionicframework.com/docs/angular/config for examples on how to set config globally, per-component, and per-platform.
|
||||
* **ios:** The tab bar and toolbar default background colors have been updated to better reflect the latest iOS styles.
|
||||
* **header:** The last toolbar in the header with a collapsible large title no longer has a border.
|
||||
* **toast:** The `--white-space` CSS Variable now defaults to `normal`.
|
||||
|
||||
|
||||
|
||||
## [5.9.1](https://github.com/ionic-team/ionic/compare/v5.9.0...v5.9.1) (2021-11-17)
|
||||
|
||||
|
||||
@@ -414,31 +55,6 @@ Please see the [Ionic 6 Upgrade Guide](https://ionicframework.com/docs/next/intr
|
||||
|
||||
|
||||
|
||||
# [6.0.0-rc.2](https://github.com/ionic-team/ionic/compare/v6.0.0-rc.1...v6.0.0-rc.2) (2021-11-03)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* **all:** resolve compilation issues with Stencil 2.10 ([#24152](https://github.com/ionic-team/ionic/issues/24152)) ([8b940e5](https://github.com/ionic-team/ionic-framework/commit/8b940e505e79bdf5da829850ed949847d5df8b90)), closes [#24153](https://github.com/ionic-team/ionic-framework/issues/24153)
|
||||
* **datetime:** resolve month and year jumping issue on ios ([#24142](https://github.com/ionic-team/ionic/issues/24142)) ([27aef93](https://github.com/ionic-team/ionic/commit/27aef9343cada9a83adec8fe00e8bc3bafa8e049)), closes [#23910](https://github.com/ionic-team/ionic/issues/23910)
|
||||
|
||||
|
||||
|
||||
# [6.0.0-rc.1](https://github.com/ionic-team/ionic/compare/v6.0.0-rc.0...v6.0.0-rc.1) (2021-10-27)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* **accordion-group:** ionChange is now fired properly in vue ([#24063](https://github.com/ionic-team/ionic/issues/24063)) ([61b99d1](https://github.com/ionic-team/ionic/commit/61b99d13bfab5c57617cbcdc7e54e43f88885f66)), closes [#23762](https://github.com/ionic-team/ionic/issues/23762)
|
||||
* **angular:** resolve issues with ng add on angular 12 ([#23970](https://github.com/ionic-team/ionic/issues/23970)) ([3451a34](https://github.com/ionic-team/ionic/commit/3451a34ad0c893be0b6c17dc91ac9a75d2b9b52c))
|
||||
* **datetime:** clear button is now rendered even if showDefaultButtons is false ([#24075](https://github.com/ionic-team/ionic/issues/24075)) ([e3996cf](https://github.com/ionic-team/ionic/commit/e3996cfbd50f5e9ae54ffcbe2594124e3b9969b0))
|
||||
* **datetime:** default sizing preserves shape of datetime ([#24104](https://github.com/ionic-team/ionic/issues/24104)) ([71fab0f](https://github.com/ionic-team/ionic/commit/71fab0fa124254f8cdc3b513627aa7b045993f4e))
|
||||
* **infinite-scroll:** infinite scroll event now fired with custom elements build ([#24043](https://github.com/ionic-team/ionic/issues/24043)) ([8a86cfb](https://github.com/ionic-team/ionic/commit/8a86cfb7050989e914fa85ccc1ea755d73f58c90)), closes [#24034](https://github.com/ionic-team/ionic/issues/24034)
|
||||
* **modal:** fix backdrop animation for sheets with off-center backdropBreakpoint ([#24061](https://github.com/ionic-team/ionic/issues/24061)) ([49db6d0](https://github.com/ionic-team/ionic/commit/49db6d02883b11b5f179300e2eaa298002a381e8))
|
||||
* **react:** overlays shown with useIonModal and useIonPopover no longer render outside of main react tree ([f3e492c](https://github.com/ionic-team/ionic/commit/f3e492c897c8cda2b98050156f130654f4d7014a)), closes [#23516](https://github.com/ionic-team/ionic/issues/23516) [#23516](https://github.com/ionic-team/ionic/issues/23516)
|
||||
|
||||
|
||||
|
||||
## [5.8.5](https://github.com/ionic-team/ionic/compare/v5.8.4...v5.8.5) (2021-10-27)
|
||||
|
||||
|
||||
@@ -460,15 +76,6 @@ Please see the [Ionic 6 Upgrade Guide](https://ionicframework.com/docs/next/intr
|
||||
|
||||
|
||||
|
||||
# [6.0.0-rc.0](https://github.com/ionic-team/ionic/compare/v6.0.0-beta.7...v6.0.0-rc.0) (2021-10-07)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* **angular:** setup config properly ([#24028](https://github.com/ionic-team/ionic/issues/24028)) ([907996c](https://github.com/ionic-team/ionic/commit/907996ce16446d0dc12939da325b7b5dae09ebd9))
|
||||
|
||||
|
||||
|
||||
## [5.8.3](https://github.com/ionic-team/ionic/compare/v5.8.2...v5.8.3) (2021-10-07)
|
||||
|
||||
|
||||
@@ -478,33 +85,6 @@ Please see the [Ionic 6 Upgrade Guide](https://ionicframework.com/docs/next/intr
|
||||
|
||||
|
||||
|
||||
# [6.0.0-beta.7](https://github.com/ionic-team/ionic/compare/v6.0.0-beta.6...v6.0.0-beta.7) (2021-10-06)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* **datetime:** ionBlur and ionFocus now fires correctly ([#23980](https://github.com/ionic-team/ionic/issues/23980)) ([86a77bd](https://github.com/ionic-team/ionic/commit/86a77bd379c6dca57d5feb9694d18afe6d82934d))
|
||||
* **datetime:** ionChange is no longer called for out of range dates ([#23940](https://github.com/ionic-team/ionic/issues/23940)) ([ea39c6e](https://github.com/ionic-team/ionic/commit/ea39c6e5b3781ceb4c87277cf4a5e0be9c75bc20)), closes [#23939](https://github.com/ionic-team/ionic/issues/23939)
|
||||
* **datetime:** time picker uses new iOS 15 style ([#23996](https://github.com/ionic-team/ionic/issues/23996)) ([0ab37b5](https://github.com/ionic-team/ionic/commit/0ab37b5061728bd60fd42781645b96add130a79f)), closes [#23768](https://github.com/ionic-team/ionic/issues/23768)
|
||||
* **modal:** backdropBreakpoint is now an exclusive value ([#23954](https://github.com/ionic-team/ionic/issues/23954)) ([ed455ab](https://github.com/ionic-team/ionic/commit/ed455ab4c6df73f801a3c941da21261c205c9634))
|
||||
* **react:** ensure inline modal content is visible ([#23968](https://github.com/ionic-team/ionic/issues/23968)) ([285a371](https://github.com/ionic-team/ionic/commit/285a371101e714e74d6df68701cbee9dfe23605e))
|
||||
* **reorder-group:** wait for content to render before getting scroll position ([#24007](https://github.com/ionic-team/ionic/issues/24007)) ([225a278](https://github.com/ionic-team/ionic/commit/225a2787407c5ce68a953ee3448647d00af26517)), closes [#23875](https://github.com/ionic-team/ionic/issues/23875)
|
||||
* **select:** ensure popover options with number values are searched for correctly ([#23998](https://github.com/ionic-team/ionic/issues/23998)) ([c204083](https://github.com/ionic-team/ionic/commit/c20408369bd332b5e225a3d50ec94978f6f5ec97))
|
||||
* **select:** focus selected item in popovers ([#23991](https://github.com/ionic-team/ionic/issues/23991)) ([2497a53](https://github.com/ionic-team/ionic/commit/2497a53255dc43052755bba842dfcf556d930dcd))
|
||||
|
||||
|
||||
### Features
|
||||
|
||||
* **all:** add CustomEvents types to components that emit events ([#23956](https://github.com/ionic-team/ionic/issues/23956)) ([8708095](https://github.com/ionic-team/ionic/commit/87080951112a409893a4bac2def1deca06642b16)), closes [#22925](https://github.com/ionic-team/ionic/issues/22925)
|
||||
* **header, footer:** add ios fading header style ([#24011](https://github.com/ionic-team/ionic/issues/24011)) ([7ce3959](https://github.com/ionic-team/ionic/commit/7ce3959b66a08e980c7dac3bb7d7df6bf0ae874e))
|
||||
|
||||
|
||||
### BREAKING CHANGES
|
||||
|
||||
* **radio:** The `RadioChangeEventDetail` interface has been removed in favor of `RadioGroupChangeEventDetail`.
|
||||
|
||||
|
||||
|
||||
## [5.8.2](https://github.com/ionic-team/ionic/compare/v5.8.1...v5.8.2) (2021-10-06)
|
||||
|
||||
|
||||
@@ -530,30 +110,6 @@ Please see the [Ionic 6 Upgrade Guide](https://ionicframework.com/docs/next/intr
|
||||
|
||||
|
||||
|
||||
# [6.0.0-beta.6](https://github.com/ionic-team/ionic/compare/v6.0.0-beta.5...v6.0.0-beta.6) (2021-09-15)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* **menu:** add console error for incorrect usage of contentId ([#23871](https://github.com/ionic-team/ionic/issues/23871)) ([879ab8e](https://github.com/ionic-team/ionic/commit/879ab8ebdacc1468ed206701c00b60100dbab9e4)), closes [#23810](https://github.com/ionic-team/ionic/issues/23810)
|
||||
* **modal:** add sheet modal properties for angular ([#23899](https://github.com/ionic-team/ionic/issues/23899)) ([d1763fc](https://github.com/ionic-team/ionic/commit/d1763fc8b56c8cb5272224ae0faaebfe3e516fdb))
|
||||
* **modal:** expose breakpoint props in ModalOptions interface ([#23867](https://github.com/ionic-team/ionic/issues/23867)) ([5fd80fd](https://github.com/ionic-team/ionic/commit/5fd80fd43885a5d0cd65f0eef4e0ff15e82c4fe0)), closes [#23866](https://github.com/ionic-team/ionic/issues/23866)
|
||||
* **modal:** handle on sheet modal can now be turned off ([#23900](https://github.com/ionic-team/ionic/issues/23900)) ([e2d2ad6](https://github.com/ionic-team/ionic/commit/e2d2ad6f8eaf798c6f4b4a69f2b8176f0ac22d32))
|
||||
* **modal:** modal displays in middle of screen on desktop ([#23911](https://github.com/ionic-team/ionic/issues/23911)) ([9d87028](https://github.com/ionic-team/ionic/commit/9d87028e81723a0f1498c8cf231319676078eda0))
|
||||
* **modal:** sheet animation works correctly if breakpoints value does not include 1 ([#23927](https://github.com/ionic-team/ionic/issues/23927)) ([414f246](https://github.com/ionic-team/ionic/commit/414f24685cbc67a7fff142b7786d33ce1cd67a0c))
|
||||
* **modal:** sheet modal handle is now positioned correctly ([#23901](https://github.com/ionic-team/ionic/issues/23901)) ([58a4ba2](https://github.com/ionic-team/ionic/commit/58a4ba285389e45276df49a0b4a3412daa95e92c))
|
||||
* **modal:** sheet modal now accounts for safe area ([#23884](https://github.com/ionic-team/ionic/issues/23884)) ([195d817](https://github.com/ionic-team/ionic/commit/195d8179676155315f8532636b6371dd2a63e4b9)), closes [#23874](https://github.com/ionic-team/ionic/issues/23874)
|
||||
|
||||
|
||||
### Features
|
||||
|
||||
* **datetime:** add ability to select only month, year, or month and year ([#23913](https://github.com/ionic-team/ionic/issues/23913)) ([4ae44b7](https://github.com/ionic-team/ionic/commit/4ae44b7a236004738d593406d7b1236600bc6d95))
|
||||
* **datetime:** add clear button ([#23920](https://github.com/ionic-team/ionic/issues/23920)) ([18765e7](https://github.com/ionic-team/ionic/commit/18765e7e39b9f205f47f394d26d6ecc4b53e17ef)), closes [#17482](https://github.com/ionic-team/ionic/issues/17482)
|
||||
* **platform:** add ability to override platform detection methods ([#23915](https://github.com/ionic-team/ionic/issues/23915)) ([45cabae](https://github.com/ionic-team/ionic/commit/45cabae04bf9236cd069793fbf2ac8f68c372cc3)), closes [#19737](https://github.com/ionic-team/ionic/issues/19737)
|
||||
* **react:** add custom elements bundle ([#23896](https://github.com/ionic-team/ionic/issues/23896)) ([c50d895](https://github.com/ionic-team/ionic/commit/c50d895370a56d0809019dc59fe32ec840b72f03))
|
||||
|
||||
|
||||
|
||||
# [5.8.0 Calcium](https://github.com/ionic-team/ionic/compare/v5.7.0...v5.8.0) (2021-09-15)
|
||||
|
||||
|
||||
@@ -572,24 +128,6 @@ Please see the [Ionic 6 Upgrade Guide](https://ionicframework.com/docs/next/intr
|
||||
|
||||
|
||||
|
||||
# [6.0.0-beta.5](https://github.com/ionic-team/ionic/compare/v6.0.0-beta.4...v6.0.0-beta.5) (2021-09-01)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* **angular:** overlay interfaces are now properly exported ([#23847](https://github.com/ionic-team/ionic/issues/23847)) ([c925274](https://github.com/ionic-team/ionic/commit/c925274c3bb22532a323b2a07771d7448f7de542)), closes [#23846](https://github.com/ionic-team/ionic/issues/23846)
|
||||
* **datetime:** prevent vertical page scroll on interaction ([#23780](https://github.com/ionic-team/ionic/issues/23780)) ([950350a](https://github.com/ionic-team/ionic/commit/950350a948320f889589a0c9d2ec9045637215e5)), closes [#23554](https://github.com/ionic-team/ionic/issues/23554)
|
||||
* **item:** form validation states are now properly shown ([#23853](https://github.com/ionic-team/ionic/issues/23853)) ([5ca2ce9](https://github.com/ionic-team/ionic/commit/5ca2ce91971408218d7bdc52509ce61a6ebb46aa)), closes [#23733](https://github.com/ionic-team/ionic/issues/23733) [#23850](https://github.com/ionic-team/ionic/issues/23850)
|
||||
* **overlays:** thrown errors are no longer suppressed ([#23831](https://github.com/ionic-team/ionic/issues/23831)) ([a212eb5](https://github.com/ionic-team/ionic/commit/a212eb52599e35d3706e2d3cef751e490e3a7259)), closes [#22724](https://github.com/ionic-team/ionic/issues/22724)
|
||||
|
||||
|
||||
### Features
|
||||
|
||||
* **modal:** add bottom sheet functionality ([#23828](https://github.com/ionic-team/ionic/issues/23828)) ([12216d3](https://github.com/ionic-team/ionic/commit/12216d378df091e16fd77d271b107e819278481c)), closes [#21039](https://github.com/ionic-team/ionic/issues/21039)
|
||||
* **popover:** add ability to pass event to present method ([#23827](https://github.com/ionic-team/ionic/issues/23827)) ([1d2ee92](https://github.com/ionic-team/ionic/commit/1d2ee92ca01b77bcf87c7783b50d59efcf0a402a)), closes [#23813](https://github.com/ionic-team/ionic/issues/23813)
|
||||
|
||||
|
||||
|
||||
# [5.7.0 Potassium](https://github.com/ionic-team/ionic/compare/v5.6.14...v5.7.0) (2021-09-01)
|
||||
|
||||
|
||||
@@ -611,27 +149,6 @@ Please see the [Ionic 6 Upgrade Guide](https://ionicframework.com/docs/next/intr
|
||||
|
||||
|
||||
|
||||
# [6.0.0-beta.4](https://github.com/ionic-team/ionic/compare/v6.0.0-beta.3...v6.0.0-beta.4) (2021-08-18)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* **datetime:** reduce time presentation min height ([#23771](https://github.com/ionic-team/ionic/issues/23771)) ([bc4e826](https://github.com/ionic-team/ionic/commit/bc4e8267aa00e7f162cd01579d8d3adbf3cd7a83)), closes [#23690](https://github.com/ionic-team/ionic/issues/23690)
|
||||
* **datetime:** text color on ios mode now accounts for color contrast ([#23729](https://github.com/ionic-team/ionic/issues/23729)) ([5980db4](https://github.com/ionic-team/ionic/commit/5980db44e5a765d15e681471325e916d566eca8d)), closes [#23723](https://github.com/ionic-team/ionic/issues/23723)
|
||||
* **item:** highlight now appears above helper/error text ([#23763](https://github.com/ionic-team/ionic/issues/23763)) ([2995e33](https://github.com/ionic-team/ionic/commit/2995e337c8b4612a87eb7111224ec702494fd1d7)), closes [#23510](https://github.com/ionic-team/ionic/issues/23510)
|
||||
* **toast:** ToastOptions interface now contains icon prop ([#23737](https://github.com/ionic-team/ionic/issues/23737)) ([fbd32ff](https://github.com/ionic-team/ionic/commit/fbd32ffb2633b17d71a34a8760386a319f2e2bca)), closes [#23736](https://github.com/ionic-team/ionic/issues/23736)
|
||||
* **vue:** custom element internal properties are no longer overridden in vue 3.1.0 ([#23738](https://github.com/ionic-team/ionic/issues/23738)) ([ea39c70](https://github.com/ionic-team/ionic/commit/ea39c70b3ec78b2ea5ef64263e8528b543378784)), closes [#23539](https://github.com/ionic-team/ionic/issues/23539)
|
||||
* **vue:** modal and popover components now correctly pass properties ([#23761](https://github.com/ionic-team/ionic/issues/23761)) ([578b906](https://github.com/ionic-team/ionic/commit/578b9062dd793c8526b80a769d94aa7aad8fe368)), closes [#23698](https://github.com/ionic-team/ionic/issues/23698)
|
||||
|
||||
|
||||
### Features
|
||||
|
||||
* **action-sheet:** add data property to ActionSheetButton ([#23744](https://github.com/ionic-team/ionic/issues/23744)) ([30f8508](https://github.com/ionic-team/ionic/commit/30f8508296cfc8f8b1c03d04b24abfa184624200)), closes [#23700](https://github.com/ionic-team/ionic/issues/23700)
|
||||
* **datetime:** add firstDayOfWeek property ([#23692](https://github.com/ionic-team/ionic/issues/23692)) ([ea348f0](https://github.com/ionic-team/ionic/commit/ea348f005aef7b2fda581a99338139f6fefcda63)), closes [#23556](https://github.com/ionic-team/ionic/issues/23556)
|
||||
* **datetime:** add hourCycle property ([#23686](https://github.com/ionic-team/ionic/issues/23686)) ([6342fde](https://github.com/ionic-team/ionic/commit/6342fde56c7687703edd212b8383536c8b9a6400)), closes [#23661](https://github.com/ionic-team/ionic/issues/23661)
|
||||
|
||||
|
||||
|
||||
## [5.6.14](https://github.com/ionic-team/ionic/compare/v5.6.13...v5.6.14) (2021-08-18)
|
||||
|
||||
|
||||
@@ -645,22 +162,6 @@ Please see the [Ionic 6 Upgrade Guide](https://ionicframework.com/docs/next/intr
|
||||
|
||||
|
||||
|
||||
# [6.0.0-beta.3](https://github.com/ionic-team/ionic/compare/v6.0.0-beta.2...v6.0.0-beta.3) (2021-08-04)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* **list:** change inset border radius to match iOS 15 ([#23711](https://github.com/ionic-team/ionic/issues/23711)) ([fe2810b](https://github.com/ionic-team/ionic/commit/fe2810b227abc482e663b210cd89f29b76119ff5))
|
||||
* **popover:** fix keyboard arrow navigation ([#23709](https://github.com/ionic-team/ionic/issues/23709)) ([f2e7a26](https://github.com/ionic-team/ionic/commit/f2e7a267973a06b50a0f6dcbba0a204930bccf69)), closes [#23512](https://github.com/ionic-team/ionic/issues/23512)
|
||||
* **vue:** popover positioning is now correct with custom elements build ([#23680](https://github.com/ionic-team/ionic/issues/23680)) ([3a1a9cb](https://github.com/ionic-team/ionic/commit/3a1a9cbce45ad128c9ba87940535dabfa167fb9e))
|
||||
|
||||
|
||||
### Features
|
||||
|
||||
* **toast:** add icon property to show icon at start of toast content ([#23596](https://github.com/ionic-team/ionic/issues/23596)) ([df24c8c](https://github.com/ionic-team/ionic/commit/df24c8c5ae0b493841c07c05e0d620fa4a90c05a)), closes [#23524](https://github.com/ionic-team/ionic/issues/23524)
|
||||
|
||||
|
||||
|
||||
## [5.6.13](https://github.com/ionic-team/ionic/compare/v5.6.12...v5.6.13) (2021-08-04)
|
||||
|
||||
|
||||
@@ -675,34 +176,6 @@ Please see the [Ionic 6 Upgrade Guide](https://ionicframework.com/docs/next/intr
|
||||
|
||||
|
||||
|
||||
# [6.0.0-beta.2](https://github.com/ionic-team/ionic/compare/v6.0.0-beta.1...v6.0.0-beta.2) (2021-07-21)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* **accordion:** value can now be set as string when using multiple is true ([#23581](https://github.com/ionic-team/ionic/issues/23581)) ([8f172de](https://github.com/ionic-team/ionic/commit/8f172de355bc7c910d600ce4d8446b04a6212545)), closes [#23550](https://github.com/ionic-team/ionic/issues/23550)
|
||||
* **angular:** modal and popover now have correct props defined on angular component ([#23565](https://github.com/ionic-team/ionic/issues/23565)) ([e5a7b34](https://github.com/ionic-team/ionic/commit/e5a7b342623b159d41cc83e0a418fb3984ceb3a7))
|
||||
* **datetime:** add keyboard year navigation ([#23585](https://github.com/ionic-team/ionic/issues/23585)) ([55bd1f7](https://github.com/ionic-team/ionic/commit/55bd1f749bac01cc691e16283728c42e755cc706)), closes [#21553](https://github.com/ionic-team/ionic/issues/21553) [#18122](https://github.com/ionic-team/ionic/issues/18122)
|
||||
* **datetime:** selecting time now works correctly on firefox ([#23583](https://github.com/ionic-team/ionic/issues/23583)) ([4188964](https://github.com/ionic-team/ionic/commit/4188964dc8da2c46494245b81864ca6e305611f5)), closes [#23545](https://github.com/ionic-team/ionic/issues/23545)
|
||||
* **datetime:** years displayed now more consistent with v5 datetime, max and min are now accounted for in MD mode ([#23616](https://github.com/ionic-team/ionic/issues/23616)) ([be219a2](https://github.com/ionic-team/ionic/commit/be219a2814800927e6328ff105616713003340b7)), closes [#23615](https://github.com/ionic-team/ionic/issues/23615)
|
||||
|
||||
|
||||
### Features
|
||||
|
||||
* **breadcrumbs:** ionCollapsedClick event payload now contains references to collapsed breadcrumb elements ([#23611](https://github.com/ionic-team/ionic/issues/23611)) ([9ce57d2](https://github.com/ionic-team/ionic/commit/9ce57d2efb84130895a37e22e0fd7e5d713a9fa5)), closes [#23552](https://github.com/ionic-team/ionic/issues/23552)
|
||||
* **datetime:** add showDefaultTimeLabel property and time-label slot ([#23577](https://github.com/ionic-team/ionic/issues/23577)) ([7ac0109](https://github.com/ionic-team/ionic/commit/7ac010943b2c9ad42a1833153ea16ccffd169b91)), closes [#23555](https://github.com/ionic-team/ionic/issues/23555)
|
||||
* **datetime:** add size property ([#23649](https://github.com/ionic-team/ionic/issues/23649)) ([321341d](https://github.com/ionic-team/ionic/commit/321341d97dff98b76b69a1efce58923a80e92bc4)), closes [#23518](https://github.com/ionic-team/ionic/issues/23518)
|
||||
* **range:** add support for customizing pin format ([#22972](https://github.com/ionic-team/ionic/issues/22972)) ([8f2c4f7](https://github.com/ionic-team/ionic/commit/8f2c4f73db167503cdf60222f42bcaadf905b401))
|
||||
* **segment:** add keyboard navigation, add selectOnFocus property to control selection follow focus behavior ([#23590](https://github.com/ionic-team/ionic/issues/23590)) ([b6c53e5](https://github.com/ionic-team/ionic/commit/b6c53e539b0855fa95b0fe02e5fa74ce403b68b8)), closes [#23520](https://github.com/ionic-team/ionic/issues/23520)
|
||||
* **select:** update popover interface to match MD spec on desktop, allow multiple values in popover interface ([#23474](https://github.com/ionic-team/ionic/issues/23474)) ([2c07a15](https://github.com/ionic-team/ionic/commit/2c07a1566b6f8570f7e12a55ca8f86d8fb8a968e)), closes [#23657](https://github.com/ionic-team/ionic/issues/23657) [#15500](https://github.com/ionic-team/ionic/issues/15500) [#12310](https://github.com/ionic-team/ionic/issues/12310)
|
||||
|
||||
|
||||
### Performance Improvements
|
||||
|
||||
* remove shims for legacy browsers no longer supported in v6 ([#23592](https://github.com/ionic-team/ionic/issues/23592)) ([259b135](https://github.com/ionic-team/ionic/commit/259b1359dbd20d4f85036ae46901a051cd8fc98b))
|
||||
|
||||
|
||||
|
||||
## [5.6.12](https://github.com/ionic-team/ionic/compare/v5.6.11...v5.6.12) (2021-07-21)
|
||||
|
||||
|
||||
@@ -717,36 +190,9 @@ Please see the [Ionic 6 Upgrade Guide](https://ionicframework.com/docs/next/intr
|
||||
|
||||
|
||||
|
||||
# [6.0.0-beta.1](https://github.com/ionic-team/ionic/compare/v6.0.0-beta.0...v6.0.0-beta.1) (2021-07-01)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* **accordion:** improved reliability of accordion animations ([#23531](https://github.com/ionic-team/ionic/issues/23531)) ([6fbd60b](https://github.com/ionic-team/ionic/commit/6fbd60b0df56dc927226474a1ffa322d979c563e)), closes [#23504](https://github.com/ionic-team/ionic/issues/23504)
|
||||
* **content:** add touch-action manipulation for a11y zoom and pan ([#23534](https://github.com/ionic-team/ionic/issues/23534)) ([6ca1780](https://github.com/ionic-team/ionic/commit/6ca17805b8b1ea38d7fc16d091324da16a4193c6)), closes [#22805](https://github.com/ionic-team/ionic/issues/22805)
|
||||
* **datetime:** scroll position no longer gets reset when using datetime in overlay ([#23543](https://github.com/ionic-team/ionic/issues/23543)) ([b735b58](https://github.com/ionic-team/ionic/commit/b735b587cda777ac481bb580c883d9734145f31e))
|
||||
* **input, select, textarea:** change type of placeholder prop to string only ([#23500](https://github.com/ionic-team/ionic/issues/23500)) ([f3ae431](https://github.com/ionic-team/ionic/commit/f3ae4319bb64debab304973856a33e422ac910a1)), closes [#22976](https://github.com/ionic-team/ionic/issues/22976)
|
||||
* **popover:** size property now works when providing only event ([#23532](https://github.com/ionic-team/ionic/issues/23532)) ([bdc1f23](https://github.com/ionic-team/ionic/commit/bdc1f2360d7795472cc242a86eb4376d05fa0bb7)), closes [#23528](https://github.com/ionic-team/ionic/issues/23528)
|
||||
* **popover:** update animation to better match MD spec ([#23541](https://github.com/ionic-team/ionic/issues/23541)) ([bdb95b7](https://github.com/ionic-team/ionic/commit/bdb95b7b6dd798cbc6d1786ae54fa95ac1dfd096))
|
||||
* **react:** export accordion and accordion group components ([#23497](https://github.com/ionic-team/ionic/issues/23497)) ([a664d42](https://github.com/ionic-team/ionic/commit/a664d4268dea8e84ab9e3b150043ac8f87fb53c7))
|
||||
* **vue:** navigating between parameterized pages now results in page transition ([#23525](https://github.com/ionic-team/ionic/issues/23525)) ([e30b17c](https://github.com/ionic-team/ionic/commit/e30b17c5bbd1af6936a8d7a98d1f7a115073e029)), closes [#22662](https://github.com/ionic-team/ionic/issues/22662)
|
||||
|
||||
|
||||
### Features
|
||||
|
||||
* **accordion-group:** add animated property to disable animations ([#23530](https://github.com/ionic-team/ionic/issues/23530)) ([9a60dd0](https://github.com/ionic-team/ionic/commit/9a60dd0ea7c55acf0fdd1161433e5b4ed40778f2))
|
||||
* **action-sheet, alert:** add id to AlertButton and ActionSheetButton ([#18992](https://github.com/ionic-team/ionic/issues/18992)) ([9e24a0b](https://github.com/ionic-team/ionic/commit/9e24a0b49357a3a39ca89f026ff23271a365d935)), closes [#22959](https://github.com/ionic-team/ionic/issues/22959)
|
||||
* **vue:** extend useIonRouter hook for programmatic navigation with animation control ([#23499](https://github.com/ionic-team/ionic/issues/23499)) ([fc9e1b4](https://github.com/ionic-team/ionic/commit/fc9e1b4b361938e5644683c395a565be2de1eab9)), closes [#23450](https://github.com/ionic-team/ionic/issues/23450)
|
||||
|
||||
|
||||
### BREAKING CHANGES
|
||||
|
||||
* **input, select, textarea:** Updated the `placeholder` property on `ion-input`, `ion-textarea`, and `ion-select` to have a type of `string | undefined`.
|
||||
|
||||
|
||||
|
||||
## [5.6.11](https://github.com/ionic-team/ionic/compare/v5.6.10...v5.6.11) (2021-07-01)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* **animation:** typescript interface has correct return value for progress methods ([#23536](https://github.com/ionic-team/ionic/issues/23536)) ([f3d6abb](https://github.com/ionic-team/ionic/commit/f3d6abbc1beeafe3b5e7f473d70d0b8ef4c79bc8))
|
||||
@@ -754,63 +200,6 @@ Please see the [Ionic 6 Upgrade Guide](https://ionicframework.com/docs/next/intr
|
||||
|
||||
|
||||
|
||||
# [6.0.0-beta.0](https://github.com/ionic-team/ionic/compare/v5.6.10...v6.0.0-beta.0) (2021-06-23)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* **accordion:** toggle icon now shows up in vue and react ([#23426](https://github.com/ionic-team/ionic/issues/23426)) ([c716617](https://github.com/ionic-team/ionic/commit/c7166179457a8e2c7e1702c5761bc6368dbd156f))
|
||||
* **datetime:** changing time emits ionChange ([#23463](https://github.com/ionic-team/ionic/issues/23463)) ([b0cce36](https://github.com/ionic-team/ionic/commit/b0cce360c83ac564e053523cc31b32d1deaeda0c))
|
||||
* **modal:** add additional padding to toolbars in iOS modal ([#23262](https://github.com/ionic-team/ionic/issues/23262)) ([a037b65](https://github.com/ionic-team/ionic/commit/a037b65aad5cfc0477322a8f36105b9009366ec2)), closes [#22778](https://github.com/ionic-team/ionic/issues/22778)
|
||||
* **modal:** border radius is correctly set on card style modal ([#23461](https://github.com/ionic-team/ionic/issues/23461)) ([bccb8ad](https://github.com/ionic-team/ionic/commit/bccb8ad5fb5ec7f98a6cbfa62a403ecaca7fbdb6))
|
||||
* **modal, popover:** overlays now automatically determine if they are inline ([#23434](https://github.com/ionic-team/ionic/issues/23434)) ([8dbe8ba](https://github.com/ionic-team/ionic/commit/8dbe8ba7bc26792c5024f81cf4752f5b78317492))
|
||||
* **popover:** shadow parts now correctly added ([#23446](https://github.com/ionic-team/ionic/issues/23446)) ([e1a9613](https://github.com/ionic-team/ionic/commit/e1a96130ebab1e481e880f0f3876f421976f08d5))
|
||||
* **popover:** update prop defaults, use correct delegate ([#23340](https://github.com/ionic-team/ionic/issues/23340)) ([960778a](https://github.com/ionic-team/ionic/commit/960778a36f6eb6318cc740c4f7a255107723b8fd))
|
||||
* **searchbar:** showClearButton now defaults to 'always' for improved usability with screen readers ([#23475](https://github.com/ionic-team/ionic/issues/23475)) ([80f181d](https://github.com/ionic-team/ionic/commit/80f181d4846507ee6bd4150bb568fca9b6660428))
|
||||
* **vue:** ensure webpack does not eliminate core css ([#23465](https://github.com/ionic-team/ionic/issues/23465)) ([ee3a00f](https://github.com/ionic-team/ionic/commit/ee3a00fde61b4d1d3168d34b3d23bb97dd154154))
|
||||
|
||||
|
||||
### Code Refactoring
|
||||
|
||||
* **all:** update required browser, framework, and mobile platform versions for v6 ([#23443](https://github.com/ionic-team/ionic/issues/23443)) ([c842dd8](https://github.com/ionic-team/ionic/commit/c842dd88c98888b2afab08ac5e8bc57c2a4c2fbd))
|
||||
* **angular:** remove Config.set() method ([#22918](https://github.com/ionic-team/ionic/issues/22918)) ([9e05891](https://github.com/ionic-team/ionic/commit/9e0589173607b3c0eff7794079123354c2eeaa1a))
|
||||
* **header:** removed border from last toolbar when using collapsible large title ([#22891](https://github.com/ionic-team/ionic/issues/22891)) ([c72bc5d](https://github.com/ionic-team/ionic/commit/c72bc5dbd76cd3ce622a4b3cedcb7446a2819384)), closes [#22777](https://github.com/ionic-team/ionic/issues/22777)
|
||||
* **ios:** update toolbar and tabbar default background colors ([#22852](https://github.com/ionic-team/ionic/issues/22852)) ([3d615cb](https://github.com/ionic-team/ionic/commit/3d615cb3c7b233b08b9da6ac04096e16bbb60bfc)), closes [#22780](https://github.com/ionic-team/ionic/issues/22780)
|
||||
* **toast:** whitespace variable now defaults to normal ([#22866](https://github.com/ionic-team/ionic/issues/22866)) ([9b78689](https://github.com/ionic-team/ionic/commit/9b786899e550c391b9395c669f9bba8f39ac98aa))
|
||||
* **vue:** drop support for "on" prefixed overlay events and bump minimum required version of vue to 3.0.6 ([#23229](https://github.com/ionic-team/ionic/issues/23229)) ([6fcb3a6](https://github.com/ionic-team/ionic/commit/6fcb3a62b1b12c5ded11179e83854592d4309bdf))
|
||||
* **vue:** remove support for child routes nested inside of tabs ([#22919](https://github.com/ionic-team/ionic/issues/22919)) ([75458ac](https://github.com/ionic-team/ionic/commit/75458ac7fb95f56a6ec460f85cf7d7720ce0c070))
|
||||
|
||||
|
||||
### Features
|
||||
|
||||
* **accordion:** add accordion and accordion-group components ([#22865](https://github.com/ionic-team/ionic/issues/22865)) ([073883a](https://github.com/ionic-team/ionic/commit/073883a0987149e9f6258ca43c46f5ed4bce0dc5)), closes [#17094](https://github.com/ionic-team/ionic/issues/17094)
|
||||
* **breadcrumbs:** add breadcrumbs component ([#22701](https://github.com/ionic-team/ionic/issues/22701)) ([2f6b1e4](https://github.com/ionic-team/ionic/commit/2f6b1e4eea307c6f14345704e5824378ef079acb)), closes [#22770](https://github.com/ionic-team/ionic/issues/22770)
|
||||
* **datetime:** add calendar picker ([#23416](https://github.com/ionic-team/ionic/issues/23416)) ([932d3ca](https://github.com/ionic-team/ionic/commit/932d3ca62f3e3ef08acb065ce6ec46faa3811f96)), closes [#19423](https://github.com/ionic-team/ionic/issues/19423)
|
||||
* **item:** add helper text, error text, counter, shape, and fill mode ([#23354](https://github.com/ionic-team/ionic/issues/23354)) ([faefe97](https://github.com/ionic-team/ionic/commit/faefe97da6a9d5beff1183d10efd0df9c4e3ebd7)), closes [#19619](https://github.com/ionic-team/ionic/issues/19619)
|
||||
* **modal:** modals can now be used inline ([#23341](https://github.com/ionic-team/ionic/issues/23341)) ([3be1c3d](https://github.com/ionic-team/ionic/commit/3be1c3dcd73e6039a89b19b409e63877cda37f6e)), closes [#20117](https://github.com/ionic-team/ionic/issues/20117) [#20263](https://github.com/ionic-team/ionic/issues/20263)
|
||||
* **popover:** account for ionShadowTarget elements ([#23436](https://github.com/ionic-team/ionic/issues/23436)) ([0e38d42](https://github.com/ionic-team/ionic/commit/0e38d4276110dcd94db5adc3b6aee3b5b0befc5c))
|
||||
* **popover:** add desktop support ([#23258](https://github.com/ionic-team/ionic/issues/23258)) ([a67a0fa](https://github.com/ionic-team/ionic/commit/a67a0fabb8249685bbe93ed862839e2b2e76cd5a)), closes [#21599](https://github.com/ionic-team/ionic/issues/21599)
|
||||
* **popover:** popover can now be used inline ([#23231](https://github.com/ionic-team/ionic/issues/23231)) ([308fa1c](https://github.com/ionic-team/ionic/commit/308fa1c0dd054cfc2ea54d2edc99e7a4b549f6f0))
|
||||
* **slides:** add IonicSwiper modules, deprecate ion-slides, and add link to migration ([#23447](https://github.com/ionic-team/ionic/issues/23447)) ([623c84a](https://github.com/ionic-team/ionic/commit/623c84ab082668a996c654e18ffc9768f68b85dd))
|
||||
* **spinner:** add lines-sharp, lines-sharp-small, update styles for ios 14 ([#22397](https://github.com/ionic-team/ionic/issues/22397)) ([2a5b272](https://github.com/ionic-team/ionic/commit/2a5b272a329bbad1ca07705f84f0fd06e3ef32ad))
|
||||
* **vue:** add custom elements bundle ([#23458](https://github.com/ionic-team/ionic/issues/23458)) ([dc48a9f](https://github.com/ionic-team/ionic/commit/dc48a9f1a2dff8a2d644112bbe1df8b0b6811848))
|
||||
|
||||
|
||||
### BREAKING CHANGES
|
||||
|
||||
* **searchbar:** The `showClearButton` property on `ion-searchbar` now defaults to `'always'`.
|
||||
* **datetime:** The `ion-datetime` component has been revamped to use a new calendar style. As a result, some APIs have been removed. See https://github.com/ionic-team/ionic-framework/blob/master/BREAKING.md for more details.
|
||||
* **all:** Browser, JS Framework, and mobile platform minimum required versions have been updated.
|
||||
* **popover:** Converted `ion-popover` to use the Shadow DOM.
|
||||
* **vue:** - Dropped support for prefixed overlay events in favor of non prefixed events (I.e. `@onDidDismiss` becomes `@didDismiss`).
|
||||
- Minimum required version of Vue is now Vue v3.0.6 or newer.
|
||||
* **vue:** Support for child routes nested inside of tabs has been removed to better conform to Vue Router's best practices. Additional routes should be written as sibling routes with the parent tab as the path prefix.
|
||||
* **angular:** The `Config.set()` method has been removed. See https://ionicframework.com/docs/angular/config for examples on how to set config globally, per-component, and per-platform.
|
||||
* **ios:** The tab bar and toolbar default background colors have been updated to better reflect the latest iOS styles.
|
||||
* **header:** The last toolbar in the header with a collapsible large title no longer has a border.
|
||||
* **toast:** The `--white-space` CSS Variable now defaults to `normal`.
|
||||
|
||||
|
||||
## [5.6.10](https://github.com/ionic-team/ionic/compare/v5.6.9...v5.6.10) (2021-06-22)
|
||||
|
||||
|
||||
@@ -4737,4 +4126,4 @@ The following dependencies need to be updated to resolve build errors
|
||||
|
||||
<a name="0.1.0"></a>
|
||||
|
||||
## [0.1.0](https://github.com/ionic-team/ionic/commit/43a8c4c7a719169336a84964fc1c737562d764a6) (2018-03-01)
|
||||
## [0.1.0](https://github.com/ionic-team/ionic/commit/43a8c4c7a719169336a84964fc1c737562d764a6) (2018-03-01)
|
||||
84
README.md
84
README.md
@@ -1,63 +1,22 @@
|
||||
<p align="center">
|
||||
<a href="#">
|
||||
<img alt="Ionic" src="https://github.com/ionic-team/ionic-framework/blob/main/.github/assets/logo.png?raw=true" width="60" />
|
||||
</a>
|
||||
</p>
|
||||
# Ionic Framework
|
||||
|
||||
<h1 align="center">
|
||||
Ionic
|
||||
</h1>
|
||||
[Ionic Framework](https://ionicframework.com/) is the open-source mobile app development framework that makes it easy to
|
||||
build top quality native and progressive web apps with web technologies.
|
||||
|
||||
<p align="center">
|
||||
Ionic is an open source app development toolkit for building modern, fast, top-quality cross-platform native and Progressive Web Apps from a single codebase with JavaScript and the Web.
|
||||
</p>
|
||||
<p align="center">
|
||||
Ionic is based on <a href="https://www.webcomponents.org/introduction">Web Components</a>, which enables significant performance, usability, and feature improvements alongside support for popular web frameworks like <a href="https://angular.io/">Angular</a>, <a href="https://reactjs.com/">React</a>, and <a href="https://vuejs.org/">Vue</a>.
|
||||
Ionic Framework is based on [Web Components](https://www.webcomponents.org/introduction) and comes with many significant performance, usability, and feature improvements over the past versions.
|
||||
|
||||
</p>
|
||||
## Looking for the Ionic Framework v6 beta?
|
||||
|
||||
<p align="center">
|
||||
<a href="https://github.com/ionic-team/ionic-framework/blob/main/LICENSE">
|
||||
<img src="https://img.shields.io/badge/license-MIT-blue.svg" alt="Ionic Framework is released under the MIT license." />
|
||||
</a>
|
||||
<a href="https://github.com/ionic-team/ionic/blob/main/.github/CONTRIBUTING.md">
|
||||
<img src="https://img.shields.io/badge/PRs-welcome-brightgreen.svg" alt="PRs welcome!" />
|
||||
</a>
|
||||
<a href="https://twitter.com/Ionicframework">
|
||||
<img src="https://img.shields.io/twitter/follow/ionicframework.svg?label=Follow%20@IonicFramework" alt="Follow @IonicFramework">
|
||||
</a>
|
||||
<a href="https://ionic.link/discord">
|
||||
<img src="https://img.shields.io/discord/520266681499779082?color=7289DA&label=%23ionic&logo=discord&logoColor=white" alt="Official Ionic Discord" />
|
||||
</a>
|
||||
</p>
|
||||
|
||||
<h2 align="center">
|
||||
<a href="https://ionicframework.com/getting-started/">Quickstart</a>
|
||||
<span> · </span>
|
||||
<a href="https://ionicframework.com/docs/">
|
||||
Documentation
|
||||
</a>
|
||||
<span> · </span>
|
||||
<a href="https://github.com/ionic-team/ionic/blob/main/.github/CONTRIBUTING.md">Contribute</a>
|
||||
<span> · </span>
|
||||
<a href="https://blog.ionicframework.com/">Blog</a>
|
||||
<br />
|
||||
Community:
|
||||
<a href="https://ionic.link/discord">Discord</a>
|
||||
<span> · </span>
|
||||
<a href="https://forum.ionicframework.com/">Forums</a>
|
||||
<span> · </span>
|
||||
<a href="https://twitter.com/Ionicframework">Twitter</a>
|
||||
</h2>
|
||||
[Click here to get started!](https://github.com/ionic-team/ionic-framework/blob/next/BETA.md)
|
||||
|
||||
### Packages
|
||||
|
||||
| Project | Package | Version | Downloads| Links |
|
||||
| ------- | ------- | ------- | -------- |:-----:|
|
||||
| **Core** | [`@ionic/core`](https://www.npmjs.com/package/@ionic/core) | [](https://www.npmjs.com/package/@ionic/core) | <a href="https://www.npmjs.com/package/@ionic/core" target="_blank"><img src="https://img.shields.io/npm/dm/@ionic/core.svg" alt="NPM Downloads" /></a> | [`README.md`](core/README.md)
|
||||
| **Angular** | [`@ionic/angular`](https://www.npmjs.com/package/@ionic/angular) | [](https://www.npmjs.com/package/@ionic/angular) | <a href="https://www.npmjs.com/package/@ionic/angular" target="_blank"><img src="https://img.shields.io/npm/dm/@ionic/angular.svg" alt="NPM Downloads" /></a> | [`README.md`](angular/README.md)
|
||||
| **Vue** | [`@ionic/vue`](https://www.npmjs.com/package/@ionic/vue) | [](https://www.npmjs.com/package/@ionic/vue) | <a href="https://www.npmjs.com/package/@ionic/vue" target="_blank"><img src="https://img.shields.io/npm/dm/@ionic/vue.svg" alt="NPM Downloads" /></a> | [`README.md`](packages/vue/README.md)
|
||||
| **React** | [`@ionic/react`](https://www.npmjs.com/package/@ionic/react) | [](https://www.npmjs.com/package/@ionic/react) | <a href="https://www.npmjs.com/package/@ionic/react" target="_blank"><img src="https://img.shields.io/npm/dm/@ionic/react.svg" alt="NPM Downloads" /></a> |[`README.md`](packages/react/README.md)
|
||||
| Project | Package | Version | Links |
|
||||
| ------- | ------- | ------- |:-----:|
|
||||
| **Core** | [`@ionic/core`](https://www.npmjs.com/package/@ionic/core) | [](https://www.npmjs.com/package/@ionic/core) | [`README.md`](core/README.md)
|
||||
| **Angular** | [`@ionic/angular`](https://www.npmjs.com/package/@ionic/angular) | [](https://www.npmjs.com/package/@ionic/angular) | [`README.md`](angular/README.md)
|
||||
| **Vue** | [`@ionic/vue`](https://www.npmjs.com/package/@ionic/vue) | [](https://www.npmjs.com/package/@ionic/vue) | [`README.md`](packages/vue/README.md)
|
||||
| **React** | [`@ionic/react`](https://www.npmjs.com/package/@ionic/react) | [](https://www.npmjs.com/package/@ionic/react) | [`README.md`](packages/react/README.md)
|
||||
|
||||
Looking for the `ionic-angular` package? Ionic 3 has been moved to the [`ionic-v3`](https://github.com/ionic-team/ionic-v3) repo. See [Earlier Versions](#earlier-versions).
|
||||
|
||||
@@ -67,18 +26,6 @@ Start a new project by following our quick [Getting Started guide](https://ionic
|
||||
We would love to hear from you! If you have any feedback or run into issues using our framework, please file
|
||||
an [issue](https://github.com/ionic-team/ionic/issues/new) on this repository.
|
||||
|
||||
### Migration Guides
|
||||
|
||||
Already have an Ionic app? These guides will help you migrate to the latest versions.
|
||||
|
||||
* [Migrate from v5 to v6](https://ionicframework.com/docs/reference/migration#migrating-from-ionic-5x-to-ionic-6x)
|
||||
* [Migrate from v4 to v5](https://ionicframework.com/docs/reference/migration#migrating-from-ionic-4x-to-ionic-5x)
|
||||
* [Migrate from v3 to v4](https://ionicframework.com/docs/reference/migration#migrating-from-ionic-30-to-ionic-40)
|
||||
|
||||
### Examples
|
||||
|
||||
The [Ionic Conference App](https://github.com/ionic-team/ionic-conference-app) is a full featured Ionic app.
|
||||
It is the perfect starting point for learning and building your own app.
|
||||
|
||||
### Contributing
|
||||
|
||||
@@ -89,6 +36,13 @@ label.
|
||||
|
||||
Please note that this project is released with a [Contributor Code of Conduct](https://github.com/ionic-team/ionic/blob/main/CODE_OF_CONDUCT.md). By participating in this project you agree to abide by its terms.
|
||||
|
||||
|
||||
### Examples
|
||||
|
||||
The [Ionic Conference App](https://github.com/ionic-team/ionic-conference-app) is a full featured Ionic app.
|
||||
It is the perfect starting point for learning and building your own app.
|
||||
|
||||
|
||||
### Future Goals
|
||||
|
||||
As Ionic Framework components migrate to the web component standard, a goal of ours is to have Ionic Framework easily work within all of the popular frameworks.
|
||||
|
||||
@@ -1,4 +0,0 @@
|
||||
dist
|
||||
virtual-scroll
|
||||
scripts
|
||||
proxies.ts
|
||||
@@ -1,30 +0,0 @@
|
||||
{
|
||||
"root": true,
|
||||
"ignorePatterns": ["test/**/*", "src/directives/virtual-scroll/**/*"],
|
||||
"overrides": [
|
||||
{
|
||||
"files": ["*.ts"],
|
||||
"parserOptions": {
|
||||
"project": ["tsconfig.json"],
|
||||
"createDefaultProgram": true
|
||||
},
|
||||
"extends": [
|
||||
"@ionic/eslint-config/recommended",
|
||||
"plugin:@angular-eslint/recommended",
|
||||
"plugin:@angular-eslint/template/process-inline-templates"
|
||||
],
|
||||
"rules": {
|
||||
"@typescript-eslint/consistent-type-imports": "off",
|
||||
"@angular-eslint/component-class-suffix": "off",
|
||||
"@angular-eslint/component-selector": [
|
||||
"error",
|
||||
{
|
||||
"type": "element",
|
||||
"prefix": "ion",
|
||||
"style": "kebab-case"
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
@@ -1,6 +0,0 @@
|
||||
dist
|
||||
virtual-scroll
|
||||
scripts
|
||||
test
|
||||
src/directives/proxies.ts
|
||||
src/directives/angular-component-lib/utils.ts
|
||||
@@ -1,12 +0,0 @@
|
||||
# Change Log
|
||||
|
||||
All notable changes to this project will be documented in this file.
|
||||
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
|
||||
|
||||
## [6.0.2](https://github.com/ionic-team/ionic/compare/v6.0.1...v6.0.2) (2022-01-11)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* **angular:** attach change detector ref for inline overlays ([#24521](https://github.com/ionic-team/ionic/issues/24521)) ([5c54593](https://github.com/ionic-team/ionic/commit/5c54593dde64ae61347568405ebf74502cfff370)), closes [#24502](https://github.com/ionic-team/ionic/issues/24502)
|
||||
* **angular:** popover will respect side attribute value ([#24470](https://github.com/ionic-team/ionic/issues/24470)) ([e6955a2](https://github.com/ionic-team/ionic/commit/e6955a26b92fc536c5c73b60b5943881c7d58ee1)), closes [#24466](https://github.com/ionic-team/ionic/issues/24466)
|
||||
15800
angular/package-lock.json
generated
15800
angular/package-lock.json
generated
File diff suppressed because it is too large
Load Diff
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@ionic/angular",
|
||||
"version": "6.0.2",
|
||||
"version": "5.9.3",
|
||||
"description": "Angular specific wrappers for @ionic/core",
|
||||
"keywords": [
|
||||
"ionic",
|
||||
@@ -22,76 +22,65 @@
|
||||
"bugs": {
|
||||
"url": "https://github.com/ionic-team/ionic/issues"
|
||||
},
|
||||
"publishConfig": {
|
||||
"directory": "dist"
|
||||
},
|
||||
"homepage": "https://ionicframework.com/",
|
||||
"scripts": {
|
||||
"prepublishOnly": "npm run build",
|
||||
"build": "npm run clean && npm run build.ng && npm run build.core && npm run clean-generated",
|
||||
"build.core": "node scripts/build-core.js",
|
||||
"build.fesm": "rollup --config ./scripts/rollup.config.js",
|
||||
"build.link": "npm run build && node scripts/link-copy.js",
|
||||
"build.ng": "ng-packagr -p package.json -c tsconfig.json",
|
||||
"build.ng": "ng-packagr -p package.json",
|
||||
"build.es2015": "ngc -p tsconfig.json && rollup --config ./scripts/rollup.config.js",
|
||||
"build.es5": "ngc -p tsconfig.legacy.json && rollup --config ./scripts/rollup.config.legacy.js",
|
||||
"clean": "node scripts/clean.js",
|
||||
"clean-generated": "node ./scripts/clean-generated.js",
|
||||
"lint": "npm run eslint && npm run prettier -- --check",
|
||||
"fmt": "npm run eslint -- --fix && npm run prettier -- --write",
|
||||
"prettier": "prettier \"**/*.ts\"",
|
||||
"eslint": "eslint . --ext .ts",
|
||||
"lint": "npm run lint.ts",
|
||||
"lint.ts": "tslint --project .",
|
||||
"lint.fix": "tslint --project . --fix",
|
||||
"prerelease": "npm run validate && np prerelease --yolo --any-branch --tag next",
|
||||
"test": "echo 'angular no tests yet'",
|
||||
"tsc": "tsc -p .",
|
||||
"validate": "npm i && npm run lint && npm run test && npm run build"
|
||||
},
|
||||
"dependencies": {
|
||||
"@ionic/core": "^6.0.2",
|
||||
"jsonc-parser": "^3.0.0",
|
||||
"tslib": "^2.0.0"
|
||||
"@ionic/core": "5.9.3",
|
||||
"tslib": "^1.9.3"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"@angular/core": ">=12.0.0",
|
||||
"@angular/forms": ">=12.0.0",
|
||||
"@angular/router": ">=12.0.0",
|
||||
"rxjs": ">=6.6.0",
|
||||
"zone.js": ">=0.11.0"
|
||||
"@angular/core": ">=8.2.7",
|
||||
"@angular/forms": ">=8.2.7",
|
||||
"@angular/router": ">=8.2.7",
|
||||
"rxjs": ">=6.2.0",
|
||||
"zone.js": ">=0.8.26"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@angular-devkit/core": "^12.0.0",
|
||||
"@angular-devkit/schematics": "^12.0.0",
|
||||
"@angular-eslint/eslint-plugin": "^12.5.0",
|
||||
"@angular-eslint/eslint-plugin-template": "^12.5.0",
|
||||
"@angular-eslint/template-parser": "^12.5.0",
|
||||
"@angular/common": "^12.0.0",
|
||||
"@angular/compiler": "^12.0.0",
|
||||
"@angular/compiler-cli": "^12.0.0",
|
||||
"@angular/core": "^12.0.0",
|
||||
"@angular/forms": "^12.0.0",
|
||||
"@angular/router": "^12.0.0",
|
||||
"@ionic/eslint-config": "^0.3.0",
|
||||
"@ionic/prettier-config": "^2.0.0",
|
||||
"@schematics/angular": "^12.2.9",
|
||||
"@angular-devkit/core": "8.3.17",
|
||||
"@angular-devkit/schematics": "8.3.17",
|
||||
"@angular/common": "8.2.13",
|
||||
"@angular/compiler": "8.2.13",
|
||||
"@angular/compiler-cli": "8.2.13",
|
||||
"@angular/core": "8.2.13",
|
||||
"@angular/forms": "8.2.13",
|
||||
"@angular/router": "8.2.13",
|
||||
"@types/node": "12.12.5",
|
||||
"@typescript-eslint/eslint-plugin": "^4.32.0",
|
||||
"@typescript-eslint/parser": "^4.32.0",
|
||||
"eslint": "^7.32.0",
|
||||
"eslint-plugin-import": "^2.25.2",
|
||||
"fs-extra": "^7.0.0",
|
||||
"ng-packagr": "^12.0.0",
|
||||
"prettier": "^2.4.1",
|
||||
"glob": "^7.1.4",
|
||||
"ng-packagr": "^9.1.5",
|
||||
"rollup": "~1.17.0",
|
||||
"rollup-plugin-node-resolve": "~5.2.0",
|
||||
"rxjs": "^6.6.2",
|
||||
"typescript": "4.2.4",
|
||||
"typescript-eslint-language-service": "^4.1.5",
|
||||
"zone.js": "~0.11.4"
|
||||
"tsickle": "^0.39.1",
|
||||
"tslint": "^5.12.1",
|
||||
"tslint-ionic-rules": "0.0.21",
|
||||
"typescript": "3.4.5",
|
||||
"zone.js": "^0.11.1"
|
||||
},
|
||||
"prettier": "@ionic/prettier-config",
|
||||
"schematics": "./schematics/collection.json",
|
||||
"ngPackage": {
|
||||
"lib": {
|
||||
"entryFile": "src/index.ts"
|
||||
},
|
||||
"allowedNonPeerDependencies": [
|
||||
"@ionic/core",
|
||||
"jsonc-parser"
|
||||
"whitelistedNonPeerDependencies": [
|
||||
"@ionic/core"
|
||||
]
|
||||
}
|
||||
}
|
||||
|
||||
@@ -10,13 +10,15 @@ export const appInitialize = (config: Config, doc: Document, zone: NgZone) => {
|
||||
return (): any => {
|
||||
const win: IonicWindow | undefined = doc.defaultView as any;
|
||||
if (win && typeof (window as any) !== 'undefined') {
|
||||
|
||||
setupConfig({
|
||||
...config,
|
||||
_zoneGate: (h: any) => zone.run(h),
|
||||
_zoneGate: (h: any) => zone.run(h)
|
||||
});
|
||||
|
||||
const aelFn =
|
||||
'__zone_symbol__addEventListener' in (doc.body as any) ? '__zone_symbol__addEventListener' : 'addEventListener';
|
||||
const aelFn = '__zone_symbol__addEventListener' in (doc.body as any)
|
||||
? '__zone_symbol__addEventListener'
|
||||
: 'addEventListener';
|
||||
|
||||
return applyPolyfills().then(() => {
|
||||
return defineCustomElements(win, {
|
||||
@@ -29,7 +31,7 @@ export const appInitialize = (config: Config, doc: Document, zone: NgZone) => {
|
||||
},
|
||||
rel(elm, eventName, cb, opts) {
|
||||
elm.removeEventListener(eventName, cb, opts);
|
||||
},
|
||||
}
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
@@ -1,63 +0,0 @@
|
||||
/* eslint-disable */
|
||||
/* tslint:disable */
|
||||
import { fromEvent } from 'rxjs';
|
||||
|
||||
export const proxyInputs = (Cmp: any, inputs: string[]) => {
|
||||
const Prototype = Cmp.prototype;
|
||||
inputs.forEach(item => {
|
||||
Object.defineProperty(Prototype, item, {
|
||||
get() {
|
||||
return this.el[item];
|
||||
},
|
||||
set(val: any) {
|
||||
this.z.runOutsideAngular(() => (this.el[item] = val));
|
||||
}
|
||||
});
|
||||
});
|
||||
};
|
||||
|
||||
export const proxyMethods = (Cmp: any, methods: string[]) => {
|
||||
const Prototype = Cmp.prototype;
|
||||
methods.forEach(methodName => {
|
||||
Prototype[methodName] = function () {
|
||||
const args = arguments;
|
||||
return this.z.runOutsideAngular(() =>
|
||||
this.el[methodName].apply(this.el, args)
|
||||
);
|
||||
};
|
||||
});
|
||||
};
|
||||
|
||||
export const proxyOutputs = (instance: any, el: any, events: string[]) => {
|
||||
events.forEach(eventName => instance[eventName] = fromEvent(el, eventName));
|
||||
}
|
||||
|
||||
export const defineCustomElement = (tagName: string, customElement: any) => {
|
||||
if (
|
||||
customElement !== undefined &&
|
||||
typeof customElements !== 'undefined' &&
|
||||
!customElements.get(tagName)
|
||||
) {
|
||||
customElements.define(tagName, customElement);
|
||||
}
|
||||
}
|
||||
|
||||
// tslint:disable-next-line: only-arrow-functions
|
||||
export function ProxyCmp(opts: { defineCustomElementFn?: () => void, inputs?: any; methods?: any }) {
|
||||
const decorator = function (cls: any) {
|
||||
const { defineCustomElementFn, inputs, methods } = opts;
|
||||
|
||||
if (defineCustomElementFn !== undefined) {
|
||||
defineCustomElementFn();
|
||||
}
|
||||
|
||||
if (inputs) {
|
||||
proxyInputs(cls, inputs);
|
||||
}
|
||||
if (methods) {
|
||||
proxyMethods(cls, methods);
|
||||
}
|
||||
return cls;
|
||||
};
|
||||
return decorator;
|
||||
}
|
||||
@@ -1,30 +1,32 @@
|
||||
import { Directive, HostListener, ElementRef, Injector } from '@angular/core';
|
||||
import { Directive, ElementRef, HostListener, Injector } from '@angular/core';
|
||||
import { NG_VALUE_ACCESSOR } from '@angular/forms';
|
||||
|
||||
import { ValueAccessor, setIonicClasses } from './value-accessor';
|
||||
|
||||
@Directive({
|
||||
/* tslint:disable-next-line:directive-selector */
|
||||
selector: 'ion-checkbox,ion-toggle',
|
||||
providers: [
|
||||
{
|
||||
provide: NG_VALUE_ACCESSOR,
|
||||
useExisting: BooleanValueAccessorDirective,
|
||||
multi: true,
|
||||
},
|
||||
],
|
||||
useExisting: BooleanValueAccessor,
|
||||
multi: true
|
||||
}
|
||||
]
|
||||
})
|
||||
export class BooleanValueAccessorDirective extends ValueAccessor {
|
||||
export class BooleanValueAccessor extends ValueAccessor {
|
||||
|
||||
constructor(injector: Injector, el: ElementRef) {
|
||||
super(injector, el);
|
||||
}
|
||||
|
||||
writeValue(value: any): void {
|
||||
writeValue(value: any) {
|
||||
this.el.nativeElement.checked = this.lastValue = value == null ? false : value;
|
||||
setIonicClasses(this.el);
|
||||
}
|
||||
|
||||
@HostListener('ionChange', ['$event.target'])
|
||||
_handleIonChange(el: any): void {
|
||||
_handleIonChange(el: any) {
|
||||
this.handleChangeEvent(el, el.checked);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,30 +1,32 @@
|
||||
import { Directive, HostListener, ElementRef, Injector } from '@angular/core';
|
||||
import { Directive, ElementRef, HostListener, Injector } from '@angular/core';
|
||||
import { NG_VALUE_ACCESSOR } from '@angular/forms';
|
||||
|
||||
import { ValueAccessor } from './value-accessor';
|
||||
|
||||
@Directive({
|
||||
/* tslint:disable-next-line:directive-selector */
|
||||
selector: 'ion-input[type=number]',
|
||||
providers: [
|
||||
{
|
||||
provide: NG_VALUE_ACCESSOR,
|
||||
useExisting: NumericValueAccessorDirective,
|
||||
multi: true,
|
||||
},
|
||||
],
|
||||
useExisting: NumericValueAccessor,
|
||||
multi: true
|
||||
}
|
||||
]
|
||||
})
|
||||
export class NumericValueAccessorDirective extends ValueAccessor {
|
||||
export class NumericValueAccessor extends ValueAccessor {
|
||||
|
||||
constructor(injector: Injector, el: ElementRef) {
|
||||
super(injector, el);
|
||||
}
|
||||
|
||||
@HostListener('ionChange', ['$event.target'])
|
||||
_handleIonChange(el: any): void {
|
||||
_handleIonChange(el: any) {
|
||||
this.handleChangeEvent(el, el.value);
|
||||
}
|
||||
|
||||
registerOnChange(fn: (_: number | null) => void): void {
|
||||
super.registerOnChange((value) => {
|
||||
registerOnChange(fn: (_: number | null) => void) {
|
||||
super.registerOnChange(value => {
|
||||
fn(value === '' ? null : parseFloat(value));
|
||||
});
|
||||
}
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { ElementRef, Injector, Directive, HostListener } from '@angular/core';
|
||||
import { Directive, ElementRef, HostListener, Injector } from '@angular/core';
|
||||
import { NG_VALUE_ACCESSOR } from '@angular/forms';
|
||||
|
||||
import { ValueAccessor } from './value-accessor';
|
||||
@@ -9,18 +9,19 @@ import { ValueAccessor } from './value-accessor';
|
||||
providers: [
|
||||
{
|
||||
provide: NG_VALUE_ACCESSOR,
|
||||
useExisting: RadioValueAccessorDirective,
|
||||
multi: true,
|
||||
},
|
||||
],
|
||||
useExisting: RadioValueAccessor,
|
||||
multi: true
|
||||
}
|
||||
]
|
||||
})
|
||||
export class RadioValueAccessorDirective extends ValueAccessor {
|
||||
export class RadioValueAccessor extends ValueAccessor {
|
||||
|
||||
constructor(injector: Injector, el: ElementRef) {
|
||||
super(injector, el);
|
||||
}
|
||||
|
||||
@HostListener('ionSelect', ['$event.target'])
|
||||
_handleIonSelect(el: any): void {
|
||||
_handleIonSelect(el: any) {
|
||||
this.handleChangeEvent(el, el.checked);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { ElementRef, Injector, Directive, HostListener } from '@angular/core';
|
||||
import { Directive, ElementRef, HostListener, Injector } from '@angular/core';
|
||||
import { NG_VALUE_ACCESSOR } from '@angular/forms';
|
||||
|
||||
import { ValueAccessor } from './value-accessor';
|
||||
@@ -9,18 +9,19 @@ import { ValueAccessor } from './value-accessor';
|
||||
providers: [
|
||||
{
|
||||
provide: NG_VALUE_ACCESSOR,
|
||||
useExisting: SelectValueAccessorDirective,
|
||||
multi: true,
|
||||
},
|
||||
],
|
||||
useExisting: SelectValueAccessor,
|
||||
multi: true
|
||||
}
|
||||
]
|
||||
})
|
||||
export class SelectValueAccessorDirective extends ValueAccessor {
|
||||
export class SelectValueAccessor extends ValueAccessor {
|
||||
|
||||
constructor(injector: Injector, el: ElementRef) {
|
||||
super(injector, el);
|
||||
}
|
||||
|
||||
@HostListener('ionChange', ['$event.target'])
|
||||
_handleChangeEvent(el: any): void {
|
||||
_handleChangeEvent(el: any) {
|
||||
this.handleChangeEvent(el, el.value);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { ElementRef, Injector, Directive, HostListener } from '@angular/core';
|
||||
import { Directive, ElementRef, HostListener, Injector } from '@angular/core';
|
||||
import { NG_VALUE_ACCESSOR } from '@angular/forms';
|
||||
|
||||
import { ValueAccessor } from './value-accessor';
|
||||
@@ -9,18 +9,19 @@ import { ValueAccessor } from './value-accessor';
|
||||
providers: [
|
||||
{
|
||||
provide: NG_VALUE_ACCESSOR,
|
||||
useExisting: TextValueAccessorDirective,
|
||||
multi: true,
|
||||
},
|
||||
],
|
||||
useExisting: TextValueAccessor,
|
||||
multi: true
|
||||
}
|
||||
]
|
||||
})
|
||||
export class TextValueAccessorDirective extends ValueAccessor {
|
||||
export class TextValueAccessor extends ValueAccessor {
|
||||
|
||||
constructor(injector: Injector, el: ElementRef) {
|
||||
super(injector, el);
|
||||
}
|
||||
|
||||
@HostListener('ionChange', ['$event.target'])
|
||||
_handleInputEvent(el: any): void {
|
||||
_handleInputEvent(el: any) {
|
||||
this.handleChangeEvent(el, el.value);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,23 +1,19 @@
|
||||
import { AfterViewInit, ElementRef, Injector, OnDestroy, Directive, HostListener } from '@angular/core';
|
||||
import { AfterViewInit, ElementRef, HostListener, Injector, OnDestroy, Type } from '@angular/core';
|
||||
import { ControlValueAccessor, NgControl } from '@angular/forms';
|
||||
import { Subscription } from 'rxjs';
|
||||
|
||||
import { raf } from '../../util/util';
|
||||
|
||||
@Directive()
|
||||
export class ValueAccessor implements ControlValueAccessor, AfterViewInit, OnDestroy {
|
||||
private onChange: (value: any) => void = () => {
|
||||
/**/
|
||||
};
|
||||
private onTouched: () => void = () => {
|
||||
/**/
|
||||
};
|
||||
|
||||
private onChange: (value: any) => void = () => {/**/};
|
||||
private onTouched: () => void = () => {/**/};
|
||||
protected lastValue: any;
|
||||
private statusChanges?: Subscription;
|
||||
|
||||
constructor(protected injector: Injector, protected el: ElementRef) {}
|
||||
|
||||
writeValue(value: any): void {
|
||||
writeValue(value: any) {
|
||||
/**
|
||||
* TODO for Ionic 6:
|
||||
* Change `value == null ? '' : value;`
|
||||
@@ -29,7 +25,7 @@ export class ValueAccessor implements ControlValueAccessor, AfterViewInit, OnDes
|
||||
setIonicClasses(this.el);
|
||||
}
|
||||
|
||||
handleChangeEvent(el: HTMLElement, value: any): void {
|
||||
handleChangeEvent(el: HTMLElement, value: any) {
|
||||
if (el === this.el.nativeElement) {
|
||||
if (value !== this.lastValue) {
|
||||
this.lastValue = value;
|
||||
@@ -40,42 +36,38 @@ export class ValueAccessor implements ControlValueAccessor, AfterViewInit, OnDes
|
||||
}
|
||||
|
||||
@HostListener('ionBlur', ['$event.target'])
|
||||
_handleBlurEvent(el: any): void {
|
||||
_handleBlurEvent(el: any) {
|
||||
if (el === this.el.nativeElement) {
|
||||
this.onTouched();
|
||||
setIonicClasses(this.el);
|
||||
}
|
||||
}
|
||||
|
||||
registerOnChange(fn: (value: any) => void): void {
|
||||
registerOnChange(fn: (value: any) => void) {
|
||||
this.onChange = fn;
|
||||
}
|
||||
|
||||
registerOnTouched(fn: () => void): void {
|
||||
registerOnTouched(fn: () => void) {
|
||||
this.onTouched = fn;
|
||||
}
|
||||
|
||||
setDisabledState(isDisabled: boolean): void {
|
||||
setDisabledState(isDisabled: boolean) {
|
||||
this.el.nativeElement.disabled = isDisabled;
|
||||
}
|
||||
|
||||
ngOnDestroy(): void {
|
||||
ngOnDestroy() {
|
||||
if (this.statusChanges) {
|
||||
this.statusChanges.unsubscribe();
|
||||
}
|
||||
}
|
||||
|
||||
ngAfterViewInit(): void {
|
||||
ngAfterViewInit() {
|
||||
let ngControl;
|
||||
try {
|
||||
ngControl = this.injector.get<NgControl>(NgControl);
|
||||
} catch {
|
||||
/* No FormControl or ngModel binding */
|
||||
}
|
||||
ngControl = this.injector.get<NgControl>(NgControl as Type<NgControl>);
|
||||
} catch { /* No FormControl or ngModel binding */ }
|
||||
|
||||
if (!ngControl) {
|
||||
return;
|
||||
}
|
||||
if (!ngControl) { return; }
|
||||
|
||||
// Listen for changes in validity, disabled, or pending states
|
||||
if (ngControl.statusChanges) {
|
||||
@@ -92,15 +84,15 @@ export class ValueAccessor implements ControlValueAccessor, AfterViewInit, OnDes
|
||||
* This patches the methods to manually sync
|
||||
* the classes until this feature is implemented in Angular.
|
||||
*/
|
||||
const formControl = ngControl.control as any;
|
||||
const formControl = ngControl.control;
|
||||
if (formControl) {
|
||||
const methodsToPatch = ['markAsTouched', 'markAllAsTouched', 'markAsUntouched', 'markAsDirty', 'markAsPristine'];
|
||||
methodsToPatch.forEach((method) => {
|
||||
if (formControl.get(method)) {
|
||||
const oldFn = formControl[method].bind(formControl);
|
||||
formControl[method] = (...params: any[]) => {
|
||||
oldFn(...params);
|
||||
setIonicClasses(this.el);
|
||||
const methodsToPatch = ['markAsTouched', 'markAllAsTouched', 'markAsUntouched', 'markAsDirty', 'markAsPristine'] as const;
|
||||
methodsToPatch.forEach(method => {
|
||||
if (formControl[method]) {
|
||||
const oldFn = formControl[method].bind(formControl);
|
||||
formControl[method] = (...params: any[]) => {
|
||||
oldFn(...params);
|
||||
setIonicClasses(this.el);
|
||||
};
|
||||
}
|
||||
});
|
||||
@@ -108,7 +100,7 @@ export class ValueAccessor implements ControlValueAccessor, AfterViewInit, OnDes
|
||||
}
|
||||
}
|
||||
|
||||
export const setIonicClasses = (element: ElementRef): void => {
|
||||
export const setIonicClasses = (element: ElementRef) => {
|
||||
raf(() => {
|
||||
const input = element.nativeElement as HTMLElement;
|
||||
const classes = getClasses(input);
|
||||
@@ -135,11 +127,16 @@ const getClasses = (element: HTMLElement) => {
|
||||
|
||||
const setClasses = (element: HTMLElement, classes: string[]) => {
|
||||
const classList = element.classList;
|
||||
['ion-valid', 'ion-invalid', 'ion-touched', 'ion-untouched', 'ion-dirty', 'ion-pristine'].forEach((c) =>
|
||||
classList.remove(c)
|
||||
);
|
||||
[
|
||||
'ion-valid',
|
||||
'ion-invalid',
|
||||
'ion-touched',
|
||||
'ion-untouched',
|
||||
'ion-dirty',
|
||||
'ion-pristine'
|
||||
].forEach(c => classList.remove(c));
|
||||
|
||||
classes.forEach((c) => classList.add(c));
|
||||
classes.forEach(c => classList.add(c));
|
||||
};
|
||||
|
||||
const startsWith = (input: string, search: string): boolean => {
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { Directive, HostListener, Input, Optional } from '@angular/core';
|
||||
import { Directive, HostListener, Optional } from '@angular/core';
|
||||
import { AnimationBuilder } from '@ionic/core';
|
||||
|
||||
import { Config } from '../../providers/config';
|
||||
@@ -8,12 +8,11 @@ import { IonRouterOutlet } from './ion-router-outlet';
|
||||
|
||||
@Directive({
|
||||
selector: 'ion-back-button',
|
||||
inputs: ['defaultHref', 'routerAnimation'],
|
||||
})
|
||||
export class IonBackButtonDelegateDirective {
|
||||
@Input()
|
||||
defaultHref: string | undefined | null;
|
||||
export class IonBackButtonDelegate {
|
||||
|
||||
@Input()
|
||||
defaultHref: string | undefined | null;
|
||||
routerAnimation?: AnimationBuilder;
|
||||
|
||||
constructor(
|
||||
@@ -26,10 +25,10 @@ export class IonBackButtonDelegateDirective {
|
||||
* @internal
|
||||
*/
|
||||
@HostListener('click', ['$event'])
|
||||
onClick(ev: Event): void {
|
||||
onClick(ev: Event) {
|
||||
const defaultHref = this.defaultHref || this.config.get('backButtonDefaultHref');
|
||||
|
||||
if (this.routerOutlet?.canGoBack()) {
|
||||
if (this.routerOutlet && this.routerOutlet.canGoBack()) {
|
||||
this.navCtrl.setDirection('back', undefined, undefined, this.routerAnimation);
|
||||
this.routerOutlet.pop();
|
||||
ev.preventDefault();
|
||||
|
||||
@@ -1,26 +1,11 @@
|
||||
import { Location } from '@angular/common';
|
||||
import {
|
||||
ComponentFactoryResolver,
|
||||
ComponentRef,
|
||||
ElementRef,
|
||||
Injector,
|
||||
NgZone,
|
||||
OnDestroy,
|
||||
OnInit,
|
||||
ViewContainerRef,
|
||||
Attribute,
|
||||
Directive,
|
||||
EventEmitter,
|
||||
Optional,
|
||||
Output,
|
||||
SkipSelf,
|
||||
} from '@angular/core';
|
||||
import { OutletContext, Router, ActivatedRoute, ChildrenOutletContexts, PRIMARY_OUTLET } from '@angular/router';
|
||||
import { Attribute, ComponentFactoryResolver, ComponentRef, Directive, ElementRef, EventEmitter, Injector, NgZone, OnDestroy, OnInit, Optional, Output, SkipSelf, ViewContainerRef } from '@angular/core';
|
||||
import { ActivatedRoute, ChildrenOutletContexts, OutletContext, PRIMARY_OUTLET, Router } from '@angular/router';
|
||||
import { componentOnReady } from '@ionic/core';
|
||||
import { Observable, BehaviorSubject } from 'rxjs';
|
||||
import { BehaviorSubject, Observable } from 'rxjs';
|
||||
import { distinctUntilChanged, filter, switchMap } from 'rxjs/operators';
|
||||
|
||||
import { AnimationBuilder } from '../../ionic-core';
|
||||
import { AnimationBuilder } from '../../';
|
||||
import { Config } from '../../providers/config';
|
||||
import { NavController } from '../../providers/nav-controller';
|
||||
|
||||
@@ -30,10 +15,8 @@ import { RouteView, getUrl } from './stack-utils';
|
||||
@Directive({
|
||||
selector: 'ion-router-outlet',
|
||||
exportAs: 'outlet',
|
||||
// eslint-disable-next-line @angular-eslint/no-inputs-metadata-property
|
||||
inputs: ['animated', 'animation', 'swipeGesture'],
|
||||
inputs: ['animated', 'animation', 'swipeGesture']
|
||||
})
|
||||
// eslint-disable-next-line @angular-eslint/directive-class-suffix
|
||||
export class IonRouterOutlet implements OnDestroy, OnInit {
|
||||
nativeEl: HTMLIonRouterOutletElement;
|
||||
|
||||
@@ -54,9 +37,7 @@ export class IonRouterOutlet implements OnDestroy, OnInit {
|
||||
tabsPrefix: string | undefined;
|
||||
|
||||
@Output() stackEvents = new EventEmitter<any>();
|
||||
// eslint-disable-next-line @angular-eslint/no-output-rename
|
||||
@Output('activate') activateEvents = new EventEmitter<any>();
|
||||
// eslint-disable-next-line @angular-eslint/no-output-rename
|
||||
@Output('deactivate') deactivateEvents = new EventEmitter<any>();
|
||||
|
||||
set animation(animation: AnimationBuilder) {
|
||||
@@ -70,13 +51,11 @@ export class IonRouterOutlet implements OnDestroy, OnInit {
|
||||
set swipeGesture(swipe: boolean) {
|
||||
this._swipeGesture = swipe;
|
||||
|
||||
this.nativeEl.swipeHandler = swipe
|
||||
? {
|
||||
canStart: () => this.stackCtrl.canGoBack(1) && !this.stackCtrl.hasRunningTask(),
|
||||
onStart: () => this.stackCtrl.startBackTransition(),
|
||||
onEnd: (shouldContinue) => this.stackCtrl.endBackTransition(shouldContinue),
|
||||
}
|
||||
: undefined;
|
||||
this.nativeEl.swipeHandler = swipe ? {
|
||||
canStart: () => this.stackCtrl.canGoBack(1) && !this.stackCtrl.hasRunningTask(),
|
||||
onStart: () => this.stackCtrl.startBackTransition(),
|
||||
onEnd: shouldContinue => this.stackCtrl.endBackTransition(shouldContinue)
|
||||
} : undefined;
|
||||
}
|
||||
|
||||
constructor(
|
||||
@@ -114,12 +93,12 @@ export class IonRouterOutlet implements OnDestroy, OnInit {
|
||||
// If the outlet was not instantiated at the time the route got activated we need to populate
|
||||
// the outlet when it is initialized (ie inside a NgIf)
|
||||
const context = this.getContext();
|
||||
if (context?.route) {
|
||||
if (context && context.route) {
|
||||
this.activateWith(context.route, context.resolver || null);
|
||||
}
|
||||
}
|
||||
|
||||
new Promise((resolve) => componentOnReady(this.nativeEl, resolve)).then(() => {
|
||||
new Promise(resolve => componentOnReady(this.nativeEl, resolve)).then(() => {
|
||||
if (this._swipeGesture === undefined) {
|
||||
this.swipeGesture = this.config.getBoolean('swipeBackEnabled', (this.nativeEl as any).mode === 'ios');
|
||||
}
|
||||
@@ -130,7 +109,7 @@ export class IonRouterOutlet implements OnDestroy, OnInit {
|
||||
return !!this.activated;
|
||||
}
|
||||
|
||||
get component(): Record<string, unknown> {
|
||||
get component(): object {
|
||||
if (!this.activated) {
|
||||
throw new Error('Outlet is not activated');
|
||||
}
|
||||
@@ -161,15 +140,13 @@ export class IonRouterOutlet implements OnDestroy, OnInit {
|
||||
/**
|
||||
* Called when the `RouteReuseStrategy` instructs to re-attach a previously detached subtree
|
||||
*/
|
||||
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
||||
attach(_ref: ComponentRef<any>, _activatedRoute: ActivatedRoute): void {
|
||||
attach(_ref: ComponentRef<any>, _activatedRoute: ActivatedRoute) {
|
||||
throw new Error('incompatible reuse strategy');
|
||||
}
|
||||
|
||||
deactivate(): void {
|
||||
if (this.activated) {
|
||||
if (this.activatedView) {
|
||||
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
|
||||
const context = this.getContext()!;
|
||||
this.activatedView.savedData = new Map(context.children['contexts']);
|
||||
|
||||
@@ -195,7 +172,7 @@ export class IonRouterOutlet implements OnDestroy, OnInit {
|
||||
const contextSnapshot = context.route.snapshot;
|
||||
|
||||
this.activatedView.savedExtras.queryParams = contextSnapshot.queryParams;
|
||||
(this.activatedView.savedExtras.fragment as string | null) = contextSnapshot.fragment;
|
||||
this.activatedView.savedExtras.fragment = contextSnapshot.fragment;
|
||||
}
|
||||
}
|
||||
const c = this.component;
|
||||
@@ -206,7 +183,7 @@ export class IonRouterOutlet implements OnDestroy, OnInit {
|
||||
}
|
||||
}
|
||||
|
||||
activateWith(activatedRoute: ActivatedRoute, resolver: ComponentFactoryResolver | null): void {
|
||||
activateWith(activatedRoute: ActivatedRoute, resolver: ComponentFactoryResolver | null) {
|
||||
if (this.isActivated) {
|
||||
throw new Error('Cannot activate an already activated outlet');
|
||||
}
|
||||
@@ -219,7 +196,6 @@ export class IonRouterOutlet implements OnDestroy, OnInit {
|
||||
const saved = enteringView.savedData;
|
||||
if (saved) {
|
||||
// self-restore
|
||||
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
|
||||
const context = this.getContext()!;
|
||||
context.children['contexts'] = saved;
|
||||
}
|
||||
@@ -227,7 +203,6 @@ export class IonRouterOutlet implements OnDestroy, OnInit {
|
||||
this.updateActivatedRouteProxy(cmpRef.instance, activatedRoute);
|
||||
} else {
|
||||
const snapshot = (activatedRoute as any)._futureSnapshot;
|
||||
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
|
||||
const component = snapshot.routeConfig!.component as any;
|
||||
resolver = resolver || this.resolver;
|
||||
|
||||
@@ -255,7 +230,7 @@ export class IonRouterOutlet implements OnDestroy, OnInit {
|
||||
}
|
||||
|
||||
this.activatedView = enteringView;
|
||||
this.stackCtrl.setActive(enteringView).then((data) => {
|
||||
this.stackCtrl.setActive(enteringView).then(data => {
|
||||
this.navCtrl.setTopOutlet(this);
|
||||
this.activateEvents.emit(cmpRef.instance);
|
||||
this.stackEvents.emit(data);
|
||||
@@ -338,11 +313,11 @@ export class IonRouterOutlet implements OnDestroy, OnInit {
|
||||
private proxyObservable(component$: Observable<any>, path: string): Observable<any> {
|
||||
return component$.pipe(
|
||||
// First wait until the component instance is pushed
|
||||
filter((component) => !!component),
|
||||
switchMap((component) =>
|
||||
filter(component => !!component),
|
||||
switchMap(component =>
|
||||
this.currentActivatedRoute$.pipe(
|
||||
filter((current) => current !== null && current.component === component),
|
||||
switchMap((current) => current && (current.activatedRoute as any)[path]),
|
||||
filter(current => current !== null && current.component === component),
|
||||
switchMap(current => current && (current.activatedRoute as any)[path]),
|
||||
distinctUntilChanged()
|
||||
)
|
||||
)
|
||||
@@ -369,7 +344,11 @@ export class IonRouterOutlet implements OnDestroy, OnInit {
|
||||
}
|
||||
|
||||
class OutletInjector implements Injector {
|
||||
constructor(private route: ActivatedRoute, private childContexts: ChildrenOutletContexts, private parent: Injector) {}
|
||||
constructor(
|
||||
private route: ActivatedRoute,
|
||||
private childContexts: ChildrenOutletContexts,
|
||||
private parent: Injector
|
||||
) { }
|
||||
|
||||
get(token: any, notFoundValue?: any): any {
|
||||
if (token === ActivatedRoute) {
|
||||
@@ -380,6 +359,7 @@ class OutletInjector implements Injector {
|
||||
return this.childContexts;
|
||||
}
|
||||
|
||||
// tslint:disable-next-line
|
||||
return this.parent.get(token, notFoundValue);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -8,53 +8,54 @@ import { StackEvent } from './stack-utils';
|
||||
|
||||
@Component({
|
||||
selector: 'ion-tabs',
|
||||
template: ` <ng-content select="[slot=top]"></ng-content>
|
||||
template: `
|
||||
<ng-content select="[slot=top]"></ng-content>
|
||||
<div class="tabs-inner">
|
||||
<ion-router-outlet #outlet tabs="true" (stackEvents)="onPageSelected($event)"></ion-router-outlet>
|
||||
</div>
|
||||
<ng-content></ng-content>`,
|
||||
styles: [
|
||||
`
|
||||
:host {
|
||||
display: flex;
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
right: 0;
|
||||
bottom: 0;
|
||||
styles: [`
|
||||
:host {
|
||||
display: flex;
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
right: 0;
|
||||
bottom: 0;
|
||||
|
||||
flex-direction: column;
|
||||
flex-direction: column;
|
||||
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
|
||||
contain: layout size style;
|
||||
z-index: $z-index-page-container;
|
||||
}
|
||||
.tabs-inner {
|
||||
position: relative;
|
||||
contain: layout size style;
|
||||
z-index: $z-index-page-container;
|
||||
}
|
||||
.tabs-inner {
|
||||
position: relative;
|
||||
|
||||
flex: 1;
|
||||
flex: 1;
|
||||
|
||||
contain: layout size style;
|
||||
}
|
||||
`,
|
||||
],
|
||||
contain: layout size style;
|
||||
}`
|
||||
]
|
||||
})
|
||||
// eslint-disable-next-line @angular-eslint/component-class-suffix
|
||||
export class IonTabs {
|
||||
|
||||
@ViewChild('outlet', { read: IonRouterOutlet, static: false }) outlet: IonRouterOutlet;
|
||||
@ContentChild(IonTabBar, { static: false }) tabBar: IonTabBar | undefined;
|
||||
|
||||
@Output() ionTabsWillChange = new EventEmitter<{ tab: string }>();
|
||||
@Output() ionTabsDidChange = new EventEmitter<{ tab: string }>();
|
||||
|
||||
constructor(private navCtrl: NavController) {}
|
||||
constructor(
|
||||
private navCtrl: NavController,
|
||||
) { }
|
||||
|
||||
/**
|
||||
* @internal
|
||||
*/
|
||||
onPageSelected(detail: StackEvent): void {
|
||||
onPageSelected(detail: StackEvent) {
|
||||
const stackId = detail.enteringView.stackId;
|
||||
if (detail.tabSwitch && stackId !== undefined) {
|
||||
if (this.tabBar) {
|
||||
@@ -86,9 +87,9 @@ export class IonTabs {
|
||||
* to the default tabRootUrl
|
||||
*/
|
||||
@HostListener('ionTabButtonClick', ['$event'])
|
||||
select(tabOrEvent: string | CustomEvent): Promise<boolean> | undefined {
|
||||
select(tabOrEvent: string | CustomEvent) {
|
||||
const isTabString = typeof tabOrEvent === 'string';
|
||||
const tab = isTabString ? tabOrEvent : (tabOrEvent as CustomEvent).detail.tab;
|
||||
const tab = (isTabString) ? tabOrEvent : (tabOrEvent as CustomEvent).detail.tab;
|
||||
const alreadySelected = this.outlet.getActiveStackId() === tab;
|
||||
const tabRootUrl = `${this.outlet.tabsPrefix}/${tab}`;
|
||||
|
||||
@@ -107,14 +108,12 @@ export class IonTabs {
|
||||
const activeView = this.outlet.getLastRouteView(activeStackId);
|
||||
|
||||
// If on root tab, do not navigate to root tab again
|
||||
if (activeView?.url === tabRootUrl) {
|
||||
return;
|
||||
}
|
||||
if (activeView.url === tabRootUrl) { return; }
|
||||
|
||||
const rootView = this.outlet.getRootView(tab);
|
||||
const navigationExtras = rootView && tabRootUrl === rootView.url && rootView.savedExtras;
|
||||
return this.navCtrl.navigateRoot(tabRootUrl, {
|
||||
...navigationExtras,
|
||||
...(navigationExtras),
|
||||
animated: true,
|
||||
animationDirection: 'back',
|
||||
});
|
||||
@@ -124,11 +123,11 @@ export class IonTabs {
|
||||
* If there is a lastRoute, goto that, otherwise goto the fallback url of the
|
||||
* selected tab
|
||||
*/
|
||||
const url = lastRoute?.url || tabRootUrl;
|
||||
const navigationExtras = lastRoute?.savedExtras;
|
||||
const url = lastRoute && lastRoute.url || tabRootUrl;
|
||||
const navigationExtras = lastRoute && lastRoute.savedExtras;
|
||||
|
||||
return this.navCtrl.navigateRoot(url, {
|
||||
...navigationExtras,
|
||||
...(navigationExtras),
|
||||
animated: true,
|
||||
animationDirection: 'back',
|
||||
});
|
||||
|
||||
@@ -1,30 +1,15 @@
|
||||
import { ComponentFactoryResolver, ElementRef, Injector, ViewContainerRef, Directive } from '@angular/core';
|
||||
import { ComponentFactoryResolver, Directive, ElementRef, Injector, ViewContainerRef } from '@angular/core';
|
||||
|
||||
import { AngularDelegate } from '../../providers/angular-delegate';
|
||||
import { ProxyCmp, proxyOutputs } from '../angular-component-lib/utils';
|
||||
import { ProxyCmp, proxyOutputs } from '../proxies-utils';
|
||||
|
||||
@ProxyCmp({
|
||||
inputs: ['animated', 'animation', 'root', 'rootParams', 'swipeGesture'],
|
||||
methods: [
|
||||
'push',
|
||||
'insert',
|
||||
'insertPages',
|
||||
'pop',
|
||||
'popTo',
|
||||
'popToRoot',
|
||||
'removeIndex',
|
||||
'setRoot',
|
||||
'setPages',
|
||||
'getActive',
|
||||
'getByIndex',
|
||||
'canGoBack',
|
||||
'getPrevious',
|
||||
],
|
||||
methods: ['push', 'insert', 'insertPages', 'pop', 'popTo', 'popToRoot', 'removeIndex', 'setRoot', 'setPages', 'getActive', 'getByIndex', 'canGoBack', 'getPrevious']
|
||||
})
|
||||
@Directive({
|
||||
selector: 'ion-nav',
|
||||
selector: 'ion-nav'
|
||||
})
|
||||
// eslint-disable-next-line @angular-eslint/directive-class-suffix
|
||||
export class NavDelegate {
|
||||
protected el: HTMLElement;
|
||||
constructor(
|
||||
@@ -36,6 +21,6 @@ export class NavDelegate {
|
||||
) {
|
||||
this.el = ref.nativeElement;
|
||||
ref.nativeElement.delegate = angularDelegate.create(resolver, injector, location);
|
||||
proxyOutputs(this, this.el, ['ionNavDidChange', 'ionNavWillChange']);
|
||||
proxyOutputs(this, this.el, ['ionNavDidChange' , 'ionNavWillChange' ]);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -19,7 +19,8 @@
|
||||
* ```
|
||||
*/
|
||||
export class NavParams {
|
||||
constructor(public data: { [key: string]: any } = {}) {}
|
||||
|
||||
constructor(public data: {[key: string]: any} = {}) {}
|
||||
|
||||
/**
|
||||
* Get the value of a nav-parameter for the current view
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import { LocationStrategy } from '@angular/common';
|
||||
import { ElementRef, OnChanges, OnDestroy, OnInit, Directive, HostListener, Input, Optional } from '@angular/core';
|
||||
import { Directive, ElementRef, HostListener, Optional } from '@angular/core';
|
||||
import { Router, RouterLink } from '@angular/router';
|
||||
import { AnimationBuilder, RouterDirection } from '@ionic/core';
|
||||
import { Subscription } from 'rxjs';
|
||||
@@ -8,14 +8,13 @@ import { NavController } from '../../providers/nav-controller';
|
||||
|
||||
@Directive({
|
||||
selector: '[routerLink]',
|
||||
inputs: ['routerDirection', 'routerAnimation']
|
||||
})
|
||||
export class RouterLinkDelegateDirective implements OnInit, OnChanges, OnDestroy {
|
||||
export class RouterLinkDelegate {
|
||||
|
||||
private subscription?: Subscription;
|
||||
|
||||
@Input()
|
||||
routerDirection: RouterDirection = 'forward';
|
||||
|
||||
@Input()
|
||||
routerAnimation?: AnimationBuilder;
|
||||
|
||||
constructor(
|
||||
@@ -23,18 +22,18 @@ export class RouterLinkDelegateDirective implements OnInit, OnChanges, OnDestroy
|
||||
private navCtrl: NavController,
|
||||
private elementRef: ElementRef,
|
||||
private router: Router,
|
||||
@Optional() private routerLink?: RouterLink
|
||||
) {}
|
||||
@Optional() private routerLink?: RouterLink,
|
||||
) { }
|
||||
|
||||
ngOnInit(): void {
|
||||
ngOnInit() {
|
||||
this.updateTargetUrlAndHref();
|
||||
}
|
||||
|
||||
ngOnChanges(): void {
|
||||
ngOnChanges(): any {
|
||||
this.updateTargetUrlAndHref();
|
||||
}
|
||||
|
||||
ngOnDestroy(): void {
|
||||
ngOnDestroy(): any {
|
||||
if (this.subscription) {
|
||||
this.subscription.unsubscribe();
|
||||
}
|
||||
@@ -51,7 +50,7 @@ export class RouterLinkDelegateDirective implements OnInit, OnChanges, OnDestroy
|
||||
* @internal
|
||||
*/
|
||||
@HostListener('click', ['$event'])
|
||||
onClick(ev: UIEvent): void {
|
||||
onClick(ev: UIEvent) {
|
||||
this.navCtrl.setDirection(this.routerDirection, undefined, undefined, this.routerAnimation);
|
||||
ev.preventDefault();
|
||||
}
|
||||
|
||||
@@ -6,18 +6,10 @@ import { AnimationBuilder, RouterDirection } from '@ionic/core';
|
||||
import { bindLifecycleEvents } from '../../providers/angular-delegate';
|
||||
import { NavController } from '../../providers/nav-controller';
|
||||
|
||||
import {
|
||||
RouteView,
|
||||
StackEvent,
|
||||
computeStackId,
|
||||
destroyView,
|
||||
getUrl,
|
||||
insertView,
|
||||
isTabSwitch,
|
||||
toSegments,
|
||||
} from './stack-utils';
|
||||
import { RouteView, StackEvent, computeStackId, destroyView, getUrl, insertView, isTabSwitch, toSegments } from './stack-utils';
|
||||
|
||||
export class StackController {
|
||||
|
||||
private views: RouteView[] = [];
|
||||
private runningTask?: Promise<any>;
|
||||
private skipTransition = false;
|
||||
@@ -38,7 +30,7 @@ export class StackController {
|
||||
|
||||
createView(ref: ComponentRef<any>, activatedRoute: ActivatedRoute): RouteView {
|
||||
const url = getUrl(this.router, activatedRoute);
|
||||
const element = ref?.location?.nativeElement as HTMLElement;
|
||||
const element = (ref && ref.location && ref.location.nativeElement) as HTMLElement;
|
||||
const unlistenEvents = bindLifecycleEvents(this.zone, ref.instance, element);
|
||||
return {
|
||||
id: this.nextId++,
|
||||
@@ -52,7 +44,7 @@ export class StackController {
|
||||
|
||||
getExistingView(activatedRoute: ActivatedRoute): RouteView | undefined {
|
||||
const activatedUrlKey = getUrl(this.router, activatedRoute);
|
||||
const view = this.views.find((vw) => vw.url === activatedUrlKey);
|
||||
const view = this.views.find(vw => vw.url === activatedUrlKey);
|
||||
if (view) {
|
||||
view.ref.changeDetectorRef.reattach();
|
||||
}
|
||||
@@ -73,14 +65,17 @@ export class StackController {
|
||||
|
||||
let currentNavigation;
|
||||
|
||||
const router = this.router as any;
|
||||
const router = (this.router as any);
|
||||
|
||||
// Angular >= 7.2.0
|
||||
if (router.getCurrentNavigation) {
|
||||
currentNavigation = router.getCurrentNavigation();
|
||||
|
||||
// Angular < 7.2.0
|
||||
} else if (router.navigations?.value) {
|
||||
} else if (
|
||||
router.navigations &&
|
||||
router.navigations.value
|
||||
) {
|
||||
currentNavigation = router.navigations.value;
|
||||
}
|
||||
|
||||
@@ -91,7 +86,11 @@ export class StackController {
|
||||
* we remove the last item
|
||||
* from our views stack
|
||||
*/
|
||||
if (currentNavigation?.extras?.replaceUrl) {
|
||||
if (
|
||||
currentNavigation &&
|
||||
currentNavigation.extras &&
|
||||
currentNavigation.extras.replaceUrl
|
||||
) {
|
||||
if (this.views.length > 0) {
|
||||
this.views.splice(-1, 1);
|
||||
}
|
||||
@@ -115,7 +114,12 @@ export class StackController {
|
||||
* provided another animation.
|
||||
*/
|
||||
const customAnimation = enteringView.animationBuilder;
|
||||
if (animationBuilder === undefined && direction === 'back' && !tabSwitch && customAnimation !== undefined) {
|
||||
if (
|
||||
animationBuilder === undefined &&
|
||||
direction === 'back' &&
|
||||
!tabSwitch &&
|
||||
customAnimation !== undefined
|
||||
) {
|
||||
animationBuilder = customAnimation;
|
||||
}
|
||||
|
||||
@@ -144,7 +148,7 @@ export class StackController {
|
||||
enteringView,
|
||||
direction,
|
||||
animation,
|
||||
tabSwitch,
|
||||
tabSwitch
|
||||
}));
|
||||
});
|
||||
});
|
||||
@@ -154,7 +158,7 @@ export class StackController {
|
||||
return this.getStack(stackId).length > deep;
|
||||
}
|
||||
|
||||
pop(deep: number, stackId = this.getActiveStackId()): Promise<boolean> {
|
||||
pop(deep: number, stackId = this.getActiveStackId()) {
|
||||
return this.zone.run(() => {
|
||||
const views = this.getStack(stackId);
|
||||
if (views.length <= deep) {
|
||||
@@ -166,7 +170,13 @@ export class StackController {
|
||||
const viewSavedData = view.savedData;
|
||||
if (viewSavedData) {
|
||||
const primaryOutlet = viewSavedData.get('primary');
|
||||
if (primaryOutlet?.route?._routerState?.snapshot.url) {
|
||||
if (
|
||||
primaryOutlet &&
|
||||
primaryOutlet.route &&
|
||||
primaryOutlet.route._routerState &&
|
||||
primaryOutlet.route._routerState.snapshot &&
|
||||
primaryOutlet.route._routerState.snapshot.url
|
||||
) {
|
||||
url = primaryOutlet.route._routerState.snapshot.url;
|
||||
}
|
||||
}
|
||||
@@ -175,7 +185,7 @@ export class StackController {
|
||||
});
|
||||
}
|
||||
|
||||
startBackTransition(): Promise<boolean> | Promise<void> {
|
||||
startBackTransition() {
|
||||
const leavingView = this.activeView;
|
||||
if (leavingView) {
|
||||
const views = this.getStack(leavingView.stackId);
|
||||
@@ -196,7 +206,7 @@ export class StackController {
|
||||
return Promise.resolve();
|
||||
}
|
||||
|
||||
endBackTransition(shouldComplete: boolean): void {
|
||||
endBackTransition(shouldComplete: boolean) {
|
||||
if (shouldComplete) {
|
||||
this.skipTransition = true;
|
||||
this.pop(1);
|
||||
@@ -205,7 +215,7 @@ export class StackController {
|
||||
}
|
||||
}
|
||||
|
||||
getLastUrl(stackId?: string): RouteView | undefined {
|
||||
getLastUrl(stackId?: string) {
|
||||
const views = this.getStack(stackId);
|
||||
return views.length > 0 ? views[views.length - 1] : undefined;
|
||||
}
|
||||
@@ -213,7 +223,7 @@ export class StackController {
|
||||
/**
|
||||
* @internal
|
||||
*/
|
||||
getRootUrl(stackId?: string): RouteView | undefined {
|
||||
getRootUrl(stackId?: string) {
|
||||
const views = this.getStack(stackId);
|
||||
return views.length > 0 ? views[0] : undefined;
|
||||
}
|
||||
@@ -226,8 +236,7 @@ export class StackController {
|
||||
return this.runningTask !== undefined;
|
||||
}
|
||||
|
||||
destroy(): void {
|
||||
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
|
||||
destroy() {
|
||||
this.containerEl = undefined!;
|
||||
this.views.forEach(destroyView);
|
||||
this.activeView = undefined;
|
||||
@@ -235,7 +244,7 @@ export class StackController {
|
||||
}
|
||||
|
||||
private getStack(stackId: string | undefined) {
|
||||
return this.views.filter((v) => v.stackId === stackId);
|
||||
return this.views.filter(v => v.stackId === stackId);
|
||||
}
|
||||
|
||||
private insertView(enteringView: RouteView, direction: RouterDirection) {
|
||||
@@ -276,7 +285,7 @@ export class StackController {
|
||||
direction,
|
||||
showGoBack,
|
||||
progressAnimation,
|
||||
animationBuilder,
|
||||
animationBuilder
|
||||
});
|
||||
}
|
||||
}
|
||||
@@ -288,15 +297,15 @@ export class StackController {
|
||||
await this.runningTask;
|
||||
this.runningTask = undefined;
|
||||
}
|
||||
const promise = (this.runningTask = task());
|
||||
promise.finally(() => (this.runningTask = undefined));
|
||||
const promise = this.runningTask = task();
|
||||
promise.finally(() => this.runningTask = undefined);
|
||||
return promise;
|
||||
}
|
||||
}
|
||||
|
||||
const cleanupAsync = (activeRoute: RouteView, views: RouteView[], viewsSnapshot: RouteView[], location: Location) => {
|
||||
if (typeof (requestAnimationFrame as any) === 'function') {
|
||||
return new Promise<void>((resolve) => {
|
||||
return new Promise<void>(resolve => {
|
||||
requestAnimationFrame(() => {
|
||||
cleanup(activeRoute, views, viewsSnapshot, location);
|
||||
resolve();
|
||||
@@ -307,9 +316,11 @@ const cleanupAsync = (activeRoute: RouteView, views: RouteView[], viewsSnapshot:
|
||||
};
|
||||
|
||||
const cleanup = (activeRoute: RouteView, views: RouteView[], viewsSnapshot: RouteView[], location: Location) => {
|
||||
viewsSnapshot.filter((view) => !views.includes(view)).forEach(destroyView);
|
||||
viewsSnapshot
|
||||
.filter(view => !views.includes(view))
|
||||
.forEach(destroyView);
|
||||
|
||||
views.forEach((view) => {
|
||||
views.forEach(view => {
|
||||
/**
|
||||
* In the event that a user navigated multiple
|
||||
* times in rapid succession, we want to make sure
|
||||
|
||||
@@ -2,7 +2,7 @@ import { ComponentRef } from '@angular/core';
|
||||
import { ActivatedRoute, NavigationExtras, Router } from '@angular/router';
|
||||
import { AnimationBuilder, NavDirection, RouterDirection } from '@ionic/core';
|
||||
|
||||
export const insertView = (views: RouteView[], view: RouteView, direction: RouterDirection): RouteView[] => {
|
||||
export const insertView = (views: RouteView[], view: RouteView, direction: RouterDirection) => {
|
||||
if (direction === 'root') {
|
||||
return setRoot(views, view);
|
||||
} else if (direction === 'forward') {
|
||||
@@ -13,7 +13,7 @@ export const insertView = (views: RouteView[], view: RouteView, direction: Route
|
||||
};
|
||||
|
||||
const setRoot = (views: RouteView[], view: RouteView) => {
|
||||
views = views.filter((v) => v.stackId !== view.stackId);
|
||||
views = views.filter(v => v.stackId !== view.stackId);
|
||||
views.push(view);
|
||||
return views;
|
||||
};
|
||||
@@ -21,7 +21,7 @@ const setRoot = (views: RouteView[], view: RouteView) => {
|
||||
const setForward = (views: RouteView[], view: RouteView) => {
|
||||
const index = views.indexOf(view);
|
||||
if (index >= 0) {
|
||||
views = views.filter((v) => v.stackId !== view.stackId || v.id <= view.id);
|
||||
views = views.filter(v => v.stackId !== view.stackId || v.id <= view.id);
|
||||
} else {
|
||||
views.push(view);
|
||||
}
|
||||
@@ -31,25 +31,25 @@ const setForward = (views: RouteView[], view: RouteView) => {
|
||||
const setBack = (views: RouteView[], view: RouteView) => {
|
||||
const index = views.indexOf(view);
|
||||
if (index >= 0) {
|
||||
return views.filter((v) => v.stackId !== view.stackId || v.id <= view.id);
|
||||
return views.filter(v => v.stackId !== view.stackId || v.id <= view.id);
|
||||
} else {
|
||||
return setRoot(views, view);
|
||||
}
|
||||
};
|
||||
|
||||
export const getUrl = (router: Router, activatedRoute: ActivatedRoute): string => {
|
||||
export const getUrl = (router: Router, activatedRoute: ActivatedRoute) => {
|
||||
const urlTree = router.createUrlTree(['.'], { relativeTo: activatedRoute });
|
||||
return router.serializeUrl(urlTree);
|
||||
};
|
||||
|
||||
export const isTabSwitch = (enteringView: RouteView, leavingView: RouteView | undefined): boolean => {
|
||||
export const isTabSwitch = (enteringView: RouteView, leavingView: RouteView | undefined) => {
|
||||
if (!leavingView) {
|
||||
return true;
|
||||
}
|
||||
return enteringView.stackId !== leavingView.stackId;
|
||||
};
|
||||
|
||||
export const computeStackId = (prefixUrl: string[] | undefined, url: string): string | undefined => {
|
||||
export const computeStackId = (prefixUrl: string[] | undefined, url: string) => {
|
||||
if (!prefixUrl) {
|
||||
return undefined;
|
||||
}
|
||||
@@ -65,14 +65,14 @@ export const computeStackId = (prefixUrl: string[] | undefined, url: string): st
|
||||
return undefined;
|
||||
};
|
||||
|
||||
export const toSegments = (path: string): string[] => {
|
||||
export const toSegments = (path: string) => {
|
||||
return path
|
||||
.split('/')
|
||||
.map((s) => s.trim())
|
||||
.filter((s) => s !== '');
|
||||
.map(s => s.trim())
|
||||
.filter(s => s !== '');
|
||||
};
|
||||
|
||||
export const destroyView = (view: RouteView | undefined): void => {
|
||||
export const destroyView = (view: RouteView | undefined) => {
|
||||
if (view) {
|
||||
// TODO lifecycle event
|
||||
view.ref.destroy();
|
||||
|
||||
@@ -1,128 +0,0 @@
|
||||
/* eslint-disable */
|
||||
/* tslint:disable */
|
||||
import {
|
||||
ChangeDetectionStrategy,
|
||||
ChangeDetectorRef,
|
||||
Component,
|
||||
ContentChild,
|
||||
ElementRef,
|
||||
EventEmitter,
|
||||
NgZone,
|
||||
TemplateRef,
|
||||
} from '@angular/core';
|
||||
import { ProxyCmp, proxyOutputs } from '../angular-component-lib/utils';
|
||||
import { Components } from '@ionic/core';
|
||||
|
||||
export declare interface IonModal extends Components.IonModal {
|
||||
/**
|
||||
* Emitted after the modal has presented.
|
||||
**/
|
||||
ionModalDidPresent: EventEmitter<CustomEvent>;
|
||||
/**
|
||||
* Emitted before the modal has presented.
|
||||
*/
|
||||
ionModalWillPresent: EventEmitter<CustomEvent>;
|
||||
/**
|
||||
* Emitted before the modal has dismissed.
|
||||
*/
|
||||
ionModalWillDismiss: EventEmitter<CustomEvent>;
|
||||
/**
|
||||
* Emitted after the modal has dismissed.
|
||||
*/
|
||||
ionModalDidDismiss: EventEmitter<CustomEvent>;
|
||||
/**
|
||||
* Emitted after the modal has presented. Shorthand for ionModalWillDismiss.
|
||||
*/
|
||||
didPresent: EventEmitter<CustomEvent>;
|
||||
/**
|
||||
* Emitted before the modal has presented. Shorthand for ionModalWillPresent.
|
||||
*/
|
||||
willPresent: EventEmitter<CustomEvent>;
|
||||
/**
|
||||
* Emitted before the modal has dismissed. Shorthand for ionModalWillDismiss.
|
||||
*/
|
||||
willDismiss: EventEmitter<CustomEvent>;
|
||||
/**
|
||||
* Emitted after the modal has dismissed. Shorthand for ionModalDidDismiss.
|
||||
*/
|
||||
didDismiss: EventEmitter<CustomEvent>;
|
||||
}
|
||||
@ProxyCmp({
|
||||
inputs: [
|
||||
'animated',
|
||||
'backdropBreakpoint',
|
||||
'backdropDismiss',
|
||||
'breakpoints',
|
||||
'cssClass',
|
||||
'enterAnimation',
|
||||
'event',
|
||||
'handle',
|
||||
'initialBreakpoint',
|
||||
'isOpen',
|
||||
'keyboardClose',
|
||||
'leaveAnimation',
|
||||
'mode',
|
||||
'presentingElement',
|
||||
'showBackdrop',
|
||||
'swipeToClose',
|
||||
'translucent',
|
||||
'trigger',
|
||||
],
|
||||
methods: ['present', 'dismiss', 'onDidDismiss', 'onWillDismiss'],
|
||||
})
|
||||
@Component({
|
||||
selector: 'ion-modal',
|
||||
changeDetection: ChangeDetectionStrategy.OnPush,
|
||||
template: `<ng-container [ngTemplateOutlet]="template" *ngIf="isCmpOpen"></ng-container>`,
|
||||
inputs: [
|
||||
'animated',
|
||||
'backdropBreakpoint',
|
||||
'backdropDismiss',
|
||||
'breakpoints',
|
||||
'cssClass',
|
||||
'enterAnimation',
|
||||
'event',
|
||||
'handle',
|
||||
'initialBreakpoint',
|
||||
'isOpen',
|
||||
'keyboardClose',
|
||||
'leaveAnimation',
|
||||
'mode',
|
||||
'presentingElement',
|
||||
'showBackdrop',
|
||||
'swipeToClose',
|
||||
'translucent',
|
||||
'trigger',
|
||||
],
|
||||
})
|
||||
export class IonModal {
|
||||
@ContentChild(TemplateRef, { static: false }) template: TemplateRef<any>;
|
||||
|
||||
isCmpOpen: boolean = false;
|
||||
|
||||
protected el: HTMLElement;
|
||||
|
||||
constructor(c: ChangeDetectorRef, r: ElementRef, protected z: NgZone) {
|
||||
this.el = r.nativeElement;
|
||||
|
||||
this.el.addEventListener('willPresent', () => {
|
||||
this.isCmpOpen = true;
|
||||
c.detectChanges();
|
||||
});
|
||||
this.el.addEventListener('didDismiss', () => {
|
||||
this.isCmpOpen = false;
|
||||
c.detectChanges();
|
||||
});
|
||||
|
||||
proxyOutputs(this, this.el, [
|
||||
'ionModalDidPresent',
|
||||
'ionModalWillPresent',
|
||||
'ionModalWillDismiss',
|
||||
'ionModalDidDismiss',
|
||||
'didPresent',
|
||||
'willPresent',
|
||||
'willDismiss',
|
||||
'didDismiss',
|
||||
]);
|
||||
}
|
||||
}
|
||||
@@ -1,128 +0,0 @@
|
||||
/* eslint-disable */
|
||||
/* tslint:disable */
|
||||
import {
|
||||
ChangeDetectionStrategy,
|
||||
ChangeDetectorRef,
|
||||
Component,
|
||||
ContentChild,
|
||||
ElementRef,
|
||||
EventEmitter,
|
||||
NgZone,
|
||||
TemplateRef,
|
||||
} from '@angular/core';
|
||||
import { ProxyCmp, proxyOutputs } from '../angular-component-lib/utils';
|
||||
import { Components } from '@ionic/core';
|
||||
export declare interface IonPopover extends Components.IonPopover {
|
||||
/**
|
||||
* Emitted after the popover has presented.
|
||||
*/
|
||||
ionPopoverDidPresent: EventEmitter<CustomEvent>;
|
||||
/**
|
||||
* Emitted before the popover has presented.
|
||||
*/
|
||||
ionPopoverWillPresent: EventEmitter<CustomEvent>;
|
||||
/**
|
||||
* Emitted after the popover has dismissed.
|
||||
*/
|
||||
ionPopoverWillDismiss: EventEmitter<CustomEvent>;
|
||||
/**
|
||||
* Emitted after the popover has dismissed.
|
||||
*/
|
||||
ionPopoverDidDismiss: EventEmitter<CustomEvent>;
|
||||
/**
|
||||
* Emitted after the popover has presented. Shorthand for ionPopoverWillDismiss.
|
||||
*/
|
||||
didPresent: EventEmitter<CustomEvent>;
|
||||
/**
|
||||
* Emitted before the popover has presented. Shorthand for ionPopoverWillPresent.
|
||||
*/
|
||||
willPresent: EventEmitter<CustomEvent>;
|
||||
/**
|
||||
* Emitted after the popover has presented. Shorthand for ionPopoverWillDismiss.
|
||||
*/
|
||||
willDismiss: EventEmitter<CustomEvent>;
|
||||
/**
|
||||
* Emitted after the popover has dismissed. Shorthand for ionPopoverDidDismiss.
|
||||
*/
|
||||
didDismiss: EventEmitter<CustomEvent>;
|
||||
}
|
||||
@ProxyCmp({
|
||||
inputs: [
|
||||
'alignment',
|
||||
'animated',
|
||||
'arrow',
|
||||
'backdropDismiss',
|
||||
'cssClass',
|
||||
'dismissOnSelect',
|
||||
'enterAnimation',
|
||||
'event',
|
||||
'isOpen',
|
||||
'keyboardClose',
|
||||
'leaveAnimation',
|
||||
'mode',
|
||||
'showBackdrop',
|
||||
'translucent',
|
||||
'trigger',
|
||||
'triggerAction',
|
||||
'reference',
|
||||
'size',
|
||||
'side',
|
||||
],
|
||||
methods: ['present', 'dismiss', 'onDidDismiss', 'onWillDismiss'],
|
||||
})
|
||||
@Component({
|
||||
selector: 'ion-popover',
|
||||
changeDetection: ChangeDetectionStrategy.OnPush,
|
||||
template: `<ng-container [ngTemplateOutlet]="template" *ngIf="isCmpOpen"></ng-container>`,
|
||||
inputs: [
|
||||
'alignment',
|
||||
'animated',
|
||||
'arrow',
|
||||
'backdropDismiss',
|
||||
'cssClass',
|
||||
'dismissOnSelect',
|
||||
'enterAnimation',
|
||||
'event',
|
||||
'isOpen',
|
||||
'keyboardClose',
|
||||
'leaveAnimation',
|
||||
'mode',
|
||||
'showBackdrop',
|
||||
'translucent',
|
||||
'trigger',
|
||||
'triggerAction',
|
||||
'reference',
|
||||
'size',
|
||||
'side',
|
||||
],
|
||||
})
|
||||
export class IonPopover {
|
||||
@ContentChild(TemplateRef, { static: false }) template: TemplateRef<any>;
|
||||
|
||||
isCmpOpen: boolean = false;
|
||||
|
||||
protected el: HTMLElement;
|
||||
|
||||
constructor(c: ChangeDetectorRef, r: ElementRef, protected z: NgZone) {
|
||||
this.el = r.nativeElement;
|
||||
|
||||
this.el.addEventListener('willPresent', () => {
|
||||
this.isCmpOpen = true;
|
||||
c.detectChanges();
|
||||
});
|
||||
this.el.addEventListener('didDismiss', () => {
|
||||
this.isCmpOpen = false;
|
||||
c.detectChanges();
|
||||
});
|
||||
proxyOutputs(this, this.el, [
|
||||
'ionPopoverDidPresent',
|
||||
'ionPopoverWillPresent',
|
||||
'ionPopoverWillDismiss',
|
||||
'ionPopoverDidDismiss',
|
||||
'didPresent',
|
||||
'willPresent',
|
||||
'willDismiss',
|
||||
'didDismiss',
|
||||
]);
|
||||
}
|
||||
}
|
||||
@@ -1,16 +1,12 @@
|
||||
|
||||
import * as d from './proxies';
|
||||
import type * as d from './proxies';
|
||||
|
||||
export const DIRECTIVES = [
|
||||
d.IonAccordion,
|
||||
d.IonAccordionGroup,
|
||||
d.IonApp,
|
||||
d.IonAvatar,
|
||||
d.IonBackButton,
|
||||
d.IonBackdrop,
|
||||
d.IonBadge,
|
||||
d.IonBreadcrumb,
|
||||
d.IonBreadcrumbs,
|
||||
d.IonButton,
|
||||
d.IonButtons,
|
||||
d.IonCard,
|
||||
|
||||
46
angular/src/directives/proxies-utils.ts
Normal file
46
angular/src/directives/proxies-utils.ts
Normal file
@@ -0,0 +1,46 @@
|
||||
/* eslint-disable */
|
||||
/* tslint:disable */
|
||||
import { fromEvent } from 'rxjs';
|
||||
|
||||
export const proxyInputs = (Cmp: any, inputs: string[]) => {
|
||||
const Prototype = Cmp.prototype;
|
||||
inputs.forEach(item => {
|
||||
Object.defineProperty(Prototype, item, {
|
||||
get() {
|
||||
return this.el[item];
|
||||
},
|
||||
set(val: any) {
|
||||
this.z.runOutsideAngular(() => (this.el[item] = val));
|
||||
}
|
||||
});
|
||||
});
|
||||
};
|
||||
|
||||
export const proxyMethods = (Cmp: any, methods: string[]) => {
|
||||
const Prototype = Cmp.prototype;
|
||||
methods.forEach(methodName => {
|
||||
Prototype[methodName] = function () {
|
||||
const args = arguments;
|
||||
return this.z.runOutsideAngular(() =>
|
||||
this.el[methodName].apply(this.el, args)
|
||||
);
|
||||
};
|
||||
});
|
||||
};
|
||||
|
||||
export const proxyOutputs = (instance: any, el: any, events: string[]) => {
|
||||
events.forEach(eventName => instance[eventName] = fromEvent(el, eventName));
|
||||
}
|
||||
|
||||
export function ProxyCmp(opts: { inputs?: any; methods?: any }) {
|
||||
const decorator = function(cls: any){
|
||||
if (opts.inputs) {
|
||||
proxyInputs(cls, opts.inputs);
|
||||
}
|
||||
if (opts.methods) {
|
||||
proxyMethods(cls, opts.methods);
|
||||
}
|
||||
return cls;
|
||||
};
|
||||
return decorator;
|
||||
}
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,7 +1,7 @@
|
||||
import { ChangeDetectionStrategy, Component, ContentChild, ElementRef, EmbeddedViewRef, IterableDiffer, IterableDiffers, NgZone, SimpleChanges, TrackByFunction } from '@angular/core';
|
||||
import { Cell, CellType, FooterHeightFn, HeaderFn, HeaderHeightFn, ItemHeightFn } from '@ionic/core';
|
||||
|
||||
import { ProxyCmp } from '../angular-component-lib/utils';
|
||||
import { ProxyCmp } from '../proxies-utils';
|
||||
|
||||
import { VirtualFooter } from './virtual-footer';
|
||||
import { VirtualHeader } from './virtual-header';
|
||||
@@ -205,8 +205,8 @@ export class IonVirtualScroll {
|
||||
case 'item': return this.itmTmp.templateRef;
|
||||
case 'header': return this.hdrTmp.templateRef;
|
||||
case 'footer': return this.ftrTmp.templateRef;
|
||||
default: throw new Error('template for virtual item was not provided');
|
||||
}
|
||||
throw new Error('template for virtual item was not provided');
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1,21 +1,19 @@
|
||||
// DIRECTIVES
|
||||
export { BooleanValueAccessorDirective as BooleanValueAccessor } from './directives/control-value-accessors/boolean-value-accessor';
|
||||
export { NumericValueAccessorDirective as NumericValueAccessor } from './directives/control-value-accessors/numeric-value-accesssor';
|
||||
export { RadioValueAccessorDirective as RadioValueAccessor } from './directives/control-value-accessors/radio-value-accessor';
|
||||
export { SelectValueAccessorDirective as SelectValueAccessor } from './directives/control-value-accessors/select-value-accessor';
|
||||
export { TextValueAccessorDirective as TextValueAccessor } from './directives/control-value-accessors/text-value-accessor';
|
||||
export { BooleanValueAccessor } from './directives/control-value-accessors/boolean-value-accessor';
|
||||
export { NumericValueAccessor } from './directives/control-value-accessors/numeric-value-accesssor';
|
||||
export { RadioValueAccessor } from './directives/control-value-accessors/radio-value-accessor';
|
||||
export { SelectValueAccessor } from './directives/control-value-accessors/select-value-accessor';
|
||||
export { TextValueAccessor } from './directives/control-value-accessors/text-value-accessor';
|
||||
export { IonTabs } from './directives/navigation/ion-tabs';
|
||||
export { IonBackButtonDelegateDirective as IonBackButtonDelegate } from './directives/navigation/ion-back-button';
|
||||
export { IonBackButtonDelegate } from './directives/navigation/ion-back-button';
|
||||
export { NavDelegate } from './directives/navigation/nav-delegate';
|
||||
export { IonRouterOutlet } from './directives/navigation/ion-router-outlet';
|
||||
export { RouterLinkDelegateDirective as RouterLinkDelegate } from './directives/navigation/router-link-delegate';
|
||||
export { RouterLinkDelegate } from './directives/navigation/router-link-delegate';
|
||||
export { NavParams } from './directives/navigation/nav-params';
|
||||
export { IonVirtualScroll } from './directives/virtual-scroll/virtual-scroll';
|
||||
export { VirtualItem } from './directives/virtual-scroll/virtual-item';
|
||||
export { VirtualHeader } from './directives/virtual-scroll/virtual-header';
|
||||
export { VirtualFooter } from './directives/virtual-scroll/virtual-footer';
|
||||
export { IonModal } from './directives/overlays/modal';
|
||||
export { IonPopover } from './directives/overlays/popover';
|
||||
export * from './directives/proxies';
|
||||
|
||||
// PROVIDERS
|
||||
@@ -44,18 +42,11 @@ export * from './types/ionic-lifecycle-hooks';
|
||||
// PACKAGE MODULE
|
||||
export { IonicModule } from './ionic-module';
|
||||
|
||||
// UTILS
|
||||
export { IonicSafeString, getPlatforms, isPlatform, createAnimation, IonicSwiper, IonicSlides } from '@ionic/core';
|
||||
|
||||
// CORE TYPES
|
||||
export {
|
||||
// UTILS
|
||||
createAnimation,
|
||||
createGesture,
|
||||
iosTransitionAnimation,
|
||||
mdTransitionAnimation,
|
||||
IonicSwiper,
|
||||
IonicSlides,
|
||||
getPlatforms,
|
||||
isPlatform,
|
||||
getTimeGivenProgression,
|
||||
// TYPES
|
||||
Animation,
|
||||
AnimationBuilder,
|
||||
AnimationCallbackOptions,
|
||||
@@ -66,62 +57,33 @@ export {
|
||||
Gesture,
|
||||
GestureConfig,
|
||||
GestureDetail,
|
||||
mdTransitionAnimation,
|
||||
iosTransitionAnimation,
|
||||
NavComponentWithProps,
|
||||
|
||||
SpinnerTypes,
|
||||
AccordionGroupCustomEvent,
|
||||
AccordionGroupChangeEventDetail,
|
||||
BreadcrumbCustomEvent,
|
||||
BreadcrumbCollapsedClickEventDetail,
|
||||
|
||||
ActionSheetOptions,
|
||||
ActionSheetButton,
|
||||
|
||||
AlertOptions,
|
||||
AlertInput,
|
||||
AlertTextareaAttributes,
|
||||
AlertInputAttributes,
|
||||
AlertButton,
|
||||
BackButtonEvent,
|
||||
CheckboxCustomEvent,
|
||||
CheckboxChangeEventDetail,
|
||||
DatetimeCustomEvent,
|
||||
DatetimeChangeEventDetail,
|
||||
InfiniteScrollCustomEvent,
|
||||
InputCustomEvent,
|
||||
InputChangeEventDetail,
|
||||
ItemReorderEventDetail,
|
||||
ItemReorderCustomEvent,
|
||||
ItemSlidingCustomEvent,
|
||||
IonicSafeString,
|
||||
|
||||
LoadingOptions,
|
||||
MenuCustomEvent,
|
||||
|
||||
ModalOptions,
|
||||
NavCustomEvent,
|
||||
|
||||
PickerOptions,
|
||||
PickerButton,
|
||||
PickerColumn,
|
||||
PickerColumnOption,
|
||||
PlatformConfig,
|
||||
|
||||
PopoverOptions,
|
||||
RadioGroupCustomEvent,
|
||||
RadioGroupChangeEventDetail,
|
||||
RefresherCustomEvent,
|
||||
RefresherEventDetail,
|
||||
RouterEventDetail,
|
||||
RouterCustomEvent,
|
||||
ScrollBaseCustomEvent,
|
||||
ScrollBaseDetail,
|
||||
ScrollDetail,
|
||||
ScrollCustomEvent,
|
||||
SearchbarCustomEvent,
|
||||
SearchbarChangeEventDetail,
|
||||
SegmentChangeEventDetail,
|
||||
SegmentCustomEvent,
|
||||
SelectChangeEventDetail,
|
||||
SelectCustomEvent,
|
||||
TabsCustomEvent,
|
||||
TextareaChangeEventDetail,
|
||||
TextareaCustomEvent,
|
||||
|
||||
ToastOptions,
|
||||
ToastButton,
|
||||
ToggleChangeEventDetail,
|
||||
ToggleCustomEvent,
|
||||
ToastButton
|
||||
|
||||
} from '@ionic/core';
|
||||
|
||||
@@ -1,21 +0,0 @@
|
||||
// Re-exports from ionic/core
|
||||
|
||||
// UTILS
|
||||
export { IonicSafeString, getPlatforms, isPlatform, createAnimation } from '@ionic/core';
|
||||
|
||||
// CORE TYPES
|
||||
export {
|
||||
Animation,
|
||||
AnimationBuilder,
|
||||
AnimationCallbackOptions,
|
||||
AnimationDirection,
|
||||
AnimationFill,
|
||||
AnimationKeyFrames,
|
||||
AnimationLifecycle,
|
||||
Gesture,
|
||||
GestureConfig,
|
||||
GestureDetail,
|
||||
mdTransitionAnimation,
|
||||
iosTransitionAnimation,
|
||||
NavComponentWithProps,
|
||||
} from '@ionic/core';
|
||||
@@ -1,97 +1,19 @@
|
||||
import { CommonModule, DOCUMENT } from '@angular/common';
|
||||
import { ModuleWithProviders, APP_INITIALIZER, NgModule, NgZone } from '@angular/core';
|
||||
import { APP_INITIALIZER, ModuleWithProviders, NgModule, NgZone } from '@angular/core';
|
||||
import { IonicConfig } from '@ionic/core';
|
||||
|
||||
import { appInitialize } from './app-initialize';
|
||||
import { BooleanValueAccessorDirective } from './directives/control-value-accessors/boolean-value-accessor';
|
||||
import { NumericValueAccessorDirective } from './directives/control-value-accessors/numeric-value-accesssor';
|
||||
import { RadioValueAccessorDirective } from './directives/control-value-accessors/radio-value-accessor';
|
||||
import { SelectValueAccessorDirective } from './directives/control-value-accessors/select-value-accessor';
|
||||
import { TextValueAccessorDirective } from './directives/control-value-accessors/text-value-accessor';
|
||||
import { IonBackButtonDelegateDirective } from './directives/navigation/ion-back-button';
|
||||
import { BooleanValueAccessor } from './directives/control-value-accessors/boolean-value-accessor';
|
||||
import { NumericValueAccessor } from './directives/control-value-accessors/numeric-value-accesssor';
|
||||
import { RadioValueAccessor } from './directives/control-value-accessors/radio-value-accessor';
|
||||
import { SelectValueAccessor } from './directives/control-value-accessors/select-value-accessor';
|
||||
import { TextValueAccessor } from './directives/control-value-accessors/text-value-accessor';
|
||||
import { IonBackButtonDelegate } from './directives/navigation/ion-back-button';
|
||||
import { IonRouterOutlet } from './directives/navigation/ion-router-outlet';
|
||||
import { IonTabs } from './directives/navigation/ion-tabs';
|
||||
import { NavDelegate } from './directives/navigation/nav-delegate';
|
||||
import { RouterLinkDelegateDirective } from './directives/navigation/router-link-delegate';
|
||||
import { IonModal } from './directives/overlays/modal';
|
||||
import { IonPopover } from './directives/overlays/popover';
|
||||
import {
|
||||
IonAccordion,
|
||||
IonAccordionGroup,
|
||||
IonApp,
|
||||
IonAvatar,
|
||||
IonBackButton,
|
||||
IonBackdrop,
|
||||
IonBadge,
|
||||
IonBreadcrumb,
|
||||
IonBreadcrumbs,
|
||||
IonButton,
|
||||
IonButtons,
|
||||
IonCard,
|
||||
IonCardContent,
|
||||
IonCardHeader,
|
||||
IonCardSubtitle,
|
||||
IonCardTitle,
|
||||
IonCheckbox,
|
||||
IonChip,
|
||||
IonCol,
|
||||
IonContent,
|
||||
IonDatetime,
|
||||
IonFab,
|
||||
IonFabButton,
|
||||
IonFabList,
|
||||
IonFooter,
|
||||
IonGrid,
|
||||
IonHeader,
|
||||
IonIcon,
|
||||
IonImg,
|
||||
IonInfiniteScroll,
|
||||
IonInfiniteScrollContent,
|
||||
IonInput,
|
||||
IonItem,
|
||||
IonItemDivider,
|
||||
IonItemGroup,
|
||||
IonItemOption,
|
||||
IonItemOptions,
|
||||
IonItemSliding,
|
||||
IonLabel,
|
||||
IonList,
|
||||
IonListHeader,
|
||||
IonMenu,
|
||||
IonMenuButton,
|
||||
IonMenuToggle,
|
||||
IonNav,
|
||||
IonNavLink,
|
||||
IonNote,
|
||||
IonProgressBar,
|
||||
IonRadio,
|
||||
IonRadioGroup,
|
||||
IonRange,
|
||||
IonRefresher,
|
||||
IonRefresherContent,
|
||||
IonReorder,
|
||||
IonReorderGroup,
|
||||
IonRippleEffect,
|
||||
IonRow,
|
||||
IonSearchbar,
|
||||
IonSegment,
|
||||
IonSegmentButton,
|
||||
IonSelect,
|
||||
IonSelectOption,
|
||||
IonSkeletonText,
|
||||
IonSlide,
|
||||
IonSlides,
|
||||
IonSpinner,
|
||||
IonSplitPane,
|
||||
IonTabBar,
|
||||
IonTabButton,
|
||||
IonText,
|
||||
IonTextarea,
|
||||
IonThumbnail,
|
||||
IonTitle,
|
||||
IonToggle,
|
||||
IonToolbar,
|
||||
} from './directives/proxies';
|
||||
import { RouterLinkDelegate } from './directives/navigation/router-link-delegate';
|
||||
import { IonApp, IonAvatar, IonBackButton, IonBackdrop, IonBadge, IonButton, IonButtons, IonCard, IonCardContent, IonCardHeader, IonCardSubtitle, IonCardTitle, IonCheckbox, IonChip, IonCol, IonContent, IonDatetime, IonFab, IonFabButton, IonFabList, IonFooter, IonGrid, IonHeader, IonIcon, IonImg, IonInfiniteScroll, IonInfiniteScrollContent, IonInput, IonItem, IonItemDivider, IonItemGroup, IonItemOption, IonItemOptions, IonItemSliding, IonLabel, IonList, IonListHeader, IonMenu, IonMenuButton, IonMenuToggle, IonNav, IonNavLink, IonNote, IonProgressBar, IonRadio, IonRadioGroup, IonRange, IonRefresher, IonRefresherContent, IonReorder, IonReorderGroup, IonRippleEffect, IonRow, IonSearchbar, IonSegment, IonSegmentButton, IonSelect, IonSelectOption, IonSkeletonText, IonSlide, IonSlides, IonSpinner, IonSplitPane, IonTabBar, IonTabButton, IonText, IonTextarea, IonThumbnail, IonTitle, IonToggle, IonToolbar } from './directives/proxies';
|
||||
import { VirtualFooter } from './directives/virtual-scroll/virtual-footer';
|
||||
import { VirtualHeader } from './directives/virtual-scroll/virtual-header';
|
||||
import { VirtualItem } from './directives/virtual-scroll/virtual-item';
|
||||
@@ -103,15 +25,11 @@ import { PopoverController } from './providers/popover-controller';
|
||||
|
||||
const DECLARATIONS = [
|
||||
// proxies
|
||||
IonAccordion,
|
||||
IonAccordionGroup,
|
||||
IonApp,
|
||||
IonAvatar,
|
||||
IonBackButton,
|
||||
IonBackdrop,
|
||||
IonBadge,
|
||||
IonBreadcrumb,
|
||||
IonBreadcrumbs,
|
||||
IonButton,
|
||||
IonButtons,
|
||||
IonCard,
|
||||
@@ -147,11 +65,9 @@ const DECLARATIONS = [
|
||||
IonMenu,
|
||||
IonMenuButton,
|
||||
IonMenuToggle,
|
||||
IonModal,
|
||||
IonNav,
|
||||
IonNavLink,
|
||||
IonNote,
|
||||
IonPopover,
|
||||
IonProgressBar,
|
||||
IonRadio,
|
||||
IonRadioGroup,
|
||||
@@ -184,30 +100,30 @@ const DECLARATIONS = [
|
||||
IonTabs,
|
||||
|
||||
// ngModel accessors
|
||||
BooleanValueAccessorDirective,
|
||||
NumericValueAccessorDirective,
|
||||
RadioValueAccessorDirective,
|
||||
SelectValueAccessorDirective,
|
||||
TextValueAccessorDirective,
|
||||
BooleanValueAccessor,
|
||||
NumericValueAccessor,
|
||||
RadioValueAccessor,
|
||||
SelectValueAccessor,
|
||||
TextValueAccessor,
|
||||
|
||||
// navigation
|
||||
IonRouterOutlet,
|
||||
IonBackButtonDelegateDirective,
|
||||
IonBackButtonDelegate,
|
||||
NavDelegate,
|
||||
RouterLinkDelegateDirective,
|
||||
RouterLinkDelegate,
|
||||
|
||||
// virtual scroll
|
||||
VirtualFooter,
|
||||
VirtualHeader,
|
||||
VirtualItem,
|
||||
IonVirtualScroll,
|
||||
IonVirtualScroll
|
||||
];
|
||||
|
||||
@NgModule({
|
||||
declarations: DECLARATIONS,
|
||||
exports: DECLARATIONS,
|
||||
providers: [AngularDelegate, ModalController, PopoverController],
|
||||
imports: [CommonModule],
|
||||
imports: [CommonModule]
|
||||
})
|
||||
export class IonicModule {
|
||||
static forRoot(config?: IonicConfig): ModuleWithProviders<IonicModule> {
|
||||
@@ -216,15 +132,19 @@ export class IonicModule {
|
||||
providers: [
|
||||
{
|
||||
provide: ConfigToken,
|
||||
useValue: config,
|
||||
useValue: config
|
||||
},
|
||||
{
|
||||
provide: APP_INITIALIZER,
|
||||
useFactory: appInitialize,
|
||||
multi: true,
|
||||
deps: [ConfigToken, DOCUMENT, NgZone],
|
||||
},
|
||||
],
|
||||
deps: [
|
||||
ConfigToken,
|
||||
DOCUMENT,
|
||||
NgZone
|
||||
]
|
||||
}
|
||||
]
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,37 +1,27 @@
|
||||
import {
|
||||
ApplicationRef,
|
||||
ComponentFactoryResolver,
|
||||
NgZone,
|
||||
ViewContainerRef,
|
||||
Injectable,
|
||||
InjectionToken,
|
||||
Injector,
|
||||
} from '@angular/core';
|
||||
import {
|
||||
FrameworkDelegate,
|
||||
LIFECYCLE_DID_ENTER,
|
||||
LIFECYCLE_DID_LEAVE,
|
||||
LIFECYCLE_WILL_ENTER,
|
||||
LIFECYCLE_WILL_LEAVE,
|
||||
LIFECYCLE_WILL_UNLOAD,
|
||||
} from '@ionic/core';
|
||||
import { ApplicationRef, ComponentFactoryResolver, Injectable, InjectionToken, Injector, NgZone, ViewContainerRef } from '@angular/core';
|
||||
import { FrameworkDelegate, LIFECYCLE_DID_ENTER, LIFECYCLE_DID_LEAVE, LIFECYCLE_WILL_ENTER, LIFECYCLE_WILL_LEAVE, LIFECYCLE_WILL_UNLOAD } from '@ionic/core';
|
||||
|
||||
import { NavParams } from '../directives/navigation/nav-params';
|
||||
|
||||
@Injectable()
|
||||
export class AngularDelegate {
|
||||
constructor(private zone: NgZone, private appRef: ApplicationRef) {}
|
||||
|
||||
constructor(
|
||||
private zone: NgZone,
|
||||
private appRef: ApplicationRef
|
||||
) {}
|
||||
|
||||
create(
|
||||
resolver: ComponentFactoryResolver,
|
||||
injector: Injector,
|
||||
location?: ViewContainerRef
|
||||
): AngularFrameworkDelegate {
|
||||
location?: ViewContainerRef,
|
||||
) {
|
||||
return new AngularFrameworkDelegate(resolver, injector, location, this.appRef, this.zone);
|
||||
}
|
||||
}
|
||||
|
||||
export class AngularFrameworkDelegate implements FrameworkDelegate {
|
||||
|
||||
private elRefMap = new WeakMap<HTMLElement, any>();
|
||||
private elEventsMap = new WeakMap<HTMLElement, () => void>();
|
||||
|
||||
@@ -40,24 +30,16 @@ export class AngularFrameworkDelegate implements FrameworkDelegate {
|
||||
private injector: Injector,
|
||||
private location: ViewContainerRef | undefined,
|
||||
private appRef: ApplicationRef,
|
||||
private zone: NgZone
|
||||
private zone: NgZone,
|
||||
) {}
|
||||
|
||||
attachViewToDom(container: any, component: any, params?: any, cssClasses?: string[]): Promise<any> {
|
||||
return this.zone.run(() => {
|
||||
return new Promise((resolve) => {
|
||||
return new Promise(resolve => {
|
||||
const el = attachView(
|
||||
this.zone,
|
||||
this.resolver,
|
||||
this.injector,
|
||||
this.location,
|
||||
this.appRef,
|
||||
this.elRefMap,
|
||||
this.elEventsMap,
|
||||
container,
|
||||
component,
|
||||
params,
|
||||
cssClasses
|
||||
this.zone, this.resolver, this.injector, this.location, this.appRef,
|
||||
this.elRefMap, this.elEventsMap,
|
||||
container, component, params, cssClasses
|
||||
);
|
||||
resolve(el);
|
||||
});
|
||||
@@ -66,7 +48,7 @@ export class AngularFrameworkDelegate implements FrameworkDelegate {
|
||||
|
||||
removeViewFromDom(_container: any, component: any): Promise<void> {
|
||||
return this.zone.run(() => {
|
||||
return new Promise((resolve) => {
|
||||
return new Promise(resolve => {
|
||||
const componentRef = this.elRefMap.get(component);
|
||||
if (componentRef) {
|
||||
componentRef.destroy();
|
||||
@@ -91,17 +73,14 @@ export const attachView = (
|
||||
appRef: ApplicationRef,
|
||||
elRefMap: WeakMap<HTMLElement, any>,
|
||||
elEventsMap: WeakMap<HTMLElement, () => void>,
|
||||
container: any,
|
||||
component: any,
|
||||
params: any,
|
||||
cssClasses: string[] | undefined
|
||||
): any => {
|
||||
container: any, component: any, params: any, cssClasses: string[] | undefined
|
||||
) => {
|
||||
const factory = resolver.resolveComponentFactory(component);
|
||||
const childInjector = Injector.create({
|
||||
providers: getProviders(params),
|
||||
parent: injector,
|
||||
parent: injector
|
||||
});
|
||||
const componentRef = location
|
||||
const componentRef = (location)
|
||||
? location.createComponent(factory, location.length, childInjector)
|
||||
: factory.create(childInjector);
|
||||
|
||||
@@ -132,36 +111,35 @@ const LIFECYCLES = [
|
||||
LIFECYCLE_DID_ENTER,
|
||||
LIFECYCLE_WILL_LEAVE,
|
||||
LIFECYCLE_DID_LEAVE,
|
||||
LIFECYCLE_WILL_UNLOAD,
|
||||
LIFECYCLE_WILL_UNLOAD
|
||||
];
|
||||
|
||||
export const bindLifecycleEvents = (zone: NgZone, instance: any, element: HTMLElement): (() => void) => {
|
||||
export const bindLifecycleEvents = (zone: NgZone, instance: any, element: HTMLElement) => {
|
||||
return zone.run(() => {
|
||||
const unregisters = LIFECYCLES.filter((eventName) => typeof instance[eventName] === 'function').map((eventName) => {
|
||||
const handler = (ev: any) => instance[eventName](ev.detail);
|
||||
element.addEventListener(eventName, handler);
|
||||
return () => element.removeEventListener(eventName, handler);
|
||||
});
|
||||
return () => unregisters.forEach((fn) => fn());
|
||||
const unregisters = LIFECYCLES
|
||||
.filter(eventName => typeof instance[eventName] === 'function')
|
||||
.map(eventName => {
|
||||
const handler = (ev: any) => instance[eventName](ev.detail);
|
||||
element.addEventListener(eventName, handler);
|
||||
return () => element.removeEventListener(eventName, handler);
|
||||
});
|
||||
return () => unregisters.forEach(fn => fn());
|
||||
});
|
||||
};
|
||||
|
||||
const NavParamsToken = new InjectionToken<any>('NavParamsToken');
|
||||
|
||||
const getProviders = (params: { [key: string]: any }) => {
|
||||
const getProviders = (params: {[key: string]: any}) => {
|
||||
return [
|
||||
{
|
||||
provide: NavParamsToken,
|
||||
useValue: params,
|
||||
provide: NavParamsToken, useValue: params
|
||||
},
|
||||
{
|
||||
provide: NavParams,
|
||||
useFactory: provideNavParamsInjectable,
|
||||
deps: [NavParamsToken],
|
||||
},
|
||||
provide: NavParams, useFactory: provideNavParamsInjectable, deps: [NavParamsToken]
|
||||
}
|
||||
];
|
||||
};
|
||||
|
||||
const provideNavParamsInjectable = (params: { [key: string]: any }) => {
|
||||
const provideNavParamsInjectable = (params: {[key: string]: any}) => {
|
||||
return new NavParams(params);
|
||||
};
|
||||
|
||||
@@ -4,9 +4,10 @@ import { Config as CoreConfig, IonicConfig } from '@ionic/core';
|
||||
import { IonicWindow } from '../types/interfaces';
|
||||
|
||||
@Injectable({
|
||||
providedIn: 'root',
|
||||
providedIn: 'root'
|
||||
})
|
||||
export class Config {
|
||||
|
||||
get(key: keyof IonicConfig, fallback?: any): any {
|
||||
const c = getConfig();
|
||||
if (c) {
|
||||
@@ -30,6 +31,14 @@ export class Config {
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
set(key: keyof IonicConfig, value?: any) {
|
||||
console.warn(`[DEPRECATION][Config]: The Config.set() method is deprecated and will be removed in Ionic Framework 6.0. Please see https://ionicframework.com/docs/angular/config for alternatives.`);
|
||||
const c = getConfig();
|
||||
if (c) {
|
||||
c.set(key, value);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
export const ConfigToken = new InjectionToken<any>('USERCONFIG');
|
||||
@@ -37,7 +46,7 @@ export const ConfigToken = new InjectionToken<any>('USERCONFIG');
|
||||
const getConfig = (): CoreConfig | null => {
|
||||
if (typeof (window as any) !== 'undefined') {
|
||||
const Ionic = (window as any as IonicWindow).Ionic;
|
||||
if (Ionic?.config) {
|
||||
if (Ionic && Ionic.config) {
|
||||
return Ionic.config;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -4,11 +4,12 @@ import { Injectable } from '@angular/core';
|
||||
providedIn: 'root',
|
||||
})
|
||||
export class DomController {
|
||||
|
||||
/**
|
||||
* Schedules a task to run during the READ phase of the next frame.
|
||||
* This task should only read the DOM, but never modify it.
|
||||
*/
|
||||
read(cb: RafCallback): void {
|
||||
read(cb: RafCallback) {
|
||||
getQueue().read(cb);
|
||||
}
|
||||
|
||||
@@ -16,29 +17,29 @@ export class DomController {
|
||||
* Schedules a task to run during the WRITE phase of the next frame.
|
||||
* This task should write the DOM, but never READ it.
|
||||
*/
|
||||
write(cb: RafCallback): void {
|
||||
write(cb: RafCallback) {
|
||||
getQueue().write(cb);
|
||||
}
|
||||
}
|
||||
|
||||
const getQueue = () => {
|
||||
const win = typeof (window as any) !== 'undefined' ? window : (null as any);
|
||||
const win = typeof (window as any) !== 'undefined' ? window : null as any;
|
||||
|
||||
if (win != null) {
|
||||
const Ionic = win.Ionic;
|
||||
if (Ionic?.queue) {
|
||||
if (Ionic && Ionic.queue) {
|
||||
return Ionic.queue;
|
||||
}
|
||||
|
||||
return {
|
||||
read: (cb: any) => win.requestAnimationFrame(cb),
|
||||
write: (cb: any) => win.requestAnimationFrame(cb),
|
||||
write: (cb: any) => win.requestAnimationFrame(cb)
|
||||
};
|
||||
}
|
||||
|
||||
return {
|
||||
read: (cb: any) => cb(),
|
||||
write: (cb: any) => cb(),
|
||||
write: (cb: any) => cb()
|
||||
};
|
||||
};
|
||||
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { NgZone, Injectable } from '@angular/core';
|
||||
import { Injectable, NgZone } from '@angular/core';
|
||||
import { Gesture, GestureConfig, createGesture } from '@ionic/core';
|
||||
|
||||
@Injectable({
|
||||
@@ -11,10 +11,10 @@ export class GestureController {
|
||||
*/
|
||||
create(opts: GestureConfig, runInsideAngularZone = false): Gesture {
|
||||
if (runInsideAngularZone) {
|
||||
Object.getOwnPropertyNames(opts).forEach((key) => {
|
||||
Object.getOwnPropertyNames(opts).forEach(key => {
|
||||
if (typeof opts[key] === 'function') {
|
||||
const fn = opts[key];
|
||||
opts[key] = (...props: any[]) => this.zone.run(() => fn(...props));
|
||||
opts[key] = (...props) => this.zone.run(() => fn(...props));
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@@ -5,12 +5,13 @@ import { menuController } from '@ionic/core';
|
||||
providedIn: 'root',
|
||||
})
|
||||
export class MenuController {
|
||||
|
||||
/**
|
||||
* Programmatically open the Menu.
|
||||
* @param [menuId] Optionally get the menu by its id, or side.
|
||||
* @return returns a promise when the menu is fully opened
|
||||
*/
|
||||
open(menuId?: string): Promise<boolean> {
|
||||
open(menuId?: string) {
|
||||
return menuController.open(menuId);
|
||||
}
|
||||
|
||||
@@ -21,7 +22,7 @@ export class MenuController {
|
||||
* @param [menuId] Optionally get the menu by its id, or side.
|
||||
* @return returns a promise when the menu is fully closed
|
||||
*/
|
||||
close(menuId?: string): Promise<boolean> {
|
||||
close(menuId?: string) {
|
||||
return menuController.close(menuId);
|
||||
}
|
||||
|
||||
@@ -31,7 +32,7 @@ export class MenuController {
|
||||
* @param [menuId] Optionally get the menu by its id, or side.
|
||||
* @return returns a promise when the menu has been toggled
|
||||
*/
|
||||
toggle(menuId?: string): Promise<boolean> {
|
||||
toggle(menuId?: string) {
|
||||
return menuController.toggle(menuId);
|
||||
}
|
||||
|
||||
@@ -43,7 +44,7 @@ export class MenuController {
|
||||
* @param [menuId] Optionally get the menu by its id, or side.
|
||||
* @return Returns the instance of the menu, which is useful for chaining.
|
||||
*/
|
||||
enable(shouldEnable: boolean, menuId?: string): Promise<HTMLIonMenuElement | undefined> {
|
||||
enable(shouldEnable: boolean, menuId?: string) {
|
||||
return menuController.enable(shouldEnable, menuId);
|
||||
}
|
||||
|
||||
@@ -53,7 +54,7 @@ export class MenuController {
|
||||
* @param [menuId] Optionally get the menu by its id, or side.
|
||||
* @return Returns the instance of the menu, which is useful for chaining.
|
||||
*/
|
||||
swipeGesture(shouldEnable: boolean, menuId?: string): Promise<HTMLIonMenuElement | undefined> {
|
||||
swipeGesture(shouldEnable: boolean, menuId?: string) {
|
||||
return menuController.swipeGesture(shouldEnable, menuId);
|
||||
}
|
||||
|
||||
@@ -62,7 +63,7 @@ export class MenuController {
|
||||
* @return Returns true if the specified menu is currently open, otherwise false.
|
||||
* If the menuId is not specified, it returns true if ANY menu is currenly open.
|
||||
*/
|
||||
isOpen(menuId?: string): Promise<boolean> {
|
||||
isOpen(menuId?: string) {
|
||||
return menuController.isOpen(menuId);
|
||||
}
|
||||
|
||||
@@ -70,7 +71,7 @@ export class MenuController {
|
||||
* @param [menuId] Optionally get the menu by its id, or side.
|
||||
* @return Returns true if the menu is currently enabled, otherwise false.
|
||||
*/
|
||||
isEnabled(menuId?: string): Promise<boolean> {
|
||||
isEnabled(menuId?: string) {
|
||||
return menuController.isEnabled(menuId);
|
||||
}
|
||||
|
||||
@@ -83,21 +84,21 @@ export class MenuController {
|
||||
* @param [menuId] Optionally get the menu by its id, or side.
|
||||
* @return Returns the instance of the menu if found, otherwise `null`.
|
||||
*/
|
||||
get(menuId?: string): Promise<HTMLIonMenuElement | undefined> {
|
||||
get(menuId?: string) {
|
||||
return menuController.get(menuId);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Returns the instance of the menu already opened, otherwise `null`.
|
||||
*/
|
||||
getOpen(): Promise<HTMLIonMenuElement | undefined> {
|
||||
getOpen() {
|
||||
return menuController.getOpen();
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Returns an array of all menu instances.
|
||||
*/
|
||||
getMenus(): Promise<HTMLIonMenuElement[]> {
|
||||
getMenus() {
|
||||
return menuController.getMenus();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { ComponentFactoryResolver, Injector, Injectable } from '@angular/core';
|
||||
import { ComponentFactoryResolver, Injectable, Injector } from '@angular/core';
|
||||
import { ModalOptions, modalController } from '@ionic/core';
|
||||
|
||||
import { OverlayBaseController } from '../util/overlay';
|
||||
@@ -7,10 +7,11 @@ import { AngularDelegate } from './angular-delegate';
|
||||
|
||||
@Injectable()
|
||||
export class ModalController extends OverlayBaseController<ModalOptions, HTMLIonModalElement> {
|
||||
|
||||
constructor(
|
||||
private angularDelegate: AngularDelegate,
|
||||
private resolver: ComponentFactoryResolver,
|
||||
private injector: Injector
|
||||
private injector: Injector,
|
||||
) {
|
||||
super(modalController);
|
||||
}
|
||||
@@ -18,7 +19,7 @@ export class ModalController extends OverlayBaseController<ModalOptions, HTMLIon
|
||||
create(opts: ModalOptions): Promise<HTMLIonModalElement> {
|
||||
return super.create({
|
||||
...opts,
|
||||
delegate: this.angularDelegate.create(this.resolver, this.injector),
|
||||
delegate: this.angularDelegate.create(this.resolver, this.injector)
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import { Location } from '@angular/common';
|
||||
import { Injectable, Optional } from '@angular/core';
|
||||
import { NavigationExtras, Router, UrlSerializer, UrlTree, NavigationStart } from '@angular/router';
|
||||
import { NavigationExtras, NavigationStart, Router, UrlSerializer, UrlTree } from '@angular/router';
|
||||
import { AnimationBuilder, NavDirection, RouterDirection } from '@ionic/core';
|
||||
|
||||
import { IonRouterOutlet } from '../directives/navigation/ion-router-outlet';
|
||||
@@ -19,6 +19,7 @@ export interface NavigationOptions extends NavigationExtras, AnimationOptions {}
|
||||
providedIn: 'root',
|
||||
})
|
||||
export class NavController {
|
||||
|
||||
private topOutlet?: IonRouterOutlet;
|
||||
private direction: 'forward' | 'back' | 'root' | 'auto' = DEFAULT_DIRECTION;
|
||||
private animated?: NavDirection = DEFAULT_ANIMATED;
|
||||
@@ -31,13 +32,13 @@ export class NavController {
|
||||
platform: Platform,
|
||||
private location: Location,
|
||||
private serializer: UrlSerializer,
|
||||
@Optional() private router?: Router
|
||||
@Optional() private router?: Router,
|
||||
) {
|
||||
// Subscribe to router events to detect direction
|
||||
if (router) {
|
||||
router.events.subscribe((ev) => {
|
||||
router.events.subscribe(ev => {
|
||||
if (ev instanceof NavigationStart) {
|
||||
const id = ev.restoredState ? ev.restoredState.navigationId : ev.id;
|
||||
const id = (ev.restoredState) ? ev.restoredState.navigationId : ev.id;
|
||||
this.guessDirection = id < this.lastNavId ? 'back' : 'forward';
|
||||
this.guessAnimation = !ev.restoredState ? this.guessDirection : undefined;
|
||||
this.lastNavId = this.guessDirection === 'forward' ? ev.id : id;
|
||||
@@ -46,7 +47,7 @@ export class NavController {
|
||||
}
|
||||
|
||||
// Subscribe to backButton events
|
||||
platform.backButton.subscribeWithPriority(0, (processNextHandler) => {
|
||||
platform.backButton.subscribeWithPriority(0, processNextHandler => {
|
||||
this.pop();
|
||||
processNextHandler();
|
||||
});
|
||||
@@ -121,7 +122,7 @@ export class NavController {
|
||||
* It will use the standard `window.history.back()` under the hood, but featuring a `back` animation
|
||||
* by default.
|
||||
*/
|
||||
back(options: AnimationOptions = { animated: true, animationDirection: 'back' }): void {
|
||||
back(options: AnimationOptions = { animated: true, animationDirection: 'back' }) {
|
||||
this.setDirection('back', options.animated, options.animationDirection, options.animation);
|
||||
return this.location.back();
|
||||
}
|
||||
@@ -132,7 +133,7 @@ export class NavController {
|
||||
* It recursively finds the top active `ion-router-outlet` and calls `pop()`.
|
||||
* This is the recommended way to go back when you are using `ion-router-outlet`.
|
||||
*/
|
||||
async pop(): Promise<void> {
|
||||
async pop() {
|
||||
let outlet = this.topOutlet;
|
||||
|
||||
while (outlet) {
|
||||
@@ -151,12 +152,7 @@ export class NavController {
|
||||
*
|
||||
* It's recommended to use `navigateForward()`, `navigateBack()` and `navigateRoot()` instead of `setDirection()`.
|
||||
*/
|
||||
setDirection(
|
||||
direction: RouterDirection,
|
||||
animated?: boolean,
|
||||
animationDirection?: 'forward' | 'back',
|
||||
animationBuilder?: AnimationBuilder
|
||||
): void {
|
||||
setDirection(direction: RouterDirection, animated?: boolean, animationDirection?: 'forward' | 'back', animationBuilder?: AnimationBuilder) {
|
||||
this.direction = direction;
|
||||
this.animated = getAnimation(direction, animated, animationDirection);
|
||||
this.animationBuilder = animationBuilder;
|
||||
@@ -165,18 +161,14 @@ export class NavController {
|
||||
/**
|
||||
* @internal
|
||||
*/
|
||||
setTopOutlet(outlet: IonRouterOutlet): void {
|
||||
setTopOutlet(outlet: IonRouterOutlet) {
|
||||
this.topOutlet = outlet;
|
||||
}
|
||||
|
||||
/**
|
||||
* @internal
|
||||
*/
|
||||
consumeTransition(): {
|
||||
direction: RouterDirection;
|
||||
animation: NavDirection | undefined;
|
||||
animationBuilder: AnimationBuilder | undefined;
|
||||
} {
|
||||
consumeTransition() {
|
||||
let direction: RouterDirection = 'root';
|
||||
let animation: NavDirection | undefined;
|
||||
const animationBuilder = this.animationBuilder;
|
||||
@@ -195,15 +187,15 @@ export class NavController {
|
||||
return {
|
||||
direction,
|
||||
animation,
|
||||
animationBuilder,
|
||||
animationBuilder
|
||||
};
|
||||
}
|
||||
|
||||
private navigate(url: string | UrlTree | any[], options: NavigationOptions) {
|
||||
if (Array.isArray(url)) {
|
||||
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
|
||||
return this.router!.navigate(url, options);
|
||||
} else {
|
||||
|
||||
/**
|
||||
* navigateByUrl ignores any properties that
|
||||
* would change the url, so things like queryParams
|
||||
@@ -225,17 +217,12 @@ export class NavController {
|
||||
* that do not modify the url, such as `replaceUrl` which is why
|
||||
* `options` is passed in here.
|
||||
*/
|
||||
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
|
||||
return this.router!.navigateByUrl(urlTree, options);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const 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;
|
||||
}
|
||||
|
||||
@@ -1,19 +1,17 @@
|
||||
import { DOCUMENT } from '@angular/common';
|
||||
import { NgZone, Inject, Injectable } from '@angular/core';
|
||||
import { Inject, Injectable, NgZone } from '@angular/core';
|
||||
import { BackButtonEventDetail, KeyboardEventDetail, Platforms, getPlatforms, isPlatform } from '@ionic/core';
|
||||
import { Subscription, Subject } from 'rxjs';
|
||||
import { Subject, Subscription } from 'rxjs';
|
||||
|
||||
export interface BackButtonEmitter extends Subject<BackButtonEventDetail> {
|
||||
subscribeWithPriority(
|
||||
priority: number,
|
||||
callback: (processNextHandler: () => void) => Promise<any> | void
|
||||
): Subscription;
|
||||
subscribeWithPriority(priority: number, callback: (processNextHandler: () => void) => Promise<any> | void): Subscription;
|
||||
}
|
||||
|
||||
@Injectable({
|
||||
providedIn: 'root',
|
||||
})
|
||||
export class Platform {
|
||||
|
||||
private _readyPromise: Promise<string>;
|
||||
private win: any;
|
||||
|
||||
@@ -59,9 +57,9 @@ export class Platform {
|
||||
constructor(@Inject(DOCUMENT) private doc: any, zone: NgZone) {
|
||||
zone.run(() => {
|
||||
this.win = doc.defaultView;
|
||||
this.backButton.subscribeWithPriority = function (priority, callback) {
|
||||
return this.subscribe((ev) => {
|
||||
return ev.register(priority, (processNextHandler) => zone.run(() => callback(processNextHandler)));
|
||||
this.backButton.subscribeWithPriority = function(priority, callback) {
|
||||
return this.subscribe(ev => {
|
||||
return ev.register(priority, processNextHandler => zone.run(() => callback(processNextHandler)));
|
||||
});
|
||||
};
|
||||
|
||||
@@ -73,19 +71,12 @@ export class Platform {
|
||||
proxyEvent(this.keyboardDidHide, this.win, 'ionKeyboardDidHide');
|
||||
|
||||
let readyResolve: (value: string) => void;
|
||||
this._readyPromise = new Promise((res) => {
|
||||
readyResolve = res;
|
||||
});
|
||||
if (this.win?.['cordova']) {
|
||||
doc.addEventListener(
|
||||
'deviceready',
|
||||
() => {
|
||||
readyResolve('cordova');
|
||||
},
|
||||
{ once: true }
|
||||
);
|
||||
this._readyPromise = new Promise(res => { readyResolve = res; });
|
||||
if (this.win && this.win['cordova']) {
|
||||
doc.addEventListener('deviceready', () => {
|
||||
readyResolve('cordova');
|
||||
}, { once: true });
|
||||
} else {
|
||||
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
|
||||
readyResolve!('dom');
|
||||
}
|
||||
});
|
||||
@@ -222,25 +213,25 @@ export class Platform {
|
||||
* Returns `true` if the app is in portrait mode.
|
||||
*/
|
||||
isPortrait(): boolean {
|
||||
return this.win.matchMedia?.('(orientation: portrait)').matches;
|
||||
return this.win.matchMedia && this.win.matchMedia('(orientation: portrait)').matches;
|
||||
}
|
||||
|
||||
testUserAgent(expression: string): boolean {
|
||||
const nav = this.win.navigator;
|
||||
return !!(nav?.userAgent && nav.userAgent.indexOf(expression) >= 0);
|
||||
return !!(nav && nav.userAgent && nav.userAgent.indexOf(expression) >= 0);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the current url.
|
||||
*/
|
||||
url(): string {
|
||||
url() {
|
||||
return this.win.location.href;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the width of the platform's viewport using `window.innerWidth`.
|
||||
*/
|
||||
width(): number {
|
||||
width() {
|
||||
return this.win.innerWidth;
|
||||
}
|
||||
|
||||
@@ -253,17 +244,17 @@ export class Platform {
|
||||
}
|
||||
|
||||
const readQueryParam = (url: string, key: string) => {
|
||||
key = key.replace(/[[]/, '\\[').replace(/[\]]/, '\\]');
|
||||
key = key.replace(/[\[]/, '\\[').replace(/[\]]/, '\\]');
|
||||
const regex = new RegExp('[\\?&]' + key + '=([^&#]*)');
|
||||
const results = regex.exec(url);
|
||||
return results ? decodeURIComponent(results[1].replace(/\+/g, ' ')) : null;
|
||||
};
|
||||
|
||||
const proxyEvent = <T>(emitter: Subject<T>, el: EventTarget, eventName: string) => {
|
||||
if (el as any) {
|
||||
if ((el as any)) {
|
||||
el.addEventListener(eventName, (ev: Event | undefined | null) => {
|
||||
// ?? cordova might emit "null" events
|
||||
emitter.next(ev != null ? ((ev as any).detail as T) : undefined);
|
||||
emitter.next(ev != null ? (ev as any).detail as T : undefined);
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { ComponentFactoryResolver, Injector, Injectable } from '@angular/core';
|
||||
import { ComponentFactoryResolver, Injectable, Injector } from '@angular/core';
|
||||
import { PopoverOptions, popoverController } from '@ionic/core';
|
||||
|
||||
import { OverlayBaseController } from '../util/overlay';
|
||||
@@ -7,10 +7,11 @@ import { AngularDelegate } from './angular-delegate';
|
||||
|
||||
@Injectable()
|
||||
export class PopoverController extends OverlayBaseController<PopoverOptions, HTMLIonPopoverElement> {
|
||||
|
||||
constructor(
|
||||
private angularDelegate: AngularDelegate,
|
||||
private resolver: ComponentFactoryResolver,
|
||||
private injector: Injector
|
||||
private injector: Injector,
|
||||
) {
|
||||
super(popoverController);
|
||||
}
|
||||
@@ -18,7 +19,7 @@ export class PopoverController extends OverlayBaseController<PopoverOptions, HTM
|
||||
create(opts: PopoverOptions): Promise<HTMLIonPopoverElement> {
|
||||
return super.create({
|
||||
...opts,
|
||||
delegate: this.angularDelegate.create(this.resolver, this.injector),
|
||||
delegate: this.angularDelegate.create(this.resolver, this.injector)
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,21 +1,8 @@
|
||||
import { Path, join } from '@angular-devkit/core';
|
||||
import {
|
||||
Rule,
|
||||
SchematicContext,
|
||||
Tree,
|
||||
apply,
|
||||
chain,
|
||||
mergeWith,
|
||||
move,
|
||||
SchematicsException,
|
||||
template,
|
||||
url,
|
||||
} from '@angular-devkit/schematics';
|
||||
import { join, Path } from '@angular-devkit/core';
|
||||
import { apply, chain, mergeWith, move, Rule, SchematicContext, SchematicsException, template, Tree, url } from '@angular-devkit/schematics';
|
||||
import { NodePackageInstallTask } from '@angular-devkit/schematics/tasks';
|
||||
import { getWorkspace } from '@schematics/angular/utility/workspace';
|
||||
|
||||
import { addModuleImportToRootModule } from './../utils/ast';
|
||||
import { addArchitectBuilder, addAsset, addStyle, getDefaultAngularAppName } from './../utils/config';
|
||||
import { addArchitectBuilder, addAsset, addStyle, getDefaultAngularAppName, getWorkspace, WorkspaceProject, WorkspaceSchema } from './../utils/config';
|
||||
import { addPackageToPackageJson } from './../utils/package';
|
||||
import { Schema as IonAddOptions } from './schema';
|
||||
|
||||
@@ -28,14 +15,24 @@ function addIonicAngularToPackageJson(): Rule {
|
||||
|
||||
function addIonicAngularToolkitToPackageJson(): Rule {
|
||||
return (host: Tree) => {
|
||||
addPackageToPackageJson(host, 'devDependencies', '@ionic/angular-toolkit', 'latest');
|
||||
addPackageToPackageJson(
|
||||
host,
|
||||
'devDependencies',
|
||||
'@ionic/angular-toolkit',
|
||||
'latest'
|
||||
);
|
||||
return host;
|
||||
};
|
||||
}
|
||||
|
||||
function addIonicAngularModuleToAppModule(projectSourceRoot: Path): Rule {
|
||||
return (host: Tree) => {
|
||||
addModuleImportToRootModule(host, projectSourceRoot, 'IonicModule.forRoot()', '@ionic/angular');
|
||||
addModuleImportToRootModule(
|
||||
host,
|
||||
projectSourceRoot,
|
||||
'IonicModule.forRoot()',
|
||||
'@ionic/angular'
|
||||
);
|
||||
return host;
|
||||
};
|
||||
}
|
||||
@@ -53,13 +50,13 @@ function addIonicStyles(projectName: string, projectSourceRoot: Path): Rule {
|
||||
'node_modules/@ionic/angular/css/text-alignment.css',
|
||||
'node_modules/@ionic/angular/css/text-transformation.css',
|
||||
'node_modules/@ionic/angular/css/flex-utils.css',
|
||||
`${projectSourceRoot}/theme/variables.css`,
|
||||
];
|
||||
`${projectSourceRoot}/theme/variables.css`
|
||||
]
|
||||
|
||||
ionicStyles.forEach((entry) => {
|
||||
ionicStyles.forEach(entry => {
|
||||
addStyle(host, projectName, entry);
|
||||
});
|
||||
return host;
|
||||
return host;
|
||||
};
|
||||
}
|
||||
|
||||
@@ -68,7 +65,7 @@ function addIonicons(projectName: string): Rule {
|
||||
const ioniconsGlob = {
|
||||
glob: '**/*.svg',
|
||||
input: 'node_modules/ionicons/dist/ionicons/svg',
|
||||
output: './svg',
|
||||
output: './svg'
|
||||
};
|
||||
addAsset(host, projectName, 'build', ioniconsGlob);
|
||||
addAsset(host, projectName, 'test', ioniconsGlob);
|
||||
@@ -82,25 +79,25 @@ function addIonicBuilder(projectName: string): Rule {
|
||||
builder: '@ionic/angular-toolkit:cordova-serve',
|
||||
options: {
|
||||
cordovaBuildTarget: `${projectName}:ionic-cordova-build`,
|
||||
devServerTarget: `${projectName}:serve`,
|
||||
devServerTarget: `${projectName}:serve`
|
||||
},
|
||||
configurations: {
|
||||
production: {
|
||||
cordovaBuildTarget: `${projectName}:ionic-cordova-build:production`,
|
||||
devServerTarget: `${projectName}:serve:production`,
|
||||
},
|
||||
},
|
||||
devServerTarget: `${projectName}:serve:production`
|
||||
}
|
||||
}
|
||||
});
|
||||
addArchitectBuilder(host, projectName, 'ionic-cordova-build', {
|
||||
builder: '@ionic/angular-toolkit:cordova-build',
|
||||
options: {
|
||||
browserTarget: `${projectName}:build`,
|
||||
browserTarget: `${projectName}:build`
|
||||
},
|
||||
configurations: {
|
||||
production: {
|
||||
browserTarget: `${projectName}:build:production`,
|
||||
},
|
||||
},
|
||||
browserTarget: `${projectName}:build:production`
|
||||
}
|
||||
}
|
||||
});
|
||||
return host;
|
||||
};
|
||||
@@ -113,18 +110,22 @@ function installNodeDeps() {
|
||||
}
|
||||
|
||||
export default function ngAdd(options: IonAddOptions): Rule {
|
||||
return async (host: Tree) => {
|
||||
const workspace = await getWorkspace(host);
|
||||
return (host: Tree) => {
|
||||
const workspace: WorkspaceSchema = getWorkspace(host);
|
||||
if (!options.project) {
|
||||
options.project = getDefaultAngularAppName(workspace);
|
||||
}
|
||||
const project = workspace.projects.get(options.project);
|
||||
|
||||
if (!project || project.extensions.projectType !== 'application') {
|
||||
throw new SchematicsException(`Ionic Add requires a project type of "application".`);
|
||||
const project: WorkspaceProject = workspace.projects[options.project];
|
||||
if (project.projectType !== 'application') {
|
||||
throw new SchematicsException(
|
||||
`Ionic Add requires a project type of "application".`
|
||||
);
|
||||
}
|
||||
const sourcePath: Path = join(project.sourceRoot as Path);
|
||||
const rootTemplateSource = apply(url('./files/root'), [template({ ...options }), move(sourcePath)]);
|
||||
const rootTemplateSource = apply(url('./files/root'), [
|
||||
template({ ...options }),
|
||||
move(sourcePath)
|
||||
]);
|
||||
return chain([
|
||||
// @ionic/angular
|
||||
addIonicAngularToPackageJson(),
|
||||
@@ -135,7 +136,7 @@ export default function ngAdd(options: IonAddOptions): Rule {
|
||||
addIonicons(options.project),
|
||||
mergeWith(rootTemplateSource),
|
||||
// install freshly added dependencies
|
||||
installNodeDeps(),
|
||||
installNodeDeps()
|
||||
]);
|
||||
};
|
||||
}
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"$schema": "http://json-schema.org/schema",
|
||||
"$id": "ionicNgAdd",
|
||||
"id": "ionicNgAdd",
|
||||
"title": "Ionic Add options",
|
||||
"type": "object",
|
||||
"properties": {
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
import { SchematicsException, Tree } from '@angular-devkit/schematics';
|
||||
import { normalize } from '@angular-devkit/core';
|
||||
import { Tree, SchematicsException } from '@angular-devkit/schematics';
|
||||
import * as ts from 'typescript';
|
||||
|
||||
import { addImportToModule } from './devkit-utils/ast-utils';
|
||||
import { InsertChange } from './devkit-utils/change';
|
||||
|
||||
@@ -14,7 +13,12 @@ export function getSourceFile(host: Tree, path: string): ts.SourceFile {
|
||||
throw new SchematicsException(`Could not find file for path: ${path}`);
|
||||
}
|
||||
const content = buffer.toString();
|
||||
const source = ts.createSourceFile(path, content, ts.ScriptTarget.Latest, true);
|
||||
const source = ts.createSourceFile(
|
||||
path,
|
||||
content,
|
||||
ts.ScriptTarget.Latest,
|
||||
true
|
||||
);
|
||||
return source;
|
||||
}
|
||||
|
||||
@@ -26,8 +30,13 @@ export function addModuleImportToRootModule(
|
||||
projectSourceRoot: string,
|
||||
moduleName: string,
|
||||
importSrc: string
|
||||
): void {
|
||||
addModuleImportToModule(host, normalize(`${projectSourceRoot}/app/app.module.ts`), moduleName, importSrc);
|
||||
) {
|
||||
addModuleImportToModule(
|
||||
host,
|
||||
normalize(`${projectSourceRoot}/app/app.module.ts`),
|
||||
moduleName,
|
||||
importSrc
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -37,12 +46,17 @@ export function addModuleImportToRootModule(
|
||||
* @param moduleName name of module to import
|
||||
* @param src src location to import
|
||||
*/
|
||||
export function addModuleImportToModule(host: Tree, modulePath: string, moduleName: string, src: string): void {
|
||||
export function addModuleImportToModule(
|
||||
host: Tree,
|
||||
modulePath: string,
|
||||
moduleName: string,
|
||||
src: string
|
||||
) {
|
||||
const moduleSource = getSourceFile(host, modulePath);
|
||||
const changes = addImportToModule(moduleSource, modulePath, moduleName, src);
|
||||
const recorder = host.beginUpdate(modulePath);
|
||||
|
||||
changes.forEach((change) => {
|
||||
changes.forEach(change => {
|
||||
if (change instanceof InsertChange) {
|
||||
recorder.insertLeft(change.pos, change.toAdd);
|
||||
}
|
||||
|
||||
@@ -1,19 +1,18 @@
|
||||
import { WorkspaceDefinition } from '@angular-devkit/core/src/workspace';
|
||||
import { Tree, SchematicsException } from '@angular-devkit/schematics';
|
||||
import { parse } from 'jsonc-parser';
|
||||
import { SchematicsException, Tree } from '@angular-devkit/schematics';
|
||||
import { experimental, parseJson, JsonParseMode } from '@angular-devkit/core';
|
||||
|
||||
const CONFIG_PATH = 'angular.json';
|
||||
|
||||
export function readConfig(host: Tree): any {
|
||||
const sourceText = host.read(CONFIG_PATH)?.toString('utf-8');
|
||||
export function readConfig(host: Tree) {
|
||||
const sourceText = host.read(CONFIG_PATH)!.toString('utf-8');
|
||||
return JSON.parse(sourceText);
|
||||
}
|
||||
|
||||
export function writeConfig(host: Tree, config: JSON): void {
|
||||
export function writeConfig(host: Tree, config: JSON) {
|
||||
host.overwrite(CONFIG_PATH, JSON.stringify(config, null, 2));
|
||||
}
|
||||
|
||||
function isAngularBrowserProject(projectConfig: any): boolean {
|
||||
function isAngularBrowserProject(projectConfig: any) {
|
||||
if (projectConfig.projectType === 'application') {
|
||||
const buildConfig = projectConfig.architect.build;
|
||||
return buildConfig.builder === '@angular-devkit/build-angular:browser';
|
||||
@@ -37,7 +36,6 @@ export function getDefaultAngularAppName(config: any): string {
|
||||
}
|
||||
|
||||
export function getAngularAppConfig(config: any, projectName: string): any | never {
|
||||
// eslint-disable-next-line no-prototype-builtins
|
||||
if (!config.projects.hasOwnProperty(projectName)) {
|
||||
throw new SchematicsException(`Could not find project: ${projectName}`);
|
||||
}
|
||||
@@ -55,50 +53,40 @@ export function getAngularAppConfig(config: any, projectName: string): any | nev
|
||||
}
|
||||
}
|
||||
|
||||
export function addStyle(host: Tree, projectName: string, stylePath: string): void {
|
||||
export function addStyle(host: Tree, projectName: string, stylePath: string) {
|
||||
const config = readConfig(host);
|
||||
const appConfig = getAngularAppConfig(config, projectName);
|
||||
appConfig.architect.build.options.styles.push({
|
||||
input: stylePath,
|
||||
input: stylePath
|
||||
});
|
||||
writeConfig(host, config);
|
||||
}
|
||||
|
||||
export function addAsset(
|
||||
host: Tree,
|
||||
projectName: string,
|
||||
architect: string,
|
||||
asset: string | { glob: string; input: string; output: string }
|
||||
): void {
|
||||
export function addAsset(host: Tree, projectName: string, architect: string, asset: string | {glob: string; input: string; output: string}) {
|
||||
const config = readConfig(host);
|
||||
const appConfig = getAngularAppConfig(config, projectName);
|
||||
const target = appConfig.architect[architect];
|
||||
if (target) {
|
||||
target.options.assets.push(asset);
|
||||
writeConfig(host, config);
|
||||
}
|
||||
appConfig.architect[architect].options.assets.push(asset);
|
||||
writeConfig(host, config);
|
||||
}
|
||||
|
||||
export function addArchitectBuilder(
|
||||
host: Tree,
|
||||
projectName: string,
|
||||
builderName: string,
|
||||
builderOpts: any
|
||||
): void | never {
|
||||
export function addArchitectBuilder(host: Tree, projectName: string, builderName: string, builderOpts: any): void | never {
|
||||
const config = readConfig(host);
|
||||
const appConfig = getAngularAppConfig(config, projectName);
|
||||
appConfig.architect[builderName] = builderOpts;
|
||||
writeConfig(host, config);
|
||||
}
|
||||
|
||||
export type WorkspaceSchema = experimental.workspace.WorkspaceSchema;
|
||||
export type WorkspaceProject = experimental.workspace.WorkspaceProject;
|
||||
|
||||
export function getWorkspacePath(host: Tree): string {
|
||||
const possibleFiles = ['/angular.json', '/.angular.json'];
|
||||
const path = possibleFiles.filter((path) => host.exists(path))[0];
|
||||
const path = possibleFiles.filter(path => host.exists(path))[0];
|
||||
|
||||
return path;
|
||||
}
|
||||
|
||||
export function getWorkspace(host: Tree): WorkspaceDefinition {
|
||||
export function getWorkspace(host: Tree): WorkspaceSchema {
|
||||
const path = getWorkspacePath(host);
|
||||
const configBuffer = host.read(path);
|
||||
if (configBuffer === null) {
|
||||
@@ -106,5 +94,5 @@ export function getWorkspace(host: Tree): WorkspaceDefinition {
|
||||
}
|
||||
const content = configBuffer.toString();
|
||||
|
||||
return parse(content) as WorkspaceDefinition;
|
||||
return (parseJson(content, JsonParseMode.Loose) as {}) as WorkspaceSchema;
|
||||
}
|
||||
|
||||
@@ -6,9 +6,9 @@
|
||||
* found in the LICENSE file at https://angular.io/license
|
||||
*/
|
||||
import * as ts from 'typescript';
|
||||
|
||||
import { Change, InsertChange, NoopChange } from './change';
|
||||
|
||||
|
||||
/**
|
||||
* Add Import `import { symbolName } from fileName` if the import doesn't exit
|
||||
* already. Assumes fileToEdit can be resolved and accessed.
|
||||
@@ -18,32 +18,26 @@ import { Change, InsertChange, NoopChange } from './change';
|
||||
* @param isDefault (if true, import follows style for importing default exports)
|
||||
* @return Change
|
||||
*/
|
||||
export function insertImport(
|
||||
source: ts.SourceFile,
|
||||
fileToEdit: string,
|
||||
symbolName: string,
|
||||
fileName: string,
|
||||
isDefault = false
|
||||
): Change {
|
||||
export function insertImport(source: ts.SourceFile, fileToEdit: string, symbolName: string,
|
||||
fileName: string, isDefault = false): Change {
|
||||
const rootNode = source;
|
||||
const allImports = findNodes(rootNode, ts.SyntaxKind.ImportDeclaration);
|
||||
|
||||
// get nodes that map to import statements from the file fileName
|
||||
const relevantImports = allImports.filter((node) => {
|
||||
const relevantImports = allImports.filter(node => {
|
||||
// StringLiteral of the ImportDeclaration is the import file (fileName in this case).
|
||||
const importFiles = node
|
||||
.getChildren()
|
||||
.filter((child) => child.kind === ts.SyntaxKind.StringLiteral)
|
||||
.map((n) => (n as ts.StringLiteral).text);
|
||||
const importFiles = node.getChildren()
|
||||
.filter(child => child.kind === ts.SyntaxKind.StringLiteral)
|
||||
.map(n => (n as ts.StringLiteral).text);
|
||||
|
||||
return importFiles.filter((file) => file === fileName).length === 1;
|
||||
return importFiles.filter(file => file === fileName).length === 1;
|
||||
});
|
||||
|
||||
if (relevantImports.length > 0) {
|
||||
let importsAsterisk = false;
|
||||
// imports from import file
|
||||
const imports: ts.Node[] = [];
|
||||
relevantImports.forEach((n) => {
|
||||
relevantImports.forEach(n => {
|
||||
Array.prototype.push.apply(imports, findNodes(n, ts.SyntaxKind.Identifier));
|
||||
if (findNodes(n, ts.SyntaxKind.AsteriskToken).length > 0) {
|
||||
importsAsterisk = true;
|
||||
@@ -55,7 +49,7 @@ export function insertImport(
|
||||
return new NoopChange();
|
||||
}
|
||||
|
||||
const importTextNodes = imports.filter((n) => (n as ts.Identifier).text === symbolName);
|
||||
const importTextNodes = imports.filter(n => (n as ts.Identifier).text === symbolName);
|
||||
|
||||
// insert import if it's not there
|
||||
if (importTextNodes.length === 0) {
|
||||
@@ -70,9 +64,8 @@ export function insertImport(
|
||||
}
|
||||
|
||||
// no such import declaration exists
|
||||
const useStrict = findNodes(rootNode, ts.SyntaxKind.StringLiteral).filter(
|
||||
(n: ts.StringLiteral) => n.text === 'use strict'
|
||||
);
|
||||
const useStrict = findNodes(rootNode, ts.SyntaxKind.StringLiteral)
|
||||
.filter((n: ts.StringLiteral) => n.text === 'use strict');
|
||||
let fallbackPos = 0;
|
||||
if (useStrict.length > 0) {
|
||||
fallbackPos = useStrict[0].end;
|
||||
@@ -82,12 +75,19 @@ export function insertImport(
|
||||
// if there are no imports or 'use strict' statement, insert import at beginning of file
|
||||
const insertAtBeginning = allImports.length === 0 && useStrict.length === 0;
|
||||
const separator = insertAtBeginning ? '' : ';\n';
|
||||
const toInsert =
|
||||
`${separator}import ${open}${symbolName}${close}` + ` from '${fileName}'${insertAtBeginning ? ';\n' : ''}`;
|
||||
const toInsert = `${separator}import ${open}${symbolName}${close}` +
|
||||
` from '${fileName}'${insertAtBeginning ? ';\n' : ''}`;
|
||||
|
||||
return insertAfterLastOccurrence(allImports, toInsert, fileToEdit, fallbackPos, ts.SyntaxKind.StringLiteral);
|
||||
return insertAfterLastOccurrence(
|
||||
allImports,
|
||||
toInsert,
|
||||
fileToEdit,
|
||||
fallbackPos,
|
||||
ts.SyntaxKind.StringLiteral,
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Find all nodes from the AST in the subtree of node of SyntaxKind kind.
|
||||
* @param node
|
||||
@@ -107,7 +107,7 @@ export function findNodes(node: ts.Node, kind: ts.SyntaxKind, max = Infinity): t
|
||||
}
|
||||
if (max > 0) {
|
||||
for (const child of node.getChildren()) {
|
||||
findNodes(child, kind, max).forEach((node) => {
|
||||
findNodes(child, kind, max).forEach(node => {
|
||||
if (max > 0) {
|
||||
arr.push(node);
|
||||
}
|
||||
@@ -123,6 +123,7 @@ export function findNodes(node: ts.Node, kind: ts.SyntaxKind, max = Infinity): t
|
||||
return arr;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Get all the nodes from a source.
|
||||
* @param sourceFile The source file object.
|
||||
@@ -153,13 +154,14 @@ export function findNode(node: ts.Node, kind: ts.SyntaxKind, text: string): ts.N
|
||||
}
|
||||
|
||||
let foundNode: ts.Node | null = null;
|
||||
ts.forEachChild(node, (childNode) => {
|
||||
ts.forEachChild(node, childNode => {
|
||||
foundNode = foundNode || findNode(childNode, kind, text);
|
||||
});
|
||||
|
||||
return foundNode;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Helper for sorting nodes.
|
||||
* @return function to sort nodes in increasing order of position in sourceFile
|
||||
@@ -168,6 +170,7 @@ function nodesByPosition(first: ts.Node, second: ts.Node): number {
|
||||
return first.getStart() - second.getStart();
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Insert `toInsert` after the last occurence of `ts.SyntaxKind[nodes[i].kind]`
|
||||
* or after the last of occurence of `syntaxKind` if the last occurence is a sub child
|
||||
@@ -181,13 +184,11 @@ function nodesByPosition(first: ts.Node, second: ts.Node): number {
|
||||
* @return Change instance
|
||||
* @throw Error if toInsert is first occurence but fall back is not set
|
||||
*/
|
||||
export function insertAfterLastOccurrence(
|
||||
nodes: ts.Node[],
|
||||
toInsert: string,
|
||||
file: string,
|
||||
fallbackPos: number,
|
||||
syntaxKind?: ts.SyntaxKind
|
||||
): Change {
|
||||
export function insertAfterLastOccurrence(nodes: ts.Node[],
|
||||
toInsert: string,
|
||||
file: string,
|
||||
fallbackPos: number,
|
||||
syntaxKind?: ts.SyntaxKind): Change {
|
||||
// sort() has a side effect, so make a copy so that we won't overwrite the parent's object.
|
||||
let lastItem = [...nodes].sort(nodesByPosition).pop();
|
||||
if (!lastItem) {
|
||||
@@ -204,6 +205,7 @@ export function insertAfterLastOccurrence(
|
||||
return new InsertChange(file, lastItemPosition, toInsert);
|
||||
}
|
||||
|
||||
|
||||
export function getContentOfKeyLiteral(_source: ts.SourceFile, node: ts.Node): string | null {
|
||||
if (node.kind == ts.SyntaxKind.Identifier) {
|
||||
return (node as ts.Identifier).text;
|
||||
@@ -214,11 +216,9 @@ export function getContentOfKeyLiteral(_source: ts.SourceFile, node: ts.Node): s
|
||||
}
|
||||
}
|
||||
|
||||
function _angularImportsFromNode(
|
||||
node: ts.ImportDeclaration,
|
||||
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
||||
_sourceFile: ts.SourceFile
|
||||
): { [name: string]: string } {
|
||||
|
||||
function _angularImportsFromNode(node: ts.ImportDeclaration,
|
||||
_sourceFile: ts.SourceFile): {[name: string]: string} {
|
||||
const ms = node.moduleSpecifier;
|
||||
let modulePath: string;
|
||||
switch (ms.kind) {
|
||||
@@ -249,8 +249,8 @@ function _angularImportsFromNode(
|
||||
const namedImports = nb as ts.NamedImports;
|
||||
|
||||
return namedImports.elements
|
||||
.map((is: ts.ImportSpecifier) => (is.propertyName ? is.propertyName.text : is.name.text))
|
||||
.reduce((acc: { [name: string]: string }, curr: string) => {
|
||||
.map((is: ts.ImportSpecifier) => is.propertyName ? is.propertyName.text : is.name.text)
|
||||
.reduce((acc: {[name: string]: string}, curr: string) => {
|
||||
acc[curr] = modulePath;
|
||||
|
||||
return acc;
|
||||
@@ -265,10 +265,13 @@ function _angularImportsFromNode(
|
||||
}
|
||||
}
|
||||
|
||||
export function getDecoratorMetadata(source: ts.SourceFile, identifier: string, module: string): ts.Node[] {
|
||||
const angularImports: { [name: string]: string } = findNodes(source, ts.SyntaxKind.ImportDeclaration)
|
||||
|
||||
export function getDecoratorMetadata(source: ts.SourceFile, identifier: string,
|
||||
module: string): ts.Node[] {
|
||||
const angularImports: {[name: string]: string}
|
||||
= findNodes(source, ts.SyntaxKind.ImportDeclaration)
|
||||
.map((node: ts.ImportDeclaration) => _angularImportsFromNode(node, source))
|
||||
.reduce((acc: { [name: string]: string }, current: { [name: string]: string }) => {
|
||||
.reduce((acc: {[name: string]: string}, current: {[name: string]: string}) => {
|
||||
for (const key of Object.keys(current)) {
|
||||
acc[key] = current[key];
|
||||
}
|
||||
@@ -277,17 +280,17 @@ export function getDecoratorMetadata(source: ts.SourceFile, identifier: string,
|
||||
}, {});
|
||||
|
||||
return getSourceNodes(source)
|
||||
.filter((node) => {
|
||||
return (
|
||||
node.kind == ts.SyntaxKind.Decorator && (node as ts.Decorator).expression.kind == ts.SyntaxKind.CallExpression
|
||||
);
|
||||
.filter(node => {
|
||||
return node.kind == ts.SyntaxKind.Decorator
|
||||
&& (node as ts.Decorator).expression.kind == ts.SyntaxKind.CallExpression;
|
||||
})
|
||||
.map((node) => (node as ts.Decorator).expression as ts.CallExpression)
|
||||
.filter((expr) => {
|
||||
.map(node => (node as ts.Decorator).expression as ts.CallExpression)
|
||||
.filter(expr => {
|
||||
if (expr.expression.kind == ts.SyntaxKind.Identifier) {
|
||||
const id = expr.expression as ts.Identifier;
|
||||
|
||||
return id.getFullText(source) == identifier && angularImports[id.getFullText(source)] === module;
|
||||
return id.getFullText(source) == identifier
|
||||
&& angularImports[id.getFullText(source)] === module;
|
||||
} else if (expr.expression.kind == ts.SyntaxKind.PropertyAccessExpression) {
|
||||
// This covers foo.NgModule when importing * as foo.
|
||||
const paExpr = expr.expression as ts.PropertyAccessExpression;
|
||||
@@ -299,16 +302,17 @@ export function getDecoratorMetadata(source: ts.SourceFile, identifier: string,
|
||||
const id = paExpr.name.text;
|
||||
const moduleId = (paExpr.expression as ts.Identifier).getText(source);
|
||||
|
||||
return id === identifier && angularImports[moduleId + '.'] === module;
|
||||
return id === identifier && (angularImports[moduleId + '.'] === module);
|
||||
}
|
||||
|
||||
return false;
|
||||
})
|
||||
.filter((expr) => expr.arguments[0] && expr.arguments[0].kind == ts.SyntaxKind.ObjectLiteralExpression)
|
||||
.map((expr) => expr.arguments[0] as ts.ObjectLiteralExpression);
|
||||
.filter(expr => expr.arguments[0]
|
||||
&& expr.arguments[0].kind == ts.SyntaxKind.ObjectLiteralExpression)
|
||||
.map(expr => expr.arguments[0] as ts.ObjectLiteralExpression);
|
||||
}
|
||||
|
||||
function findClassDeclarationParent(node: ts.Node): ts.ClassDeclaration | undefined {
|
||||
function findClassDeclarationParent(node: ts.Node): ts.ClassDeclaration|undefined {
|
||||
if (ts.isClassDeclaration(node)) {
|
||||
return node;
|
||||
}
|
||||
@@ -322,7 +326,7 @@ function findClassDeclarationParent(node: ts.Node): ts.ClassDeclaration | undefi
|
||||
* @param source source file containing one or more @NgModule
|
||||
* @returns the name of the first @NgModule, or `undefined` if none is found
|
||||
*/
|
||||
export function getFirstNgModuleName(source: ts.SourceFile): string | undefined {
|
||||
export function getFirstNgModuleName(source: ts.SourceFile): string|undefined {
|
||||
// First, find the @NgModule decorators.
|
||||
const ngModulesMetadata = getDecoratorMetadata(source, 'NgModule', '@angular/core');
|
||||
if (ngModulesMetadata.length === 0) {
|
||||
@@ -345,10 +349,10 @@ export function addSymbolToNgModuleMetadata(
|
||||
ngModulePath: string,
|
||||
metadataField: string,
|
||||
symbolName: string,
|
||||
importPath: string | null = null
|
||||
importPath: string | null = null,
|
||||
): Change[] {
|
||||
const nodes = getDecoratorMetadata(source, 'NgModule', '@angular/core');
|
||||
let node: any = nodes[0]; // tslint:disable-line:no-any
|
||||
let node: any = nodes[0]; // tslint:disable-line:no-any
|
||||
|
||||
// Find the decorator declaration.
|
||||
if (!node) {
|
||||
@@ -356,8 +360,9 @@ export function addSymbolToNgModuleMetadata(
|
||||
}
|
||||
|
||||
// Get all the children property assignment of object literals.
|
||||
const matchingProperties: ts.ObjectLiteralElement[] = (node as ts.ObjectLiteralExpression).properties
|
||||
.filter((prop) => prop.kind == ts.SyntaxKind.PropertyAssignment)
|
||||
const matchingProperties: ts.ObjectLiteralElement[] =
|
||||
(node as ts.ObjectLiteralExpression).properties
|
||||
.filter(prop => prop.kind == ts.SyntaxKind.PropertyAssignment)
|
||||
// Filter out every fields that's not "metadataField". Also handles string literals
|
||||
// (but not expressions).
|
||||
.filter((prop: ts.PropertyAssignment) => {
|
||||
@@ -427,9 +432,8 @@ export function addSymbolToNgModuleMetadata(
|
||||
}
|
||||
|
||||
if (Array.isArray(node)) {
|
||||
// eslint-disable-next-line @typescript-eslint/ban-types
|
||||
const nodeArray = node as {} as ts.Node[];
|
||||
const symbolsArray = nodeArray.map((node) => node.getText());
|
||||
const nodeArray = node as {} as Array<ts.Node>;
|
||||
const symbolsArray = nodeArray.map(node => node.getText());
|
||||
if (symbolsArray.includes(symbolName)) {
|
||||
return [];
|
||||
}
|
||||
@@ -484,93 +488,81 @@ export function addSymbolToNgModuleMetadata(
|
||||
* Custom function to insert a declaration (component, pipe, directive)
|
||||
* into NgModule declarations. It also imports the component.
|
||||
*/
|
||||
export function addDeclarationToModule(
|
||||
source: ts.SourceFile,
|
||||
modulePath: string,
|
||||
classifiedName: string,
|
||||
importPath: string
|
||||
): Change[] {
|
||||
return addSymbolToNgModuleMetadata(source, modulePath, 'declarations', classifiedName, importPath);
|
||||
export function addDeclarationToModule(source: ts.SourceFile,
|
||||
modulePath: string, classifiedName: string,
|
||||
importPath: string): Change[] {
|
||||
return addSymbolToNgModuleMetadata(
|
||||
source, modulePath, 'declarations', classifiedName, importPath);
|
||||
}
|
||||
|
||||
/**
|
||||
* Custom function to insert an NgModule into NgModule imports. It also imports the module.
|
||||
*/
|
||||
export function addImportToModule(
|
||||
source: ts.SourceFile,
|
||||
modulePath: string,
|
||||
classifiedName: string,
|
||||
importPath: string
|
||||
): Change[] {
|
||||
export function addImportToModule(source: ts.SourceFile,
|
||||
modulePath: string, classifiedName: string,
|
||||
importPath: string): Change[] {
|
||||
|
||||
return addSymbolToNgModuleMetadata(source, modulePath, 'imports', classifiedName, importPath);
|
||||
}
|
||||
|
||||
/**
|
||||
* Custom function to insert a provider into NgModule. It also imports it.
|
||||
*/
|
||||
export function addProviderToModule(
|
||||
source: ts.SourceFile,
|
||||
modulePath: string,
|
||||
classifiedName: string,
|
||||
importPath: string
|
||||
): Change[] {
|
||||
export function addProviderToModule(source: ts.SourceFile,
|
||||
modulePath: string, classifiedName: string,
|
||||
importPath: string): Change[] {
|
||||
return addSymbolToNgModuleMetadata(source, modulePath, 'providers', classifiedName, importPath);
|
||||
}
|
||||
|
||||
/**
|
||||
* Custom function to insert an export into NgModule. It also imports it.
|
||||
*/
|
||||
export function addExportToModule(
|
||||
source: ts.SourceFile,
|
||||
modulePath: string,
|
||||
classifiedName: string,
|
||||
importPath: string
|
||||
): Change[] {
|
||||
export function addExportToModule(source: ts.SourceFile,
|
||||
modulePath: string, classifiedName: string,
|
||||
importPath: string): Change[] {
|
||||
return addSymbolToNgModuleMetadata(source, modulePath, 'exports', classifiedName, importPath);
|
||||
}
|
||||
|
||||
/**
|
||||
* Custom function to insert an export into NgModule. It also imports it.
|
||||
*/
|
||||
export function addBootstrapToModule(
|
||||
source: ts.SourceFile,
|
||||
modulePath: string,
|
||||
classifiedName: string,
|
||||
importPath: string
|
||||
): Change[] {
|
||||
export function addBootstrapToModule(source: ts.SourceFile,
|
||||
modulePath: string, classifiedName: string,
|
||||
importPath: string): Change[] {
|
||||
return addSymbolToNgModuleMetadata(source, modulePath, 'bootstrap', classifiedName, importPath);
|
||||
}
|
||||
|
||||
/**
|
||||
* Custom function to insert an entryComponent into NgModule. It also imports it.
|
||||
*/
|
||||
export function addEntryComponentToModule(
|
||||
source: ts.SourceFile,
|
||||
modulePath: string,
|
||||
classifiedName: string,
|
||||
importPath: string
|
||||
): Change[] {
|
||||
return addSymbolToNgModuleMetadata(source, modulePath, 'entryComponents', classifiedName, importPath);
|
||||
export function addEntryComponentToModule(source: ts.SourceFile,
|
||||
modulePath: string, classifiedName: string,
|
||||
importPath: string): Change[] {
|
||||
return addSymbolToNgModuleMetadata(
|
||||
source, modulePath,
|
||||
'entryComponents', classifiedName, importPath,
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Determine if an import already exists.
|
||||
*/
|
||||
export function isImported(source: ts.SourceFile, classifiedName: string, importPath: string): boolean {
|
||||
export function isImported(source: ts.SourceFile,
|
||||
classifiedName: string,
|
||||
importPath: string): boolean {
|
||||
const allNodes = getSourceNodes(source);
|
||||
const matchingNodes = allNodes
|
||||
.filter((node) => node.kind === ts.SyntaxKind.ImportDeclaration)
|
||||
.filter(node => node.kind === ts.SyntaxKind.ImportDeclaration)
|
||||
.filter((imp: ts.ImportDeclaration) => imp.moduleSpecifier.kind === ts.SyntaxKind.StringLiteral)
|
||||
.filter((imp: ts.ImportDeclaration) => {
|
||||
return (imp.moduleSpecifier as ts.StringLiteral).text === importPath;
|
||||
return (<ts.StringLiteral> imp.moduleSpecifier).text === importPath;
|
||||
})
|
||||
.filter((imp: ts.ImportDeclaration) => {
|
||||
if (!imp.importClause) {
|
||||
return false;
|
||||
}
|
||||
const nodes = findNodes(imp.importClause, ts.SyntaxKind.ImportSpecifier).filter(
|
||||
(n) => n.getText() === classifiedName
|
||||
);
|
||||
const nodes = findNodes(imp.importClause, ts.SyntaxKind.ImportSpecifier)
|
||||
.filter(n => n.getText() === classifiedName);
|
||||
|
||||
return nodes.length > 0;
|
||||
});
|
||||
|
||||
@@ -10,6 +10,7 @@ export interface Host {
|
||||
read(path: string): Promise<string>;
|
||||
}
|
||||
|
||||
|
||||
export interface Change {
|
||||
apply(host: Host): Promise<void>;
|
||||
|
||||
@@ -25,6 +26,7 @@ export interface Change {
|
||||
readonly description: string;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* An operation that does nothing.
|
||||
*/
|
||||
@@ -32,15 +34,15 @@ export class NoopChange implements Change {
|
||||
description = 'No operation.';
|
||||
order = Infinity;
|
||||
path = null;
|
||||
apply(): Promise<void> {
|
||||
return Promise.resolve();
|
||||
}
|
||||
apply() { return Promise.resolve(); }
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Will add text to the source code.
|
||||
*/
|
||||
export class InsertChange implements Change {
|
||||
|
||||
order: number;
|
||||
description: string;
|
||||
|
||||
@@ -55,8 +57,8 @@ export class InsertChange implements Change {
|
||||
/**
|
||||
* This method does not insert spaces if there is none in the original string.
|
||||
*/
|
||||
apply(host: Host): Promise<void> {
|
||||
return host.read(this.path).then((content) => {
|
||||
apply(host: Host) {
|
||||
return host.read(this.path).then(content => {
|
||||
const prefix = content.substring(0, this.pos);
|
||||
const suffix = content.substring(this.pos);
|
||||
|
||||
@@ -69,6 +71,7 @@ export class InsertChange implements Change {
|
||||
* Will remove text from the source code.
|
||||
*/
|
||||
export class RemoveChange implements Change {
|
||||
|
||||
order: number;
|
||||
description: string;
|
||||
|
||||
@@ -81,7 +84,7 @@ export class RemoveChange implements Change {
|
||||
}
|
||||
|
||||
apply(host: Host): Promise<void> {
|
||||
return host.read(this.path).then((content) => {
|
||||
return host.read(this.path).then(content => {
|
||||
const prefix = content.substring(0, this.pos);
|
||||
const suffix = content.substring(this.pos + this.toRemove.length);
|
||||
|
||||
@@ -98,7 +101,8 @@ export class ReplaceChange implements Change {
|
||||
order: number;
|
||||
description: string;
|
||||
|
||||
constructor(public path: string, private pos: number, private oldText: string, private newText: string) {
|
||||
constructor(public path: string, private pos: number, private oldText: string,
|
||||
private newText: string) {
|
||||
if (pos < 0) {
|
||||
throw new Error('Negative positions are invalid');
|
||||
}
|
||||
@@ -107,7 +111,7 @@ export class ReplaceChange implements Change {
|
||||
}
|
||||
|
||||
apply(host: Host): Promise<void> {
|
||||
return host.read(this.path).then((content) => {
|
||||
return host.read(this.path).then(content => {
|
||||
const prefix = content.substring(0, this.pos);
|
||||
const suffix = content.substring(this.pos + this.oldText.length);
|
||||
const text = content.substring(this.pos, this.pos + this.oldText.length);
|
||||
|
||||
@@ -3,3 +3,5 @@
|
||||
These are utility files copied over from `@angular-devkit`.
|
||||
They are not exported so they need to be manually copied over.
|
||||
Please do not edit directly.
|
||||
|
||||
|
||||
|
||||
@@ -6,7 +6,6 @@
|
||||
* found in the LICENSE file at https://angular.io/license
|
||||
*/
|
||||
import * as ts from 'typescript';
|
||||
|
||||
import { findNodes, insertAfterLastOccurrence } from './ast-utils';
|
||||
import { Change, NoopChange } from './change';
|
||||
|
||||
@@ -31,22 +30,25 @@ export function insertImport(
|
||||
const allImports = findNodes(rootNode, ts.SyntaxKind.ImportDeclaration);
|
||||
|
||||
// get nodes that map to import statements from the file fileName
|
||||
const relevantImports = allImports.filter((node) => {
|
||||
const relevantImports = allImports.filter(node => {
|
||||
// StringLiteral of the ImportDeclaration is the import file (fileName in this case).
|
||||
const importFiles = node
|
||||
.getChildren()
|
||||
.filter((child) => child.kind === ts.SyntaxKind.StringLiteral)
|
||||
.map((n) => (n as ts.StringLiteral).text);
|
||||
.filter(child => child.kind === ts.SyntaxKind.StringLiteral)
|
||||
.map(n => (n as ts.StringLiteral).text);
|
||||
|
||||
return importFiles.filter((file) => file === fileName).length === 1;
|
||||
return importFiles.filter(file => file === fileName).length === 1;
|
||||
});
|
||||
|
||||
if (relevantImports.length > 0) {
|
||||
let importsAsterisk = false;
|
||||
// imports from import file
|
||||
const imports: ts.Node[] = [];
|
||||
relevantImports.forEach((n) => {
|
||||
Array.prototype.push.apply(imports, findNodes(n, ts.SyntaxKind.Identifier));
|
||||
relevantImports.forEach(n => {
|
||||
Array.prototype.push.apply(
|
||||
imports,
|
||||
findNodes(n, ts.SyntaxKind.Identifier)
|
||||
);
|
||||
if (findNodes(n, ts.SyntaxKind.AsteriskToken).length > 0) {
|
||||
importsAsterisk = true;
|
||||
}
|
||||
@@ -57,15 +59,25 @@ export function insertImport(
|
||||
return new NoopChange();
|
||||
}
|
||||
|
||||
const importTextNodes = imports.filter((n) => (n as ts.Identifier).text === symbolName);
|
||||
const importTextNodes = imports.filter(
|
||||
n => (n as ts.Identifier).text === symbolName
|
||||
);
|
||||
|
||||
// insert import if it's not there
|
||||
if (importTextNodes.length === 0) {
|
||||
const fallbackPos =
|
||||
findNodes(relevantImports[0], ts.SyntaxKind.CloseBraceToken)[0].getStart() ||
|
||||
findNodes(
|
||||
relevantImports[0],
|
||||
ts.SyntaxKind.CloseBraceToken
|
||||
)[0].getStart() ||
|
||||
findNodes(relevantImports[0], ts.SyntaxKind.FromKeyword)[0].getStart();
|
||||
|
||||
return insertAfterLastOccurrence(imports, `, ${symbolName}`, fileToEdit, fallbackPos);
|
||||
return insertAfterLastOccurrence(
|
||||
imports,
|
||||
`, ${symbolName}`,
|
||||
fileToEdit,
|
||||
fallbackPos
|
||||
);
|
||||
}
|
||||
|
||||
return new NoopChange();
|
||||
@@ -85,7 +97,14 @@ export function insertImport(
|
||||
const insertAtBeginning = allImports.length === 0 && useStrict.length === 0;
|
||||
const separator = insertAtBeginning ? '' : ';\n';
|
||||
const toInsert =
|
||||
`${separator}import ${open}${symbolName}${close}` + ` from '${fileName}'${insertAtBeginning ? ';\n' : ''}`;
|
||||
`${separator}import ${open}${symbolName}${close}` +
|
||||
` from '${fileName}'${insertAtBeginning ? ';\n' : ''}`;
|
||||
|
||||
return insertAfterLastOccurrence(allImports, toInsert, fileToEdit, fallbackPos, ts.SyntaxKind.StringLiteral);
|
||||
return insertAfterLastOccurrence(
|
||||
allImports,
|
||||
toInsert,
|
||||
fileToEdit,
|
||||
fallbackPos,
|
||||
ts.SyntaxKind.StringLiteral
|
||||
);
|
||||
}
|
||||
|
||||
@@ -1,11 +1,11 @@
|
||||
import { Tree } from '@angular-devkit/schematics';
|
||||
import {Tree} from '@angular-devkit/schematics';
|
||||
|
||||
/**
|
||||
* Adds a package to the package.json
|
||||
*/
|
||||
export function addPackageToPackageJson(host: Tree, type: string, pkg: string, version: string): Tree {
|
||||
export function addPackageToPackageJson(host: Tree, type: string, pkg: string, version: string) {
|
||||
if (host.exists('package.json')) {
|
||||
const sourceText = host.read('package.json')?.toString('utf-8');
|
||||
const sourceText = host.read('package.json')!.toString('utf-8');
|
||||
const json = JSON.parse(sourceText);
|
||||
if (!json[type]) {
|
||||
json[type] = {};
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
|
||||
export interface IonicGlobal {
|
||||
config?: any;
|
||||
asyncQueue?: boolean;
|
||||
|
||||
@@ -1,31 +1,27 @@
|
||||
import { ActivatedRouteSnapshot, DetachedRouteHandle, RouteReuseStrategy } from '@angular/router';
|
||||
|
||||
export class IonicRouteStrategy implements RouteReuseStrategy {
|
||||
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
||||
|
||||
shouldDetach(_route: ActivatedRouteSnapshot): boolean {
|
||||
return false;
|
||||
}
|
||||
|
||||
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
||||
shouldAttach(_route: ActivatedRouteSnapshot): boolean {
|
||||
return false;
|
||||
}
|
||||
|
||||
store(
|
||||
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
||||
_route: ActivatedRouteSnapshot,
|
||||
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
||||
_detachedTree: DetachedRouteHandle
|
||||
): void {
|
||||
store(_route: ActivatedRouteSnapshot, _detachedTree: DetachedRouteHandle): void {
|
||||
return;
|
||||
}
|
||||
|
||||
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
||||
retrieve(_route: ActivatedRouteSnapshot): DetachedRouteHandle | null {
|
||||
return null;
|
||||
}
|
||||
|
||||
shouldReuseRoute(future: ActivatedRouteSnapshot, curr: ActivatedRouteSnapshot): boolean {
|
||||
shouldReuseRoute(
|
||||
future: ActivatedRouteSnapshot,
|
||||
curr: ActivatedRouteSnapshot
|
||||
): boolean {
|
||||
if (future.routeConfig !== curr.routeConfig) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
|
||||
interface ControllerShape<Opts, HTMLElm> {
|
||||
create(options: Opts): Promise<HTMLElm>;
|
||||
dismiss(data?: any, role?: string, id?: string): Promise<boolean>;
|
||||
@@ -10,7 +11,7 @@ export class OverlayBaseController<Opts, Overlay> implements ControllerShape<Opt
|
||||
/**
|
||||
* Creates a new overlay
|
||||
*/
|
||||
create(opts?: Opts): Promise<Overlay> {
|
||||
create(opts?: Opts) {
|
||||
// TODO: next major release opts is not optional
|
||||
return this.ctrl.create((opts || {}) as any);
|
||||
}
|
||||
@@ -18,14 +19,14 @@ export class OverlayBaseController<Opts, Overlay> implements ControllerShape<Opt
|
||||
/**
|
||||
* When `id` is not provided, it dismisses the top overlay.
|
||||
*/
|
||||
dismiss(data?: any, role?: string, id?: string): Promise<boolean> {
|
||||
dismiss(data?: any, role?: string, id?: string) {
|
||||
return this.ctrl.dismiss(data, role, id);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the top overlay.
|
||||
*/
|
||||
getTop(): Promise<Overlay | undefined> {
|
||||
getTop() {
|
||||
return this.ctrl.getTop();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,7 +1,8 @@
|
||||
|
||||
declare const __zone_symbol__requestAnimationFrame: any;
|
||||
declare const requestAnimationFrame: any;
|
||||
|
||||
export const raf = (h: any): any => {
|
||||
export const raf = (h: any) => {
|
||||
if (typeof __zone_symbol__requestAnimationFrame === 'function') {
|
||||
return __zone_symbol__requestAnimationFrame(h);
|
||||
}
|
||||
|
||||
@@ -1,51 +0,0 @@
|
||||
{
|
||||
"root": true,
|
||||
"ignorePatterns": [
|
||||
"projects/**/*"
|
||||
],
|
||||
"overrides": [
|
||||
{
|
||||
"files": [
|
||||
"*.ts"
|
||||
],
|
||||
"parserOptions": {
|
||||
"project": [
|
||||
"tsconfig.json",
|
||||
"e2e/tsconfig.json"
|
||||
],
|
||||
"createDefaultProgram": true
|
||||
},
|
||||
"extends": [
|
||||
"plugin:@angular-eslint/recommended",
|
||||
"plugin:@angular-eslint/template/process-inline-templates"
|
||||
],
|
||||
"rules": {
|
||||
"@angular-eslint/component-selector": [
|
||||
"error",
|
||||
{
|
||||
"prefix": "app",
|
||||
"style": "kebab-case",
|
||||
"type": "element"
|
||||
}
|
||||
],
|
||||
"@angular-eslint/directive-selector": [
|
||||
"error",
|
||||
{
|
||||
"prefix": "app",
|
||||
"style": "camelCase",
|
||||
"type": "attribute"
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
{
|
||||
"files": [
|
||||
"*.html"
|
||||
],
|
||||
"extends": [
|
||||
"plugin:@angular-eslint/template/recommended"
|
||||
],
|
||||
"rules": {}
|
||||
}
|
||||
]
|
||||
}
|
||||
@@ -33,9 +33,7 @@
|
||||
"output": "./svg"
|
||||
}
|
||||
],
|
||||
"styles": [
|
||||
"src/styles.css"
|
||||
],
|
||||
"styles": ["src/styles.css"],
|
||||
"scripts": []
|
||||
},
|
||||
"configurations": {
|
||||
@@ -49,6 +47,7 @@
|
||||
"optimization": true,
|
||||
"outputHashing": "all",
|
||||
"sourceMap": false,
|
||||
"extractCss": true,
|
||||
"namedChunks": false,
|
||||
"aot": true,
|
||||
"progress": false,
|
||||
@@ -87,12 +86,10 @@
|
||||
}
|
||||
},
|
||||
"lint": {
|
||||
"builder": "@angular-eslint/builder:lint",
|
||||
"builder": "@angular-devkit/build-angular:tslint",
|
||||
"options": {
|
||||
"lintFilePatterns": [
|
||||
"src/**/*.ts",
|
||||
"src/**/*.html"
|
||||
]
|
||||
"tsConfig": ["tsconfig.app.json", "tsconfig.spec.json"],
|
||||
"exclude": ["**/node_modules/**"]
|
||||
}
|
||||
},
|
||||
"server": {
|
||||
@@ -140,8 +137,5 @@
|
||||
}
|
||||
}
|
||||
},
|
||||
"defaultProject": "test-app",
|
||||
"cli": {
|
||||
"defaultCollection": "@angular-eslint/schematics"
|
||||
}
|
||||
"defaultProject": "test-app"
|
||||
}
|
||||
|
||||
@@ -41,23 +41,3 @@ describe('Modals', () => {
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
|
||||
describe('Modals: Inline', () => {
|
||||
beforeEach(() => {
|
||||
cy.visit('/modal-inline');
|
||||
});
|
||||
|
||||
it('should initially have no items', () => {
|
||||
cy.get('ion-list ion-item').should('not.exist');
|
||||
});
|
||||
|
||||
it('should have items after 1500ms', () => {
|
||||
cy.wait(1500);
|
||||
|
||||
cy.get('ion-list ion-item:nth-child(1)').should('have.text', 'A');
|
||||
cy.get('ion-list ion-item:nth-child(2)').should('have.text', 'B');
|
||||
cy.get('ion-list ion-item:nth-child(3)').should('have.text', 'C');
|
||||
cy.get('ion-list ion-item:nth-child(4)').should('have.text', 'D');
|
||||
});
|
||||
});
|
||||
|
||||
@@ -1,18 +0,0 @@
|
||||
describe('Popovers: Inline', () => {
|
||||
beforeEach(() => {
|
||||
cy.visit('/popover-inline');
|
||||
});
|
||||
|
||||
it('should initially have no items', () => {
|
||||
cy.get('ion-list ion-item').should('not.exist');
|
||||
});
|
||||
|
||||
it('should have items after 1500ms', () => {
|
||||
cy.wait(1500);
|
||||
|
||||
cy.get('ion-list ion-item:nth-child(1)').should('have.text', 'A');
|
||||
cy.get('ion-list ion-item:nth-child(2)').should('have.text', 'B');
|
||||
cy.get('ion-list ion-item:nth-child(3)').should('have.text', 'C');
|
||||
cy.get('ion-list ion-item:nth-child(4)').should('have.text', 'D');
|
||||
});
|
||||
});
|
||||
33483
angular/test/test-app/package-lock.json
generated
33483
angular/test/test-app/package-lock.json
generated
File diff suppressed because it is too large
Load Diff
@@ -7,7 +7,7 @@
|
||||
"start": "npm run sync && ng serve",
|
||||
"sync:build": "sh scripts/build-ionic.sh",
|
||||
"sync": "sh scripts/sync.sh",
|
||||
"build": "npm run sync && ng build --configuration production --no-progress",
|
||||
"build": "npm run sync && ng build --prod --no-progress",
|
||||
"lint": "ng lint",
|
||||
"postinstall": "npm run sync && ngcc",
|
||||
"serve:ssr": "node dist/test-app/server/main.js",
|
||||
@@ -20,49 +20,41 @@
|
||||
"test.watch": "concurrently \"npm run start\" \"wait-on http-get://localhost:4200 && npm run cy.open\" --kill-others --success first"
|
||||
},
|
||||
"dependencies": {
|
||||
"@angular/animations": "^12.2.8",
|
||||
"@angular/common": "^12.2.8",
|
||||
"@angular/compiler": "^12.2.8",
|
||||
"@angular/core": "^12.2.8",
|
||||
"@angular/forms": "^12.2.8",
|
||||
"@angular/platform-browser": "^12.2.8",
|
||||
"@angular/platform-browser-dynamic": "^12.2.8",
|
||||
"@angular/platform-server": "^12.2.8",
|
||||
"@angular/router": "^12.2.8",
|
||||
"@angular/animations": "^11.2.11",
|
||||
"@angular/common": "^11.2.11",
|
||||
"@angular/compiler": "^11.2.11",
|
||||
"@angular/core": "^11.2.11",
|
||||
"@angular/forms": "^11.2.11",
|
||||
"@angular/platform-browser": "^11.2.11",
|
||||
"@angular/platform-browser-dynamic": "^11.2.11",
|
||||
"@angular/platform-server": "^11.2.11",
|
||||
"@angular/router": "^11.2.11",
|
||||
"@ionic/angular": "^5.3.1",
|
||||
"@ionic/angular-server": "^5.3.1",
|
||||
"@nguniversal/express-engine": "^12.1.1",
|
||||
"@nguniversal/express-engine": "^11.2.1",
|
||||
"angular-in-memory-web-api": "^0.11.0",
|
||||
"core-js": "^2.6.11",
|
||||
"express": "^4.15.2",
|
||||
"rxjs": "^6.5.5",
|
||||
"tslib": "^2.0.0",
|
||||
"typescript-eslint-language-service": "^4.1.5",
|
||||
"zone.js": "^0.11.4"
|
||||
"zone.js": "^0.10.3"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@angular-devkit/build-angular": "^12.2.8",
|
||||
"@angular-eslint/builder": "12.5.0",
|
||||
"@angular-eslint/eslint-plugin": "12.5.0",
|
||||
"@angular-eslint/eslint-plugin-template": "12.5.0",
|
||||
"@angular-eslint/schematics": "12.5.0",
|
||||
"@angular-eslint/template-parser": "12.5.0",
|
||||
"@angular/cli": "^12.2.8",
|
||||
"@angular/compiler-cli": "^12.2.8",
|
||||
"@angular/language-service": "^12.2.8",
|
||||
"@nguniversal/builders": "^12.1.1",
|
||||
"@angular-devkit/build-angular": "^0.1102.10",
|
||||
"@angular/cli": "^11.2.10",
|
||||
"@angular/compiler-cli": "^11.2.11",
|
||||
"@angular/language-service": "^11.2.11",
|
||||
"@nguniversal/builders": "^11.2.1",
|
||||
"@types/express": "^4.17.7",
|
||||
"@types/node": "^12.12.54",
|
||||
"@typescript-eslint/eslint-plugin": "4.28.2",
|
||||
"@typescript-eslint/parser": "4.28.2",
|
||||
"codelyzer": "^6.0.1",
|
||||
"concurrently": "^6.0.0",
|
||||
"cypress": "^6.7.1",
|
||||
"eslint": "^7.26.0",
|
||||
"ts-loader": "^6.2.2",
|
||||
"ts-node": "^8.3.0",
|
||||
"typescript": "^4.3.5",
|
||||
"tslint": "~6.1.0",
|
||||
"typescript": "^4.0.7",
|
||||
"wait-on": "^5.2.1",
|
||||
"webpack": "^5.61.0",
|
||||
"webpack-cli": "^3.3.12"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -27,9 +27,7 @@ const routes: Routes = [
|
||||
{ path: 'inputs', component: InputsComponent },
|
||||
{ path: 'form', component: FormComponent },
|
||||
{ path: 'modals', component: ModalComponent },
|
||||
{ path: 'modal-inline', loadChildren: () => import('./modal-inline').then(m => m.ModalInlineModule) },
|
||||
{ path: 'view-child', component: ViewChildComponent },
|
||||
{ path: 'popover-inline', loadChildren: () => import('./popover-inline').then(m => m.PopoverInlineModule) },
|
||||
{ path: 'providers', component: ProvidersComponent },
|
||||
{ path: 'router-link', component: RouterLinkComponent },
|
||||
{ path: 'router-link-page', component: RouterLinkPageComponent },
|
||||
|
||||
@@ -63,7 +63,7 @@ import { AlertComponent } from './alert/alert.component';
|
||||
AppRoutingModule,
|
||||
FormsModule,
|
||||
ReactiveFormsModule,
|
||||
IonicModule.forRoot({ keyboardHeight: 12345 }),
|
||||
IonicModule.forRoot(),
|
||||
],
|
||||
entryComponents: [
|
||||
ModalExampleComponent,
|
||||
|
||||
@@ -1,2 +0,0 @@
|
||||
export * from './modal-inline.component';
|
||||
export * from './modal-inline.module';
|
||||
@@ -1,16 +0,0 @@
|
||||
import { NgModule } from "@angular/core";
|
||||
import { RouterModule } from "@angular/router";
|
||||
import { ModalInlineComponent } from ".";
|
||||
|
||||
@NgModule({
|
||||
imports: [
|
||||
RouterModule.forChild([
|
||||
{
|
||||
path: '',
|
||||
component: ModalInlineComponent
|
||||
}
|
||||
])
|
||||
],
|
||||
exports: [RouterModule]
|
||||
})
|
||||
export class ModalInlineRoutingModule { }
|
||||
@@ -1,11 +0,0 @@
|
||||
<ion-modal [isOpen]="true" [breakpoints]="[0.1, 0.5, 1]" [initialBreakpoint]="0.5">
|
||||
<ng-template>
|
||||
<ion-content>
|
||||
<ion-list>
|
||||
<ion-item *ngFor="let item of items">
|
||||
<ion-label>{{ item }}</ion-label>
|
||||
</ion-item>
|
||||
</ion-list>
|
||||
</ion-content>
|
||||
</ng-template>
|
||||
</ion-modal>
|
||||
@@ -1,21 +0,0 @@
|
||||
import { AfterViewInit, Component } from "@angular/core";
|
||||
|
||||
/**
|
||||
* Validates that inline modals will correctly display
|
||||
* dynamic contents that are updated after the modal is
|
||||
* display.
|
||||
*/
|
||||
@Component({
|
||||
selector: 'app-modal-inline',
|
||||
templateUrl: 'modal-inline.component.html'
|
||||
})
|
||||
export class ModalInlineComponent implements AfterViewInit {
|
||||
|
||||
items: string[] = [];
|
||||
|
||||
ngAfterViewInit(): void {
|
||||
setTimeout(() => {
|
||||
this.items = ['A', 'B', 'C', 'D'];
|
||||
}, 1000);
|
||||
}
|
||||
}
|
||||
@@ -1,12 +0,0 @@
|
||||
import { CommonModule } from "@angular/common";
|
||||
import { NgModule } from "@angular/core";
|
||||
import { IonicModule } from "@ionic/angular";
|
||||
import { ModalInlineRoutingModule } from "./modal-inline-routing.module";
|
||||
import { ModalInlineComponent } from "./modal-inline.component";
|
||||
|
||||
@NgModule({
|
||||
imports: [CommonModule, IonicModule, ModalInlineRoutingModule],
|
||||
declarations: [ModalInlineComponent],
|
||||
exports: [ModalInlineComponent]
|
||||
})
|
||||
export class ModalInlineModule { }
|
||||
@@ -1 +0,0 @@
|
||||
export * from './popover-inline.module';
|
||||
@@ -1,14 +0,0 @@
|
||||
import { NgModule } from "@angular/core";
|
||||
import { RouterModule } from "@angular/router";
|
||||
import { PopoverInlineComponent } from "./popover-inline.component";
|
||||
|
||||
@NgModule({
|
||||
imports: [RouterModule.forChild([
|
||||
{
|
||||
path: '',
|
||||
component: PopoverInlineComponent
|
||||
}
|
||||
])],
|
||||
exports: [RouterModule]
|
||||
})
|
||||
export class PopoverInlineRoutingModule { }
|
||||
@@ -1,11 +0,0 @@
|
||||
<ion-popover [isOpen]="true">
|
||||
<ng-template>
|
||||
<ion-content>
|
||||
<ion-list>
|
||||
<ion-item *ngFor="let item of items">
|
||||
<ion-label>{{ item }}</ion-label>
|
||||
</ion-item>
|
||||
</ion-list>
|
||||
</ion-content>
|
||||
</ng-template>
|
||||
</ion-popover>
|
||||
@@ -1,22 +0,0 @@
|
||||
import { AfterViewInit, Component } from "@angular/core";
|
||||
|
||||
/**
|
||||
* Validates that inline popovers will correctly display
|
||||
* dynamic contents that are updated after the modal is
|
||||
* display.
|
||||
*/
|
||||
@Component({
|
||||
selector: 'app-popover-inline',
|
||||
templateUrl: 'popover-inline.component.html'
|
||||
})
|
||||
export class PopoverInlineComponent implements AfterViewInit {
|
||||
|
||||
items: string[] = [];
|
||||
|
||||
ngAfterViewInit(): void {
|
||||
setTimeout(() => {
|
||||
this.items = ['A', 'B', 'C', 'D'];
|
||||
}, 1000);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,11 +0,0 @@
|
||||
import { CommonModule } from "@angular/common";
|
||||
import { NgModule } from "@angular/core";
|
||||
import { IonicModule } from "@ionic/angular";
|
||||
import { PopoverInlineRoutingModule } from "./popover-inline-routing.module";
|
||||
import { PopoverInlineComponent } from "./popover-inline.component";
|
||||
|
||||
@NgModule({
|
||||
imports: [CommonModule, IonicModule, PopoverInlineRoutingModule],
|
||||
declarations: [PopoverInlineComponent],
|
||||
})
|
||||
export class PopoverInlineModule { }
|
||||
@@ -69,6 +69,7 @@ export class ProvidersComponent {
|
||||
|
||||
// test config
|
||||
this.isTesting = config.getBoolean('_testing');
|
||||
config.set('keyboardHeight', 12345);
|
||||
this.keyboardHeight = config.getNumber('keyboardHeight');
|
||||
|
||||
zone.runOutsideAngular(() => {
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user