Compare commits
46 Commits
v6.3.1-nig
...
FW-388-a
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
7d629ba9f1 | ||
|
|
57105d54ea | ||
|
|
9f0b30e460 | ||
|
|
bb005956ea | ||
|
|
1f7fc8f05c | ||
|
|
e9306f8ad9 | ||
|
|
c6db6c7822 | ||
|
|
5e8a75a643 | ||
|
|
4c30a80b7e | ||
|
|
1504b8888d | ||
|
|
bbbd37bc49 | ||
|
|
c0f4381745 | ||
|
|
b364d58710 | ||
|
|
8ac3b8b575 | ||
|
|
1320948b24 | ||
|
|
a7e15babf3 | ||
|
|
3745083b7c | ||
|
|
c3882d8b21 | ||
|
|
a5b45821cd | ||
|
|
53caa22212 | ||
|
|
6bbb372980 | ||
|
|
0fa68cfa61 | ||
|
|
8ec350ae65 | ||
|
|
74be79e9d8 | ||
|
|
51ab5f67b5 | ||
|
|
0548fe8588 | ||
|
|
479d56b3b2 | ||
|
|
d4d569ac09 | ||
|
|
ffcf8ec4e0 | ||
|
|
5d77fde503 | ||
|
|
1a6595b895 | ||
|
|
7e5c03ae40 | ||
|
|
2192409123 | ||
|
|
0e7f7fcdca | ||
|
|
fbbebee7be | ||
|
|
d76a24dd9e | ||
|
|
d60973b244 | ||
|
|
5e4892676c | ||
|
|
04df45a443 | ||
|
|
256b03f12a | ||
|
|
ff6df69a67 | ||
|
|
bbd6c9ae6c | ||
|
|
61cc278f05 | ||
|
|
01840741ce | ||
|
|
448e3fc385 | ||
|
|
5e030f996a |
@@ -3,7 +3,7 @@ description: 'Build Ionic Angular Server'
|
||||
runs:
|
||||
using: 'composite'
|
||||
steps:
|
||||
- uses: actions/setup-node@v1
|
||||
- uses: actions/setup-node@v3
|
||||
with:
|
||||
node-version: 16.x
|
||||
|
||||
|
||||
@@ -3,19 +3,19 @@ description: 'Build Ionic Angular'
|
||||
runs:
|
||||
using: 'composite'
|
||||
steps:
|
||||
- uses: actions/setup-node@v1
|
||||
- uses: actions/setup-node@v3
|
||||
with:
|
||||
node-version: 16.x
|
||||
|
||||
- name: Cache Core Node Modules
|
||||
uses: actions/cache@v2
|
||||
uses: actions/cache@v3
|
||||
env:
|
||||
cache-name: core-node-modules
|
||||
with:
|
||||
path: ./core/node_modules
|
||||
key: ${{ runner.os }}-build-${{ env.cache-name }}-${{ hashFiles('./core/package-lock.json')}}-v2
|
||||
- name: Cache Angular Node Modules
|
||||
uses: actions/cache@v2
|
||||
uses: actions/cache@v3
|
||||
env:
|
||||
cache-name: angular-node-modules
|
||||
with:
|
||||
|
||||
@@ -3,16 +3,16 @@ description: 'Build Ionic Core'
|
||||
runs:
|
||||
using: 'composite'
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
- uses: actions/checkout@v3
|
||||
with:
|
||||
# Checkout the latest commit in this branch
|
||||
ref: ${{ github.event.pull_request.head.sha }}
|
||||
- uses: actions/setup-node@v1
|
||||
- uses: actions/setup-node@v3
|
||||
with:
|
||||
node-version: 16.x
|
||||
|
||||
- name: Cache Node Modules
|
||||
uses: actions/cache@v2
|
||||
uses: actions/cache@v3
|
||||
env:
|
||||
cache-name: core-node-modules
|
||||
with:
|
||||
|
||||
@@ -3,12 +3,12 @@ description: 'Build Ionic React Router'
|
||||
runs:
|
||||
using: 'composite'
|
||||
steps:
|
||||
- uses: actions/setup-node@v1
|
||||
- uses: actions/setup-node@v3
|
||||
with:
|
||||
node-version: 16.x
|
||||
|
||||
- name: Cache Core Node Modules
|
||||
uses: actions/cache@v2
|
||||
uses: actions/cache@v3
|
||||
env:
|
||||
cache-name: core-node-modules
|
||||
with:
|
||||
|
||||
@@ -3,12 +3,12 @@ description: 'Build Ionic React'
|
||||
runs:
|
||||
using: 'composite'
|
||||
steps:
|
||||
- uses: actions/setup-node@v1
|
||||
- uses: actions/setup-node@v3
|
||||
with:
|
||||
node-version: 16.x
|
||||
|
||||
- name: Cache Core Node Modules
|
||||
uses: actions/cache@v2
|
||||
uses: actions/cache@v3
|
||||
env:
|
||||
cache-name: core-node-modules
|
||||
with:
|
||||
|
||||
@@ -3,12 +3,12 @@ description: 'Builds Ionic Vue Router'
|
||||
runs:
|
||||
using: 'composite'
|
||||
steps:
|
||||
- uses: actions/setup-node@v1
|
||||
- uses: actions/setup-node@v3
|
||||
with:
|
||||
node-version: 16.x
|
||||
|
||||
- name: Cache Core Node Modules
|
||||
uses: actions/cache@v2
|
||||
uses: actions/cache@v3
|
||||
env:
|
||||
cache-name: core-node-modules
|
||||
with:
|
||||
|
||||
@@ -3,12 +3,12 @@ description: 'Build Ionic Vue'
|
||||
runs:
|
||||
using: 'composite'
|
||||
steps:
|
||||
- uses: actions/setup-node@v1
|
||||
- uses: actions/setup-node@v3
|
||||
with:
|
||||
node-version: 16.x
|
||||
|
||||
- name: Cache Core Node Modules
|
||||
uses: actions/cache@v2
|
||||
uses: actions/cache@v3
|
||||
env:
|
||||
cache-name: core-node-modules
|
||||
with:
|
||||
|
||||
@@ -10,7 +10,7 @@ inputs:
|
||||
runs:
|
||||
using: 'composite'
|
||||
steps:
|
||||
- uses: actions/download-artifact@v2
|
||||
- uses: actions/download-artifact@v3
|
||||
with:
|
||||
name: ${{ inputs.name }}
|
||||
path: ${{ inputs.path }}
|
||||
|
||||
@@ -6,12 +6,12 @@ inputs:
|
||||
runs:
|
||||
using: 'composite'
|
||||
steps:
|
||||
- uses: actions/setup-node@v1
|
||||
- uses: actions/setup-node@v3
|
||||
with:
|
||||
node-version: 16
|
||||
|
||||
- name: Cache Core Node Modules
|
||||
uses: actions/cache@v2
|
||||
uses: actions/cache@v3
|
||||
env:
|
||||
cache-name: core-node-modules
|
||||
with:
|
||||
@@ -37,7 +37,7 @@ runs:
|
||||
shell: bash
|
||||
working-directory: ./angular/test
|
||||
- name: Install Dependencies
|
||||
run: npm install
|
||||
run: npm install --legacy-peer-deps
|
||||
shell: bash
|
||||
working-directory: ./angular/test/build/${{ inputs.app }}
|
||||
- name: Sync Built Changes
|
||||
|
||||
@@ -3,7 +3,7 @@ description: 'Test Core Clean Build'
|
||||
runs:
|
||||
using: 'composite'
|
||||
steps:
|
||||
- uses: actions/setup-node@v1
|
||||
- uses: actions/setup-node@v3
|
||||
with:
|
||||
node-version: 16.x
|
||||
|
||||
|
||||
@@ -3,12 +3,12 @@ description: 'Test Core E2E'
|
||||
runs:
|
||||
using: 'composite'
|
||||
steps:
|
||||
- uses: actions/setup-node@v1
|
||||
- uses: actions/setup-node@v3
|
||||
with:
|
||||
node-version: 16.x
|
||||
|
||||
- name: Cache Core Node Modules
|
||||
uses: actions/cache@v2
|
||||
uses: actions/cache@v3
|
||||
env:
|
||||
cache-name: core-node-modules
|
||||
with:
|
||||
|
||||
@@ -3,12 +3,12 @@ description: 'Test Core Lint'
|
||||
runs:
|
||||
using: 'composite'
|
||||
steps:
|
||||
- uses: actions/setup-node@v1
|
||||
- uses: actions/setup-node@v3
|
||||
with:
|
||||
node-version: 16.x
|
||||
|
||||
- name: Cache Core Node Modules
|
||||
uses: actions/cache@v2
|
||||
uses: actions/cache@v3
|
||||
env:
|
||||
cache-name: core-node-modules
|
||||
with:
|
||||
|
||||
@@ -10,12 +10,12 @@ inputs:
|
||||
runs:
|
||||
using: 'composite'
|
||||
steps:
|
||||
- uses: actions/setup-node@v1
|
||||
- uses: actions/setup-node@v3
|
||||
with:
|
||||
node-version: 16.x
|
||||
|
||||
- name: Cache Core Node Modules
|
||||
uses: actions/cache@v2
|
||||
uses: actions/cache@v3
|
||||
env:
|
||||
cache-name: core-node-modules
|
||||
with:
|
||||
@@ -72,7 +72,7 @@ runs:
|
||||
working-directory: ./core
|
||||
- name: Archive Updated Screenshots
|
||||
if: inputs.update == 'true' && steps.test-and-update.outputs.hasUpdatedScreenshots == 'true'
|
||||
uses: actions/upload-artifact@v2
|
||||
uses: actions/upload-artifact@v3
|
||||
with:
|
||||
name: updated-screenshots-${{ inputs.shard }}-${{ inputs.totalShards }}
|
||||
path: UpdatedScreenshots-${{ inputs.shard }}-${{ inputs.totalShards }}.zip
|
||||
|
||||
@@ -3,12 +3,12 @@ description: 'Test Core Spec'
|
||||
runs:
|
||||
using: 'composite'
|
||||
steps:
|
||||
- uses: actions/setup-node@v1
|
||||
- uses: actions/setup-node@v3
|
||||
with:
|
||||
node-version: 16.x
|
||||
|
||||
- name: Cache Core Node Modules
|
||||
uses: actions/cache@v2
|
||||
uses: actions/cache@v3
|
||||
env:
|
||||
cache-name: core-node-modules
|
||||
with:
|
||||
|
||||
@@ -3,12 +3,12 @@ description: 'Test React E2E'
|
||||
runs:
|
||||
using: 'composite'
|
||||
steps:
|
||||
- uses: actions/setup-node@v1
|
||||
- uses: actions/setup-node@v3
|
||||
with:
|
||||
node-version: 16.x
|
||||
|
||||
- name: Cache Core Node Modules
|
||||
uses: actions/cache@v2
|
||||
uses: actions/cache@v3
|
||||
env:
|
||||
cache-name: core-node-modules
|
||||
with:
|
||||
|
||||
@@ -3,12 +3,12 @@ description: 'Test React Router '
|
||||
runs:
|
||||
using: 'composite'
|
||||
steps:
|
||||
- uses: actions/setup-node@v1
|
||||
- uses: actions/setup-node@v3
|
||||
with:
|
||||
node-version: 16.x
|
||||
|
||||
- name: Cache Core Node Modules
|
||||
uses: actions/cache@v2
|
||||
uses: actions/cache@v3
|
||||
env:
|
||||
cache-name: core-node-modules
|
||||
with:
|
||||
|
||||
@@ -6,12 +6,12 @@ inputs:
|
||||
runs:
|
||||
using: 'composite'
|
||||
steps:
|
||||
- uses: actions/setup-node@v1
|
||||
- uses: actions/setup-node@v3
|
||||
with:
|
||||
node-version: 16.x
|
||||
|
||||
- name: Cache Core Node Modules
|
||||
uses: actions/cache@v2
|
||||
uses: actions/cache@v3
|
||||
env:
|
||||
cache-name: core-node-modules
|
||||
with:
|
||||
|
||||
@@ -7,10 +7,10 @@ on:
|
||||
runs:
|
||||
using: 'composite'
|
||||
steps:
|
||||
- uses: actions/setup-node@v1
|
||||
- uses: actions/setup-node@v3
|
||||
with:
|
||||
node-version: 16.x
|
||||
- uses: actions/download-artifact@v2
|
||||
- uses: actions/download-artifact@v3
|
||||
with:
|
||||
path: ./artifacts
|
||||
- name: Extract Archives
|
||||
|
||||
@@ -13,7 +13,7 @@ runs:
|
||||
- name: Create Archive
|
||||
run: zip -q -r ${{ inputs.output }} ${{ inputs.paths }}
|
||||
shell: bash
|
||||
- uses: actions/upload-artifact@v2
|
||||
- uses: actions/upload-artifact@v3
|
||||
with:
|
||||
name: ${{ inputs.name }}
|
||||
path: ${{ inputs.output }}
|
||||
|
||||
34
.github/workflows/build.yml
vendored
@@ -15,7 +15,7 @@ jobs:
|
||||
build-core:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
- uses: actions/checkout@v3
|
||||
with:
|
||||
# Checkout the latest commit in this branch
|
||||
ref: ${{ github.event.pull_request.head.sha }}
|
||||
@@ -25,28 +25,28 @@ jobs:
|
||||
needs: [build-core]
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
- uses: actions/checkout@v3
|
||||
- uses: ./.github/workflows/actions/test-core-clean-build
|
||||
|
||||
test-core-lint:
|
||||
needs: [build-core]
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
- uses: actions/checkout@v3
|
||||
- uses: ./.github/workflows/actions/test-core-lint
|
||||
|
||||
test-core-spec:
|
||||
needs: [build-core]
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
- uses: actions/checkout@v3
|
||||
- uses: ./.github/workflows/actions/test-core-spec
|
||||
|
||||
test-core-e2e:
|
||||
needs: [build-core]
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
- uses: actions/checkout@v3
|
||||
- uses: ./.github/workflows/actions/test-core-e2e
|
||||
|
||||
test-core-screenshot:
|
||||
@@ -67,7 +67,7 @@ jobs:
|
||||
needs: [build-core]
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
- uses: actions/checkout@v3
|
||||
- uses: ./.github/workflows/actions/test-core-screenshot
|
||||
with:
|
||||
shard: ${{ matrix.shard }}
|
||||
@@ -95,14 +95,14 @@ jobs:
|
||||
needs: [build-core]
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
- uses: actions/checkout@v3
|
||||
- uses: ./.github/workflows/actions/build-vue
|
||||
|
||||
build-vue-router:
|
||||
needs: [build-vue]
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
- uses: actions/checkout@v3
|
||||
- uses: ./.github/workflows/actions/build-vue-router
|
||||
|
||||
test-vue-e2e:
|
||||
@@ -113,7 +113,7 @@ jobs:
|
||||
needs: [build-vue, build-vue-router]
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
- uses: actions/checkout@v3
|
||||
- uses: ./.github/workflows/actions/test-vue-e2e
|
||||
with:
|
||||
app: ${{ matrix.apps }}
|
||||
@@ -131,25 +131,25 @@ jobs:
|
||||
needs: [build-core]
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
- uses: actions/checkout@v3
|
||||
- uses: ./.github/workflows/actions/build-angular
|
||||
|
||||
build-angular-server:
|
||||
needs: [build-angular]
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
- uses: actions/checkout@v3
|
||||
- uses: ./.github/workflows/actions/build-angular-server
|
||||
|
||||
test-angular-e2e:
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
apps: [ng12, ng13, ng14]
|
||||
apps: [ng12, ng13, ng14, ng15]
|
||||
needs: [build-angular, build-angular-server]
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
- uses: actions/checkout@v3
|
||||
- uses: ./.github/workflows/actions/test-angular-e2e
|
||||
with:
|
||||
app: ${{ matrix.apps }}
|
||||
@@ -167,26 +167,26 @@ jobs:
|
||||
needs: [build-core]
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
- uses: actions/checkout@v3
|
||||
- uses: ./.github/workflows/actions/build-react
|
||||
|
||||
build-react-router:
|
||||
needs: [build-react]
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
- uses: actions/checkout@v3
|
||||
- uses: ./.github/workflows/actions/build-react-router
|
||||
|
||||
test-react-router-e2e:
|
||||
needs: [build-react, build-react-router]
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
- uses: actions/checkout@v3
|
||||
- uses: ./.github/workflows/actions/test-react-router-e2e
|
||||
|
||||
test-react-e2e:
|
||||
needs: [build-react, build-react-router]
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
- uses: actions/checkout@v3
|
||||
- uses: ./.github/workflows/actions/test-react-e2e
|
||||
|
||||
4
.github/workflows/dev-build.yml
vendored
@@ -9,8 +9,8 @@ jobs:
|
||||
outputs:
|
||||
version: ${{ steps.dev-build.outputs.version }}
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
- uses: actions/setup-node@v2
|
||||
- uses: actions/checkout@v3
|
||||
- uses: actions/setup-node@v3
|
||||
with:
|
||||
node-version: 16
|
||||
- name: Install Dependencies
|
||||
|
||||
4
.github/workflows/nightly.yml
vendored
@@ -10,10 +10,10 @@ jobs:
|
||||
nightly-build:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
- uses: actions/checkout@v3
|
||||
with:
|
||||
fetch-depth: 0
|
||||
- uses: actions/setup-node@v2
|
||||
- uses: actions/setup-node@v3
|
||||
with:
|
||||
node-version: 16
|
||||
- name: Install Dependencies
|
||||
|
||||
4
.github/workflows/pre-release.yml
vendored
@@ -25,8 +25,8 @@ jobs:
|
||||
build-ionic:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
- uses: actions/setup-node@v2
|
||||
- uses: actions/checkout@v3
|
||||
- uses: actions/setup-node@v3
|
||||
with:
|
||||
node-version: 16
|
||||
- name: Configure Identity
|
||||
|
||||
13
.github/workflows/release.yml
vendored
@@ -24,11 +24,11 @@ jobs:
|
||||
build-ionic:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
- uses: actions/checkout@v3
|
||||
with:
|
||||
token: ${{ secrets.IONITRON_TOKEN }}
|
||||
fetch-depth: 0
|
||||
- uses: actions/setup-node@v2
|
||||
- uses: actions/setup-node@v3
|
||||
with:
|
||||
node-version: 16
|
||||
- name: Configure Identity
|
||||
@@ -55,6 +55,15 @@ jobs:
|
||||
env:
|
||||
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
shell: bash
|
||||
# Lerna does not automatically bump versions
|
||||
# of Ionic dependencies that have changed,
|
||||
# so we do that here.
|
||||
- name: Bump Package Lock
|
||||
run: |
|
||||
lerna exec "npm install --package-lock-only --legacy-peer-deps"
|
||||
git add .
|
||||
git commit -m "chore(): update package lock files"
|
||||
git push
|
||||
# Purge the JSDeliver CDN cache so
|
||||
# component playgrounds always load
|
||||
# the latest version of Ionic.
|
||||
|
||||
6
.github/workflows/update-screenshots.yml
vendored
@@ -7,7 +7,7 @@ jobs:
|
||||
build-core:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
- uses: actions/checkout@v3
|
||||
- uses: ./.github/workflows/actions/build-core
|
||||
|
||||
test-core-screenshot:
|
||||
@@ -28,7 +28,7 @@ jobs:
|
||||
needs: [build-core]
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
- uses: actions/checkout@v3
|
||||
- uses: ./.github/workflows/actions/test-core-screenshot
|
||||
with:
|
||||
shard: ${{ matrix.shard }}
|
||||
@@ -39,7 +39,7 @@ jobs:
|
||||
runs-on: ubuntu-latest
|
||||
needs: [test-core-screenshot]
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
- uses: actions/checkout@v3
|
||||
# Normally, we could just push with the
|
||||
# default GITHUB_TOKEN, but that will
|
||||
# not cause the build workflow
|
||||
|
||||
45
CHANGELOG.md
@@ -3,7 +3,50 @@
|
||||
All notable changes to this project will be documented in this file.
|
||||
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
|
||||
|
||||
## [6.3.1-nightly.20221011](https://github.com/ionic-team/ionic-framework/compare/v6.3.0...v6.3.1-nightly.20221011) (2022-10-11)
|
||||
## [6.3.4](https://github.com/ionic-team/ionic-framework/compare/v6.3.3...v6.3.4) (2022-11-02)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* **datetime:** account for allowed values when setting default date ([#26093](https://github.com/ionic-team/ionic-framework/issues/26093)) ([3745083](https://github.com/ionic-team/ionic-framework/commit/3745083b7cdf8651d1c7f5f1a0214b487ea286ca)), closes [#24722](https://github.com/ionic-team/ionic-framework/issues/24722)
|
||||
* **modal, popover:** remove trigger click listeners when overlay is unmounted ([#26167](https://github.com/ionic-team/ionic-framework/issues/26167)) ([1320948](https://github.com/ionic-team/ionic-framework/commit/1320948b245be3defe8610b9f049e781a4903a6e))
|
||||
* **modal:** buttons are highlighted with VoiceOver ([#26180](https://github.com/ionic-team/ionic-framework/issues/26180)) ([1504b88](https://github.com/ionic-team/ionic-framework/commit/1504b8888d6f79ea382935ed52b104b9f841d150)), closes [#26156](https://github.com/ionic-team/ionic-framework/issues/26156)
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
## [6.3.3](https://github.com/ionic-team/ionic-framework/compare/v6.3.2...v6.3.3) (2022-10-26)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* **datetime:** empty string is treated as no value ([#26131](https://github.com/ionic-team/ionic-framework/issues/26131)) ([51ab5f6](https://github.com/ionic-team/ionic-framework/commit/51ab5f67b50013c0ed8ca3160d6dfc56bc269f2a)), closes [#26116](https://github.com/ionic-team/ionic-framework/issues/26116)
|
||||
* **datetime:** preferWheel can now show title ([#26101](https://github.com/ionic-team/ionic-framework/issues/26101)) ([479d56b](https://github.com/ionic-team/ionic-framework/commit/479d56b3b26d45bfd03d4095458c37ed00485c54)), closes [#26095](https://github.com/ionic-team/ionic-framework/issues/26095)
|
||||
* **datetime:** values are adjusted to be in bounds ([#26125](https://github.com/ionic-team/ionic-framework/issues/26125)) ([0548fe8](https://github.com/ionic-team/ionic-framework/commit/0548fe858854f0187e0dfe00efaec142cd5bb6cf)), closes [#25894](https://github.com/ionic-team/ionic-framework/issues/25894) [#25708](https://github.com/ionic-team/ionic-framework/issues/25708)
|
||||
* **dependencies:** latest patch is installed ([#26148](https://github.com/ionic-team/ionic-framework/issues/26148)) ([74be79e](https://github.com/ionic-team/ionic-framework/commit/74be79e9d81fd5431ae2fc442fd6387cf37b2015)), closes [#26137](https://github.com/ionic-team/ionic-framework/issues/26137)
|
||||
* **many:** haptics only fire on supported platforms ([#26130](https://github.com/ionic-team/ionic-framework/issues/26130)) ([d4d569a](https://github.com/ionic-team/ionic-framework/commit/d4d569ac09ab25ab5a490825cf1fc655fe97bb87)), closes [#26109](https://github.com/ionic-team/ionic-framework/issues/26109)
|
||||
* **react:** inline overlays can be conditionally rendered ([#26111](https://github.com/ionic-team/ionic-framework/issues/26111)) ([8ec350a](https://github.com/ionic-team/ionic-framework/commit/8ec350ae652095ae29e2f02a7f105cb709a72583)), closes [#25590](https://github.com/ionic-team/ionic-framework/issues/25590)
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
## [6.3.2](https://github.com/ionic-team/ionic-framework/compare/v6.3.1...v6.3.2) (2022-10-17)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* **datetime:** header renders correct date ([#26120](https://github.com/ionic-team/ionic-framework/issues/26120)) ([04df45a](https://github.com/ionic-team/ionic-framework/commit/04df45a443e4faeea644daa76dc509fea0d24ca2)), closes [#26116](https://github.com/ionic-team/ionic-framework/issues/26116)
|
||||
* **datetime:** selecting days updates value ([#26121](https://github.com/ionic-team/ionic-framework/issues/26121)) ([d76a24d](https://github.com/ionic-team/ionic-framework/commit/d76a24dd9e485a2f3cc517231bbb1dab51fa1fd3))
|
||||
* **modal:** sheet modal dismisses correctly ([#26110](https://github.com/ionic-team/ionic-framework/issues/26110)) ([256b03f](https://github.com/ionic-team/ionic-framework/commit/256b03f12a57c2b5904d9017e4fa93b11eea8fc7)), closes [#26108](https://github.com/ionic-team/ionic-framework/issues/26108)
|
||||
* **vue:** routing components define child components ([#26107](https://github.com/ionic-team/ionic-framework/issues/26107)) ([d60973b](https://github.com/ionic-team/ionic-framework/commit/d60973b2449b29a982b752a98b10d2b043ecff2f))
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
## [6.3.1](https://github.com/ionic-team/ionic-framework/compare/v6.3.0...v6.3.1) (2022-10-12)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
@@ -3,7 +3,35 @@
|
||||
All notable changes to this project will be documented in this file.
|
||||
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
|
||||
|
||||
## [6.3.1-nightly.20221011](https://github.com/ionic-team/ionic/compare/v6.3.0...v6.3.1-nightly.20221011) (2022-10-11)
|
||||
## [6.3.4](https://github.com/ionic-team/ionic/compare/v6.3.3...v6.3.4) (2022-11-02)
|
||||
|
||||
**Note:** Version bump only for package @ionic/angular
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
## [6.3.3](https://github.com/ionic-team/ionic/compare/v6.3.2...v6.3.3) (2022-10-26)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* **datetime:** empty string is treated as no value ([#26131](https://github.com/ionic-team/ionic/issues/26131)) ([51ab5f6](https://github.com/ionic-team/ionic/commit/51ab5f67b50013c0ed8ca3160d6dfc56bc269f2a)), closes [#26116](https://github.com/ionic-team/ionic/issues/26116)
|
||||
* **dependencies:** latest patch is installed ([#26148](https://github.com/ionic-team/ionic/issues/26148)) ([74be79e](https://github.com/ionic-team/ionic/commit/74be79e9d81fd5431ae2fc442fd6387cf37b2015)), closes [#26137](https://github.com/ionic-team/ionic/issues/26137)
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
## [6.3.2](https://github.com/ionic-team/ionic/compare/v6.3.1...v6.3.2) (2022-10-17)
|
||||
|
||||
**Note:** Version bump only for package @ionic/angular
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
## [6.3.1](https://github.com/ionic-team/ionic/compare/v6.3.0...v6.3.1) (2022-10-12)
|
||||
|
||||
**Note:** Version bump only for package @ionic/angular
|
||||
|
||||
|
||||
18
angular/package-lock.json
generated
@@ -1,15 +1,15 @@
|
||||
{
|
||||
"name": "@ionic/angular",
|
||||
"version": "6.3.1-nightly.20221011",
|
||||
"version": "6.3.4",
|
||||
"lockfileVersion": 2,
|
||||
"requires": true,
|
||||
"packages": {
|
||||
"": {
|
||||
"name": "@ionic/angular",
|
||||
"version": "6.3.1-nightly.20221011",
|
||||
"version": "6.3.4",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@ionic/core": "6.3.1-nightly.20221011",
|
||||
"@ionic/core": "^6.3.4",
|
||||
"jsonc-parser": "^3.0.0",
|
||||
"tslib": "^2.0.0"
|
||||
},
|
||||
@@ -1023,9 +1023,9 @@
|
||||
"dev": true
|
||||
},
|
||||
"node_modules/@ionic/core": {
|
||||
"version": "6.3.0",
|
||||
"resolved": "https://registry.npmjs.org/@ionic/core/-/core-6.3.0.tgz",
|
||||
"integrity": "sha512-6MR0hOdIM6sQyZyXez3/jWAnHScrZKaQxzGT2XiXXIpBrKztNdeAhqDLXoxbDU1PLyDnXXPWBzT6xZ698gG67g==",
|
||||
"version": "6.3.4",
|
||||
"resolved": "https://registry.npmjs.org/@ionic/core/-/core-6.3.4.tgz",
|
||||
"integrity": "sha512-3EnKqFdon7Im8JNvuPoq/iGyYK7hskdb9u5hlQE0fHU/9Q0DvFVh17QTq1sQjXntoJovfRhaPJhG+kvZK3mVAQ==",
|
||||
"dependencies": {
|
||||
"@stencil/core": "^2.18.0",
|
||||
"ionicons": "^6.0.3",
|
||||
@@ -7951,9 +7951,9 @@
|
||||
"dev": true
|
||||
},
|
||||
"@ionic/core": {
|
||||
"version": "6.3.0",
|
||||
"resolved": "https://registry.npmjs.org/@ionic/core/-/core-6.3.0.tgz",
|
||||
"integrity": "sha512-6MR0hOdIM6sQyZyXez3/jWAnHScrZKaQxzGT2XiXXIpBrKztNdeAhqDLXoxbDU1PLyDnXXPWBzT6xZ698gG67g==",
|
||||
"version": "6.3.4",
|
||||
"resolved": "https://registry.npmjs.org/@ionic/core/-/core-6.3.4.tgz",
|
||||
"integrity": "sha512-3EnKqFdon7Im8JNvuPoq/iGyYK7hskdb9u5hlQE0fHU/9Q0DvFVh17QTq1sQjXntoJovfRhaPJhG+kvZK3mVAQ==",
|
||||
"requires": {
|
||||
"@stencil/core": "^2.18.0",
|
||||
"ionicons": "^6.0.3",
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@ionic/angular",
|
||||
"version": "6.3.1-nightly.20221011",
|
||||
"version": "6.3.4",
|
||||
"description": "Angular specific wrappers for @ionic/core",
|
||||
"keywords": [
|
||||
"ionic",
|
||||
@@ -45,7 +45,7 @@
|
||||
"validate": "npm i && npm run lint && npm run test && npm run build"
|
||||
},
|
||||
"dependencies": {
|
||||
"@ionic/core": "6.3.1-nightly.20221011",
|
||||
"@ionic/core": "^6.3.4",
|
||||
"jsonc-parser": "^3.0.0",
|
||||
"tslib": "^2.0.0"
|
||||
},
|
||||
|
||||
@@ -19,7 +19,7 @@ export class ValueAccessor implements ControlValueAccessor, AfterViewInit, OnDes
|
||||
|
||||
writeValue(value: any): void {
|
||||
/**
|
||||
* TODO for Ionic 6:
|
||||
* TODO FW-2646
|
||||
* Change `value == null ? '' : value;`
|
||||
* to `value`. This was a fix for IE9, but IE9
|
||||
* is no longer supported; however, this change
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
|
||||
import * as d from './proxies';
|
||||
|
||||
export const DIRECTIVES = [
|
||||
@@ -76,5 +77,5 @@ export const DIRECTIVES = [
|
||||
d.IonThumbnail,
|
||||
d.IonTitle,
|
||||
d.IonToggle,
|
||||
d.IonToolbar,
|
||||
d.IonToolbar
|
||||
];
|
||||
|
||||
@@ -30,7 +30,7 @@ export class FormComponent {
|
||||
formControl.markAsTouched();
|
||||
}
|
||||
|
||||
onSubmit(_ev) {
|
||||
onSubmit() {
|
||||
this.submitted = 'true';
|
||||
}
|
||||
|
||||
|
||||
@@ -30,7 +30,7 @@ export class FormComponent {
|
||||
formControl.markAsTouched();
|
||||
}
|
||||
|
||||
onSubmit(_ev) {
|
||||
onSubmit() {
|
||||
this.submitted = 'true';
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,9 @@
|
||||
describe('Routing with Standalone Components', () => {
|
||||
beforeEach(() => {
|
||||
cy.visit('/version-test/standalone');
|
||||
});
|
||||
|
||||
it('should render the component', () => {
|
||||
cy.get('ion-content').contains('This is a standalone component rendered from a route.');
|
||||
});
|
||||
});
|
||||
27969
angular/test/apps/ng15/package-lock.json
generated
Normal file
68
angular/test/apps/ng15/package.json
Normal file
@@ -0,0 +1,68 @@
|
||||
{
|
||||
"name": "ionic-angular-test-app",
|
||||
"version": "0.0.0",
|
||||
"private": true,
|
||||
"scripts": {
|
||||
"ng": "ng",
|
||||
"start": "ng serve",
|
||||
"sync:build": "sh scripts/build-ionic.sh",
|
||||
"sync": "sh scripts/sync.sh",
|
||||
"build": "ng build --configuration production --no-progress",
|
||||
"lint": "ng lint",
|
||||
"postinstall": "ngcc",
|
||||
"serve:ssr": "node dist/test-app/server/main.js",
|
||||
"build:ssr": "ng build --prod && ng run test-app:server:production",
|
||||
"dev:ssr": "ng run test-app:serve-ssr",
|
||||
"prerender": "ng run test-app:prerender",
|
||||
"cy.open": "cypress open",
|
||||
"cy.run": "cypress run",
|
||||
"test": "concurrently \"npm run start -- --configuration production\" \"wait-on http-get://localhost:4200 && npm run cy.run\" --kill-others --success first",
|
||||
"test.watch": "concurrently \"npm run start\" \"wait-on http-get://localhost:4200 && npm run cy.open\" --kill-others --success first"
|
||||
},
|
||||
"dependencies": {
|
||||
"@angular/animations": "^15.0.0-rc.1",
|
||||
"@angular/common": "^15.0.0-rc.1",
|
||||
"@angular/compiler": "^15.0.0-rc.1",
|
||||
"@angular/core": "^15.0.0-rc.1",
|
||||
"@angular/forms": "^15.0.0-rc.1",
|
||||
"@angular/platform-browser": "^15.0.0-rc.1",
|
||||
"@angular/platform-browser-dynamic": "^15.0.0-rc.1",
|
||||
"@angular/platform-server": "^15.0.0-rc.1",
|
||||
"@angular/router": "^15.0.0-rc.1",
|
||||
"@ionic/angular": "^6.1.15",
|
||||
"@ionic/angular-server": "^6.1.15",
|
||||
"@nguniversal/express-engine": "^14.0.3",
|
||||
"angular-in-memory-web-api": "^0.11.0",
|
||||
"core-js": "^2.6.11",
|
||||
"express": "^4.15.2",
|
||||
"rxjs": "~7.5.0",
|
||||
"tslib": "^2.3.0",
|
||||
"typescript-eslint-language-service": "^4.1.5",
|
||||
"zone.js": "~0.11.4"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@angular-devkit/build-angular": "^15.0.0-rc.1",
|
||||
"@angular-eslint/builder": "^14.0.2",
|
||||
"@angular-eslint/eslint-plugin": "^14.0.2",
|
||||
"@angular-eslint/eslint-plugin-template": "^14.0.2",
|
||||
"@angular-eslint/schematics": "^14.0.2",
|
||||
"@angular-eslint/template-parser": "^14.0.2",
|
||||
"@angular/cli": "^15.0.0-rc.1",
|
||||
"@angular/compiler-cli": "^15.0.0-rc.1",
|
||||
"@angular/language-service": "^15.0.0-rc.1",
|
||||
"@nguniversal/builders": "^15.0.0-next.0",
|
||||
"@types/express": "^4.17.7",
|
||||
"@types/node": "^12.12.54",
|
||||
"@typescript-eslint/eslint-plugin": "4.28.2",
|
||||
"@typescript-eslint/parser": "4.28.2",
|
||||
"concurrently": "^6.0.0",
|
||||
"cypress": "^10.2.0",
|
||||
"eslint": "^7.26.0",
|
||||
"ts-loader": "^6.2.2",
|
||||
"ts-node": "^8.3.0",
|
||||
"typescript": "~4.8.4",
|
||||
"wait-on": "^5.2.1",
|
||||
"webpack": "^5.61.0",
|
||||
"webpack-cli": "^4.9.2"
|
||||
}
|
||||
}
|
||||
3
angular/test/apps/ng15/src/app/app.component.html
Normal file
@@ -0,0 +1,3 @@
|
||||
<ion-app>
|
||||
<ion-router-outlet [environmentInjector]="environmentInjector"></ion-router-outlet>
|
||||
</ion-app>
|
||||
11
angular/test/apps/ng15/src/app/app.component.ts
Normal file
@@ -0,0 +1,11 @@
|
||||
import { Component, EnvironmentInjector } from '@angular/core';
|
||||
|
||||
@Component({
|
||||
selector: 'app-root',
|
||||
templateUrl: './app.component.html',
|
||||
styleUrls: ['./app.component.css']
|
||||
})
|
||||
export class AppComponent {
|
||||
|
||||
constructor(public environmentInjector: EnvironmentInjector) { }
|
||||
}
|
||||
@@ -0,0 +1,4 @@
|
||||
<ion-content>
|
||||
<p>This is a standalone component rendered from a route.</p>
|
||||
<ion-button routerLink="/">Return home</ion-button>
|
||||
</ion-content>
|
||||
@@ -0,0 +1,12 @@
|
||||
import { Component } from "@angular/core";
|
||||
import { RouterModule } from "@angular/router";
|
||||
|
||||
import { IonicModule } from '@ionic/angular';
|
||||
|
||||
@Component({
|
||||
selector: 'app-standalone',
|
||||
templateUrl: './standalone.component.html',
|
||||
standalone: true,
|
||||
imports: [IonicModule, RouterModule]
|
||||
})
|
||||
export class StandaloneComponent { }
|
||||
@@ -0,0 +1,15 @@
|
||||
import { NgModule } from "@angular/core";
|
||||
import { RouterModule } from "@angular/router";
|
||||
|
||||
@NgModule({
|
||||
imports: [
|
||||
RouterModule.forChild([
|
||||
{
|
||||
path: 'standalone',
|
||||
loadComponent: () => import('./standalone/standalone.component').then(m => m.StandaloneComponent)
|
||||
}
|
||||
])
|
||||
],
|
||||
exports: [RouterModule]
|
||||
})
|
||||
export class VersionTestRoutingModule { }
|
||||
35
angular/test/apps/ng15/tsconfig.json
Normal file
@@ -0,0 +1,35 @@
|
||||
{
|
||||
"compileOnSave": false,
|
||||
"compilerOptions": {
|
||||
"outDir": "./dist/out-tsc",
|
||||
"forceConsistentCasingInFileNames": true,
|
||||
"strict": true,
|
||||
"noImplicitOverride": true,
|
||||
"noPropertyAccessFromIndexSignature": true,
|
||||
"noImplicitReturns": true,
|
||||
"noFallthroughCasesInSwitch": true,
|
||||
"sourceMap": true,
|
||||
"declaration": false,
|
||||
"downlevelIteration": true,
|
||||
"experimentalDecorators": true,
|
||||
"moduleResolution": "node",
|
||||
"importHelpers": true,
|
||||
"target": "ES2022",
|
||||
"module": "es2020",
|
||||
"emitDecoratorMetadata": true,
|
||||
"typeRoots": ["node_modules/@types"],
|
||||
"lib": ["es2020", "dom"],
|
||||
"plugins": [
|
||||
{
|
||||
"name": "typescript-eslint-language-service"
|
||||
}
|
||||
],
|
||||
"useDefineForClassFields": false
|
||||
},
|
||||
"angularCompilerOptions": {
|
||||
"enableI18nLegacyMessageIdFormat": false,
|
||||
"strictInjectionParameters": true,
|
||||
"strictInputAccessModifiers": true,
|
||||
"strictTemplates": true
|
||||
}
|
||||
}
|
||||
28
angular/test/base/e2e/src/output-target.spec.ts
Normal file
@@ -0,0 +1,28 @@
|
||||
describe('Angular Output Target', () => {
|
||||
beforeEach(() => {
|
||||
cy.visit('/output-target');
|
||||
});
|
||||
|
||||
it('should emit one event per emission', () => {
|
||||
/**
|
||||
* Angular @Output() events aren't actual DOM events,
|
||||
* instead they are an "EventEmitter" (RxJS Subject)
|
||||
* that emits a change.
|
||||
*
|
||||
* In the Angular output target, we manually create
|
||||
* a RxJS Subject (EventEmitter) for each DOM event,
|
||||
* so that developers can use the same binding syntax
|
||||
* and have the expected behavior that Angular events
|
||||
* do not bubble up the DOM tree.
|
||||
*
|
||||
* We additionally "trick" Angular by creating
|
||||
* @Output decorated properties for each DOM event
|
||||
* on the component proxy class and manually clearing
|
||||
* the decorated metadata. This allows Angular to
|
||||
* not add its own event listener and cause duplicate
|
||||
* event emissions for the web component events.
|
||||
*/
|
||||
cy.get('#ionChangeInput').type('a');
|
||||
cy.get('#ionChangeEmittedCount').should('have.text', '1');
|
||||
});
|
||||
});
|
||||
@@ -5,7 +5,7 @@ import { Component } from '@angular/core';
|
||||
templateUrl: './accordion-modal.component.html',
|
||||
})
|
||||
export class AccordionModalComponent {
|
||||
modal: HTMLIonModalElement;
|
||||
modal!: HTMLIonModalElement;
|
||||
|
||||
constructor() {}
|
||||
}
|
||||
|
||||
@@ -73,6 +73,10 @@ const routes: Routes = [
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
path: 'output-target',
|
||||
loadChildren: () => import('./output-target/output-target.module').then(m => m.OutputTargetModule)
|
||||
}
|
||||
];
|
||||
|
||||
@NgModule({
|
||||
|
||||
@@ -7,7 +7,7 @@
|
||||
</ion-header>
|
||||
|
||||
<ion-content>
|
||||
<form [formGroup]="profileForm" (ngSubmit)="onSubmit($event)">
|
||||
<form [formGroup]="profileForm" (ngSubmit)="onSubmit()">
|
||||
<ion-list>
|
||||
|
||||
<ion-item>
|
||||
|
||||
@@ -27,10 +27,12 @@ export class FormComponent {
|
||||
|
||||
setTouched() {
|
||||
const formControl = this.profileForm.get('input');
|
||||
formControl.markAsTouched();
|
||||
if (formControl) {
|
||||
formControl.markAsTouched();
|
||||
}
|
||||
}
|
||||
|
||||
onSubmit(_ev) {
|
||||
onSubmit() {
|
||||
this.submitted = 'true';
|
||||
}
|
||||
|
||||
|
||||
@@ -6,12 +6,12 @@ import { Component } from '@angular/core';
|
||||
})
|
||||
export class InputsComponent {
|
||||
|
||||
datetime = '1994-03-15';
|
||||
input = 'some text';
|
||||
datetime? = '1994-03-15';
|
||||
input? = 'some text';
|
||||
checkbox = true;
|
||||
toggle = true;
|
||||
select = 'nes';
|
||||
range = 10;
|
||||
select? = 'nes';
|
||||
range? = 10;
|
||||
changes = 0;
|
||||
|
||||
setValues() {
|
||||
|
||||
@@ -8,7 +8,7 @@ import { ModalController, NavParams, IonNav, ViewWillLeave, ViewDidEnter, ViewDi
|
||||
})
|
||||
export class ModalExampleComponent implements OnInit, ViewWillLeave, ViewDidEnter, ViewWillLeave, ViewDidLeave {
|
||||
|
||||
@Input() value: string;
|
||||
@Input() value?: string;
|
||||
|
||||
form = new UntypedFormGroup({
|
||||
select: new UntypedFormControl([])
|
||||
@@ -21,7 +21,7 @@ export class ModalExampleComponent implements OnInit, ViewWillLeave, ViewDidEnte
|
||||
willLeave = 0;
|
||||
didLeave = 0;
|
||||
|
||||
modal: HTMLElement;
|
||||
modal!: HTMLElement;
|
||||
|
||||
constructor(
|
||||
private modalCtrl: ModalController,
|
||||
|
||||
@@ -0,0 +1,17 @@
|
||||
import { NgModule } from "@angular/core";
|
||||
import { RouterModule } from "@angular/router";
|
||||
|
||||
import { OutputTargetComponent } from "./output-target.component";
|
||||
|
||||
@NgModule({
|
||||
imports: [
|
||||
RouterModule.forChild([
|
||||
{
|
||||
path: "",
|
||||
component: OutputTargetComponent
|
||||
}
|
||||
])
|
||||
],
|
||||
exports: [RouterModule]
|
||||
})
|
||||
export class OutputTargetRoutingModule { }
|
||||
@@ -0,0 +1,11 @@
|
||||
<ion-content>
|
||||
<p>This test template verifies key behaviors in the <code>@stencil/angular-output-target</code>.</p>
|
||||
|
||||
<ion-list>
|
||||
<ion-item>
|
||||
<ion-label>Events are emitted once</ion-label>
|
||||
<ion-input id="ionChangeInput" type="text" (ionChange)="onIonChange()"></ion-input>
|
||||
<p id="ionChangeEmittedCount">{{ ionChangeEmittedCount }}</p>
|
||||
</ion-item>
|
||||
</ion-list>
|
||||
</ion-content>
|
||||
@@ -0,0 +1,15 @@
|
||||
import { Component } from "@angular/core";
|
||||
|
||||
@Component({
|
||||
selector: "app-output-target",
|
||||
templateUrl: "./output-target.component.html",
|
||||
})
|
||||
export class OutputTargetComponent {
|
||||
|
||||
ionChangeEmittedCount = 0;
|
||||
|
||||
onIonChange() {
|
||||
this.ionChangeEmittedCount++;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
import { NgModule } from "@angular/core";
|
||||
import { IonicModule } from "@ionic/angular";
|
||||
|
||||
import { OutputTargetRoutingModule } from "./output-target-routing.module";
|
||||
import { OutputTargetComponent } from "./output-target.component";
|
||||
|
||||
@NgModule({
|
||||
imports: [IonicModule, OutputTargetRoutingModule],
|
||||
declarations: [OutputTargetComponent]
|
||||
})
|
||||
export class OutputTargetModule { }
|
||||
@@ -1,5 +1,7 @@
|
||||
import { Component } from "@angular/core";
|
||||
|
||||
import { IonPopover } from "@ionic/angular";
|
||||
|
||||
/**
|
||||
* Validates that inline popovers will correctly display
|
||||
* dynamic contents that are updated after the modal is
|
||||
@@ -13,7 +15,7 @@ export class PopoverInlineComponent {
|
||||
|
||||
items: string[] = [];
|
||||
|
||||
openPopover(popover: HTMLIonPopoverElement) {
|
||||
openPopover(popover: IonPopover) {
|
||||
popover.present();
|
||||
|
||||
setTimeout(() => {
|
||||
|
||||
@@ -16,9 +16,9 @@ export class ProvidersComponent {
|
||||
isResumed = false;
|
||||
isPaused = false;
|
||||
isResized = false;
|
||||
isTesting: boolean = undefined;
|
||||
isDesktop: boolean = undefined;
|
||||
isMobile: boolean = undefined;
|
||||
isTesting?: boolean = undefined;
|
||||
isDesktop?: boolean = undefined;
|
||||
isMobile?: boolean = undefined;
|
||||
keyboardHeight = 0;
|
||||
queryParams = '';
|
||||
|
||||
|
||||
@@ -12,7 +12,7 @@ export class RouterLinkPageComponent implements OnInit, ViewWillLeave, ViewDidEn
|
||||
didEnter = 0;
|
||||
willLeave = 0;
|
||||
didLeave = 0;
|
||||
canGoBack: boolean = null;
|
||||
canGoBack: boolean | null | undefined = null;
|
||||
|
||||
constructor(
|
||||
private ionRouterOutlet: IonRouterOutlet
|
||||
|
||||
@@ -6,11 +6,11 @@ import { IonSlides } from '@ionic/angular';
|
||||
templateUrl: './slides.component.html',
|
||||
})
|
||||
export class SlidesComponent implements AfterViewInit {
|
||||
@ViewChild(IonSlides, { static: true }) slides: IonSlides;
|
||||
@ViewChild(IonSlides, { static: true }) slides!: IonSlides;
|
||||
|
||||
slideIndex = 0;
|
||||
slideIndex2 = 0;
|
||||
slidesData = [];
|
||||
slidesData: string[] = [];
|
||||
|
||||
constructor() { }
|
||||
|
||||
|
||||
@@ -7,7 +7,7 @@ import { NavController } from '@ionic/angular';
|
||||
templateUrl: './tabs-tab1-nested.component.html',
|
||||
})
|
||||
export class TabsTab1NestedComponent implements OnInit {
|
||||
id = '';
|
||||
id: string | null = '';
|
||||
constructor(
|
||||
private route: ActivatedRoute,
|
||||
public navCtrl: NavController
|
||||
@@ -18,6 +18,9 @@ export class TabsTab1NestedComponent implements OnInit {
|
||||
}
|
||||
|
||||
next() {
|
||||
if (this.id === null) {
|
||||
return '1';
|
||||
}
|
||||
return parseInt(this.id, 10) + 1;
|
||||
}
|
||||
|
||||
|
||||
@@ -9,13 +9,13 @@ import { IonTabBar } from '@ionic/angular';
|
||||
export class TabsComponent {
|
||||
tabsDidChangeCounter = 0;
|
||||
tabsDidChangeEvent = '';
|
||||
tabsDidChangeSelectedTab = '';
|
||||
tabsDidChangeSelectedTab? = '';
|
||||
|
||||
tabsWillChangeCounter = 0;
|
||||
tabsWillChangeEvent = '';
|
||||
tabsWillChangeSelectedTab = '';
|
||||
tabsWillChangeSelectedTab? = '';
|
||||
|
||||
@ViewChild(IonTabBar) tabBar: IonTabBar;
|
||||
@ViewChild(IonTabBar) tabBar!: IonTabBar;
|
||||
|
||||
tabChanged(ev: { tab: string }) {
|
||||
console.log('ionTabsDidChange', this.tabBar.selectedTab);
|
||||
|
||||
@@ -7,11 +7,11 @@ import { IonTabs, IonButton, IonSlides, IonSlide } from '@ionic/angular';
|
||||
})
|
||||
export class ViewChildComponent implements AfterViewInit {
|
||||
|
||||
@ViewChild(IonSlides, { static: true }) slides: IonSlides;
|
||||
@ViewChild(IonButton, { static: true }) button: IonButton;
|
||||
@ViewChild(IonTabs, { static: true }) tabs: IonTabs;
|
||||
@ViewChild('div', { static: true }) div: ElementRef;
|
||||
@ViewChild('slide', { static: true }) slide: IonSlide;
|
||||
@ViewChild(IonSlides, { static: true }) slides!: IonSlides;
|
||||
@ViewChild(IonButton, { static: true }) button!: IonButton;
|
||||
@ViewChild(IonTabs, { static: true }) tabs!: IonTabs;
|
||||
@ViewChild('div', { static: true }) div!: ElementRef;
|
||||
@ViewChild('slide', { static: true }) slide!: IonSlide;
|
||||
|
||||
ngAfterViewInit() {
|
||||
const loaded = !!(this.slides && this.button && this.tabs && this.div && this.slide);
|
||||
|
||||
@@ -14,7 +14,7 @@ export class VirtualScrollDetailComponent implements OnInit, ViewWillEnter, View
|
||||
willLeave = 0;
|
||||
didLeave = 0;
|
||||
|
||||
itemNu = 'none';
|
||||
itemNu: string | null = 'none';
|
||||
|
||||
constructor(private route: ActivatedRoute) {}
|
||||
|
||||
|
||||
@@ -6,7 +6,7 @@ import { Component, OnInit, NgZone, Input } from '@angular/core';
|
||||
})
|
||||
export class VirtualScrollInnerComponent implements OnInit {
|
||||
|
||||
@Input() value: string;
|
||||
@Input() value?: string;
|
||||
onInit = 0;
|
||||
|
||||
ngOnInit() {
|
||||
|
||||
@@ -8,7 +8,7 @@ import { IonVirtualScroll } from '@ionic/angular';
|
||||
})
|
||||
export class VirtualScrollComponent {
|
||||
|
||||
@ViewChild(IonVirtualScroll, { static: true }) virtualScroll: IonVirtualScroll;
|
||||
@ViewChild(IonVirtualScroll, { static: true }) virtualScroll!: IonVirtualScroll;
|
||||
|
||||
items = Array.from({length: 100}, (_, i) => ({ name: `${i}`, checked: true}));
|
||||
|
||||
@@ -18,12 +18,14 @@ export class VirtualScrollComponent {
|
||||
if ((index % 10) === 0) {
|
||||
return `Header ${index}`;
|
||||
}
|
||||
return '';
|
||||
}
|
||||
|
||||
myFooterFn: HeaderFn = (_, index) => {
|
||||
if ((index % 5) === 0) {
|
||||
return `Footer ${index}`;
|
||||
}
|
||||
return '';
|
||||
}
|
||||
|
||||
addItems() {
|
||||
|
||||
@@ -3,7 +3,47 @@
|
||||
All notable changes to this project will be documented in this file.
|
||||
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
|
||||
|
||||
## [6.3.1-nightly.20221011](https://github.com/ionic-team/ionic/compare/v6.3.0...v6.3.1-nightly.20221011) (2022-10-11)
|
||||
## [6.3.4](https://github.com/ionic-team/ionic/compare/v6.3.3...v6.3.4) (2022-11-02)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* **datetime:** account for allowed values when setting default date ([#26093](https://github.com/ionic-team/ionic/issues/26093)) ([3745083](https://github.com/ionic-team/ionic/commit/3745083b7cdf8651d1c7f5f1a0214b487ea286ca)), closes [#24722](https://github.com/ionic-team/ionic/issues/24722)
|
||||
* **modal, popover:** remove trigger click listeners when overlay is unmounted ([#26167](https://github.com/ionic-team/ionic/issues/26167)) ([1320948](https://github.com/ionic-team/ionic/commit/1320948b245be3defe8610b9f049e781a4903a6e))
|
||||
* **modal:** buttons are highlighted with VoiceOver ([#26180](https://github.com/ionic-team/ionic/issues/26180)) ([1504b88](https://github.com/ionic-team/ionic/commit/1504b8888d6f79ea382935ed52b104b9f841d150)), closes [#26156](https://github.com/ionic-team/ionic/issues/26156)
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
## [6.3.3](https://github.com/ionic-team/ionic/compare/v6.3.2...v6.3.3) (2022-10-26)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* **datetime:** empty string is treated as no value ([#26131](https://github.com/ionic-team/ionic/issues/26131)) ([51ab5f6](https://github.com/ionic-team/ionic/commit/51ab5f67b50013c0ed8ca3160d6dfc56bc269f2a)), closes [#26116](https://github.com/ionic-team/ionic/issues/26116)
|
||||
* **datetime:** preferWheel can now show title ([#26101](https://github.com/ionic-team/ionic/issues/26101)) ([479d56b](https://github.com/ionic-team/ionic/commit/479d56b3b26d45bfd03d4095458c37ed00485c54)), closes [#26095](https://github.com/ionic-team/ionic/issues/26095)
|
||||
* **datetime:** values are adjusted to be in bounds ([#26125](https://github.com/ionic-team/ionic/issues/26125)) ([0548fe8](https://github.com/ionic-team/ionic/commit/0548fe858854f0187e0dfe00efaec142cd5bb6cf)), closes [#25894](https://github.com/ionic-team/ionic/issues/25894) [#25708](https://github.com/ionic-team/ionic/issues/25708)
|
||||
* **many:** haptics only fire on supported platforms ([#26130](https://github.com/ionic-team/ionic/issues/26130)) ([d4d569a](https://github.com/ionic-team/ionic/commit/d4d569ac09ab25ab5a490825cf1fc655fe97bb87)), closes [#26109](https://github.com/ionic-team/ionic/issues/26109)
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
## [6.3.2](https://github.com/ionic-team/ionic/compare/v6.3.1...v6.3.2) (2022-10-17)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* **datetime:** header renders correct date ([#26120](https://github.com/ionic-team/ionic/issues/26120)) ([04df45a](https://github.com/ionic-team/ionic/commit/04df45a443e4faeea644daa76dc509fea0d24ca2)), closes [#26116](https://github.com/ionic-team/ionic/issues/26116)
|
||||
* **datetime:** selecting days updates value ([#26121](https://github.com/ionic-team/ionic/issues/26121)) ([d76a24d](https://github.com/ionic-team/ionic/commit/d76a24dd9e485a2f3cc517231bbb1dab51fa1fd3))
|
||||
* **modal:** sheet modal dismisses correctly ([#26110](https://github.com/ionic-team/ionic/issues/26110)) ([256b03f](https://github.com/ionic-team/ionic/commit/256b03f12a57c2b5904d9017e4fa93b11eea8fc7)), closes [#26108](https://github.com/ionic-team/ionic/issues/26108)
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
## [6.3.1](https://github.com/ionic-team/ionic/compare/v6.3.0...v6.3.1) (2022-10-12)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
4
core/package-lock.json
generated
@@ -1,12 +1,12 @@
|
||||
{
|
||||
"name": "@ionic/core",
|
||||
"version": "6.3.1-nightly.20221011",
|
||||
"version": "6.3.4",
|
||||
"lockfileVersion": 2,
|
||||
"requires": true,
|
||||
"packages": {
|
||||
"": {
|
||||
"name": "@ionic/core",
|
||||
"version": "6.3.1-nightly.20221011",
|
||||
"version": "6.3.4",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@stencil/core": "^2.18.0",
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@ionic/core",
|
||||
"version": "6.3.1-nightly.20221011",
|
||||
"version": "6.3.4",
|
||||
"description": "Base components for Ionic",
|
||||
"keywords": [
|
||||
"ionic",
|
||||
@@ -86,7 +86,7 @@
|
||||
"css.sass": "sass --embed-sources src/css:./css",
|
||||
"eslint": "eslint src",
|
||||
"lint": "npm run lint.ts && npm run lint.sass && npm run prettier -- --write",
|
||||
"lint.fix": "npm run lint.ts.fix && npm run lint.sass.fix",
|
||||
"lint.fix": "npm run lint.ts.fix && npm run lint.sass.fix && npm run prettier -- --write",
|
||||
"lint.sass": "stylelint \"src/**/*.scss\"",
|
||||
"lint.sass.fix": "npm run lint.sass -- --fix",
|
||||
"lint.ts": "npm run eslint",
|
||||
|
||||
@@ -1,11 +1,11 @@
|
||||
import type { PlaywrightTestConfig } from '@playwright/test';
|
||||
import type { PlaywrightTestConfig, PlaywrightTestOptions, PlaywrightWorkerOptions, Project } from '@playwright/test';
|
||||
import { devices, expect } from '@playwright/test';
|
||||
|
||||
import { matchers } from './src/utils/test/playwright';
|
||||
|
||||
expect.extend(matchers);
|
||||
|
||||
const projects = [
|
||||
const projects: Project<PlaywrightTestOptions, PlaywrightWorkerOptions>[] = [
|
||||
{
|
||||
/**
|
||||
* This is really just desktop Firefox
|
||||
@@ -24,10 +24,6 @@ const projects = [
|
||||
width: 393,
|
||||
height: 727
|
||||
},
|
||||
screen: {
|
||||
width: 393,
|
||||
height: 851
|
||||
}
|
||||
},
|
||||
},
|
||||
{
|
||||
@@ -49,7 +45,7 @@ const projects = [
|
||||
const modes = ['ios', 'md'];
|
||||
|
||||
const generateProjects = () => {
|
||||
const projectsWithMetadata = [];
|
||||
const projectsWithMetadata: Project<PlaywrightTestOptions, PlaywrightWorkerOptions>[] = [];
|
||||
|
||||
modes.forEach(mode => {
|
||||
projects.forEach(project => {
|
||||
@@ -105,9 +101,6 @@ const config: PlaywrightTestConfig = {
|
||||
use: {
|
||||
/* Maximum time each action such as `click()` can take. Defaults to 0 (no limit). */
|
||||
actionTimeout: 0,
|
||||
/* Base URL to use in actions like `await page.goto('/')`. */
|
||||
// baseURL: 'http://localhost:3000',
|
||||
|
||||
/**
|
||||
* All failed tests should create
|
||||
* a trace file for easier debugging.
|
||||
|
||||
@@ -35,9 +35,12 @@ test.describe('alert: a11y', () => {
|
||||
});
|
||||
|
||||
test('should not have accessibility violations when header and message are defined', async ({ page }) => {
|
||||
const didPresent = await page.spyOnEvent('ionAlertDidPresent');
|
||||
const button = page.locator('#bothHeaders');
|
||||
await button.click();
|
||||
|
||||
await didPresent.next();
|
||||
|
||||
const results = await new AxeBuilder({ page }).analyze();
|
||||
expect(results.violations).toEqual([]);
|
||||
});
|
||||
|
||||
@@ -1,34 +0,0 @@
|
||||
// Roboto Font
|
||||
// Google
|
||||
// Apache License, version 2.0
|
||||
// http://www.apache.org/licenses/LICENSE-2.0.html
|
||||
|
||||
$roboto-font-path: $font-path !default;
|
||||
|
||||
@font-face {
|
||||
font-family: "Roboto";
|
||||
font-style: normal;
|
||||
font-weight: 300;
|
||||
src: local("Roboto Light"), local("Roboto-Light"), url("#{$roboto-font-path}/roboto-light.woff2") format("woff2"), url("#{$roboto-font-path}/roboto-light.woff") format("woff"), url("#{$roboto-font-path}/roboto-light.ttf") format("truetype");
|
||||
}
|
||||
|
||||
@font-face {
|
||||
font-family: "Roboto";
|
||||
font-style: normal;
|
||||
font-weight: 400;
|
||||
src: local("Roboto"), local("Roboto-Regular"), url("#{$roboto-font-path}/roboto-regular.woff2") format("woff2"), url("#{$roboto-font-path}/roboto-regular.woff") format("woff"), url("#{$roboto-font-path}/roboto-regular.ttf") format("truetype");
|
||||
}
|
||||
|
||||
@font-face {
|
||||
font-family: "Roboto";
|
||||
font-style: normal;
|
||||
font-weight: 500;
|
||||
src: local("Roboto Medium"), local("Roboto-Medium"), url("#{$roboto-font-path}/roboto-medium.woff2") format("woff2"), url("#{$roboto-font-path}/roboto-medium.woff") format("woff"), url("#{$roboto-font-path}/roboto-medium.ttf") format("truetype");
|
||||
}
|
||||
|
||||
@font-face {
|
||||
font-family: "Roboto";
|
||||
font-style: normal;
|
||||
font-weight: 700;
|
||||
src: local("Roboto Bold"), local("Roboto-Bold"), url("#{$roboto-font-path}/roboto-bold.woff2") format("woff2"), url("#{$roboto-font-path}/roboto-bold.woff") format("woff"), url("#{$roboto-font-path}/roboto-bold.ttf") format("truetype");
|
||||
}
|
||||
@@ -160,7 +160,8 @@ export class DatetimeButton implements ComponentInterface {
|
||||
* to keep checking if the datetime value is `string` or `string[]`.
|
||||
*/
|
||||
private getParsedDateValues = (value?: string[] | string | null): string[] => {
|
||||
if (value === undefined || value === null) {
|
||||
// TODO FW-2646 Remove value === ''
|
||||
if (value === '' || value === undefined || value === null) {
|
||||
return [];
|
||||
}
|
||||
|
||||
|
||||
@@ -17,6 +17,7 @@ test.describe('datetime-button: switching to correct view', () => {
|
||||
expect(datetime).toHaveJSProperty('presentation', 'date-time');
|
||||
|
||||
await page.locator('#date-button').click();
|
||||
await page.waitForChanges();
|
||||
|
||||
expect(datetime).toHaveJSProperty('presentation', 'date');
|
||||
});
|
||||
@@ -25,6 +26,7 @@ test.describe('datetime-button: switching to correct view', () => {
|
||||
expect(datetime).toHaveJSProperty('presentation', 'date-time');
|
||||
|
||||
await page.locator('#time-button').click();
|
||||
await page.waitForChanges();
|
||||
|
||||
expect(datetime).toHaveJSProperty('presentation', 'time');
|
||||
});
|
||||
|
||||
@@ -36,6 +36,7 @@ import { is24Hour, isLocaleDayPeriodRTL, isMonthFirstLocale, getNumDaysInMonth }
|
||||
import {
|
||||
calculateHourFromAMPM,
|
||||
convertDataToISO,
|
||||
getClosestValidDate,
|
||||
getEndOfWeek,
|
||||
getNextDay,
|
||||
getNextMonth,
|
||||
@@ -96,7 +97,8 @@ export class Datetime implements ComponentInterface {
|
||||
|
||||
private minParts?: any;
|
||||
private maxParts?: any;
|
||||
private todayParts = parseDate(getToday());
|
||||
private todayParts!: DatetimeParts;
|
||||
private defaultParts!: DatetimeParts;
|
||||
|
||||
private prevPresentation: string | null = null;
|
||||
|
||||
@@ -559,13 +561,13 @@ export class Datetime implements ComponentInterface {
|
||||
* may not be set. This function works
|
||||
* by returning the first selected date in
|
||||
* "activePartsClone" and then falling back to
|
||||
* today's DatetimeParts if no active date is selected.
|
||||
* defaultParts if no active date is selected.
|
||||
*/
|
||||
private getDefaultPart = () => {
|
||||
const { activePartsClone, todayParts } = this;
|
||||
private getActivePartsWithFallback = () => {
|
||||
const { activePartsClone, defaultParts } = this;
|
||||
|
||||
const firstPart = Array.isArray(activePartsClone) ? activePartsClone[0] : activePartsClone;
|
||||
return firstPart ?? todayParts;
|
||||
return firstPart ?? defaultParts;
|
||||
};
|
||||
|
||||
private closeParentOverlay = () => {
|
||||
@@ -585,7 +587,7 @@ export class Datetime implements ComponentInterface {
|
||||
};
|
||||
|
||||
private setActiveParts = (parts: DatetimeParts, removeDate = false) => {
|
||||
const { multiple, activePartsClone } = this;
|
||||
const { multiple, minParts, maxParts, activePartsClone } = this;
|
||||
|
||||
/**
|
||||
* When setting the active parts, it is possible
|
||||
@@ -597,7 +599,7 @@ export class Datetime implements ComponentInterface {
|
||||
* Additionally, we need to update the working parts
|
||||
* too in the event that the validated parts are different.
|
||||
*/
|
||||
const validatedParts = validateParts(parts);
|
||||
const validatedParts = validateParts(parts, minParts, maxParts);
|
||||
this.setWorkingParts(validatedParts);
|
||||
|
||||
if (multiple) {
|
||||
@@ -780,24 +782,24 @@ export class Datetime implements ComponentInterface {
|
||||
};
|
||||
|
||||
private processMinParts = () => {
|
||||
const { min, todayParts } = this;
|
||||
const { min, defaultParts } = this;
|
||||
if (min === undefined) {
|
||||
this.minParts = undefined;
|
||||
return;
|
||||
}
|
||||
|
||||
this.minParts = parseMinParts(min, todayParts);
|
||||
this.minParts = parseMinParts(min, defaultParts);
|
||||
};
|
||||
|
||||
private processMaxParts = () => {
|
||||
const { max, todayParts } = this;
|
||||
const { max, defaultParts } = this;
|
||||
|
||||
if (max === undefined) {
|
||||
this.maxParts = undefined;
|
||||
return;
|
||||
}
|
||||
|
||||
this.maxParts = parseMaxParts(max, todayParts);
|
||||
this.maxParts = parseMaxParts(max, defaultParts);
|
||||
};
|
||||
|
||||
private initializeCalendarListener = () => {
|
||||
@@ -1154,8 +1156,11 @@ export class Datetime implements ComponentInterface {
|
||||
}
|
||||
|
||||
private processValue = (value?: string | string[] | null) => {
|
||||
const hasValue = value !== null && value !== undefined;
|
||||
let valueToProcess = parseDate(value ?? getToday());
|
||||
/**
|
||||
* TODO FW-2646 remove value !== ''
|
||||
*/
|
||||
const hasValue = value !== '' && value !== null && value !== undefined;
|
||||
let valueToProcess = hasValue ? parseDate(value) : this.defaultParts;
|
||||
|
||||
const { minParts, maxParts, multiple } = this;
|
||||
if (!multiple && Array.isArray(value)) {
|
||||
@@ -1233,12 +1238,16 @@ export class Datetime implements ComponentInterface {
|
||||
|
||||
this.processMinParts();
|
||||
this.processMaxParts();
|
||||
const hourValues = (this.parsedHourValues = convertToArrayOfNumbers(this.hourValues));
|
||||
const minuteValues = (this.parsedMinuteValues = convertToArrayOfNumbers(this.minuteValues));
|
||||
const monthValues = (this.parsedMonthValues = convertToArrayOfNumbers(this.monthValues));
|
||||
const yearValues = (this.parsedYearValues = convertToArrayOfNumbers(this.yearValues));
|
||||
const dayValues = (this.parsedDayValues = convertToArrayOfNumbers(this.dayValues));
|
||||
|
||||
const todayParts = (this.todayParts = parseDate(getToday()));
|
||||
this.defaultParts = getClosestValidDate(todayParts, monthValues, dayValues, yearValues, hourValues, minuteValues);
|
||||
this.processValue(this.value);
|
||||
this.parsedHourValues = convertToArrayOfNumbers(this.hourValues);
|
||||
this.parsedMinuteValues = convertToArrayOfNumbers(this.minuteValues);
|
||||
this.parsedMonthValues = convertToArrayOfNumbers(this.monthValues);
|
||||
this.parsedYearValues = convertToArrayOfNumbers(this.yearValues);
|
||||
this.parsedDayValues = convertToArrayOfNumbers(this.dayValues);
|
||||
|
||||
this.emitStyle();
|
||||
}
|
||||
|
||||
@@ -1393,7 +1402,9 @@ export class Datetime implements ComponentInterface {
|
||||
}
|
||||
|
||||
private renderCombinedDatePickerColumn() {
|
||||
const { activeParts, workingParts, locale, minParts, maxParts, todayParts, isDateEnabled } = this;
|
||||
const { defaultParts, workingParts, locale, minParts, maxParts, todayParts, isDateEnabled } = this;
|
||||
|
||||
const activePart = this.getActivePartsWithFallback();
|
||||
|
||||
/**
|
||||
* By default, generate a range of 3 months:
|
||||
@@ -1459,12 +1470,12 @@ export class Datetime implements ComponentInterface {
|
||||
|
||||
/**
|
||||
* If we have selected a day already, then default the column
|
||||
* to that value. Otherwise, default it to today.
|
||||
* to that value. Otherwise, set it to the default date.
|
||||
*/
|
||||
const todayString =
|
||||
workingParts.day !== null
|
||||
? `${workingParts.year}-${workingParts.month}-${workingParts.day}`
|
||||
: `${todayParts.year}-${todayParts.month}-${todayParts.day}`;
|
||||
: `${defaultParts.year}-${defaultParts.month}-${defaultParts.day}`;
|
||||
|
||||
return (
|
||||
<ion-picker-column-internal
|
||||
@@ -1489,12 +1500,10 @@ export class Datetime implements ComponentInterface {
|
||||
...findPart,
|
||||
});
|
||||
|
||||
if (!Array.isArray(activeParts)) {
|
||||
this.setActiveParts({
|
||||
...activeParts,
|
||||
...findPart,
|
||||
});
|
||||
}
|
||||
this.setActiveParts({
|
||||
...activePart,
|
||||
...findPart,
|
||||
});
|
||||
|
||||
// We can re-attach the scroll listener after
|
||||
// the working parts have been updated.
|
||||
@@ -1552,7 +1561,7 @@ export class Datetime implements ComponentInterface {
|
||||
|
||||
const shouldRenderYears = forcePresentation !== 'month' && forcePresentation !== 'time';
|
||||
const years = shouldRenderYears
|
||||
? getYearColumnData(this.locale, this.todayParts, this.minParts, this.maxParts, this.parsedYearValues)
|
||||
? getYearColumnData(this.locale, this.defaultParts, this.minParts, this.maxParts, this.parsedYearValues)
|
||||
: [];
|
||||
|
||||
/**
|
||||
@@ -1583,14 +1592,16 @@ export class Datetime implements ComponentInterface {
|
||||
return [];
|
||||
}
|
||||
|
||||
const { activeParts, workingParts } = this;
|
||||
const { workingParts } = this;
|
||||
|
||||
const activePart = this.getActivePartsWithFallback();
|
||||
|
||||
return (
|
||||
<ion-picker-column-internal
|
||||
class="day-column"
|
||||
color={this.color}
|
||||
items={days}
|
||||
value={(workingParts.day !== null ? workingParts.day : this.todayParts.day) ?? undefined}
|
||||
value={(workingParts.day !== null ? workingParts.day : this.defaultParts.day) ?? undefined}
|
||||
onIonChange={(ev: CustomEvent) => {
|
||||
// TODO(FW-1823) Remove this when iOS 14 support is dropped.
|
||||
// Due to a Safari 14 issue we need to destroy
|
||||
@@ -1605,12 +1616,10 @@ export class Datetime implements ComponentInterface {
|
||||
day: ev.detail.value,
|
||||
});
|
||||
|
||||
if (!Array.isArray(activeParts)) {
|
||||
this.setActiveParts({
|
||||
...activeParts,
|
||||
day: ev.detail.value,
|
||||
});
|
||||
}
|
||||
this.setActiveParts({
|
||||
...activePart,
|
||||
day: ev.detail.value,
|
||||
});
|
||||
|
||||
// We can re-attach the scroll listener after
|
||||
// the working parts have been updated.
|
||||
@@ -1627,7 +1636,9 @@ export class Datetime implements ComponentInterface {
|
||||
return [];
|
||||
}
|
||||
|
||||
const { activeParts, workingParts } = this;
|
||||
const { workingParts } = this;
|
||||
|
||||
const activePart = this.getActivePartsWithFallback();
|
||||
|
||||
return (
|
||||
<ion-picker-column-internal
|
||||
@@ -1649,12 +1660,10 @@ export class Datetime implements ComponentInterface {
|
||||
month: ev.detail.value,
|
||||
});
|
||||
|
||||
if (!Array.isArray(activeParts)) {
|
||||
this.setActiveParts({
|
||||
...activeParts,
|
||||
month: ev.detail.value,
|
||||
});
|
||||
}
|
||||
this.setActiveParts({
|
||||
...activePart,
|
||||
month: ev.detail.value,
|
||||
});
|
||||
|
||||
// We can re-attach the scroll listener after
|
||||
// the working parts have been updated.
|
||||
@@ -1670,7 +1679,9 @@ export class Datetime implements ComponentInterface {
|
||||
return [];
|
||||
}
|
||||
|
||||
const { activeParts, workingParts } = this;
|
||||
const { workingParts } = this;
|
||||
|
||||
const activePart = this.getActivePartsWithFallback();
|
||||
|
||||
return (
|
||||
<ion-picker-column-internal
|
||||
@@ -1692,12 +1703,10 @@ export class Datetime implements ComponentInterface {
|
||||
year: ev.detail.value,
|
||||
});
|
||||
|
||||
if (!Array.isArray(activeParts)) {
|
||||
this.setActiveParts({
|
||||
...activeParts,
|
||||
year: ev.detail.value,
|
||||
});
|
||||
}
|
||||
this.setActiveParts({
|
||||
...activePart,
|
||||
year: ev.detail.value,
|
||||
});
|
||||
|
||||
// We can re-attach the scroll listener after
|
||||
// the working parts have been updated.
|
||||
@@ -1736,7 +1745,7 @@ export class Datetime implements ComponentInterface {
|
||||
const { workingParts } = this;
|
||||
if (hoursData.length === 0) return [];
|
||||
|
||||
const activePart = this.getDefaultPart();
|
||||
const activePart = this.getActivePartsWithFallback();
|
||||
|
||||
return (
|
||||
<ion-picker-column-internal
|
||||
@@ -1750,12 +1759,10 @@ export class Datetime implements ComponentInterface {
|
||||
hour: ev.detail.value,
|
||||
});
|
||||
|
||||
if (!Array.isArray(activePart)) {
|
||||
this.setActiveParts({
|
||||
...activePart,
|
||||
hour: ev.detail.value,
|
||||
});
|
||||
}
|
||||
this.setActiveParts({
|
||||
...activePart,
|
||||
hour: ev.detail.value,
|
||||
});
|
||||
|
||||
ev.stopPropagation();
|
||||
}}
|
||||
@@ -1766,7 +1773,7 @@ export class Datetime implements ComponentInterface {
|
||||
const { workingParts } = this;
|
||||
if (minutesData.length === 0) return [];
|
||||
|
||||
const activePart = this.getDefaultPart();
|
||||
const activePart = this.getActivePartsWithFallback();
|
||||
|
||||
return (
|
||||
<ion-picker-column-internal
|
||||
@@ -1780,12 +1787,10 @@ export class Datetime implements ComponentInterface {
|
||||
minute: ev.detail.value,
|
||||
});
|
||||
|
||||
if (!Array.isArray(activePart)) {
|
||||
this.setActiveParts({
|
||||
...activePart,
|
||||
minute: ev.detail.value,
|
||||
});
|
||||
}
|
||||
this.setActiveParts({
|
||||
...activePart,
|
||||
minute: ev.detail.value,
|
||||
});
|
||||
|
||||
ev.stopPropagation();
|
||||
}}
|
||||
@@ -1798,7 +1803,7 @@ export class Datetime implements ComponentInterface {
|
||||
return [];
|
||||
}
|
||||
|
||||
const activePart = this.getDefaultPart();
|
||||
const activePart = this.getActivePartsWithFallback();
|
||||
const isDayPeriodRTL = isLocaleDayPeriodRTL(this.locale);
|
||||
|
||||
return (
|
||||
@@ -1816,13 +1821,11 @@ export class Datetime implements ComponentInterface {
|
||||
hour,
|
||||
});
|
||||
|
||||
if (!Array.isArray(activePart)) {
|
||||
this.setActiveParts({
|
||||
...activePart,
|
||||
ampm: ev.detail.value,
|
||||
hour,
|
||||
});
|
||||
}
|
||||
this.setActiveParts({
|
||||
...activePart,
|
||||
ampm: ev.detail.value,
|
||||
hour,
|
||||
});
|
||||
|
||||
ev.stopPropagation();
|
||||
}}
|
||||
@@ -1914,6 +1917,8 @@ export class Datetime implements ComponentInterface {
|
||||
// can free-scroll the calendar.
|
||||
const isWorkingMonth = this.workingParts.month === month && this.workingParts.year === year;
|
||||
|
||||
const activePart = this.getActivePartsWithFallback();
|
||||
|
||||
return (
|
||||
<div
|
||||
// Non-visible months should be hidden from screen readers
|
||||
@@ -1998,7 +2003,7 @@ export class Datetime implements ComponentInterface {
|
||||
);
|
||||
} else {
|
||||
this.setActiveParts({
|
||||
...this.activeParts,
|
||||
...activePart,
|
||||
month,
|
||||
day,
|
||||
year,
|
||||
@@ -2042,7 +2047,7 @@ export class Datetime implements ComponentInterface {
|
||||
|
||||
private renderTimeOverlay() {
|
||||
const use24Hour = is24Hour(this.locale, this.hourCycle);
|
||||
const activePart = this.getDefaultPart();
|
||||
const activePart = this.getActivePartsWithFallback();
|
||||
|
||||
return [
|
||||
<div class="time-header">{this.renderTimeLabel()}</div>,
|
||||
@@ -2106,17 +2111,13 @@ export class Datetime implements ComponentInterface {
|
||||
</ion-popover>,
|
||||
];
|
||||
}
|
||||
private renderCalendarViewHeader() {
|
||||
const hasSlottedTitle = this.el.querySelector('[slot="title"]') !== null;
|
||||
if (!hasSlottedTitle && !this.showDefaultTitle) {
|
||||
return;
|
||||
}
|
||||
|
||||
const { activeParts, titleSelectedDatesFormatter } = this;
|
||||
private getHeaderSelectedDateText() {
|
||||
const { activeParts, multiple, titleSelectedDatesFormatter } = this;
|
||||
const isArray = Array.isArray(activeParts);
|
||||
|
||||
let headerText: string;
|
||||
if (isArray && activeParts.length !== 1) {
|
||||
if (multiple && isArray && activeParts.length !== 1) {
|
||||
headerText = `${activeParts.length} days`; // default/fallback for multiple selection
|
||||
if (titleSelectedDatesFormatter !== undefined) {
|
||||
try {
|
||||
@@ -2127,7 +2128,16 @@ export class Datetime implements ComponentInterface {
|
||||
}
|
||||
} else {
|
||||
// for exactly 1 day selected (multiple set or not), show a formatted version of that
|
||||
headerText = getMonthAndDay(this.locale, this.getDefaultPart());
|
||||
headerText = getMonthAndDay(this.locale, this.getActivePartsWithFallback());
|
||||
}
|
||||
|
||||
return headerText;
|
||||
}
|
||||
|
||||
private renderCalendarViewHeader(showExpandedHeader = true) {
|
||||
const hasSlottedTitle = this.el.querySelector('[slot="title"]') !== null;
|
||||
if (!hasSlottedTitle && !this.showDefaultTitle) {
|
||||
return;
|
||||
}
|
||||
|
||||
return (
|
||||
@@ -2135,7 +2145,7 @@ export class Datetime implements ComponentInterface {
|
||||
<div class="datetime-title">
|
||||
<slot name="title">Select Date</slot>
|
||||
</div>
|
||||
<div class="datetime-selected-date">{headerText}</div>
|
||||
{showExpandedHeader && <div class="datetime-selected-date">{this.getHeaderSelectedDateText()}</div>}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
@@ -2182,7 +2192,7 @@ export class Datetime implements ComponentInterface {
|
||||
*/
|
||||
const hasWheelVariant = presentation === 'date' || presentation === 'date-time' || presentation === 'time-date';
|
||||
if (preferWheel && hasWheelVariant) {
|
||||
return [this.renderWheelView(), this.renderFooter()];
|
||||
return [this.renderCalendarViewHeader(false), this.renderWheelView(), this.renderFooter()];
|
||||
}
|
||||
|
||||
switch (presentation) {
|
||||
|
||||
@@ -72,6 +72,39 @@ test.describe('datetime: selecting a day', () => {
|
||||
|
||||
await expect(activeDay).toHaveText('13');
|
||||
});
|
||||
test('should set both date and time when no value is initially set', async ({ page }) => {
|
||||
await page.setContent(`
|
||||
<ion-datetime locale="en-US" presentation="date-time"></ion-datetime>
|
||||
|
||||
<script>
|
||||
const mockToday = '2022-10-10T16:22';
|
||||
Date = class extends Date {
|
||||
constructor(...args) {
|
||||
if (args.length === 0) {
|
||||
super(mockToday)
|
||||
} else {
|
||||
super(...args);
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
`);
|
||||
|
||||
await page.waitForSelector('.datetime-ready');
|
||||
const datetime = page.locator('ion-datetime');
|
||||
const ionChange = await page.spyOnEvent('ionChange');
|
||||
|
||||
// Oct 1, 2022
|
||||
await page.click('.calendar-day[data-month="10"][data-year="2022"][data-day="1"]');
|
||||
|
||||
await ionChange.next();
|
||||
|
||||
const value = await datetime.evaluate((el: HTMLIonDatetimeElement) => el.value);
|
||||
await expect(typeof value).toBe('string');
|
||||
|
||||
// Check to make sure value includes current time
|
||||
await expect(value!.includes('2022-10-01T16:22')).toBe(true);
|
||||
});
|
||||
});
|
||||
|
||||
test.describe('datetime: confirm date', () => {
|
||||
|
||||
@@ -14,6 +14,7 @@ import {
|
||||
calculateHourFromAMPM,
|
||||
subtractDays,
|
||||
addDays,
|
||||
validateParts,
|
||||
} from '../utils/manipulation';
|
||||
|
||||
describe('addDays()', () => {
|
||||
@@ -487,3 +488,72 @@ describe('getPreviousYear()', () => {
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe('validateParts()', () => {
|
||||
it('should move day in bounds', () => {
|
||||
expect(validateParts({ month: 2, day: 31, year: 2022, hour: 8, minute: 0 })).toEqual({
|
||||
month: 2,
|
||||
day: 28,
|
||||
year: 2022,
|
||||
hour: 8,
|
||||
minute: 0,
|
||||
});
|
||||
});
|
||||
it('should move the hour back in bounds according to the min', () => {
|
||||
expect(
|
||||
validateParts(
|
||||
{ month: 1, day: 1, year: 2022, hour: 8, minute: 0 },
|
||||
{ month: 1, day: 1, year: 2022, hour: 9, minute: 0 }
|
||||
)
|
||||
).toEqual({ month: 1, day: 1, year: 2022, hour: 9, minute: 0 });
|
||||
});
|
||||
it('should move the minute back in bounds according to the min', () => {
|
||||
expect(
|
||||
validateParts(
|
||||
{ month: 1, day: 1, year: 2022, hour: 9, minute: 20 },
|
||||
{ month: 1, day: 1, year: 2022, hour: 9, minute: 30 }
|
||||
)
|
||||
).toEqual({ month: 1, day: 1, year: 2022, hour: 9, minute: 30 });
|
||||
});
|
||||
it('should move the hour and minute back in bounds according to the min', () => {
|
||||
expect(
|
||||
validateParts(
|
||||
{ month: 1, day: 1, year: 2022, hour: 8, minute: 30 },
|
||||
{ month: 1, day: 1, year: 2022, hour: 9, minute: 0 }
|
||||
)
|
||||
).toEqual({ month: 1, day: 1, year: 2022, hour: 9, minute: 0 });
|
||||
});
|
||||
it('should move the hour back in bounds according to the max', () => {
|
||||
expect(
|
||||
validateParts({ month: 1, day: 1, year: 2022, hour: 10, minute: 0 }, undefined, {
|
||||
month: 1,
|
||||
day: 1,
|
||||
year: 2022,
|
||||
hour: 9,
|
||||
minute: 0,
|
||||
})
|
||||
).toEqual({ month: 1, day: 1, year: 2022, hour: 9, minute: 0 });
|
||||
});
|
||||
it('should move the minute back in bounds according to the max', () => {
|
||||
expect(
|
||||
validateParts({ month: 1, day: 1, year: 2022, hour: 9, minute: 40 }, undefined, {
|
||||
month: 1,
|
||||
day: 1,
|
||||
year: 2022,
|
||||
hour: 9,
|
||||
minute: 30,
|
||||
})
|
||||
).toEqual({ month: 1, day: 1, year: 2022, hour: 9, minute: 30 });
|
||||
});
|
||||
it('should move the hour and minute back in bounds according to the max', () => {
|
||||
expect(
|
||||
validateParts({ month: 1, day: 1, year: 2022, hour: 10, minute: 20 }, undefined, {
|
||||
month: 1,
|
||||
day: 1,
|
||||
year: 2022,
|
||||
hour: 9,
|
||||
minute: 30,
|
||||
})
|
||||
).toEqual({ month: 1, day: 1, year: 2022, hour: 9, minute: 30 });
|
||||
});
|
||||
});
|
||||
|
||||
@@ -234,4 +234,53 @@ test.describe('datetime: minmax', () => {
|
||||
);
|
||||
await expect(hourPickerItems).toHaveText(['12', '1', '2', '3', '4', '5', '6', '7', '8', '9', '10', '11']);
|
||||
});
|
||||
|
||||
test.describe('minmax value adjustment when out of bounds', () => {
|
||||
test.beforeEach(({ skip }) => {
|
||||
skip.rtl();
|
||||
skip.mode('ios', 'This implementation is the same across modes.');
|
||||
});
|
||||
test('should reset to min time if out of bounds', async ({ page }) => {
|
||||
await page.setContent(`
|
||||
<ion-datetime
|
||||
min="2022-10-10T08:00"
|
||||
value="2022-10-11T06:00"
|
||||
></ion-datetime>
|
||||
`);
|
||||
|
||||
await page.waitForSelector('.datetime-ready');
|
||||
|
||||
const datetime = page.locator('ion-datetime');
|
||||
const ionChange = await page.spyOnEvent('ionChange');
|
||||
const dayButton = page.locator('ion-datetime .calendar-day[data-day="10"][data-month="10"][data-year="2022"]');
|
||||
await dayButton.click();
|
||||
|
||||
await ionChange.next();
|
||||
|
||||
const value = await datetime.evaluate((el: HTMLIonDatetimeElement) => el.value);
|
||||
await expect(typeof value).toBe('string');
|
||||
await expect(value!.includes('2022-10-10T08:00')).toBe(true);
|
||||
});
|
||||
test('should reset to max time if out of bounds', async ({ page }) => {
|
||||
await page.setContent(`
|
||||
<ion-datetime
|
||||
max="2022-10-10T08:00"
|
||||
value="2022-10-11T09:00"
|
||||
></ion-datetime>
|
||||
`);
|
||||
|
||||
await page.waitForSelector('.datetime-ready');
|
||||
|
||||
const datetime = page.locator('ion-datetime');
|
||||
const ionChange = await page.spyOnEvent('ionChange');
|
||||
const dayButton = page.locator('ion-datetime .calendar-day[data-day="10"][data-month="10"][data-year="2022"]');
|
||||
await dayButton.click();
|
||||
|
||||
await ionChange.next();
|
||||
|
||||
const value = await datetime.evaluate((el: HTMLIonDatetimeElement) => el.value);
|
||||
await expect(typeof value).toBe('string');
|
||||
await expect(value!.includes('2022-10-10T08:00')).toBe(true);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
@@ -189,4 +189,28 @@ test.describe('datetime: multiple date selection (functionality)', () => {
|
||||
await juneButtons.nth(0).click();
|
||||
await expect(header).toHaveText('Selected: 0');
|
||||
});
|
||||
|
||||
test('header text should render default date when multiple="false"', async ({ page }) => {
|
||||
await page.setContent(`
|
||||
<ion-datetime locale="en-US" show-default-title="true"></ion-datetime>
|
||||
|
||||
<script>
|
||||
const mockToday = '2022-10-10T16:22';
|
||||
Date = class extends Date {
|
||||
constructor(...args) {
|
||||
if (args.length === 0) {
|
||||
super(mockToday)
|
||||
} else {
|
||||
super(...args);
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
`);
|
||||
await page.waitForSelector(`.datetime-ready`);
|
||||
const datetime = page.locator('ion-datetime');
|
||||
const header = datetime.locator('.datetime-selected-date');
|
||||
|
||||
await expect(header).toHaveText('Mon, Oct 10');
|
||||
});
|
||||
});
|
||||
|
||||
@@ -40,6 +40,18 @@ test.describe('datetime: prefer wheel', () => {
|
||||
`datetime-wheel-time-date-diff-${page.getSnapshotSettings()}.png`
|
||||
);
|
||||
});
|
||||
test('should render a condense header when specified', async ({ page }) => {
|
||||
await page.setContent(`
|
||||
<ion-datetime size="cover" presentation="time-date" prefer-wheel="true" value="2019-05-30T16:30:00"><div slot="title">My Custom Title</div></ion-datetime>
|
||||
`);
|
||||
await page.waitForSelector('.datetime-ready');
|
||||
|
||||
const datetime = page.locator('ion-datetime');
|
||||
|
||||
expect(await datetime.screenshot()).toMatchSnapshot(
|
||||
`datetime-wheel-header-diff-${page.getSnapshotSettings()}.png`
|
||||
);
|
||||
});
|
||||
});
|
||||
test.describe('datetime: date wheel', () => {
|
||||
test.beforeEach(({ skip }) => {
|
||||
@@ -112,6 +124,77 @@ test.describe('datetime: prefer wheel', () => {
|
||||
expect(await yearValues.count()).toBe(3);
|
||||
expect(await dayValues.count()).toBe(5);
|
||||
});
|
||||
test('selecting month should update value when no value is set', async ({ page }) => {
|
||||
await page.setContent(`
|
||||
<ion-datetime
|
||||
presentation="date"
|
||||
prefer-wheel="true"
|
||||
></ion-datetime>
|
||||
`);
|
||||
|
||||
await page.waitForSelector('.datetime-ready');
|
||||
|
||||
const ionChange = await page.spyOnEvent('ionChange');
|
||||
const monthValues = page.locator('.month-column .picker-item:not(.picker-item-empty)');
|
||||
|
||||
// Change month value
|
||||
await monthValues.nth(0).click();
|
||||
|
||||
await ionChange.next();
|
||||
});
|
||||
test('selecting day should update value when no value is set', async ({ page }) => {
|
||||
await page.setContent(`
|
||||
<ion-datetime
|
||||
presentation="date"
|
||||
prefer-wheel="true"
|
||||
></ion-datetime>
|
||||
|
||||
<script>
|
||||
const mockToday = '2022-10-10T16:22';
|
||||
Date = class extends Date {
|
||||
constructor(...args) {
|
||||
if (args.length === 0) {
|
||||
super(mockToday)
|
||||
} else {
|
||||
super(...args);
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
`);
|
||||
|
||||
await page.waitForSelector('.datetime-ready');
|
||||
|
||||
const ionChange = await page.spyOnEvent('ionChange');
|
||||
const dayValues = page.locator('.day-column .picker-item:not(.picker-item-empty)');
|
||||
|
||||
// Change day value
|
||||
await dayValues.nth(0).click();
|
||||
|
||||
await ionChange.next();
|
||||
});
|
||||
test('selecting year should update value when no value is set', async ({ page }) => {
|
||||
await page.setContent(`
|
||||
<ion-datetime
|
||||
presentation="date"
|
||||
prefer-wheel="true"
|
||||
></ion-datetime>
|
||||
`);
|
||||
|
||||
await page.waitForSelector('.datetime-ready');
|
||||
|
||||
const ionChange = await page.spyOnEvent('ionChange');
|
||||
const yearValues = page.locator('.year-column .picker-item:not(.picker-item-empty)');
|
||||
|
||||
/**
|
||||
* Change year value
|
||||
* The 0th index is the current
|
||||
* year, so select something other than that.
|
||||
*/
|
||||
await yearValues.nth(10).click();
|
||||
|
||||
await ionChange.next();
|
||||
});
|
||||
test.describe('datetime: date wheel localization', () => {
|
||||
test('should correctly localize the date data', async ({ page }) => {
|
||||
await page.setContent(`
|
||||
@@ -314,6 +397,24 @@ test.describe('datetime: prefer wheel', () => {
|
||||
|
||||
expect(await dayValues.count()).toBe(15);
|
||||
});
|
||||
test('selecting date should update value when no value is set', async ({ page }) => {
|
||||
await page.setContent(`
|
||||
<ion-datetime
|
||||
presentation="date-time"
|
||||
prefer-wheel="true"
|
||||
></ion-datetime>
|
||||
`);
|
||||
|
||||
await page.waitForSelector('.datetime-ready');
|
||||
|
||||
const ionChange = await page.spyOnEvent('ionChange');
|
||||
const dayValues = page.locator('.date-column .picker-item:not(.picker-item-empty)');
|
||||
|
||||
// Change day/month value
|
||||
await dayValues.nth(0).click();
|
||||
|
||||
await ionChange.next();
|
||||
});
|
||||
});
|
||||
test.describe('datetime: time-date wheel', () => {
|
||||
test.beforeEach(({ skip }) => {
|
||||
|
||||
|
After Width: | Height: | Size: 47 KiB |
|
After Width: | Height: | Size: 18 KiB |
|
After Width: | Height: | Size: 49 KiB |
|
After Width: | Height: | Size: 47 KiB |
|
After Width: | Height: | Size: 18 KiB |
|
After Width: | Height: | Size: 49 KiB |
|
After Width: | Height: | Size: 57 KiB |
|
After Width: | Height: | Size: 20 KiB |
|
After Width: | Height: | Size: 52 KiB |
|
After Width: | Height: | Size: 57 KiB |
|
After Width: | Height: | Size: 20 KiB |