mirror of
https://github.com/ionic-team/ionic-framework.git
synced 2026-03-13 10:22:08 +08:00
Compare commits
1 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
f332f62cbd |
@@ -3,7 +3,7 @@ description: 'Build Ionic Angular Server'
|
||||
runs:
|
||||
using: 'composite'
|
||||
steps:
|
||||
- uses: actions/setup-node@v6
|
||||
- uses: actions/setup-node@v5
|
||||
with:
|
||||
node-version: 22.x
|
||||
- uses: ./.github/workflows/actions/download-archive
|
||||
|
||||
@@ -3,7 +3,7 @@ description: 'Build Ionic Angular'
|
||||
runs:
|
||||
using: 'composite'
|
||||
steps:
|
||||
- uses: actions/setup-node@v6
|
||||
- uses: actions/setup-node@v5
|
||||
with:
|
||||
node-version: 22.x
|
||||
- uses: ./.github/workflows/actions/download-archive
|
||||
|
||||
@@ -9,7 +9,7 @@ runs:
|
||||
using: 'composite'
|
||||
steps:
|
||||
- uses: actions/checkout@v5
|
||||
- uses: actions/setup-node@v6
|
||||
- uses: actions/setup-node@v5
|
||||
with:
|
||||
node-version: 22.x
|
||||
|
||||
|
||||
@@ -9,7 +9,7 @@ runs:
|
||||
using: 'composite'
|
||||
steps:
|
||||
- uses: actions/checkout@v5
|
||||
- uses: actions/setup-node@v6
|
||||
- uses: actions/setup-node@v5
|
||||
with:
|
||||
node-version: 22.x
|
||||
- name: Install Dependencies
|
||||
|
||||
@@ -3,7 +3,7 @@ description: 'Build Ionic React Router'
|
||||
runs:
|
||||
using: 'composite'
|
||||
steps:
|
||||
- uses: actions/setup-node@v6
|
||||
- uses: actions/setup-node@v5
|
||||
with:
|
||||
node-version: 22.x
|
||||
- uses: ./.github/workflows/actions/download-archive
|
||||
|
||||
@@ -3,7 +3,7 @@ description: 'Build Ionic React'
|
||||
runs:
|
||||
using: 'composite'
|
||||
steps:
|
||||
- uses: actions/setup-node@v6
|
||||
- uses: actions/setup-node@v5
|
||||
with:
|
||||
node-version: 22.x
|
||||
- uses: ./.github/workflows/actions/download-archive
|
||||
|
||||
@@ -3,7 +3,7 @@ description: 'Builds Ionic Vue Router'
|
||||
runs:
|
||||
using: 'composite'
|
||||
steps:
|
||||
- uses: actions/setup-node@v6
|
||||
- uses: actions/setup-node@v5
|
||||
with:
|
||||
node-version: 22.x
|
||||
- uses: ./.github/workflows/actions/download-archive
|
||||
|
||||
@@ -3,7 +3,7 @@ description: 'Build Ionic Vue'
|
||||
runs:
|
||||
using: 'composite'
|
||||
steps:
|
||||
- uses: actions/setup-node@v6
|
||||
- uses: actions/setup-node@v5
|
||||
with:
|
||||
node-version: 22.x
|
||||
- uses: ./.github/workflows/actions/download-archive
|
||||
|
||||
@@ -19,7 +19,7 @@ inputs:
|
||||
runs:
|
||||
using: 'composite'
|
||||
steps:
|
||||
- uses: actions/setup-node@v6
|
||||
- uses: actions/setup-node@v5
|
||||
with:
|
||||
node-version: 22.x
|
||||
# Provenance requires npm 9.5.0+
|
||||
|
||||
@@ -6,7 +6,7 @@ inputs:
|
||||
runs:
|
||||
using: 'composite'
|
||||
steps:
|
||||
- uses: actions/setup-node@v6
|
||||
- uses: actions/setup-node@v5
|
||||
with:
|
||||
node-version: 22.x
|
||||
- uses: ./.github/workflows/actions/download-archive
|
||||
|
||||
@@ -3,7 +3,7 @@ description: 'Test Core Clean Build'
|
||||
runs:
|
||||
using: 'composite'
|
||||
steps:
|
||||
- uses: actions/setup-node@v6
|
||||
- uses: actions/setup-node@v5
|
||||
with:
|
||||
node-version: 22.x
|
||||
|
||||
|
||||
@@ -3,7 +3,7 @@ description: 'Test Core Lint'
|
||||
runs:
|
||||
using: 'composite'
|
||||
steps:
|
||||
- uses: actions/setup-node@v6
|
||||
- uses: actions/setup-node@v5
|
||||
with:
|
||||
node-version: 22.x
|
||||
- name: Install Dependencies
|
||||
|
||||
@@ -13,7 +13,7 @@ inputs:
|
||||
runs:
|
||||
using: 'composite'
|
||||
steps:
|
||||
- uses: actions/setup-node@v6
|
||||
- uses: actions/setup-node@v5
|
||||
with:
|
||||
node-version: 22.x
|
||||
- uses: ./.github/workflows/actions/download-archive
|
||||
|
||||
@@ -6,7 +6,7 @@ inputs:
|
||||
runs:
|
||||
using: 'composite'
|
||||
steps:
|
||||
- uses: actions/setup-node@v6
|
||||
- uses: actions/setup-node@v5
|
||||
with:
|
||||
node-version: 22.x
|
||||
- name: Install Dependencies
|
||||
|
||||
@@ -6,7 +6,7 @@ inputs:
|
||||
runs:
|
||||
using: 'composite'
|
||||
steps:
|
||||
- uses: actions/setup-node@v6
|
||||
- uses: actions/setup-node@v5
|
||||
with:
|
||||
node-version: 22.x
|
||||
- uses: ./.github/workflows/actions/download-archive
|
||||
|
||||
@@ -6,7 +6,7 @@ inputs:
|
||||
runs:
|
||||
using: 'composite'
|
||||
steps:
|
||||
- uses: actions/setup-node@v6
|
||||
- uses: actions/setup-node@v5
|
||||
with:
|
||||
node-version: 22.x
|
||||
- uses: ./.github/workflows/actions/download-archive
|
||||
|
||||
@@ -6,7 +6,7 @@ inputs:
|
||||
runs:
|
||||
using: 'composite'
|
||||
steps:
|
||||
- uses: actions/setup-node@v6
|
||||
- uses: actions/setup-node@v5
|
||||
with:
|
||||
node-version: 22.x
|
||||
- uses: ./.github/workflows/actions/download-archive
|
||||
|
||||
@@ -7,7 +7,7 @@ on:
|
||||
runs:
|
||||
using: 'composite'
|
||||
steps:
|
||||
- uses: actions/setup-node@v6
|
||||
- uses: actions/setup-node@v5
|
||||
with:
|
||||
node-version: 22.x
|
||||
- uses: actions/download-artifact@v5
|
||||
|
||||
4
.github/workflows/codeql-analysis.yml
vendored
4
.github/workflows/codeql-analysis.yml
vendored
@@ -15,7 +15,7 @@ jobs:
|
||||
security-events: write
|
||||
steps:
|
||||
- uses: actions/checkout@v5
|
||||
- uses: github/codeql-action/init@v4
|
||||
- uses: github/codeql-action/init@v3
|
||||
with:
|
||||
languages: javascript
|
||||
- uses: github/codeql-action/analyze@v4
|
||||
- uses: github/codeql-action/analyze@v3
|
||||
|
||||
24
CHANGELOG.md
24
CHANGELOG.md
@@ -3,30 +3,6 @@
|
||||
All notable changes to this project will be documented in this file.
|
||||
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
|
||||
|
||||
## [8.7.7](https://github.com/ionic-team/ionic-framework/compare/v8.7.6...v8.7.7) (2025-10-15)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* **header:** ensure one banner role in condensed header ([#30718](https://github.com/ionic-team/ionic-framework/issues/30718)) ([12084af](https://github.com/ionic-team/ionic-framework/commit/12084af163ed811b9c6bda3c7850fc0c53c60c7b))
|
||||
* **header:** prevent flickering during iOS page transitions ([#30705](https://github.com/ionic-team/ionic-framework/issues/30705)) ([820fa28](https://github.com/ionic-team/ionic-framework/commit/820fa2854331722d22efd0e38a1936117477967a)), closes [#25326](https://github.com/ionic-team/ionic-framework/issues/25326)
|
||||
* **select:** improve screen reader announcement timing for validation errors ([#30723](https://github.com/ionic-team/ionic-framework/issues/30723)) ([03303d7](https://github.com/ionic-team/ionic-framework/commit/03303d73f0bfe2380ced7931525fc52fd8576367))
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
## [8.7.6](https://github.com/ionic-team/ionic-framework/compare/v8.7.5...v8.7.6) (2025-10-08)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* **tabs:** respect stencil lifecycle order for tab selection ([#30702](https://github.com/ionic-team/ionic-framework/issues/30702)) ([7bb9535](https://github.com/ionic-team/ionic-framework/commit/7bb9535f601d2469ce60687a9c03f8b1cfe4aba4)), closes [#30611](https://github.com/ionic-team/ionic-framework/issues/30611)
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
## [8.7.5](https://github.com/ionic-team/ionic-framework/compare/v8.7.4...v8.7.5) (2025-09-24)
|
||||
|
||||
|
||||
|
||||
@@ -3,30 +3,6 @@
|
||||
All notable changes to this project will be documented in this file.
|
||||
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
|
||||
|
||||
## [8.7.7](https://github.com/ionic-team/ionic-framework/compare/v8.7.6...v8.7.7) (2025-10-15)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* **header:** ensure one banner role in condensed header ([#30718](https://github.com/ionic-team/ionic-framework/issues/30718)) ([12084af](https://github.com/ionic-team/ionic-framework/commit/12084af163ed811b9c6bda3c7850fc0c53c60c7b))
|
||||
* **header:** prevent flickering during iOS page transitions ([#30705](https://github.com/ionic-team/ionic-framework/issues/30705)) ([820fa28](https://github.com/ionic-team/ionic-framework/commit/820fa2854331722d22efd0e38a1936117477967a)), closes [#25326](https://github.com/ionic-team/ionic-framework/issues/25326)
|
||||
* **select:** improve screen reader announcement timing for validation errors ([#30723](https://github.com/ionic-team/ionic-framework/issues/30723)) ([03303d7](https://github.com/ionic-team/ionic-framework/commit/03303d73f0bfe2380ced7931525fc52fd8576367))
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
## [8.7.6](https://github.com/ionic-team/ionic-framework/compare/v8.7.5...v8.7.6) (2025-10-08)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* **tabs:** respect stencil lifecycle order for tab selection ([#30702](https://github.com/ionic-team/ionic-framework/issues/30702)) ([7bb9535](https://github.com/ionic-team/ionic-framework/commit/7bb9535f601d2469ce60687a9c03f8b1cfe4aba4)), closes [#30611](https://github.com/ionic-team/ionic-framework/issues/30611)
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
## [8.7.5](https://github.com/ionic-team/ionic-framework/compare/v8.7.4...v8.7.5) (2025-09-24)
|
||||
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
# Get Playwright
|
||||
FROM mcr.microsoft.com/playwright:v1.56.0
|
||||
FROM mcr.microsoft.com/playwright:v1.55.1
|
||||
|
||||
# Set the working directory
|
||||
WORKDIR /ionic
|
||||
|
||||
67
core/package-lock.json
generated
67
core/package-lock.json
generated
@@ -1,15 +1,15 @@
|
||||
{
|
||||
"name": "@ionic/core",
|
||||
"version": "8.7.7",
|
||||
"version": "8.7.5",
|
||||
"lockfileVersion": 2,
|
||||
"requires": true,
|
||||
"packages": {
|
||||
"": {
|
||||
"name": "@ionic/core",
|
||||
"version": "8.7.7",
|
||||
"version": "8.7.5",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@stencil/core": "4.38.0",
|
||||
"@stencil/core": "4.36.2",
|
||||
"ionicons": "^8.0.13",
|
||||
"tslib": "^2.1.0"
|
||||
},
|
||||
@@ -22,7 +22,7 @@
|
||||
"@clack/prompts": "^0.11.0",
|
||||
"@ionic/eslint-config": "^0.3.0",
|
||||
"@ionic/prettier-config": "^2.0.0",
|
||||
"@playwright/test": "^1.56.0",
|
||||
"@playwright/test": "^1.55.1",
|
||||
"@rollup/plugin-node-resolve": "^8.4.0",
|
||||
"@rollup/plugin-virtual": "^2.0.3",
|
||||
"@stencil/angular-output-target": "^0.10.0",
|
||||
@@ -1715,12 +1715,12 @@
|
||||
}
|
||||
},
|
||||
"node_modules/@playwright/test": {
|
||||
"version": "1.56.0",
|
||||
"resolved": "https://registry.npmjs.org/@playwright/test/-/test-1.56.0.tgz",
|
||||
"integrity": "sha512-Tzh95Twig7hUwwNe381/K3PggZBZblKUe2wv25oIpzWLr6Z0m4KgV1ZVIjnR6GM9ANEqjZD7XsZEa6JL/7YEgg==",
|
||||
"version": "1.55.1",
|
||||
"resolved": "https://registry.npmjs.org/@playwright/test/-/test-1.55.1.tgz",
|
||||
"integrity": "sha512-IVAh/nOJaw6W9g+RJVlIQJ6gSiER+ae6mKQ5CX1bERzQgbC1VSeBlwdvczT7pxb0GWiyrxH4TGKbMfDb4Sq/ig==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"playwright": "1.56.0"
|
||||
"playwright": "1.55.1"
|
||||
},
|
||||
"bin": {
|
||||
"playwright": "cli.js"
|
||||
@@ -1914,9 +1914,10 @@
|
||||
}
|
||||
},
|
||||
"node_modules/@stencil/core": {
|
||||
"version": "4.38.0",
|
||||
"resolved": "https://registry.npmjs.org/@stencil/core/-/core-4.38.0.tgz",
|
||||
"integrity": "sha512-oC3QFKO0X1yXVvETgc8OLY525MNKhn9vISBrbtKnGoPlokJ6rI8Vk1RK22TevnNrHLI4SExNLbcDnqilKR35JQ==",
|
||||
"version": "4.36.2",
|
||||
"resolved": "https://registry.npmjs.org/@stencil/core/-/core-4.36.2.tgz",
|
||||
"integrity": "sha512-PRFSpxNzX9Oi0Wfh02asztN9Sgev/MacfZwmd+VVyE6ZxW+a/kEpAYZhzGAmE+/aKVOGYuug7R9SulanYGxiDQ==",
|
||||
"license": "MIT",
|
||||
"bin": {
|
||||
"stencil": "bin/stencil"
|
||||
},
|
||||
@@ -8592,12 +8593,12 @@
|
||||
}
|
||||
},
|
||||
"node_modules/playwright": {
|
||||
"version": "1.56.0",
|
||||
"resolved": "https://registry.npmjs.org/playwright/-/playwright-1.56.0.tgz",
|
||||
"integrity": "sha512-X5Q1b8lOdWIE4KAoHpW3SE8HvUB+ZZsUoN64ZhjnN8dOb1UpujxBtENGiZFE+9F/yhzJwYa+ca3u43FeLbboHA==",
|
||||
"version": "1.55.1",
|
||||
"resolved": "https://registry.npmjs.org/playwright/-/playwright-1.55.1.tgz",
|
||||
"integrity": "sha512-cJW4Xd/G3v5ovXtJJ52MAOclqeac9S/aGGgRzLabuF8TnIb6xHvMzKIa6JmrRzUkeXJgfL1MhukP0NK6l39h3A==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"playwright-core": "1.56.0"
|
||||
"playwright-core": "1.55.1"
|
||||
},
|
||||
"bin": {
|
||||
"playwright": "cli.js"
|
||||
@@ -8610,9 +8611,9 @@
|
||||
}
|
||||
},
|
||||
"node_modules/playwright-core": {
|
||||
"version": "1.56.0",
|
||||
"resolved": "https://registry.npmjs.org/playwright-core/-/playwright-core-1.56.0.tgz",
|
||||
"integrity": "sha512-1SXl7pMfemAMSDn5rkPeZljxOCYAmQnYLBTExuh6E8USHXGSX3dx6lYZN/xPpTz1vimXmPA9CDnILvmJaB8aSQ==",
|
||||
"version": "1.55.1",
|
||||
"resolved": "https://registry.npmjs.org/playwright-core/-/playwright-core-1.55.1.tgz",
|
||||
"integrity": "sha512-Z6Mh9mkwX+zxSlHqdr5AOcJnfp+xUWLCt9uKV18fhzA8eyxUd8NUWzAjxUh55RZKSYwDGX0cfaySdhZJGMoJ+w==",
|
||||
"dev": true,
|
||||
"bin": {
|
||||
"playwright-core": "cli.js"
|
||||
@@ -11862,12 +11863,12 @@
|
||||
}
|
||||
},
|
||||
"@playwright/test": {
|
||||
"version": "1.56.0",
|
||||
"resolved": "https://registry.npmjs.org/@playwright/test/-/test-1.56.0.tgz",
|
||||
"integrity": "sha512-Tzh95Twig7hUwwNe381/K3PggZBZblKUe2wv25oIpzWLr6Z0m4KgV1ZVIjnR6GM9ANEqjZD7XsZEa6JL/7YEgg==",
|
||||
"version": "1.55.1",
|
||||
"resolved": "https://registry.npmjs.org/@playwright/test/-/test-1.55.1.tgz",
|
||||
"integrity": "sha512-IVAh/nOJaw6W9g+RJVlIQJ6gSiER+ae6mKQ5CX1bERzQgbC1VSeBlwdvczT7pxb0GWiyrxH4TGKbMfDb4Sq/ig==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"playwright": "1.56.0"
|
||||
"playwright": "1.55.1"
|
||||
}
|
||||
},
|
||||
"@rollup/plugin-node-resolve": {
|
||||
@@ -11983,9 +11984,9 @@
|
||||
"requires": {}
|
||||
},
|
||||
"@stencil/core": {
|
||||
"version": "4.38.0",
|
||||
"resolved": "https://registry.npmjs.org/@stencil/core/-/core-4.38.0.tgz",
|
||||
"integrity": "sha512-oC3QFKO0X1yXVvETgc8OLY525MNKhn9vISBrbtKnGoPlokJ6rI8Vk1RK22TevnNrHLI4SExNLbcDnqilKR35JQ==",
|
||||
"version": "4.36.2",
|
||||
"resolved": "https://registry.npmjs.org/@stencil/core/-/core-4.36.2.tgz",
|
||||
"integrity": "sha512-PRFSpxNzX9Oi0Wfh02asztN9Sgev/MacfZwmd+VVyE6ZxW+a/kEpAYZhzGAmE+/aKVOGYuug7R9SulanYGxiDQ==",
|
||||
"requires": {
|
||||
"@rollup/rollup-darwin-arm64": "4.34.9",
|
||||
"@rollup/rollup-darwin-x64": "4.34.9",
|
||||
@@ -16811,19 +16812,19 @@
|
||||
}
|
||||
},
|
||||
"playwright": {
|
||||
"version": "1.56.0",
|
||||
"resolved": "https://registry.npmjs.org/playwright/-/playwright-1.56.0.tgz",
|
||||
"integrity": "sha512-X5Q1b8lOdWIE4KAoHpW3SE8HvUB+ZZsUoN64ZhjnN8dOb1UpujxBtENGiZFE+9F/yhzJwYa+ca3u43FeLbboHA==",
|
||||
"version": "1.55.1",
|
||||
"resolved": "https://registry.npmjs.org/playwright/-/playwright-1.55.1.tgz",
|
||||
"integrity": "sha512-cJW4Xd/G3v5ovXtJJ52MAOclqeac9S/aGGgRzLabuF8TnIb6xHvMzKIa6JmrRzUkeXJgfL1MhukP0NK6l39h3A==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"fsevents": "2.3.2",
|
||||
"playwright-core": "1.56.0"
|
||||
"playwright-core": "1.55.1"
|
||||
}
|
||||
},
|
||||
"playwright-core": {
|
||||
"version": "1.56.0",
|
||||
"resolved": "https://registry.npmjs.org/playwright-core/-/playwright-core-1.56.0.tgz",
|
||||
"integrity": "sha512-1SXl7pMfemAMSDn5rkPeZljxOCYAmQnYLBTExuh6E8USHXGSX3dx6lYZN/xPpTz1vimXmPA9CDnILvmJaB8aSQ==",
|
||||
"version": "1.55.1",
|
||||
"resolved": "https://registry.npmjs.org/playwright-core/-/playwright-core-1.55.1.tgz",
|
||||
"integrity": "sha512-Z6Mh9mkwX+zxSlHqdr5AOcJnfp+xUWLCt9uKV18fhzA8eyxUd8NUWzAjxUh55RZKSYwDGX0cfaySdhZJGMoJ+w==",
|
||||
"dev": true
|
||||
},
|
||||
"postcss": {
|
||||
@@ -18337,4 +18338,4 @@
|
||||
"dev": true
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@ionic/core",
|
||||
"version": "8.7.7",
|
||||
"version": "8.7.5",
|
||||
"description": "Base components for Ionic",
|
||||
"keywords": [
|
||||
"ionic",
|
||||
@@ -31,7 +31,7 @@
|
||||
"loader/"
|
||||
],
|
||||
"dependencies": {
|
||||
"@stencil/core": "4.38.0",
|
||||
"@stencil/core": "4.36.2",
|
||||
"ionicons": "^8.0.13",
|
||||
"tslib": "^2.1.0"
|
||||
},
|
||||
@@ -44,7 +44,7 @@
|
||||
"@clack/prompts": "^0.11.0",
|
||||
"@ionic/eslint-config": "^0.3.0",
|
||||
"@ionic/prettier-config": "^2.0.0",
|
||||
"@playwright/test": "^1.56.0",
|
||||
"@playwright/test": "^1.55.1",
|
||||
"@rollup/plugin-node-resolve": "^8.4.0",
|
||||
"@rollup/plugin-virtual": "^2.0.3",
|
||||
"@stencil/angular-output-target": "^0.10.0",
|
||||
|
||||
@@ -361,7 +361,11 @@ export class Button implements ComponentInterface, AnchorInterface, ButtonInterf
|
||||
target,
|
||||
};
|
||||
let fill = this.fill;
|
||||
if (fill === undefined) {
|
||||
/**
|
||||
* We check both undefined and null to
|
||||
* work around https://github.com/ionic-team/stencil/issues/3586.
|
||||
*/
|
||||
if (fill == null) {
|
||||
fill = this.inToolbar || this.inListHeader ? 'clear' : 'solid';
|
||||
}
|
||||
|
||||
|
||||
@@ -39,15 +39,6 @@
|
||||
--opacity-scale: inherit;
|
||||
}
|
||||
|
||||
/**
|
||||
* Override styles applied during the page transition to prevent
|
||||
* header flickering.
|
||||
*/
|
||||
.header-collapse-fade.header-transitioning ion-toolbar {
|
||||
--background: transparent;
|
||||
--border-style: none;
|
||||
}
|
||||
|
||||
// iOS Header - Collapse Condense
|
||||
// --------------------------------------------------
|
||||
.header-collapse-condense {
|
||||
@@ -74,6 +65,8 @@
|
||||
* since it needs to blend in with the header above it.
|
||||
*/
|
||||
.header-collapse-condense ion-toolbar {
|
||||
--background: var(--ion-background-color, #fff);
|
||||
|
||||
z-index: 0;
|
||||
}
|
||||
|
||||
@@ -100,28 +93,6 @@
|
||||
transition: all 0.2s ease-in-out;
|
||||
}
|
||||
|
||||
/**
|
||||
* Large title toolbar should just use the content background
|
||||
* since it needs to blend in with the header above it.
|
||||
*/
|
||||
.header-collapse-condense ion-toolbar,
|
||||
/**
|
||||
* Override styles applied during the page transition to prevent
|
||||
* header flickering.
|
||||
*/
|
||||
.header-collapse-condense-inactive.header-transitioning:not(.header-collapse-condense) ion-toolbar {
|
||||
--background: var(--ion-background-color, #fff);
|
||||
}
|
||||
|
||||
/**
|
||||
* Override styles applied during the page transition to prevent
|
||||
* header flickering.
|
||||
*/
|
||||
.header-collapse-condense-inactive.header-transitioning:not(.header-collapse-condense) ion-toolbar {
|
||||
--border-style: none;
|
||||
--opacity-scale: 1;
|
||||
}
|
||||
|
||||
.header-collapse-condense-inactive:not(.header-collapse-condense) ion-toolbar.in-toolbar ion-title,
|
||||
.header-collapse-condense-inactive:not(.header-collapse-condense) ion-toolbar.in-toolbar ion-buttons.buttons-collapse {
|
||||
opacity: 0;
|
||||
|
||||
@@ -15,7 +15,6 @@ import {
|
||||
handleToolbarIntersection,
|
||||
setHeaderActive,
|
||||
setToolbarBackgroundOpacity,
|
||||
getRoleType,
|
||||
} from './header.utils';
|
||||
|
||||
/**
|
||||
@@ -209,10 +208,9 @@ export class Header implements ComponentInterface {
|
||||
const { translucent, inheritedAttributes } = this;
|
||||
const mode = getIonMode(this);
|
||||
const collapse = this.collapse || 'none';
|
||||
const isCondensed = collapse === 'condense';
|
||||
|
||||
// banner role must be at top level, so remove role if inside a menu
|
||||
const roleType = getRoleType(hostContext('ion-menu', this.el), isCondensed, mode);
|
||||
const roleType = hostContext('ion-menu', this.el) ? 'none' : 'banner';
|
||||
|
||||
return (
|
||||
<Host
|
||||
|
||||
@@ -2,8 +2,6 @@ import { readTask, writeTask } from '@stencil/core';
|
||||
import { clamp } from '@utils/helpers';
|
||||
|
||||
const TRANSITION = 'all 0.2s ease-in-out';
|
||||
const ROLE_NONE = 'none';
|
||||
const ROLE_BANNER = 'banner';
|
||||
|
||||
interface HeaderIndex {
|
||||
el: HTMLIonHeaderElement;
|
||||
@@ -173,7 +171,6 @@ export const setHeaderActive = (headerIndex: HeaderIndex, active = true) => {
|
||||
const ionTitles = toolbars.map((toolbar) => toolbar.ionTitleEl);
|
||||
|
||||
if (active) {
|
||||
headerEl.setAttribute('role', ROLE_BANNER);
|
||||
headerEl.classList.remove('header-collapse-condense-inactive');
|
||||
|
||||
ionTitles.forEach((ionTitle) => {
|
||||
@@ -182,16 +179,6 @@ export const setHeaderActive = (headerIndex: HeaderIndex, active = true) => {
|
||||
}
|
||||
});
|
||||
} else {
|
||||
/**
|
||||
* There can only be one banner landmark per page.
|
||||
* By default, all ion-headers have the banner role.
|
||||
* This causes an accessibility issue when using a
|
||||
* condensed header since there are two ion-headers
|
||||
* on the page at once (active and inactive).
|
||||
* To solve this, the role needs to be toggled
|
||||
* based on which header is active.
|
||||
*/
|
||||
headerEl.setAttribute('role', ROLE_NONE);
|
||||
headerEl.classList.add('header-collapse-condense-inactive');
|
||||
|
||||
/**
|
||||
@@ -257,28 +244,3 @@ export const handleHeaderFade = (scrollEl: HTMLElement, baseEl: HTMLElement, con
|
||||
});
|
||||
});
|
||||
};
|
||||
|
||||
/**
|
||||
* Get the role type for the ion-header.
|
||||
*
|
||||
* @param isInsideMenu If ion-header is inside ion-menu.
|
||||
* @param isCondensed If ion-header has collapse="condense".
|
||||
* @param mode The current mode.
|
||||
* @returns 'none' if inside ion-menu or if condensed in md
|
||||
* mode, otherwise 'banner'.
|
||||
*/
|
||||
export const getRoleType = (isInsideMenu: boolean, isCondensed: boolean, mode: 'ios' | 'md') => {
|
||||
// If the header is inside a menu, it should not have the banner role.
|
||||
if (isInsideMenu) {
|
||||
return ROLE_NONE;
|
||||
}
|
||||
/**
|
||||
* Only apply role="none" to `md` mode condensed headers
|
||||
* since the large header is never shown.
|
||||
*/
|
||||
if (isCondensed && mode === 'md') {
|
||||
return ROLE_NONE;
|
||||
}
|
||||
// Default to banner role.
|
||||
return ROLE_BANNER;
|
||||
};
|
||||
|
||||
@@ -40,45 +40,5 @@ configs({ modes: ['ios'], directions: ['ltr'] }).forEach(({ title, screenshot, c
|
||||
|
||||
await expect(smallTitle).toHaveAttribute('aria-hidden', 'true');
|
||||
});
|
||||
|
||||
test('should only have the banner role on the active header', async ({ page }) => {
|
||||
await page.goto('/src/components/header/test/condense', config);
|
||||
const largeTitleHeader = page.locator('#largeTitleHeader');
|
||||
const smallTitleHeader = page.locator('#smallTitleHeader');
|
||||
const content = page.locator('ion-content');
|
||||
|
||||
await expect(largeTitleHeader).toHaveAttribute('role', 'banner');
|
||||
await expect(smallTitleHeader).toHaveAttribute('role', 'none');
|
||||
|
||||
await content.evaluate(async (el: HTMLIonContentElement) => {
|
||||
await el.scrollToBottom();
|
||||
});
|
||||
await page.locator('#largeTitleHeader.header-collapse-condense-inactive').waitFor();
|
||||
|
||||
await expect(largeTitleHeader).toHaveAttribute('role', 'none');
|
||||
await expect(smallTitleHeader).toHaveAttribute('role', 'banner');
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
configs({ modes: ['md'], directions: ['ltr'] }).forEach(({ title, config }) => {
|
||||
test.describe(title('header: condense'), () => {
|
||||
test('should only have the banner role on the small header', async ({ page }) => {
|
||||
await page.goto('/src/components/header/test/condense', config);
|
||||
const largeTitleHeader = page.locator('#largeTitleHeader');
|
||||
const smallTitleHeader = page.locator('#smallTitleHeader');
|
||||
const content = page.locator('ion-content');
|
||||
|
||||
await expect(smallTitleHeader).toHaveAttribute('role', 'banner');
|
||||
await expect(largeTitleHeader).toHaveAttribute('role', 'none');
|
||||
|
||||
await content.evaluate(async (el: HTMLIonContentElement) => {
|
||||
await el.scrollToBottom();
|
||||
});
|
||||
await page.waitForChanges();
|
||||
|
||||
await expect(smallTitleHeader).toHaveAttribute('role', 'banner');
|
||||
await expect(largeTitleHeader).toHaveAttribute('role', 'none');
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
@@ -14,7 +14,7 @@ import {
|
||||
h,
|
||||
} from '@stencil/core';
|
||||
import type { NotchController } from '@utils/forms';
|
||||
import { createNotchController, checkInvalidState } from '@utils/forms';
|
||||
import { createNotchController } from '@utils/forms';
|
||||
import type { Attributes } from '@utils/helpers';
|
||||
import { inheritAriaAttributes, debounceEvent, inheritAttributes, componentOnReady } from '@utils/helpers';
|
||||
import { createSlotMutationController } from '@utils/slot-mutation-controller';
|
||||
@@ -403,6 +403,16 @@ export class Input implements ComponentInterface {
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if the input is in an invalid state based on Ionic validation classes
|
||||
*/
|
||||
private checkInvalidState(): boolean {
|
||||
const hasIonTouched = this.el.classList.contains('ion-touched');
|
||||
const hasIonInvalid = this.el.classList.contains('ion-invalid');
|
||||
|
||||
return hasIonTouched && hasIonInvalid;
|
||||
}
|
||||
|
||||
connectedCallback() {
|
||||
const { el } = this;
|
||||
|
||||
@@ -416,7 +426,7 @@ export class Input implements ComponentInterface {
|
||||
// Watch for class changes to update validation state
|
||||
if (Build.isBrowser && typeof MutationObserver !== 'undefined') {
|
||||
this.validationObserver = new MutationObserver(() => {
|
||||
const newIsInvalid = checkInvalidState(el);
|
||||
const newIsInvalid = this.checkInvalidState();
|
||||
if (this.isInvalid !== newIsInvalid) {
|
||||
this.isInvalid = newIsInvalid;
|
||||
// Force a re-render to update aria-describedby immediately
|
||||
@@ -431,7 +441,7 @@ export class Input implements ComponentInterface {
|
||||
}
|
||||
|
||||
// Always set initial state
|
||||
this.isInvalid = checkInvalidState(el);
|
||||
this.isInvalid = this.checkInvalidState();
|
||||
|
||||
this.debounceChanged();
|
||||
if (Build.isBrowser) {
|
||||
|
||||
@@ -98,7 +98,11 @@ export const createSheetGesture = (
|
||||
// Respect explicit opt-out of focus trapping/backdrop interactions
|
||||
// If focusTrap is false or showBackdrop is false, do not enable the backdrop or re-enable focus trap
|
||||
const el = baseEl as HTMLIonModalElement & { focusTrap?: boolean; showBackdrop?: boolean };
|
||||
if (el.focusTrap === false || el.showBackdrop === false) {
|
||||
const focusTrapAttr = el.getAttribute?.('focus-trap');
|
||||
const showBackdropAttr = el.getAttribute?.('show-backdrop');
|
||||
const focusTrapDisabled = el.focusTrap === false || focusTrapAttr === 'false';
|
||||
const backdropDisabled = el.showBackdrop === false || showBackdropAttr === 'false';
|
||||
if (focusTrapDisabled || backdropDisabled) {
|
||||
return;
|
||||
}
|
||||
baseEl.style.setProperty('pointer-events', 'auto');
|
||||
@@ -241,10 +245,12 @@ export const createSheetGesture = (
|
||||
* ion-backdrop and .modal-wrapper always have pointer-events: auto
|
||||
* applied, so the modal content can still be interacted with.
|
||||
*/
|
||||
const shouldEnableBackdrop =
|
||||
currentBreakpoint > backdropBreakpoint &&
|
||||
(baseEl as HTMLIonModalElement & { focusTrap?: boolean }).focusTrap !== false &&
|
||||
(baseEl as HTMLIonModalElement & { showBackdrop?: boolean }).showBackdrop !== false;
|
||||
const modalEl = baseEl as HTMLIonModalElement & { focusTrap?: boolean; showBackdrop?: boolean };
|
||||
const focusTrapAttr = modalEl.getAttribute?.('focus-trap');
|
||||
const showBackdropAttr = modalEl.getAttribute?.('show-backdrop');
|
||||
const focusTrapDisabled = modalEl.focusTrap === false || focusTrapAttr === 'false';
|
||||
const backdropDisabled = modalEl.showBackdrop === false || showBackdropAttr === 'false';
|
||||
const shouldEnableBackdrop = currentBreakpoint > backdropBreakpoint && !focusTrapDisabled && !backdropDisabled;
|
||||
if (shouldEnableBackdrop) {
|
||||
enableBackdrop();
|
||||
} else {
|
||||
@@ -591,10 +597,16 @@ export const createSheetGesture = (
|
||||
* Backdrop should become enabled
|
||||
* after the backdropBreakpoint value
|
||||
*/
|
||||
const modalEl = baseEl as HTMLIonModalElement & {
|
||||
focusTrap?: boolean;
|
||||
showBackdrop?: boolean;
|
||||
};
|
||||
const focusTrapAttr = modalEl.getAttribute?.('focus-trap');
|
||||
const showBackdropAttr = modalEl.getAttribute?.('show-backdrop');
|
||||
const focusTrapDisabled = modalEl.focusTrap === false || focusTrapAttr === 'false';
|
||||
const backdropDisabled = modalEl.showBackdrop === false || showBackdropAttr === 'false';
|
||||
const shouldEnableBackdrop =
|
||||
currentBreakpoint > backdropBreakpoint &&
|
||||
(baseEl as HTMLIonModalElement & { focusTrap?: boolean }).focusTrap !== false &&
|
||||
(baseEl as HTMLIonModalElement & { showBackdrop?: boolean }).showBackdrop !== false;
|
||||
currentBreakpoint > backdropBreakpoint && !focusTrapDisabled && !backdropDisabled;
|
||||
if (shouldEnableBackdrop) {
|
||||
enableBackdrop();
|
||||
} else {
|
||||
|
||||
@@ -1237,6 +1237,7 @@ export class Modal implements ComponentInterface, OverlayInterface {
|
||||
const isHandleCycle = handleBehavior === 'cycle';
|
||||
const isSheetModalWithHandle = isSheetModal && showHandle;
|
||||
|
||||
const focusTrapAttr = this.el.getAttribute('focus-trap');
|
||||
return (
|
||||
<Host
|
||||
no-router
|
||||
@@ -1253,7 +1254,7 @@ export class Modal implements ComponentInterface, OverlayInterface {
|
||||
[`modal-sheet`]: isSheetModal,
|
||||
[`modal-no-expand-scroll`]: isSheetModal && !expandToScroll,
|
||||
'overlay-hidden': true,
|
||||
[FOCUS_TRAP_DISABLE_CLASS]: focusTrap === false,
|
||||
[FOCUS_TRAP_DISABLE_CLASS]: focusTrap === false || focusTrapAttr === 'false',
|
||||
...getClassMap(this.cssClass),
|
||||
}}
|
||||
onIonBackdropTap={this.onBackdropTap}
|
||||
|
||||
@@ -28,6 +28,18 @@ describe('modal: focus trap', () => {
|
||||
|
||||
expect(modal.classList.contains(FOCUS_TRAP_DISABLE_CLASS)).toBe(true);
|
||||
});
|
||||
it('should set the focus trap class when disabled via attribute string', async () => {
|
||||
const page = await newSpecPage({
|
||||
components: [Modal],
|
||||
html: `
|
||||
<ion-modal focus-trap="false"></ion-modal>
|
||||
`,
|
||||
});
|
||||
|
||||
const modal = page.body.querySelector('ion-modal')!;
|
||||
|
||||
expect(modal.classList.contains(FOCUS_TRAP_DISABLE_CLASS)).toBe(true);
|
||||
});
|
||||
it('should not set the focus trap class by default', async () => {
|
||||
const page = await newSpecPage({
|
||||
components: [Modal],
|
||||
|
||||
@@ -687,6 +687,7 @@ export class Popover implements ComponentInterface, PopoverInterface {
|
||||
const { onLifecycle, parentPopover, dismissOnSelect, side, arrow, htmlAttributes, focusTrap } = this;
|
||||
const desktop = isPlatform('desktop');
|
||||
const enableArrow = arrow && !parentPopover;
|
||||
const focusTrapAttr = this.el.getAttribute('focus-trap');
|
||||
|
||||
return (
|
||||
<Host
|
||||
@@ -704,7 +705,7 @@ export class Popover implements ComponentInterface, PopoverInterface {
|
||||
'overlay-hidden': true,
|
||||
'popover-desktop': desktop,
|
||||
[`popover-side-${side}`]: true,
|
||||
[FOCUS_TRAP_DISABLE_CLASS]: focusTrap === false,
|
||||
[FOCUS_TRAP_DISABLE_CLASS]: focusTrap === false || focusTrapAttr === 'false',
|
||||
'popover-nested': !!parentPopover,
|
||||
}}
|
||||
onIonPopoverDidPresent={onLifecycle}
|
||||
|
||||
@@ -29,6 +29,18 @@ describe('popover: focus trap', () => {
|
||||
|
||||
expect(popover.classList.contains(FOCUS_TRAP_DISABLE_CLASS)).toBe(true);
|
||||
});
|
||||
it('should set the focus trap class when disabled via attribute string', async () => {
|
||||
const page = await newSpecPage({
|
||||
components: [Popover],
|
||||
html: `
|
||||
<ion-popover focus-trap="false"></ion-popover>
|
||||
`,
|
||||
});
|
||||
|
||||
const popover = page.body.querySelector('ion-popover')!;
|
||||
|
||||
expect(popover.classList.contains(FOCUS_TRAP_DISABLE_CLASS)).toBe(true);
|
||||
});
|
||||
it('should not set the focus trap class by default', async () => {
|
||||
const page = await newSpecPage({
|
||||
components: [Popover],
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import type { ComponentInterface, EventEmitter } from '@stencil/core';
|
||||
import { Build, Component, Element, Event, Host, Method, Prop, State, Watch, h, forceUpdate } from '@stencil/core';
|
||||
import { Component, Element, Event, Host, Method, Prop, State, Watch, h, forceUpdate } from '@stencil/core';
|
||||
import type { NotchController } from '@utils/forms';
|
||||
import { compareOptions, createNotchController, isOptionSelected, checkInvalidState } from '@utils/forms';
|
||||
import { compareOptions, createNotchController, isOptionSelected } from '@utils/forms';
|
||||
import { focusVisibleElement, renderHiddenInput, inheritAttributes } from '@utils/helpers';
|
||||
import type { Attributes } from '@utils/helpers';
|
||||
import { printIonWarning } from '@utils/logging';
|
||||
@@ -64,7 +64,6 @@ export class Select implements ComponentInterface {
|
||||
private inheritedAttributes: Attributes = {};
|
||||
private nativeWrapperEl: HTMLElement | undefined;
|
||||
private notchSpacerEl: HTMLElement | undefined;
|
||||
private validationObserver?: MutationObserver;
|
||||
|
||||
private notchController?: NotchController;
|
||||
|
||||
@@ -82,13 +81,6 @@ export class Select implements ComponentInterface {
|
||||
*/
|
||||
@State() hasFocus = false;
|
||||
|
||||
/**
|
||||
* Track validation state for proper aria-live announcements.
|
||||
*/
|
||||
@State() isInvalid = false;
|
||||
|
||||
@State() private hintTextID?: string;
|
||||
|
||||
/**
|
||||
* The text to display on the cancel button.
|
||||
*/
|
||||
@@ -306,51 +298,10 @@ export class Select implements ComponentInterface {
|
||||
*/
|
||||
forceUpdate(this);
|
||||
});
|
||||
|
||||
// Watch for class changes to update validation state.
|
||||
if (Build.isBrowser && typeof MutationObserver !== 'undefined') {
|
||||
this.validationObserver = new MutationObserver(() => {
|
||||
const newIsInvalid = checkInvalidState(this.el);
|
||||
if (this.isInvalid !== newIsInvalid) {
|
||||
this.isInvalid = newIsInvalid;
|
||||
/**
|
||||
* Screen readers tend to announce changes
|
||||
* to `aria-describedby` when the attribute
|
||||
* is changed during a blur event for a
|
||||
* native form control.
|
||||
* However, the announcement can be spotty
|
||||
* when using a non-native form control
|
||||
* and `forceUpdate()`.
|
||||
* This is due to `forceUpdate()` internally
|
||||
* rescheduling the DOM update to a lower
|
||||
* priority queue regardless if it's called
|
||||
* inside a Promise or not, thus causing
|
||||
* the screen reader to potentially miss the
|
||||
* change.
|
||||
* By using a State variable inside a Promise,
|
||||
* it guarantees a re-render immediately at
|
||||
* a higher priority.
|
||||
*/
|
||||
Promise.resolve().then(() => {
|
||||
this.hintTextID = this.getHintTextID();
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
this.validationObserver.observe(el, {
|
||||
attributes: true,
|
||||
attributeFilter: ['class'],
|
||||
});
|
||||
}
|
||||
|
||||
// Always set initial state
|
||||
this.isInvalid = checkInvalidState(this.el);
|
||||
}
|
||||
|
||||
componentWillLoad() {
|
||||
this.inheritedAttributes = inheritAttributes(this.el, ['aria-label']);
|
||||
|
||||
this.hintTextID = this.getHintTextID();
|
||||
}
|
||||
|
||||
componentDidLoad() {
|
||||
@@ -377,12 +328,6 @@ export class Select implements ComponentInterface {
|
||||
this.notchController.destroy();
|
||||
this.notchController = undefined;
|
||||
}
|
||||
|
||||
// Clean up validation observer to prevent memory leaks.
|
||||
if (this.validationObserver) {
|
||||
this.validationObserver.disconnect();
|
||||
this.validationObserver = undefined;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -1111,8 +1056,8 @@ export class Select implements ComponentInterface {
|
||||
aria-label={this.ariaLabel}
|
||||
aria-haspopup="dialog"
|
||||
aria-expanded={`${isExpanded}`}
|
||||
aria-describedby={this.hintTextID}
|
||||
aria-invalid={this.isInvalid ? 'true' : undefined}
|
||||
aria-describedby={this.getHintTextID()}
|
||||
aria-invalid={this.getHintTextID() === this.errorTextId}
|
||||
aria-required={`${required}`}
|
||||
onFocus={this.onFocus}
|
||||
onBlur={this.onBlur}
|
||||
@@ -1122,9 +1067,9 @@ export class Select implements ComponentInterface {
|
||||
}
|
||||
|
||||
private getHintTextID(): string | undefined {
|
||||
const { helperText, errorText, helperTextId, errorTextId, isInvalid } = this;
|
||||
const { el, helperText, errorText, helperTextId, errorTextId } = this;
|
||||
|
||||
if (isInvalid && errorText) {
|
||||
if (el.classList.contains('ion-touched') && el.classList.contains('ion-invalid') && errorText) {
|
||||
return errorTextId;
|
||||
}
|
||||
|
||||
@@ -1139,14 +1084,14 @@ export class Select implements ComponentInterface {
|
||||
* Renders the helper text or error text values
|
||||
*/
|
||||
private renderHintText() {
|
||||
const { helperText, errorText, helperTextId, errorTextId, isInvalid } = this;
|
||||
const { helperText, errorText, helperTextId, errorTextId } = this;
|
||||
|
||||
return [
|
||||
<div id={helperTextId} class="helper-text" part="supporting-text helper-text" aria-live="polite">
|
||||
{!isInvalid ? helperText : null}
|
||||
<div id={helperTextId} class="helper-text" part="supporting-text helper-text">
|
||||
{helperText}
|
||||
</div>,
|
||||
<div id={errorTextId} class="error-text" part="supporting-text error-text" role="alert">
|
||||
{isInvalid ? errorText : null}
|
||||
<div id={errorTextId} class="error-text" part="supporting-text error-text">
|
||||
{errorText}
|
||||
</div>,
|
||||
];
|
||||
}
|
||||
|
||||
@@ -1,200 +0,0 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="en" dir="ltr">
|
||||
<head>
|
||||
<meta charset="UTF-8" />
|
||||
<title>Select - Validation</title>
|
||||
<meta
|
||||
name="viewport"
|
||||
content="viewport-fit=cover, width=device-width, initial-scale=1.0, minimum-scale=1.0, maximum-scale=1.0, user-scalable=no"
|
||||
/>
|
||||
<link href="../../../../../css/ionic.bundle.css" rel="stylesheet" />
|
||||
<link href="../../../../../scripts/testing/styles.css" rel="stylesheet" />
|
||||
<script src="../../../../../scripts/testing/scripts.js"></script>
|
||||
<script nomodule src="../../../../../dist/ionic/ionic.js"></script>
|
||||
<script type="module" src="../../../../../dist/ionic/ionic.esm.js"></script>
|
||||
<style>
|
||||
.grid {
|
||||
display: grid;
|
||||
grid-template-columns: repeat(auto-fill, minmax(250px, 1fr));
|
||||
grid-row-gap: 30px;
|
||||
grid-column-gap: 30px;
|
||||
}
|
||||
|
||||
h2 {
|
||||
font-size: 12px;
|
||||
font-weight: normal;
|
||||
|
||||
color: var(--ion-color-step-600);
|
||||
|
||||
margin-top: 10px;
|
||||
margin-bottom: 5px;
|
||||
}
|
||||
|
||||
.validation-info {
|
||||
margin: 20px;
|
||||
padding: 10px;
|
||||
background: var(--ion-color-light);
|
||||
border-radius: 4px;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<ion-app>
|
||||
<ion-header>
|
||||
<ion-toolbar>
|
||||
<ion-title>Select - Validation Test</ion-title>
|
||||
</ion-toolbar>
|
||||
</ion-header>
|
||||
|
||||
<ion-content class="ion-padding">
|
||||
<div class="validation-info">
|
||||
<h2>Screen Reader Testing Instructions:</h2>
|
||||
<ol>
|
||||
<li>Enable your screen reader (VoiceOver, NVDA, JAWS, etc.)</li>
|
||||
<li>Tab through the form fields</li>
|
||||
<li>When you tab away from an empty required field, the error should be announced immediately</li>
|
||||
<li>The error text should be announced BEFORE the next field is announced</li>
|
||||
<li>Test in Chrome, Safari, and Firefox to verify consistent behavior</li>
|
||||
</ol>
|
||||
</div>
|
||||
|
||||
<div class="grid">
|
||||
<div>
|
||||
<h2>Required Field</h2>
|
||||
<ion-select
|
||||
id="fruits-select"
|
||||
label="Fruits"
|
||||
placeholder="Select one"
|
||||
interface="alert"
|
||||
helper-text="You must select an option to continue"
|
||||
error-text="This field is required"
|
||||
required
|
||||
>
|
||||
<ion-select-option value="apples">Apples</ion-select-option>
|
||||
<ion-select-option value="oranges">Oranges</ion-select-option>
|
||||
<ion-select-option value="pears">Pears</ion-select-option>
|
||||
</ion-select>
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<h2>Optional Field (No Validation)</h2>
|
||||
<ion-select
|
||||
id="optional-select"
|
||||
label="Colors"
|
||||
placeholder="Select one"
|
||||
interface="alert"
|
||||
helper-text="You can skip this field"
|
||||
>
|
||||
<ion-select-option value="red">Red</ion-select-option>
|
||||
<ion-select-option value="blue">Blue</ion-select-option>
|
||||
<ion-select-option value="green">Green</ion-select-option>
|
||||
</ion-select>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="ion-padding">
|
||||
<ion-button id="submit-btn" expand="block" disabled>Submit Form</ion-button>
|
||||
<ion-button id="reset-btn" expand="block" fill="outline">Reset Form</ion-button>
|
||||
</div>
|
||||
</ion-content>
|
||||
</ion-app>
|
||||
|
||||
<script>
|
||||
// Simple validation logic
|
||||
const selects = document.querySelectorAll('ion-select');
|
||||
const submitBtn = document.getElementById('submit-btn');
|
||||
const resetBtn = document.getElementById('reset-btn');
|
||||
|
||||
// Track which fields have been touched
|
||||
const touchedFields = new Set();
|
||||
|
||||
// Validation functions
|
||||
const validators = {
|
||||
'fruits-select': (value) => {
|
||||
return value !== '' && value !== undefined;
|
||||
},
|
||||
'optional-select': () => true, // Always valid
|
||||
};
|
||||
|
||||
function validateField(select) {
|
||||
const selectId = select.id;
|
||||
const value = select.value;
|
||||
const isValid = validators[selectId] ? validators[selectId](value) : true;
|
||||
|
||||
// Only show validation state if field has been touched
|
||||
if (touchedFields.has(selectId)) {
|
||||
if (isValid) {
|
||||
select.classList.remove('ion-invalid');
|
||||
select.classList.add('ion-valid');
|
||||
} else {
|
||||
select.classList.remove('ion-valid');
|
||||
select.classList.add('ion-invalid');
|
||||
}
|
||||
select.classList.add('ion-touched');
|
||||
}
|
||||
|
||||
return isValid;
|
||||
}
|
||||
|
||||
function validateForm() {
|
||||
let allValid = true;
|
||||
selects.forEach((select) => {
|
||||
if (select.id !== 'optional-select') {
|
||||
const isValid = validateField(select);
|
||||
if (!isValid) {
|
||||
allValid = false;
|
||||
}
|
||||
}
|
||||
});
|
||||
submitBtn.disabled = !allValid;
|
||||
return allValid;
|
||||
}
|
||||
|
||||
// Add event listeners
|
||||
selects.forEach((select) => {
|
||||
// Mark as touched on blur
|
||||
select.addEventListener('ionBlur', (e) => {
|
||||
console.log('Blur event on:', select.id);
|
||||
touchedFields.add(select.id);
|
||||
validateField(select);
|
||||
validateForm();
|
||||
|
||||
const isInvalid = select.classList.contains('ion-invalid');
|
||||
if (isInvalid) {
|
||||
console.log('Field marked invalid:', select.label, select.errorText);
|
||||
}
|
||||
});
|
||||
|
||||
// Validate on change
|
||||
select.addEventListener('ionChange', (e) => {
|
||||
console.log('Change event on:', select.id);
|
||||
if (touchedFields.has(select.id)) {
|
||||
validateField(select);
|
||||
validateForm();
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
// Reset button
|
||||
resetBtn.addEventListener('click', () => {
|
||||
selects.forEach((select) => {
|
||||
select.value = '';
|
||||
select.classList.remove('ion-valid', 'ion-invalid', 'ion-touched');
|
||||
});
|
||||
touchedFields.clear();
|
||||
submitBtn.disabled = true;
|
||||
});
|
||||
|
||||
// Submit button
|
||||
submitBtn.addEventListener('click', () => {
|
||||
if (validateForm()) {
|
||||
alert('Form submitted successfully!');
|
||||
}
|
||||
});
|
||||
|
||||
// Initial setup
|
||||
validateForm();
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
@@ -22,7 +22,6 @@ import type { TabBarChangedEventDetail } from './tab-bar-interface';
|
||||
})
|
||||
export class TabBar implements ComponentInterface {
|
||||
private keyboardCtrl: KeyboardController | null = null;
|
||||
private didLoad = false;
|
||||
|
||||
@Element() el!: HTMLElement;
|
||||
|
||||
@@ -41,12 +40,6 @@ export class TabBar implements ComponentInterface {
|
||||
@Prop() selectedTab?: string;
|
||||
@Watch('selectedTab')
|
||||
selectedTabChanged() {
|
||||
// Skip the initial watcher call that happens during component load
|
||||
// We handle that in componentDidLoad to ensure children are ready
|
||||
if (!this.didLoad) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (this.selectedTab !== undefined) {
|
||||
this.ionTabBarChanged.emit({
|
||||
tab: this.selectedTab,
|
||||
@@ -72,19 +65,8 @@ export class TabBar implements ComponentInterface {
|
||||
*/
|
||||
@Event() ionTabBarLoaded!: EventEmitter<void>;
|
||||
|
||||
componentDidLoad() {
|
||||
this.ionTabBarLoaded.emit();
|
||||
// Set the flag to indicate the component has loaded
|
||||
// This allows the watcher to emit changes from this point forward
|
||||
this.didLoad = true;
|
||||
|
||||
// Emit the initial selected tab after the component is fully loaded
|
||||
// This ensures all child components (ion-tab-button) are ready
|
||||
if (this.selectedTab !== undefined) {
|
||||
this.ionTabBarChanged.emit({
|
||||
tab: this.selectedTab,
|
||||
});
|
||||
}
|
||||
componentWillLoad() {
|
||||
this.selectedTabChanged();
|
||||
}
|
||||
|
||||
async connectedCallback() {
|
||||
@@ -108,6 +90,10 @@ export class TabBar implements ComponentInterface {
|
||||
}
|
||||
}
|
||||
|
||||
componentDidLoad() {
|
||||
this.ionTabBarLoaded.emit();
|
||||
}
|
||||
|
||||
render() {
|
||||
const { color, translucent, keyboardVisible } = this;
|
||||
const mode = getIonMode(this);
|
||||
|
||||
Binary file not shown.
|
Before Width: | Height: | Size: 9.3 KiB After Width: | Height: | Size: 9.3 KiB |
Binary file not shown.
|
Before Width: | Height: | Size: 5.6 KiB After Width: | Height: | Size: 5.7 KiB |
@@ -65,33 +65,32 @@ export class Tabs implements NavOutlet {
|
||||
this.ionNavWillLoad.emit();
|
||||
}
|
||||
|
||||
componentDidLoad() {
|
||||
this.updateTabBar();
|
||||
}
|
||||
|
||||
componentDidUpdate() {
|
||||
this.updateTabBar();
|
||||
}
|
||||
|
||||
private updateTabBar() {
|
||||
componentWillRender() {
|
||||
const tabBar = this.el.querySelector('ion-tab-bar');
|
||||
if (!tabBar) {
|
||||
return;
|
||||
if (tabBar) {
|
||||
let tab = this.selectedTab ? this.selectedTab.tab : undefined;
|
||||
|
||||
// Fallback: if no selectedTab is set but we're using router mode,
|
||||
// determine the active tab from the current URL. This works around
|
||||
// timing issues in React Router integration where setRouteId may not
|
||||
// be called in time for the initial render.
|
||||
// TODO(FW-6724): Remove this with React Router upgrade
|
||||
if (!tab && this.useRouter && typeof window !== 'undefined') {
|
||||
const currentPath = window.location.pathname;
|
||||
const tabButtons = this.el.querySelectorAll('ion-tab-button');
|
||||
|
||||
// Look for a tab button that matches the current path pattern
|
||||
for (const tabButton of tabButtons) {
|
||||
const tabId = tabButton.getAttribute('tab');
|
||||
if (tabId && currentPath.includes(tabId)) {
|
||||
tab = tabId;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
tabBar.selectedTab = tab;
|
||||
}
|
||||
|
||||
const tab = this.selectedTab ? this.selectedTab.tab : undefined;
|
||||
|
||||
// If tabs has no selected tab but tab-bar already has a selected-tab set,
|
||||
// don't overwrite it. This handles cases where tab-bar is used without ion-tab elements.
|
||||
if (tab === undefined) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (tabBar.selectedTab === tab) {
|
||||
return;
|
||||
}
|
||||
|
||||
tabBar.selectedTab = tab;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -163,7 +162,6 @@ export class Tabs implements NavOutlet {
|
||||
this.selectedTab = selectedTab;
|
||||
this.ionTabsWillChange.emit({ tab: selectedTab.tab });
|
||||
selectedTab.active = true;
|
||||
this.updateTabBar();
|
||||
return Promise.resolve();
|
||||
}
|
||||
|
||||
|
||||
@@ -15,7 +15,7 @@ import {
|
||||
writeTask,
|
||||
} from '@stencil/core';
|
||||
import type { NotchController } from '@utils/forms';
|
||||
import { createNotchController, checkInvalidState } from '@utils/forms';
|
||||
import { createNotchController } from '@utils/forms';
|
||||
import type { Attributes } from '@utils/helpers';
|
||||
import { inheritAriaAttributes, debounceEvent, inheritAttributes, componentOnReady } from '@utils/helpers';
|
||||
import { createSlotMutationController } from '@utils/slot-mutation-controller';
|
||||
@@ -335,6 +335,16 @@ export class Textarea implements ComponentInterface {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if the textarea is in an invalid state based on Ionic validation classes
|
||||
*/
|
||||
private checkValidationState(): boolean {
|
||||
const hasIonTouched = this.el.classList.contains('ion-touched');
|
||||
const hasIonInvalid = this.el.classList.contains('ion-invalid');
|
||||
|
||||
return hasIonTouched && hasIonInvalid;
|
||||
}
|
||||
|
||||
connectedCallback() {
|
||||
const { el } = this;
|
||||
this.slotMutationController = createSlotMutationController(el, ['label', 'start', 'end'], () => forceUpdate(this));
|
||||
@@ -347,7 +357,7 @@ export class Textarea implements ComponentInterface {
|
||||
// Watch for class changes to update validation state
|
||||
if (Build.isBrowser && typeof MutationObserver !== 'undefined') {
|
||||
this.validationObserver = new MutationObserver(() => {
|
||||
const newIsInvalid = checkInvalidState(this.el);
|
||||
const newIsInvalid = this.checkValidationState();
|
||||
if (this.isInvalid !== newIsInvalid) {
|
||||
this.isInvalid = newIsInvalid;
|
||||
// Force a re-render to update aria-describedby immediately
|
||||
@@ -362,7 +372,7 @@ export class Textarea implements ComponentInterface {
|
||||
}
|
||||
|
||||
// Always set initial state
|
||||
this.isInvalid = checkInvalidState(this.el);
|
||||
this.isInvalid = this.checkValidationState();
|
||||
|
||||
this.debounceChanged();
|
||||
if (Build.isBrowser) {
|
||||
|
||||
@@ -1,3 +1,2 @@
|
||||
export * from './notch-controller';
|
||||
export * from './compare-with-utils';
|
||||
export * from './validity';
|
||||
|
||||
@@ -1,15 +0,0 @@
|
||||
type FormElement = HTMLIonInputElement | HTMLIonTextareaElement | HTMLIonSelectElement;
|
||||
|
||||
/**
|
||||
* Checks if the form element is in an invalid state based on
|
||||
* Ionic validation classes.
|
||||
*
|
||||
* @param el The form element to check.
|
||||
* @returns `true` if the element is invalid, `false` otherwise.
|
||||
*/
|
||||
export const checkInvalidState = (el: FormElement): boolean => {
|
||||
const hasIonTouched = el.classList.contains('ion-touched');
|
||||
const hasIonInvalid = el.classList.contains('ion-invalid');
|
||||
|
||||
return hasIonTouched && hasIonInvalid;
|
||||
};
|
||||
@@ -539,11 +539,18 @@ export const present = async <OverlayPresentOptions>(
|
||||
* view container subtree, skip adding aria-hidden/inert there
|
||||
* to avoid disabling the overlay.
|
||||
*/
|
||||
const overlayEl = overlay.el as HTMLIonOverlayElement & { focusTrap?: boolean; showBackdrop?: boolean };
|
||||
const shouldTrapFocus = overlayEl.tagName !== 'ION-TOAST' && overlayEl.focusTrap !== false;
|
||||
const overlayEl = overlay.el as HTMLIonOverlayElement & {
|
||||
focusTrap?: boolean;
|
||||
showBackdrop?: boolean;
|
||||
};
|
||||
const focusTrapAttr = overlayEl.getAttribute?.('focus-trap');
|
||||
const showBackdropAttr = overlayEl.getAttribute?.('show-backdrop');
|
||||
const focusTrapDisabled = overlayEl.focusTrap === false || focusTrapAttr === 'false';
|
||||
const backdropDisabled = overlayEl.showBackdrop === false || showBackdropAttr === 'false';
|
||||
const shouldTrapFocus = overlayEl.tagName !== 'ION-TOAST' && !focusTrapDisabled;
|
||||
// Only lock out root content when backdrop is active. Developers relying on showBackdrop=false
|
||||
// expect background interaction to remain enabled.
|
||||
const shouldLockRoot = shouldTrapFocus && overlayEl.showBackdrop !== false;
|
||||
const shouldLockRoot = shouldTrapFocus && !backdropDisabled;
|
||||
|
||||
overlay.presented = true;
|
||||
overlay.willPresent.emit();
|
||||
@@ -681,11 +688,21 @@ export const dismiss = async <OverlayDismissOptions>(
|
||||
*/
|
||||
const overlaysLockingRoot = presentedOverlays.filter((o) => {
|
||||
const el = o as HTMLIonOverlayElement & { focusTrap?: boolean; showBackdrop?: boolean };
|
||||
return el.tagName !== 'ION-TOAST' && el.focusTrap !== false && el.showBackdrop !== false;
|
||||
const focusTrapAttr = el.getAttribute?.('focus-trap');
|
||||
const showBackdropAttr = el.getAttribute?.('show-backdrop');
|
||||
const focusTrapDisabled = el.focusTrap === false || focusTrapAttr === 'false';
|
||||
const backdropDisabled = el.showBackdrop === false || showBackdropAttr === 'false';
|
||||
return el.tagName !== 'ION-TOAST' && !focusTrapDisabled && !backdropDisabled;
|
||||
});
|
||||
const overlayEl = overlay.el as HTMLIonOverlayElement & { focusTrap?: boolean; showBackdrop?: boolean };
|
||||
const locksRoot =
|
||||
overlayEl.tagName !== 'ION-TOAST' && overlayEl.focusTrap !== false && overlayEl.showBackdrop !== false;
|
||||
const overlayEl = overlay.el as HTMLIonOverlayElement & {
|
||||
focusTrap?: boolean;
|
||||
showBackdrop?: boolean;
|
||||
};
|
||||
const focusTrapAttr = overlayEl.getAttribute?.('focus-trap');
|
||||
const showBackdropAttr = overlayEl.getAttribute?.('show-backdrop');
|
||||
const focusTrapDisabled = overlayEl.focusTrap === false || focusTrapAttr === 'false';
|
||||
const backdropDisabled = overlayEl.showBackdrop === false || showBackdropAttr === 'false';
|
||||
const locksRoot = overlayEl.tagName !== 'ION-TOAST' && !focusTrapDisabled && !backdropDisabled;
|
||||
|
||||
/**
|
||||
* If this is the last visible overlay that is trapping focus
|
||||
|
||||
@@ -37,6 +37,26 @@ describe('overlays: scroll blocking', () => {
|
||||
expect(body).not.toHaveClass('backdrop-no-scroll');
|
||||
});
|
||||
|
||||
it('should not block scroll when focus-trap attribute is set to "false"', async () => {
|
||||
const page = await newSpecPage({
|
||||
components: [Modal],
|
||||
html: `
|
||||
<ion-modal focus-trap="false"></ion-modal>
|
||||
`,
|
||||
});
|
||||
|
||||
const modal = page.body.querySelector('ion-modal')!;
|
||||
const body = page.doc.querySelector('body')!;
|
||||
|
||||
await modal.present();
|
||||
|
||||
expect(body).not.toHaveClass('backdrop-no-scroll');
|
||||
|
||||
await modal.dismiss();
|
||||
|
||||
expect(body).not.toHaveClass('backdrop-no-scroll');
|
||||
});
|
||||
|
||||
it('should not block scroll when the overlay is dismissed', async () => {
|
||||
const page = await newSpecPage({
|
||||
components: [Modal],
|
||||
|
||||
@@ -18,51 +18,34 @@ const focusController = createFocusController();
|
||||
|
||||
// TODO(FW-2832): types
|
||||
|
||||
/**
|
||||
* Executes the main page transition.
|
||||
* It also manages the lifecycle of header visibility (if any)
|
||||
* to prevent visual flickering in iOS. The flickering only
|
||||
* occurs for a condensed header that is placed above the content.
|
||||
*
|
||||
* @param opts Options for the transition.
|
||||
* @returns A promise that resolves when the transition is complete.
|
||||
*/
|
||||
export const transition = (opts: TransitionOptions): Promise<TransitionResult> => {
|
||||
return new Promise((resolve, reject) => {
|
||||
writeTask(() => {
|
||||
const transitioningInactiveHeader = getIosIonHeader(opts);
|
||||
beforeTransition(opts, transitioningInactiveHeader);
|
||||
runTransition(opts)
|
||||
.then(
|
||||
(result) => {
|
||||
if (result.animation) {
|
||||
result.animation.destroy();
|
||||
}
|
||||
afterTransition(opts);
|
||||
resolve(result);
|
||||
},
|
||||
(error) => {
|
||||
afterTransition(opts);
|
||||
reject(error);
|
||||
beforeTransition(opts);
|
||||
runTransition(opts).then(
|
||||
(result) => {
|
||||
if (result.animation) {
|
||||
result.animation.destroy();
|
||||
}
|
||||
)
|
||||
.finally(() => {
|
||||
// Ensure that the header is restored to its original state.
|
||||
setHeaderTransitionClass(transitioningInactiveHeader, false);
|
||||
});
|
||||
afterTransition(opts);
|
||||
resolve(result);
|
||||
},
|
||||
(error) => {
|
||||
afterTransition(opts);
|
||||
reject(error);
|
||||
}
|
||||
);
|
||||
});
|
||||
});
|
||||
};
|
||||
|
||||
const beforeTransition = (opts: TransitionOptions, transitioningInactiveHeader: HTMLElement | null) => {
|
||||
const beforeTransition = (opts: TransitionOptions) => {
|
||||
const enteringEl = opts.enteringEl;
|
||||
const leavingEl = opts.leavingEl;
|
||||
|
||||
focusController.saveViewFocus(leavingEl);
|
||||
|
||||
setZIndex(enteringEl, leavingEl, opts.direction);
|
||||
// Prevent flickering of the header by adding a class.
|
||||
setHeaderTransitionClass(transitioningInactiveHeader, true);
|
||||
|
||||
if (opts.showGoBack) {
|
||||
enteringEl.classList.add('can-go-back');
|
||||
@@ -295,40 +278,6 @@ const setZIndex = (
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Add a class to ensure that the header (if any)
|
||||
* does not flicker during the transition. By adding the
|
||||
* transitioning class, we ensure that the header has
|
||||
* the necessary styles to prevent the following flickers:
|
||||
* 1. When entering a page with a condensed header, the
|
||||
* header should never be visible. However,
|
||||
* it briefly renders the background color while
|
||||
* the transition is occurring.
|
||||
* 2. When leaving a page with a condensed header, the
|
||||
* header has an opacity of 0 and the pages
|
||||
* have a z-index which causes the entering page to
|
||||
* briefly show it's content underneath the leaving page.
|
||||
* 3. When entering a page or leaving a page with a fade
|
||||
* header, the header should not have a background color.
|
||||
* However, it briefly shows the background color while
|
||||
* the transition is occurring.
|
||||
*
|
||||
* @param header The header element to modify.
|
||||
* @param isTransitioning Whether the transition is occurring.
|
||||
*/
|
||||
const setHeaderTransitionClass = (header: HTMLElement | null, isTransitioning: boolean) => {
|
||||
if (!header) {
|
||||
return;
|
||||
}
|
||||
|
||||
const transitionClass = 'header-transitioning';
|
||||
if (isTransitioning) {
|
||||
header.classList.add(transitionClass);
|
||||
} else {
|
||||
header.classList.remove(transitionClass);
|
||||
}
|
||||
};
|
||||
|
||||
export const getIonPageElement = (element: HTMLElement) => {
|
||||
if (element.classList.contains('ion-page')) {
|
||||
return element;
|
||||
@@ -342,32 +291,6 @@ export const getIonPageElement = (element: HTMLElement) => {
|
||||
return element;
|
||||
};
|
||||
|
||||
/**
|
||||
* Retrieves the ion-header element from a page based on the
|
||||
* direction of the transition.
|
||||
*
|
||||
* @param opts Options for the transition.
|
||||
* @returns The ion-header element or null if not found or not in 'ios' mode.
|
||||
*/
|
||||
const getIosIonHeader = (opts: TransitionOptions): HTMLElement | null => {
|
||||
const enteringEl = opts.enteringEl;
|
||||
const leavingEl = opts.leavingEl;
|
||||
const direction = opts.direction;
|
||||
const mode = opts.mode;
|
||||
|
||||
if (mode !== 'ios') {
|
||||
return null;
|
||||
}
|
||||
|
||||
const element = direction === 'back' ? leavingEl : enteringEl;
|
||||
|
||||
if (!element) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return element.querySelector('ion-header');
|
||||
};
|
||||
|
||||
export interface TransitionOptions extends NavOptions {
|
||||
progressCallback?: (ani: Animation | undefined) => void;
|
||||
baseEl: any;
|
||||
|
||||
@@ -3,5 +3,5 @@
|
||||
"core",
|
||||
"packages/*"
|
||||
],
|
||||
"version": "8.7.7"
|
||||
"version": "8.7.5"
|
||||
}
|
||||
@@ -3,22 +3,6 @@
|
||||
All notable changes to this project will be documented in this file.
|
||||
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
|
||||
|
||||
## [8.7.7](https://github.com/ionic-team/ionic-framework/compare/v8.7.6...v8.7.7) (2025-10-15)
|
||||
|
||||
**Note:** Version bump only for package @ionic/angular-server
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
## [8.7.6](https://github.com/ionic-team/ionic-framework/compare/v8.7.5...v8.7.6) (2025-10-08)
|
||||
|
||||
**Note:** Version bump only for package @ionic/angular-server
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
## [8.7.5](https://github.com/ionic-team/ionic-framework/compare/v8.7.4...v8.7.5) (2025-09-24)
|
||||
|
||||
**Note:** Version bump only for package @ionic/angular-server
|
||||
|
||||
36
packages/angular-server/package-lock.json
generated
36
packages/angular-server/package-lock.json
generated
@@ -1,15 +1,15 @@
|
||||
{
|
||||
"name": "@ionic/angular-server",
|
||||
"version": "8.7.7",
|
||||
"version": "8.7.5",
|
||||
"lockfileVersion": 2,
|
||||
"requires": true,
|
||||
"packages": {
|
||||
"": {
|
||||
"name": "@ionic/angular-server",
|
||||
"version": "8.7.7",
|
||||
"version": "8.7.5",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@ionic/core": "^8.7.7"
|
||||
"@ionic/core": "^8.7.5"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@angular-eslint/eslint-plugin": "^16.0.0",
|
||||
@@ -1031,12 +1031,12 @@
|
||||
"dev": true
|
||||
},
|
||||
"node_modules/@ionic/core": {
|
||||
"version": "8.7.6",
|
||||
"resolved": "https://registry.npmjs.org/@ionic/core/-/core-8.7.6.tgz",
|
||||
"integrity": "sha512-ufV64Pl0BYSoNla+DaTRXTS3hX6MQZZJPhAR3fJQ4N5Fg/vwMcHADQffstKZeoPqk6mbJoLqoTBjcWvaLRdO0g==",
|
||||
"version": "8.7.5",
|
||||
"resolved": "https://registry.npmjs.org/@ionic/core/-/core-8.7.5.tgz",
|
||||
"integrity": "sha512-Uk1qdGPoLHaVhd2FnYSAvRehd3VwwcPIfXaR51qiC7C2L5VhD27VyLSgDetc15G4U+VAIFjgUSR/pKdLFEuMPA==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@stencil/core": "4.38.0",
|
||||
"@stencil/core": "4.36.2",
|
||||
"ionicons": "^8.0.13",
|
||||
"tslib": "^2.1.0"
|
||||
}
|
||||
@@ -1386,9 +1386,9 @@
|
||||
]
|
||||
},
|
||||
"node_modules/@stencil/core": {
|
||||
"version": "4.38.0",
|
||||
"resolved": "https://registry.npmjs.org/@stencil/core/-/core-4.38.0.tgz",
|
||||
"integrity": "sha512-oC3QFKO0X1yXVvETgc8OLY525MNKhn9vISBrbtKnGoPlokJ6rI8Vk1RK22TevnNrHLI4SExNLbcDnqilKR35JQ==",
|
||||
"version": "4.36.2",
|
||||
"resolved": "https://registry.npmjs.org/@stencil/core/-/core-4.36.2.tgz",
|
||||
"integrity": "sha512-PRFSpxNzX9Oi0Wfh02asztN9Sgev/MacfZwmd+VVyE6ZxW+a/kEpAYZhzGAmE+/aKVOGYuug7R9SulanYGxiDQ==",
|
||||
"license": "MIT",
|
||||
"bin": {
|
||||
"stencil": "bin/stencil"
|
||||
@@ -7306,11 +7306,11 @@
|
||||
"dev": true
|
||||
},
|
||||
"@ionic/core": {
|
||||
"version": "8.7.6",
|
||||
"resolved": "https://registry.npmjs.org/@ionic/core/-/core-8.7.6.tgz",
|
||||
"integrity": "sha512-ufV64Pl0BYSoNla+DaTRXTS3hX6MQZZJPhAR3fJQ4N5Fg/vwMcHADQffstKZeoPqk6mbJoLqoTBjcWvaLRdO0g==",
|
||||
"version": "8.7.5",
|
||||
"resolved": "https://registry.npmjs.org/@ionic/core/-/core-8.7.5.tgz",
|
||||
"integrity": "sha512-Uk1qdGPoLHaVhd2FnYSAvRehd3VwwcPIfXaR51qiC7C2L5VhD27VyLSgDetc15G4U+VAIFjgUSR/pKdLFEuMPA==",
|
||||
"requires": {
|
||||
"@stencil/core": "4.38.0",
|
||||
"@stencil/core": "4.36.2",
|
||||
"ionicons": "^8.0.13",
|
||||
"tslib": "^2.1.0"
|
||||
}
|
||||
@@ -7529,9 +7529,9 @@
|
||||
"optional": true
|
||||
},
|
||||
"@stencil/core": {
|
||||
"version": "4.38.0",
|
||||
"resolved": "https://registry.npmjs.org/@stencil/core/-/core-4.38.0.tgz",
|
||||
"integrity": "sha512-oC3QFKO0X1yXVvETgc8OLY525MNKhn9vISBrbtKnGoPlokJ6rI8Vk1RK22TevnNrHLI4SExNLbcDnqilKR35JQ==",
|
||||
"version": "4.36.2",
|
||||
"resolved": "https://registry.npmjs.org/@stencil/core/-/core-4.36.2.tgz",
|
||||
"integrity": "sha512-PRFSpxNzX9Oi0Wfh02asztN9Sgev/MacfZwmd+VVyE6ZxW+a/kEpAYZhzGAmE+/aKVOGYuug7R9SulanYGxiDQ==",
|
||||
"requires": {
|
||||
"@rollup/rollup-darwin-arm64": "4.34.9",
|
||||
"@rollup/rollup-darwin-x64": "4.34.9",
|
||||
@@ -11286,4 +11286,4 @@
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@ionic/angular-server",
|
||||
"version": "8.7.7",
|
||||
"version": "8.7.5",
|
||||
"description": "Angular SSR Module for Ionic",
|
||||
"keywords": [
|
||||
"ionic",
|
||||
@@ -62,6 +62,6 @@
|
||||
},
|
||||
"prettier": "@ionic/prettier-config",
|
||||
"dependencies": {
|
||||
"@ionic/core": "^8.7.7"
|
||||
"@ionic/core": "^8.7.5"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3,25 +3,6 @@
|
||||
All notable changes to this project will be documented in this file.
|
||||
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
|
||||
|
||||
## [8.7.7](https://github.com/ionic-team/ionic-framework/compare/v8.7.6...v8.7.7) (2025-10-15)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* **select:** improve screen reader announcement timing for validation errors ([#30723](https://github.com/ionic-team/ionic-framework/issues/30723)) ([03303d7](https://github.com/ionic-team/ionic-framework/commit/03303d73f0bfe2380ced7931525fc52fd8576367))
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
## [8.7.6](https://github.com/ionic-team/ionic-framework/compare/v8.7.5...v8.7.6) (2025-10-08)
|
||||
|
||||
**Note:** Version bump only for package @ionic/angular
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
## [8.7.5](https://github.com/ionic-team/ionic-framework/compare/v8.7.4...v8.7.5) (2025-09-24)
|
||||
|
||||
|
||||
|
||||
22
packages/angular/package-lock.json
generated
22
packages/angular/package-lock.json
generated
@@ -1,15 +1,15 @@
|
||||
{
|
||||
"name": "@ionic/angular",
|
||||
"version": "8.7.7",
|
||||
"version": "8.7.5",
|
||||
"lockfileVersion": 3,
|
||||
"requires": true,
|
||||
"packages": {
|
||||
"": {
|
||||
"name": "@ionic/angular",
|
||||
"version": "8.7.7",
|
||||
"version": "8.7.5",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@ionic/core": "^8.7.7",
|
||||
"@ionic/core": "^8.7.5",
|
||||
"ionicons": "^8.0.13",
|
||||
"jsonc-parser": "^3.0.0",
|
||||
"tslib": "^2.3.0"
|
||||
@@ -1398,12 +1398,12 @@
|
||||
"dev": true
|
||||
},
|
||||
"node_modules/@ionic/core": {
|
||||
"version": "8.7.6",
|
||||
"resolved": "https://registry.npmjs.org/@ionic/core/-/core-8.7.6.tgz",
|
||||
"integrity": "sha512-ufV64Pl0BYSoNla+DaTRXTS3hX6MQZZJPhAR3fJQ4N5Fg/vwMcHADQffstKZeoPqk6mbJoLqoTBjcWvaLRdO0g==",
|
||||
"version": "8.7.5",
|
||||
"resolved": "https://registry.npmjs.org/@ionic/core/-/core-8.7.5.tgz",
|
||||
"integrity": "sha512-Uk1qdGPoLHaVhd2FnYSAvRehd3VwwcPIfXaR51qiC7C2L5VhD27VyLSgDetc15G4U+VAIFjgUSR/pKdLFEuMPA==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@stencil/core": "4.38.0",
|
||||
"@stencil/core": "4.36.2",
|
||||
"ionicons": "^8.0.13",
|
||||
"tslib": "^2.1.0"
|
||||
}
|
||||
@@ -2308,9 +2308,9 @@
|
||||
}
|
||||
},
|
||||
"node_modules/@stencil/core": {
|
||||
"version": "4.38.0",
|
||||
"resolved": "https://registry.npmjs.org/@stencil/core/-/core-4.38.0.tgz",
|
||||
"integrity": "sha512-oC3QFKO0X1yXVvETgc8OLY525MNKhn9vISBrbtKnGoPlokJ6rI8Vk1RK22TevnNrHLI4SExNLbcDnqilKR35JQ==",
|
||||
"version": "4.36.2",
|
||||
"resolved": "https://registry.npmjs.org/@stencil/core/-/core-4.36.2.tgz",
|
||||
"integrity": "sha512-PRFSpxNzX9Oi0Wfh02asztN9Sgev/MacfZwmd+VVyE6ZxW+a/kEpAYZhzGAmE+/aKVOGYuug7R9SulanYGxiDQ==",
|
||||
"license": "MIT",
|
||||
"bin": {
|
||||
"stencil": "bin/stencil"
|
||||
@@ -9079,4 +9079,4 @@
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@ionic/angular",
|
||||
"version": "8.7.7",
|
||||
"version": "8.7.5",
|
||||
"description": "Angular specific wrappers for @ionic/core",
|
||||
"keywords": [
|
||||
"ionic",
|
||||
@@ -48,7 +48,7 @@
|
||||
}
|
||||
},
|
||||
"dependencies": {
|
||||
"@ionic/core": "^8.7.7",
|
||||
"@ionic/core": "^8.7.5",
|
||||
"ionicons": "^8.0.13",
|
||||
"jsonc-parser": "^3.0.0",
|
||||
"tslib": "^2.3.0"
|
||||
|
||||
@@ -77,31 +77,6 @@
|
||||
<p>MinLength Errors: <span id="minlength-errors">{{minLengthField.errors | json}}</span></p>
|
||||
</ion-label>
|
||||
</ion-item>
|
||||
|
||||
<!-- Test ion-select with required validation -->
|
||||
<ion-item>
|
||||
<ion-select
|
||||
label="Required Select"
|
||||
[(ngModel)]="selectValue"
|
||||
name="selectField"
|
||||
required
|
||||
#selectField="ngModel"
|
||||
id="template-select-test"
|
||||
errorText="This field is required"
|
||||
helperText="Select an option">
|
||||
<ion-select-option value="option1">Option 1</ion-select-option>
|
||||
<ion-select-option value="option2">Option 2</ion-select-option>
|
||||
</ion-select>
|
||||
</ion-item>
|
||||
|
||||
<!-- Display validation state for debugging -->
|
||||
<ion-item>
|
||||
<ion-label>
|
||||
<p>Select Touched: <span id="select-touched">{{selectField.touched}}</span></p>
|
||||
<p>Select Invalid: <span id="select-invalid">{{selectField.invalid}}</span></p>
|
||||
<p>Select Errors: <span id="select-errors">{{selectField.errors | json}}</span></p>
|
||||
</ion-label>
|
||||
</ion-item>
|
||||
</ion-list>
|
||||
|
||||
<div class="ion-padding">
|
||||
|
||||
@@ -9,7 +9,6 @@ export class TemplateFormComponent {
|
||||
inputValue = '';
|
||||
textareaValue = '';
|
||||
minLengthValue = '';
|
||||
selectValue = '';
|
||||
|
||||
// Track if form has been submitted
|
||||
submitted = false;
|
||||
|
||||
@@ -47,7 +47,6 @@ export const routes: Routes = [
|
||||
children: [
|
||||
{ path: 'input-validation', loadComponent: () => import('../validation/input-validation/input-validation.component').then(c => c.InputValidationComponent) },
|
||||
{ path: 'textarea-validation', loadComponent: () => import('../validation/textarea-validation/textarea-validation.component').then(c => c.TextareaValidationComponent) },
|
||||
{ path: 'select-validation', loadComponent: () => import('../validation/select-validation/select-validation.component').then(c => c.SelectValidationComponent) },
|
||||
{ path: '**', redirectTo: 'input-validation' }
|
||||
]
|
||||
},
|
||||
|
||||
@@ -131,11 +131,6 @@
|
||||
Textarea Validation Test
|
||||
</ion-label>
|
||||
</ion-item>
|
||||
<ion-item routerLink="/standalone/validation/select-validation">
|
||||
<ion-label>
|
||||
Select Validation Test
|
||||
</ion-label>
|
||||
</ion-item>
|
||||
</ion-list>
|
||||
|
||||
<ion-list>
|
||||
|
||||
@@ -1,63 +0,0 @@
|
||||
<ion-header>
|
||||
<ion-toolbar>
|
||||
<ion-title>Select - Validation Test</ion-title>
|
||||
</ion-toolbar>
|
||||
</ion-header>
|
||||
|
||||
<ion-content class="ion-padding">
|
||||
<div class="validation-info">
|
||||
<h2>Screen Reader Testing Instructions:</h2>
|
||||
<ol>
|
||||
<li>Enable your screen reader (VoiceOver, NVDA, JAWS, etc.)</li>
|
||||
<li>Tab through the form fields</li>
|
||||
<li>When you tab away from an empty required field, the error should be announced immediately</li>
|
||||
<li>The error text should be announced BEFORE the next field is announced</li>
|
||||
<li>Test in Chrome, Safari, and Firefox to verify consistent behavior</li>
|
||||
</ol>
|
||||
</div>
|
||||
|
||||
<form [formGroup]="form">
|
||||
<div class="grid">
|
||||
<div>
|
||||
<h2>Required Field</h2>
|
||||
<ion-select
|
||||
#fruitsSelect
|
||||
id="fruits-select"
|
||||
[label]="fieldMetadata.fruits.label"
|
||||
placeholder="Select one"
|
||||
interface="alert"
|
||||
[helperText]="fieldMetadata.fruits.helperText"
|
||||
[errorText]="fieldMetadata.fruits.errorText"
|
||||
formControlName="fruits"
|
||||
required
|
||||
>
|
||||
<ion-select-option value="apples">Apples</ion-select-option>
|
||||
<ion-select-option value="oranges">Oranges</ion-select-option>
|
||||
<ion-select-option value="pears">Pears</ion-select-option>
|
||||
</ion-select>
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<h2>Optional Field (No Validation)</h2>
|
||||
<ion-select
|
||||
#optionalSelect
|
||||
id="optional-select"
|
||||
[label]="fieldMetadata.optional.label"
|
||||
placeholder="Select one"
|
||||
interface="alert"
|
||||
[helperText]="fieldMetadata.optional.helperText"
|
||||
formControlName="optional"
|
||||
>
|
||||
<ion-select-option value="red">Red</ion-select-option>
|
||||
<ion-select-option value="blue">Blue</ion-select-option>
|
||||
<ion-select-option value="green">Green</ion-select-option>
|
||||
</ion-select>
|
||||
</div>
|
||||
</div>
|
||||
</form>
|
||||
|
||||
<div class="ion-padding">
|
||||
<ion-button id="submit-btn" expand="block" [disabled]="form.invalid" (click)="onSubmit()">Submit Form</ion-button>
|
||||
<ion-button id="reset-btn" expand="block" fill="outline" (click)="form.reset()">Reset Form</ion-button>
|
||||
</div>
|
||||
</ion-content>
|
||||
@@ -1,36 +0,0 @@
|
||||
.grid {
|
||||
display: grid;
|
||||
grid-template-columns: repeat(auto-fill, minmax(250px, 1fr));
|
||||
grid-row-gap: 20px;
|
||||
grid-column-gap: 20px;
|
||||
}
|
||||
|
||||
h2 {
|
||||
font-size: 12px;
|
||||
font-weight: normal;
|
||||
color: var(--ion-color-step-600);
|
||||
margin-top: 10px;
|
||||
margin-bottom: 5px;
|
||||
}
|
||||
|
||||
.validation-info {
|
||||
margin: 20px;
|
||||
padding: 10px;
|
||||
background: var(--ion-color-light);
|
||||
border-radius: 4px;
|
||||
}
|
||||
|
||||
.validation-info h2 {
|
||||
font-size: 14px;
|
||||
font-weight: 600;
|
||||
margin-bottom: 10px;
|
||||
}
|
||||
|
||||
.validation-info ol {
|
||||
margin: 0;
|
||||
padding-left: 20px;
|
||||
}
|
||||
|
||||
.validation-info li {
|
||||
margin-bottom: 5px;
|
||||
}
|
||||
@@ -1,63 +0,0 @@
|
||||
import { CommonModule } from '@angular/common';
|
||||
import { Component } from '@angular/core';
|
||||
import {
|
||||
FormBuilder,
|
||||
ReactiveFormsModule,
|
||||
Validators
|
||||
} from '@angular/forms';
|
||||
import {
|
||||
IonButton,
|
||||
IonContent,
|
||||
IonHeader,
|
||||
IonSelect,
|
||||
IonSelectOption,
|
||||
IonTitle,
|
||||
IonToolbar
|
||||
} from '@ionic/angular/standalone';
|
||||
|
||||
@Component({
|
||||
selector: 'app-select-validation',
|
||||
templateUrl: './select-validation.component.html',
|
||||
styleUrls: ['./select-validation.component.scss'],
|
||||
standalone: true,
|
||||
imports: [
|
||||
CommonModule,
|
||||
ReactiveFormsModule,
|
||||
IonSelect,
|
||||
IonSelectOption,
|
||||
IonButton,
|
||||
IonHeader,
|
||||
IonToolbar,
|
||||
IonTitle,
|
||||
IonContent
|
||||
]
|
||||
})
|
||||
export class SelectValidationComponent {
|
||||
// Field metadata for labels and error messages
|
||||
fieldMetadata = {
|
||||
fruits: {
|
||||
label: 'Fruits',
|
||||
helperText: "Select an option",
|
||||
errorText: 'This field is required'
|
||||
},
|
||||
optional: {
|
||||
label: 'Colors',
|
||||
helperText: 'You can skip this field',
|
||||
errorText: ''
|
||||
}
|
||||
};
|
||||
|
||||
form = this.fb.group({
|
||||
fruits: ['', Validators.required],
|
||||
optional: ['']
|
||||
});
|
||||
|
||||
constructor(private fb: FormBuilder) {}
|
||||
|
||||
// Submit form
|
||||
onSubmit(): void {
|
||||
if (this.form.valid) {
|
||||
alert('Form submitted successfully!');
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -3,22 +3,6 @@
|
||||
All notable changes to this project will be documented in this file.
|
||||
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
|
||||
|
||||
## [8.7.7](https://github.com/ionic-team/ionic-framework/compare/v8.7.6...v8.7.7) (2025-10-15)
|
||||
|
||||
**Note:** Version bump only for package @ionic/docs
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
## [8.7.6](https://github.com/ionic-team/ionic-framework/compare/v8.7.5...v8.7.6) (2025-10-08)
|
||||
|
||||
**Note:** Version bump only for package @ionic/docs
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
## [8.7.5](https://github.com/ionic-team/ionic-framework/compare/v8.7.4...v8.7.5) (2025-09-24)
|
||||
|
||||
**Note:** Version bump only for package @ionic/docs
|
||||
|
||||
6
packages/docs/package-lock.json
generated
6
packages/docs/package-lock.json
generated
@@ -1,13 +1,13 @@
|
||||
{
|
||||
"name": "@ionic/docs",
|
||||
"version": "8.7.7",
|
||||
"version": "8.7.5",
|
||||
"lockfileVersion": 2,
|
||||
"requires": true,
|
||||
"packages": {
|
||||
"": {
|
||||
"name": "@ionic/docs",
|
||||
"version": "8.7.7",
|
||||
"version": "8.7.5",
|
||||
"license": "MIT"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@ionic/docs",
|
||||
"version": "8.7.7",
|
||||
"version": "8.7.5",
|
||||
"description": "Pre-packaged API documentation for the Ionic docs.",
|
||||
"main": "core.json",
|
||||
"types": "core.d.ts",
|
||||
|
||||
@@ -3,22 +3,6 @@
|
||||
All notable changes to this project will be documented in this file.
|
||||
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
|
||||
|
||||
## [8.7.7](https://github.com/ionic-team/ionic-framework/compare/v8.7.6...v8.7.7) (2025-10-15)
|
||||
|
||||
**Note:** Version bump only for package @ionic/react-router
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
## [8.7.6](https://github.com/ionic-team/ionic-framework/compare/v8.7.5...v8.7.6) (2025-10-08)
|
||||
|
||||
**Note:** Version bump only for package @ionic/react-router
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
## [8.7.5](https://github.com/ionic-team/ionic-framework/compare/v8.7.4...v8.7.5) (2025-09-24)
|
||||
|
||||
**Note:** Version bump only for package @ionic/react-router
|
||||
|
||||
52
packages/react-router/package-lock.json
generated
52
packages/react-router/package-lock.json
generated
@@ -1,15 +1,15 @@
|
||||
{
|
||||
"name": "@ionic/react-router",
|
||||
"version": "8.7.7",
|
||||
"version": "8.7.5",
|
||||
"lockfileVersion": 2,
|
||||
"requires": true,
|
||||
"packages": {
|
||||
"": {
|
||||
"name": "@ionic/react-router",
|
||||
"version": "8.7.7",
|
||||
"version": "8.7.5",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@ionic/react": "^8.7.7",
|
||||
"@ionic/react": "^8.7.5",
|
||||
"tslib": "*"
|
||||
},
|
||||
"devDependencies": {
|
||||
@@ -238,12 +238,12 @@
|
||||
"dev": true
|
||||
},
|
||||
"node_modules/@ionic/core": {
|
||||
"version": "8.7.6",
|
||||
"resolved": "https://registry.npmjs.org/@ionic/core/-/core-8.7.6.tgz",
|
||||
"integrity": "sha512-ufV64Pl0BYSoNla+DaTRXTS3hX6MQZZJPhAR3fJQ4N5Fg/vwMcHADQffstKZeoPqk6mbJoLqoTBjcWvaLRdO0g==",
|
||||
"version": "8.7.5",
|
||||
"resolved": "https://registry.npmjs.org/@ionic/core/-/core-8.7.5.tgz",
|
||||
"integrity": "sha512-Uk1qdGPoLHaVhd2FnYSAvRehd3VwwcPIfXaR51qiC7C2L5VhD27VyLSgDetc15G4U+VAIFjgUSR/pKdLFEuMPA==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@stencil/core": "4.38.0",
|
||||
"@stencil/core": "4.36.2",
|
||||
"ionicons": "^8.0.13",
|
||||
"tslib": "^2.1.0"
|
||||
}
|
||||
@@ -415,12 +415,12 @@
|
||||
}
|
||||
},
|
||||
"node_modules/@ionic/react": {
|
||||
"version": "8.7.6",
|
||||
"resolved": "https://registry.npmjs.org/@ionic/react/-/react-8.7.6.tgz",
|
||||
"integrity": "sha512-7uoqcd5AOovtN7MJd5v9xeQFKF4og8W++bvDgka6TQcMTE/8mmzpFJUpOSvhFeOITMaqBHtkCNMvQSCa7vsmfw==",
|
||||
"version": "8.7.5",
|
||||
"resolved": "https://registry.npmjs.org/@ionic/react/-/react-8.7.5.tgz",
|
||||
"integrity": "sha512-ID1in1YhmjlpLUF1aMv9zSEVc+ZiXs1fNWKJLK4U02LRQoNxmKagwYLxItAuls0KqduCErcqfC5pOcBJDtMl4Q==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@ionic/core": "8.7.6",
|
||||
"@ionic/core": "8.7.5",
|
||||
"ionicons": "^8.0.13",
|
||||
"tslib": "*"
|
||||
},
|
||||
@@ -669,9 +669,9 @@
|
||||
]
|
||||
},
|
||||
"node_modules/@stencil/core": {
|
||||
"version": "4.38.0",
|
||||
"resolved": "https://registry.npmjs.org/@stencil/core/-/core-4.38.0.tgz",
|
||||
"integrity": "sha512-oC3QFKO0X1yXVvETgc8OLY525MNKhn9vISBrbtKnGoPlokJ6rI8Vk1RK22TevnNrHLI4SExNLbcDnqilKR35JQ==",
|
||||
"version": "4.36.2",
|
||||
"resolved": "https://registry.npmjs.org/@stencil/core/-/core-4.36.2.tgz",
|
||||
"integrity": "sha512-PRFSpxNzX9Oi0Wfh02asztN9Sgev/MacfZwmd+VVyE6ZxW+a/kEpAYZhzGAmE+/aKVOGYuug7R9SulanYGxiDQ==",
|
||||
"license": "MIT",
|
||||
"bin": {
|
||||
"stencil": "bin/stencil"
|
||||
@@ -4175,11 +4175,11 @@
|
||||
"dev": true
|
||||
},
|
||||
"@ionic/core": {
|
||||
"version": "8.7.6",
|
||||
"resolved": "https://registry.npmjs.org/@ionic/core/-/core-8.7.6.tgz",
|
||||
"integrity": "sha512-ufV64Pl0BYSoNla+DaTRXTS3hX6MQZZJPhAR3fJQ4N5Fg/vwMcHADQffstKZeoPqk6mbJoLqoTBjcWvaLRdO0g==",
|
||||
"version": "8.7.5",
|
||||
"resolved": "https://registry.npmjs.org/@ionic/core/-/core-8.7.5.tgz",
|
||||
"integrity": "sha512-Uk1qdGPoLHaVhd2FnYSAvRehd3VwwcPIfXaR51qiC7C2L5VhD27VyLSgDetc15G4U+VAIFjgUSR/pKdLFEuMPA==",
|
||||
"requires": {
|
||||
"@stencil/core": "4.38.0",
|
||||
"@stencil/core": "4.36.2",
|
||||
"ionicons": "^8.0.13",
|
||||
"tslib": "^2.1.0"
|
||||
}
|
||||
@@ -4281,11 +4281,11 @@
|
||||
"requires": {}
|
||||
},
|
||||
"@ionic/react": {
|
||||
"version": "8.7.6",
|
||||
"resolved": "https://registry.npmjs.org/@ionic/react/-/react-8.7.6.tgz",
|
||||
"integrity": "sha512-7uoqcd5AOovtN7MJd5v9xeQFKF4og8W++bvDgka6TQcMTE/8mmzpFJUpOSvhFeOITMaqBHtkCNMvQSCa7vsmfw==",
|
||||
"version": "8.7.5",
|
||||
"resolved": "https://registry.npmjs.org/@ionic/react/-/react-8.7.5.tgz",
|
||||
"integrity": "sha512-ID1in1YhmjlpLUF1aMv9zSEVc+ZiXs1fNWKJLK4U02LRQoNxmKagwYLxItAuls0KqduCErcqfC5pOcBJDtMl4Q==",
|
||||
"requires": {
|
||||
"@ionic/core": "8.7.6",
|
||||
"@ionic/core": "8.7.5",
|
||||
"ionicons": "^8.0.13",
|
||||
"tslib": "*"
|
||||
}
|
||||
@@ -4422,9 +4422,9 @@
|
||||
"optional": true
|
||||
},
|
||||
"@stencil/core": {
|
||||
"version": "4.38.0",
|
||||
"resolved": "https://registry.npmjs.org/@stencil/core/-/core-4.38.0.tgz",
|
||||
"integrity": "sha512-oC3QFKO0X1yXVvETgc8OLY525MNKhn9vISBrbtKnGoPlokJ6rI8Vk1RK22TevnNrHLI4SExNLbcDnqilKR35JQ==",
|
||||
"version": "4.36.2",
|
||||
"resolved": "https://registry.npmjs.org/@stencil/core/-/core-4.36.2.tgz",
|
||||
"integrity": "sha512-PRFSpxNzX9Oi0Wfh02asztN9Sgev/MacfZwmd+VVyE6ZxW+a/kEpAYZhzGAmE+/aKVOGYuug7R9SulanYGxiDQ==",
|
||||
"requires": {
|
||||
"@rollup/rollup-darwin-arm64": "4.34.9",
|
||||
"@rollup/rollup-darwin-x64": "4.34.9",
|
||||
@@ -6844,4 +6844,4 @@
|
||||
"dev": true
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@ionic/react-router",
|
||||
"version": "8.7.7",
|
||||
"version": "8.7.5",
|
||||
"description": "React Router wrapper for @ionic/react",
|
||||
"keywords": [
|
||||
"ionic",
|
||||
@@ -36,7 +36,7 @@
|
||||
"dist/"
|
||||
],
|
||||
"dependencies": {
|
||||
"@ionic/react": "^8.7.7",
|
||||
"@ionic/react": "^8.7.5",
|
||||
"tslib": "*"
|
||||
},
|
||||
"peerDependencies": {
|
||||
|
||||
@@ -3,22 +3,6 @@
|
||||
All notable changes to this project will be documented in this file.
|
||||
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
|
||||
|
||||
## [8.7.7](https://github.com/ionic-team/ionic-framework/compare/v8.7.6...v8.7.7) (2025-10-15)
|
||||
|
||||
**Note:** Version bump only for package @ionic/react
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
## [8.7.6](https://github.com/ionic-team/ionic-framework/compare/v8.7.5...v8.7.6) (2025-10-08)
|
||||
|
||||
**Note:** Version bump only for package @ionic/react
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
## [8.7.5](https://github.com/ionic-team/ionic-framework/compare/v8.7.4...v8.7.5) (2025-09-24)
|
||||
|
||||
|
||||
|
||||
22
packages/react/package-lock.json
generated
22
packages/react/package-lock.json
generated
@@ -1,15 +1,15 @@
|
||||
{
|
||||
"name": "@ionic/react",
|
||||
"version": "8.7.7",
|
||||
"version": "8.7.5",
|
||||
"lockfileVersion": 3,
|
||||
"requires": true,
|
||||
"packages": {
|
||||
"": {
|
||||
"name": "@ionic/react",
|
||||
"version": "8.7.7",
|
||||
"version": "8.7.5",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@ionic/core": "^8.7.7",
|
||||
"@ionic/core": "^8.7.5",
|
||||
"ionicons": "^8.0.13",
|
||||
"tslib": "*"
|
||||
},
|
||||
@@ -736,12 +736,12 @@
|
||||
"dev": true
|
||||
},
|
||||
"node_modules/@ionic/core": {
|
||||
"version": "8.7.6",
|
||||
"resolved": "https://registry.npmjs.org/@ionic/core/-/core-8.7.6.tgz",
|
||||
"integrity": "sha512-ufV64Pl0BYSoNla+DaTRXTS3hX6MQZZJPhAR3fJQ4N5Fg/vwMcHADQffstKZeoPqk6mbJoLqoTBjcWvaLRdO0g==",
|
||||
"version": "8.7.5",
|
||||
"resolved": "https://registry.npmjs.org/@ionic/core/-/core-8.7.5.tgz",
|
||||
"integrity": "sha512-Uk1qdGPoLHaVhd2FnYSAvRehd3VwwcPIfXaR51qiC7C2L5VhD27VyLSgDetc15G4U+VAIFjgUSR/pKdLFEuMPA==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@stencil/core": "4.38.0",
|
||||
"@stencil/core": "4.36.2",
|
||||
"ionicons": "^8.0.13",
|
||||
"tslib": "^2.1.0"
|
||||
}
|
||||
@@ -1726,9 +1726,9 @@
|
||||
}
|
||||
},
|
||||
"node_modules/@stencil/core": {
|
||||
"version": "4.38.0",
|
||||
"resolved": "https://registry.npmjs.org/@stencil/core/-/core-4.38.0.tgz",
|
||||
"integrity": "sha512-oC3QFKO0X1yXVvETgc8OLY525MNKhn9vISBrbtKnGoPlokJ6rI8Vk1RK22TevnNrHLI4SExNLbcDnqilKR35JQ==",
|
||||
"version": "4.36.2",
|
||||
"resolved": "https://registry.npmjs.org/@stencil/core/-/core-4.36.2.tgz",
|
||||
"integrity": "sha512-PRFSpxNzX9Oi0Wfh02asztN9Sgev/MacfZwmd+VVyE6ZxW+a/kEpAYZhzGAmE+/aKVOGYuug7R9SulanYGxiDQ==",
|
||||
"license": "MIT",
|
||||
"bin": {
|
||||
"stencil": "bin/stencil"
|
||||
@@ -11913,4 +11913,4 @@
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@ionic/react",
|
||||
"version": "8.7.7",
|
||||
"version": "8.7.5",
|
||||
"description": "React specific wrapper for @ionic/core",
|
||||
"keywords": [
|
||||
"ionic",
|
||||
@@ -40,7 +40,7 @@
|
||||
"css/"
|
||||
],
|
||||
"dependencies": {
|
||||
"@ionic/core": "^8.7.7",
|
||||
"@ionic/core": "^8.7.5",
|
||||
"ionicons": "^8.0.13",
|
||||
"tslib": "*"
|
||||
},
|
||||
|
||||
@@ -3,22 +3,6 @@
|
||||
All notable changes to this project will be documented in this file.
|
||||
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
|
||||
|
||||
## [8.7.7](https://github.com/ionic-team/ionic-framework/compare/v8.7.6...v8.7.7) (2025-10-15)
|
||||
|
||||
**Note:** Version bump only for package @ionic/vue-router
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
## [8.7.6](https://github.com/ionic-team/ionic-framework/compare/v8.7.5...v8.7.6) (2025-10-08)
|
||||
|
||||
**Note:** Version bump only for package @ionic/vue-router
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
## [8.7.5](https://github.com/ionic-team/ionic-framework/compare/v8.7.4...v8.7.5) (2025-09-24)
|
||||
|
||||
**Note:** Version bump only for package @ionic/vue-router
|
||||
|
||||
52
packages/vue-router/package-lock.json
generated
52
packages/vue-router/package-lock.json
generated
@@ -1,15 +1,15 @@
|
||||
{
|
||||
"name": "@ionic/vue-router",
|
||||
"version": "8.7.7",
|
||||
"version": "8.7.5",
|
||||
"lockfileVersion": 2,
|
||||
"requires": true,
|
||||
"packages": {
|
||||
"": {
|
||||
"name": "@ionic/vue-router",
|
||||
"version": "8.7.7",
|
||||
"version": "8.7.5",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@ionic/vue": "^8.7.7"
|
||||
"@ionic/vue": "^8.7.5"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@ionic/eslint-config": "^0.3.0",
|
||||
@@ -673,12 +673,12 @@
|
||||
"dev": true
|
||||
},
|
||||
"node_modules/@ionic/core": {
|
||||
"version": "8.7.6",
|
||||
"resolved": "https://registry.npmjs.org/@ionic/core/-/core-8.7.6.tgz",
|
||||
"integrity": "sha512-ufV64Pl0BYSoNla+DaTRXTS3hX6MQZZJPhAR3fJQ4N5Fg/vwMcHADQffstKZeoPqk6mbJoLqoTBjcWvaLRdO0g==",
|
||||
"version": "8.7.5",
|
||||
"resolved": "https://registry.npmjs.org/@ionic/core/-/core-8.7.5.tgz",
|
||||
"integrity": "sha512-Uk1qdGPoLHaVhd2FnYSAvRehd3VwwcPIfXaR51qiC7C2L5VhD27VyLSgDetc15G4U+VAIFjgUSR/pKdLFEuMPA==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@stencil/core": "4.38.0",
|
||||
"@stencil/core": "4.36.2",
|
||||
"ionicons": "^8.0.13",
|
||||
"tslib": "^2.1.0"
|
||||
}
|
||||
@@ -865,12 +865,12 @@
|
||||
}
|
||||
},
|
||||
"node_modules/@ionic/vue": {
|
||||
"version": "8.7.6",
|
||||
"resolved": "https://registry.npmjs.org/@ionic/vue/-/vue-8.7.6.tgz",
|
||||
"integrity": "sha512-gK5x5Y0ZpZAW12gjvyBO9oUfwDZxMS7y0xcO0P9qzo++h3ZLcFcSGjHs8D4isUY/mF6mRagt1Y/5b0xDhgUBBw==",
|
||||
"version": "8.7.5",
|
||||
"resolved": "https://registry.npmjs.org/@ionic/vue/-/vue-8.7.5.tgz",
|
||||
"integrity": "sha512-wx7o+ABDDTWLM47CIjxueoZtKbvMQ9AolqGY4/2JvAJds/JlSs4kOEes/AzQ/1dREEp+4sOapmTtJnyauErY3A==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@ionic/core": "8.7.6",
|
||||
"@ionic/core": "8.7.5",
|
||||
"@stencil/vue-output-target": "0.10.7",
|
||||
"ionicons": "^8.0.13"
|
||||
}
|
||||
@@ -1523,9 +1523,9 @@
|
||||
}
|
||||
},
|
||||
"node_modules/@stencil/core": {
|
||||
"version": "4.38.0",
|
||||
"resolved": "https://registry.npmjs.org/@stencil/core/-/core-4.38.0.tgz",
|
||||
"integrity": "sha512-oC3QFKO0X1yXVvETgc8OLY525MNKhn9vISBrbtKnGoPlokJ6rI8Vk1RK22TevnNrHLI4SExNLbcDnqilKR35JQ==",
|
||||
"version": "4.36.2",
|
||||
"resolved": "https://registry.npmjs.org/@stencil/core/-/core-4.36.2.tgz",
|
||||
"integrity": "sha512-PRFSpxNzX9Oi0Wfh02asztN9Sgev/MacfZwmd+VVyE6ZxW+a/kEpAYZhzGAmE+/aKVOGYuug7R9SulanYGxiDQ==",
|
||||
"license": "MIT",
|
||||
"bin": {
|
||||
"stencil": "bin/stencil"
|
||||
@@ -8041,11 +8041,11 @@
|
||||
"dev": true
|
||||
},
|
||||
"@ionic/core": {
|
||||
"version": "8.7.6",
|
||||
"resolved": "https://registry.npmjs.org/@ionic/core/-/core-8.7.6.tgz",
|
||||
"integrity": "sha512-ufV64Pl0BYSoNla+DaTRXTS3hX6MQZZJPhAR3fJQ4N5Fg/vwMcHADQffstKZeoPqk6mbJoLqoTBjcWvaLRdO0g==",
|
||||
"version": "8.7.5",
|
||||
"resolved": "https://registry.npmjs.org/@ionic/core/-/core-8.7.5.tgz",
|
||||
"integrity": "sha512-Uk1qdGPoLHaVhd2FnYSAvRehd3VwwcPIfXaR51qiC7C2L5VhD27VyLSgDetc15G4U+VAIFjgUSR/pKdLFEuMPA==",
|
||||
"requires": {
|
||||
"@stencil/core": "4.38.0",
|
||||
"@stencil/core": "4.36.2",
|
||||
"ionicons": "^8.0.13",
|
||||
"tslib": "^2.1.0"
|
||||
}
|
||||
@@ -8156,11 +8156,11 @@
|
||||
"requires": {}
|
||||
},
|
||||
"@ionic/vue": {
|
||||
"version": "8.7.6",
|
||||
"resolved": "https://registry.npmjs.org/@ionic/vue/-/vue-8.7.6.tgz",
|
||||
"integrity": "sha512-gK5x5Y0ZpZAW12gjvyBO9oUfwDZxMS7y0xcO0P9qzo++h3ZLcFcSGjHs8D4isUY/mF6mRagt1Y/5b0xDhgUBBw==",
|
||||
"version": "8.7.5",
|
||||
"resolved": "https://registry.npmjs.org/@ionic/vue/-/vue-8.7.5.tgz",
|
||||
"integrity": "sha512-wx7o+ABDDTWLM47CIjxueoZtKbvMQ9AolqGY4/2JvAJds/JlSs4kOEes/AzQ/1dREEp+4sOapmTtJnyauErY3A==",
|
||||
"requires": {
|
||||
"@ionic/core": "8.7.6",
|
||||
"@ionic/core": "8.7.5",
|
||||
"@stencil/vue-output-target": "0.10.7",
|
||||
"ionicons": "^8.0.13"
|
||||
}
|
||||
@@ -8624,9 +8624,9 @@
|
||||
}
|
||||
},
|
||||
"@stencil/core": {
|
||||
"version": "4.38.0",
|
||||
"resolved": "https://registry.npmjs.org/@stencil/core/-/core-4.38.0.tgz",
|
||||
"integrity": "sha512-oC3QFKO0X1yXVvETgc8OLY525MNKhn9vISBrbtKnGoPlokJ6rI8Vk1RK22TevnNrHLI4SExNLbcDnqilKR35JQ==",
|
||||
"version": "4.36.2",
|
||||
"resolved": "https://registry.npmjs.org/@stencil/core/-/core-4.36.2.tgz",
|
||||
"integrity": "sha512-PRFSpxNzX9Oi0Wfh02asztN9Sgev/MacfZwmd+VVyE6ZxW+a/kEpAYZhzGAmE+/aKVOGYuug7R9SulanYGxiDQ==",
|
||||
"requires": {
|
||||
"@rollup/rollup-darwin-arm64": "4.34.9",
|
||||
"@rollup/rollup-darwin-x64": "4.34.9",
|
||||
@@ -12991,4 +12991,4 @@
|
||||
"dev": true
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@ionic/vue-router",
|
||||
"version": "8.7.7",
|
||||
"version": "8.7.5",
|
||||
"description": "Vue Router integration for @ionic/vue",
|
||||
"scripts": {
|
||||
"test.spec": "jest",
|
||||
@@ -44,7 +44,7 @@
|
||||
},
|
||||
"homepage": "https://github.com/ionic-team/ionic-framework#readme",
|
||||
"dependencies": {
|
||||
"@ionic/vue": "^8.7.7"
|
||||
"@ionic/vue": "^8.7.5"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@ionic/eslint-config": "^0.3.0",
|
||||
|
||||
@@ -3,22 +3,6 @@
|
||||
All notable changes to this project will be documented in this file.
|
||||
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
|
||||
|
||||
## [8.7.7](https://github.com/ionic-team/ionic-framework/compare/v8.7.6...v8.7.7) (2025-10-15)
|
||||
|
||||
**Note:** Version bump only for package @ionic/vue
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
## [8.7.6](https://github.com/ionic-team/ionic-framework/compare/v8.7.5...v8.7.6) (2025-10-08)
|
||||
|
||||
**Note:** Version bump only for package @ionic/vue
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
## [8.7.5](https://github.com/ionic-team/ionic-framework/compare/v8.7.4...v8.7.5) (2025-09-24)
|
||||
|
||||
|
||||
|
||||
22
packages/vue/package-lock.json
generated
22
packages/vue/package-lock.json
generated
@@ -1,15 +1,15 @@
|
||||
{
|
||||
"name": "@ionic/vue",
|
||||
"version": "8.7.7",
|
||||
"version": "8.7.5",
|
||||
"lockfileVersion": 3,
|
||||
"requires": true,
|
||||
"packages": {
|
||||
"": {
|
||||
"name": "@ionic/vue",
|
||||
"version": "8.7.7",
|
||||
"version": "8.7.5",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@ionic/core": "^8.7.7",
|
||||
"@ionic/core": "^8.7.5",
|
||||
"@stencil/vue-output-target": "0.10.7",
|
||||
"ionicons": "^8.0.13"
|
||||
},
|
||||
@@ -222,12 +222,12 @@
|
||||
"dev": true
|
||||
},
|
||||
"node_modules/@ionic/core": {
|
||||
"version": "8.7.6",
|
||||
"resolved": "https://registry.npmjs.org/@ionic/core/-/core-8.7.6.tgz",
|
||||
"integrity": "sha512-ufV64Pl0BYSoNla+DaTRXTS3hX6MQZZJPhAR3fJQ4N5Fg/vwMcHADQffstKZeoPqk6mbJoLqoTBjcWvaLRdO0g==",
|
||||
"version": "8.7.5",
|
||||
"resolved": "https://registry.npmjs.org/@ionic/core/-/core-8.7.5.tgz",
|
||||
"integrity": "sha512-Uk1qdGPoLHaVhd2FnYSAvRehd3VwwcPIfXaR51qiC7C2L5VhD27VyLSgDetc15G4U+VAIFjgUSR/pKdLFEuMPA==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@stencil/core": "4.38.0",
|
||||
"@stencil/core": "4.36.2",
|
||||
"ionicons": "^8.0.13",
|
||||
"tslib": "^2.1.0"
|
||||
}
|
||||
@@ -674,9 +674,9 @@
|
||||
]
|
||||
},
|
||||
"node_modules/@stencil/core": {
|
||||
"version": "4.38.0",
|
||||
"resolved": "https://registry.npmjs.org/@stencil/core/-/core-4.38.0.tgz",
|
||||
"integrity": "sha512-oC3QFKO0X1yXVvETgc8OLY525MNKhn9vISBrbtKnGoPlokJ6rI8Vk1RK22TevnNrHLI4SExNLbcDnqilKR35JQ==",
|
||||
"version": "4.36.2",
|
||||
"resolved": "https://registry.npmjs.org/@stencil/core/-/core-4.36.2.tgz",
|
||||
"integrity": "sha512-PRFSpxNzX9Oi0Wfh02asztN9Sgev/MacfZwmd+VVyE6ZxW+a/kEpAYZhzGAmE+/aKVOGYuug7R9SulanYGxiDQ==",
|
||||
"license": "MIT",
|
||||
"bin": {
|
||||
"stencil": "bin/stencil"
|
||||
@@ -4019,4 +4019,4 @@
|
||||
"dev": true
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@ionic/vue",
|
||||
"version": "8.7.7",
|
||||
"version": "8.7.5",
|
||||
"description": "Vue specific wrapper for @ionic/core",
|
||||
"scripts": {
|
||||
"eslint": "eslint src",
|
||||
@@ -68,7 +68,7 @@
|
||||
"vue-router": "^4.0.16"
|
||||
},
|
||||
"dependencies": {
|
||||
"@ionic/core": "^8.7.7",
|
||||
"@ionic/core": "^8.7.5",
|
||||
"@stencil/vue-output-target": "0.10.7",
|
||||
"ionicons": "^8.0.13"
|
||||
},
|
||||
|
||||
@@ -8,19 +8,12 @@
|
||||
groupName: "Download + Upload Artifacts"
|
||||
},
|
||||
{
|
||||
matchPackagePatterns: ["@stencil/core", "@stencil/sass"],
|
||||
matchPackagePatterns: ["@stencil/core", "@stencil/angular-output-target", "@stencil/react-output-target", "@stencil/sass", "@stencil/vue-output-target"],
|
||||
groupName: "stencil",
|
||||
matchFileNames: [
|
||||
"core/package.json"
|
||||
]
|
||||
},
|
||||
{
|
||||
matchPackagePatterns: ["@stencil/angular-output-target", "@stencil/react-output-target", "@stencil/vue-output-target"],
|
||||
groupName: "stencil-output-targets",
|
||||
matchFileNames: [
|
||||
"core/package.json"
|
||||
]
|
||||
},
|
||||
// TODO(ROU-11172): unpin React output target version
|
||||
{
|
||||
matchPackageNames: ["@stencil/react-output-target"],
|
||||
|
||||
Reference in New Issue
Block a user