Compare commits

..

46 Commits

Author SHA1 Message Date
Sean Perkins
7d629ba9f1 test(angular): events are emitted once per emission 2022-11-04 11:45:28 -04:00
Bittor Poza
57105d54ea fix(react): loading layout is correct with no message (#26222)
Resolves #26219
2022-11-03 11:48:55 -04:00
Sean Perkins
9f0b30e460 test(angular): ng15 test infrastructure (#26197) 2022-11-03 10:40:24 -04:00
Sean Perkins
bb005956ea fix(overlays): presenting an overlay does not create nested elements (#26154)
Resolves #26117
2022-11-02 16:57:22 -04:00
Sean Perkins
1f7fc8f05c fix(vue): generate web-types for components (#26205)
Resolves #26198
2022-11-02 12:18:48 -04:00
Liam DeBeasi
e9306f8ad9 merge release-6.3.4
Release 6.3.4
2022-11-02 10:23:32 -04:00
ionitron
c6db6c7822 chore(): update package lock files 2022-11-02 14:01:20 +00:00
ionitron
5e8a75a643 v6.3.4 2022-11-02 13:57:32 +00:00
Liam DeBeasi
4c30a80b7e test(datetime): fix ionChange wheel test (#26203) 2022-11-01 11:27:59 -04:00
Liam DeBeasi
1504b8888d fix(modal): buttons are highlighted with VoiceOver (#26180)
resolves #26156
2022-10-31 15:02:09 -04:00
Sean Perkins
bbbd37bc49 chore(item): remove unused item SCSS mixins (#26182) 2022-10-31 11:10:32 -04:00
Sean Perkins
c0f4381745 test(menu-button): migrate tests to playwright (#26174) 2022-10-27 10:34:25 -04:00
Sean Perkins
b364d58710 chore(playwright): project types (#26165) 2022-10-26 16:41:48 -04:00
Brandy Carney
8ac3b8b575 test(header): migrate to playwright (#26112) 2022-10-26 16:16:59 -04:00
Amanda Johnston
1320948b24 fix(modal, popover): remove trigger click listeners when overlay is unmounted (#26167) 2022-10-26 13:59:43 -05:00
Liam DeBeasi
a7e15babf3 test(list): migrate lines test to playwright (#26171) 2022-10-26 13:30:08 -04:00
Liam DeBeasi
3745083b7c fix(datetime): account for allowed values when setting default date (#26093)
resolves #24722
2022-10-26 10:54:26 -04:00
Liam DeBeasi
c3882d8b21 merge release-6.3.3
Release 6.3.3
2022-10-26 09:15:14 -05:00
ionitron
a5b45821cd chore(): update package lock files 2022-10-26 13:50:57 +00:00
ionitron
53caa22212 v6.3.3 2022-10-26 13:47:18 +00:00
Amanda Johnston
6bbb372980 test(menu-toggle): add basic Playwright test (#26164) 2022-10-24 15:22:35 -05:00
Brandy Carney
0fa68cfa61 test(footer): migrate to playwright (#26094) 2022-10-19 14:25:35 -04:00
Sean Perkins
8ec350ae65 fix(react): inline overlays can be conditionally rendered (#26111)
Resolves #25590

Co-authored-by: liamdebeasi <liamdebeasi@users.noreply.github.com>
2022-10-17 16:43:32 -04:00
Liam DeBeasi
74be79e9d8 fix(dependencies): latest patch is installed (#26148)
resolves #26137
2022-10-17 16:21:29 -04:00
Liam DeBeasi
51ab5f67b5 fix(datetime): empty string is treated as no value (#26131)
resolves #26116
2022-10-17 15:01:27 -04:00
Liam DeBeasi
0548fe8588 fix(datetime): values are adjusted to be in bounds (#26125)
resolves #25894, resolves #25708
2022-10-17 14:19:02 -04:00
Liam DeBeasi
479d56b3b2 fix(datetime): preferWheel can now show title (#26101)
resolves #26095
2022-10-17 13:12:45 -04:00
Liam DeBeasi
d4d569ac09 fix(many): haptics only fire on supported platforms (#26130)
resolves #26109
2022-10-17 12:07:38 -04:00
Liam DeBeasi
ffcf8ec4e0 merge release-6.3.2
Release 6.3.2
2022-10-17 10:39:44 -05:00
ionitron
5d77fde503 chore(): update package lock files 2022-10-17 14:15:29 +00:00
ionitron
1a6595b895 v6.3.2 2022-10-17 14:10:40 +00:00
Amanda Johnston
7e5c03ae40 test(item-sliding): skip flaky gesture test for now (#26136) 2022-10-14 13:07:12 -05:00
Liam DeBeasi
2192409123 test(alert): a11y test is not flaky (#26133) 2022-10-14 12:57:57 -04:00
Liam DeBeasi
0e7f7fcdca test(range): skip flaky test for now (#26134) 2022-10-14 12:39:26 -04:00
Amanda Johnston
fbbebee7be test(item-sliding): migrate tests to Playwright (#26092) 2022-10-14 11:15:18 -05:00
Liam DeBeasi
d76a24dd9e fix(datetime): selecting days updates value (#26121) 2022-10-13 16:34:28 -04:00
Liam DeBeasi
d60973b244 fix(vue): routing components define child components (#26107) 2022-10-13 13:35:15 -04:00
Liam DeBeasi
5e4892676c chore(ci): update actions versions (#26100) 2022-10-13 13:04:01 -04:00
Liam DeBeasi
04df45a443 fix(datetime): header renders correct date (#26120)
resolves #26116
2022-10-13 12:17:21 -04:00
Liam DeBeasi
256b03f12a fix(modal): sheet modal dismisses correctly (#26110)
resolves #26108
2022-10-13 09:58:06 -04:00
Liam DeBeasi
ff6df69a67 chore(core): lint.fix command now runs prettier (#26114) 2022-10-12 18:25:32 -04:00
Liam DeBeasi
bbd6c9ae6c merge release-6.3.1
v6.3.1
2022-10-12 10:06:55 -05:00
Liam DeBeasi
61cc278f05 chore(ci): release script bumps package-lock files 2022-10-12 14:12:40 +00:00
Liam DeBeasi
01840741ce chore(): bump package-lock files 2022-10-12 14:12:17 +00:00
ionitron
448e3fc385 v6.3.1 2022-10-12 12:40:53 +00:00
Liam DeBeasi
5e030f996a chore(): remove roboto source from codebase (#26097) 2022-10-11 10:13:13 -04:00
365 changed files with 30859 additions and 2872 deletions

View File

@@ -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

View File

@@ -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:

View File

@@ -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:

View File

@@ -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:

View File

@@ -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:

View File

@@ -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:

View File

@@ -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:

View File

@@ -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 }}

View File

@@ -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

View File

@@ -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

View File

@@ -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:

View File

@@ -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:

View File

@@ -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

View File

@@ -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:

View File

@@ -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:

View File

@@ -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:

View File

@@ -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:

View File

@@ -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

View File

@@ -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 }}

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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.

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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",

View File

@@ -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"
},

View File

@@ -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

View File

@@ -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
];

View File

@@ -30,7 +30,7 @@ export class FormComponent {
formControl.markAsTouched();
}
onSubmit(_ev) {
onSubmit() {
this.submitted = 'true';
}

View File

@@ -30,7 +30,7 @@ export class FormComponent {
formControl.markAsTouched();
}
onSubmit(_ev) {
onSubmit() {
this.submitted = 'true';
}

View File

@@ -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
View File

File diff suppressed because it is too large Load Diff

View 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"
}
}

View File

@@ -0,0 +1,3 @@
<ion-app>
<ion-router-outlet [environmentInjector]="environmentInjector"></ion-router-outlet>
</ion-app>

View 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) { }
}

View File

@@ -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>

View File

@@ -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 { }

View File

@@ -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 { }

View 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
}
}

View 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');
});
});

View File

@@ -5,7 +5,7 @@ import { Component } from '@angular/core';
templateUrl: './accordion-modal.component.html',
})
export class AccordionModalComponent {
modal: HTMLIonModalElement;
modal!: HTMLIonModalElement;
constructor() {}
}

View File

@@ -73,6 +73,10 @@ const routes: Routes = [
}
]
},
{
path: 'output-target',
loadChildren: () => import('./output-target/output-target.module').then(m => m.OutputTargetModule)
}
];
@NgModule({

View File

@@ -7,7 +7,7 @@
</ion-header>
<ion-content>
<form [formGroup]="profileForm" (ngSubmit)="onSubmit($event)">
<form [formGroup]="profileForm" (ngSubmit)="onSubmit()">
<ion-list>
<ion-item>

View File

@@ -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';
}

View File

@@ -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() {

View File

@@ -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,

View File

@@ -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 { }

View File

@@ -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>

View File

@@ -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++;
}
}

View File

@@ -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 { }

View File

@@ -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(() => {

View File

@@ -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 = '';

View File

@@ -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

View File

@@ -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() { }

View File

@@ -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;
}

View File

@@ -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);

View File

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

View File

@@ -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) {}

View File

@@ -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() {

View File

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

View File

@@ -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

View File

@@ -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",

View File

@@ -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",

View File

@@ -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.

View File

@@ -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([]);
});

View File

Binary file not shown.

View File

Binary file not shown.

View File

Binary file not shown.

View File

Binary file not shown.

View File

Binary file not shown.

View File

Binary file not shown.

View File

Binary file not shown.

View File

Binary file not shown.

View File

Binary file not shown.

View File

Binary file not shown.

View File

Binary file not shown.

View File

Binary file not shown.

View File

@@ -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");
}

View File

@@ -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 [];
}

View File

@@ -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');
});

View File

@@ -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) {

View File

@@ -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', () => {

View File

@@ -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 });
});
});

View File

@@ -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);
});
});
});

View File

@@ -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');
});
});

View File

@@ -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 }) => {

View File

Binary file not shown.

After

Width:  |  Height:  |  Size: 47 KiB

View File

Binary file not shown.

After

Width:  |  Height:  |  Size: 18 KiB

View File

Binary file not shown.

After

Width:  |  Height:  |  Size: 49 KiB

View File

Binary file not shown.

After

Width:  |  Height:  |  Size: 47 KiB

View File

Binary file not shown.

After

Width:  |  Height:  |  Size: 18 KiB

View File

Binary file not shown.

After

Width:  |  Height:  |  Size: 49 KiB

View File

Binary file not shown.

After

Width:  |  Height:  |  Size: 57 KiB

View File

Binary file not shown.

After

Width:  |  Height:  |  Size: 20 KiB

View File

Binary file not shown.

After

Width:  |  Height:  |  Size: 52 KiB

View File

Binary file not shown.

After

Width:  |  Height:  |  Size: 57 KiB

View File

Binary file not shown.

After

Width:  |  Height:  |  Size: 20 KiB

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