diff --git a/.github/actions/publish-npm/action.yml b/.github/actions/publish-npm/action.yml
index 0b5e9924719..d3e06d5fb01 100644
--- a/.github/actions/publish-npm/action.yml
+++ b/.github/actions/publish-npm/action.yml
@@ -22,7 +22,7 @@ runs:
using: 'composite'
steps:
- name: π’ Configure Node for Publish
- uses: actions/setup-node@395ad3262231945c25e8478fd5baf05154b1d79f # v6.1.0
+ uses: actions/setup-node@48b55a011bda9f5d6aeb4c2d9c7362e8dae4041e # v6.4.0
with:
node-version: ${{ inputs.node-version }}
registry-url: 'https://registry.npmjs.org'
diff --git a/.github/ionic-issue-bot.yml b/.github/ionic-issue-bot.yml
index c1e02a5f068..d98b2a53205 100644
--- a/.github/ionic-issue-bot.yml
+++ b/.github/ionic-issue-bot.yml
@@ -40,7 +40,7 @@ comment:
If the requested feature is something you would find useful for your applications, please react to the original post with π (`+1`). If you would like to provide an additional use case for the feature, please post a comment.
-
+
The team will review this feedback and make a final decision. Any decision will be posted on this thread, but please note that we may ultimately decide not to pursue this feature.
@@ -83,6 +83,7 @@ stale:
exemptLabels:
- "good first issue"
- "triage"
+ - "bug: external"
- "type: bug"
- "type: feature request"
- "needs: investigation"
diff --git a/.github/workflows/actions/build-angular-server/action.yml b/.github/workflows/actions/build-angular-server/action.yml
index a90da3676c1..b5d37c5a9ac 100644
--- a/.github/workflows/actions/build-angular-server/action.yml
+++ b/.github/workflows/actions/build-angular-server/action.yml
@@ -3,7 +3,7 @@ description: 'Build Ionic Angular Server'
runs:
using: 'composite'
steps:
- - uses: actions/setup-node@395ad3262231945c25e8478fd5baf05154b1d79f # v6.1.0
+ - uses: actions/setup-node@48b55a011bda9f5d6aeb4c2d9c7362e8dae4041e # v6.4.0
with:
node-version: 24.x
- uses: ./.github/workflows/actions/download-archive
diff --git a/.github/workflows/actions/build-angular/action.yml b/.github/workflows/actions/build-angular/action.yml
index fc7496de421..5224f9741e0 100644
--- a/.github/workflows/actions/build-angular/action.yml
+++ b/.github/workflows/actions/build-angular/action.yml
@@ -27,6 +27,10 @@ runs:
run: npm run build
shell: bash
working-directory: ./packages/angular
+ - name: Clean core package.json
+ run: git checkout ./package.json
+ shell: bash
+ working-directory: ./core
- name: π Check Diff
run: git diff --exit-code
shell: bash
diff --git a/.github/workflows/actions/build-core-stencil-prerelease/action.yml b/.github/workflows/actions/build-core-stencil-prerelease/action.yml
index 323ba6f7259..742c45a9b68 100644
--- a/.github/workflows/actions/build-core-stencil-prerelease/action.yml
+++ b/.github/workflows/actions/build-core-stencil-prerelease/action.yml
@@ -8,8 +8,8 @@ inputs:
runs:
using: 'composite'
steps:
- - uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1
- - uses: actions/setup-node@395ad3262231945c25e8478fd5baf05154b1d79f # v6.1.0
+ - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
+ - uses: actions/setup-node@48b55a011bda9f5d6aeb4c2d9c7362e8dae4041e # v6.4.0
with:
node-version: 24.x
@@ -29,4 +29,4 @@ runs:
with:
name: ionic-core
output: core/CoreBuild.zip
- paths: core/dist core/components core/src/foundations core/css core/themes core/hydrate core/loader core/src/components.d.ts
+ paths: core/dist core/components core/src/foundations core/css core/themes core/hydrate core/loader core/src/components.d.ts core/package.json
diff --git a/.github/workflows/actions/build-core/action.yml b/.github/workflows/actions/build-core/action.yml
index 2211059e817..0f712bda8f4 100644
--- a/.github/workflows/actions/build-core/action.yml
+++ b/.github/workflows/actions/build-core/action.yml
@@ -8,8 +8,8 @@ inputs:
runs:
using: 'composite'
steps:
- - uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1
- - uses: actions/setup-node@395ad3262231945c25e8478fd5baf05154b1d79f # v6.1.0
+ - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
+ - uses: actions/setup-node@48b55a011bda9f5d6aeb4c2d9c7362e8dae4041e # v6.4.0
with:
node-version: 24.x
- name: πΈοΈ Install Dependencies
diff --git a/.github/workflows/actions/build-react-router/action.yml b/.github/workflows/actions/build-react-router/action.yml
index a003fd83d6c..c8083494b0a 100644
--- a/.github/workflows/actions/build-react-router/action.yml
+++ b/.github/workflows/actions/build-react-router/action.yml
@@ -3,7 +3,7 @@ description: 'Build Ionic React Router'
runs:
using: 'composite'
steps:
- - uses: actions/setup-node@395ad3262231945c25e8478fd5baf05154b1d79f # v6.1.0
+ - uses: actions/setup-node@48b55a011bda9f5d6aeb4c2d9c7362e8dae4041e # v6.4.0
with:
node-version: 24.x
- uses: ./.github/workflows/actions/download-archive
diff --git a/.github/workflows/actions/build-react/action.yml b/.github/workflows/actions/build-react/action.yml
index b65292f5dc7..5899335ad3e 100644
--- a/.github/workflows/actions/build-react/action.yml
+++ b/.github/workflows/actions/build-react/action.yml
@@ -3,7 +3,7 @@ description: 'Build Ionic React'
runs:
using: 'composite'
steps:
- - uses: actions/setup-node@395ad3262231945c25e8478fd5baf05154b1d79f # v6.1.0
+ - uses: actions/setup-node@48b55a011bda9f5d6aeb4c2d9c7362e8dae4041e # v6.4.0
with:
node-version: 24.x
- uses: ./.github/workflows/actions/download-archive
@@ -31,6 +31,10 @@ runs:
run: npm run test.spec
shell: bash
working-directory: ./packages/react
+ - name: Clean core package.json
+ run: git checkout ./package.json
+ shell: bash
+ working-directory: ./core
- name: π Check Diff
run: git diff --exit-code
shell: bash
diff --git a/.github/workflows/actions/build-vue-router/action.yml b/.github/workflows/actions/build-vue-router/action.yml
index b5bb65c6f89..9b07ce64973 100644
--- a/.github/workflows/actions/build-vue-router/action.yml
+++ b/.github/workflows/actions/build-vue-router/action.yml
@@ -3,7 +3,7 @@ description: 'Builds Ionic Vue Router'
runs:
using: 'composite'
steps:
- - uses: actions/setup-node@395ad3262231945c25e8478fd5baf05154b1d79f # v6.1.0
+ - uses: actions/setup-node@48b55a011bda9f5d6aeb4c2d9c7362e8dae4041e # v6.4.0
with:
node-version: 24.x
- uses: ./.github/workflows/actions/download-archive
diff --git a/.github/workflows/actions/build-vue/action.yml b/.github/workflows/actions/build-vue/action.yml
index e660c31bbbd..5c7497ec359 100644
--- a/.github/workflows/actions/build-vue/action.yml
+++ b/.github/workflows/actions/build-vue/action.yml
@@ -3,7 +3,7 @@ description: 'Build Ionic Vue'
runs:
using: 'composite'
steps:
- - uses: actions/setup-node@395ad3262231945c25e8478fd5baf05154b1d79f # v6.1.0
+ - uses: actions/setup-node@48b55a011bda9f5d6aeb4c2d9c7362e8dae4041e # v6.4.0
with:
node-version: 24.x
- uses: ./.github/workflows/actions/download-archive
@@ -27,6 +27,10 @@ runs:
run: npm run build
shell: bash
working-directory: ./packages/vue
+ - name: Clean core package.json
+ run: git checkout ./package.json
+ shell: bash
+ working-directory: ./core
- name: π Check Diff
run: git diff --exit-code
shell: bash
diff --git a/.github/workflows/actions/download-archive/action.yml b/.github/workflows/actions/download-archive/action.yml
index e61c44a0910..2acddf9713f 100644
--- a/.github/workflows/actions/download-archive/action.yml
+++ b/.github/workflows/actions/download-archive/action.yml
@@ -10,7 +10,7 @@ inputs:
runs:
using: 'composite'
steps:
- - uses: actions/download-artifact@v7
+ - uses: actions/download-artifact@v8
with:
name: ${{ inputs.name }}
path: ${{ inputs.path }}
diff --git a/.github/workflows/actions/test-angular-e2e/action.yml b/.github/workflows/actions/test-angular-e2e/action.yml
index 9c3ac716d53..a4835a0210a 100644
--- a/.github/workflows/actions/test-angular-e2e/action.yml
+++ b/.github/workflows/actions/test-angular-e2e/action.yml
@@ -6,7 +6,7 @@ inputs:
runs:
using: 'composite'
steps:
- - uses: actions/setup-node@395ad3262231945c25e8478fd5baf05154b1d79f # v6.1.0
+ - uses: actions/setup-node@48b55a011bda9f5d6aeb4c2d9c7362e8dae4041e # v6.4.0
with:
node-version: 24.x
- uses: ./.github/workflows/actions/download-archive
@@ -17,7 +17,7 @@ runs:
- uses: ./.github/workflows/actions/download-archive
with:
name: ionic-angular
- path: ./angular
+ path: ./packages/angular
filename: AngularBuild.zip
- uses: ./.github/workflows/actions/download-archive
with:
diff --git a/.github/workflows/actions/test-core-clean-build/action.yml b/.github/workflows/actions/test-core-clean-build/action.yml
index b69a485b33f..96abc90121c 100644
--- a/.github/workflows/actions/test-core-clean-build/action.yml
+++ b/.github/workflows/actions/test-core-clean-build/action.yml
@@ -3,7 +3,7 @@ description: 'Test Core Clean Build'
runs:
using: 'composite'
steps:
- - uses: actions/setup-node@395ad3262231945c25e8478fd5baf05154b1d79f # v6.1.0
+ - uses: actions/setup-node@48b55a011bda9f5d6aeb4c2d9c7362e8dae4041e # v6.4.0
with:
node-version: 24.x
@@ -12,6 +12,10 @@ runs:
name: ionic-core
path: ./core
filename: CoreBuild.zip
+ - name: Clean core package.json
+ run: git checkout ./package.json
+ shell: bash
+ working-directory: ./core
- name: π Check Diff
run: |
git diff --exit-code || {
diff --git a/.github/workflows/actions/test-core-lint/action.yml b/.github/workflows/actions/test-core-lint/action.yml
index 8e81bd6a635..f9f0011719a 100644
--- a/.github/workflows/actions/test-core-lint/action.yml
+++ b/.github/workflows/actions/test-core-lint/action.yml
@@ -3,13 +3,17 @@ description: 'Test Core Lint'
runs:
using: 'composite'
steps:
- - uses: actions/setup-node@395ad3262231945c25e8478fd5baf05154b1d79f # v6.1.0
+ - uses: actions/setup-node@48b55a011bda9f5d6aeb4c2d9c7362e8dae4041e # v6.4.0
with:
node-version: 24.x
- name: πΈοΈ Install Dependencies
run: npm ci
working-directory: ./core
shell: bash
+ - name: Clean core package.json
+ run: git checkout ./package.json
+ shell: bash
+ working-directory: ./core
- name: ποΈ Lint
run: npm run lint
shell: bash
diff --git a/.github/workflows/actions/test-core-screenshot/action.yml b/.github/workflows/actions/test-core-screenshot/action.yml
index e3c7d8771d5..1f8699e66d4 100644
--- a/.github/workflows/actions/test-core-screenshot/action.yml
+++ b/.github/workflows/actions/test-core-screenshot/action.yml
@@ -13,7 +13,7 @@ inputs:
runs:
using: 'composite'
steps:
- - uses: actions/setup-node@395ad3262231945c25e8478fd5baf05154b1d79f # v6.1.0
+ - uses: actions/setup-node@48b55a011bda9f5d6aeb4c2d9c7362e8dae4041e # v6.4.0
with:
node-version: 24.x
- uses: ./.github/workflows/actions/download-archive
@@ -30,6 +30,10 @@ runs:
run: npm run test.e2e.docker.ci ${{ inputs.component }} -- --shard=${{ inputs.shard }}/${{ inputs.totalShards }}
shell: bash
working-directory: ./core
+ - name: Clean core package.json
+ run: git checkout ./package.json
+ shell: bash
+ working-directory: ./core
- name: Test and Update
id: test-and-update
if: inputs.update == 'true'
@@ -62,7 +66,7 @@ runs:
working-directory: ./core
- name: π¦ Archive Updated Screenshots
if: inputs.update == 'true' && steps.test-and-update.outputs.hasUpdatedScreenshots == 'true'
- uses: actions/upload-artifact@v6
+ uses: actions/upload-artifact@v7
with:
name: updated-screenshots-${{ inputs.shard }}-${{ inputs.totalShards }}
path: UpdatedScreenshots-${{ inputs.shard }}-${{ inputs.totalShards }}.zip
diff --git a/.github/workflows/actions/test-core-spec/action.yml b/.github/workflows/actions/test-core-spec/action.yml
index ee54ae604cf..2aab4b1be94 100644
--- a/.github/workflows/actions/test-core-spec/action.yml
+++ b/.github/workflows/actions/test-core-spec/action.yml
@@ -6,7 +6,7 @@ inputs:
runs:
using: 'composite'
steps:
- - uses: actions/setup-node@395ad3262231945c25e8478fd5baf05154b1d79f # v6.1.0
+ - uses: actions/setup-node@48b55a011bda9f5d6aeb4c2d9c7362e8dae4041e # v6.4.0
with:
node-version: 24.x
- name: πΈοΈ Install Dependencies
diff --git a/.github/workflows/actions/test-react-e2e/action.yml b/.github/workflows/actions/test-react-e2e/action.yml
index d27dd9f836e..a1bcbf7a4db 100644
--- a/.github/workflows/actions/test-react-e2e/action.yml
+++ b/.github/workflows/actions/test-react-e2e/action.yml
@@ -6,7 +6,7 @@ inputs:
runs:
using: 'composite'
steps:
- - uses: actions/setup-node@395ad3262231945c25e8478fd5baf05154b1d79f # v6.1.0
+ - uses: actions/setup-node@48b55a011bda9f5d6aeb4c2d9c7362e8dae4041e # v6.4.0
with:
node-version: 24.x
- uses: ./.github/workflows/actions/download-archive
diff --git a/.github/workflows/actions/test-react-router-e2e/action.yml b/.github/workflows/actions/test-react-router-e2e/action.yml
index b4e627ee896..034cfdce747 100644
--- a/.github/workflows/actions/test-react-router-e2e/action.yml
+++ b/.github/workflows/actions/test-react-router-e2e/action.yml
@@ -6,7 +6,7 @@ inputs:
runs:
using: 'composite'
steps:
- - uses: actions/setup-node@395ad3262231945c25e8478fd5baf05154b1d79f # v6.1.0
+ - uses: actions/setup-node@48b55a011bda9f5d6aeb4c2d9c7362e8dae4041e # v6.4.0
with:
node-version: 24.x
- uses: ./.github/workflows/actions/download-archive
diff --git a/.github/workflows/actions/test-vue-e2e/action.yml b/.github/workflows/actions/test-vue-e2e/action.yml
index c0adfd409b9..191cd193c8a 100644
--- a/.github/workflows/actions/test-vue-e2e/action.yml
+++ b/.github/workflows/actions/test-vue-e2e/action.yml
@@ -6,7 +6,7 @@ inputs:
runs:
using: 'composite'
steps:
- - uses: actions/setup-node@395ad3262231945c25e8478fd5baf05154b1d79f # v6.1.0
+ - uses: actions/setup-node@48b55a011bda9f5d6aeb4c2d9c7362e8dae4041e # v6.4.0
with:
node-version: 24.x
- uses: ./.github/workflows/actions/download-archive
diff --git a/.github/workflows/actions/update-reference-screenshots/action.yml b/.github/workflows/actions/update-reference-screenshots/action.yml
index ad41d5e724d..6ee56689b10 100644
--- a/.github/workflows/actions/update-reference-screenshots/action.yml
+++ b/.github/workflows/actions/update-reference-screenshots/action.yml
@@ -7,10 +7,10 @@ on:
runs:
using: 'composite'
steps:
- - uses: actions/setup-node@395ad3262231945c25e8478fd5baf05154b1d79f # v6.1.0
+ - uses: actions/setup-node@48b55a011bda9f5d6aeb4c2d9c7362e8dae4041e # v6.4.0
with:
node-version: 24.x
- - uses: actions/download-artifact@v7
+ - uses: actions/download-artifact@v8
with:
path: ./artifacts
- name: π Extract Archives
@@ -21,6 +21,10 @@ runs:
find . -type f -name 'UpdatedScreenshots-*.zip' -exec unzip -q -o -d ../ {} \;
shell: bash
working-directory: ./artifacts
+ - name: Clean core package.json
+ run: git checkout ./package.json
+ shell: bash
+ working-directory: ./core
- name: πΈ Push Screenshots
# Configure user as Ionitron
# and push only the changed .png snapshots
diff --git a/.github/workflows/actions/upload-archive/action.yml b/.github/workflows/actions/upload-archive/action.yml
index 67465651c88..c09397345f9 100644
--- a/.github/workflows/actions/upload-archive/action.yml
+++ b/.github/workflows/actions/upload-archive/action.yml
@@ -13,7 +13,7 @@ runs:
- name: ποΈ Create Archive
run: zip -q -r ${{ inputs.output }} ${{ inputs.paths }}
shell: bash
- - uses: actions/upload-artifact@v6
+ - uses: actions/upload-artifact@v7
with:
name: ${{ inputs.name }}
path: ${{ inputs.output }}
diff --git a/.github/workflows/assign-issues.yml b/.github/workflows/assign-issues.yml
index d06c1f52e10..d79a8c17c2c 100644
--- a/.github/workflows/assign-issues.yml
+++ b/.github/workflows/assign-issues.yml
@@ -11,7 +11,7 @@ jobs:
issues: write
steps:
- name: 'Auto-assign issue'
- uses: pozil/auto-assign-issue@39c06395cbac76e79afc4ad4e5c5c6db6ecfdd2e # v2.2.0
+ uses: pozil/auto-assign-issue@70adb98ca8b3941524e9ecde48e89067c4f96736 # v3.0.0
with:
assignees: brandyscarney, thetaPC, ShaneK
numOfAssignee: 1
diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml
index d3d52e048be..7772b2c432f 100644
--- a/.github/workflows/build.yml
+++ b/.github/workflows/build.yml
@@ -22,7 +22,7 @@ jobs:
build-core:
runs-on: ubuntu-latest
steps:
- - uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1
+ - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
- uses: ./.github/workflows/actions/build-core
with:
ionicons-version: ${{ inputs.ionicons_npm_release_tag }}
@@ -31,21 +31,21 @@ jobs:
needs: [build-core]
runs-on: ubuntu-latest
steps:
- - uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1
+ - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
- uses: ./.github/workflows/actions/test-core-clean-build
test-core-lint:
needs: [build-core]
runs-on: ubuntu-latest
steps:
- - uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1
+ - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
- uses: ./.github/workflows/actions/test-core-lint
test-core-spec:
needs: [build-core]
runs-on: ubuntu-latest
steps:
- - uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1
+ - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
- uses: ./.github/workflows/actions/test-core-spec
test-core-screenshot:
@@ -62,7 +62,7 @@ jobs:
needs: [build-core]
runs-on: ubuntu-latest
steps:
- - uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1
+ - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
- uses: ./.github/workflows/actions/test-core-screenshot
with:
shard: ${{ matrix.shard }}
@@ -90,14 +90,14 @@ jobs:
needs: [build-core]
runs-on: ubuntu-latest
steps:
- - uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1
+ - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
- uses: ./.github/workflows/actions/build-vue
build-vue-router:
needs: [build-vue]
runs-on: ubuntu-latest
steps:
- - uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1
+ - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
- uses: ./.github/workflows/actions/build-vue-router
test-vue-e2e:
@@ -108,7 +108,7 @@ jobs:
needs: [build-vue, build-vue-router]
runs-on: ubuntu-latest
steps:
- - uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1
+ - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
- uses: ./.github/workflows/actions/test-vue-e2e
with:
app: ${{ matrix.apps }}
@@ -126,14 +126,14 @@ jobs:
needs: [build-core]
runs-on: ubuntu-latest
steps:
- - uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1
+ - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
- uses: ./.github/workflows/actions/build-angular
build-angular-server:
needs: [build-core]
runs-on: ubuntu-latest
steps:
- - uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1
+ - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
- uses: ./.github/workflows/actions/build-angular-server
test-angular-e2e:
@@ -144,7 +144,7 @@ jobs:
needs: [build-angular, build-angular-server]
runs-on: ubuntu-latest
steps:
- - uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1
+ - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
- uses: ./.github/workflows/actions/test-angular-e2e
with:
app: ${{ matrix.apps }}
@@ -162,14 +162,14 @@ jobs:
needs: [build-core]
runs-on: ubuntu-latest
steps:
- - uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1
+ - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
- uses: ./.github/workflows/actions/build-react
build-react-router:
needs: [build-react]
runs-on: ubuntu-latest
steps:
- - uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1
+ - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
- uses: ./.github/workflows/actions/build-react-router
test-react-router-e2e:
@@ -180,7 +180,7 @@ jobs:
needs: [build-react, build-react-router]
runs-on: ubuntu-latest
steps:
- - uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1
+ - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
- uses: ./.github/workflows/actions/test-react-router-e2e
with:
app: ${{ matrix.apps }}
@@ -202,7 +202,7 @@ jobs:
needs: [build-react, build-react-router]
runs-on: ubuntu-latest
steps:
- - uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1
+ - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
- uses: ./.github/workflows/actions/test-react-e2e
with:
app: ${{ matrix.apps }}
diff --git a/.github/workflows/codeql-analysis.yml b/.github/workflows/codeql-analysis.yml
index 2844a4f9b01..5e6715d02b1 100644
--- a/.github/workflows/codeql-analysis.yml
+++ b/.github/workflows/codeql-analysis.yml
@@ -14,7 +14,7 @@ jobs:
permissions:
security-events: write
steps:
- - uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1
+ - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
- uses: github/codeql-action/init@v4
with:
languages: javascript
diff --git a/.github/workflows/dev-build.yml b/.github/workflows/dev-build.yml
index 2c459097e67..51806128a8e 100644
--- a/.github/workflows/dev-build.yml
+++ b/.github/workflows/dev-build.yml
@@ -13,7 +13,7 @@ jobs:
outputs:
dev-hash: ${{ steps.create-dev-hash.outputs.DEV_HASH }}
steps:
- - uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1
+ - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
# A 1 is required before the timestamp
# as lerna will fail when there is a leading 0
# See https://github.com/lerna/lerna/issues/2840
diff --git a/.github/workflows/nightly.yml b/.github/workflows/nightly.yml
index dc2fa5860a9..2f64d9f9bd5 100644
--- a/.github/workflows/nightly.yml
+++ b/.github/workflows/nightly.yml
@@ -13,7 +13,7 @@ jobs:
outputs:
nightly-hash: ${{ steps.create-nightly-hash.outputs.NIGHTLY_HASH }}
steps:
- - uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1
+ - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
# A 1 is required before the timestamp
# as lerna will fail when there is a leading 0
# See https://github.com/lerna/lerna/issues/2840
diff --git a/.github/workflows/release-ionic.yml b/.github/workflows/release-ionic.yml
index c3f9e5740b6..70f1fb1956b 100644
--- a/.github/workflows/release-ionic.yml
+++ b/.github/workflows/release-ionic.yml
@@ -23,7 +23,7 @@ jobs:
release-core:
runs-on: ubuntu-latest
steps:
- - uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1
+ - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
- uses: ./.github/actions/publish-npm
with:
scope: '@ionic/core'
@@ -48,7 +48,7 @@ jobs:
needs: [release-core]
runs-on: ubuntu-latest
steps:
- - uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1
+ - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
- name: Restore @ionic/docs built cache
uses: ./.github/workflows/actions/download-archive
with:
@@ -67,7 +67,7 @@ jobs:
needs: [release-core]
runs-on: ubuntu-latest
steps:
- - uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1
+ - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
- name: Restore @ionic/core built cache
uses: ./.github/workflows/actions/download-archive
with:
@@ -93,7 +93,7 @@ jobs:
needs: [release-core]
runs-on: ubuntu-latest
steps:
- - uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1
+ - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
- name: Restore @ionic/core built cache
uses: ./.github/workflows/actions/download-archive
with:
@@ -118,7 +118,7 @@ jobs:
needs: [release-core]
runs-on: ubuntu-latest
steps:
- - uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1
+ - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
- name: Restore @ionic/core built cache
uses: ./.github/workflows/actions/download-archive
with:
@@ -143,7 +143,7 @@ jobs:
needs: [release-core]
runs-on: ubuntu-latest
steps:
- - uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1
+ - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
- name: Restore @ionic/core built cache
uses: ./.github/workflows/actions/download-archive
with:
@@ -163,7 +163,7 @@ jobs:
needs: [release-react]
runs-on: ubuntu-latest
steps:
- - uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1
+ - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
- name: Restore @ionic/core built cache
uses: ./.github/workflows/actions/download-archive
with:
@@ -188,7 +188,7 @@ jobs:
needs: [release-vue]
runs-on: ubuntu-latest
steps:
- - uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1
+ - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
- name: Restore @ionic/core built cache
uses: ./.github/workflows/actions/download-archive
with:
diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml
index a3bb4491cf5..df4429a806b 100644
--- a/.github/workflows/release.yml
+++ b/.github/workflows/release.yml
@@ -58,7 +58,7 @@ jobs:
contents: write
id-token: write
steps:
- - uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1
+ - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
with:
token: ${{ secrets.IONITRON_TOKEN }}
fetch-depth: 0
@@ -89,7 +89,7 @@ jobs:
contents: write
id-token: write
steps:
- - uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1
+ - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
# Pull the latest version of the reference
# branch instead of the revision that triggered
# the workflow otherwise we won't get the commit
diff --git a/.github/workflows/stencil-nightly.yml b/.github/workflows/stencil-nightly.yml
index b00ac8c42a0..3e8d714ccc1 100644
--- a/.github/workflows/stencil-nightly.yml
+++ b/.github/workflows/stencil-nightly.yml
@@ -26,7 +26,7 @@ jobs:
build-core-with-stencil-nightly:
runs-on: ubuntu-latest
steps:
- - uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1
+ - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
- uses: ./.github/workflows/actions/build-core-stencil-prerelease
with:
stencil-version: ${{ inputs.npm_release_tag || 'nightly' }}
@@ -35,21 +35,21 @@ jobs:
needs: [build-core-with-stencil-nightly]
runs-on: ubuntu-latest
steps:
- - uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1
+ - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
- uses: ./.github/workflows/actions/test-core-clean-build
test-core-lint:
needs: [build-core-with-stencil-nightly]
runs-on: ubuntu-latest
steps:
- - uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1
+ - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
- uses: ./.github/workflows/actions/test-core-lint
test-core-spec:
needs: [build-core-with-stencil-nightly]
runs-on: ubuntu-latest
steps:
- - uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1
+ - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
- uses: ./.github/workflows/actions/test-core-spec
with:
stencil-version: ${{ inputs.npm_release_tag || 'nightly' }}
@@ -72,7 +72,7 @@ jobs:
needs: [build-core-with-stencil-nightly]
runs-on: ubuntu-latest
steps:
- - uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1
+ - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
- uses: ./.github/workflows/actions/test-core-screenshot
with:
shard: ${{ matrix.shard }}
@@ -100,14 +100,14 @@ jobs:
needs: [build-core-with-stencil-nightly]
runs-on: ubuntu-latest
steps:
- - uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1
+ - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
- uses: ./.github/workflows/actions/build-vue
build-vue-router:
needs: [build-vue]
runs-on: ubuntu-latest
steps:
- - uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1
+ - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
- uses: ./.github/workflows/actions/build-vue-router
test-vue-e2e:
@@ -118,7 +118,7 @@ jobs:
needs: [build-vue, build-vue-router]
runs-on: ubuntu-latest
steps:
- - uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1
+ - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
- uses: ./.github/workflows/actions/test-vue-e2e
with:
app: ${{ matrix.apps }}
@@ -136,14 +136,14 @@ jobs:
needs: [build-core-with-stencil-nightly]
runs-on: ubuntu-latest
steps:
- - uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1
+ - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
- uses: ./.github/workflows/actions/build-angular
build-angular-server:
needs: [build-core-with-stencil-nightly]
runs-on: ubuntu-latest
steps:
- - uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1
+ - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
- uses: ./.github/workflows/actions/build-angular-server
test-angular-e2e:
@@ -154,7 +154,7 @@ jobs:
needs: [build-angular, build-angular-server]
runs-on: ubuntu-latest
steps:
- - uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1
+ - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
- uses: ./.github/workflows/actions/test-angular-e2e
with:
app: ${{ matrix.apps }}
@@ -172,14 +172,14 @@ jobs:
needs: [build-core-with-stencil-nightly]
runs-on: ubuntu-latest
steps:
- - uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1
+ - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
- uses: ./.github/workflows/actions/build-react
build-react-router:
needs: [build-react]
runs-on: ubuntu-latest
steps:
- - uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1
+ - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
- uses: ./.github/workflows/actions/build-react-router
test-react-router-e2e:
@@ -190,7 +190,7 @@ jobs:
needs: [build-react, build-react-router]
runs-on: ubuntu-latest
steps:
- - uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1
+ - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
- uses: ./.github/workflows/actions/test-react-router-e2e
with:
app: ${{ matrix.apps }}
@@ -212,7 +212,7 @@ jobs:
needs: [build-react, build-react-router]
runs-on: ubuntu-latest
steps:
- - uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1
+ - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
- uses: ./.github/workflows/actions/test-react-e2e
with:
app: ${{ matrix.apps }}
diff --git a/.github/workflows/update-screenshots.yml b/.github/workflows/update-screenshots.yml
index eefcddcb893..6efecbd8f95 100644
--- a/.github/workflows/update-screenshots.yml
+++ b/.github/workflows/update-screenshots.yml
@@ -26,7 +26,7 @@ jobs:
build-core:
runs-on: ubuntu-latest
steps:
- - uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1
+ - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
- uses: ./.github/workflows/actions/build-core
test-core-screenshot:
@@ -47,7 +47,7 @@ jobs:
needs: [build-core]
runs-on: ubuntu-latest
steps:
- - uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1
+ - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
- uses: ./.github/workflows/actions/test-core-screenshot
with:
shard: ${{ matrix.shard }}
@@ -59,7 +59,7 @@ jobs:
runs-on: ubuntu-latest
needs: [test-core-screenshot]
steps:
- - uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1
+ - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
# Normally, we could just push with the
# default GITHUB_TOKEN, but that will
# not cause the build workflow
diff --git a/BREAKING.md b/BREAKING.md
index ffecb8605f9..c47e098e609 100644
--- a/BREAKING.md
+++ b/BREAKING.md
@@ -19,9 +19,13 @@ This is a comprehensive list of the breaking changes introduced in the major ver
- [Button](#version-9x-button)
- [Card](#version-9x-card)
- [Chip](#version-9x-chip)
+ - [Datetime](#version-9x-datetime)
- [Grid](#version-9x-grid)
+ - [Input Otp](#version-9x-input-otp)
- [Item Divider](#version-9x-item-divider)
+ - [Radio Group](#version-9x-radio-group)
- [Spinner](#version-9x-spinner)
+ - [Textarea](#version-9x-textarea)
Global Styles
@@ -37,7 +41,35 @@ This is a comprehensive list of the breaking changes introduced in the major ver
Card
-- The `border-radius` of the `ios` and `md` card now defaults to `14px` and `12px` instead of `8px` and `4px`, respectively, in accordance with the iOS and Material Design 3 guidelines. To revert to the previous appearance, set the `shape` to `"soft"`, or override the `--border-radius` CSS variable to specify a different value.
+- **ion-card**: The `border-radius` of the `ios` and `md` card now defaults to `14px` and `12px` instead of `8px` and `4px`, respectively, in accordance with the iOS and Material Design 3 guidelines. To revert to the previous appearance, set the `shape` to `"soft"`, or override the `--border-radius` CSS variable to specify a different value.
+
+- **ion-card-content**: The `ion-card-content` component has been updated to Shadow DOM. With this update, all card-related components now use Shadow DOM for style encapsulation. The default styles for heading elements inside `ion-card-content` have been removed. If you need custom styling for headings, you can add your own CSS targeting these elements. For example:
+
+ ```css
+ ion-card-content h1 {
+ margin-top: 0;
+ margin-bottom: 2px;
+
+ font-size: 1.5rem;
+ }
+
+ ion-card-content h2 {
+ margin-top: 2px;
+ margin-bottom: 2px;
+
+ font-size: 1rem;
+ }
+
+ ion-card-content h3,
+ ion-card-content h4,
+ ion-card-content h5,
+ ion-card-content h6 {
+ margin-top: 2px;
+ margin-bottom: 2px;
+
+ font-size: 0.875rem;
+ }
+ ```
Chip
@@ -50,19 +82,18 @@ This is a comprehensive list of the breaking changes introduced in the major ver
- Specific theme classes (e.g., `ion-chip.md`) are no longer supported. Style modifications based on the active theme must be implemented using theme tokens rather than direct class targeting.
- The `border-radius` of the `ios` and `md` chip now defaults to `10px` and `8px`, respectively, instead of `16px` in accordance with the iOS and Material Design 3 guidelines. To revert to the previous appearance, set the `shape` to `"round"`, or override the `IonChip.shape.round.border.radius` to specify a different value for global styles and `--ion-chip-shape-round-border-radius` for component-specific styles.
-Grid
+Datetime
-- The properties `pull` and `push` have been deprecated and no longer work. A similar look can be achieved with the newly added property `order`.
+- The `ion-buttons` component has been removed from the internal implementation of `ion-datetime` and is no longer required when passing custom buttons to the `slot="buttons"`. When providing custom buttons, use a `div` element instead of `ion-buttons`. While existing code using `ion-buttons` may continue to work visually, future updates to the `ion-buttons` component may cause any styles you rely on to break.
-Radio Group
+Grid
-- Converted `ion-radio-group` to use [Shadow DOM](https://developer.mozilla.org/en-US/docs/Web/Web_Components/Using_shadow_DOM).
-If you were targeting the internals of `ion-radio-group` in your CSS, you will need to target the `supporting-text`, `helper-text` or `error-text` [Shadow Parts](https://ionicframework.com/docs/theming/css-shadow-parts) instead, or use the provided CSS Variables.
-Additionally, the `radio-group-wrapper` div element has been removed, causing slotted elements to be direct children of the `ion-radio-group`.
+- The properties `pull` and `push` have been deprecated and no longer work. A similar look can be achieved with the newly added property `order`.
Example 1: Swap two columns
**Version up to 8.x**
+
```html
@@ -72,7 +103,9 @@ Additionally, the `radio-group-wrapper` div element has been removed, causing sl
```
+
**Version 9.x+**
+
```html
@@ -84,9 +117,11 @@ Additionally, the `radio-group-wrapper` div element has been removed, causing sl
```
Example 2: Reorder columns with specific sizes
+
To reorder two columns where column 1 has `size="9" push="3"` and column 2 has `size="3" pull="9"`:
**Version up to 8.x**
+
```html
@@ -95,7 +130,9 @@ To reorder two columns where column 1 has `size="9" push="3"` and column 2 has `
```
+
**Version 9.x+**
+
```html
@@ -104,7 +141,9 @@ To reorder two columns where column 1 has `size="9" push="3"` and column 2 has `
```
+
Example 3: Push
+
```html
@@ -117,7 +156,9 @@ To reorder two columns where column 1 has `size="9" push="3"` and column 2 has `
```
+
**Version 9.x+**
+
```html
@@ -132,6 +173,7 @@ To reorder two columns where column 1 has `size="9" push="3"` and column 2 has `
```
Example 4: Push and Pull
+
```html
@@ -144,7 +186,9 @@ To reorder two columns where column 1 has `size="9" push="3"` and column 2 has `
```
+
**Version 9.x+**
+
```html
@@ -158,6 +202,12 @@ To reorder two columns where column 1 has `size="9" push="3"` and column 2 has `
```
+
+
+Converted `ion-input-otp` to use [Shadow DOM](https://developer.mozilla.org/en-US/docs/Web/Web_Components/Using_shadow_DOM).
+
+If you were targeting the internals of `ion-input-otp` in your CSS, you will need to target the `group`, `container`, `native`, `separator` or `description` [Shadow Parts](https://ionicframework.com/docs/theming/css-shadow-parts) instead, or use the provided CSS Variables.
+
Item Divider
- Component CSS variables have been removed. The component now utilizes the centralized Ionic Theming system. Global updates should be managed via the theme tokens file, while component-specific overrides are handled through localized CSS variables.
@@ -173,6 +223,14 @@ To reorder two columns where column 1 has `size="9" push="3"` and column 2 has `
- `--inner-padding-start` is replaced by `IonItemDivider.inner.padding.start` for global styles and `--ion-item-divider-inner-padding-start` for component-specific overrides.
- Specific theme classes (e.g., `ion-item-divider.md`) are no longer supported. Style modifications based on the active theme must be implemented using theme tokens rather than direct class targeting.
+Radio Group
+
+Converted `ion-radio-group` to use [Shadow DOM](https://developer.mozilla.org/en-US/docs/Web/Web_Components/Using_shadow_DOM).
+
+If you were targeting the internals of `ion-radio-group` in your CSS, you will need to target the `supporting-text`, `helper-text` or `error-text` [Shadow Parts](https://ionicframework.com/docs/theming/css-shadow-parts) instead, or use the provided CSS Variables.
+
+Additionally, the `radio-group-wrapper` div element has been removed, causing slotted elements to be direct children of the `ion-radio-group`.
+
Spinner
- Component CSS variables have been removed. The component now utilizes the centralized Ionic Theming system. Global updates should be managed via the theme tokens file, while component-specific overrides are handled through localized CSS variables.
@@ -181,3 +239,9 @@ To reorder two columns where column 1 has `size="9" push="3"` and column 2 has `
- CSS classes now include the property name to improve clarity.
- `.spinner-[spinner-name]` β `.spinner-name-[spinner-name]`
- Specific theme classes (e.g., `ion-spinner.md`) are no longer supported. Style modifications based on the active theme must be implemented using theme tokens rather than direct class targeting.
+
+Textarea
+
+Converted `ion-textarea` to use [Shadow DOM](https://developer.mozilla.org/en-US/docs/Web/Web_Components/Using_shadow_DOM).
+
+If you were targeting the internals of `ion-textarea` in your CSS, you will need to target the `wrapper`, `container`, `label`, `native`, `supporting-text`, `helper-text`, `error-text`, `counter`, or `bottom` [Shadow Parts](https://ionicframework.com/docs/theming/css-shadow-parts) instead, or use the provided CSS Variables.
diff --git a/CHANGELOG.md b/CHANGELOG.md
index f5d8b1ae591..32f33d2cafe 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -3,6 +3,177 @@
All notable changes to this project will be documented in this file.
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
+## [8.8.6](https://github.com/ionic-team/ionic-framework/compare/v8.8.5...v8.8.6) (2026-05-06)
+
+
+### Bug Fixes
+
+* **action-sheet:** restore action-sheet-selected class on non-radio buttons ([#31109](https://github.com/ionic-team/ionic-framework/issues/31109)) ([c18502f](https://github.com/ionic-team/ionic-framework/commit/c18502f3efdec5440a11289235a93c62ce27ab89)), closes [#31090](https://github.com/ionic-team/ionic-framework/issues/31090)
+* **datetime:** prevent hidden-state observer from tearing down ready class on initial entry ([#31108](https://github.com/ionic-team/ionic-framework/issues/31108)) ([30b479a](https://github.com/ionic-team/ionic-framework/commit/30b479a53acbc16961002df256bec358dc11e7fa))
+* **segment:** segment drag would set disabled segment button checked ([#31112](https://github.com/ionic-team/ionic-framework/issues/31112)) ([44be424](https://github.com/ionic-team/ionic-framework/commit/44be424221bee11ffbe91c4b1fa0a4d56fe1ecac))
+
+
+
+
+
+## [8.8.5](https://github.com/ionic-team/ionic-framework/compare/v8.8.4...v8.8.5) (2026-04-29)
+
+
+### Bug Fixes
+
+* **modal:** remove safe-area gap and flash in fullscreen modals ([#31092](https://github.com/ionic-team/ionic-framework/issues/31092)) ([f3cd39b](https://github.com/ionic-team/ionic-framework/commit/f3cd39b7fb291286374285c4a326ec6b9a8ea237)), closes [#31015](https://github.com/ionic-team/ionic-framework/issues/31015)
+* **select:** select focused option on Enter in popover and modal interfaces ([#31093](https://github.com/ionic-team/ionic-framework/issues/31093)) ([fd79771](https://github.com/ionic-team/ionic-framework/commit/fd79771e5be77c9f38379a3a7b9ab44bb11ff325)), closes [#30561](https://github.com/ionic-team/ionic-framework/issues/30561)
+
+
+
+
+
+## [8.8.4](https://github.com/ionic-team/ionic-framework/compare/v8.8.3...v8.8.4) (2026-04-15)
+
+
+### Bug Fixes
+
+* **checkbox:** show labels after page navigation ([#31062](https://github.com/ionic-team/ionic-framework/issues/31062)) ([f4ac445](https://github.com/ionic-team/ionic-framework/commit/f4ac4459f8317bd5eeff7d4809f9cb0991c8efd9)), closes [#31052](https://github.com/ionic-team/ionic-framework/issues/31052)
+* **datetime:** multiple month selected and flakiness display ([#31053](https://github.com/ionic-team/ionic-framework/issues/31053)) ([308aef5](https://github.com/ionic-team/ionic-framework/commit/308aef569d8c6ebc3ad2186bca6969da8e4b2a8d))
+* **tab-button:** update dark palette focused background color ([#31050](https://github.com/ionic-team/ionic-framework/issues/31050)) ([dec46b5](https://github.com/ionic-team/ionic-framework/commit/dec46b5d317080dd5d97dc056f0d8e6d4c8c45ac))
+
+
+
+
+
+## [8.8.3](https://github.com/ionic-team/ionic-framework/compare/v8.8.2...v8.8.3) (2026-04-01)
+
+
+### Bug Fixes
+
+* **datetime:** scroll failing for adjacent days on ios ([#31033](https://github.com/ionic-team/ionic-framework/issues/31033)) ([3afd67f](https://github.com/ionic-team/ionic-framework/commit/3afd67f997521290a34c4448445ae227dc67f8f1))
+* **input-otp:** prevent deletion and paste when disabled or readonly ([#30983](https://github.com/ionic-team/ionic-framework/issues/30983)) ([81aa977](https://github.com/ionic-team/ionic-framework/commit/81aa977fde4867146adf67fcf72e24026574929c)), closes [#30913](https://github.com/ionic-team/ionic-framework/issues/30913)
+
+
+
+
+
+## [8.8.2](https://github.com/ionic-team/ionic-framework/compare/v8.8.1...v8.8.2) (2026-03-25)
+
+
+### Bug Fixes
+
+* **angular:** forward generic type parameter on ModalOptions and PopoverOptions ([#31022](https://github.com/ionic-team/ionic-framework/issues/31022)) ([cbfe7cc](https://github.com/ionic-team/ionic-framework/commit/cbfe7cce3be345eacbf9fe29e74438a927c16679)), closes [#31012](https://github.com/ionic-team/ionic-framework/issues/31012)
+* **checkbox:** re-evaluate label visibility when label is updated ([#30980](https://github.com/ionic-team/ionic-framework/issues/30980)) ([ce83407](https://github.com/ionic-team/ionic-framework/commit/ce83407e1debbe74f20d2d6dc2535a0ef3f974a0))
+* **datetime:** days keep in focus after changing the month ([#31021](https://github.com/ionic-team/ionic-framework/issues/31021)) ([5fdaba2](https://github.com/ionic-team/ionic-framework/commit/5fdaba2b021fe8b2b43a49eae7c687544c97d502))
+
+
+
+
+
+## [8.8.1](https://github.com/ionic-team/ionic-framework/compare/v8.8.0...v8.8.1) (2026-03-06)
+
+
+### Bug Fixes
+
+* **accordion:** update tabindex based on disabled state ([#30986](https://github.com/ionic-team/ionic-framework/issues/30986)) ([0e76a69](https://github.com/ionic-team/ionic-framework/commit/0e76a69370083702568825c29d63cf257d6b88f1))
+* **angular:** export RefresherPullEnd types ([#30991](https://github.com/ionic-team/ionic-framework/issues/30991)) ([72abcca](https://github.com/ionic-team/ionic-framework/commit/72abccaad8df3c1db004da28610fddd95ac93c02))
+
+
+### Features
+
+* **toast:** add wrapper and content parts (originally intended for 8.8.0 but omitted from that release) ([#30992](https://github.com/ionic-team/ionic-framework/issues/30992)) ([366f00e](https://github.com/ionic-team/ionic-framework/commit/366f00e25f06e28aa7166275445716c2d301e44a)), closes [#30735](https://github.com/ionic-team/ionic-framework/issues/30735)
+
+
+
+
+
+# [8.8.0](https://github.com/ionic-team/ionic-framework/compare/v8.7.18...v8.8.0) (2026-03-04)
+
+
+### Features
+
+* **angular:** add custom injector support for modal and popover controllers ([#30899](https://github.com/ionic-team/ionic-framework/issues/30899)) ([822da42](https://github.com/ionic-team/ionic-framework/commit/822da428af86cd9b036b81515272321eb8fa586c)), closes [#30638](https://github.com/ionic-team/ionic-framework/issues/30638)
+* **content:** add content-fullscreen class when fullscreen is true ([#30926](https://github.com/ionic-team/ionic-framework/issues/30926)) ([d74b11b](https://github.com/ionic-team/ionic-framework/commit/d74b11bc19d6268b256daf23ba6f107483c00320))
+* **datetime:** add header parts ([#30945](https://github.com/ionic-team/ionic-framework/issues/30945)) ([6ea186d](https://github.com/ionic-team/ionic-framework/commit/6ea186d96d80a94b774d4d0a51d536e0e5599935))
+* **datetime:** add wheel part to ion-picker-column ([#30934](https://github.com/ionic-team/ionic-framework/issues/30934)) ([0cf4c03](https://github.com/ionic-team/ionic-framework/commit/0cf4c03e298bb4f7eea71c966a1473765ebd6d7a))
+* **item-divider:** add inner and container parts ([#30928](https://github.com/ionic-team/ionic-framework/issues/30928)) ([5cdeb7f](https://github.com/ionic-team/ionic-framework/commit/5cdeb7fd357298f15e7ae29b14412d97bdc7c656))
+* **item-option:** add inner and container parts ([#30929](https://github.com/ionic-team/ionic-framework/issues/30929)) ([f8f7ffd](https://github.com/ionic-team/ionic-framework/commit/f8f7ffda318c0143d9bb5c79fe55b4ecb88e6ce3))
+* **item:** add inner and container parts ([#30927](https://github.com/ionic-team/ionic-framework/issues/30927)) ([a2c6559](https://github.com/ionic-team/ionic-framework/commit/a2c655923bb1cff51864949575e19028623c695d))
+* **list-header:** add inner part ([#30930](https://github.com/ionic-team/ionic-framework/issues/30930)) ([ef73476](https://github.com/ionic-team/ionic-framework/commit/ef73476e08670630907e775a38f9ed30a84e3f1f))
+* **modal:** add drag events for sheet and card modals ([#30962](https://github.com/ionic-team/ionic-framework/issues/30962)) ([d29ac71](https://github.com/ionic-team/ionic-framework/commit/d29ac713fad604c256fb385eb0c26eb9717e1ff4)), closes [#23955](https://github.com/ionic-team/ionic-framework/issues/23955)
+* **range:** add classes and expose parts to allow individual styling of dual knobs ([#30941](https://github.com/ionic-team/ionic-framework/issues/30941)) ([5bcf921](https://github.com/ionic-team/ionic-framework/commit/5bcf92184118055483bf306ab9e319b8e3e61870)), closes [#29862](https://github.com/ionic-team/ionic-framework/issues/29862)
+* **range:** add classes to the range when the value is at the min or max ([#30932](https://github.com/ionic-team/ionic-framework/issues/30932)) ([fac1a66](https://github.com/ionic-team/ionic-framework/commit/fac1a6673c88a531f1d79656be4eb544f235f819))
+* **refresher:** add ionPullStart and ionPullEnd events ([#30946](https://github.com/ionic-team/ionic-framework/issues/30946)) ([814c2e5](https://github.com/ionic-team/ionic-framework/commit/814c2e5ccd6d5bfda12bdf13a566cd66ff830d5b)), closes [#24524](https://github.com/ionic-team/ionic-framework/issues/24524)
+* **segment-view:** add swipeGesture property to disable swiping ([#30948](https://github.com/ionic-team/ionic-framework/issues/30948)) ([46806bd](https://github.com/ionic-team/ionic-framework/commit/46806bd6e2af90a0b31fca68f508c06d3d281ec0)), closes [#30290](https://github.com/ionic-team/ionic-framework/issues/30290)
+* **select:** add wrapper and bottom shadow parts ([#30951](https://github.com/ionic-team/ionic-framework/issues/30951)) ([5cea5ae](https://github.com/ionic-team/ionic-framework/commit/5cea5aeb44393edab7064e5980a1eb7e607d1b8d))
+* **select:** pass cancelText property to modal interface ([#30282](https://github.com/ionic-team/ionic-framework/issues/30282)) ([6e4f60a](https://github.com/ionic-team/ionic-framework/commit/6e4f60af4c188ae04028b444aa21118ae27c2ca7))
+* **textarea:** reflect disabled and readonly props ([#30910](https://github.com/ionic-team/ionic-framework/issues/30910)) ([55735df](https://github.com/ionic-team/ionic-framework/commit/55735df3fa62c8e259c56db3169f3d5459e71c0c))
+
+
+
+
+
+## [8.7.18](https://github.com/ionic-team/ionic-framework/compare/v8.7.17...v8.7.18) (2026-02-25)
+
+
+### Bug Fixes
+
+* **datetime:** stretch ion-buttons to fill space for ios ([#30963](https://github.com/ionic-team/ionic-framework/issues/30963)) ([d46b0b1](https://github.com/ionic-team/ionic-framework/commit/d46b0b15f6a652da6f863cf303e7ce06cfc820a8))
+* **many:** clear timeouts ([#30851](https://github.com/ionic-team/ionic-framework/issues/30851)) ([70b1237](https://github.com/ionic-team/ionic-framework/commit/70b1237823dd0cdab852486a6b2cbbfe0d0aaae9)), closes [#30860](https://github.com/ionic-team/ionic-framework/issues/30860)
+* **modal, popover:** respect safe area insets on popovers and modals ([#30949](https://github.com/ionic-team/ionic-framework/issues/30949)) ([6490797](https://github.com/ionic-team/ionic-framework/commit/6490797851cede3bfda893a19b10f165259ec988)), closes [#28411](https://github.com/ionic-team/ionic-framework/issues/28411)
+* **nav-controller:** reset direction state when navigation is canceled ([#30955](https://github.com/ionic-team/ionic-framework/issues/30955)) ([53172d1](https://github.com/ionic-team/ionic-framework/commit/53172d1a4035d5b510c230553aabd53dc1389e4b))
+* **radio-group:** prevent DOMException and NotFoundError when filtering radios ([#30958](https://github.com/ionic-team/ionic-framework/issues/30958)) ([682a17e](https://github.com/ionic-team/ionic-framework/commit/682a17ebb754da7714989623cf84b75e715e20e1)), closes [#30279](https://github.com/ionic-team/ionic-framework/issues/30279) [#30359](https://github.com/ionic-team/ionic-framework/issues/30359)
+* **toast:** keep icon on the same line as long message in stacked layout ([#30923](https://github.com/ionic-team/ionic-framework/issues/30923)) ([442e3e9](https://github.com/ionic-team/ionic-framework/commit/442e3e983107a69cea4fb5587fb33da718eee8a3)), closes [#30908](https://github.com/ionic-team/ionic-framework/issues/30908)
+
+
+
+
+
+## [8.7.17](https://github.com/ionic-team/ionic-framework/compare/v8.7.15...v8.7.17) (2026-01-14)
+
+
+### Bug Fixes
+
+* **input:** prevent Android TalkBack from focusing label separately ([#30895](https://github.com/ionic-team/ionic-framework/issues/30895)) ([ab733b7](https://github.com/ionic-team/ionic-framework/commit/ab733b71dd355d9486757f219fe09acaefeeefcc))
+* **input:** prevent placeholder from overlapping start slot during scroll assist ([#30896](https://github.com/ionic-team/ionic-framework/issues/30896)) ([3b3318d](https://github.com/ionic-team/ionic-framework/commit/3b3318da513b199128f3822bd8226797cd118b0f))
+* **tab-bar:** prevent keyboard controller memory leak on rapid mount/unmount ([#30906](https://github.com/ionic-team/ionic-framework/issues/30906)) ([f99d000](https://github.com/ionic-team/ionic-framework/commit/f99d0007a8ffc9c7d3d2636e912c37c12112b21d))
+
+
+
+
+
+## [8.7.16](https://github.com/ionic-team/ionic-framework/compare/v8.7.15...v8.7.16) (2025-12-31)
+
+
+### Bug Fixes
+
+* **modal:** prevent card modal animation on viewport resize when modal is closed ([#30894](https://github.com/ionic-team/ionic-framework/issues/30894)) ([e5634d4](https://github.com/ionic-team/ionic-framework/commit/e5634d45ee5fd32715f6e6b75e0448f74ee1f8f2)), closes [#30679](https://github.com/ionic-team/ionic-framework/issues/30679)
+
+
+
+
+
+## [8.7.15](https://github.com/ionic-team/ionic-framework/compare/v8.7.14...v8.7.15) (2025-12-23)
+
+
+### Bug Fixes
+
+* **core:** use Capacitor safe-area CSS variables on older WebViews ([#30865](https://github.com/ionic-team/ionic-framework/issues/30865)) ([8573bf8](https://github.com/ionic-team/ionic-framework/commit/8573bf8083f75eda13c954a56731a6aac8ca5724))
+* **header:** show iOS condense header when app is in MD mode ([#30690](https://github.com/ionic-team/ionic-framework/issues/30690)) ([f83b000](https://github.com/ionic-team/ionic-framework/commit/f83b0005309400d674e43c497bdffbcb9d2c4d94)), closes [#29929](https://github.com/ionic-team/ionic-framework/issues/29929)
+* **input-password-toggle:** improve screen reader announcements ([#30885](https://github.com/ionic-team/ionic-framework/issues/30885)) ([12ede4b](https://github.com/ionic-team/ionic-framework/commit/12ede4b79c8d5cffc2b014c7c8a0d2ef1d3bf90d))
+* **modal:** dismiss top-most overlay when multiple IDs match ([#30883](https://github.com/ionic-team/ionic-framework/issues/30883)) ([3b60a1d](https://github.com/ionic-team/ionic-framework/commit/3b60a1d68a1df1606ffee0bde7db7a206bac404a)), closes [#30030](https://github.com/ionic-team/ionic-framework/issues/30030)
+
+
+
+
+
+## [8.7.14](https://github.com/ionic-team/ionic-framework/compare/v8.7.13...v8.7.14) (2025-12-17)
+
+
+### Bug Fixes
+
+* **tabs:** select correct tab when routes have similar prefixes ([#30863](https://github.com/ionic-team/ionic-framework/issues/30863)) ([03fb422](https://github.com/ionic-team/ionic-framework/commit/03fb422bfa775e3e9dd695ea1857fa88d4245ecd)), closes [#30448](https://github.com/ionic-team/ionic-framework/issues/30448)
+
+
+
+
+
## [8.7.13](https://github.com/ionic-team/ionic-framework/compare/v8.7.12...v8.7.13) (2025-12-13)
**Note:** Version bump only for package ionic-framework
diff --git a/core/CHANGELOG.md b/core/CHANGELOG.md
index d71c543621e..0b0ea102b40 100644
--- a/core/CHANGELOG.md
+++ b/core/CHANGELOG.md
@@ -3,6 +3,171 @@
All notable changes to this project will be documented in this file.
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
+## [8.8.6](https://github.com/ionic-team/ionic-framework/compare/v8.8.5...v8.8.6) (2026-05-06)
+
+
+### Bug Fixes
+
+* **action-sheet:** restore action-sheet-selected class on non-radio buttons ([#31109](https://github.com/ionic-team/ionic-framework/issues/31109)) ([c18502f](https://github.com/ionic-team/ionic-framework/commit/c18502f3efdec5440a11289235a93c62ce27ab89)), closes [#31090](https://github.com/ionic-team/ionic-framework/issues/31090)
+* **datetime:** prevent hidden-state observer from tearing down ready class on initial entry ([#31108](https://github.com/ionic-team/ionic-framework/issues/31108)) ([30b479a](https://github.com/ionic-team/ionic-framework/commit/30b479a53acbc16961002df256bec358dc11e7fa))
+* **segment:** segment drag would set disabled segment button checked ([#31112](https://github.com/ionic-team/ionic-framework/issues/31112)) ([44be424](https://github.com/ionic-team/ionic-framework/commit/44be424221bee11ffbe91c4b1fa0a4d56fe1ecac))
+
+
+
+
+
+## [8.8.5](https://github.com/ionic-team/ionic-framework/compare/v8.8.4...v8.8.5) (2026-04-29)
+
+
+### Bug Fixes
+
+* **modal:** remove safe-area gap and flash in fullscreen modals ([#31092](https://github.com/ionic-team/ionic-framework/issues/31092)) ([f3cd39b](https://github.com/ionic-team/ionic-framework/commit/f3cd39b7fb291286374285c4a326ec6b9a8ea237)), closes [#31015](https://github.com/ionic-team/ionic-framework/issues/31015)
+* **select:** select focused option on Enter in popover and modal interfaces ([#31093](https://github.com/ionic-team/ionic-framework/issues/31093)) ([fd79771](https://github.com/ionic-team/ionic-framework/commit/fd79771e5be77c9f38379a3a7b9ab44bb11ff325)), closes [#30561](https://github.com/ionic-team/ionic-framework/issues/30561)
+
+
+
+
+
+## [8.8.4](https://github.com/ionic-team/ionic-framework/compare/v8.8.3...v8.8.4) (2026-04-15)
+
+
+### Bug Fixes
+
+* **checkbox:** show labels after page navigation ([#31062](https://github.com/ionic-team/ionic-framework/issues/31062)) ([f4ac445](https://github.com/ionic-team/ionic-framework/commit/f4ac4459f8317bd5eeff7d4809f9cb0991c8efd9)), closes [#31052](https://github.com/ionic-team/ionic-framework/issues/31052)
+* **datetime:** multiple month selected and flakiness display ([#31053](https://github.com/ionic-team/ionic-framework/issues/31053)) ([308aef5](https://github.com/ionic-team/ionic-framework/commit/308aef569d8c6ebc3ad2186bca6969da8e4b2a8d))
+* **tab-button:** update dark palette focused background color ([#31050](https://github.com/ionic-team/ionic-framework/issues/31050)) ([dec46b5](https://github.com/ionic-team/ionic-framework/commit/dec46b5d317080dd5d97dc056f0d8e6d4c8c45ac))
+
+
+
+
+
+## [8.8.3](https://github.com/ionic-team/ionic-framework/compare/v8.8.2...v8.8.3) (2026-04-01)
+
+
+### Bug Fixes
+
+* **datetime:** scroll failing for adjacent days on ios ([#31033](https://github.com/ionic-team/ionic-framework/issues/31033)) ([3afd67f](https://github.com/ionic-team/ionic-framework/commit/3afd67f997521290a34c4448445ae227dc67f8f1))
+* **input-otp:** prevent deletion and paste when disabled or readonly ([#30983](https://github.com/ionic-team/ionic-framework/issues/30983)) ([81aa977](https://github.com/ionic-team/ionic-framework/commit/81aa977fde4867146adf67fcf72e24026574929c)), closes [#30913](https://github.com/ionic-team/ionic-framework/issues/30913)
+
+
+
+
+
+## [8.8.2](https://github.com/ionic-team/ionic-framework/compare/v8.8.1...v8.8.2) (2026-03-25)
+
+
+### Bug Fixes
+
+* **checkbox:** re-evaluate label visibility when label is updated ([#30980](https://github.com/ionic-team/ionic-framework/issues/30980)) ([ce83407](https://github.com/ionic-team/ionic-framework/commit/ce83407e1debbe74f20d2d6dc2535a0ef3f974a0))
+* **datetime:** days keep in focus after changing the month ([#31021](https://github.com/ionic-team/ionic-framework/issues/31021)) ([5fdaba2](https://github.com/ionic-team/ionic-framework/commit/5fdaba2b021fe8b2b43a49eae7c687544c97d502))
+
+
+
+
+
+## [8.8.1](https://github.com/ionic-team/ionic-framework/compare/v8.8.0...v8.8.1) (2026-03-06)
+
+
+### Bug Fixes
+
+* **accordion:** update tabindex based on disabled state ([#30986](https://github.com/ionic-team/ionic-framework/issues/30986)) ([0e76a69](https://github.com/ionic-team/ionic-framework/commit/0e76a69370083702568825c29d63cf257d6b88f1))
+* **angular:** export RefresherPullEnd types ([#30991](https://github.com/ionic-team/ionic-framework/issues/30991)) ([72abcca](https://github.com/ionic-team/ionic-framework/commit/72abccaad8df3c1db004da28610fddd95ac93c02))
+
+
+### Features
+
+* **toast:** add wrapper and content parts (originally intended for 8.8.0 but omitted from that release) ([#30992](https://github.com/ionic-team/ionic-framework/issues/30992)) ([366f00e](https://github.com/ionic-team/ionic-framework/commit/366f00e25f06e28aa7166275445716c2d301e44a)), closes [#30735](https://github.com/ionic-team/ionic-framework/issues/30735)
+
+
+
+
+
+# [8.8.0](https://github.com/ionic-team/ionic-framework/compare/v8.7.18...v8.8.0) (2026-03-04)
+
+
+### Features
+
+* **content:** add content-fullscreen class when fullscreen is true ([#30926](https://github.com/ionic-team/ionic-framework/issues/30926)) ([d74b11b](https://github.com/ionic-team/ionic-framework/commit/d74b11bc19d6268b256daf23ba6f107483c00320))
+* **datetime:** add header parts ([#30945](https://github.com/ionic-team/ionic-framework/issues/30945)) ([6ea186d](https://github.com/ionic-team/ionic-framework/commit/6ea186d96d80a94b774d4d0a51d536e0e5599935))
+* **datetime:** add wheel part to ion-picker-column ([#30934](https://github.com/ionic-team/ionic-framework/issues/30934)) ([0cf4c03](https://github.com/ionic-team/ionic-framework/commit/0cf4c03e298bb4f7eea71c966a1473765ebd6d7a))
+* **item-divider:** add inner and container parts ([#30928](https://github.com/ionic-team/ionic-framework/issues/30928)) ([5cdeb7f](https://github.com/ionic-team/ionic-framework/commit/5cdeb7fd357298f15e7ae29b14412d97bdc7c656))
+* **item-option:** add inner and container parts ([#30929](https://github.com/ionic-team/ionic-framework/issues/30929)) ([f8f7ffd](https://github.com/ionic-team/ionic-framework/commit/f8f7ffda318c0143d9bb5c79fe55b4ecb88e6ce3))
+* **item:** add inner and container parts ([#30927](https://github.com/ionic-team/ionic-framework/issues/30927)) ([a2c6559](https://github.com/ionic-team/ionic-framework/commit/a2c655923bb1cff51864949575e19028623c695d))
+* **list-header:** add inner part ([#30930](https://github.com/ionic-team/ionic-framework/issues/30930)) ([ef73476](https://github.com/ionic-team/ionic-framework/commit/ef73476e08670630907e775a38f9ed30a84e3f1f))
+* **modal:** add drag events for sheet and card modals ([#30962](https://github.com/ionic-team/ionic-framework/issues/30962)) ([d29ac71](https://github.com/ionic-team/ionic-framework/commit/d29ac713fad604c256fb385eb0c26eb9717e1ff4)), closes [#23955](https://github.com/ionic-team/ionic-framework/issues/23955)
+* **range:** add classes and expose parts to allow individual styling of dual knobs ([#30941](https://github.com/ionic-team/ionic-framework/issues/30941)) ([5bcf921](https://github.com/ionic-team/ionic-framework/commit/5bcf92184118055483bf306ab9e319b8e3e61870)), closes [#29862](https://github.com/ionic-team/ionic-framework/issues/29862)
+* **range:** add classes to the range when the value is at the min or max ([#30932](https://github.com/ionic-team/ionic-framework/issues/30932)) ([fac1a66](https://github.com/ionic-team/ionic-framework/commit/fac1a6673c88a531f1d79656be4eb544f235f819))
+* **refresher:** add ionPullStart and ionPullEnd events ([#30946](https://github.com/ionic-team/ionic-framework/issues/30946)) ([814c2e5](https://github.com/ionic-team/ionic-framework/commit/814c2e5ccd6d5bfda12bdf13a566cd66ff830d5b)), closes [#24524](https://github.com/ionic-team/ionic-framework/issues/24524)
+* **segment-view:** add swipeGesture property to disable swiping ([#30948](https://github.com/ionic-team/ionic-framework/issues/30948)) ([46806bd](https://github.com/ionic-team/ionic-framework/commit/46806bd6e2af90a0b31fca68f508c06d3d281ec0)), closes [#30290](https://github.com/ionic-team/ionic-framework/issues/30290)
+* **select:** add wrapper and bottom shadow parts ([#30951](https://github.com/ionic-team/ionic-framework/issues/30951)) ([5cea5ae](https://github.com/ionic-team/ionic-framework/commit/5cea5aeb44393edab7064e5980a1eb7e607d1b8d))
+* **select:** pass cancelText property to modal interface ([#30282](https://github.com/ionic-team/ionic-framework/issues/30282)) ([6e4f60a](https://github.com/ionic-team/ionic-framework/commit/6e4f60af4c188ae04028b444aa21118ae27c2ca7))
+* **textarea:** reflect disabled and readonly props ([#30910](https://github.com/ionic-team/ionic-framework/issues/30910)) ([55735df](https://github.com/ionic-team/ionic-framework/commit/55735df3fa62c8e259c56db3169f3d5459e71c0c))
+
+
+
+
+
+## [8.7.18](https://github.com/ionic-team/ionic-framework/compare/v8.7.17...v8.7.18) (2026-02-25)
+
+
+### Bug Fixes
+
+* **datetime:** stretch ion-buttons to fill space for ios ([#30963](https://github.com/ionic-team/ionic-framework/issues/30963)) ([d46b0b1](https://github.com/ionic-team/ionic-framework/commit/d46b0b15f6a652da6f863cf303e7ce06cfc820a8))
+* **many:** clear timeouts ([#30851](https://github.com/ionic-team/ionic-framework/issues/30851)) ([70b1237](https://github.com/ionic-team/ionic-framework/commit/70b1237823dd0cdab852486a6b2cbbfe0d0aaae9)), closes [#30860](https://github.com/ionic-team/ionic-framework/issues/30860)
+* **modal, popover:** respect safe area insets on popovers and modals ([#30949](https://github.com/ionic-team/ionic-framework/issues/30949)) ([6490797](https://github.com/ionic-team/ionic-framework/commit/6490797851cede3bfda893a19b10f165259ec988)), closes [#28411](https://github.com/ionic-team/ionic-framework/issues/28411)
+* **radio-group:** prevent DOMException and NotFoundError when filtering radios ([#30958](https://github.com/ionic-team/ionic-framework/issues/30958)) ([682a17e](https://github.com/ionic-team/ionic-framework/commit/682a17ebb754da7714989623cf84b75e715e20e1)), closes [#30279](https://github.com/ionic-team/ionic-framework/issues/30279) [#30359](https://github.com/ionic-team/ionic-framework/issues/30359)
+* **toast:** keep icon on the same line as long message in stacked layout ([#30923](https://github.com/ionic-team/ionic-framework/issues/30923)) ([442e3e9](https://github.com/ionic-team/ionic-framework/commit/442e3e983107a69cea4fb5587fb33da718eee8a3)), closes [#30908](https://github.com/ionic-team/ionic-framework/issues/30908)
+
+
+
+
+
+## [8.7.17](https://github.com/ionic-team/ionic-framework/compare/v8.7.15...v8.7.17) (2026-01-14)
+
+
+### Bug Fixes
+
+* **input:** prevent Android TalkBack from focusing label separately ([#30895](https://github.com/ionic-team/ionic-framework/issues/30895)) ([ab733b7](https://github.com/ionic-team/ionic-framework/commit/ab733b71dd355d9486757f219fe09acaefeeefcc))
+* **input:** prevent placeholder from overlapping start slot during scroll assist ([#30896](https://github.com/ionic-team/ionic-framework/issues/30896)) ([3b3318d](https://github.com/ionic-team/ionic-framework/commit/3b3318da513b199128f3822bd8226797cd118b0f))
+* **tab-bar:** prevent keyboard controller memory leak on rapid mount/unmount ([#30906](https://github.com/ionic-team/ionic-framework/issues/30906)) ([f99d000](https://github.com/ionic-team/ionic-framework/commit/f99d0007a8ffc9c7d3d2636e912c37c12112b21d))
+
+
+
+
+
+## [8.7.16](https://github.com/ionic-team/ionic-framework/compare/v8.7.15...v8.7.16) (2025-12-31)
+
+
+### Bug Fixes
+
+* **modal:** prevent card modal animation on viewport resize when modal is closed ([#30894](https://github.com/ionic-team/ionic-framework/issues/30894)) ([e5634d4](https://github.com/ionic-team/ionic-framework/commit/e5634d45ee5fd32715f6e6b75e0448f74ee1f8f2)), closes [#30679](https://github.com/ionic-team/ionic-framework/issues/30679)
+
+
+
+
+
+## [8.7.15](https://github.com/ionic-team/ionic-framework/compare/v8.7.14...v8.7.15) (2025-12-23)
+
+
+### Bug Fixes
+
+* **core:** use Capacitor safe-area CSS variables on older WebViews ([#30865](https://github.com/ionic-team/ionic-framework/issues/30865)) ([8573bf8](https://github.com/ionic-team/ionic-framework/commit/8573bf8083f75eda13c954a56731a6aac8ca5724))
+* **header:** show iOS condense header when app is in MD mode ([#30690](https://github.com/ionic-team/ionic-framework/issues/30690)) ([f83b000](https://github.com/ionic-team/ionic-framework/commit/f83b0005309400d674e43c497bdffbcb9d2c4d94)), closes [#29929](https://github.com/ionic-team/ionic-framework/issues/29929)
+* **input-password-toggle:** improve screen reader announcements ([#30885](https://github.com/ionic-team/ionic-framework/issues/30885)) ([12ede4b](https://github.com/ionic-team/ionic-framework/commit/12ede4b79c8d5cffc2b014c7c8a0d2ef1d3bf90d))
+* **modal:** dismiss top-most overlay when multiple IDs match ([#30883](https://github.com/ionic-team/ionic-framework/issues/30883)) ([3b60a1d](https://github.com/ionic-team/ionic-framework/commit/3b60a1d68a1df1606ffee0bde7db7a206bac404a)), closes [#30030](https://github.com/ionic-team/ionic-framework/issues/30030)
+
+
+
+
+
+## [8.7.14](https://github.com/ionic-team/ionic-framework/compare/v8.7.13...v8.7.14) (2025-12-17)
+
+**Note:** Version bump only for package @ionic/core
+
+
+
+
+
## [8.7.13](https://github.com/ionic-team/ionic-framework/compare/v8.7.12...v8.7.13) (2025-12-13)
**Note:** Version bump only for package @ionic/core
diff --git a/core/Dockerfile b/core/Dockerfile
index 50a4687701c..374f962fdbe 100644
--- a/core/Dockerfile
+++ b/core/Dockerfile
@@ -1,5 +1,5 @@
# Get Playwright
-FROM mcr.microsoft.com/playwright:v1.56.1
+FROM mcr.microsoft.com/playwright:v1.58.2
# Set the working directory
WORKDIR /ionic
diff --git a/core/api.txt b/core/api.txt
index f2af11afc9b..a0e6fa5def2 100644
--- a/core/api.txt
+++ b/core/api.txt
@@ -555,7 +555,7 @@ ion-card,css-prop,--color,ios
ion-card,css-prop,--color,md
ion-card,part,native
-ion-card-content,none
+ion-card-content,shadow
ion-card-content,prop,mode,"ios" | "md",undefined,false,false
ion-card-content,prop,theme,"ios" | "md" | "ionic",undefined,false,false
@@ -881,9 +881,18 @@ ion-datetime,part,calendar-day
ion-datetime,part,calendar-day active
ion-datetime,part,calendar-day disabled
ion-datetime,part,calendar-day today
+ion-datetime,part,calendar-days-of-week
+ion-datetime,part,calendar-header
+ion-datetime,part,datetime-header
+ion-datetime,part,datetime-selected-date
+ion-datetime,part,datetime-title
ion-datetime,part,month-year-button
+ion-datetime,part,navigation-button
+ion-datetime,part,next-button
+ion-datetime,part,previous-button
ion-datetime,part,time-button
ion-datetime,part,time-button active
+ion-datetime,part,wheel
ion-datetime,part,wheel-item
ion-datetime,part,wheel-item active
@@ -1075,7 +1084,7 @@ ion-infinite-scroll-content,prop,theme,"ios" | "md" | "ionic",undefined,false,fa
ion-input,scoped
ion-input,prop,autocapitalize,string,'off',false,false
-ion-input,prop,autocomplete,"name" | "url" | "off" | "on" | "additional-name" | "address-level1" | "address-level2" | "address-level3" | "address-level4" | "address-line1" | "address-line2" | "address-line3" | "bday-day" | "bday-month" | "bday-year" | "cc-csc" | "cc-exp" | "cc-exp-month" | "cc-exp-year" | "cc-family-name" | "cc-given-name" | "cc-name" | "cc-number" | "cc-type" | "country" | "country-name" | "current-password" | "family-name" | "given-name" | "honorific-prefix" | "honorific-suffix" | "new-password" | "one-time-code" | "organization" | "postal-code" | "street-address" | "transaction-amount" | "transaction-currency" | "username" | "email" | "tel" | "tel-area-code" | "tel-country-code" | "tel-extension" | "tel-local" | "tel-national" | "nickname" | "organization-title" | "cc-additional-name" | "language" | "bday" | "sex" | "impp" | "photo",'off',false,false
+ion-input,prop,autocomplete,"additional-name" | "address-level1" | "address-level2" | "address-level3" | "address-level4" | "address-line1" | "address-line2" | "address-line3" | "bday" | "bday-day" | "bday-month" | "bday-year" | "cc-additional-name" | "cc-csc" | "cc-exp" | "cc-exp-month" | "cc-exp-year" | "cc-family-name" | "cc-given-name" | "cc-name" | "cc-number" | "cc-type" | "country" | "country-name" | "current-password" | "email" | "family-name" | "given-name" | "honorific-prefix" | "honorific-suffix" | "impp" | "language" | "name" | "new-password" | "nickname" | "off" | "on" | "one-time-code" | "organization" | "organization-title" | "photo" | "postal-code" | "sex" | "street-address" | "tel" | "tel-area-code" | "tel-country-code" | "tel-extension" | "tel-local" | "tel-national" | "transaction-amount" | "transaction-currency" | "url" | "username",'off',false,false
ion-input,prop,autocorrect,"off" | "on",'off',false,false
ion-input,prop,autofocus,boolean,false,false,false
ion-input,prop,clearInput,boolean,false,false,false
@@ -1170,18 +1179,20 @@ ion-input,css-prop,--placeholder-opacity,ionic
ion-input,css-prop,--placeholder-opacity,ios
ion-input,css-prop,--placeholder-opacity,md
-ion-input-otp,scoped
+ion-input-otp,shadow
ion-input-otp,prop,autocapitalize,string,'off',false,false
ion-input-otp,prop,color,"danger" | "dark" | "light" | "medium" | "primary" | "secondary" | "success" | "tertiary" | "warning" | string & Record | undefined,undefined,false,true
ion-input-otp,prop,disabled,boolean,false,false,true
ion-input-otp,prop,fill,"outline" | "solid" | undefined,'outline',false,false
ion-input-otp,prop,inputmode,"decimal" | "email" | "none" | "numeric" | "search" | "tel" | "text" | "url" | undefined,undefined,false,false
ion-input-otp,prop,length,number,4,false,false
+ion-input-otp,prop,mode,"ios" | "md",undefined,false,false
ion-input-otp,prop,pattern,string | undefined,undefined,false,false
ion-input-otp,prop,readonly,boolean,false,false,true
ion-input-otp,prop,separators,number[] | string | undefined,undefined,false,false
ion-input-otp,prop,shape,"rectangular" | "round" | "soft",'round',false,false
ion-input-otp,prop,size,"large" | "medium" | "small",'medium',false,false
+ion-input-otp,prop,theme,"ios" | "md" | "ionic",undefined,false,false
ion-input-otp,prop,type,"number" | "text",'number',false,false
ion-input-otp,prop,value,null | number | string | undefined,'',false,false
ion-input-otp,method,setFocus,setFocus(index?: number) => Promise
@@ -1262,6 +1273,11 @@ ion-input-otp,css-prop,--separator-width,md
ion-input-otp,css-prop,--width,ionic
ion-input-otp,css-prop,--width,ios
ion-input-otp,css-prop,--width,md
+ion-input-otp,part,container
+ion-input-otp,part,description
+ion-input-otp,part,group
+ion-input-otp,part,native
+ion-input-otp,part,separator
ion-input-password-toggle,shadow
ion-input-password-toggle,prop,color,"danger" | "dark" | "light" | "medium" | "primary" | "secondary" | "success" | "tertiary" | "warning" | string & Record | undefined,undefined,false,true
@@ -1378,7 +1394,9 @@ ion-item,css-prop,--ripple-color,md
ion-item,css-prop,--transition,ionic
ion-item,css-prop,--transition,ios
ion-item,css-prop,--transition,md
+ion-item,part,container
ion-item,part,detail-icon
+ion-item,part,inner
ion-item,part,native
ion-item-divider,shadow
@@ -1460,6 +1478,8 @@ ion-item-divider,css-prop,--ion-item-divider-thumbnail-margin-top
ion-item-divider,css-prop,--ion-item-divider-thumbnail-start-slotted-margin-end
ion-item-divider,css-prop,--ion-item-divider-thumbnail-start-slotted-margin-start
ion-item-divider,css-prop,--ion-item-divider-thumbnail-width
+ion-item-divider,part,container
+ion-item-divider,part,inner
ion-item-group,none
ion-item-group,prop,mode,"ios" | "md",undefined,false,false
@@ -1484,6 +1504,8 @@ ion-item-option,css-prop,--background,md
ion-item-option,css-prop,--color,ionic
ion-item-option,css-prop,--color,ios
ion-item-option,css-prop,--color,md
+ion-item-option,part,container
+ion-item-option,part,inner
ion-item-option,part,native
ion-item-options,none
@@ -1543,6 +1565,7 @@ ion-list-header,css-prop,--color,md
ion-list-header,css-prop,--inner-border-width,ionic
ion-list-header,css-prop,--inner-border-width,ios
ion-list-header,css-prop,--inner-border-width,md
+ion-list-header,part,inner
ion-loading,scoped
ion-loading,prop,animated,boolean,true,false,false
@@ -1733,6 +1756,9 @@ ion-modal,method,setCurrentBreakpoint,setCurrentBreakpoint(breakpoint: number) =
ion-modal,event,didDismiss,OverlayEventDetail,true
ion-modal,event,didPresent,void,true
ion-modal,event,ionBreakpointDidChange,ModalBreakpointChangeEventDetail,true
+ion-modal,event,ionDragEnd,ModalDragEventDetail,true
+ion-modal,event,ionDragMove,ModalDragEventDetail,true
+ion-modal,event,ionDragStart,void,true
ion-modal,event,ionModalDidDismiss,OverlayEventDetail,true
ion-modal,event,ionModalDidPresent,void,true
ion-modal,event,ionModalWillDismiss,OverlayEventDetail,true
@@ -1784,7 +1810,7 @@ ion-nav,prop,animated,boolean,true,false,false
ion-nav,prop,animation,((baseEl: any, opts?: any) => Animation) | undefined,undefined,false,false
ion-nav,prop,mode,"ios" | "md",undefined,false,false
ion-nav,prop,root,Function | HTMLElement | ViewController | null | string | undefined,undefined,false,false
-ion-nav,prop,rootParams,undefined | { [key: string]: any; },undefined,false,false
+ion-nav,prop,rootParams,T | undefined,undefined,false,false
ion-nav,prop,swipeGesture,boolean | undefined,undefined,false,false
ion-nav,prop,theme,"ios" | "md" | "ionic",undefined,false,false
ion-nav,method,canGoBack,canGoBack(view?: ViewController) => Promise
@@ -1806,7 +1832,7 @@ ion-nav,event,ionNavWillChange,void,false
ion-nav-link,none
ion-nav-link,prop,component,Function | HTMLElement | ViewController | null | string | undefined,undefined,false,false
-ion-nav-link,prop,componentProps,undefined | { [key: string]: any; },undefined,false,false
+ion-nav-link,prop,componentProps,T | undefined,undefined,false,false
ion-nav-link,prop,mode,"ios" | "md",undefined,false,false
ion-nav-link,prop,routerAnimation,((baseEl: any, opts?: any) => Animation) | undefined,undefined,false,false
ion-nav-link,prop,routerDirection,"back" | "forward" | "root",'forward',false,false
@@ -1911,7 +1937,7 @@ ion-popover,prop,animated,boolean,true,false,false
ion-popover,prop,arrow,boolean,true,false,false
ion-popover,prop,backdropDismiss,boolean,true,false,false
ion-popover,prop,component,Function | HTMLElement | null | string | undefined,undefined,false,false
-ion-popover,prop,componentProps,undefined | { [key: string]: any; },undefined,false,false
+ion-popover,prop,componentProps,T | undefined,undefined,false,false
ion-popover,prop,dismissOnSelect,boolean,false,false,false
ion-popover,prop,enterAnimation,((baseEl: any, opts?: any) => Animation) | undefined,undefined,false,false
ion-popover,prop,event,any,undefined,false,false
@@ -2106,11 +2132,28 @@ ion-range,css-prop,--pin-background,md
ion-range,css-prop,--pin-color,ionic
ion-range,css-prop,--pin-color,ios
ion-range,css-prop,--pin-color,md
+ion-range,part,activated
ion-range,part,bar
ion-range,part,bar-active
+ion-range,part,focused
+ion-range,part,hover
ion-range,part,knob
+ion-range,part,knob-a
+ion-range,part,knob-b
+ion-range,part,knob-handle
+ion-range,part,knob-handle-a
+ion-range,part,knob-handle-b
+ion-range,part,knob-handle-lower
+ion-range,part,knob-handle-upper
+ion-range,part,knob-lower
+ion-range,part,knob-upper
ion-range,part,label
ion-range,part,pin
+ion-range,part,pin-a
+ion-range,part,pin-b
+ion-range,part,pin-lower
+ion-range,part,pin-upper
+ion-range,part,pressed
ion-range,part,tick
ion-range,part,tick-active
@@ -2127,6 +2170,8 @@ ion-refresher,method,cancel,cancel() => Promise
ion-refresher,method,complete,complete() => Promise
ion-refresher,method,getProgress,getProgress() => Promise
ion-refresher,event,ionPull,void,true
+ion-refresher,event,ionPullEnd,RefresherPullEndEventDetail,true
+ion-refresher,event,ionPullStart,void,true
ion-refresher,event,ionRefresh,RefresherEventDetail,true
ion-refresher,event,ionStart,void,true
@@ -2210,7 +2255,7 @@ ion-row,css-prop,--ion-grid-gap
ion-searchbar,scoped
ion-searchbar,prop,animated,boolean,false,false,false
ion-searchbar,prop,autocapitalize,string,'off',false,false
-ion-searchbar,prop,autocomplete,"name" | "url" | "off" | "on" | "additional-name" | "address-level1" | "address-level2" | "address-level3" | "address-level4" | "address-line1" | "address-line2" | "address-line3" | "bday-day" | "bday-month" | "bday-year" | "cc-csc" | "cc-exp" | "cc-exp-month" | "cc-exp-year" | "cc-family-name" | "cc-given-name" | "cc-name" | "cc-number" | "cc-type" | "country" | "country-name" | "current-password" | "family-name" | "given-name" | "honorific-prefix" | "honorific-suffix" | "new-password" | "one-time-code" | "organization" | "postal-code" | "street-address" | "transaction-amount" | "transaction-currency" | "username" | "email" | "tel" | "tel-area-code" | "tel-country-code" | "tel-extension" | "tel-local" | "tel-national" | "nickname" | "organization-title" | "cc-additional-name" | "language" | "bday" | "sex" | "impp" | "photo",'off',false,false
+ion-searchbar,prop,autocomplete,"additional-name" | "address-level1" | "address-level2" | "address-level3" | "address-level4" | "address-line1" | "address-line2" | "address-line3" | "bday" | "bday-day" | "bday-month" | "bday-year" | "cc-additional-name" | "cc-csc" | "cc-exp" | "cc-exp-month" | "cc-exp-year" | "cc-family-name" | "cc-given-name" | "cc-name" | "cc-number" | "cc-type" | "country" | "country-name" | "current-password" | "email" | "family-name" | "given-name" | "honorific-prefix" | "honorific-suffix" | "impp" | "language" | "name" | "new-password" | "nickname" | "off" | "on" | "one-time-code" | "organization" | "organization-title" | "photo" | "postal-code" | "sex" | "street-address" | "tel" | "tel-area-code" | "tel-country-code" | "tel-extension" | "tel-local" | "tel-national" | "transaction-amount" | "transaction-currency" | "url" | "username",'off',false,false
ion-searchbar,prop,autocorrect,"off" | "on",'off',false,false
ion-searchbar,prop,cancelButtonIcon,string | undefined,undefined,false,false
ion-searchbar,prop,cancelButtonText,string,'Cancel',false,false
@@ -2387,9 +2432,11 @@ ion-segment-content,shadow
ion-segment-view,shadow
ion-segment-view,prop,disabled,boolean,false,false,false
+ion-segment-view,prop,swipeGesture,boolean,true,false,false
ion-segment-view,event,ionSegmentViewScroll,SegmentViewScrollEvent,true
ion-select,shadow
+ion-select,prop,cancelIcon,boolean,false,false,false
ion-select,prop,cancelText,string,'Cancel',false,false
ion-select,prop,color,"danger" | "dark" | "light" | "medium" | "primary" | "secondary" | "success" | "tertiary" | "warning" | string & Record | undefined,undefined,false,true
ion-select,prop,compareWith,((currentValue: any, compareValue: any) => boolean) | null | string | undefined,undefined,false,false
@@ -2469,21 +2516,48 @@ ion-select,css-prop,--placeholder-opacity,md
ion-select,css-prop,--ripple-color,ionic
ion-select,css-prop,--ripple-color,ios
ion-select,css-prop,--ripple-color,md
+ion-select,css-prop,--select-text-gap,ionic
+ion-select,css-prop,--select-text-gap,ios
+ion-select,css-prop,--select-text-gap,md
+ion-select,css-prop,--select-text-media-border-color,ionic
+ion-select,css-prop,--select-text-media-border-color,ios
+ion-select,css-prop,--select-text-media-border-color,md
+ion-select,css-prop,--select-text-media-border-radius,ionic
+ion-select,css-prop,--select-text-media-border-radius,ios
+ion-select,css-prop,--select-text-media-border-radius,md
+ion-select,css-prop,--select-text-media-border-style,ionic
+ion-select,css-prop,--select-text-media-border-style,ios
+ion-select,css-prop,--select-text-media-border-style,md
+ion-select,css-prop,--select-text-media-border-width,ionic
+ion-select,css-prop,--select-text-media-border-width,ios
+ion-select,css-prop,--select-text-media-border-width,md
+ion-select,css-prop,--select-text-media-height,ionic
+ion-select,css-prop,--select-text-media-height,ios
+ion-select,css-prop,--select-text-media-height,md
+ion-select,css-prop,--select-text-media-width,ionic
+ion-select,css-prop,--select-text-media-width,ios
+ion-select,css-prop,--select-text-media-width,md
+ion-select,part,bottom
ion-select,part,container
ion-select,part,error-text
ion-select,part,helper-text
ion-select,part,icon
+ion-select,part,inner
ion-select,part,label
ion-select,part,placeholder
ion-select,part,supporting-text
ion-select,part,text
+ion-select,part,wrapper
ion-select-modal,scoped
+ion-select-modal,prop,cancelIcon,boolean,false,false,false
+ion-select-modal,prop,cancelText,string,'Close',false,false
ion-select-modal,prop,header,string | undefined,undefined,false,false
ion-select-modal,prop,multiple,boolean | undefined,undefined,false,false
ion-select-modal,prop,options,SelectModalOption[],[],false,false
ion-select-option,shadow
+ion-select-option,prop,description,string | undefined,undefined,false,false
ion-select-option,prop,disabled,boolean,false,false,false
ion-select-option,prop,mode,"ios" | "md",undefined,false,false
ion-select-option,prop,theme,"ios" | "md" | "ionic",undefined,false,false
@@ -2553,6 +2627,7 @@ ion-tab,method,setActive,setActive() => Promise
ion-tab-bar,shadow
ion-tab-bar,prop,color,"danger" | "dark" | "light" | "medium" | "primary" | "secondary" | "success" | "tertiary" | "warning" | string & Record | undefined,undefined,false,true
ion-tab-bar,prop,expand,"compact" | "full",'full',false,false
+ion-tab-bar,prop,hideOnScroll,boolean,false,false,false
ion-tab-bar,prop,mode,"ios" | "md",undefined,false,false
ion-tab-bar,prop,selectedTab,string | undefined,undefined,false,false
ion-tab-bar,prop,shape,"rectangular" | "round" | "soft" | undefined,undefined,false,false
@@ -2629,7 +2704,7 @@ ion-text,prop,color,"danger" | "dark" | "light" | "medium" | "primary" | "second
ion-text,prop,mode,"ios" | "md",undefined,false,false
ion-text,prop,theme,"ios" | "md" | "ionic",undefined,false,false
-ion-textarea,scoped
+ion-textarea,shadow
ion-textarea,prop,autoGrow,boolean,false,false,true
ion-textarea,prop,autocapitalize,string,'none',false,false
ion-textarea,prop,autofocus,boolean,false,false,false
@@ -2639,7 +2714,7 @@ ion-textarea,prop,cols,number | undefined,undefined,false,true
ion-textarea,prop,counter,boolean,false,false,false
ion-textarea,prop,counterFormatter,((inputLength: number, maxLength: number) => string) | undefined,undefined,false,false
ion-textarea,prop,debounce,number | undefined,undefined,false,false
-ion-textarea,prop,disabled,boolean,false,false,false
+ion-textarea,prop,disabled,boolean,false,false,true
ion-textarea,prop,enterkeyhint,"done" | "enter" | "go" | "next" | "previous" | "search" | "send" | undefined,undefined,false,false
ion-textarea,prop,errorText,string | undefined,undefined,false,false
ion-textarea,prop,fill,"outline" | "solid" | undefined,undefined,false,false
@@ -2652,8 +2727,8 @@ ion-textarea,prop,minlength,number | undefined,undefined,false,false
ion-textarea,prop,mode,"ios" | "md",undefined,false,false
ion-textarea,prop,name,string,this.inputId,false,false
ion-textarea,prop,placeholder,string | undefined,undefined,false,false
-ion-textarea,prop,readonly,boolean,false,false,false
-ion-textarea,prop,required,boolean,false,false,false
+ion-textarea,prop,readonly,boolean,false,false,true
+ion-textarea,prop,required,boolean,false,false,true
ion-textarea,prop,rows,number | undefined,undefined,false,false
ion-textarea,prop,shape,"rectangular" | "round" | "soft" | undefined,undefined,false,false
ion-textarea,prop,size,"large" | "medium" | "small" | undefined,'medium',false,false
@@ -2721,6 +2796,15 @@ ion-textarea,css-prop,--placeholder-font-weight,md
ion-textarea,css-prop,--placeholder-opacity,ionic
ion-textarea,css-prop,--placeholder-opacity,ios
ion-textarea,css-prop,--placeholder-opacity,md
+ion-textarea,part,bottom
+ion-textarea,part,container
+ion-textarea,part,counter
+ion-textarea,part,error-text
+ion-textarea,part,helper-text
+ion-textarea,part,label
+ion-textarea,part,native
+ion-textarea,part,supporting-text
+ion-textarea,part,wrapper
ion-thumbnail,shadow
ion-thumbnail,prop,mode,"ios" | "md",undefined,false,false
@@ -2827,9 +2911,11 @@ ion-toast,css-prop,--width,md
ion-toast,part,button
ion-toast,part,button cancel
ion-toast,part,container
+ion-toast,part,content
ion-toast,part,header
ion-toast,part,icon
ion-toast,part,message
+ion-toast,part,wrapper
ion-toggle,shadow
ion-toggle,prop,alignment,"center" | "start" | undefined,undefined,false,false
@@ -2896,6 +2982,7 @@ ion-toolbar,shadow
ion-toolbar,prop,color,"danger" | "dark" | "light" | "medium" | "primary" | "secondary" | "success" | "tertiary" | "warning" | string & Record | undefined,undefined,false,true
ion-toolbar,prop,mode,"ios" | "md",undefined,false,false
ion-toolbar,prop,theme,"ios" | "md" | "ionic",undefined,false,false
+ion-toolbar,prop,titlePlacement,"center" | "end" | "start" | undefined,undefined,false,false
ion-toolbar,css-prop,--background,ionic
ion-toolbar,css-prop,--background,ios
ion-toolbar,css-prop,--background,md
diff --git a/core/package-lock.json b/core/package-lock.json
index d273935ea14..25e7b64662b 100644
--- a/core/package-lock.json
+++ b/core/package-lock.json
@@ -1,29 +1,28 @@
{
"name": "@ionic/core",
- "version": "8.7.13",
+ "version": "8.8.6",
"lockfileVersion": 3,
"requires": true,
"packages": {
"": {
"name": "@ionic/core",
- "version": "8.7.13",
+ "version": "8.8.6",
"license": "MIT",
"dependencies": {
"@phosphor-icons/core": "^2.1.1",
- "@stencil/core": "4.38.0",
+ "@stencil/core": "4.43.0",
"ionicons": "^8.0.13",
"tslib": "^2.1.0"
},
"devDependencies": {
- "@axe-core/playwright": "^4.11.0",
+ "@axe-core/playwright": "^4.11.1",
"@capacitor/core": "^8.0.0",
"@capacitor/haptics": "^8.0.0",
"@capacitor/keyboard": "^8.0.0",
"@capacitor/status-bar": "^8.0.0",
- "@clack/prompts": "^0.11.0",
"@ionic/eslint-config": "^0.3.0",
"@ionic/prettier-config": "^2.0.0",
- "@playwright/test": "^1.56.1",
+ "@playwright/test": "^1.58.2",
"@rollup/plugin-node-resolve": "^8.4.0",
"@rollup/plugin-virtual": "^2.0.3",
"@stencil/angular-output-target": "^0.10.0",
@@ -45,8 +44,8 @@
"fs-extra": "^9.0.1",
"jest": "^29.7.0",
"jest-cli": "^29.7.0",
- "outsystems-design-tokens": "^1.3.4",
- "playwright-core": "^1.56.1",
+ "outsystems-design-tokens": "^1.3.8",
+ "playwright-core": "^1.58.2",
"prettier": "^2.8.8",
"rollup": "^2.26.4",
"sass": "^1.33.0",
@@ -64,11 +63,13 @@
"dev": true
},
"node_modules/@axe-core/playwright": {
- "version": "4.11.0",
+ "version": "4.11.1",
+ "resolved": "https://registry.npmjs.org/@axe-core/playwright/-/playwright-4.11.1.tgz",
+ "integrity": "sha512-mKEfoUIB1MkVTht0BGZFXtSAEKXMJoDkyV5YZ9jbBmZCcWDz71tegNsdTkIN8zc/yMi5Gm2kx7Z5YQ9PfWNAWw==",
"dev": true,
"license": "MPL-2.0",
"dependencies": {
- "axe-core": "~4.11.0"
+ "axe-core": "~4.11.1"
},
"peerDependencies": {
"playwright-core": ">= 1.0.0"
@@ -97,7 +98,6 @@
"version": "7.16.12",
"dev": true,
"license": "MIT",
- "peer": true,
"dependencies": {
"@babel/code-frame": "^7.16.7",
"@babel/generator": "^7.16.8",
@@ -714,20 +714,19 @@
}
},
"node_modules/@capacitor/core": {
- "version": "8.0.0",
- "resolved": "https://registry.npmjs.org/@capacitor/core/-/core-8.0.0.tgz",
- "integrity": "sha512-250HTVd/W/KdMygoqaedisvNbHbpbQTN2Hy/8ZYGm1nAqE0Fx7sGss4l0nDg33STxEdDhtVRoL2fIaaiukKseA==",
+ "version": "8.3.1",
+ "resolved": "https://registry.npmjs.org/@capacitor/core/-/core-8.3.1.tgz",
+ "integrity": "sha512-UF8ItlHguU1Z6GXfPTeT2gakf+ctNI8pAS1kwSBQlsJMlfD4OPoto/SmKnOxKCQvnF4WRcdWeg6C0zREUNaAQg==",
"dev": true,
"license": "MIT",
- "peer": true,
"dependencies": {
"tslib": "^2.1.0"
}
},
"node_modules/@capacitor/haptics": {
- "version": "8.0.0",
- "resolved": "https://registry.npmjs.org/@capacitor/haptics/-/haptics-8.0.0.tgz",
- "integrity": "sha512-DY1IUOjke1T4ITl7mFHQIKCaJJyHYAYRYHG9bVApU7PDOZiMVGMp48Yjzdqjya+wv/AHS5mDabSTUmhJ5uDvBA==",
+ "version": "8.0.2",
+ "resolved": "https://registry.npmjs.org/@capacitor/haptics/-/haptics-8.0.2.tgz",
+ "integrity": "sha512-c2hZzRR5Fk1tbTvhG1jhh2XBAf3EhnIerMIb2sl7Mt41Gxx1fhBJFDa0/BI1IbY4loVepyyuqNC9820/GZuoWQ==",
"dev": true,
"license": "MIT",
"peerDependencies": {
@@ -735,9 +734,9 @@
}
},
"node_modules/@capacitor/keyboard": {
- "version": "8.0.0",
- "resolved": "https://registry.npmjs.org/@capacitor/keyboard/-/keyboard-8.0.0.tgz",
- "integrity": "sha512-ycPW6iQyFwzDK95jihesj5EGiyyGSfbBqNek11iNp9tBOB7zDeYkUA2S/vPpOETt3dhP6pWr7a9gNVGuEfj11g==",
+ "version": "8.0.3",
+ "resolved": "https://registry.npmjs.org/@capacitor/keyboard/-/keyboard-8.0.3.tgz",
+ "integrity": "sha512-27Bv5/2w1Ss2njguBgTS98O0Bb8DRJhAARyzXYib0JlT/n6BrJw/EZ0CokM4C8GFUjFDjJnEKF1Ie01buTMEXQ==",
"dev": true,
"license": "MIT",
"peerDependencies": {
@@ -745,15 +744,16 @@
}
},
"node_modules/@capacitor/status-bar": {
- "version": "8.0.0",
- "resolved": "https://registry.npmjs.org/@capacitor/status-bar/-/status-bar-8.0.0.tgz",
- "integrity": "sha512-aIj3bc7z8lfPgOen8HlrBrkfnxpFnh21OCx6jCUx4Mvv+B6eEkUQ49b32DOddgVfr+igRHLX2SYi7duqIsNDXg==",
+ "version": "8.0.2",
+ "resolved": "https://registry.npmjs.org/@capacitor/status-bar/-/status-bar-8.0.2.tgz",
+ "integrity": "sha512-WXs8YB8B9eEaPZz+bcdY6t2nForF1FLoj/JU0Dl9RRgQnddnS98FEEyDooQhaY7wivr000j4+SC1FyeJkrFO7A==",
"dev": true,
"license": "MIT",
"peerDependencies": {
"@capacitor/core": ">=8.0.0"
}
},
+<<<<<<< HEAD
"node_modules/@clack/core": {
"version": "0.5.0",
"dev": true,
@@ -1215,6 +1215,8 @@
"node": ">=18"
}
},
+=======
+>>>>>>> origin/next
"node_modules/@eslint-community/eslint-utils": {
"version": "4.4.0",
"dev": true,
@@ -1399,7 +1401,6 @@
"version": "4.33.0",
"dev": true,
"license": "BSD-2-Clause",
- "peer": true,
"dependencies": {
"@typescript-eslint/scope-manager": "4.33.0",
"@typescript-eslint/types": "4.33.0",
@@ -2360,11 +2361,13 @@
"license": "MIT"
},
"node_modules/@playwright/test": {
- "version": "1.56.1",
+ "version": "1.58.2",
+ "resolved": "https://registry.npmjs.org/@playwright/test/-/test-1.58.2.tgz",
+ "integrity": "sha512-akea+6bHYBBfA9uQqSYmlJXn61cTa+jbO87xVLCWbTqbWadRVmhxlXATaOjOgcBaWU4ePo0wB41KMFv3o35IXA==",
"dev": true,
"license": "Apache-2.0",
"dependencies": {
- "playwright": "1.56.1"
+ "playwright": "1.58.2"
},
"bin": {
"playwright": "cli.js"
@@ -2549,9 +2552,10 @@
}
},
"node_modules/@stencil/core": {
- "version": "4.38.0",
+ "version": "4.43.0",
+ "resolved": "https://registry.npmjs.org/@stencil/core/-/core-4.43.0.tgz",
+ "integrity": "sha512-6Uj2Z3lzLuufYAE7asZ6NLKgSwsB9uxl84Eh34PASnUjfj32GkrP4DtKK7fNeh1WFGGyffsTDka3gwtl+4reUg==",
"license": "MIT",
- "peer": true,
"bin": {
"stencil": "bin/stencil"
},
@@ -2981,7 +2985,6 @@
"version": "6.7.2",
"dev": true,
"license": "BSD-2-Clause",
- "peer": true,
"dependencies": {
"@typescript-eslint/scope-manager": "6.7.2",
"@typescript-eslint/types": "6.7.2",
@@ -3207,6 +3210,7 @@
"integrity": "sha512-vay5/oQJdsNHmliWoZfHPoVZZRmnSWhug0BYT34njkYTPqClh3DNWLkZNJBVSjsNMrg0CCrBfoKkjZQPM/QVUw==",
"dev": true,
"license": "MIT",
+ "peer": true,
"dependencies": {
"@babel/parser": "^7.28.5",
"@vue/shared": "3.5.25",
@@ -3221,6 +3225,7 @@
"integrity": "sha512-V0hjH4dGPh9Ao5p0MoRY6BVqtwCjhz6vI5LT8AJ55H+4g9/4vbHx1I54fS0XuclLhDHArPQCiMjDxjaL8fPxhw==",
"dev": true,
"license": "BSD-2-Clause",
+ "peer": true,
"engines": {
"node": ">=0.12"
},
@@ -3233,7 +3238,8 @@
"resolved": "https://registry.npmjs.org/estree-walker/-/estree-walker-2.0.2.tgz",
"integrity": "sha512-Rfkk/Mp/DL7JVje3u18FxFujQlTNR2q6QfMSMB7AvCBx91NGj/ba3kCfza0f6dVDbw7YlRf/nDrn7pQrCCyQ/w==",
"dev": true,
- "license": "MIT"
+ "license": "MIT",
+ "peer": true
},
"node_modules/@vue/compiler-dom": {
"version": "3.5.25",
@@ -3241,6 +3247,7 @@
"integrity": "sha512-4We0OAcMZsKgYoGlMjzYvaoErltdFI2/25wqanuTu+S4gismOTRTBPi4IASOjxWdzIwrYSjnqONfKvuqkXzE2Q==",
"dev": true,
"license": "MIT",
+ "peer": true,
"dependencies": {
"@vue/compiler-core": "3.5.25",
"@vue/shared": "3.5.25"
@@ -3252,6 +3259,7 @@
"integrity": "sha512-PUgKp2rn8fFsI++lF2sO7gwO2d9Yj57Utr5yEsDf3GNaQcowCLKL7sf+LvVFvtJDXUp/03+dC6f2+LCv5aK1ag==",
"dev": true,
"license": "MIT",
+ "peer": true,
"dependencies": {
"@babel/parser": "^7.28.5",
"@vue/compiler-core": "3.5.25",
@@ -3269,7 +3277,8 @@
"resolved": "https://registry.npmjs.org/estree-walker/-/estree-walker-2.0.2.tgz",
"integrity": "sha512-Rfkk/Mp/DL7JVje3u18FxFujQlTNR2q6QfMSMB7AvCBx91NGj/ba3kCfza0f6dVDbw7YlRf/nDrn7pQrCCyQ/w==",
"dev": true,
- "license": "MIT"
+ "license": "MIT",
+ "peer": true
},
"node_modules/@vue/compiler-sfc/node_modules/postcss": {
"version": "8.5.6",
@@ -3291,6 +3300,7 @@
}
],
"license": "MIT",
+ "peer": true,
"dependencies": {
"nanoid": "^3.3.11",
"picocolors": "^1.1.1",
@@ -3306,6 +3316,7 @@
"integrity": "sha512-ritPSKLBcParnsKYi+GNtbdbrIE1mtuFEJ4U1sWeuOMlIziK5GtOL85t5RhsNy4uWIXPgk+OUdpnXiTdzn8o3A==",
"dev": true,
"license": "MIT",
+ "peer": true,
"dependencies": {
"@vue/compiler-dom": "3.5.25",
"@vue/shared": "3.5.25"
@@ -3317,6 +3328,7 @@
"integrity": "sha512-5xfAypCQepv4Jog1U4zn8cZIcbKKFka3AgWHEFQeK65OW+Ys4XybP6z2kKgws4YB43KGpqp5D/K3go2UPPunLA==",
"dev": true,
"license": "MIT",
+ "peer": true,
"dependencies": {
"@vue/shared": "3.5.25"
}
@@ -3327,6 +3339,7 @@
"integrity": "sha512-Z751v203YWwYzy460bzsYQISDfPjHTl+6Zzwo/a3CsAf+0ccEjQ8c+0CdX1WsumRTHeywvyUFtW6KvNukT/smA==",
"dev": true,
"license": "MIT",
+ "peer": true,
"dependencies": {
"@vue/reactivity": "3.5.25",
"@vue/shared": "3.5.25"
@@ -3338,6 +3351,7 @@
"integrity": "sha512-a4WrkYFbb19i9pjkz38zJBg8wa/rboNERq3+hRRb0dHiJh13c+6kAbgqCPfMaJ2gg4weWD3APZswASOfmKwamA==",
"dev": true,
"license": "MIT",
+ "peer": true,
"dependencies": {
"@vue/reactivity": "3.5.25",
"@vue/runtime-core": "3.5.25",
@@ -3351,6 +3365,7 @@
"integrity": "sha512-UJaXR54vMG61i8XNIzTSf2Q7MOqZHpp8+x3XLGtE3+fL+nQd+k7O5+X3D/uWrnQXOdMw5VPih+Uremcw+u1woQ==",
"dev": true,
"license": "MIT",
+ "peer": true,
"dependencies": {
"@vue/compiler-ssr": "3.5.25",
"@vue/shared": "3.5.25"
@@ -3364,7 +3379,8 @@
"resolved": "https://registry.npmjs.org/@vue/shared/-/shared-3.5.25.tgz",
"integrity": "sha512-AbOPdQQnAnzs58H2FrrDxYj/TJfmeS2jdfEEhgiKINy+bnOANmVizIEgq1r+C5zsbs6l1CCQxtcj71rwNQ4jWg==",
"dev": true,
- "license": "MIT"
+ "license": "MIT",
+ "peer": true
},
"node_modules/@zeit/schemas": {
"version": "2.21.0",
@@ -3399,7 +3415,6 @@
"version": "7.4.0",
"dev": true,
"license": "MIT",
- "peer": true,
"bin": {
"acorn": "bin/acorn"
},
@@ -3633,7 +3648,9 @@
}
},
"node_modules/axe-core": {
- "version": "4.11.0",
+ "version": "4.11.1",
+ "resolved": "https://registry.npmjs.org/axe-core/-/axe-core-4.11.1.tgz",
+ "integrity": "sha512-BASOg+YwO2C+346x3LZOeoovTIoTrRqEsqMa6fmfAV0P+U9mFr9NsyOEpiYvFjbc64NMrSswhV50WdXzdb/Z5A==",
"dev": true,
"license": "MPL-2.0",
"engines": {
@@ -4696,7 +4713,8 @@
"resolved": "https://registry.npmjs.org/csstype/-/csstype-3.2.3.tgz",
"integrity": "sha512-z1HGKcYy2xA8AGQfwrn0PAy+PB7X/GSj3UVJW9qKyn43xWa+gl5nXmU4qqLMRzWVLFC8KusUX8T/0kCiOYpAIQ==",
"dev": true,
- "license": "MIT"
+ "license": "MIT",
+ "peer": true
},
"node_modules/debug": {
"version": "2.6.9",
@@ -5107,7 +5125,6 @@
"version": "7.32.0",
"dev": true,
"license": "MIT",
- "peer": true,
"dependencies": {
"@babel/code-frame": "7.12.11",
"@eslint/eslintrc": "^0.4.3",
@@ -8585,6 +8602,7 @@
"integrity": "sha512-vd2F4YUyEXKGcLHoq+TEyCjxueSeHnFxyyjNp80yg0XV4vUhnDer/lvvlqM/arB5bXQN5K2/3oinyCRyx8T2CQ==",
"dev": true,
"license": "MIT",
+ "peer": true,
"dependencies": {
"@jridgewell/sourcemap-codec": "^1.5.5"
}
@@ -8950,6 +8968,7 @@
}
],
"license": "MIT",
+ "peer": true,
"bin": {
"nanoid": "bin/nanoid.cjs"
},
@@ -9148,9 +9167,9 @@
}
},
"node_modules/outsystems-design-tokens": {
- "version": "1.3.6",
- "resolved": "https://registry.npmjs.org/outsystems-design-tokens/-/outsystems-design-tokens-1.3.6.tgz",
- "integrity": "sha512-j+m64nl3hfCDRniU47WwlGWDvvdCRI2tQ9DpFtG4l5SLxf1tMTtbuHalrmfKCDWdx3W8eguyF7GKR6mkE7Z37g==",
+ "version": "1.3.8",
+ "resolved": "https://registry.npmjs.org/outsystems-design-tokens/-/outsystems-design-tokens-1.3.8.tgz",
+ "integrity": "sha512-hT2r9Crd7rn1ewG9hzx7bUA5AjxEdzFsaxzUJ11DqBW86aHmc2ImsCUkaavMlADmZ1g/ZHxV/eO5Bmy3lWKpmA==",
"dev": true,
"license": "BSD-3-Clause",
"dependencies": {
@@ -9432,11 +9451,13 @@
}
},
"node_modules/playwright": {
- "version": "1.56.1",
+ "version": "1.58.2",
+ "resolved": "https://registry.npmjs.org/playwright/-/playwright-1.58.2.tgz",
+ "integrity": "sha512-vA30H8Nvkq/cPBnNw4Q8TWz1EJyqgpuinBcHET0YVJVFldr8JDNiU9LaWAE1KqSkRYazuaBhTpB5ZzShOezQ6A==",
"dev": true,
"license": "Apache-2.0",
"dependencies": {
- "playwright-core": "1.56.1"
+ "playwright-core": "1.58.2"
},
"bin": {
"playwright": "cli.js"
@@ -9449,12 +9470,11 @@
}
},
"node_modules/playwright-core": {
- "version": "1.56.1",
- "resolved": "https://registry.npmjs.org/playwright-core/-/playwright-core-1.56.1.tgz",
- "integrity": "sha512-hutraynyn31F+Bifme+Ps9Vq59hKuUCz7H1kDOcBs+2oGguKkWTU50bBWrtz34OUWmIwpBTWDxaRPXrIXkgvmQ==",
+ "version": "1.58.2",
+ "resolved": "https://registry.npmjs.org/playwright-core/-/playwright-core-1.58.2.tgz",
+ "integrity": "sha512-yZkEtftgwS8CsfYo7nm0KE8jsvm6i/PTgVtB8DL726wNf6H2IMsDuxCpJj59KDaxCtSnrWan2AeDqM7JBaultg==",
"dev": true,
"license": "Apache-2.0",
- "peer": true,
"bin": {
"playwright-core": "cli.js"
},
@@ -9476,7 +9496,6 @@
"version": "7.0.35",
"dev": true,
"license": "MIT",
- "peer": true,
"dependencies": {
"chalk": "^2.4.2",
"source-map": "^0.6.1",
@@ -9582,7 +9601,6 @@
"version": "0.36.2",
"dev": true,
"license": "MIT",
- "peer": true,
"peerDependencies": {
"postcss": ">=5.0.0"
}
@@ -9633,7 +9651,6 @@
"integrity": "sha512-tdN8qQGvNjw4CHbY+XXk0JgCXn9QiF21a55rBe5LJAU+kDyC4WQn4+awm2Xfk2lQMk5fKup9XgzTZtGkjBdP9Q==",
"dev": true,
"license": "MIT",
- "peer": true,
"bin": {
"prettier": "bin-prettier.js"
},
@@ -10017,7 +10034,6 @@
"version": "2.35.1",
"dev": true,
"license": "MIT",
- "peer": true,
"bin": {
"rollup": "dist/bin/rollup"
},
@@ -10338,6 +10354,7 @@
"integrity": "sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA==",
"dev": true,
"license": "BSD-3-Clause",
+ "peer": true,
"engines": {
"node": ">=0.10.0"
}
@@ -11097,8 +11114,7 @@
},
"node_modules/tslib": {
"version": "2.1.0",
- "license": "0BSD",
- "peer": true
+ "license": "0BSD"
},
"node_modules/tsutils": {
"version": "3.21.0",
diff --git a/core/package.json b/core/package.json
index 1e99261352e..563478ed3aa 100644
--- a/core/package.json
+++ b/core/package.json
@@ -1,6 +1,6 @@
{
"name": "@ionic/core",
- "version": "8.7.13",
+ "version": "8.8.6",
"description": "Base components for Ionic",
"engines": {
"node": ">= 16"
@@ -35,20 +35,19 @@
],
"dependencies": {
"@phosphor-icons/core": "^2.1.1",
- "@stencil/core": "4.38.0",
+ "@stencil/core": "4.43.0",
"ionicons": "^8.0.13",
"tslib": "^2.1.0"
},
"devDependencies": {
- "@axe-core/playwright": "^4.11.0",
+ "@axe-core/playwright": "^4.11.1",
"@capacitor/core": "^8.0.0",
"@capacitor/haptics": "^8.0.0",
"@capacitor/keyboard": "^8.0.0",
"@capacitor/status-bar": "^8.0.0",
- "@clack/prompts": "^0.11.0",
"@ionic/eslint-config": "^0.3.0",
"@ionic/prettier-config": "^2.0.0",
- "@playwright/test": "^1.56.1",
+ "@playwright/test": "^1.58.2",
"@rollup/plugin-node-resolve": "^8.4.0",
"@rollup/plugin-virtual": "^2.0.3",
"@stencil/angular-output-target": "^0.10.0",
@@ -70,8 +69,8 @@
"fs-extra": "^9.0.1",
"jest": "^29.7.0",
"jest-cli": "^29.7.0",
- "outsystems-design-tokens": "^1.3.4",
- "playwright-core": "^1.56.1",
+ "outsystems-design-tokens": "^1.3.8",
+ "playwright-core": "^1.58.2",
"prettier": "^2.8.8",
"rollup": "^2.26.4",
"sass": "^1.33.0",
@@ -110,8 +109,7 @@
"docker.build": "docker build -t ionic-playwright .",
"test.e2e.docker": "npm run docker.build && node ./scripts/docker.mjs",
"test.e2e.docker.update-snapshots": "npm run test.e2e.docker -- --update-snapshots='changed'",
- "test.e2e.docker.ci": "npm run docker.build && CI=true node ./scripts/docker.mjs",
- "test.e2e.script": "node scripts/testing/e2e-script.mjs"
+ "test.e2e.docker.ci": "npm run docker.build && CI=true node ./scripts/docker.mjs"
},
"author": "Ionic Team",
"license": "MIT",
diff --git a/core/scripts/testing/e2e-script.mjs b/core/scripts/testing/e2e-script.mjs
deleted file mode 100644
index 794447bf61c..00000000000
--- a/core/scripts/testing/e2e-script.mjs
+++ /dev/null
@@ -1,260 +0,0 @@
-// The purpose of this script is to provide a way run the E2E tests
-// without having the developer to manually run multiple commands based
-// on the desired end result.
-// E.g. update the local ground truths for a specific component or
-// open the Playwright report after running the E2E tests.
-
-import {
- intro,
- outro,
- confirm,
- spinner,
- isCancel,
- cancel,
- text,
- log,
-} from '@clack/prompts';
-import { exec, spawn } from 'child_process';
-import fs from 'node:fs';
-import { setTimeout as sleep } from 'node:timers/promises';
-import util from 'node:util';
-import color from 'picocolors';
-
-async function main() {
- const execAsync = util.promisify(exec);
- const cleanUpFiles = async () => {
- // Clean up the local ground truths.
- const cleanUp = spinner();
-
- // Inform the user that the local ground truths are being cleaned up.
- cleanUp.start('Restoring local ground truths');
-
- // Reset the local ground truths.
- await execAsync('git reset -- src/**/*-linux.png').catch((error) => {
- cleanUp.stop('Failed to reset local ground truths');
- console.error(error);
- return process.exit(0);
- });
-
- // Restore the local ground truths.
- await execAsync('git restore -- src/**/*-linux.png').catch((error) => {
- cleanUp.stop('Failed to restore local ground truths');
- console.error(error);
- return process.exit(0);
- });
-
- // Inform the user that the local ground truths have been cleaned up.
- cleanUp.stop('Local ground truths have been restored to their original state in order to avoid committing them.');
- };
-
- intro(color.inverse(' Update Local Ground Truths'));
-
- // Ask user for the component name they want to test.
- const componentValue = await text({
- message: 'Enter the component or path you want to test (e.g. chip, src/components/chip)',
- placeholder: 'Empty for all components',
- });
-
- // User cancelled the operation with `Ctrl+C` or `CMD+C`.
- if (isCancel(componentValue)) {
- cancel('Operation cancelled');
- return process.exit(0);
- }
-
- // Ask user if they want to update their local ground truths.
- const shouldUpdateTruths = await confirm({
- message: 'Do you want to update your local ground truths?',
- });
-
- // User cancelled the operation with `Ctrl+C` or `CMD+C`.
- if (isCancel(shouldUpdateTruths)) {
- cancel('Operation cancelled');
- return process.exit(0);
- }
-
- if (shouldUpdateTruths) {
- const defaultBaseBranch = 'main';
-
- // Ask user for the base branch.
- let baseBranch = await text({
- message: 'Enter the base branch name:',
- placeholder: `default: ${defaultBaseBranch}`,
- })
-
- // User cancelled the operation with `Ctrl+C` or `CMD+C`.
- if (isCancel(baseBranch)) {
- cancel('Operation cancelled');
- return process.exit(0);
- }
-
- // User didn't provide a base branch.
- if (!baseBranch) {
- baseBranch = defaultBaseBranch;
- }
-
- /**
- * The provided base branch needs to be fetched.
- * This ensures that the local base branch is up-to-date with the
- * remote base branch. Otherwise, there might be errors stating that
- * certain files don't exist in the local base branch.
- */
- const fetchBaseBranch = spinner();
-
- // Inform the user that the base branch is being fetched.
- fetchBaseBranch.start(`Fetching "${baseBranch}" to have the latest changes`);
-
- // Fetch the base branch.
- await execAsync(`git fetch origin ${baseBranch}`).catch((error) => {
- fetchBaseBranch.stop(`Failed to fetch "${baseBranch}"`);
- console.error(error);
- return process.exit(0);
- });
-
- // Inform the user that the base branch has been fetched.
- fetchBaseBranch.stop(`Fetched "${baseBranch}"`);
-
-
- const updateGroundTruth = spinner();
-
- // Inform the user that the local ground truths are being updated.
- updateGroundTruth.start('Updating local ground truths');
-
- // Check if user provided an existing file or directory.
- const isValidLocation = fs.existsSync(componentValue);
-
- // User provided an existing file or directory.
- if (isValidLocation) {
- const stats = fs.statSync(componentValue);
-
- // User provided a file as the component.
- // ex: `componentValue` = `src/components/chip/test/basic/chip.e2e.ts`
- if (stats.isFile()) {
- // Update the local ground truths for the provided path.
- await execAsync(`git checkout origin/${baseBranch} -- ${componentValue}-snapshots/*-linux.png`).catch((error) => {
- updateGroundTruth.stop('Failed to update local ground truths');
- console.error(error);
- return process.exit(0);
- });
- }
-
- // User provided a directory as the component.
- // ex: `componentValue` = `src/components/chip`
- if (stats.isDirectory()) {
- // Update the local ground truths for the provided directory.
- await execAsync(`git checkout origin/${baseBranch} -- ${componentValue}/test/*/*.e2e.ts-snapshots/*-linux.png`).catch((error) => {
- updateGroundTruth.stop('Failed to update local ground truths');
- console.error(error);
- return process.exit(0);
- });
- }
- }
- // User provided a component name as the component.
- // ex: `componentValue` = `chip`
- else if (componentValue) {
- // Update the local ground truths for the provided component.
- await execAsync(`git checkout origin/${baseBranch} -- src/components/${componentValue}/test/*/${componentValue}.e2e.ts-snapshots/*-linux.png`).catch((error) => {
- updateGroundTruth.stop('Failed to update local ground truths');
- console.error(error);
- return process.exit(0);
- });
- }
- // User provided an empty string.
- else {
- // Update the local ground truths for all components.
- await execAsync(`git checkout origin/${baseBranch} -- src/components/*/test/*/*.e2e.ts-snapshots/*-linux.png`).catch((error) => {
- updateGroundTruth.stop('Failed to update local ground truths');
- console.error(error);
- return process.exit(0);
- });
- }
-
- // Inform the user that the local ground truths have been updated.
- updateGroundTruth.stop('Updated local ground truths');
- }
-
- const buildCore = spinner();
-
- // Inform the user that the core is being built.
- buildCore.start('Building core');
-
- /**
- * Build core
- * Otherwise, the uncommitted changes will not be reflected in the tests because:
- * - popping the stash doesn't trigger a re-render even if `npm start` is running
- * - app is not running the `npm start` command
- */
- await execAsync('npm run build').catch((error) => {
- // Clean up the local ground truths.
- cleanUpFiles();
-
- buildCore.stop('Failed to build core');
- console.error(error);
- return process.exit(0);
- });
-
- buildCore.stop('Built core');
-
- const runE2ETests = spinner();
-
- // Inform the user that the E2E tests are being run.
- runE2ETests.start('Running E2E tests');
-
- // User provided a component value.
- if (componentValue) {
- await execAsync(`npm run test.e2e.docker.ci ${componentValue}`).catch((error) => {
- // Clean up the local ground truths.
- cleanUpFiles();
-
- runE2ETests.stop('Failed to run E2E tests');
- console.error(error);
- return process.exit(0);
- });
- } else {
- await execAsync('npm run test.e2e.docker.ci').catch((error) => {
- // Clean up the local ground truths.
- cleanUpFiles();
-
- runE2ETests.stop('Failed to run E2E tests');
- console.error(error);
- return process.exit(0);
- });
- }
-
- runE2ETests.stop('Ran E2E tests');
-
- // Clean up the local ground truths.
- await cleanUpFiles();
-
- // Ask user if they want to open the Playwright report.
- const shouldOpenReport = await confirm({
- message: 'Do you want to open the Playwright report?',
- });
-
- // User cancelled the operation with `Ctrl+C` or `CMD+C`.
- if (isCancel(shouldOpenReport)) {
- cancel('Operation cancelled');
- return process.exit(0);
- }
-
- // User chose to open the Playwright report.
- if (shouldOpenReport) {
- // Use spawn to display the server information and the key to quit the server.
- spawn('npx', ['playwright', 'show-report'], {
- stdio: 'inherit',
- });
- } else {
- // Inform the user that the Playwright report can be opened by running the following command.
- log.info('If you change your mind, you can open the Playwright report by running the following command:');
- log.info(color.bold('npx playwright show-report'));
- }
-
- if (shouldOpenReport) {
- outro("You're all set! Don't forget to quit serving the Playwright report when you're done.");
- } else {
- outro("You're all set!");
- }
-
- await sleep(1000);
-}
-
-main().catch(console.error);
diff --git a/core/scripts/vercel-build.sh b/core/scripts/vercel-build.sh
new file mode 100755
index 00000000000..99c83b22adc
--- /dev/null
+++ b/core/scripts/vercel-build.sh
@@ -0,0 +1,360 @@
+#!/bin/bash
+#
+# Vercel preview build script
+#
+# Builds core component tests (same as before) plus framework test apps
+# (Angular, React, Vue) so they're all accessible from a single preview URL.
+#
+# Core tests: /src/components/{name}/test/{scenario}
+# Angular test app: /angular/
+# React test app: /react/
+# Vue test app: /vue/
+#
+set -e
+
+# Vercel places core/ at /vercel/path1 (bind mount). The full repo clone
+# lives at /vercel/path0. We can't rely on `..` to reach it, so we search.
+CORE_DIR=$(pwd)
+OUTPUT_DIR="${CORE_DIR}/../_vercel_output"
+
+# Find the actual repo root (the directory containing packages/)
+REPO_ROOT=""
+for candidate in /vercel/path0 /vercel/path1 "${CORE_DIR}/.."; do
+ if [ -d "${candidate}/packages" ]; then
+ REPO_ROOT="${candidate}"
+ break
+ fi
+done
+
+echo "=== Ionic Framework Preview Build ==="
+echo "Core dir: ${CORE_DIR}"
+echo "Repo root: ${REPO_ROOT:-NOT FOUND}"
+if [ -z "${REPO_ROOT}" ]; then
+ echo "(This is expected in some Vercel configs -- framework test apps will be skipped)"
+fi
+
+rm -rf "${OUTPUT_DIR}"
+mkdir -p "${OUTPUT_DIR}"
+
+# Step 1 - Build Core (dependencies already installed by Vercel installCommand)
+echo ""
+echo "--- Step 1: Building Core ---"
+npm run build
+
+# Copy core files to output. The test HTML files use relative paths like
+# ../../../../../dist/ionic/ionic.esm.js so the directory structure must
+# be preserved exactly.
+echo "Copying core output..."
+cp -r "${CORE_DIR}/src" "${OUTPUT_DIR}/src"
+cp -r "${CORE_DIR}/dist" "${OUTPUT_DIR}/dist"
+cp -r "${CORE_DIR}/css" "${OUTPUT_DIR}/css"
+mkdir -p "${OUTPUT_DIR}/scripts"
+cp -r "${CORE_DIR}/scripts/testing" "${OUTPUT_DIR}/scripts/testing"
+
+# Generate directory index pages so users can browse core test pages.
+# Creates an index.html in every directory under src/components/ that
+# doesn't already have one. Only includes child directories that eventually
+# lead to a test page (an index.html). Prunes snapshot dirs and dead ends.
+echo "Generating directory indexes for core tests..."
+generate_dir_index() {
+ local dir="$1"
+ local url_path="$2"
+ # Skip if an index.html already exists (it's an actual test page)
+ [ -f "${dir}/index.html" ] && return
+
+ # Absolute hrefs based on url_path. Vercel does not redirect to add trailing
+ # slashes, so a relative href like "basic/" from a URL without a trailing
+ # slash resolves against the parent directory and breaks navigation.
+ local parent_path="${url_path%/}"
+ parent_path="${parent_path%/*}/"
+
+ local entries=""
+ for child in "${dir}"/*/; do
+ [ -d "${child}" ] || continue
+ local name=$(basename "${child}")
+ # Skip snapshot directories and hidden dirs
+ case "${name}" in *-snapshots|.*) continue ;; esac
+ # Only include if there's at least one index.html somewhere underneath
+ find "${child}" -name "index.html" -print -quit | grep -q . || continue
+ entries="${entries}${name}/\n"
+ done
+
+ [ -z "${entries}" ] && return
+
+ cat > "${dir}/index.html" << IDXEOF
+
+
+
+
+
+ Index of ${url_path}
+
+
+
+ Index of ${url_path}
+ ../
+$(echo -e "${entries}")
+
+
+IDXEOF
+}
+
+# Walk all directories under src/ (bottom-up so parent indexes reflect pruned children)
+find "${OUTPUT_DIR}/src" -depth -type d | while IFS= read -r dir; do
+ url_path="${dir#${OUTPUT_DIR}}"
+ generate_dir_index "${dir}" "${url_path}/"
+done
+
+# Vercel mounts core/ at a separate path (path1) from the repo clone (path0).
+# Framework packages reference core via relative paths (../../core/css etc.),
+# which resolve to path0/core/ -- not path1/ where we just built.
+# Symlink path0/core -> path1 so those references find the build outputs.
+if [ -n "${REPO_ROOT}" ] && [ "${CORE_DIR}" != "${REPO_ROOT}/core" ] && [ -d "${REPO_ROOT}/core" ]; then
+ echo "Linking ${REPO_ROOT}/core -> ${CORE_DIR} (so framework builds find core outputs)"
+ rm -rf "${REPO_ROOT}/core"
+ ln -s "${CORE_DIR}" "${REPO_ROOT}/core"
+fi
+
+# Check if the full repo is available
+if [ -z "${REPO_ROOT}" ]; then
+ echo ""
+ echo "WARNING: Could not find repo root (no directory with packages/ found)"
+ echo "Only core tests will be deployed (framework test apps require the full repo)."
+
+ # Generate landing page and exit -- core tests are still useful
+ cat > "${OUTPUT_DIR}/index.html" << 'LANDING_EOF'
+
+Ionic Framework - Preview
+Ionic Framework Preview
Core tests only. Browse to /src/components/{name}/test/{scenario}/
+
+LANDING_EOF
+
+ echo "=== Preview build complete (core only) ==="
+ exit 0
+fi
+
+# Step 2 - Build Framework Packages (parallel)
+echo ""
+echo "--- Step 2: Building Framework Packages ---"
+
+build_angular_pkgs() {
+ (cd "${REPO_ROOT}/packages/angular" && npm install && npm run sync && npm run build) || return 1
+ (cd "${REPO_ROOT}/packages/angular-server" && npm install && npm run build) || return 1
+}
+
+build_react_pkgs() {
+ (cd "${REPO_ROOT}/packages/react" && npm install && npm run sync && npm run build) || return 1
+ (cd "${REPO_ROOT}/packages/react-router" && npm install && npm run build) || return 1
+}
+
+build_vue_pkgs() {
+ (cd "${REPO_ROOT}/packages/vue" && npm install && npm run sync && npm run build) || return 1
+ (cd "${REPO_ROOT}/packages/vue-router" && npm install && npm run build) || return 1
+}
+
+build_angular_pkgs > /tmp/vercel-angular-pkg.log 2>&1 &
+PID_ANG=$!
+build_react_pkgs > /tmp/vercel-react-pkg.log 2>&1 &
+PID_REACT=$!
+build_vue_pkgs > /tmp/vercel-vue-pkg.log 2>&1 &
+PID_VUE=$!
+
+ANG_PKG_OK=true; REACT_PKG_OK=true; VUE_PKG_OK=true
+wait $PID_ANG || { echo "Angular packages failed:"; tail -30 /tmp/vercel-angular-pkg.log; ANG_PKG_OK=false; }
+wait $PID_REACT || { echo "React packages failed:"; tail -30 /tmp/vercel-react-pkg.log; REACT_PKG_OK=false; }
+wait $PID_VUE || { echo "Vue packages failed:"; tail -30 /tmp/vercel-vue-pkg.log; VUE_PKG_OK=false; }
+
+if ! $ANG_PKG_OK || ! $REACT_PKG_OK || ! $VUE_PKG_OK; then
+ echo "ERROR: Some framework package builds failed."
+ echo "Core tests will still be deployed. Skipping failed framework test apps."
+else
+ echo "All framework packages built."
+fi
+
+# Step 3 - Build Framework Test Apps (parallel)
+echo ""
+echo "--- Step 3: Building Framework Test Apps ---"
+
+# Find the best available app version for a given package.
+# Scans the apps/ directory and picks the newest version (reverse version sort).
+pick_app() {
+ local apps_dir="$1/apps"
+ [ -d "${apps_dir}" ] || return 1
+ local app
+ app=$(ls -1d "${apps_dir}"/*/ 2>/dev/null | xargs -n1 basename | sort -V -r | head -1)
+ [ -n "${app}" ] && echo "${app}" && return 0
+ return 1
+}
+
+build_angular_test() {
+ local APP
+ APP=$(pick_app "${REPO_ROOT}/packages/angular/test") || {
+ echo "[angular] No test app found, skipping."
+ return 0
+ }
+ echo "[angular] Building ${APP}..."
+
+ cd "${REPO_ROOT}/packages/angular/test"
+ ./build.sh "${APP}"
+ cd "build/${APP}"
+ npm install
+ npm run sync
+ # --base-href sets so Angular Router works under the sub-path
+ npm run build -- --base-href /angular/
+
+ # Output path assumes the 'browser' builder. If migrated to 'application' builder, update this.
+ if [ ! -d "dist/test-app/browser" ]; then
+ echo "[angular] ERROR: Expected output at dist/test-app/browser/ not found."
+ return 1
+ fi
+ mkdir -p "${OUTPUT_DIR}/angular"
+ cp -r dist/test-app/browser/* "${OUTPUT_DIR}/angular/"
+ echo "[angular] Done."
+}
+
+build_react_test() {
+ local APP
+ APP=$(pick_app "${REPO_ROOT}/packages/react/test") || {
+ echo "[react] No test app found, skipping."
+ return 0
+ }
+ echo "[react] Building ${APP}..."
+
+ cd "${REPO_ROOT}/packages/react/test"
+ ./build.sh "${APP}"
+ cd "build/${APP}"
+ npm install
+ npm run sync
+ # --base sets Vite's base URL; import.meta.env.BASE_URL is read by IonReactRouter basename
+ npx vite build --base /react/
+
+ mkdir -p "${OUTPUT_DIR}/react"
+ cp -r dist/* "${OUTPUT_DIR}/react/"
+ echo "[react] Done."
+}
+
+build_vue_test() {
+ local APP
+ APP=$(pick_app "${REPO_ROOT}/packages/vue/test") || {
+ echo "[vue] No test app found, skipping."
+ return 0
+ }
+ echo "[vue] Building ${APP}..."
+
+ cd "${REPO_ROOT}/packages/vue/test"
+ ./build.sh "${APP}"
+ cd "build/${APP}"
+ npm install
+ npm run sync
+ # Vue Router already reads import.meta.env.BASE_URL which Vite sets from --base
+ npx vite build --base /vue/
+
+ mkdir -p "${OUTPUT_DIR}/vue"
+ cp -r dist/* "${OUTPUT_DIR}/vue/"
+ echo "[vue] Done."
+}
+
+# TODO: Add build_react_router_test() when reactrouter6-* apps are added to
+# packages/react-router/test/apps/
+
+TEST_FAILED=""
+
+if $ANG_PKG_OK; then
+ build_angular_test > /tmp/vercel-angular-test.log 2>&1 &
+ PID_ANG_TEST=$!
+fi
+if $REACT_PKG_OK; then
+ build_react_test > /tmp/vercel-react-test.log 2>&1 &
+ PID_REACT_TEST=$!
+fi
+if $VUE_PKG_OK; then
+ build_vue_test > /tmp/vercel-vue-test.log 2>&1 &
+ PID_VUE_TEST=$!
+fi
+
+if $ANG_PKG_OK; then
+ wait $PID_ANG_TEST || { echo "Angular test app failed:"; tail -30 /tmp/vercel-angular-test.log; TEST_FAILED="${TEST_FAILED} angular"; }
+fi
+if $REACT_PKG_OK; then
+ wait $PID_REACT_TEST || { echo "React test app failed:"; tail -30 /tmp/vercel-react-test.log; TEST_FAILED="${TEST_FAILED} react"; }
+fi
+if $VUE_PKG_OK; then
+ wait $PID_VUE_TEST || { echo "Vue test app failed:"; tail -30 /tmp/vercel-vue-test.log; TEST_FAILED="${TEST_FAILED} vue"; }
+fi
+
+if [ -n "${TEST_FAILED}" ]; then
+ echo ""
+ echo "WARNING: Some test app builds failed:${TEST_FAILED}"
+ echo "Core tests and successful framework apps will still be deployed."
+fi
+
+# Step 4 - Landing Page
+echo ""
+echo "--- Step 4: Generating landing page ---"
+
+cat > "${OUTPUT_DIR}/index.html" << 'LANDING_EOF'
+
+
+
+
+
+ Ionic Framework - Preview
+
+
+
+
+
Ionic Framework Preview
+
Component test apps for manual validation
+
+
+
+
+LANDING_EOF
+
+echo ""
+echo "=== Preview build complete ==="
+ls -la "${OUTPUT_DIR}"
diff --git a/core/setupJest.js b/core/setupJest.js
index f2eb0e70a31..77ea127c680 100644
--- a/core/setupJest.js
+++ b/core/setupJest.js
@@ -8,7 +8,9 @@ expect.extend({
throw new Error('expected toHaveShadowPart to be called on an element with a shadow root');
}
- const shadowPart = received.shadowRoot.querySelector(`[part="${part}"]`);
+ // Use attribute selector with ~= to match space-separated part values
+ // e.g., [part~="knob"] matches elements with part="knob" or part="knob knob-a"
+ const shadowPart = received.shadowRoot.querySelector(`[part~="${part}"]`);
const pass = shadowPart !== null;
const message = `expected ${received.tagName.toLowerCase()} to have shadow part "${part}"`;
diff --git a/core/src/components.d.ts b/core/src/components.d.ts
index fb7e5f9cff6..1c737c6faac 100644
--- a/core/src/components.d.ts
+++ b/core/src/components.d.ts
@@ -22,7 +22,7 @@ import { SpinnerTypes } from "./components/spinner/spinner-configs";
import { InputChangeEventDetail, InputInputEventDetail } from "./components/input/input-interface";
import { InputOtpChangeEventDetail, InputOtpCompleteEventDetail, InputOtpInputEventDetail } from "./components/input-otp/input-otp-interface";
import { MenuChangeEventDetail, MenuCloseEventDetail, MenuType, Side } from "./components/menu/menu-interface";
-import { ModalBreakpointChangeEventDetail, ModalHandleBehavior } from "./components/modal/modal-interface";
+import { ModalBreakpointChangeEventDetail, ModalDragEventDetail, ModalHandleBehavior } from "./components/modal/modal-interface";
import { NavComponent, NavComponentWithProps, NavOptions, RouterOutletOptions, SwipeGestureHandler, TransitionDoneFn, TransitionInstruction } from "./components/nav/nav-interface";
import { ViewController } from "./components/nav/view-controller";
import { PickerChangeEventDetail } from "./components/picker/picker-interfaces";
@@ -32,7 +32,7 @@ import { PopoverSize, PositionAlign, PositionReference, PositionSide, TriggerAct
import { IonProgressBarShape } from "./components/progress-bar/progress-bar.interfaces";
import { RadioGroupChangeEventDetail, RadioGroupCompareFn } from "./components/radio-group/radio-group-interface";
import { PinFormatter, RangeChangeEventDetail, RangeKnobMoveEndEventDetail, RangeKnobMoveStartEventDetail, RangeValue } from "./components/range/range-interface";
-import { RefresherEventDetail } from "./components/refresher/refresher-interface";
+import { RefresherEventDetail, RefresherPullEndEventDetail } from "./components/refresher/refresher-interface";
import { ItemReorderEventDetail, ReorderEndEventDetail, ReorderMoveEventDetail } from "./components/reorder-group/reorder-group-interface";
import { NavigationHookCallback } from "./components/route/route-interface";
import { SearchbarChangeEventDetail, SearchbarInputEventDetail } from "./components/searchbar/searchbar-interface";
@@ -64,7 +64,7 @@ export { SpinnerTypes } from "./components/spinner/spinner-configs";
export { InputChangeEventDetail, InputInputEventDetail } from "./components/input/input-interface";
export { InputOtpChangeEventDetail, InputOtpCompleteEventDetail, InputOtpInputEventDetail } from "./components/input-otp/input-otp-interface";
export { MenuChangeEventDetail, MenuCloseEventDetail, MenuType, Side } from "./components/menu/menu-interface";
-export { ModalBreakpointChangeEventDetail, ModalHandleBehavior } from "./components/modal/modal-interface";
+export { ModalBreakpointChangeEventDetail, ModalDragEventDetail, ModalHandleBehavior } from "./components/modal/modal-interface";
export { NavComponent, NavComponentWithProps, NavOptions, RouterOutletOptions, SwipeGestureHandler, TransitionDoneFn, TransitionInstruction } from "./components/nav/nav-interface";
export { ViewController } from "./components/nav/view-controller";
export { PickerChangeEventDetail } from "./components/picker/picker-interfaces";
@@ -74,7 +74,7 @@ export { PopoverSize, PositionAlign, PositionReference, PositionSide, TriggerAct
export { IonProgressBarShape } from "./components/progress-bar/progress-bar.interfaces";
export { RadioGroupChangeEventDetail, RadioGroupCompareFn } from "./components/radio-group/radio-group-interface";
export { PinFormatter, RangeChangeEventDetail, RangeKnobMoveEndEventDetail, RangeKnobMoveStartEventDetail, RangeValue } from "./components/range/range-interface";
-export { RefresherEventDetail } from "./components/refresher/refresher-interface";
+export { RefresherEventDetail, RefresherPullEndEventDetail } from "./components/refresher/refresher-interface";
export { ItemReorderEventDetail, ReorderEndEventDetail, ReorderMoveEventDetail } from "./components/reorder-group/reorder-group-interface";
export { NavigationHookCallback } from "./components/route/route-interface";
export { SearchbarChangeEventDetail, SearchbarInputEventDetail } from "./components/searchbar/searchbar-interface";
@@ -604,7 +604,7 @@ export namespace Components {
*/
"expand"?: 'full' | 'block';
/**
- * Set to `"clear"` for a transparent button that resembles a flat button, to `"outline"` for a transparent button with a border, or to `"solid"` for a button with a filled background. The default fill is `"solid"` except inside of a toolbar, where the default is `"clear"`.
+ * Set to `"clear"` for a transparent button that resembles a flat button, to `"outline"` for a transparent button with a border, or to `"solid"` for a button with a filled background. The default fill is `"solid"` except when inside of a buttons or datetime component, where the default fill is `"clear"`.
*/
"fill"?: 'clear' | 'outline' | 'solid' | 'default';
/**
@@ -1783,6 +1783,10 @@ export namespace Components {
* @default 4
*/
"length": number;
+ /**
+ * The mode determines the platform behaviors of the component.
+ */
+ "mode"?: "ios" | "md";
/**
* A regex pattern string for allowed characters. Defaults based on type. For numbers (`type="number"`): `"[\p{N}]"` For text (`type="text"`): `"[\p{L}\p{N}]"`
*/
@@ -1811,6 +1815,10 @@ export namespace Components {
* @default 'medium'
*/
"size": 'small' | 'medium' | 'large';
+ /**
+ * The theme determines the visual appearance of the component.
+ */
+ "theme"?: "ios" | "md" | "ionic";
/**
* The type of input allowed in the input boxes.
* @default 'number'
@@ -3086,6 +3094,7 @@ export namespace Components {
* The theme determines the visual appearance of the component.
*/
"theme"?: "ios" | "md" | "ionic";
+ "updateRadiosTabindex": () => Promise;
/**
* the value of the radio group.
*/
@@ -3205,7 +3214,7 @@ export namespace Components {
*/
"mode"?: "ios" | "md";
/**
- * How much to multiply the pull speed by. To slow the pull animation down, pass a number less than `1`. To speed up the pull, pass a number greater than `1`. The default value is `1` which is equal to the speed of the cursor. If a negative value is passed in, the factor will be `1` instead. For example: If the value passed is `1.2` and the content is dragged by `10` pixels, instead of `10` pixels the content will be pulled by `12` pixels (an increase of 20 percent). If the value passed is `0.8`, the dragged amount will be `8` pixels, less than the amount the cursor has moved. Does not apply when the refresher content uses a spinner, enabling the native refresher.
+ * How much to multiply the pull speed by. To slow the pull animation down, pass a number less than `1`. To speed up the pull, pass a number greater than `1`. The default value is `1` which is equal to the speed of the cursor. If a negative value is passed in, the factor will be `1` instead. For example, If the value passed is `1.2` and the content is dragged by `10` pixels, instead of `10` pixels, the content will be pulled by `12` pixels (an increase of 20 percent). If the value passed is `0.8`, the dragged amount will be `8` pixels, less than the amount the cursor has moved. Does not apply when the refresher content uses a spinner, enabling the native refresher.
* @default 1
*/
"pullFactor": number;
@@ -3664,8 +3673,18 @@ export namespace Components {
* @param smoothScroll : Whether to animate the scroll transition.
*/
"setContent": (id: string, smoothScroll?: boolean) => Promise;
+ /**
+ * If `true`, users will be able to swipe the segment view to navigate between segment contents.
+ * @default true
+ */
+ "swipeGesture": boolean;
}
interface IonSelect {
+ /**
+ * If `true`, the cancel button will display an icon instead of the `cancelText`. Only applies when `interface` is set to `"modal"`. Has no effect on `"action-sheet"`, `"alert"`, or `"popover"` interfaces. When `cancelIcon` is `true`, the `cancelText` property is ignored for display but is used as the accessible label for the icon button.
+ * @default false
+ */
+ "cancelIcon": boolean;
/**
* The text to display on the cancel button.
* @default 'Cancel'
@@ -3782,6 +3801,16 @@ export namespace Components {
"value"?: any | null;
}
interface IonSelectModal {
+ /**
+ * If `true`, the cancel button will display a close icon instead of the `cancelText`. When `cancelIcon` is `true`, `cancelText` is not displayed visually but is still used as the accessible label (`aria-label`) for the button.
+ * @default false
+ */
+ "cancelIcon": boolean;
+ /**
+ * The text to display on the cancel button.
+ * @default 'Close'
+ */
+ "cancelText": string;
"header"?: string;
"multiple"?: boolean;
/**
@@ -3790,6 +3819,10 @@ export namespace Components {
"options": SelectModalOption[];
}
interface IonSelectOption {
+ /**
+ * Text that is placed underneath the option text to provide additional details about the option.
+ */
+ "description"?: string;
/**
* If `true`, the user cannot interact with the select option. This property does not apply when `interface="action-sheet"` as `ion-action-sheet` does not allow for disabled buttons.
* @default false
@@ -3943,6 +3976,11 @@ export namespace Components {
* @default 'full'
*/
"expand": 'compact' | 'full';
+ /**
+ * If `true`, the tab bar will be hidden when the user scrolls down and shown when the user scrolls up. Only applies when the theme is `"ionic"` and `expand` is `"compact"`.
+ * @default false
+ */
+ "hideOnScroll": boolean;
/**
* The mode determines the platform behaviors of the component.
*/
@@ -4436,6 +4474,10 @@ export namespace Components {
* The theme determines the visual appearance of the component.
*/
"theme"?: "ios" | "md" | "ionic";
+ /**
+ * Where to place the title relative to the other toolbar content. `"start"`: The title will appear to the left of the toolbar content in LTR and to the right in RTL. `"center"`: The title will appear in the center of the toolbar. `"end"`: The title will appear to the right of the toolbar content in LTR and to the left in RTL. Only applies in the `ionic` theme.
+ */
+ "titlePlacement"?: 'start' | 'center' | 'end';
}
}
export interface IonAccordionGroupCustomEvent extends CustomEvent {
@@ -5216,6 +5258,9 @@ declare global {
"willDismiss": OverlayEventDetail;
"didDismiss": OverlayEventDetail;
"ionMount": void;
+ "ionDragStart": void;
+ "ionDragMove": ModalDragEventDetail;
+ "ionDragEnd": ModalDragEventDetail;
}
interface HTMLIonModalElement extends Components.IonModal, HTMLStencilElement {
addEventListener(type: K, listener: (this: HTMLIonModalElement, ev: IonModalCustomEvent) => any, options?: boolean | AddEventListenerOptions): void;
@@ -5436,6 +5481,8 @@ declare global {
"ionRefresh": RefresherEventDetail;
"ionPull": void;
"ionStart": void;
+ "ionPullStart": void;
+ "ionPullEnd": RefresherPullEndEventDetail;
}
interface HTMLIonRefresherElement extends Components.IonRefresher, HTMLStencilElement {
addEventListener(type: K, listener: (this: HTMLIonRefresherElement, ev: IonRefresherCustomEvent) => any, options?: boolean | AddEventListenerOptions): void;
@@ -5983,6 +6030,8 @@ declare global {
}
}
declare namespace LocalJSX {
+ type OneOf = { [P in K]: PropT } & { [P in `attr:${K}` | `prop:${K}`]?: never } | { [P in `attr:${K}`]: AttrT } & { [P in K | `prop:${K}`]?: never } | { [P in `prop:${K}`]: PropT } & { [P in K | `attr:${K}`]?: never };
+
interface IonAccordion {
/**
* If `true`, the accordion cannot be interacted with.
@@ -6543,7 +6592,7 @@ declare namespace LocalJSX {
*/
"expand"?: 'full' | 'block';
/**
- * Set to `"clear"` for a transparent button that resembles a flat button, to `"outline"` for a transparent button with a border, or to `"solid"` for a button with a filled background. The default fill is `"solid"` except inside of a toolbar, where the default is `"clear"`.
+ * Set to `"clear"` for a transparent button that resembles a flat button, to `"outline"` for a transparent button with a border, or to `"solid"` for a button with a filled background. The default fill is `"solid"` except when inside of a buttons or datetime component, where the default fill is `"clear"`.
*/
"fill"?: 'clear' | 'outline' | 'solid' | 'default';
/**
@@ -7741,6 +7790,10 @@ declare namespace LocalJSX {
* @default 'outline'
*/
"fill"?: 'outline' | 'solid';
+ /**
+ * The `id` of a `