mirror of
https://github.com/ionic-team/ionic-framework.git
synced 2026-03-13 10:22:08 +08:00
Compare commits
114 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
a63474a621 | ||
|
|
f98151c5d1 | ||
|
|
655631ddf0 | ||
|
|
11332e446c | ||
|
|
fe9bec29d5 | ||
|
|
b1ffdadbc3 | ||
|
|
077b915ad5 | ||
|
|
2c97712601 | ||
|
|
f112ad4490 | ||
|
|
25eb8cdf98 | ||
|
|
7010fe97a7 | ||
|
|
a26275378f | ||
|
|
3ca04197a4 | ||
|
|
aa4ba890e9 | ||
|
|
bb126a02e8 | ||
|
|
598aaed4bf | ||
|
|
3c1be89112 | ||
|
|
00269941ca | ||
|
|
e483034f3a | ||
|
|
53d64c1eb8 | ||
|
|
ae1325cee6 | ||
|
|
8108edd876 | ||
|
|
874e791377 | ||
|
|
b104690192 | ||
|
|
57bc299dea | ||
|
|
5f95f45e58 | ||
|
|
6f85e010c8 | ||
|
|
bd96a81ff8 | ||
|
|
73a1daf0aa | ||
|
|
1e13429731 | ||
|
|
1ed9f07060 | ||
|
|
47829690b5 | ||
|
|
8888e2bafd | ||
|
|
e512fc1ecd | ||
|
|
a12d146c3e | ||
|
|
a0229bc7b2 | ||
|
|
11fda41420 | ||
|
|
33f0bcd437 | ||
|
|
3c442228ff | ||
|
|
50b88b24c2 | ||
|
|
9317f6eb41 | ||
|
|
9932e26a2e | ||
|
|
02409f2abf | ||
|
|
864212b0f2 | ||
|
|
34b150e5e7 | ||
|
|
e4c0023df2 | ||
|
|
f9415ef8a6 | ||
|
|
e0c4ad30be | ||
|
|
621f4faa1a | ||
|
|
6b18a89ac2 | ||
|
|
067e621bbc | ||
|
|
f83768cafe | ||
|
|
2d6e45e8d1 | ||
|
|
22b7413f51 | ||
|
|
4a64e97a3e | ||
|
|
8a941fd24c | ||
|
|
fbe648406b | ||
|
|
4edb5e2fed | ||
|
|
792864f8ab | ||
|
|
f2a05bed1e | ||
|
|
caf0917623 | ||
|
|
fb260a9e09 | ||
|
|
80edb603c2 | ||
|
|
f70ed79f47 | ||
|
|
ae0a1a3deb | ||
|
|
d8a2db73e2 | ||
|
|
86ece8f8b5 | ||
|
|
3016b79717 | ||
|
|
773bbcb211 | ||
|
|
3134e0afcd | ||
|
|
6d94a27fb9 | ||
|
|
d2ca304c12 | ||
|
|
e35386a52d | ||
|
|
d10d9f9f74 | ||
|
|
c940bd18d2 | ||
|
|
174b7de741 | ||
|
|
3cebcb0883 | ||
|
|
7315e0157b | ||
|
|
4b56744d7f | ||
|
|
c08345df2e | ||
|
|
fa069424b2 | ||
|
|
3b803ebe02 | ||
|
|
9021e7cc4b | ||
|
|
39315bc857 | ||
|
|
a15cace139 | ||
|
|
635ac195d9 | ||
|
|
34aad178d0 | ||
|
|
cffeb4d9bd | ||
|
|
69be51dc54 | ||
|
|
f3d6abbc1b | ||
|
|
0b5c470b98 | ||
|
|
d5980354fa | ||
|
|
508f1a46fb | ||
|
|
3130dd3fd8 | ||
|
|
57156526ff | ||
|
|
40fadcd9bf | ||
|
|
494a4a08fe | ||
|
|
b3847ff723 | ||
|
|
a2a4cff3d0 | ||
|
|
68c0e7136d | ||
|
|
87b4a42c96 | ||
|
|
e27b5b6ae3 | ||
|
|
10be62a71d | ||
|
|
60bedb5599 | ||
|
|
f008628851 | ||
|
|
82cfa55653 | ||
|
|
ae96563fb3 | ||
|
|
d527414e10 | ||
|
|
6cc6f4c44b | ||
|
|
62ed9712e1 | ||
|
|
e3aaa9513e | ||
|
|
e4bbaf8a7f | ||
|
|
857550a0c4 | ||
|
|
fee4e82f0e |
59
.github/ISSUE_TEMPLATE/bug_report.md
vendored
59
.github/ISSUE_TEMPLATE/bug_report.md
vendored
@@ -1,59 +0,0 @@
|
||||
---
|
||||
name: Bug Report
|
||||
about: Create a report to help us improve
|
||||
title: 'bug: '
|
||||
labels: ''
|
||||
assignees: ''
|
||||
---
|
||||
|
||||
<!-- Before submitting an issue, please consult our docs (https://ionicframework.com/docs/). -->
|
||||
|
||||
<!-- Please make sure you are posting an issue pertaining to the Ionic Framework. If you are having an issue with the Ionic Appflow services (Ionic View, Ionic Deploy, etc.) please consult the Ionic Appflow support portal (https://ionic.zendesk.com/hc/en-us) -->
|
||||
|
||||
<!-- Please do not submit support requests or "How to" questions here. Instead, please use the Ionic Forum: https://forum.ionicframework.com/ -->
|
||||
|
||||
<!-- ISSUES MISSING IMPORTANT INFORMATION MAY BE CLOSED WITHOUT INVESTIGATION. -->
|
||||
|
||||
# Bug Report
|
||||
|
||||
**Ionic version:**
|
||||
<!-- (For Ionic 1.x issues, please use https://github.com/ionic-team/ionic-v1) -->
|
||||
<!-- (For Ionic 2.x & 3.x issues, please use https://github.com/ionic-team/ionic-v3) -->
|
||||
[ ] **4.x**
|
||||
[x] **5.x**
|
||||
|
||||
**Current behavior:**
|
||||
<!-- Describe how the bug manifests. -->
|
||||
|
||||
**Expected behavior:**
|
||||
<!-- Describe what the behavior would be without the bug. -->
|
||||
|
||||
**Steps to reproduce:**
|
||||
<!-- Please explain the steps required to duplicate the issue, especially if you are able to provide a sample application. -->
|
||||
|
||||
**Related code:**
|
||||
|
||||
<!-- If you are able to illustrate the bug or feature request with an example, please provide a sample application via one of the following means:
|
||||
|
||||
A sample application via GitHub
|
||||
|
||||
StackBlitz (https://stackblitz.com)
|
||||
Ionic Angular StackBlitz: https://stackblitz.com/edit/ionic-v4-angular-tabs
|
||||
|
||||
Plunker (http://plnkr.co/edit/cpeRJs?p=preview)
|
||||
|
||||
-->
|
||||
|
||||
```
|
||||
insert short code snippets here
|
||||
```
|
||||
|
||||
**Other information:**
|
||||
<!-- List any other information that is relevant to your issue. Stack traces, related issues, suggestions on how to fix, Stack Overflow links, forum links, etc. -->
|
||||
|
||||
**Ionic info:**
|
||||
<!-- (run `ionic info` from a terminal/cmd prompt and paste output below): -->
|
||||
|
||||
```
|
||||
insert the output from ionic info here
|
||||
```
|
||||
56
.github/ISSUE_TEMPLATE/bug_report.yml
vendored
Normal file
56
.github/ISSUE_TEMPLATE/bug_report.yml
vendored
Normal file
@@ -0,0 +1,56 @@
|
||||
name: 🐛 Bug Report
|
||||
description: Create a report to help us improve Ionic Framework
|
||||
title: 'bug: '
|
||||
body:
|
||||
- type: checkboxes
|
||||
attributes:
|
||||
label: Prerequisites
|
||||
description: Please ensure you have completed all of the following.
|
||||
options:
|
||||
- label: I have read the [Contributing Guidelines](https://github.com/ionic-team/ionic-framework/blob/main/.github/CONTRIBUTING.md#creating-an-issue).
|
||||
required: true
|
||||
- label: I agree to follow the [Code of Conduct](https://ionicframework.com/code-of-conduct).
|
||||
required: true
|
||||
- label: I have searched for [existing issues](https://github.com/ionic-team/ionic-framework/issues) that already report this problem, without success.
|
||||
required: true
|
||||
- type: checkboxes
|
||||
attributes:
|
||||
label: Ionic Framework Version
|
||||
description: Please select which versions of Ionic Framework this issue impacts. For Ionic Framework 1.x issues, please use https://github.com/ionic-team/ionic-v1. For Ionic Framework 2.x and 3.x issues, please use https://github.com/ionic-team/ionic-v3.
|
||||
options:
|
||||
- label: v4.x
|
||||
- label: v5.x
|
||||
- label: v6.x
|
||||
- type: textarea
|
||||
attributes:
|
||||
label: Current Behavior
|
||||
description: A clear description of what the bug is and how it manifests.
|
||||
validations:
|
||||
required: true
|
||||
- type: textarea
|
||||
attributes:
|
||||
label: Expected Behavior
|
||||
description: A clear description of what you expected to happen.
|
||||
validations:
|
||||
required: true
|
||||
- type: textarea
|
||||
attributes:
|
||||
label: Steps to Reproduce
|
||||
description: Please explain the steps required to duplicate this issue.
|
||||
validations:
|
||||
required: true
|
||||
- type: input
|
||||
attributes:
|
||||
label: Code Reproduction URL
|
||||
description: Please reproduce this issue in a blank Ionic Framework starter application and provide a link to the repo. Try out our [Getting Started Wizard](https://ionicframework.com/start#basics) to quickly spin up an Ionic Framework starter app. This is the best way to ensure this issue is triaged quickly. Issues without a code reproduction may be closed if the Ionic Team cannot reproduce the issue you are reporting.
|
||||
placeholder: https://github.com/...
|
||||
- type: textarea
|
||||
attributes:
|
||||
label: Ionic Info
|
||||
description: Please run `ionic info` from within your Ionic Framework project directory and paste the output below.
|
||||
validations:
|
||||
requred: true
|
||||
- type: textarea
|
||||
attributes:
|
||||
label: Additional Information
|
||||
description: List any other information that is relevant to your issue. Stack traces, related issues, suggestions on how to fix, Stack Overflow links, forum links, etc.
|
||||
11
.github/ISSUE_TEMPLATE/cli.md
vendored
11
.github/ISSUE_TEMPLATE/cli.md
vendored
@@ -1,11 +0,0 @@
|
||||
---
|
||||
name: CLI
|
||||
about: Suggest an improvement for the CLI
|
||||
title: ''
|
||||
labels: 'ionitron: cli'
|
||||
assignees: ''
|
||||
---
|
||||
|
||||
# CLI
|
||||
|
||||
Please do not submit bug reports or feature requests related to the Ionic CLI. Instead, please submit an issue to the [Ionic CLI Repository](https://github.com/ionic-team/ionic-cli/issues/new/choose).
|
||||
10
.github/ISSUE_TEMPLATE/config.yml
vendored
Normal file
10
.github/ISSUE_TEMPLATE/config.yml
vendored
Normal file
@@ -0,0 +1,10 @@
|
||||
contact_links:
|
||||
- name: 📚 Documentation
|
||||
url: https://github.com/ionic-team/ionic-docs/issues/new/choose
|
||||
about: This issue tracker is not for documentation issues. Please file documentation issues on the Ionic Docs repo.
|
||||
- name: 💻 CLI
|
||||
url: https://github.com/ionic-team/ionic-cli/issues/new/choose
|
||||
about: This issue tracker is not for CLI issues. Please file CLI issues on the Ionic CLI repo.
|
||||
- name: 🤔 Support Question
|
||||
url: https://forum.ionicframework.com/
|
||||
about: This issue tracker is not for support questions. Please post your question on the Ionic Forums.
|
||||
11
.github/ISSUE_TEMPLATE/documentation.md
vendored
11
.github/ISSUE_TEMPLATE/documentation.md
vendored
@@ -1,11 +0,0 @@
|
||||
---
|
||||
name: Documentation
|
||||
about: Suggest an improvement for the documentation of this project
|
||||
title: ''
|
||||
labels: 'ionitron: docs'
|
||||
assignees: ''
|
||||
---
|
||||
|
||||
# Documentation
|
||||
|
||||
Please do not submit issues on how to improve or fix the documentation. Instead, please submit an issue to the [Ionic Docs Repository](https://github.com/ionic-team/ionic-docs/issues/new/choose).
|
||||
37
.github/ISSUE_TEMPLATE/feature_request.md
vendored
37
.github/ISSUE_TEMPLATE/feature_request.md
vendored
@@ -1,37 +0,0 @@
|
||||
---
|
||||
name: Feature Request
|
||||
about: Suggest an idea for this project
|
||||
title: 'feat: '
|
||||
labels: ''
|
||||
assignees: ''
|
||||
---
|
||||
|
||||
<!-- Before submitting an issue, please consult our docs (https://ionicframework.com/docs/). -->
|
||||
|
||||
<!-- Please make sure you are posting an issue pertaining to the Ionic Framework. If you are having an issue with the Ionic Appflow services (Ionic View, Ionic Deploy, etc.) please consult the Ionic Appflow support portal (https://ionic.zendesk.com/hc/en-us) -->
|
||||
|
||||
<!-- Please do not submit support requests or "How to" questions here. Instead, please use one of these channels: https://forum.ionicframework.com/ or http://ionicworldwide.herokuapp.com/ -->
|
||||
|
||||
<!-- ISSUES MISSING IMPORTANT INFORMATION MAY BE CLOSED WITHOUT INVESTIGATION. -->
|
||||
|
||||
# Feature Request
|
||||
|
||||
**Ionic version:**
|
||||
<!-- (For Ionic 1.x issues, please use https://github.com/ionic-team/ionic-v1) -->
|
||||
<!-- (For Ionic 2.x & 3.x issues, please use https://github.com/ionic-team/ionic-v3) -->
|
||||
[x] **4.x**
|
||||
|
||||
**Describe the Feature Request**
|
||||
<!-- A clear and concise description of what the feature request is. Please include if your feature request is related to a problem. -->
|
||||
|
||||
**Describe Preferred Solution**
|
||||
<!-- A clear and concise description of what you want to happen. -->
|
||||
|
||||
**Describe Alternatives**
|
||||
<!-- A clear and concise description of any alternative solutions or features you've considered. -->
|
||||
|
||||
**Related Code**
|
||||
<!-- If you are able to illustrate the feature request with an example, please provide a sample application via an online code collaborator such as [StackBlitz](https://stackblitz.com), or [GitHub](https://github.com). -->
|
||||
|
||||
**Additional Context**
|
||||
<!-- List any other information that is relevant to your issue. Stack traces, related issues, suggestions on how to add, use case, Stack Overflow links, forum links, screenshots, OS if applicable, etc. -->
|
||||
43
.github/ISSUE_TEMPLATE/feature_request.yml
vendored
Normal file
43
.github/ISSUE_TEMPLATE/feature_request.yml
vendored
Normal file
@@ -0,0 +1,43 @@
|
||||
name: 💡 Feature Request
|
||||
description: Suggest an idea for Ionic Framework
|
||||
title: 'feat: '
|
||||
body:
|
||||
- type: checkboxes
|
||||
attributes:
|
||||
label: Prerequisites
|
||||
description: Please ensure you have completed all of the following.
|
||||
options:
|
||||
- label: I have read the [Contributing Guidelines](https://github.com/ionic-team/ionic-framework/blob/main/.github/CONTRIBUTING.md#creating-an-issue).
|
||||
required: true
|
||||
- label: I agree to follow the [Code of Conduct](https://ionicframework.com/code-of-conduct).
|
||||
required: true
|
||||
- label: I have searched for [existing issues](https://github.com/ionic-team/ionic-framework/issues) that already include this feature request, without success.
|
||||
required: true
|
||||
- type: textarea
|
||||
attributes:
|
||||
label: Describe the Feature Request
|
||||
description: A clear and concise description of what the feature does.
|
||||
validations:
|
||||
required: true
|
||||
- type: textarea
|
||||
attributes:
|
||||
label: Describe the Use Case
|
||||
description: A clear and concise use case for what problem this feature would solve.
|
||||
validations:
|
||||
required: true
|
||||
- type: textarea
|
||||
attributes:
|
||||
label: Describe Preferred Solution
|
||||
description: A clear and concise description of what you how you want this feature to be added to Ionic Framework.
|
||||
- type: textarea
|
||||
attributes:
|
||||
label: Describe Alternatives
|
||||
description: A clear and concise description of any alternative solutions or features you have considered.
|
||||
- type: textarea
|
||||
attributes:
|
||||
label: Related Code
|
||||
description: If you are able to illustrate the feature request with an example, please provide a sample Ionic Framework application. Try out our [Getting Started Wizard](https://ionicframework.com/start#basics) to quickly spin up an Ionic Framework starter app.
|
||||
- type: textarea
|
||||
attributes:
|
||||
label: Additional Information
|
||||
description: List any other information that is relevant to your issue. Stack traces, related issues, suggestions on how to implement, Stack Overflow links, forum links, etc.
|
||||
11
.github/ISSUE_TEMPLATE/support_question.md
vendored
11
.github/ISSUE_TEMPLATE/support_question.md
vendored
@@ -1,11 +0,0 @@
|
||||
---
|
||||
name: Support Question
|
||||
about: Question on how to use this project
|
||||
title: 'support: '
|
||||
labels: 'ionitron: support'
|
||||
assignees: ''
|
||||
---
|
||||
|
||||
# Support Question
|
||||
|
||||
Please do not submit support requests or "How to" questions here. Instead, please use the Ionic Forum: https://forum.ionicframework.com/
|
||||
2
.github/PROCESS.md
vendored
2
.github/PROCESS.md
vendored
@@ -60,7 +60,7 @@ If the issue is associated with Ionic Appflow the submitter should be told to us
|
||||
|
||||
### Support Questions
|
||||
|
||||
If the issue is a support question, the submitter should be redirected to our [forum](https://forum.ionicframework.com) or [slack channel](https://ionicworldwide.herokuapp.com/). The issue should be closed and locked. Use the `ionitron: support` label to accomplish this.
|
||||
If the issue is a support question, the submitter should be redirected to our [forum](https://forum.ionicframework.com). The issue should be closed and locked. Use the `ionitron: support` label to accomplish this.
|
||||
|
||||
### Incomplete Template
|
||||
|
||||
|
||||
149
CHANGELOG.md
149
CHANGELOG.md
@@ -1,3 +1,150 @@
|
||||
## [5.8.3](https://github.com/ionic-team/ionic/compare/v5.8.2...v5.8.3) (2021-10-07)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* **react:** overlay hooks dismiss method now works ([#24038](https://github.com/ionic-team/ionic/issues/24038)) ([655631d](https://github.com/ionic-team/ionic/commit/655631ddf059ce58066d5384d0ae186d7abc09a9)), closes [#24030](https://github.com/ionic-team/ionic/issues/24030)
|
||||
|
||||
|
||||
|
||||
## [5.8.2](https://github.com/ionic-team/ionic/compare/v5.8.1...v5.8.2) (2021-10-06)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* **alert:** made it easier to tell if alert is scrollable in MD mode ([#23976](https://github.com/ionic-team/ionic/issues/23976)) ([a262753](https://github.com/ionic-team/ionic/commit/a26275378f10835343ad8a6cdea50303e6c10a14))
|
||||
* **angular:** use initialize function when setting up ionic angular to avoid config errors ([#24004](https://github.com/ionic-team/ionic/issues/24004)) ([f112ad4](https://github.com/ionic-team/ionic/commit/f112ad4490dc4a179dc3feab495530e14e655e5a)), closes [#22853](https://github.com/ionic-team/ionic/issues/22853)
|
||||
* **item-sliding:** closing an item can no longer be interrupted ([#23973](https://github.com/ionic-team/ionic/issues/23973)) ([3ca0419](https://github.com/ionic-team/ionic/commit/3ca04197a4186c85d04cdf04fa9cb2689ca1bbfb)), closes [#23969](https://github.com/ionic-team/ionic/issues/23969)
|
||||
* **react:** overlay hooks memorised properly to prevent re-renders ([#24010](https://github.com/ionic-team/ionic/issues/24010)) ([2c97712](https://github.com/ionic-team/ionic/commit/2c977126012ae0231d4e4fa63cc76a528bde699b)), closes [#23741](https://github.com/ionic-team/ionic/issues/23741)
|
||||
* **select-popover:** non-scrollable popovers no longer have forced overscroll ([#23972](https://github.com/ionic-team/ionic/issues/23972)) ([aa4ba89](https://github.com/ionic-team/ionic/commit/aa4ba890e9c18e8a911c5188b3e2e85433658be9)), closes [#23971](https://github.com/ionic-team/ionic/issues/23971)
|
||||
* **status-bar:** tapping status bar correctly scrolls content to top ([#24001](https://github.com/ionic-team/ionic/issues/24001)) ([25eb8cd](https://github.com/ionic-team/ionic/commit/25eb8cdf98fe455433ca6185e89d9e1223a6d3ae)), closes [#20423](https://github.com/ionic-team/ionic/issues/20423)
|
||||
|
||||
|
||||
|
||||
## [5.8.1](https://github.com/ionic-team/ionic/compare/v5.8.0...v5.8.1) (2021-09-22)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* **angular:** select method now has correct types ([#23953](https://github.com/ionic-team/ionic/issues/23953)) ([3c1be89](https://github.com/ionic-team/ionic/commit/3c1be89112d464e77d65c875223138aaedf350cd)), closes [#23952](https://github.com/ionic-team/ionic/issues/23952)
|
||||
* **item-sliding:** item-sliding accounts for multiple ion-item elements ([#23943](https://github.com/ionic-team/ionic/issues/23943)) ([8108edd](https://github.com/ionic-team/ionic/commit/8108edd876b10834015016385dc3cd5b8f31fbfa)), closes [#19312](https://github.com/ionic-team/ionic/issues/19312)
|
||||
* **label:** only inherit color if color property is set on ion-item ([#23944](https://github.com/ionic-team/ionic/issues/23944)) ([ae1325c](https://github.com/ionic-team/ionic/commit/ae1325cee698066a71aae4e7deb953c4185c0926)), closes [#20125](https://github.com/ionic-team/ionic/issues/20125)
|
||||
|
||||
|
||||
|
||||
# [5.8.0 Calcium](https://github.com/ionic-team/ionic/compare/v5.7.0...v5.8.0) (2021-09-15)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* **angular:** nested tabs now go to correct page ([#23902](https://github.com/ionic-team/ionic/issues/23902)) ([1ed9f07](https://github.com/ionic-team/ionic/commit/1ed9f07060736d0c951910427fb12b250d7dd9af)), closes [#23897](https://github.com/ionic-team/ionic/issues/23897)
|
||||
* **header:** role attribute can now be customized ([#23888](https://github.com/ionic-team/ionic/issues/23888)) ([8888e2b](https://github.com/ionic-team/ionic/commit/8888e2bafd76b59f32b932b5d4a6a961b52894d9)), closes [#21327](https://github.com/ionic-team/ionic/issues/21327)
|
||||
* **react:** modal now mounts child component independently of other modals ([#23903](https://github.com/ionic-team/ionic/issues/23903)) ([1e13429](https://github.com/ionic-team/ionic/commit/1e13429731c1d4b5200af7f5ca20aff1f3078bfe)), closes [#23904](https://github.com/ionic-team/ionic/issues/23904)
|
||||
* **tab-bar:** safe area padding now added when slot="top" ([#23895](https://github.com/ionic-team/ionic/issues/23895)) ([4782969](https://github.com/ionic-team/ionic/commit/47829690b538903b70ad4fe77657404013270263)), closes [#23893](https://github.com/ionic-team/ionic/issues/23893)
|
||||
|
||||
|
||||
### Features
|
||||
|
||||
* **action-sheet, loading, modal, picker, popover:** pass HTML attributes to host element ([#23929](https://github.com/ionic-team/ionic/issues/23929)) ([bd96a81](https://github.com/ionic-team/ionic/commit/bd96a81ff80ffe32914804ba9b6234c0286a33db))
|
||||
* **alert, toast:** pass arbitrary HTML attributes to host element ([#23891](https://github.com/ionic-team/ionic/issues/23891)) ([73a1daf](https://github.com/ionic-team/ionic/commit/73a1daf0aaf6ffe8c7871619f2aec5f6fca1321a)), closes [#23825](https://github.com/ionic-team/ionic/issues/23825)
|
||||
|
||||
|
||||
|
||||
# [5.7.0 Potassium](https://github.com/ionic-team/ionic/compare/v5.6.14...v5.7.0) (2021-09-01)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* **alert:** AlertButton role now has correct types ([#23791](https://github.com/ionic-team/ionic/issues/23791)) ([864212b](https://github.com/ionic-team/ionic/commit/864212b0f28d33daede5f4767aa03efa37c219ae))
|
||||
* **label:** label now only takes up as much space as needed when slotted ([#23807](https://github.com/ionic-team/ionic/issues/23807)) ([9932e26](https://github.com/ionic-team/ionic/commit/9932e26a2ef28317bc85761e71a8fc4d881b8ae8)), closes [#23806](https://github.com/ionic-team/ionic/issues/23806)
|
||||
* **reorder-group:** dragging reorder item to bottom no longer gives out of bounds index ([#23797](https://github.com/ionic-team/ionic/issues/23797)) ([02409f2](https://github.com/ionic-team/ionic/commit/02409f2abfa8acbab05d0f1217b9d1c13721746e)), closes [#23796](https://github.com/ionic-team/ionic/issues/23796)
|
||||
* **vue:** router guards are now fire correctly when written in a component ([#23821](https://github.com/ionic-team/ionic/issues/23821)) ([3c44222](https://github.com/ionic-team/ionic/commit/3c442228ff746165fd823687a2661a24edd08820)), closes [#23820](https://github.com/ionic-team/ionic/issues/23820)
|
||||
|
||||
|
||||
### Features
|
||||
|
||||
* **slides:** add IonicSlides module for Swiper migration, deprecate ion-slides ([#23844](https://github.com/ionic-team/ionic/issues/23844)) ([11fda41](https://github.com/ionic-team/ionic/commit/11fda41420343886dabd97096690be38f1c40524)), closes [#23447](https://github.com/ionic-team/ionic/issues/23447)
|
||||
|
||||
### Code Refactoring
|
||||
|
||||
* **virtual-scroll:** deprecated virtual scroll in favor of solutions provided by JS frameworks ([#23854](https://github.com/ionic-team/ionic-framework/pull/23854)) ([a0229bc](https://github.com/ionic-team/ionic-framework/commit/a0229bc7b2edb061510de0f2042e7910d04accc0))
|
||||
|
||||
|
||||
|
||||
## [5.6.14](https://github.com/ionic-team/ionic/compare/v5.6.13...v5.6.14) (2021-08-18)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* **back-button:** MD ripple now accounts for --ripple-color ([#23749](https://github.com/ionic-team/ionic/issues/23749)) ([6b18a89](https://github.com/ionic-team/ionic/commit/6b18a89ac2c446082ce7faebe329157eedb13a0e)), closes [#23748](https://github.com/ionic-team/ionic/issues/23748)
|
||||
* **img:** correctly determine when to load image when scrolling quickly on slower devices ([#23704](https://github.com/ionic-team/ionic/issues/23704)) ([067e621](https://github.com/ionic-team/ionic/commit/067e621bbc3865184ae114b8c91122188c13c860)), closes [#23703](https://github.com/ionic-team/ionic/issues/23703)
|
||||
* **item-sliding:** prevent scrolling during slide gesture ([#23774](https://github.com/ionic-team/ionic/issues/23774)) ([e0c4ad3](https://github.com/ionic-team/ionic/commit/e0c4ad30bec3f2bd325d65b210ffb0437149810f)), closes [#19564](https://github.com/ionic-team/ionic/issues/19564)
|
||||
* **nav:** custom animation is now used correctly ([#23779](https://github.com/ionic-team/ionic/issues/23779)) ([f9415ef](https://github.com/ionic-team/ionic/commit/f9415ef8a689e26078bdd01623348c79f9f818ad)), closes [#23777](https://github.com/ionic-team/ionic/issues/23777)
|
||||
* **vue:** using router.go now shows correct view ([#23773](https://github.com/ionic-team/ionic/issues/23773)) ([621f4fa](https://github.com/ionic-team/ionic/commit/621f4faa1ab03137158127a56c7fe0aa1f7ae489)), closes [#22563](https://github.com/ionic-team/ionic/issues/22563)
|
||||
|
||||
|
||||
|
||||
## [5.6.13](https://github.com/ionic-team/ionic/compare/v5.6.12...v5.6.13) (2021-08-04)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* **checkbox, radio:** change event interfaces correctly use TypeScript generics for value ([#23044](https://github.com/ionic-team/ionic/issues/23044)) ([8a941fd](https://github.com/ionic-team/ionic/commit/8a941fd24cd138817a2e91c42898878a919538e4))
|
||||
* **gesture:** onEnd now correctly fires even if the event target was removed from the DOM ([#23713](https://github.com/ionic-team/ionic/issues/23713)) ([4edb5e2](https://github.com/ionic-team/ionic/commit/4edb5e2fed55c8ea21eae50821d16d351bf3aebf)), closes [#22819](https://github.com/ionic-team/ionic/issues/22819)
|
||||
* **item-sliding:** opening item while other items are open no longer requires multiple swipes ([#23683](https://github.com/ionic-team/ionic/issues/23683)) ([792864f](https://github.com/ionic-team/ionic/commit/792864f8ab21dc178c1836a8a0d4fe2d305cc142)), closes [#21579](https://github.com/ionic-team/ionic/issues/21579)
|
||||
* **react:** IonTabs no longer causes SSR to fail ([#23696](https://github.com/ionic-team/ionic/issues/23696)) ([f2a05be](https://github.com/ionic-team/ionic/commit/f2a05bed1e2a1150e8f1823bfed2d12a219d6ad0)), closes [#23651](https://github.com/ionic-team/ionic/issues/23651)
|
||||
* **vue:** improve accuracy of ion-page dev warning ([#23677](https://github.com/ionic-team/ionic/issues/23677)) ([fb260a9](https://github.com/ionic-team/ionic/commit/fb260a9e09e6f3912b30ef2ebf581d3216483fea)), closes [#23675](https://github.com/ionic-team/ionic/issues/23675)
|
||||
* **vue:** tabs warning about user-provided router outlet change is now correctly logged ([#23724](https://github.com/ionic-team/ionic/issues/23724)) ([4a64e97](https://github.com/ionic-team/ionic/commit/4a64e97a3e390e365101bbb477acad0ddc4671ff)), closes [#23719](https://github.com/ionic-team/ionic/issues/23719)
|
||||
|
||||
|
||||
|
||||
## [5.6.12](https://github.com/ionic-team/ionic/compare/v5.6.11...v5.6.12) (2021-07-21)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* **action-sheet:** header, subheader, and icon alignment better matches native ios ([#23322](https://github.com/ionic-team/ionic/issues/23322)) ([39315bc](https://github.com/ionic-team/ionic/commit/39315bc857b850347dca386776665e21c9742cad)), closes [#23317](https://github.com/ionic-team/ionic/issues/23317)
|
||||
* **button:** buttons are now disabled during page transitions ([#23589](https://github.com/ionic-team/ionic/issues/23589)) ([3b803eb](https://github.com/ionic-team/ionic/commit/3b803ebe024be3dbcf814a30a18df51ce23c8880)), closes [#23588](https://github.com/ionic-team/ionic/issues/23588)
|
||||
* **item:** mirror disabled prop to aria attribute ([#23544](https://github.com/ionic-team/ionic/issues/23544)) ([9021e7c](https://github.com/ionic-team/ionic/commit/9021e7cc4b48a69ccc94faa7d2ddcb10a2afa340)), closes [#23513](https://github.com/ionic-team/ionic/issues/23513)
|
||||
* **menu-button:** custom aria-label can now be set ([#23608](https://github.com/ionic-team/ionic/issues/23608)) ([c08345d](https://github.com/ionic-team/ionic/commit/c08345df2ee3175f3f0d11ff877c7b6f1a102321)), closes [#23604](https://github.com/ionic-team/ionic/issues/23604)
|
||||
* **overlays:** overlay interfaces are now exported from framework packages and documented ([#23619](https://github.com/ionic-team/ionic/issues/23619)) ([773bbcb](https://github.com/ionic-team/ionic/commit/773bbcb211d3cf0caf38c25b44e666d98ddfafe5)), closes [#22790](https://github.com/ionic-team/ionic/issues/22790)
|
||||
* **router-outlet:** improve reliability of swipe back gesture when quickly swiping back ([#23527](https://github.com/ionic-team/ionic/issues/23527)) ([fa06942](https://github.com/ionic-team/ionic/commit/fa069424b265891852a07869b6d086a1cb041e93)), closes [#22895](https://github.com/ionic-team/ionic/issues/22895)
|
||||
|
||||
|
||||
|
||||
## [5.6.11](https://github.com/ionic-team/ionic/compare/v5.6.10...v5.6.11) (2021-07-01)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* **animation:** typescript interface has correct return value for progress methods ([#23536](https://github.com/ionic-team/ionic/issues/23536)) ([f3d6abb](https://github.com/ionic-team/ionic/commit/f3d6abbc1beeafe3b5e7f473d70d0b8ef4c79bc8))
|
||||
* **ios, md:** double tapping back button no longer causes app to go back 2 pages ([#23526](https://github.com/ionic-team/ionic/issues/23526)) ([69be51d](https://github.com/ionic-team/ionic/commit/69be51dc54e670b2f75cbfac28a4a09517dbf355)), closes [#18455](https://github.com/ionic-team/ionic/issues/18455)
|
||||
|
||||
|
||||
|
||||
## [5.6.10](https://github.com/ionic-team/ionic/compare/v5.6.9...v5.6.10) (2021-06-22)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* **button:** buttons using fill and color properties now account for hover and focused opacity variables ([#23442](https://github.com/ionic-team/ionic/issues/23442)) ([68c0e71](https://github.com/ionic-team/ionic/commit/68c0e7136d3f8aad8a195a0371104f7dd5fa7060)), closes [#23441](https://github.com/ionic-team/ionic/issues/23441)
|
||||
* **item:** using multiple items with inputs no longer results in console warnings ([#23429](https://github.com/ionic-team/ionic/issues/23429)) ([e27b5b6](https://github.com/ionic-team/ionic/commit/e27b5b6ae360c44d8521ac7191817cbbe0367c05)), closes [#23427](https://github.com/ionic-team/ionic/issues/23427)
|
||||
* **vue:** IonTabs can now accept IonRouterOutlet, deprecated default router outlet in tabs ([#23477](https://github.com/ionic-team/ionic/issues/23477)) ([a2a4cff](https://github.com/ionic-team/ionic/commit/a2a4cff3d0d67868f384e1e9eec7cc738e260a27)), closes [#23321](https://github.com/ionic-team/ionic/issues/23321)
|
||||
|
||||
|
||||
|
||||
## [5.6.9](https://github.com/ionic-team/ionic/compare/v5.6.8...v5.6.9) (2021-06-08)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* **modal:** swipe to close modal is no longer swipeable on footer ([#23401](https://github.com/ionic-team/ionic/issues/23401)) ([ae96563](https://github.com/ionic-team/ionic/commit/ae96563fb3c4612cb8585292b389ee746f5759f7)), closes [#23398](https://github.com/ionic-team/ionic/issues/23398)
|
||||
* **title:** inherit padding for iOS title in a toolbar ([#23343](https://github.com/ionic-team/ionic/issues/23343)) ([82cfa55](https://github.com/ionic-team/ionic/commit/82cfa5565347704b0e9f7dac792ed2aa6dd30505)), closes [#23072](https://github.com/ionic-team/ionic/issues/23072)
|
||||
* **vue:** improve v-model integration for Vue 3.1.0+ ([#23420](https://github.com/ionic-team/ionic/issues/23420)) ([f008628](https://github.com/ionic-team/ionic/commit/f0086288512bd7f7d1929d79bfd8bf702efc732e))
|
||||
* **vue:** prevent error from being thrown when testing on certain jest runners ([#23421](https://github.com/ionic-team/ionic/issues/23421)) ([60bedb5](https://github.com/ionic-team/ionic/commit/60bedb5599b286bffccfc54c4861a269d9b8df73)), closes [#23397](https://github.com/ionic-team/ionic/issues/23397)
|
||||
|
||||
|
||||
|
||||
## [5.6.8](https://github.com/ionic-team/ionic/compare/v5.6.7...v5.6.8) (2021-05-27)
|
||||
|
||||
|
||||
@@ -3901,4 +4048,4 @@ The following dependencies need to be updated to resolve build errors
|
||||
|
||||
<a name="0.1.0"></a>
|
||||
|
||||
## [0.1.0](https://github.com/ionic-team/ionic/commit/43a8c4c7a719169336a84964fc1c737562d764a6) (2018-03-01)
|
||||
## [0.1.0](https://github.com/ionic-team/ionic/commit/43a8c4c7a719169336a84964fc1c737562d764a6) (2018-03-01)
|
||||
@@ -5,6 +5,9 @@ build top quality native and progressive web apps with web technologies.
|
||||
|
||||
Ionic Framework is based on [Web Components](https://www.webcomponents.org/introduction) and comes with many significant performance, usability, and feature improvements over the past versions.
|
||||
|
||||
## Looking for the Ionic Framework v6 beta?
|
||||
|
||||
[Click here to get started!](https://github.com/ionic-team/ionic-framework/blob/next/BETA.md)
|
||||
|
||||
### Packages
|
||||
|
||||
|
||||
46
angular/package-lock.json
generated
46
angular/package-lock.json
generated
@@ -1,15 +1,15 @@
|
||||
{
|
||||
"name": "@ionic/angular",
|
||||
"version": "5.6.8",
|
||||
"version": "5.8.3",
|
||||
"lockfileVersion": 2,
|
||||
"requires": true,
|
||||
"packages": {
|
||||
"": {
|
||||
"name": "@ionic/angular",
|
||||
"version": "5.6.8",
|
||||
"version": "5.8.3",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@ionic/core": "5.6.7",
|
||||
"@ionic/core": "5.8.2",
|
||||
"tslib": "^1.9.3"
|
||||
},
|
||||
"devDependencies": {
|
||||
@@ -204,12 +204,12 @@
|
||||
}
|
||||
},
|
||||
"node_modules/@ionic/core": {
|
||||
"version": "5.6.7",
|
||||
"resolved": "https://registry.npmjs.org/@ionic/core/-/core-5.6.7.tgz",
|
||||
"integrity": "sha512-bLH1sS2DI+C8trfYe/L96G2y+hJ9fK/azrNqGvGwHQAPy2li89DldbH+wPqe/Wclru8ZaWjRv35AyLBawixC2w==",
|
||||
"version": "5.8.2",
|
||||
"resolved": "https://registry.npmjs.org/@ionic/core/-/core-5.8.2.tgz",
|
||||
"integrity": "sha512-BWIh6hyhq+tzVvebPMfRa+IhTV5/yXh4wO3a0U3Qo4PL4KDzWyBJfoiPi6bOEc+BAlFnCtOooTTXTumgXXOojg==",
|
||||
"dependencies": {
|
||||
"@stencil/core": "^2.4.0",
|
||||
"ionicons": "^5.5.1",
|
||||
"ionicons": "^5.5.3",
|
||||
"tslib": "^2.1.0"
|
||||
}
|
||||
},
|
||||
@@ -297,9 +297,9 @@
|
||||
}
|
||||
},
|
||||
"node_modules/@stencil/core": {
|
||||
"version": "2.5.0",
|
||||
"resolved": "https://registry.npmjs.org/@stencil/core/-/core-2.5.0.tgz",
|
||||
"integrity": "sha512-gpoYJEYzu5LV2hr7uPZklug3zXhEbYGKyNodPfmOOYZtO9q42l7RQ3cAnC8MzEoF4jFrfemgtevGik8sqn9ClQ==",
|
||||
"version": "2.6.0",
|
||||
"resolved": "https://registry.npmjs.org/@stencil/core/-/core-2.6.0.tgz",
|
||||
"integrity": "sha512-QsxWayZyusnqSZrlCl81R71rA3KqFjVVQSH4E0rGN15F1GdQaFonKlHLyCOLKLig1zzC+DQkLLiUuocexuvdeQ==",
|
||||
"bin": {
|
||||
"stencil": "bin/stencil"
|
||||
},
|
||||
@@ -2033,9 +2033,9 @@
|
||||
}
|
||||
},
|
||||
"node_modules/ionicons": {
|
||||
"version": "5.5.1",
|
||||
"resolved": "https://registry.npmjs.org/ionicons/-/ionicons-5.5.1.tgz",
|
||||
"integrity": "sha512-1auVisfaXmkmxINer8Q3kJGHP1vSxk86hf7By95eJ+Av9+oBcNuAEBfSe3jaMaGRVxVw8U/2j23MFq7R3c0HPg==",
|
||||
"version": "5.5.3",
|
||||
"resolved": "https://registry.npmjs.org/ionicons/-/ionicons-5.5.3.tgz",
|
||||
"integrity": "sha512-L71djrMi8pAad66tpwdnO1vwcyluCFvehzxU1PpH1k/HpYBZhZ5IaYhqXipmqUvu5aEbd4cbRguYyI5Fd4bxTw==",
|
||||
"dependencies": {
|
||||
"@stencil/core": "^2.5.0"
|
||||
}
|
||||
@@ -5156,12 +5156,12 @@
|
||||
}
|
||||
},
|
||||
"@ionic/core": {
|
||||
"version": "5.6.7",
|
||||
"resolved": "https://registry.npmjs.org/@ionic/core/-/core-5.6.7.tgz",
|
||||
"integrity": "sha512-bLH1sS2DI+C8trfYe/L96G2y+hJ9fK/azrNqGvGwHQAPy2li89DldbH+wPqe/Wclru8ZaWjRv35AyLBawixC2w==",
|
||||
"version": "5.8.2",
|
||||
"resolved": "https://registry.npmjs.org/@ionic/core/-/core-5.8.2.tgz",
|
||||
"integrity": "sha512-BWIh6hyhq+tzVvebPMfRa+IhTV5/yXh4wO3a0U3Qo4PL4KDzWyBJfoiPi6bOEc+BAlFnCtOooTTXTumgXXOojg==",
|
||||
"requires": {
|
||||
"@stencil/core": "^2.4.0",
|
||||
"ionicons": "^5.5.1",
|
||||
"ionicons": "^5.5.3",
|
||||
"tslib": "^2.1.0"
|
||||
},
|
||||
"dependencies": {
|
||||
@@ -5243,9 +5243,9 @@
|
||||
"dev": true
|
||||
},
|
||||
"@stencil/core": {
|
||||
"version": "2.5.0",
|
||||
"resolved": "https://registry.npmjs.org/@stencil/core/-/core-2.5.0.tgz",
|
||||
"integrity": "sha512-gpoYJEYzu5LV2hr7uPZklug3zXhEbYGKyNodPfmOOYZtO9q42l7RQ3cAnC8MzEoF4jFrfemgtevGik8sqn9ClQ=="
|
||||
"version": "2.6.0",
|
||||
"resolved": "https://registry.npmjs.org/@stencil/core/-/core-2.6.0.tgz",
|
||||
"integrity": "sha512-QsxWayZyusnqSZrlCl81R71rA3KqFjVVQSH4E0rGN15F1GdQaFonKlHLyCOLKLig1zzC+DQkLLiUuocexuvdeQ=="
|
||||
},
|
||||
"@szmarczak/http-timer": {
|
||||
"version": "1.1.2",
|
||||
@@ -6662,9 +6662,9 @@
|
||||
"dev": true
|
||||
},
|
||||
"ionicons": {
|
||||
"version": "5.5.1",
|
||||
"resolved": "https://registry.npmjs.org/ionicons/-/ionicons-5.5.1.tgz",
|
||||
"integrity": "sha512-1auVisfaXmkmxINer8Q3kJGHP1vSxk86hf7By95eJ+Av9+oBcNuAEBfSe3jaMaGRVxVw8U/2j23MFq7R3c0HPg==",
|
||||
"version": "5.5.3",
|
||||
"resolved": "https://registry.npmjs.org/ionicons/-/ionicons-5.5.3.tgz",
|
||||
"integrity": "sha512-L71djrMi8pAad66tpwdnO1vwcyluCFvehzxU1PpH1k/HpYBZhZ5IaYhqXipmqUvu5aEbd4cbRguYyI5Fd4bxTw==",
|
||||
"requires": {
|
||||
"@stencil/core": "^2.5.0"
|
||||
}
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@ionic/angular",
|
||||
"version": "5.6.8",
|
||||
"version": "5.8.3",
|
||||
"description": "Angular specific wrappers for @ionic/core",
|
||||
"keywords": [
|
||||
"ionic",
|
||||
@@ -42,7 +42,7 @@
|
||||
"validate": "npm i && npm run lint && npm run test && npm run build"
|
||||
},
|
||||
"dependencies": {
|
||||
"@ionic/core": "5.6.8",
|
||||
"@ionic/core": "5.8.3",
|
||||
"tslib": "^1.9.3"
|
||||
},
|
||||
"peerDependencies": {
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
import { NgZone } from '@angular/core';
|
||||
import { initialize } from '@ionic/core';
|
||||
import { applyPolyfills, defineCustomElements } from '@ionic/core/loader';
|
||||
|
||||
import { Config } from './providers/config';
|
||||
@@ -9,12 +10,11 @@ export const appInitialize = (config: Config, doc: Document, zone: NgZone) => {
|
||||
return (): any => {
|
||||
const win: IonicWindow | undefined = doc.defaultView as any;
|
||||
if (win && typeof (window as any) !== 'undefined') {
|
||||
const Ionic = win.Ionic = win.Ionic || {};
|
||||
|
||||
Ionic.config = {
|
||||
initialize({
|
||||
...config,
|
||||
_zoneGate: (h: any) => zone.run(h)
|
||||
};
|
||||
});
|
||||
|
||||
const aelFn = '__zone_symbol__addEventListener' in (doc.body as any)
|
||||
? '__zone_symbol__addEventListener'
|
||||
|
||||
@@ -86,10 +86,23 @@ export class IonTabs {
|
||||
* b. If the last route view doesn't exist, then navigate
|
||||
* to the default tabRootUrl
|
||||
*/
|
||||
@HostListener('ionTabButtonClick', ['$event.detail.tab'])
|
||||
select(tab: string) {
|
||||
@HostListener('ionTabButtonClick', ['$event'])
|
||||
select(tabOrEvent: string | CustomEvent) {
|
||||
const isTabString = typeof tabOrEvent === 'string';
|
||||
const tab = (isTabString) ? tabOrEvent : (tabOrEvent as CustomEvent).detail.tab;
|
||||
const alreadySelected = this.outlet.getActiveStackId() === tab;
|
||||
const tabRootUrl = `${this.outlet.tabsPrefix}/${tab}`;
|
||||
|
||||
/**
|
||||
* If this is a nested tab, prevent the event
|
||||
* from bubbling otherwise the outer tabs
|
||||
* will respond to this event too, causing
|
||||
* the app to get directed to the wrong place.
|
||||
*/
|
||||
if (!isTabString) {
|
||||
(tabOrEvent as CustomEvent).stopPropagation();
|
||||
}
|
||||
|
||||
if (alreadySelected) {
|
||||
const activeStackId = this.outlet.getActiveStackId();
|
||||
const activeView = this.outlet.getLastRouteView(activeStackId);
|
||||
|
||||
@@ -43,7 +43,47 @@ export * from './types/ionic-lifecycle-hooks';
|
||||
export { IonicModule } from './ionic-module';
|
||||
|
||||
// UTILS
|
||||
export { IonicSafeString, getPlatforms, isPlatform, createAnimation } from '@ionic/core';
|
||||
export { IonicSafeString, getPlatforms, isPlatform, createAnimation, IonicSwiper } from '@ionic/core';
|
||||
|
||||
// CORE TYPES
|
||||
export { Animation, AnimationBuilder, AnimationCallbackOptions, AnimationDirection, AnimationFill, AnimationKeyFrames, AnimationLifecycle, Gesture, GestureConfig, GestureDetail, mdTransitionAnimation, iosTransitionAnimation, NavComponentWithProps } from '@ionic/core';
|
||||
export {
|
||||
Animation,
|
||||
AnimationBuilder,
|
||||
AnimationCallbackOptions,
|
||||
AnimationDirection,
|
||||
AnimationFill,
|
||||
AnimationKeyFrames,
|
||||
AnimationLifecycle,
|
||||
Gesture,
|
||||
GestureConfig,
|
||||
GestureDetail,
|
||||
mdTransitionAnimation,
|
||||
iosTransitionAnimation,
|
||||
NavComponentWithProps,
|
||||
|
||||
SpinnerTypes,
|
||||
|
||||
ActionSheetOptions,
|
||||
ActionSheetButton,
|
||||
|
||||
AlertOptions,
|
||||
AlertInput,
|
||||
AlertTextareaAttributes,
|
||||
AlertInputAttributes,
|
||||
AlertButton,
|
||||
|
||||
LoadingOptions,
|
||||
|
||||
ModalOptions,
|
||||
|
||||
PickerOptions,
|
||||
PickerButton,
|
||||
PickerColumn,
|
||||
PickerColumnOption,
|
||||
|
||||
PopoverOptions,
|
||||
|
||||
ToastOptions,
|
||||
ToastButton
|
||||
|
||||
} from '@ionic/core';
|
||||
|
||||
@@ -110,6 +110,7 @@ export class Platform {
|
||||
* | Platform Name | Description |
|
||||
* |-----------------|------------------------------------|
|
||||
* | android | on a device running Android. |
|
||||
* | capacitor | on a device running Capacitor. |
|
||||
* | cordova | on a device running Cordova. |
|
||||
* | ios | on a device running iOS. |
|
||||
* | ipad | on an iPad device. |
|
||||
@@ -209,7 +210,7 @@ export class Platform {
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns `true` if the app is in portait mode.
|
||||
* Returns `true` if the app is in portrait mode.
|
||||
*/
|
||||
isPortrait(): boolean {
|
||||
return this.win.matchMedia && this.win.matchMedia('(orientation: portrait)').matches;
|
||||
|
||||
3
commitlint.config.js
Normal file
3
commitlint.config.js
Normal file
@@ -0,0 +1,3 @@
|
||||
module.exports = {
|
||||
extends: ['@commitlint/config-conventional']
|
||||
}
|
||||
@@ -254,7 +254,7 @@ rules:
|
||||
- visibility
|
||||
- z-index
|
||||
|
||||
property-blacklist:
|
||||
property-disallowed-list:
|
||||
- background-position
|
||||
- right
|
||||
- left
|
||||
|
||||
@@ -60,7 +60,7 @@ Notice how `IonBadge` is imported from `@ionic/core/components/ion-badge` rather
|
||||
|
||||
## How to contribute
|
||||
|
||||
[Check out the CONTRIBUTE guide](CONTRIBUTING.md)
|
||||
[Check out the CONTRIBUTE guide](/.github/CONTRIBUTING.md)
|
||||
|
||||
## Related
|
||||
|
||||
|
||||
13
core/api.txt
13
core/api.txt
@@ -6,6 +6,7 @@ ion-action-sheet,prop,buttons,(string | ActionSheetButton)[],[],false,false
|
||||
ion-action-sheet,prop,cssClass,string | string[] | undefined,undefined,false,false
|
||||
ion-action-sheet,prop,enterAnimation,((baseEl: any, opts?: any) => Animation) | undefined,undefined,false,false
|
||||
ion-action-sheet,prop,header,string | undefined,undefined,false,false
|
||||
ion-action-sheet,prop,htmlAttributes,ActionSheetAttributes | undefined,undefined,false,false
|
||||
ion-action-sheet,prop,keyboardClose,boolean,true,false,false
|
||||
ion-action-sheet,prop,leaveAnimation,((baseEl: any, opts?: any) => Animation) | undefined,undefined,false,false
|
||||
ion-action-sheet,prop,mode,"ios" | "md",undefined,false,false
|
||||
@@ -50,6 +51,7 @@ ion-alert,prop,buttons,(string | AlertButton)[],[],false,false
|
||||
ion-alert,prop,cssClass,string | string[] | undefined,undefined,false,false
|
||||
ion-alert,prop,enterAnimation,((baseEl: any, opts?: any) => Animation) | undefined,undefined,false,false
|
||||
ion-alert,prop,header,string | undefined,undefined,false,false
|
||||
ion-alert,prop,htmlAttributes,AlertAttributes | undefined,undefined,false,false
|
||||
ion-alert,prop,inputs,AlertInput[],[],false,false
|
||||
ion-alert,prop,keyboardClose,boolean,true,false,false
|
||||
ion-alert,prop,leaveAnimation,((baseEl: any, opts?: any) => Animation) | undefined,undefined,false,false
|
||||
@@ -230,7 +232,7 @@ ion-checkbox,prop,mode,"ios" | "md",undefined,false,false
|
||||
ion-checkbox,prop,name,string,this.inputId,false,false
|
||||
ion-checkbox,prop,value,string,'on',false,false
|
||||
ion-checkbox,event,ionBlur,void,true
|
||||
ion-checkbox,event,ionChange,CheckboxChangeEventDetail,true
|
||||
ion-checkbox,event,ionChange,CheckboxChangeEventDetail<any>,true
|
||||
ion-checkbox,event,ionFocus,void,true
|
||||
ion-checkbox,css-prop,--background
|
||||
ion-checkbox,css-prop,--background-checked
|
||||
@@ -333,7 +335,7 @@ ion-datetime,prop,monthShortNames,string | string[] | undefined,undefined,false,
|
||||
ion-datetime,prop,monthValues,number | number[] | string | undefined,undefined,false,false
|
||||
ion-datetime,prop,name,string,this.inputId,false,false
|
||||
ion-datetime,prop,pickerFormat,string | undefined,undefined,false,false
|
||||
ion-datetime,prop,pickerOptions,undefined | { columns?: PickerColumn[] | undefined; buttons?: PickerButton[] | undefined; cssClass?: string | string[] | undefined; showBackdrop?: boolean | undefined; backdropDismiss?: boolean | undefined; animated?: boolean | undefined; mode?: Mode | undefined; keyboardClose?: boolean | undefined; id?: string | undefined; enterAnimation?: AnimationBuilder | undefined; leaveAnimation?: AnimationBuilder | undefined; },undefined,false,false
|
||||
ion-datetime,prop,pickerOptions,undefined | { columns?: PickerColumn[] | undefined; buttons?: PickerButton[] | undefined; cssClass?: string | string[] | undefined; showBackdrop?: boolean | undefined; backdropDismiss?: boolean | undefined; animated?: boolean | undefined; mode?: Mode | undefined; keyboardClose?: boolean | undefined; id?: string | undefined; htmlAttributes?: PickerAttributes | undefined; enterAnimation?: AnimationBuilder | undefined; leaveAnimation?: AnimationBuilder | undefined; },undefined,false,false
|
||||
ion-datetime,prop,placeholder,null | string | undefined,undefined,false,false
|
||||
ion-datetime,prop,readonly,boolean,false,false,false
|
||||
ion-datetime,prop,value,null | string | undefined,undefined,false,false
|
||||
@@ -621,6 +623,7 @@ ion-loading,prop,backdropDismiss,boolean,false,false,false
|
||||
ion-loading,prop,cssClass,string | string[] | undefined,undefined,false,false
|
||||
ion-loading,prop,duration,number,0,false,false
|
||||
ion-loading,prop,enterAnimation,((baseEl: any, opts?: any) => Animation) | undefined,undefined,false,false
|
||||
ion-loading,prop,htmlAttributes,LoadingAttributes | undefined,undefined,false,false
|
||||
ion-loading,prop,keyboardClose,boolean,true,false,false
|
||||
ion-loading,prop,leaveAnimation,((baseEl: any, opts?: any) => Animation) | undefined,undefined,false,false
|
||||
ion-loading,prop,message,IonicSafeString | string | undefined,undefined,false,false
|
||||
@@ -708,6 +711,7 @@ ion-modal,prop,component,Function | HTMLElement | null | string,undefined,true,f
|
||||
ion-modal,prop,componentProps,undefined | { [key: string]: any; },undefined,false,false
|
||||
ion-modal,prop,cssClass,string | string[] | undefined,undefined,false,false
|
||||
ion-modal,prop,enterAnimation,((baseEl: any, opts?: any) => Animation) | undefined,undefined,false,false
|
||||
ion-modal,prop,htmlAttributes,ModalAttributes | undefined,undefined,false,false
|
||||
ion-modal,prop,keyboardClose,boolean,true,false,false
|
||||
ion-modal,prop,leaveAnimation,((baseEl: any, opts?: any) => Animation) | undefined,undefined,false,false
|
||||
ion-modal,prop,mode,"ios" | "md",undefined,false,false
|
||||
@@ -776,6 +780,7 @@ ion-picker,prop,columns,PickerColumn[],[],false,false
|
||||
ion-picker,prop,cssClass,string | string[] | undefined,undefined,false,false
|
||||
ion-picker,prop,duration,number,0,false,false
|
||||
ion-picker,prop,enterAnimation,((baseEl: any, opts?: any) => Animation) | undefined,undefined,false,false
|
||||
ion-picker,prop,htmlAttributes,PickerAttributes | undefined,undefined,false,false
|
||||
ion-picker,prop,keyboardClose,boolean,true,false,false
|
||||
ion-picker,prop,leaveAnimation,((baseEl: any, opts?: any) => Animation) | undefined,undefined,false,false
|
||||
ion-picker,prop,mode,"ios" | "md",undefined,false,false
|
||||
@@ -811,6 +816,7 @@ ion-popover,prop,componentProps,undefined | { [key: string]: any; },undefined,fa
|
||||
ion-popover,prop,cssClass,string | string[] | undefined,undefined,false,false
|
||||
ion-popover,prop,enterAnimation,((baseEl: any, opts?: any) => Animation) | undefined,undefined,false,false
|
||||
ion-popover,prop,event,any,undefined,false,false
|
||||
ion-popover,prop,htmlAttributes,PopoverAttributes | undefined,undefined,false,false
|
||||
ion-popover,prop,keyboardClose,boolean,true,false,false
|
||||
ion-popover,prop,leaveAnimation,((baseEl: any, opts?: any) => Animation) | undefined,undefined,false,false
|
||||
ion-popover,prop,mode,"ios" | "md",undefined,false,false
|
||||
@@ -867,7 +873,7 @@ ion-radio-group,none
|
||||
ion-radio-group,prop,allowEmptySelection,boolean,false,false,false
|
||||
ion-radio-group,prop,name,string,this.inputId,false,false
|
||||
ion-radio-group,prop,value,any,undefined,false,false
|
||||
ion-radio-group,event,ionChange,RadioGroupChangeEventDetail,true
|
||||
ion-radio-group,event,ionChange,RadioGroupChangeEventDetail<any>,true
|
||||
|
||||
ion-range,shadow
|
||||
ion-range,prop,color,string | undefined,undefined,false,true
|
||||
@@ -1268,6 +1274,7 @@ ion-toast,prop,cssClass,string | string[] | undefined,undefined,false,false
|
||||
ion-toast,prop,duration,number,0,false,false
|
||||
ion-toast,prop,enterAnimation,((baseEl: any, opts?: any) => Animation) | undefined,undefined,false,false
|
||||
ion-toast,prop,header,string | undefined,undefined,false,false
|
||||
ion-toast,prop,htmlAttributes,ToastAttributes | undefined,undefined,false,false
|
||||
ion-toast,prop,keyboardClose,boolean,false,false,false
|
||||
ion-toast,prop,leaveAnimation,((baseEl: any, opts?: any) => Animation) | undefined,undefined,false,false
|
||||
ion-toast,prop,message,IonicSafeString | string | undefined,undefined,false,false
|
||||
|
||||
32
core/package-lock.json
generated
32
core/package-lock.json
generated
@@ -1,16 +1,16 @@
|
||||
{
|
||||
"name": "@ionic/core",
|
||||
"version": "5.6.8",
|
||||
"version": "5.8.3",
|
||||
"lockfileVersion": 2,
|
||||
"requires": true,
|
||||
"packages": {
|
||||
"": {
|
||||
"name": "@ionic/core",
|
||||
"version": "5.6.8",
|
||||
"version": "5.8.3",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@stencil/core": "^2.4.0",
|
||||
"ionicons": "^5.5.1",
|
||||
"ionicons": "^5.5.3",
|
||||
"tslib": "^2.1.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
@@ -19,7 +19,7 @@
|
||||
"@rollup/plugin-node-resolve": "^8.4.0",
|
||||
"@rollup/plugin-virtual": "^2.0.3",
|
||||
"@stencil/sass": "1.3.2",
|
||||
"@stencil/vue-output-target": "^0.4.2",
|
||||
"@stencil/vue-output-target": "^0.4.3",
|
||||
"@types/jest": "^26.0.20",
|
||||
"@types/node": "^14.6.0",
|
||||
"@types/puppeteer": "5.4.3",
|
||||
@@ -1374,9 +1374,9 @@
|
||||
"dev": true
|
||||
},
|
||||
"node_modules/@stencil/vue-output-target": {
|
||||
"version": "0.4.2",
|
||||
"resolved": "https://registry.npmjs.org/@stencil/vue-output-target/-/vue-output-target-0.4.2.tgz",
|
||||
"integrity": "sha512-C+HYpVXpYUpD0x8eFC0Ahe45D3ZOUpMAh/RDCXsgooi1auWTaOFvA7YkXHpc6suBkh44HnPhYEA1VIslpU4QEA==",
|
||||
"version": "0.4.3",
|
||||
"resolved": "https://registry.npmjs.org/@stencil/vue-output-target/-/vue-output-target-0.4.3.tgz",
|
||||
"integrity": "sha512-+oTTSjzISERzrBDrtu3Iyhv69SSwzauQGnAej7GAWbLhzp/rCMyMHOTnZe5V+niJH9SHh1VahaVc3NQsA251qw==",
|
||||
"dev": true,
|
||||
"peerDependencies": {
|
||||
"@stencil/core": ">=1.8.0"
|
||||
@@ -5532,9 +5532,9 @@
|
||||
}
|
||||
},
|
||||
"node_modules/ionicons": {
|
||||
"version": "5.5.1",
|
||||
"resolved": "https://registry.npmjs.org/ionicons/-/ionicons-5.5.1.tgz",
|
||||
"integrity": "sha512-1auVisfaXmkmxINer8Q3kJGHP1vSxk86hf7By95eJ+Av9+oBcNuAEBfSe3jaMaGRVxVw8U/2j23MFq7R3c0HPg==",
|
||||
"version": "5.5.3",
|
||||
"resolved": "https://registry.npmjs.org/ionicons/-/ionicons-5.5.3.tgz",
|
||||
"integrity": "sha512-L71djrMi8pAad66tpwdnO1vwcyluCFvehzxU1PpH1k/HpYBZhZ5IaYhqXipmqUvu5aEbd4cbRguYyI5Fd4bxTw==",
|
||||
"dependencies": {
|
||||
"@stencil/core": "^2.5.0"
|
||||
}
|
||||
@@ -15022,9 +15022,9 @@
|
||||
"dev": true
|
||||
},
|
||||
"@stencil/vue-output-target": {
|
||||
"version": "0.4.2",
|
||||
"resolved": "https://registry.npmjs.org/@stencil/vue-output-target/-/vue-output-target-0.4.2.tgz",
|
||||
"integrity": "sha512-C+HYpVXpYUpD0x8eFC0Ahe45D3ZOUpMAh/RDCXsgooi1auWTaOFvA7YkXHpc6suBkh44HnPhYEA1VIslpU4QEA==",
|
||||
"version": "0.4.3",
|
||||
"resolved": "https://registry.npmjs.org/@stencil/vue-output-target/-/vue-output-target-0.4.3.tgz",
|
||||
"integrity": "sha512-+oTTSjzISERzrBDrtu3Iyhv69SSwzauQGnAej7GAWbLhzp/rCMyMHOTnZe5V+niJH9SHh1VahaVc3NQsA251qw==",
|
||||
"dev": true
|
||||
},
|
||||
"@stylelint/postcss-css-in-js": {
|
||||
@@ -18383,9 +18383,9 @@
|
||||
}
|
||||
},
|
||||
"ionicons": {
|
||||
"version": "5.5.1",
|
||||
"resolved": "https://registry.npmjs.org/ionicons/-/ionicons-5.5.1.tgz",
|
||||
"integrity": "sha512-1auVisfaXmkmxINer8Q3kJGHP1vSxk86hf7By95eJ+Av9+oBcNuAEBfSe3jaMaGRVxVw8U/2j23MFq7R3c0HPg==",
|
||||
"version": "5.5.3",
|
||||
"resolved": "https://registry.npmjs.org/ionicons/-/ionicons-5.5.3.tgz",
|
||||
"integrity": "sha512-L71djrMi8pAad66tpwdnO1vwcyluCFvehzxU1PpH1k/HpYBZhZ5IaYhqXipmqUvu5aEbd4cbRguYyI5Fd4bxTw==",
|
||||
"requires": {
|
||||
"@stencil/core": "^2.5.0"
|
||||
}
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@ionic/core",
|
||||
"version": "5.6.8",
|
||||
"version": "5.8.3",
|
||||
"description": "Base components for Ionic",
|
||||
"keywords": [
|
||||
"ionic",
|
||||
@@ -32,7 +32,7 @@
|
||||
],
|
||||
"dependencies": {
|
||||
"@stencil/core": "^2.4.0",
|
||||
"ionicons": "^5.5.1",
|
||||
"ionicons": "^5.5.3",
|
||||
"tslib": "^2.1.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
@@ -41,7 +41,7 @@
|
||||
"@rollup/plugin-node-resolve": "^8.4.0",
|
||||
"@rollup/plugin-virtual": "^2.0.3",
|
||||
"@stencil/sass": "1.3.2",
|
||||
"@stencil/vue-output-target": "^0.4.2",
|
||||
"@stencil/vue-output-target": "^0.4.3",
|
||||
"@types/jest": "^26.0.20",
|
||||
"@types/node": "^14.6.0",
|
||||
"@types/puppeteer": "5.4.3",
|
||||
|
||||
68
core/src/components.d.ts
vendored
68
core/src/components.d.ts
vendored
@@ -5,10 +5,12 @@
|
||||
* It contains typing information for all components that exist in this project.
|
||||
*/
|
||||
import { HTMLStencilElement, JSXBase } from "@stencil/core/internal";
|
||||
import { ActionSheetButton, AlertButton, AlertInput, AnimationBuilder, AutocompleteTypes, CheckboxChangeEventDetail, Color, ComponentProps, ComponentRef, DatetimeChangeEventDetail, DatetimeOptions, DomRenderFn, FooterHeightFn, FrameworkDelegate, HeaderFn, HeaderHeightFn, InputChangeEventDetail, ItemHeightFn, ItemRenderFn, ItemReorderEventDetail, MenuChangeEventDetail, NavComponent, NavComponentWithProps, NavOptions, OverlayEventDetail, PickerButton, PickerColumn, RadioGroupChangeEventDetail, RangeChangeEventDetail, RangeValue, RefresherEventDetail, RouteID, RouterDirection, RouterEventDetail, RouterOutletOptions, RouteWrite, ScrollBaseDetail, ScrollDetail, SearchbarChangeEventDetail, SegmentButtonLayout, SegmentChangeEventDetail, SelectChangeEventDetail, SelectInterface, SelectPopoverOption, Side, SpinnerTypes, StyleEventDetail, SwipeGestureHandler, TabBarChangedEventDetail, TabButtonClickEventDetail, TabButtonLayout, TextareaChangeEventDetail, TextFieldTypes, ToastButton, ToggleChangeEventDetail, TransitionDoneFn, TransitionInstruction, ViewController } from "./interface";
|
||||
import { ActionSheetAttributes, ActionSheetButton, AlertButton, AlertInput, AnimationBuilder, AutocompleteTypes, CheckboxChangeEventDetail, Color, ComponentProps, ComponentRef, DatetimeChangeEventDetail, DatetimeOptions, DomRenderFn, FooterHeightFn, FrameworkDelegate, HeaderFn, HeaderHeightFn, InputChangeEventDetail, ItemHeightFn, ItemRenderFn, ItemReorderEventDetail, LoadingAttributes, MenuChangeEventDetail, ModalAttributes, NavComponent, NavComponentWithProps, NavOptions, OverlayEventDetail, PickerAttributes, PickerButton, PickerColumn, PopoverAttributes, RadioGroupChangeEventDetail, RangeChangeEventDetail, RangeValue, RefresherEventDetail, RouteID, RouterDirection, RouterEventDetail, RouterOutletOptions, RouteWrite, ScrollBaseDetail, ScrollDetail, SearchbarChangeEventDetail, SegmentButtonLayout, SegmentChangeEventDetail, SelectChangeEventDetail, SelectInterface, SelectPopoverOption, Side, SpinnerTypes, StyleEventDetail, SwipeGestureHandler, TabBarChangedEventDetail, TabButtonClickEventDetail, TabButtonLayout, TextareaChangeEventDetail, TextFieldTypes, ToastButton, ToggleChangeEventDetail, TransitionDoneFn, TransitionInstruction, ViewController } from "./interface";
|
||||
import { IonicSafeString } from "./utils/sanitization";
|
||||
import { AlertAttributes } from "./components/alert/alert-interface";
|
||||
import { NavigationHookCallback } from "./components/route/route-interface";
|
||||
import { SelectCompareFn } from "./components/select/select-interface";
|
||||
import { ToastAttributes } from "./components/toast/toast-interface";
|
||||
export namespace Components {
|
||||
interface IonActionSheet {
|
||||
/**
|
||||
@@ -41,6 +43,10 @@ export namespace Components {
|
||||
* Title for the action sheet.
|
||||
*/
|
||||
"header"?: string;
|
||||
/**
|
||||
* Additional attributes to pass to the action sheet.
|
||||
*/
|
||||
"htmlAttributes"?: ActionSheetAttributes;
|
||||
/**
|
||||
* If `true`, the keyboard will be automatically dismissed when the overlay is presented.
|
||||
*/
|
||||
@@ -106,6 +112,10 @@ export namespace Components {
|
||||
* The main title in the heading of the alert.
|
||||
*/
|
||||
"header"?: string;
|
||||
/**
|
||||
* Additional attributes to pass to the alert.
|
||||
*/
|
||||
"htmlAttributes"?: AlertAttributes;
|
||||
/**
|
||||
* Array of input to show in the alert.
|
||||
*/
|
||||
@@ -1177,6 +1187,10 @@ export namespace Components {
|
||||
* Animation to use when the loading indicator is presented.
|
||||
*/
|
||||
"enterAnimation"?: AnimationBuilder;
|
||||
/**
|
||||
* Additional attributes to pass to the loader.
|
||||
*/
|
||||
"htmlAttributes"?: LoadingAttributes;
|
||||
/**
|
||||
* If `true`, the keyboard will be automatically dismissed when the overlay is presented.
|
||||
*/
|
||||
@@ -1341,6 +1355,10 @@ export namespace Components {
|
||||
* Animation to use when the modal is presented.
|
||||
*/
|
||||
"enterAnimation"?: AnimationBuilder;
|
||||
/**
|
||||
* Additional attributes to pass to the modal.
|
||||
*/
|
||||
"htmlAttributes"?: ModalAttributes;
|
||||
/**
|
||||
* If `true`, the keyboard will be automatically dismissed when the overlay is presented.
|
||||
*/
|
||||
@@ -1558,6 +1576,10 @@ export namespace Components {
|
||||
* @param name The name of the column.
|
||||
*/
|
||||
"getColumn": (name: string) => Promise<PickerColumn | undefined>;
|
||||
/**
|
||||
* Additional attributes to pass to the picker.
|
||||
*/
|
||||
"htmlAttributes"?: PickerAttributes;
|
||||
/**
|
||||
* If `true`, the keyboard will be automatically dismissed when the overlay is presented.
|
||||
*/
|
||||
@@ -1630,6 +1652,10 @@ export namespace Components {
|
||||
* The event to pass to the popover animation.
|
||||
*/
|
||||
"event": any;
|
||||
/**
|
||||
* Additional attributes to pass to the popover.
|
||||
*/
|
||||
"htmlAttributes"?: PopoverAttributes;
|
||||
/**
|
||||
* If `true`, the keyboard will be automatically dismissed when the overlay is presented.
|
||||
*/
|
||||
@@ -1816,7 +1842,7 @@ export namespace Components {
|
||||
*/
|
||||
"pullMin": number;
|
||||
/**
|
||||
* Time it takes the refresher to to snap back to the `refreshing` state. Does not apply when the refresher content uses a spinner, enabling the native refresher.
|
||||
* Time it takes the refresher to snap back to the `refreshing` state. Does not apply when the refresher content uses a spinner, enabling the native refresher.
|
||||
*/
|
||||
"snapbackDuration": string;
|
||||
}
|
||||
@@ -1910,7 +1936,7 @@ export namespace Components {
|
||||
*/
|
||||
"push": (url: string, direction?: RouterDirection, animation?: AnimationBuilder | undefined) => Promise<boolean>;
|
||||
/**
|
||||
* By default `ion-router` will match the routes at the root path ("/"). That can be changed when
|
||||
* The root path to use when matching URLs. By default, this is set to "/", but you can specify an alternate prefix for all URL paths.
|
||||
*/
|
||||
"root": string;
|
||||
/**
|
||||
@@ -2565,6 +2591,10 @@ export namespace Components {
|
||||
* Header to be shown in the toast.
|
||||
*/
|
||||
"header"?: string;
|
||||
/**
|
||||
* Additional attributes to pass to the toast.
|
||||
*/
|
||||
"htmlAttributes"?: ToastAttributes;
|
||||
/**
|
||||
* If `true`, the keyboard will be automatically dismissed when the overlay is presented.
|
||||
*/
|
||||
@@ -3346,6 +3376,10 @@ declare namespace LocalJSX {
|
||||
* Title for the action sheet.
|
||||
*/
|
||||
"header"?: string;
|
||||
/**
|
||||
* Additional attributes to pass to the action sheet.
|
||||
*/
|
||||
"htmlAttributes"?: ActionSheetAttributes;
|
||||
/**
|
||||
* If `true`, the keyboard will be automatically dismissed when the overlay is presented.
|
||||
*/
|
||||
@@ -3409,6 +3443,10 @@ declare namespace LocalJSX {
|
||||
* The main title in the heading of the alert.
|
||||
*/
|
||||
"header"?: string;
|
||||
/**
|
||||
* Additional attributes to pass to the alert.
|
||||
*/
|
||||
"htmlAttributes"?: AlertAttributes;
|
||||
/**
|
||||
* Array of input to show in the alert.
|
||||
*/
|
||||
@@ -4520,6 +4558,10 @@ declare namespace LocalJSX {
|
||||
* Animation to use when the loading indicator is presented.
|
||||
*/
|
||||
"enterAnimation"?: AnimationBuilder;
|
||||
/**
|
||||
* Additional attributes to pass to the loader.
|
||||
*/
|
||||
"htmlAttributes"?: LoadingAttributes;
|
||||
/**
|
||||
* If `true`, the keyboard will be automatically dismissed when the overlay is presented.
|
||||
*/
|
||||
@@ -4678,6 +4720,10 @@ declare namespace LocalJSX {
|
||||
* Animation to use when the modal is presented.
|
||||
*/
|
||||
"enterAnimation"?: AnimationBuilder;
|
||||
/**
|
||||
* Additional attributes to pass to the modal.
|
||||
*/
|
||||
"htmlAttributes"?: ModalAttributes;
|
||||
/**
|
||||
* If `true`, the keyboard will be automatically dismissed when the overlay is presented.
|
||||
*/
|
||||
@@ -4812,6 +4858,10 @@ declare namespace LocalJSX {
|
||||
* Animation to use when the picker is presented.
|
||||
*/
|
||||
"enterAnimation"?: AnimationBuilder;
|
||||
/**
|
||||
* Additional attributes to pass to the picker.
|
||||
*/
|
||||
"htmlAttributes"?: PickerAttributes;
|
||||
/**
|
||||
* If `true`, the keyboard will be automatically dismissed when the overlay is presented.
|
||||
*/
|
||||
@@ -4886,6 +4936,10 @@ declare namespace LocalJSX {
|
||||
* The event to pass to the popover animation.
|
||||
*/
|
||||
"event"?: any;
|
||||
/**
|
||||
* Additional attributes to pass to the popover.
|
||||
*/
|
||||
"htmlAttributes"?: PopoverAttributes;
|
||||
/**
|
||||
* If `true`, the keyboard will be automatically dismissed when the overlay is presented.
|
||||
*/
|
||||
@@ -5106,7 +5160,7 @@ declare namespace LocalJSX {
|
||||
*/
|
||||
"pullMin"?: number;
|
||||
/**
|
||||
* Time it takes the refresher to to snap back to the `refreshing` state. Does not apply when the refresher content uses a spinner, enabling the native refresher.
|
||||
* Time it takes the refresher to snap back to the `refreshing` state. Does not apply when the refresher content uses a spinner, enabling the native refresher.
|
||||
*/
|
||||
"snapbackDuration"?: string;
|
||||
}
|
||||
@@ -5196,7 +5250,7 @@ declare namespace LocalJSX {
|
||||
*/
|
||||
"onIonRouteWillChange"?: (event: CustomEvent<RouterEventDetail>) => void;
|
||||
/**
|
||||
* By default `ion-router` will match the routes at the root path ("/"). That can be changed when
|
||||
* The root path to use when matching URLs. By default, this is set to "/", but you can specify an alternate prefix for all URL paths.
|
||||
*/
|
||||
"root"?: string;
|
||||
/**
|
||||
@@ -5894,6 +5948,10 @@ declare namespace LocalJSX {
|
||||
* Header to be shown in the toast.
|
||||
*/
|
||||
"header"?: string;
|
||||
/**
|
||||
* Additional attributes to pass to the toast.
|
||||
*/
|
||||
"htmlAttributes"?: ToastAttributes;
|
||||
/**
|
||||
* If `true`, the keyboard will be automatically dismissed when the overlay is presented.
|
||||
*/
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
import { JSXBase } from '@stencil/core/internal';
|
||||
|
||||
import { AnimationBuilder, Mode } from '../../interface';
|
||||
|
||||
export interface ActionSheetOptions {
|
||||
@@ -11,11 +13,14 @@ export interface ActionSheetOptions {
|
||||
mode?: Mode;
|
||||
keyboardClose?: boolean;
|
||||
id?: string;
|
||||
htmlAttributes?: ActionSheetAttributes;
|
||||
|
||||
enterAnimation?: AnimationBuilder;
|
||||
leaveAnimation?: AnimationBuilder;
|
||||
}
|
||||
|
||||
export interface ActionSheetAttributes extends JSXBase.HTMLAttributes<HTMLElement> {}
|
||||
|
||||
export interface ActionSheetButton {
|
||||
text?: string;
|
||||
role?: 'cancel' | 'destructive' | 'selected' | string;
|
||||
|
||||
@@ -110,10 +110,16 @@
|
||||
text-align: $action-sheet-ios-text-align;
|
||||
}
|
||||
|
||||
.action-sheet-title.action-sheet-has-sub-title {
|
||||
font-weight: $action-sheet-ios-title-with-sub-title-font-weight;
|
||||
}
|
||||
|
||||
.action-sheet-sub-title {
|
||||
@include padding($action-sheet-ios-sub-title-padding-top, $action-sheet-ios-sub-title-padding-end, $action-sheet-ios-sub-title-padding-bottom, $action-sheet-ios-sub-title-padding-start);
|
||||
|
||||
font-size: $action-sheet-ios-sub-title-font-size;
|
||||
|
||||
font-weight: $action-sheet-ios-title-font-weight;
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -55,6 +55,9 @@ $action-sheet-ios-title-font-size: 13px !default;
|
||||
/// @prop - Font weight of the action sheet title
|
||||
$action-sheet-ios-title-font-weight: 400 !default;
|
||||
|
||||
/// @prop - Font weight of the action sheet title when it has a sub title
|
||||
$action-sheet-ios-title-with-sub-title-font-weight: 600 !default;
|
||||
|
||||
/// @prop - Border width of the action sheet title
|
||||
$action-sheet-ios-title-border-width: $hairlines-width !default;
|
||||
|
||||
@@ -72,10 +75,10 @@ $action-sheet-ios-title-border-color: rgba($text-col
|
||||
// --------------------------------------------------
|
||||
|
||||
/// @prop - Font size of the action sheet sub title
|
||||
$action-sheet-ios-sub-title-font-size: 12px !default;
|
||||
$action-sheet-ios-sub-title-font-size: 13px !default;
|
||||
|
||||
/// @prop - Padding top of the action sheet sub title
|
||||
$action-sheet-ios-sub-title-padding-top: 15px !default;
|
||||
$action-sheet-ios-sub-title-padding-top: 6px !default;
|
||||
|
||||
/// @prop - Padding end of the action sheet sub title
|
||||
$action-sheet-ios-sub-title-padding-end: 0 !default;
|
||||
@@ -103,7 +106,7 @@ $action-sheet-ios-button-text-color: ion-color(prim
|
||||
$action-sheet-ios-button-icon-font-size: 28px !default;
|
||||
|
||||
/// @prop - Padding right of the action sheet button icon
|
||||
$action-sheet-ios-button-icon-padding-right: .1em !default;
|
||||
$action-sheet-ios-button-icon-padding-right: .3em !default;
|
||||
|
||||
/// @prop - Font size of the action sheet button
|
||||
$action-sheet-ios-button-font-size: 20px !default;
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import { Component, ComponentInterface, Element, Event, EventEmitter, Host, Method, Prop, h, readTask } from '@stencil/core';
|
||||
|
||||
import { getIonMode } from '../../global/ionic-global';
|
||||
import { ActionSheetButton, AnimationBuilder, CssClassMap, OverlayEventDetail, OverlayInterface } from '../../interface';
|
||||
import { ActionSheetAttributes, ActionSheetButton, AnimationBuilder, CssClassMap, OverlayEventDetail, OverlayInterface } from '../../interface';
|
||||
import { Gesture } from '../../utils/gesture';
|
||||
import { createButtonActiveGesture } from '../../utils/gesture/button-active';
|
||||
import { BACKDROP, dismiss, eventMethod, isCancel, prepareOverlay, present, safeCall } from '../../utils/overlays';
|
||||
@@ -90,6 +90,11 @@ export class ActionSheet implements ComponentInterface, OverlayInterface {
|
||||
*/
|
||||
@Prop() animated = true;
|
||||
|
||||
/**
|
||||
* Additional attributes to pass to the action sheet.
|
||||
*/
|
||||
@Prop() htmlAttributes?: ActionSheetAttributes;
|
||||
|
||||
/**
|
||||
* Emitted after the alert has presented.
|
||||
*/
|
||||
@@ -228,6 +233,7 @@ export class ActionSheet implements ComponentInterface, OverlayInterface {
|
||||
}
|
||||
|
||||
render() {
|
||||
const { htmlAttributes } = this;
|
||||
const mode = getIonMode(this);
|
||||
const allButtons = this.getButtons();
|
||||
const cancelButton = allButtons.find(b => b.role === 'cancel');
|
||||
@@ -238,6 +244,7 @@ export class ActionSheet implements ComponentInterface, OverlayInterface {
|
||||
role="dialog"
|
||||
aria-modal="true"
|
||||
tabindex="-1"
|
||||
{...htmlAttributes as any}
|
||||
style={{
|
||||
zIndex: `${20000 + this.overlayIndex}`,
|
||||
}}
|
||||
@@ -258,7 +265,10 @@ export class ActionSheet implements ComponentInterface, OverlayInterface {
|
||||
<div class="action-sheet-container">
|
||||
<div class="action-sheet-group" ref={el => this.groupEl = el}>
|
||||
{this.header !== undefined &&
|
||||
<div class="action-sheet-title">
|
||||
<div class={{
|
||||
'action-sheet-title': true,
|
||||
'action-sheet-has-sub-title': this.subHeader !== undefined
|
||||
}}>
|
||||
{this.header}
|
||||
{this.subHeader && <div class="action-sheet-sub-title">{this.subHeader}</div>}
|
||||
</div>
|
||||
|
||||
@@ -34,6 +34,46 @@ Any of the defined [CSS Custom Properties](#css-custom-properties) can be used t
|
||||
|
||||
> If you are building an Ionic Angular app, the styles need to be added to a global stylesheet file. Read [Style Placement](#style-placement) in the Angular section below for more information.
|
||||
|
||||
## Interfaces
|
||||
|
||||
### ActionSheetButton
|
||||
|
||||
```typescript
|
||||
interface ActionSheetButton {
|
||||
text?: string;
|
||||
role?: 'cancel' | 'destructive' | 'selected' | string;
|
||||
icon?: string;
|
||||
cssClass?: string | string[];
|
||||
handler?: () => boolean | void | Promise<boolean | void>;
|
||||
}
|
||||
```
|
||||
|
||||
### ActionSheetOptions
|
||||
|
||||
```typescript
|
||||
interface ActionSheetOptions {
|
||||
header?: string;
|
||||
subHeader?: string;
|
||||
cssClass?: string | string[];
|
||||
buttons: (ActionSheetButton | string)[];
|
||||
backdropDismiss?: boolean;
|
||||
translucent?: boolean;
|
||||
animated?: boolean;
|
||||
mode?: Mode;
|
||||
keyboardClose?: boolean;
|
||||
id?: string;
|
||||
htmlAttributes?: ActionSheetAttributes;
|
||||
|
||||
enterAnimation?: AnimationBuilder;
|
||||
leaveAnimation?: AnimationBuilder;
|
||||
}
|
||||
```
|
||||
|
||||
### ActionSheetAttributes
|
||||
|
||||
```typescript
|
||||
interface ActionSheetAttributes extends JSXBase.HTMLAttributes<HTMLElement> {}
|
||||
```
|
||||
|
||||
<!-- Auto Generated Below -->
|
||||
|
||||
@@ -491,6 +531,7 @@ export default defineComponent({
|
||||
| `cssClass` | `css-class` | Additional classes to apply for custom CSS. If multiple classes are provided they should be separated by spaces. | `string \| string[] \| undefined` | `undefined` |
|
||||
| `enterAnimation` | -- | Animation to use when the action sheet is presented. | `((baseEl: any, opts?: any) => Animation) \| undefined` | `undefined` |
|
||||
| `header` | `header` | Title for the action sheet. | `string \| undefined` | `undefined` |
|
||||
| `htmlAttributes` | -- | Additional attributes to pass to the action sheet. | `ActionSheetAttributes \| undefined` | `undefined` |
|
||||
| `keyboardClose` | `keyboard-close` | If `true`, the keyboard will be automatically dismissed when the overlay is presented. | `boolean` | `true` |
|
||||
| `leaveAnimation` | -- | Animation to use when the action sheet is dismissed. | `((baseEl: any, opts?: any) => Animation) \| undefined` | `undefined` |
|
||||
| `mode` | `mode` | The mode determines which platform styles to use. | `"ios" \| "md"` | `undefined` |
|
||||
|
||||
@@ -111,3 +111,21 @@ test('action-sheet:rtl: basic, scroll without cancel', async () => {
|
||||
test('action-sheet:rtl: basic, custom backdrop', async () => {
|
||||
await testActionSheet(DIRECTORY, '#customBackdrop', true);
|
||||
});
|
||||
|
||||
// Attributes
|
||||
|
||||
test('action-sheet: htmlAttributes', async () => {
|
||||
const page = await newE2EPage({ url: '/src/components/action-sheet/test/basic?ionic:_testing=true' });
|
||||
|
||||
await page.click('#basic');
|
||||
await page.waitForSelector('#basic');
|
||||
|
||||
let toast = await page.find('ion-action-sheet');
|
||||
|
||||
expect(toast).not.toBe(null);
|
||||
await toast.waitForVisible();
|
||||
|
||||
const attribute = await page.evaluate((el) => document.querySelector('ion-action-sheet').getAttribute('data-testid'));
|
||||
|
||||
expect(attribute).toEqual('basic-action-sheet');
|
||||
});
|
||||
|
||||
@@ -71,6 +71,9 @@
|
||||
await openActionSheet({
|
||||
header: "Albums",
|
||||
subHeader: 'This is a sub header inside of an action sheet',
|
||||
htmlAttributes: {
|
||||
'data-testid': 'basic-action-sheet'
|
||||
},
|
||||
buttons: [{
|
||||
text: 'Delete',
|
||||
role: 'destructive',
|
||||
|
||||
@@ -13,6 +13,7 @@ export interface AlertOptions {
|
||||
backdropDismiss?: boolean;
|
||||
translucent?: boolean;
|
||||
animated?: boolean;
|
||||
htmlAttributes?: AlertAttributes;
|
||||
|
||||
mode?: Mode;
|
||||
keyboardClose?: boolean;
|
||||
@@ -22,6 +23,8 @@ export interface AlertOptions {
|
||||
leaveAnimation?: AnimationBuilder;
|
||||
}
|
||||
|
||||
export interface AlertAttributes extends JSXBase.HTMLAttributes<HTMLElement> {}
|
||||
|
||||
export interface AlertInput {
|
||||
type?: TextFieldTypes | 'checkbox' | 'radio' | 'textarea';
|
||||
name?: string;
|
||||
@@ -44,7 +47,7 @@ export interface AlertInputAttributes extends JSXBase.InputHTMLAttributes<HTMLIn
|
||||
|
||||
export interface AlertButton {
|
||||
text: string;
|
||||
role?: string;
|
||||
role?: 'cancel' | 'destructive' | string;
|
||||
cssClass?: string | string[];
|
||||
handler?: (value: any) => boolean | void | {[key: string]: any};
|
||||
}
|
||||
|
||||
@@ -80,7 +80,7 @@ $alert-md-message-empty-padding-bottom: $alert-md-message-empty-padding-to
|
||||
$alert-md-message-empty-padding-start: $alert-md-message-empty-padding-end !default;
|
||||
|
||||
/// @prop - Maximum height of the alert content
|
||||
$alert-md-content-max-height: 240px !default;
|
||||
$alert-md-content-max-height: 266px !default;
|
||||
|
||||
/// @prop - Border width of the alert input
|
||||
$alert-md-input-border-width: 1px !default;
|
||||
|
||||
@@ -8,6 +8,7 @@ import { BACKDROP, dismiss, eventMethod, isCancel, prepareOverlay, present, safe
|
||||
import { IonicSafeString, sanitizeDOMString } from '../../utils/sanitization';
|
||||
import { getClassMap } from '../../utils/theme';
|
||||
|
||||
import { AlertAttributes } from './alert-interface';
|
||||
import { iosEnterAnimation } from './animations/ios.enter';
|
||||
import { iosLeaveAnimation } from './animations/ios.leave';
|
||||
import { mdEnterAnimation } from './animations/md.enter';
|
||||
@@ -110,6 +111,11 @@ export class Alert implements ComponentInterface, OverlayInterface {
|
||||
*/
|
||||
@Prop() animated = true;
|
||||
|
||||
/**
|
||||
* Additional attributes to pass to the alert.
|
||||
*/
|
||||
@Prop() htmlAttributes?: AlertAttributes;
|
||||
|
||||
/**
|
||||
* Emitted after the alert has presented.
|
||||
*/
|
||||
@@ -550,17 +556,19 @@ export class Alert implements ComponentInterface, OverlayInterface {
|
||||
}
|
||||
|
||||
render() {
|
||||
const { overlayIndex, header, subHeader } = this;
|
||||
const { overlayIndex, header, subHeader, htmlAttributes } = this;
|
||||
const mode = getIonMode(this);
|
||||
const hdrId = `alert-${overlayIndex}-hdr`;
|
||||
const subHdrId = `alert-${overlayIndex}-sub-hdr`;
|
||||
const msgId = `alert-${overlayIndex}-msg`;
|
||||
const role = this.inputs.length > 0 || this.buttons.length > 0 ? 'alertdialog' : 'alert';
|
||||
|
||||
return (
|
||||
<Host
|
||||
role="dialog"
|
||||
role={role}
|
||||
aria-modal="true"
|
||||
tabindex="-1"
|
||||
{...htmlAttributes as any}
|
||||
style={{
|
||||
zIndex: `${20000 + overlayIndex}`,
|
||||
}}
|
||||
|
||||
@@ -41,6 +41,82 @@ Any of the defined [CSS Custom Properties](#css-custom-properties) can be used t
|
||||
|
||||
> If you are building an Ionic Angular app, the styles need to be added to a global stylesheet file. Read [Style Placement](#style-placement) in the Angular section below for more information.
|
||||
|
||||
## Interfaces
|
||||
|
||||
### AlertButton
|
||||
|
||||
```typescript
|
||||
interface AlertButton {
|
||||
text: string;
|
||||
role?: 'cancel' | 'destructive' | string;
|
||||
cssClass?: string | string[];
|
||||
handler?: (value: any) => boolean | void | {[key: string]: any};
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
### AlertInput
|
||||
|
||||
```typescript
|
||||
interface AlertInput {
|
||||
type?: TextFieldTypes | 'checkbox' | 'radio' | 'textarea';
|
||||
name?: string;
|
||||
placeholder?: string;
|
||||
value?: any;
|
||||
label?: string;
|
||||
checked?: boolean;
|
||||
disabled?: boolean;
|
||||
id?: string;
|
||||
handler?: (input: AlertInput) => void;
|
||||
min?: string | number;
|
||||
max?: string | number;
|
||||
cssClass?: string | string[];
|
||||
attributes?: AlertInputAttributes | AlertTextareaAttributes;
|
||||
tabindex?: number;
|
||||
}
|
||||
```
|
||||
|
||||
### AlertInputAttributes
|
||||
|
||||
```typescript
|
||||
interface AlertInputAttributes extends JSXBase.InputHTMLAttributes<HTMLInputElement> {}
|
||||
```
|
||||
|
||||
### AlertOptions
|
||||
|
||||
```typescript
|
||||
interface AlertOptions {
|
||||
header?: string;
|
||||
subHeader?: string;
|
||||
message?: string | IonicSafeString;
|
||||
cssClass?: string | string[];
|
||||
inputs?: AlertInput[];
|
||||
buttons?: (AlertButton | string)[];
|
||||
backdropDismiss?: boolean;
|
||||
translucent?: boolean;
|
||||
animated?: boolean;
|
||||
htmlAttributes?: AlertAttributes;
|
||||
|
||||
mode?: Mode;
|
||||
keyboardClose?: boolean;
|
||||
id?: string;
|
||||
|
||||
enterAnimation?: AnimationBuilder;
|
||||
leaveAnimation?: AnimationBuilder;
|
||||
}
|
||||
```
|
||||
|
||||
### AlertAttributes
|
||||
```typescript
|
||||
interface AlertAttributes extends JSXBase.HTMLAttributes<HTMLElement> {}
|
||||
```
|
||||
|
||||
### AlertTextareaAttributes
|
||||
```typescript
|
||||
interface AlertTextareaAttributes extends JSXBase.TextareaHTMLAttributes<HTMLTextAreaElement> {}
|
||||
```
|
||||
|
||||
|
||||
|
||||
<!-- Auto Generated Below -->
|
||||
|
||||
@@ -1698,6 +1774,7 @@ export default defineComponent({
|
||||
| `cssClass` | `css-class` | Additional classes to apply for custom CSS. If multiple classes are provided they should be separated by spaces. | `string \| string[] \| undefined` | `undefined` |
|
||||
| `enterAnimation` | -- | Animation to use when the alert is presented. | `((baseEl: any, opts?: any) => Animation) \| undefined` | `undefined` |
|
||||
| `header` | `header` | The main title in the heading of the alert. | `string \| undefined` | `undefined` |
|
||||
| `htmlAttributes` | -- | Additional attributes to pass to the alert. | `AlertAttributes \| undefined` | `undefined` |
|
||||
| `inputs` | -- | Array of input to show in the alert. | `AlertInput[]` | `[]` |
|
||||
| `keyboardClose` | `keyboard-close` | If `true`, the keyboard will be automatically dismissed when the overlay is presented. | `boolean` | `true` |
|
||||
| `leaveAnimation` | -- | Animation to use when the alert is dismissed. | `((baseEl: any, opts?: any) => Animation) \| undefined` | `undefined` |
|
||||
|
||||
@@ -102,3 +102,21 @@ test(`alert:rtl: basic, radio`, async () => {
|
||||
test(`alert:rtl: basic, checkbox`, async () => {
|
||||
await testAlert(DIRECTORY, '#checkbox', true);
|
||||
});
|
||||
|
||||
// Attributes
|
||||
|
||||
test('alert: htmlAttributes', async () => {
|
||||
const page = await newE2EPage({ url: '/src/components/alert/test/basic?ionic:_testing=true' });
|
||||
|
||||
await page.click('#basic');
|
||||
await page.waitForSelector('#basic');
|
||||
|
||||
let alert = await page.find('ion-alert');
|
||||
|
||||
expect(alert).not.toBe(null);
|
||||
await alert.waitForVisible();
|
||||
|
||||
const attribute = await page.evaluate((el) => document.querySelector('ion-alert').getAttribute('data-testid'));
|
||||
|
||||
expect(attribute).toEqual('basic-alert');
|
||||
});
|
||||
|
||||
@@ -58,7 +58,10 @@
|
||||
header: 'Alert',
|
||||
subHeader: 'Subtitle',
|
||||
message: 'This is an alert message.',
|
||||
buttons: ['OK']
|
||||
buttons: ['OK'],
|
||||
htmlAttributes: {
|
||||
'data-testid': 'basic-alert'
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
@@ -92,6 +92,13 @@
|
||||
font-kerning: none;
|
||||
}
|
||||
|
||||
// Back Button Ripple effect
|
||||
// --------------------------------------------------
|
||||
|
||||
ion-ripple-effect {
|
||||
color: var(--ripple-color);
|
||||
}
|
||||
|
||||
|
||||
// Back Button with Color
|
||||
// --------------------------------------------------
|
||||
@@ -241,4 +248,4 @@ ion-icon {
|
||||
|
||||
:host(.in-toolbar:not(.in-toolbar-color)) {
|
||||
color: #{var(--ion-toolbar-color, var(--color))};
|
||||
}
|
||||
}
|
||||
|
||||
@@ -78,6 +78,8 @@
|
||||
<ion-back-button color="secondary" class="custom"></ion-back-button>
|
||||
<ion-back-button class="custom ion-focused"></ion-back-button>
|
||||
<ion-back-button color="secondary" class="custom ion-focused"></ion-back-button>
|
||||
<ion-back-button class="ripple"></ion-back-button>
|
||||
<ion-back-button class="ripple" color="primary"></ion-back-button>
|
||||
</p>
|
||||
|
||||
<ion-toolbar>
|
||||
@@ -195,6 +197,10 @@
|
||||
--ion-toolbar-background: #222;
|
||||
--ion-toolbar-color: #ddd;
|
||||
}
|
||||
|
||||
.ripple {
|
||||
--ripple-color: red;
|
||||
}
|
||||
</style>
|
||||
</body>
|
||||
|
||||
|
||||
@@ -129,30 +129,29 @@
|
||||
// Material Design Button: Hover
|
||||
// --------------------------------------------------
|
||||
|
||||
/**
|
||||
* Only allow overriding of opacity here
|
||||
* as developers should not be overriding
|
||||
* colors when using the color prop.
|
||||
*/
|
||||
|
||||
:host(.button-solid.ion-color.ion-focused) .button-native::after {
|
||||
background: #{current-color(contrast)};
|
||||
|
||||
opacity: .24;
|
||||
}
|
||||
|
||||
:host(.button-clear.ion-color.ion-focused) .button-native::after,
|
||||
:host(.button-outline.ion-color.ion-focused) .button-native::after {
|
||||
background: #{current-color(base)};
|
||||
|
||||
opacity: .12;
|
||||
}
|
||||
|
||||
|
||||
@media (any-hover: hover) {
|
||||
:host(.button-solid.ion-color:hover) .button-native::after {
|
||||
background: #{current-color(contrast)};
|
||||
|
||||
opacity: .08;
|
||||
}
|
||||
|
||||
:host(.button-clear.ion-color:hover) .button-native::after,
|
||||
:host(.button-outline.ion-color:hover) .button-native::after {
|
||||
background: #{current-color(base)};
|
||||
|
||||
opacity: .04;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -62,7 +62,6 @@
|
||||
user-select: none;
|
||||
vertical-align: top; // the better option for most scenarios
|
||||
vertical-align: -webkit-baseline-middle; // the best for those that support it
|
||||
pointer-events: auto;
|
||||
|
||||
font-kerning: none;
|
||||
}
|
||||
|
||||
@@ -90,6 +90,7 @@
|
||||
<ion-button fill="outline" class="ion-focused" color="dark">Dark.focused</ion-button>
|
||||
<ion-button fill="outline" class="ion-activated ion-focused" color="dark">Dark.activated.focused</ion-button>
|
||||
</p>
|
||||
|
||||
<p>
|
||||
<ion-button fill="outline" disabled>Disabled</ion-button>
|
||||
<ion-button fill="outline" color="secondary" disabled>Secondary Disabled</ion-button>
|
||||
|
||||
@@ -89,6 +89,31 @@
|
||||
<ion-button class="custom ion-activated" color="warning" fill="outline">Outline</ion-button>
|
||||
<ion-button class="custom ion-activated" color="dark" fill="clear">Clear</ion-button>
|
||||
</p>
|
||||
|
||||
<div class="custom-variables">
|
||||
<ion-button>Button</ion-button>
|
||||
<ion-button fill="clear">Button</ion-button>
|
||||
<ion-button fill="outline">Button</ion-button>
|
||||
|
||||
<br>
|
||||
|
||||
<ion-button class="ion-focused">Button</ion-button>
|
||||
<ion-button class="ion-focused" fill="clear">Button</ion-button>
|
||||
<ion-button class="ion-focused" fill="outline">Button</ion-button>
|
||||
|
||||
<br>
|
||||
|
||||
<ion-button color="tertiary">Button</ion-button>
|
||||
<ion-button color="tertiary" fill="clear">Button</ion-button>
|
||||
<ion-button color="tertiary" fill="outline">Button</ion-button>
|
||||
|
||||
<br>
|
||||
|
||||
<ion-button color="tertiary" class="ion-focused">Button</ion-button>
|
||||
<ion-button color="tertiary" class="ion-focused" fill="clear">Button</ion-button>
|
||||
<ion-button color="tertiary" class="ion-focused" fill="outline">Button</ion-button>
|
||||
</div>
|
||||
|
||||
</ion-content>
|
||||
</ion-app>
|
||||
|
||||
@@ -110,6 +135,17 @@
|
||||
.custom {
|
||||
--color: red;
|
||||
}
|
||||
|
||||
.custom-variables ion-button {
|
||||
--color: black;
|
||||
|
||||
--background: pink;
|
||||
--background-focused: red;
|
||||
--background-hover: green;
|
||||
|
||||
--background-focused-opacity: .5;
|
||||
--background-hover-opacity: .5;
|
||||
}
|
||||
</style>
|
||||
</body>
|
||||
</html>
|
||||
|
||||
@@ -250,12 +250,12 @@ export class CardExample {
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { IonCard, IonCardContent, IonCardSubtitle, IonCardTitle, IonIcon, IonItem, IonLabel } from '@ionic/vue';
|
||||
import { IonCard, IonCardContent, IonCardHeader, IonCardSubtitle, IonCardTitle, IonIcon, IonItem, IonLabel } from '@ionic/vue';
|
||||
import { pin, walk, warning, wifi, wine } from 'ionicons/icons';
|
||||
import { defineComponent } from 'vue';
|
||||
|
||||
export default defineComponent({
|
||||
components: { IonCard, IonCardContent, IonCardSubtitle, IonCardTitle, IonIcon, IonItem, IonLabel }
|
||||
components: { IonCard, IonCardContent, IonCardHeader, IonCardSubtitle, IonCardTitle, IonIcon, IonItem, IonLabel }
|
||||
setup() {
|
||||
return { warning };
|
||||
}
|
||||
|
||||
@@ -49,12 +49,12 @@
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { IonCard, IonCardContent, IonCardSubtitle, IonCardTitle, IonIcon, IonItem, IonLabel } from '@ionic/vue';
|
||||
import { IonCard, IonCardContent, IonCardHeader, IonCardSubtitle, IonCardTitle, IonIcon, IonItem, IonLabel } from '@ionic/vue';
|
||||
import { pin, walk, warning, wifi, wine } from 'ionicons/icons';
|
||||
import { defineComponent } from 'vue';
|
||||
|
||||
export default defineComponent({
|
||||
components: { IonCard, IonCardContent, IonCardSubtitle, IonCardTitle, IonIcon, IonItem, IonLabel }
|
||||
components: { IonCard, IonCardContent, IonCardHeader, IonCardSubtitle, IonCardTitle, IonIcon, IonItem, IonLabel }
|
||||
setup() {
|
||||
return { warning };
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
|
||||
export interface CheckboxChangeEventDetail {
|
||||
value: any;
|
||||
export interface CheckboxChangeEventDetail<T = any> {
|
||||
value: T;
|
||||
checked: boolean;
|
||||
}
|
||||
|
||||
@@ -271,11 +271,11 @@ export default defineComponent({
|
||||
|
||||
## Events
|
||||
|
||||
| Event | Description | Type |
|
||||
| ----------- | ---------------------------------------------- | ---------------------------------------- |
|
||||
| `ionBlur` | Emitted when the checkbox loses focus. | `CustomEvent<void>` |
|
||||
| `ionChange` | Emitted when the checked property has changed. | `CustomEvent<CheckboxChangeEventDetail>` |
|
||||
| `ionFocus` | Emitted when the checkbox has focus. | `CustomEvent<void>` |
|
||||
| Event | Description | Type |
|
||||
| ----------- | ---------------------------------------------- | --------------------------------------------- |
|
||||
| `ionBlur` | Emitted when the checkbox loses focus. | `CustomEvent<void>` |
|
||||
| `ionChange` | Emitted when the checked property has changed. | `CustomEvent<CheckboxChangeEventDetail<any>>` |
|
||||
| `ionFocus` | Emitted when the checkbox has focus. | `CustomEvent<void>` |
|
||||
|
||||
|
||||
## Shadow Parts
|
||||
|
||||
@@ -150,9 +150,9 @@
|
||||
display: none;
|
||||
position: absolute;
|
||||
|
||||
/* stylelint-disable property-blacklist */
|
||||
/* stylelint-disable property-disallowed-list */
|
||||
left: -100%;
|
||||
/* stylelint-enable property-blacklist */
|
||||
/* stylelint-enable property-disallowed-list */
|
||||
|
||||
width: 100%;
|
||||
height: 100vh;
|
||||
@@ -165,9 +165,9 @@
|
||||
.transition-cover {
|
||||
position: absolute;
|
||||
|
||||
/* stylelint-disable property-blacklist */
|
||||
/* stylelint-disable property-disallowed-list */
|
||||
right: 0;
|
||||
/* stylelint-enable property-blacklist */
|
||||
/* stylelint-enable property-disallowed-list */
|
||||
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
@@ -181,9 +181,9 @@
|
||||
display: block;
|
||||
position: absolute;
|
||||
|
||||
/* stylelint-disable property-blacklist */
|
||||
/* stylelint-disable property-disallowed-list */
|
||||
right: 0;
|
||||
/* stylelint-enable property-blacklist */
|
||||
/* stylelint-enable property-disallowed-list */
|
||||
|
||||
width: 10px;
|
||||
height: 100%;
|
||||
|
||||
@@ -792,31 +792,31 @@ export default defineComponent({
|
||||
|
||||
## Properties
|
||||
|
||||
| Property | Attribute | Description | Type | Default |
|
||||
| ----------------- | ------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | --------------- |
|
||||
| `cancelText` | `cancel-text` | The text to display on the picker's cancel button. | `string` | `'Cancel'` |
|
||||
| `dayNames` | `day-names` | Full day of the week names. This can be used to provide locale names for each day in the week. Defaults to English. | `string \| string[] \| undefined` | `undefined` |
|
||||
| `dayShortNames` | `day-short-names` | Short abbreviated day of the week names. This can be used to provide locale names for each day in the week. Defaults to English. Defaults to: `['Sun', 'Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat']` | `string \| string[] \| undefined` | `undefined` |
|
||||
| `dayValues` | `day-values` | Values used to create the list of selectable days. By default every day is shown for the given month. However, to control exactly which days of the month to display, the `dayValues` input can take a number, an array of numbers, or a string of comma separated numbers. Note that even if the array days have an invalid number for the selected month, like `31` in February, it will correctly not show days which are not valid for the selected month. | `number \| number[] \| string \| undefined` | `undefined` |
|
||||
| `disabled` | `disabled` | If `true`, the user cannot interact with the datetime. | `boolean` | `false` |
|
||||
| `displayFormat` | `display-format` | The display format of the date and time as text that shows within the item. When the `pickerFormat` input is not used, then the `displayFormat` is used for both display the formatted text, and determining the datetime picker's columns. See the `pickerFormat` input description for more info. Defaults to `MMM D, YYYY`. | `string` | `'MMM D, YYYY'` |
|
||||
| `displayTimezone` | `display-timezone` | The timezone to use for display purposes only. See [Date.prototype.toLocaleString()](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Date/toLocaleString) for a list of supported timezones. If no value is provided, the component will default to displaying times in the user's local timezone. | `string \| undefined` | `undefined` |
|
||||
| `doneText` | `done-text` | The text to display on the picker's "Done" button. | `string` | `'Done'` |
|
||||
| `hourValues` | `hour-values` | Values used to create the list of selectable hours. By default the hour values range from `0` to `23` for 24-hour, or `1` to `12` for 12-hour. However, to control exactly which hours to display, the `hourValues` input can take a number, an array of numbers, or a string of comma separated numbers. | `number \| number[] \| string \| undefined` | `undefined` |
|
||||
| `max` | `max` | The maximum datetime allowed. Value must be a date string following the [ISO 8601 datetime format standard](https://www.w3.org/TR/NOTE-datetime), `1996-12-19`. The format does not have to be specific to an exact datetime. For example, the maximum could just be the year, such as `1994`. Defaults to the end of this year. | `string \| undefined` | `undefined` |
|
||||
| `min` | `min` | The minimum datetime allowed. Value must be a date string following the [ISO 8601 datetime format standard](https://www.w3.org/TR/NOTE-datetime), such as `1996-12-19`. The format does not have to be specific to an exact datetime. For example, the minimum could just be the year, such as `1994`. Defaults to the beginning of the year, 100 years ago from today. | `string \| undefined` | `undefined` |
|
||||
| `minuteValues` | `minute-values` | Values used to create the list of selectable minutes. By default the minutes range from `0` to `59`. However, to control exactly which minutes to display, the `minuteValues` input can take a number, an array of numbers, or a string of comma separated numbers. For example, if the minute selections should only be every 15 minutes, then this input value would be `minuteValues="0,15,30,45"`. | `number \| number[] \| string \| undefined` | `undefined` |
|
||||
| `mode` | `mode` | The mode determines which platform styles to use. | `"ios" \| "md"` | `undefined` |
|
||||
| `monthNames` | `month-names` | Full names for each month name. This can be used to provide locale month names. Defaults to English. | `string \| string[] \| undefined` | `undefined` |
|
||||
| `monthShortNames` | `month-short-names` | Short abbreviated names for each month name. This can be used to provide locale month names. Defaults to English. | `string \| string[] \| undefined` | `undefined` |
|
||||
| `monthValues` | `month-values` | Values used to create the list of selectable months. By default the month values range from `1` to `12`. However, to control exactly which months to display, the `monthValues` input can take a number, an array of numbers, or a string of comma separated numbers. For example, if only summer months should be shown, then this input value would be `monthValues="6,7,8"`. Note that month numbers do *not* have a zero-based index, meaning January's value is `1`, and December's is `12`. | `number \| number[] \| string \| undefined` | `undefined` |
|
||||
| `name` | `name` | The name of the control, which is submitted with the form data. | `string` | `this.inputId` |
|
||||
| `pickerFormat` | `picker-format` | The format of the date and time picker columns the user selects. A datetime input can have one or many datetime parts, each getting their own column which allow individual selection of that particular datetime part. For example, year and month columns are two individually selectable columns which help choose an exact date from the datetime picker. Each column follows the string parse format. Defaults to use `displayFormat`. | `string \| undefined` | `undefined` |
|
||||
| `pickerOptions` | -- | Any additional options that the picker interface can accept. See the [Picker API docs](../picker) for the picker options. | `undefined \| { columns?: PickerColumn[] \| undefined; buttons?: PickerButton[] \| undefined; cssClass?: string \| string[] \| undefined; showBackdrop?: boolean \| undefined; backdropDismiss?: boolean \| undefined; animated?: boolean \| undefined; mode?: Mode \| undefined; keyboardClose?: boolean \| undefined; id?: string \| undefined; enterAnimation?: AnimationBuilder \| undefined; leaveAnimation?: AnimationBuilder \| undefined; }` | `undefined` |
|
||||
| `placeholder` | `placeholder` | The text to display when there's no date selected yet. Using lowercase to match the input attribute | `null \| string \| undefined` | `undefined` |
|
||||
| `readonly` | `readonly` | If `true`, the datetime appears normal but is not interactive. | `boolean` | `false` |
|
||||
| `value` | `value` | The value of the datetime as a valid ISO 8601 datetime string. | `null \| string \| undefined` | `undefined` |
|
||||
| `yearValues` | `year-values` | Values used to create the list of selectable years. By default the year values range between the `min` and `max` datetime inputs. However, to control exactly which years to display, the `yearValues` input can take a number, an array of numbers, or string of comma separated numbers. For example, to show upcoming and recent leap years, then this input's value would be `yearValues="2024,2020,2016,2012,2008"`. | `number \| number[] \| string \| undefined` | `undefined` |
|
||||
| Property | Attribute | Description | Type | Default |
|
||||
| ----------------- | ------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | --------------- |
|
||||
| `cancelText` | `cancel-text` | The text to display on the picker's cancel button. | `string` | `'Cancel'` |
|
||||
| `dayNames` | `day-names` | Full day of the week names. This can be used to provide locale names for each day in the week. Defaults to English. | `string \| string[] \| undefined` | `undefined` |
|
||||
| `dayShortNames` | `day-short-names` | Short abbreviated day of the week names. This can be used to provide locale names for each day in the week. Defaults to English. Defaults to: `['Sun', 'Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat']` | `string \| string[] \| undefined` | `undefined` |
|
||||
| `dayValues` | `day-values` | Values used to create the list of selectable days. By default every day is shown for the given month. However, to control exactly which days of the month to display, the `dayValues` input can take a number, an array of numbers, or a string of comma separated numbers. Note that even if the array days have an invalid number for the selected month, like `31` in February, it will correctly not show days which are not valid for the selected month. | `number \| number[] \| string \| undefined` | `undefined` |
|
||||
| `disabled` | `disabled` | If `true`, the user cannot interact with the datetime. | `boolean` | `false` |
|
||||
| `displayFormat` | `display-format` | The display format of the date and time as text that shows within the item. When the `pickerFormat` input is not used, then the `displayFormat` is used for both display the formatted text, and determining the datetime picker's columns. See the `pickerFormat` input description for more info. Defaults to `MMM D, YYYY`. | `string` | `'MMM D, YYYY'` |
|
||||
| `displayTimezone` | `display-timezone` | The timezone to use for display purposes only. See [Date.prototype.toLocaleString()](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Date/toLocaleString) for a list of supported timezones. If no value is provided, the component will default to displaying times in the user's local timezone. | `string \| undefined` | `undefined` |
|
||||
| `doneText` | `done-text` | The text to display on the picker's "Done" button. | `string` | `'Done'` |
|
||||
| `hourValues` | `hour-values` | Values used to create the list of selectable hours. By default the hour values range from `0` to `23` for 24-hour, or `1` to `12` for 12-hour. However, to control exactly which hours to display, the `hourValues` input can take a number, an array of numbers, or a string of comma separated numbers. | `number \| number[] \| string \| undefined` | `undefined` |
|
||||
| `max` | `max` | The maximum datetime allowed. Value must be a date string following the [ISO 8601 datetime format standard](https://www.w3.org/TR/NOTE-datetime), `1996-12-19`. The format does not have to be specific to an exact datetime. For example, the maximum could just be the year, such as `1994`. Defaults to the end of this year. | `string \| undefined` | `undefined` |
|
||||
| `min` | `min` | The minimum datetime allowed. Value must be a date string following the [ISO 8601 datetime format standard](https://www.w3.org/TR/NOTE-datetime), such as `1996-12-19`. The format does not have to be specific to an exact datetime. For example, the minimum could just be the year, such as `1994`. Defaults to the beginning of the year, 100 years ago from today. | `string \| undefined` | `undefined` |
|
||||
| `minuteValues` | `minute-values` | Values used to create the list of selectable minutes. By default the minutes range from `0` to `59`. However, to control exactly which minutes to display, the `minuteValues` input can take a number, an array of numbers, or a string of comma separated numbers. For example, if the minute selections should only be every 15 minutes, then this input value would be `minuteValues="0,15,30,45"`. | `number \| number[] \| string \| undefined` | `undefined` |
|
||||
| `mode` | `mode` | The mode determines which platform styles to use. | `"ios" \| "md"` | `undefined` |
|
||||
| `monthNames` | `month-names` | Full names for each month name. This can be used to provide locale month names. Defaults to English. | `string \| string[] \| undefined` | `undefined` |
|
||||
| `monthShortNames` | `month-short-names` | Short abbreviated names for each month name. This can be used to provide locale month names. Defaults to English. | `string \| string[] \| undefined` | `undefined` |
|
||||
| `monthValues` | `month-values` | Values used to create the list of selectable months. By default the month values range from `1` to `12`. However, to control exactly which months to display, the `monthValues` input can take a number, an array of numbers, or a string of comma separated numbers. For example, if only summer months should be shown, then this input value would be `monthValues="6,7,8"`. Note that month numbers do *not* have a zero-based index, meaning January's value is `1`, and December's is `12`. | `number \| number[] \| string \| undefined` | `undefined` |
|
||||
| `name` | `name` | The name of the control, which is submitted with the form data. | `string` | `this.inputId` |
|
||||
| `pickerFormat` | `picker-format` | The format of the date and time picker columns the user selects. A datetime input can have one or many datetime parts, each getting their own column which allow individual selection of that particular datetime part. For example, year and month columns are two individually selectable columns which help choose an exact date from the datetime picker. Each column follows the string parse format. Defaults to use `displayFormat`. | `string \| undefined` | `undefined` |
|
||||
| `pickerOptions` | -- | Any additional options that the picker interface can accept. See the [Picker API docs](../picker) for the picker options. | `undefined \| { columns?: PickerColumn[] \| undefined; buttons?: PickerButton[] \| undefined; cssClass?: string \| string[] \| undefined; showBackdrop?: boolean \| undefined; backdropDismiss?: boolean \| undefined; animated?: boolean \| undefined; mode?: Mode \| undefined; keyboardClose?: boolean \| undefined; id?: string \| undefined; htmlAttributes?: PickerAttributes \| undefined; enterAnimation?: AnimationBuilder \| undefined; leaveAnimation?: AnimationBuilder \| undefined; }` | `undefined` |
|
||||
| `placeholder` | `placeholder` | The text to display when there's no date selected yet. Using lowercase to match the input attribute | `null \| string \| undefined` | `undefined` |
|
||||
| `readonly` | `readonly` | If `true`, the datetime appears normal but is not interactive. | `boolean` | `false` |
|
||||
| `value` | `value` | The value of the datetime as a valid ISO 8601 datetime string. | `null \| string \| undefined` | `undefined` |
|
||||
| `yearValues` | `year-values` | Values used to create the list of selectable years. By default the year values range between the `min` and `max` datetime inputs. However, to control exactly which years to display, the `yearValues` input can take a number, an array of numbers, or string of comma separated numbers. For example, to show upcoming and recent leap years, then this input's value would be `yearValues="2024,2020,2016,2012,2008"`. | `number \| number[] \| string \| undefined` | `undefined` |
|
||||
|
||||
|
||||
## Events
|
||||
|
||||
@@ -1,8 +1,10 @@
|
||||
import { Component, ComponentInterface, Element, Host, Prop, h, writeTask } from '@stencil/core';
|
||||
|
||||
import { getIonMode } from '../../global/ionic-global';
|
||||
import { inheritAttributes } from '../../utils/helpers';
|
||||
|
||||
import { cloneElement, createHeaderIndex, handleContentScroll, handleToolbarIntersection, setHeaderActive, setToolbarBackgroundOpacity } from './header.utils';
|
||||
|
||||
/**
|
||||
* @virtualProp {"ios" | "md"} mode - The mode determines which platform styles to use.
|
||||
*/
|
||||
@@ -20,6 +22,7 @@ export class Header implements ComponentInterface {
|
||||
private contentScrollCallback?: any;
|
||||
private intersectionObserver?: any;
|
||||
private collapsibleMainHeader?: HTMLElement;
|
||||
private inheritedAttributes: { [k: string]: any } = {};
|
||||
|
||||
@Element() el!: HTMLElement;
|
||||
|
||||
@@ -41,6 +44,10 @@ export class Header implements ComponentInterface {
|
||||
*/
|
||||
@Prop() translucent = false;
|
||||
|
||||
componentWillLoad() {
|
||||
this.inheritedAttributes = inheritAttributes(this.el, ['role']);
|
||||
}
|
||||
|
||||
async componentDidLoad() {
|
||||
await this.checkCollapsibleHeader();
|
||||
}
|
||||
@@ -143,9 +150,10 @@ export class Header implements ComponentInterface {
|
||||
}
|
||||
|
||||
render() {
|
||||
const { translucent } = this;
|
||||
const { translucent, inheritedAttributes } = this;
|
||||
const mode = getIonMode(this);
|
||||
const collapse = this.collapse || 'none';
|
||||
|
||||
return (
|
||||
<Host
|
||||
role="banner"
|
||||
@@ -159,6 +167,7 @@ export class Header implements ComponentInterface {
|
||||
[`header-collapse-${collapse}`]: true,
|
||||
[`header-translucent-${mode}`]: this.translucent,
|
||||
}}
|
||||
{...inheritedAttributes}
|
||||
>
|
||||
{ mode === 'ios' && translucent &&
|
||||
<div class="header-background"></div>
|
||||
|
||||
11
core/src/components/header/test/a11y/e2e.ts
Normal file
11
core/src/components/header/test/a11y/e2e.ts
Normal file
@@ -0,0 +1,11 @@
|
||||
import { newE2EPage } from '@stencil/core/testing';
|
||||
import { AxePuppeteer } from '@axe-core/puppeteer';
|
||||
|
||||
test('header: axe', async () => {
|
||||
const page = await newE2EPage({
|
||||
url: '/src/components/header/test/a11y?ionic:_testing=true'
|
||||
});
|
||||
|
||||
const results = await new AxePuppeteer(page).analyze();
|
||||
expect(results.violations.length).toEqual(0);
|
||||
});
|
||||
21
core/src/components/header/test/a11y/index.html
Normal file
21
core/src/components/header/test/a11y/index.html
Normal file
@@ -0,0 +1,21 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="en" dir="ltr">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<title>Header - a11y</title>
|
||||
<meta name="viewport"
|
||||
content="width=device-width, initial-scale=1.0, minimum-scale=1.0">
|
||||
<link href="../../../../../css/core.css" rel="stylesheet">
|
||||
<link href="../../../../../scripts/testing/styles.css" rel="stylesheet">
|
||||
<script src="../../../../../scripts/testing/scripts.js"></script>
|
||||
<script type="module" src="../../../../../dist/ionic/ionic.esm.js"></script>
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<ion-header></ion-header>
|
||||
<main>
|
||||
<h1>Headers</h1>
|
||||
<ion-header role="none"></ion-header>
|
||||
</main>
|
||||
</body>
|
||||
</html>
|
||||
@@ -60,10 +60,12 @@ export class Img implements ComponentInterface {
|
||||
'isIntersecting' in window.IntersectionObserverEntry.prototype) {
|
||||
this.removeIO();
|
||||
this.io = new IntersectionObserver(data => {
|
||||
// because there will only ever be one instance
|
||||
// of the element we are observing
|
||||
// we can just use data[0]
|
||||
if (data[0].isIntersecting) {
|
||||
/**
|
||||
* On slower devices, it is possible for an intersection observer entry to contain multiple
|
||||
* objects in the array. This happens when quickly scrolling an image into view and then out of
|
||||
* view. In this case, the last object represents the current state of the component.
|
||||
*/
|
||||
if (data[data.length - 1].isIntersecting) {
|
||||
this.load();
|
||||
this.removeIO();
|
||||
}
|
||||
|
||||
@@ -104,7 +104,7 @@ export class ItemOption implements ComponentInterface, AnchorInterface, ButtonIn
|
||||
[mode]: true,
|
||||
'item-option-disabled': disabled,
|
||||
'item-option-expandable': expandable,
|
||||
'ion-activatable': true,
|
||||
'ion-activatable': true
|
||||
})}
|
||||
>
|
||||
<TagType
|
||||
|
||||
@@ -5,10 +5,10 @@
|
||||
|
||||
ion-item-options {
|
||||
@include multi-dir() {
|
||||
/* stylelint-disable property-blacklist */
|
||||
/* stylelint-disable property-disallowed-list */
|
||||
top: 0;
|
||||
right: 0;
|
||||
/* stylelint-enable property-blacklist */
|
||||
/* stylelint-enable property-disallowed-list */
|
||||
}
|
||||
|
||||
@include ltr() {
|
||||
@@ -19,10 +19,10 @@ ion-item-options {
|
||||
justify-content: flex-start;
|
||||
|
||||
&:not(.item-options-end) {
|
||||
/* stylelint-disable property-blacklist */
|
||||
/* stylelint-disable property-disallowed-list */
|
||||
right: auto;
|
||||
left: 0;
|
||||
/* stylelint-enable property-blacklist */
|
||||
/* stylelint-enable property-disallowed-list */
|
||||
|
||||
justify-content: flex-end;
|
||||
}
|
||||
@@ -41,10 +41,10 @@ ion-item-options {
|
||||
|
||||
.item-options-start {
|
||||
@include multi-dir() {
|
||||
/* stylelint-disable property-blacklist */
|
||||
/* stylelint-disable property-disallowed-list */
|
||||
right: auto;
|
||||
left: 0;
|
||||
/* stylelint-enable property-blacklist */
|
||||
/* stylelint-enable property-disallowed-list */
|
||||
}
|
||||
|
||||
@include ltr() {
|
||||
|
||||
@@ -32,7 +32,7 @@ ion-item-sliding .item {
|
||||
|
||||
.item-sliding-active-swipe-end .item-options-end .item-option-expandable {
|
||||
@include multi-dir() {
|
||||
/* stylelint-disable-next-line property-blacklist */
|
||||
/* stylelint-disable-next-line property-disallowed-list */
|
||||
padding-left: 100%;
|
||||
}
|
||||
|
||||
@@ -50,7 +50,7 @@ ion-item-sliding .item {
|
||||
|
||||
.item-sliding-active-swipe-start .item-options-start .item-option-expandable {
|
||||
@include multi-dir() {
|
||||
/* stylelint-disable-next-line property-blacklist */
|
||||
/* stylelint-disable-next-line property-disallowed-list */
|
||||
padding-right: 100%;
|
||||
}
|
||||
|
||||
|
||||
@@ -43,6 +43,8 @@ export class ItemSliding implements ComponentInterface {
|
||||
private rightOptions?: HTMLIonItemOptionsElement;
|
||||
private optsDirty = true;
|
||||
private gesture?: Gesture;
|
||||
private closestContent: HTMLIonContentElement | null = null;
|
||||
private initialContentScrollY = true;
|
||||
|
||||
@Element() el!: HTMLIonItemSlidingElement;
|
||||
|
||||
@@ -66,6 +68,8 @@ export class ItemSliding implements ComponentInterface {
|
||||
|
||||
async connectedCallback() {
|
||||
this.item = this.el.querySelector('ion-item');
|
||||
this.closestContent = this.el.closest('ion-content');
|
||||
|
||||
await this.updateOptions();
|
||||
|
||||
this.gesture = (await import('../../utils/gesture')).createGesture({
|
||||
@@ -247,13 +251,35 @@ export class ItemSliding implements ComponentInterface {
|
||||
const selected = openSlidingItem;
|
||||
if (selected && selected !== this.el) {
|
||||
this.closeOpened();
|
||||
return false;
|
||||
}
|
||||
|
||||
return !!(this.rightOptions || this.leftOptions);
|
||||
}
|
||||
|
||||
private disableContentScrollY() {
|
||||
if (this.closestContent === null) { return }
|
||||
|
||||
this.initialContentScrollY = this.closestContent.scrollY;
|
||||
this.closestContent.scrollY = false;
|
||||
}
|
||||
|
||||
private restoreContentScrollY() {
|
||||
if (this.closestContent === null) { return }
|
||||
|
||||
this.closestContent.scrollY = this.initialContentScrollY;
|
||||
}
|
||||
|
||||
private onStart() {
|
||||
/**
|
||||
* We need to query for the ion-item
|
||||
* every time the gesture starts. Developers
|
||||
* may toggle ion-item elements via *ngIf.
|
||||
*/
|
||||
this.item = this.el.querySelector('ion-item');
|
||||
|
||||
// Prevent scrolling during gesture
|
||||
this.disableContentScrollY();
|
||||
|
||||
openSlidingItem = this.el;
|
||||
|
||||
if (this.tmr !== undefined) {
|
||||
@@ -298,6 +324,9 @@ export class ItemSliding implements ComponentInterface {
|
||||
}
|
||||
|
||||
private onEnd(gesture: GestureDetail) {
|
||||
// Restore ion-content scrollY to initial value when gesture ends
|
||||
this.restoreContentScrollY();
|
||||
|
||||
const velocity = gesture.velocityX;
|
||||
|
||||
let restingPoint = (this.openAmount > 0)
|
||||
@@ -365,16 +394,28 @@ export class ItemSliding implements ComponentInterface {
|
||||
? SlidingState.Start | SlidingState.SwipeStart
|
||||
: SlidingState.Start;
|
||||
} else {
|
||||
/**
|
||||
* Item sliding cannot be interrupted
|
||||
* while closing the item. If it did,
|
||||
* it would allow the item to get into an
|
||||
* inconsistent state where multiple
|
||||
* items are then open at the same time.
|
||||
*/
|
||||
if (this.gesture) {
|
||||
this.gesture.enable(false);
|
||||
}
|
||||
this.tmr = setTimeout(() => {
|
||||
this.state = SlidingState.Disabled;
|
||||
this.tmr = undefined;
|
||||
if (this.gesture) {
|
||||
this.gesture.enable(true);
|
||||
}
|
||||
}, 600) as any;
|
||||
|
||||
openSlidingItem = undefined;
|
||||
style.transform = '';
|
||||
return;
|
||||
}
|
||||
|
||||
style.transform = `translate3d(${-openAmount}px,0,0)`;
|
||||
this.ionDrag.emit({
|
||||
amount: openAmount,
|
||||
|
||||
@@ -41,6 +41,7 @@
|
||||
<ion-button expand="block" onclick="openItem('start')">Open Item Start</ion-button>
|
||||
<ion-button expand="block" onclick="openItem('end')">Open Item End</ion-button>
|
||||
<ion-button expand="block" onclick="openItemOneSide()">Open Item with only one side</ion-button>
|
||||
<ion-button expand="block" onclick="setDynaicItem()">Swap dynamic item</ion-button>
|
||||
</div>
|
||||
|
||||
<ion-list id="list">
|
||||
@@ -369,6 +370,17 @@
|
||||
</ion-item-options>
|
||||
</ion-item-sliding>
|
||||
|
||||
<ion-item-sliding id="dynamic-item">
|
||||
<ion-item>
|
||||
<ion-label>Dynamic First Item</ion-label>
|
||||
</ion-item>
|
||||
<ion-item-options side="end">
|
||||
<ion-item-option color="tertiary" expandable>
|
||||
First Item Options
|
||||
</ion-item-option>
|
||||
</ion-item-options>
|
||||
</ion-item-sliding>
|
||||
|
||||
<ion-item>
|
||||
<ion-label class="ion-text-wrap">
|
||||
<h2>Normal ion-item (no sliding)</h2>
|
||||
@@ -387,6 +399,20 @@
|
||||
</ion-list>
|
||||
|
||||
<script>
|
||||
const setDynaicItem = () => {
|
||||
const sliding = document.querySelector('#dynamic-item');
|
||||
sliding.innerHTML = `
|
||||
<ion-item>
|
||||
<ion-label>Dynamic Second Item</ion-label>
|
||||
</ion-item>
|
||||
<ion-item-options side="end">
|
||||
<ion-item-option color="tertiary" expandable>
|
||||
Second Item Options
|
||||
</ion-item-option>
|
||||
</ion-item-options>
|
||||
`
|
||||
}
|
||||
|
||||
var dynamicSlidingEnabled = document.getElementsByClassName('sliding-enabled');
|
||||
|
||||
// Toggle the dynamic options
|
||||
|
||||
@@ -308,7 +308,7 @@ button, a {
|
||||
z-index: 1;
|
||||
}
|
||||
|
||||
::slotted(ion-label) {
|
||||
::slotted(ion-label:not([slot="end"])) {
|
||||
flex: 1;
|
||||
}
|
||||
|
||||
|
||||
@@ -173,7 +173,7 @@ export class Item implements ComponentInterface, AnchorInterface, ButtonInterfac
|
||||
}
|
||||
|
||||
componentDidLoad() {
|
||||
this.setMultipleInputs();
|
||||
raf(() => this.setMultipleInputs());
|
||||
}
|
||||
|
||||
// If the item contains multiple clickable elements and/or inputs, then the item
|
||||
@@ -251,7 +251,7 @@ export class Item implements ComponentInterface, AnchorInterface, ButtonInterfac
|
||||
|
||||
render() {
|
||||
const { detail, detailIcon, download, labelColorStyles, lines, disabled, href, rel, target, routerAnimation, routerDirection } = this;
|
||||
const childStyles = {};
|
||||
const childStyles = {} as any;
|
||||
const mode = getIonMode(this);
|
||||
const clickable = this.isClickable();
|
||||
const canActivate = this.canActivate();
|
||||
@@ -273,10 +273,11 @@ export class Item implements ComponentInterface, AnchorInterface, ButtonInterfac
|
||||
this.itemStyles.forEach(value => {
|
||||
Object.assign(childStyles, value);
|
||||
});
|
||||
const ariaDisabled = (disabled || childStyles['item-interactive-disabled']) ? 'true' : null;
|
||||
|
||||
return (
|
||||
<Host
|
||||
aria-disabled={disabled ? 'true' : null}
|
||||
aria-disabled={ariaDisabled}
|
||||
class={{
|
||||
...childStyles,
|
||||
...labelColorStyles,
|
||||
|
||||
11
core/src/components/item/test/a11y/e2e.ts
Normal file
11
core/src/components/item/test/a11y/e2e.ts
Normal file
@@ -0,0 +1,11 @@
|
||||
import { newE2EPage } from '@stencil/core/testing';
|
||||
import { AxePuppeteer } from '@axe-core/puppeteer';
|
||||
|
||||
test('item: axe', async () => {
|
||||
const page = await newE2EPage({
|
||||
url: '/src/components/item/test/a11y?ionic:_testing=true'
|
||||
});
|
||||
|
||||
const results = await new AxePuppeteer(page).analyze();
|
||||
expect(results.violations.length).toEqual(0);
|
||||
});
|
||||
105
core/src/components/item/test/a11y/index.html
Normal file
105
core/src/components/item/test/a11y/index.html
Normal file
@@ -0,0 +1,105 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="en" dir="ltr">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<title>Item - a11y</title>
|
||||
<meta name="viewport"
|
||||
content="width=device-width, initial-scale=1.0, minimum-scale=1.0">
|
||||
<link href="../../../../../css/core.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>
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<main>
|
||||
<h1>Item</h1>
|
||||
|
||||
<ion-item>
|
||||
<ion-label>Item with Input</ion-label>
|
||||
<ion-input placeholder="Placeholder"></ion-input>
|
||||
</ion-item>
|
||||
|
||||
<ion-item disabled>
|
||||
<ion-label>Item disabled with Input</ion-label>
|
||||
<ion-input placeholder="Placeholder"></ion-input>
|
||||
</ion-item>
|
||||
|
||||
<ion-item>
|
||||
<ion-label>Item with Input disabled</ion-label>
|
||||
<ion-input placeholder="Placeholder" disabled></ion-input>
|
||||
</ion-item>
|
||||
|
||||
<ion-item>
|
||||
<ion-label position="floating">Item with Select</ion-label>
|
||||
<ion-select>
|
||||
<ion-select-option value="">No Game Console</ion-select-option>
|
||||
<ion-select-option value="nes">NES</ion-select-option>
|
||||
<ion-select-option value="n64" selected>Nintendo64</ion-select-option>
|
||||
<ion-select-option value="ps">PlayStation</ion-select-option>
|
||||
<ion-select-option value="genesis">Sega Genesis</ion-select-option>
|
||||
<ion-select-option value="saturn">Sega Saturn</ion-select-option>
|
||||
<ion-select-option value="snes">SNES</ion-select-option>
|
||||
</ion-select>
|
||||
</ion-item>
|
||||
|
||||
<ion-item disabled>
|
||||
<ion-label position="floating">Item disabled with Select</ion-label>
|
||||
<ion-select>
|
||||
<ion-select-option value="">No Game Console</ion-select-option>
|
||||
<ion-select-option value="nes">NES</ion-select-option>
|
||||
<ion-select-option value="n64" selected>Nintendo64</ion-select-option>
|
||||
<ion-select-option value="ps">PlayStation</ion-select-option>
|
||||
<ion-select-option value="genesis">Sega Genesis</ion-select-option>
|
||||
<ion-select-option value="saturn">Sega Saturn</ion-select-option>
|
||||
<ion-select-option value="snes">SNES</ion-select-option>
|
||||
</ion-select>
|
||||
</ion-item>
|
||||
|
||||
<ion-item>
|
||||
<ion-label position="floating">Item with Select disabled</ion-label>
|
||||
<ion-select disabled>
|
||||
<ion-select-option value="">No Game Console</ion-select-option>
|
||||
<ion-select-option value="nes">NES</ion-select-option>
|
||||
<ion-select-option value="n64" selected>Nintendo64</ion-select-option>
|
||||
<ion-select-option value="ps">PlayStation</ion-select-option>
|
||||
<ion-select-option value="genesis">Sega Genesis</ion-select-option>
|
||||
<ion-select-option value="saturn">Sega Saturn</ion-select-option>
|
||||
<ion-select-option value="snes">SNES</ion-select-option>
|
||||
</ion-select>
|
||||
</ion-item>
|
||||
|
||||
<ion-item>
|
||||
<ion-label>Item with Toggle</ion-label>
|
||||
<ion-toggle slot="end"></ion-toggle>
|
||||
</ion-item>
|
||||
|
||||
<ion-item disabled>
|
||||
<ion-label>Item disabled with Toggle</ion-label>
|
||||
<ion-toggle slot="end"></ion-toggle>
|
||||
</ion-item>
|
||||
|
||||
<ion-item>
|
||||
<ion-label>Item with Toggle disabled</ion-label>
|
||||
<ion-toggle slot="end" disabled></ion-toggle>
|
||||
</ion-item>
|
||||
|
||||
<ion-item>
|
||||
<ion-label>Item with Radio</ion-label>
|
||||
<ion-radio slot="start" value="biff"></ion-radio>
|
||||
</ion-item>
|
||||
|
||||
<ion-item disabled>
|
||||
<ion-label>Item disabled with Radio</ion-label>
|
||||
<ion-radio slot="start" value="biff"></ion-radio>
|
||||
</ion-item>
|
||||
|
||||
<ion-item>
|
||||
<ion-label>Item with Radio disabled</ion-label>
|
||||
<ion-radio slot="start" value="biff" disabled></ion-radio>
|
||||
</ion-item>
|
||||
|
||||
</main>
|
||||
</body>
|
||||
</html>
|
||||
@@ -118,6 +118,25 @@
|
||||
</ion-item>
|
||||
</ion-list>
|
||||
|
||||
<ion-list>
|
||||
<ion-list-header>End Labels</ion-list-header>
|
||||
<ion-item>
|
||||
<ion-label slot="end">Time</ion-label>
|
||||
<ion-datetime display-format="DDDD MMMM D YYYY hh:mm:ss a" value="2019-10-01T15:43:40.394Z"></ion-datetime>
|
||||
</ion-item>
|
||||
<ion-item>
|
||||
<ion-label slot="end">From</ion-label>
|
||||
<ion-input placeholder="Choose Starting Point"></ion-input>
|
||||
</ion-item>
|
||||
<ion-item>
|
||||
<ion-label slot="end">Destination</ion-label>
|
||||
<ion-select placeholder="Choose Really Really Long Destination Here">
|
||||
<ion-select-option>Madison, WI</ion-select-option>
|
||||
<ion-select-option>Atlanta, GA</ion-select-option>
|
||||
</ion-select>
|
||||
</ion-item>
|
||||
</ion-list>
|
||||
|
||||
</ion-content>
|
||||
</ion-app>
|
||||
|
||||
|
||||
@@ -89,11 +89,10 @@
|
||||
color: #{$item-ios-paragraph-text-color};
|
||||
}
|
||||
|
||||
:host-context(.ion-color)::slotted(p) {
|
||||
:host(.in-item-color)::slotted(p) {
|
||||
color: inherit;
|
||||
}
|
||||
|
||||
|
||||
::slotted(*) h2:last-child,
|
||||
::slotted(*) h3:last-child,
|
||||
::slotted(*) h4:last-child,
|
||||
|
||||
@@ -104,6 +104,6 @@
|
||||
color: $item-md-paragraph-text-color;
|
||||
}
|
||||
|
||||
:host-context(.ion-color)::slotted(p) {
|
||||
:host(.in-item-color)::slotted(p) {
|
||||
color: inherit;
|
||||
}
|
||||
|
||||
@@ -2,7 +2,7 @@ import { Component, ComponentInterface, Element, Event, EventEmitter, Host, Prop
|
||||
|
||||
import { getIonMode } from '../../global/ionic-global';
|
||||
import { Color, StyleEventDetail } from '../../interface';
|
||||
import { createColorClasses } from '../../utils/theme';
|
||||
import { createColorClasses, hostContext } from '../../utils/theme';
|
||||
|
||||
/**
|
||||
* @virtualProp {"ios" | "md"} mode - The mode determines which platform styles to use.
|
||||
@@ -101,6 +101,7 @@ export class Label implements ComponentInterface {
|
||||
<Host
|
||||
class={createColorClasses(this.color, {
|
||||
[mode]: true,
|
||||
'in-item-color': hostContext('ion-item.ion-color', this.el),
|
||||
[`label-${position}`]: position !== undefined,
|
||||
[`label-no-animate`]: (this.noAnimate)
|
||||
})}
|
||||
|
||||
10
core/src/components/label/test/color/e2e.ts
Normal file
10
core/src/components/label/test/color/e2e.ts
Normal file
@@ -0,0 +1,10 @@
|
||||
import { newE2EPage } from '@stencil/core/testing';
|
||||
|
||||
test('label: color', async () => {
|
||||
const page = await newE2EPage({
|
||||
url: '/src/components/label/test/color?ionic:_testing=true'
|
||||
});
|
||||
|
||||
const compare = await page.compareScreenshot();
|
||||
expect(compare).toMatchScreenshot();
|
||||
});
|
||||
29
core/src/components/label/test/color/index.html
Normal file
29
core/src/components/label/test/color/index.html
Normal file
@@ -0,0 +1,29 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="en" dir="ltr">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<title>Label - Color</title>
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0, minimum-scale=1.0, maximum-scale=1.0, user-scalable=no, viewport-fit=cover">
|
||||
<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>
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<ion-app>
|
||||
<ion-header>
|
||||
<ion-toolbar>
|
||||
<ion-title>Label - Color</ion-title>
|
||||
</ion-toolbar>
|
||||
</ion-header>
|
||||
|
||||
<ion-content color="light">
|
||||
<ion-item>
|
||||
<ion-label>Label Text<p>This paragraph should not inherit the color from content</p></ion-label>
|
||||
</ion-item>
|
||||
</ion-content>
|
||||
</ion-app>
|
||||
</body>
|
||||
</html>
|
||||
@@ -1,3 +1,5 @@
|
||||
import { JSXBase } from '@stencil/core/internal';
|
||||
|
||||
import { AnimationBuilder, Mode, SpinnerTypes } from '../../interface';
|
||||
import { IonicSafeString } from '../../utils/sanitization';
|
||||
|
||||
@@ -13,7 +15,10 @@ export interface LoadingOptions {
|
||||
mode?: Mode;
|
||||
keyboardClose?: boolean;
|
||||
id?: string;
|
||||
htmlAttributes?: LoadingAttributes;
|
||||
|
||||
enterAnimation?: AnimationBuilder;
|
||||
leaveAnimation?: AnimationBuilder;
|
||||
}
|
||||
|
||||
export interface LoadingAttributes extends JSXBase.HTMLAttributes<HTMLElement> {}
|
||||
|
||||
@@ -2,7 +2,7 @@ import { Component, ComponentInterface, Element, Event, EventEmitter, Host, Meth
|
||||
|
||||
import { config } from '../../global/config';
|
||||
import { getIonMode } from '../../global/ionic-global';
|
||||
import { AnimationBuilder, OverlayEventDetail, OverlayInterface, SpinnerTypes } from '../../interface';
|
||||
import { AnimationBuilder, LoadingAttributes, OverlayEventDetail, OverlayInterface, SpinnerTypes } from '../../interface';
|
||||
import { BACKDROP, dismiss, eventMethod, prepareOverlay, present } from '../../utils/overlays';
|
||||
import { IonicSafeString, sanitizeDOMString } from '../../utils/sanitization';
|
||||
import { getClassMap } from '../../utils/theme';
|
||||
@@ -92,6 +92,11 @@ export class Loading implements ComponentInterface, OverlayInterface {
|
||||
*/
|
||||
@Prop() animated = true;
|
||||
|
||||
/**
|
||||
* Additional attributes to pass to the loader.
|
||||
*/
|
||||
@Prop() htmlAttributes?: LoadingAttributes;
|
||||
|
||||
/**
|
||||
* Emitted after the loading has presented.
|
||||
*/
|
||||
@@ -179,15 +184,16 @@ export class Loading implements ComponentInterface, OverlayInterface {
|
||||
}
|
||||
|
||||
render() {
|
||||
const { message, spinner } = this;
|
||||
const { message, spinner, htmlAttributes } = this;
|
||||
const mode = getIonMode(this);
|
||||
return (
|
||||
<Host
|
||||
onIonBackdropTap={this.onBackdropTap}
|
||||
tabindex="-1"
|
||||
{...htmlAttributes as any}
|
||||
style={{
|
||||
zIndex: `${40000 + this.overlayIndex}`
|
||||
}}
|
||||
onIonBackdropTap={this.onBackdropTap}
|
||||
class={{
|
||||
...getClassMap(this.cssClass),
|
||||
[mode]: true,
|
||||
|
||||
@@ -37,6 +37,35 @@ Any of the defined [CSS Custom Properties](#css-custom-properties) can be used t
|
||||
|
||||
> If you are building an Ionic Angular app, the styles need to be added to a global stylesheet file. Read [Style Placement](#style-placement) in the Angular section below for more information.
|
||||
|
||||
## Interfaces
|
||||
|
||||
### LoadingOptions
|
||||
|
||||
```typescript
|
||||
interface LoadingOptions {
|
||||
spinner?: SpinnerTypes | null;
|
||||
message?: string | IonicSafeString;
|
||||
cssClass?: string | string[];
|
||||
showBackdrop?: boolean;
|
||||
duration?: number;
|
||||
translucent?: boolean;
|
||||
animated?: boolean;
|
||||
backdropDismiss?: boolean;
|
||||
mode?: Mode;
|
||||
keyboardClose?: boolean;
|
||||
id?: string;
|
||||
htmlAttributes?: LoadingAttributes;
|
||||
|
||||
enterAnimation?: AnimationBuilder;
|
||||
leaveAnimation?: AnimationBuilder;
|
||||
}
|
||||
```
|
||||
|
||||
### LoadingAttributes
|
||||
|
||||
```typescript
|
||||
interface LoadingAttributes extends JSXBase.HTMLAttributes<HTMLElement> {}
|
||||
```
|
||||
|
||||
<!-- Auto Generated Below -->
|
||||
|
||||
@@ -139,17 +168,23 @@ import { IonButton, IonContent, IonPage, useIonLoading } from '@ionic/react';
|
||||
interface LoadingProps {}
|
||||
|
||||
const LoadingExample: React.FC<LoadingProps> = () => {
|
||||
const [present] = useIonLoading();
|
||||
const [present, dismiss] = useIonLoading();
|
||||
/**
|
||||
* The recommended way of dismissing is to use the `dismiss` property
|
||||
* on `IonLoading`, but the `dismiss` method returned from `useIonLoading`
|
||||
* can be used for more complex scenarios.
|
||||
*/
|
||||
return (
|
||||
<IonPage>
|
||||
<IonContent>
|
||||
<IonButton
|
||||
expand="block"
|
||||
onClick={() =>
|
||||
onClick={() => {
|
||||
present({
|
||||
duration: 3000,
|
||||
message: 'Loading...',
|
||||
duration: 3000
|
||||
})
|
||||
}
|
||||
}}
|
||||
>
|
||||
Show Loading
|
||||
</IonButton>
|
||||
@@ -347,6 +382,7 @@ export default defineComponent({
|
||||
| `cssClass` | `css-class` | Additional classes to apply for custom CSS. If multiple classes are provided they should be separated by spaces. | `string \| string[] \| undefined` | `undefined` |
|
||||
| `duration` | `duration` | Number of milliseconds to wait before dismissing the loading indicator. | `number` | `0` |
|
||||
| `enterAnimation` | -- | Animation to use when the loading indicator is presented. | `((baseEl: any, opts?: any) => Animation) \| undefined` | `undefined` |
|
||||
| `htmlAttributes` | -- | Additional attributes to pass to the loader. | `LoadingAttributes \| undefined` | `undefined` |
|
||||
| `keyboardClose` | `keyboard-close` | If `true`, the keyboard will be automatically dismissed when the overlay is presented. | `boolean` | `true` |
|
||||
| `leaveAnimation` | -- | Animation to use when the loading indicator is dismissed. | `((baseEl: any, opts?: any) => Animation) \| undefined` | `undefined` |
|
||||
| `message` | `message` | Optional text content to display in the loading indicator. | `IonicSafeString \| string \| undefined` | `undefined` |
|
||||
|
||||
@@ -95,3 +95,19 @@ test('loading:rtl: backdrop standalone', async () => {
|
||||
test('loading:rtl: html content basic', async () => {
|
||||
await testLoading(DIRECTORY, '#html-content-loading', true);
|
||||
});
|
||||
|
||||
test('loading: htmlAttributes', async () => {
|
||||
const page = await newE2EPage({ url: '/src/components/loading/test/basic?ionic:_testing=true' });
|
||||
|
||||
await page.click('#basic-loading');
|
||||
await page.waitForSelector('#basic-loading');
|
||||
|
||||
let alert = await page.find('ion-loading');
|
||||
|
||||
expect(alert).not.toBe(null);
|
||||
await alert.waitForVisible();
|
||||
|
||||
const attribute = await page.evaluate((el) => document.querySelector('ion-loading').getAttribute('data-testid'));
|
||||
|
||||
expect(attribute).toEqual('basic-loading');
|
||||
});
|
||||
|
||||
@@ -24,7 +24,7 @@
|
||||
</ion-header>
|
||||
|
||||
<ion-content class="ion-padding">
|
||||
<ion-button id="basic-loading" expand="block" onclick="openLoading({ message: 'Hellooo', duration: 2000 })">Show Loading</ion-button>
|
||||
<ion-button id="basic-loading" expand="block" onclick="openLoading({ message: 'Hellooo', duration: 2000, htmlAttributes: { 'data-testid': 'basic-loading' } })">Show Loading</ion-button>
|
||||
<ion-button id="default" expand="block" onclick="openLoading({duration: 2000, content: 'Please wait...'})">Show Default Loading</ion-button>
|
||||
<ion-button id="long-content-loading" expand="block" onclick="openLoading({duration: 2000, message: 'Lorem ipsum dolor sit amet, consectetur adipisicing elit. Ea voluptatibus quibusdam eum nihil optio, ullam accusamus magni, nobis suscipit reprehenderit, sequi quam amet impedit. Accusamus dolorem voluptates laborum dolor obcaecati.'})">Show Loading with long message</ion-button>
|
||||
<ion-button id="no-spinner-loading" expand="block" onclick="openLoading({duration: 2000, message: 'Please wait...', spinner: null})">Show Loading with no spinner</ion-button>
|
||||
|
||||
@@ -7,17 +7,23 @@ import { IonButton, IonContent, IonPage, useIonLoading } from '@ionic/react';
|
||||
interface LoadingProps {}
|
||||
|
||||
const LoadingExample: React.FC<LoadingProps> = () => {
|
||||
const [present] = useIonLoading();
|
||||
const [present, dismiss] = useIonLoading();
|
||||
/**
|
||||
* The recommended way of dismissing is to use the `dismiss` property
|
||||
* on `IonLoading`, but the `dismiss` method returned from `useIonLoading`
|
||||
* can be used for more complex scenarios.
|
||||
*/
|
||||
return (
|
||||
<IonPage>
|
||||
<IonContent>
|
||||
<IonButton
|
||||
expand="block"
|
||||
onClick={() =>
|
||||
onClick={() => {
|
||||
present({
|
||||
duration: 3000,
|
||||
message: 'Loading...',
|
||||
duration: 3000
|
||||
})
|
||||
}
|
||||
}}
|
||||
>
|
||||
Show Loading
|
||||
</IonButton>
|
||||
|
||||
@@ -4,6 +4,7 @@ import { config } from '../../global/config';
|
||||
import { getIonMode } from '../../global/ionic-global';
|
||||
import { Color } from '../../interface';
|
||||
import { ButtonInterface } from '../../utils/element-interface';
|
||||
import { inheritAttributes } from '../../utils/helpers';
|
||||
import { menuController } from '../../utils/menu-controller';
|
||||
import { createColorClasses, hostContext } from '../../utils/theme';
|
||||
import { updateVisibility } from '../menu-toggle/menu-toggle-util';
|
||||
@@ -23,6 +24,8 @@ import { updateVisibility } from '../menu-toggle/menu-toggle-util';
|
||||
shadow: true
|
||||
})
|
||||
export class MenuButton implements ComponentInterface, ButtonInterface {
|
||||
private inheritedAttributes: { [k: string]: any } = {};
|
||||
|
||||
@Element() el!: HTMLIonSegmentElement;
|
||||
|
||||
@State() visible = false;
|
||||
@@ -54,6 +57,10 @@ export class MenuButton implements ComponentInterface, ButtonInterface {
|
||||
*/
|
||||
@Prop() type: 'submit' | 'reset' | 'button' = 'button';
|
||||
|
||||
componentWillLoad() {
|
||||
this.inheritedAttributes = inheritAttributes(this.el, ['aria-label']);
|
||||
}
|
||||
|
||||
componentDidLoad() {
|
||||
this.visibilityChanged();
|
||||
}
|
||||
@@ -69,7 +76,7 @@ export class MenuButton implements ComponentInterface, ButtonInterface {
|
||||
}
|
||||
|
||||
render() {
|
||||
const { color, disabled } = this;
|
||||
const { color, disabled, inheritedAttributes } = this;
|
||||
const mode = getIonMode(this);
|
||||
const menuIcon = config.get('menuIcon', mode === 'ios' ? 'menu-outline' : 'menu-sharp');
|
||||
const hidden = this.autoHide && !this.visible;
|
||||
@@ -78,6 +85,8 @@ export class MenuButton implements ComponentInterface, ButtonInterface {
|
||||
type: this.type
|
||||
};
|
||||
|
||||
const ariaLabel = inheritedAttributes['aria-label'] || 'menu';
|
||||
|
||||
return (
|
||||
<Host
|
||||
onClick={this.onClick}
|
||||
@@ -99,7 +108,7 @@ export class MenuButton implements ComponentInterface, ButtonInterface {
|
||||
disabled={disabled}
|
||||
class="button-native"
|
||||
part="native"
|
||||
aria-label="menu"
|
||||
aria-label={ariaLabel}
|
||||
>
|
||||
<span class="button-inner">
|
||||
<slot>
|
||||
|
||||
11
core/src/components/menu-button/test/a11y/e2e.ts
Normal file
11
core/src/components/menu-button/test/a11y/e2e.ts
Normal file
@@ -0,0 +1,11 @@
|
||||
import { newE2EPage } from '@stencil/core/testing';
|
||||
import { AxePuppeteer } from '@axe-core/puppeteer';
|
||||
|
||||
test('menu-button: axe', async () => {
|
||||
const page = await newE2EPage({
|
||||
url: '/src/components/menu-button/test/a11y?ionic:_testing=true'
|
||||
});
|
||||
|
||||
const results = await new AxePuppeteer(page).analyze();
|
||||
expect(results.violations.length).toEqual(0);
|
||||
});
|
||||
21
core/src/components/menu-button/test/a11y/index.html
Normal file
21
core/src/components/menu-button/test/a11y/index.html
Normal file
@@ -0,0 +1,21 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="en" dir="ltr">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<title>Menu Button - a11y</title>
|
||||
<meta name="viewport"
|
||||
content="width=device-width, initial-scale=1.0, minimum-scale=1.0">
|
||||
<link href="../../../../../css/core.css" rel="stylesheet">
|
||||
<link href="../../../../../scripts/testing/styles.css" rel="stylesheet">
|
||||
<script src="../../../../../scripts/testing/scripts.js"></script>
|
||||
<script type="module" src="../../../../../dist/ionic/ionic.esm.js"></script>
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<main>
|
||||
<h1>Menu Button</h1>
|
||||
<ion-menu-button auto-hide="false"></ion-menu-button>
|
||||
<ion-menu-button auto-hide="false" aria-label="Custom Label"></ion-menu-button>
|
||||
</main>
|
||||
</body>
|
||||
</html>
|
||||
@@ -29,6 +29,7 @@
|
||||
<ion-menu-button auto-hide="false" color="secondary" class="custom ion-focused"></ion-menu-button>
|
||||
<ion-menu-button auto-hide="false" class="custom-large"></ion-menu-button>
|
||||
<ion-menu-button auto-hide="false" class="custom-large ion-focused"></ion-menu-button>
|
||||
<ion-menu-button auto-hide="false" aria-label="My Custom Menu Button Label"></ion-menu-button>
|
||||
|
||||
<h1>Colors</h1>
|
||||
<ion-menu-button auto-hide="false" color="primary"></ion-menu-button>
|
||||
|
||||
@@ -63,7 +63,7 @@
|
||||
--ion-safe-area-right: 0px;
|
||||
|
||||
@include multi-dir() {
|
||||
/* stylelint-disable property-blacklist */
|
||||
/* stylelint-disable property-disallowed-list */
|
||||
right: auto;
|
||||
left: 0;
|
||||
}
|
||||
@@ -75,7 +75,7 @@
|
||||
@include multi-dir() {
|
||||
right: 0;
|
||||
left: auto;
|
||||
/* stylelint-enable property-blacklist */
|
||||
/* stylelint-enable property-disallowed-list */
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -24,11 +24,11 @@ export const createSwipeToCloseGesture = (
|
||||
return true;
|
||||
}
|
||||
|
||||
const content = target.closest('ion-content');
|
||||
if (content === null) {
|
||||
const contentOrFooter = target.closest('ion-content, ion-footer');
|
||||
if (contentOrFooter === null) {
|
||||
return true;
|
||||
}
|
||||
// Target is in the content so we don't start the gesture.
|
||||
// Target is in the content or the footer so do not start the gesture.
|
||||
// We could be more nuanced here and allow it for content that
|
||||
// does not need to scroll.
|
||||
return false;
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
import { JSXBase } from '@stencil/core/internal';
|
||||
|
||||
import { AnimationBuilder, ComponentProps, ComponentRef, FrameworkDelegate, Mode } from '../../interface';
|
||||
|
||||
export interface ModalOptions<T extends ComponentRef = ComponentRef> {
|
||||
@@ -14,7 +16,10 @@ export interface ModalOptions<T extends ComponentRef = ComponentRef> {
|
||||
mode?: Mode;
|
||||
keyboardClose?: boolean;
|
||||
id?: string;
|
||||
htmlAttributes?: ModalAttributes;
|
||||
|
||||
enterAnimation?: AnimationBuilder;
|
||||
leaveAnimation?: AnimationBuilder;
|
||||
}
|
||||
|
||||
export interface ModalAttributes extends JSXBase.HTMLAttributes<HTMLElement> {}
|
||||
|
||||
@@ -2,7 +2,7 @@ import { Component, ComponentInterface, Element, Event, EventEmitter, Host, Meth
|
||||
|
||||
import { config } from '../../global/config';
|
||||
import { getIonMode } from '../../global/ionic-global';
|
||||
import { Animation, AnimationBuilder, ComponentProps, ComponentRef, FrameworkDelegate, Gesture, OverlayEventDetail, OverlayInterface } from '../../interface';
|
||||
import { Animation, AnimationBuilder, ComponentProps, ComponentRef, FrameworkDelegate, Gesture, ModalAttributes, OverlayEventDetail, OverlayInterface } from '../../interface';
|
||||
import { attachComponent, detachComponent } from '../../utils/framework-delegate';
|
||||
import { BACKDROP, activeAnimations, dismiss, eventMethod, prepareOverlay, present } from '../../utils/overlays';
|
||||
import { getClassMap } from '../../utils/theme';
|
||||
@@ -102,6 +102,11 @@ export class Modal implements ComponentInterface, OverlayInterface {
|
||||
*/
|
||||
@Prop() presentingElement?: HTMLElement;
|
||||
|
||||
/**
|
||||
* Additional attributes to pass to the modal.
|
||||
*/
|
||||
@Prop() htmlAttributes?: ModalAttributes;
|
||||
|
||||
/**
|
||||
* Emitted after the modal has presented.
|
||||
*/
|
||||
@@ -265,6 +270,7 @@ export class Modal implements ComponentInterface, OverlayInterface {
|
||||
}
|
||||
|
||||
render() {
|
||||
const { htmlAttributes } = this;
|
||||
const mode = getIonMode(this);
|
||||
|
||||
return (
|
||||
@@ -272,14 +278,15 @@ export class Modal implements ComponentInterface, OverlayInterface {
|
||||
no-router
|
||||
aria-modal="true"
|
||||
tabindex="-1"
|
||||
{...htmlAttributes as any}
|
||||
style={{
|
||||
zIndex: `${20000 + this.overlayIndex}`,
|
||||
}}
|
||||
class={{
|
||||
[mode]: true,
|
||||
[`modal-card`]: this.presentingElement !== undefined && mode === 'ios',
|
||||
...getClassMap(this.cssClass)
|
||||
}}
|
||||
style={{
|
||||
zIndex: `${20000 + this.overlayIndex}`,
|
||||
}}
|
||||
onIonBackdropTap={this.onBackdropTap}
|
||||
onIonDismiss={this.onDismiss}
|
||||
onIonModalDidPresent={this.onLifecycle}
|
||||
|
||||
@@ -42,6 +42,37 @@ ion-modal.stack-modal {
|
||||
}
|
||||
```
|
||||
|
||||
## Interfaces
|
||||
|
||||
### ModalOptions
|
||||
|
||||
```typescript
|
||||
interface ModalOptions<T extends ComponentRef = ComponentRef> {
|
||||
component: T;
|
||||
componentProps?: ComponentProps<T>;
|
||||
presentingElement?: HTMLElement;
|
||||
showBackdrop?: boolean;
|
||||
backdropDismiss?: boolean;
|
||||
cssClass?: string | string[];
|
||||
animated?: boolean;
|
||||
swipeToClose?: boolean;
|
||||
|
||||
mode?: Mode;
|
||||
keyboardClose?: boolean;
|
||||
id?: string;
|
||||
htmlAttributes?: ModalAttributes;
|
||||
|
||||
enterAnimation?: AnimationBuilder;
|
||||
leaveAnimation?: AnimationBuilder;
|
||||
}
|
||||
```
|
||||
|
||||
### ModalAttributes
|
||||
|
||||
```typescript
|
||||
interface ModalAttributes extends JSXBase.HTMLAttributes<HTMLElement> {}
|
||||
```
|
||||
|
||||
|
||||
<!-- Auto Generated Below -->
|
||||
|
||||
@@ -489,6 +520,7 @@ In most scenarios, setting a ref on `IonRouterOutlet` and passing that ref's `cu
|
||||
isOpen={show2ndModal}
|
||||
cssClass='my-custom-class'
|
||||
presentingElement={firstModalRef.current}
|
||||
swipeToClose={true}
|
||||
onDidDismiss={() => setShow2ndModal(false)}>
|
||||
<p>This is more modal content</p>
|
||||
<IonButton onClick={() => setShow2ndModal(false)}>Close Modal</IonButton>
|
||||
@@ -751,6 +783,47 @@ export default defineComponent({
|
||||
|
||||
> If you need a wrapper element inside of your modal component, we recommend using an `<ion-page>` so that the component dimensions are still computed properly.
|
||||
|
||||
### Swipeable Modals
|
||||
|
||||
Modals in iOS mode have the ability to be presented in a card-style and swiped to close. The card-style presentation and swipe to close gesture are not mutually exclusive, meaning you can pick and choose which features you want to use. For example, you can have a card-style modal that cannot be swiped or a full sized modal that can be swiped.
|
||||
|
||||
> Card style modals when running on iPhone-sized devices do not have backdrops. As a result, the `--backdrop-opacity` variable will not have any effect.
|
||||
|
||||
```html
|
||||
<template>
|
||||
<ion-page>
|
||||
<ion-content>
|
||||
<ion-button @click="setOpen(true)">Show Modal</ion-button>
|
||||
<ion-modal
|
||||
:is-open="isOpenRef"
|
||||
css-class="my-custom-class"
|
||||
:swipe-to-close="true"
|
||||
:presenting-element="$parent.$refs.ionRouterOutlet"
|
||||
@didDismiss="setOpen(false)"
|
||||
>
|
||||
<Modal :data="data"></Modal>
|
||||
</ion-modal>
|
||||
</ion-content>
|
||||
</ion-page>
|
||||
</template>
|
||||
|
||||
<script lang="ts">
|
||||
import { IonModal, IonButton, IonContent, IonPage } from '@ionic/vue';
|
||||
import { defineComponent, ref } from 'vue';
|
||||
import Modal from './modal.vue'
|
||||
|
||||
export default defineComponent({
|
||||
components: { IonModal, IonButton, Modal, IonContent, IonPage },
|
||||
setup() {
|
||||
const isOpenRef = ref(false);
|
||||
const setOpen = (state: boolean) => isOpenRef.value = state;
|
||||
const data = { content: 'New Content' };
|
||||
return { isOpenRef, setOpen, data }
|
||||
}
|
||||
});
|
||||
</script>
|
||||
```
|
||||
|
||||
|
||||
|
||||
## Properties
|
||||
@@ -763,6 +836,7 @@ export default defineComponent({
|
||||
| `componentProps` | -- | The data to pass to the modal component. | `undefined \| { [key: string]: any; }` | `undefined` |
|
||||
| `cssClass` | `css-class` | Additional classes to apply for custom CSS. If multiple classes are provided they should be separated by spaces. | `string \| string[] \| undefined` | `undefined` |
|
||||
| `enterAnimation` | -- | Animation to use when the modal is presented. | `((baseEl: any, opts?: any) => Animation) \| undefined` | `undefined` |
|
||||
| `htmlAttributes` | -- | Additional attributes to pass to the modal. | `ModalAttributes \| undefined` | `undefined` |
|
||||
| `keyboardClose` | `keyboard-close` | If `true`, the keyboard will be automatically dismissed when the overlay is presented. | `boolean` | `true` |
|
||||
| `leaveAnimation` | -- | Animation to use when the modal is dismissed. | `((baseEl: any, opts?: any) => Animation) \| undefined` | `undefined` |
|
||||
| `mode` | `mode` | The mode determines which platform styles to use. | `"ios" \| "md"` | `undefined` |
|
||||
|
||||
@@ -71,3 +71,19 @@ test('modal: basic', async () => {
|
||||
test('modal:rtl: basic', async () => {
|
||||
await testModal(DIRECTORY, '#basic-modal', true);
|
||||
});
|
||||
|
||||
test('modal: htmlAttributes', async () => {
|
||||
const page = await newE2EPage({ url: '/src/components/modal/test/basic?ionic:_testing=true' });
|
||||
|
||||
await page.click('#basic-modal');
|
||||
await page.waitForSelector('#basic-modal');
|
||||
|
||||
let alert = await page.find('ion-modal');
|
||||
|
||||
expect(alert).not.toBe(null);
|
||||
await alert.waitForVisible();
|
||||
|
||||
const attribute = await page.evaluate((el) => document.querySelector('ion-modal').getAttribute('data-testid'));
|
||||
|
||||
expect(attribute).toEqual('basic-modal');
|
||||
});
|
||||
|
||||
@@ -67,7 +67,10 @@
|
||||
|
||||
// present the modal
|
||||
const modalElement = Object.assign(document.createElement('ion-modal'), {
|
||||
component: element
|
||||
component: element,
|
||||
htmlAttributes: {
|
||||
'data-testid': 'basic-modal'
|
||||
}
|
||||
});
|
||||
// listen for close event
|
||||
const button = element.querySelector('ion-button');
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<title>Modal - Basic</title>
|
||||
<title>Modal - Custom</title>
|
||||
<meta name="viewport" content="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">
|
||||
@@ -11,22 +11,27 @@
|
||||
<script nomodule src="../../../../../dist/ionic/ionic.js"></script>
|
||||
<script type="module" src="../../../../../dist/ionic/ionic.esm.js"></script>
|
||||
<style>
|
||||
.custom-modal {
|
||||
--height: 70%;
|
||||
--border-style: solid;
|
||||
--border-width: 7px 0 0 0;
|
||||
--border-color: #0d51aa;
|
||||
--border-radius: 20px 20px 0 0;
|
||||
|
||||
align-items: flex-end;
|
||||
}
|
||||
|
||||
@media (max-width: 400px) {
|
||||
.custom-modal {
|
||||
--max-width: 98%;
|
||||
--height: 98%;
|
||||
--height: 70%;
|
||||
--border-style: solid;
|
||||
--border-width: 7px 0 0 0;
|
||||
--border-color: #0d51aa;
|
||||
--border-radius: 20px 20px 0 0;
|
||||
|
||||
align-items: flex-end;
|
||||
}
|
||||
|
||||
.custom-modal ion-toolbar {
|
||||
--padding-top: 46px;
|
||||
--padding-bottom: 10px;
|
||||
}
|
||||
|
||||
@media (max-width: 400px) {
|
||||
.custom-modal {
|
||||
--max-width: 98%;
|
||||
--height: 98%;
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
|
||||
@@ -35,7 +40,7 @@
|
||||
|
||||
<ion-header>
|
||||
<ion-toolbar>
|
||||
<ion-title>Modal - Basic</ion-title>
|
||||
<ion-title>Modal - Custom</ion-title>
|
||||
</ion-toolbar>
|
||||
</ion-header>
|
||||
|
||||
@@ -55,13 +60,23 @@
|
||||
element.innerHTML = `
|
||||
<ion-header>
|
||||
<ion-toolbar>
|
||||
<ion-buttons slot="start">
|
||||
<ion-button>
|
||||
<ion-icon slot="icon-only" name="add-circle-outline"></ion-icon>
|
||||
</ion-button>
|
||||
</ion-buttons>
|
||||
<ion-title>Super Modal</ion-title>
|
||||
<ion-buttons slot="end">
|
||||
<ion-button class="dismiss">
|
||||
Close
|
||||
</ion-button>
|
||||
</ion-buttons>
|
||||
</ion-toolbar>
|
||||
</ion-header>
|
||||
<ion-content>
|
||||
<h1>Content of doom</h1>
|
||||
<div>Here's some more content</div>
|
||||
<ion-button class="dismiss">Dismiss Modal</ion-button>
|
||||
<ion-button class="dismiss" class="dismiss">Dismiss Modal</ion-button>
|
||||
</ion-content>
|
||||
`;
|
||||
|
||||
@@ -72,10 +87,12 @@
|
||||
});
|
||||
|
||||
// listen for close event
|
||||
const button = element.querySelector('ion-button');
|
||||
button.addEventListener('click', () => {
|
||||
modalElement.dismiss();
|
||||
});
|
||||
const buttons = element.querySelectorAll('.dismiss');
|
||||
for (var button of buttons) {
|
||||
button.addEventListener('click', () => {
|
||||
modalElement.dismiss();
|
||||
});
|
||||
}
|
||||
document.body.appendChild(modalElement);
|
||||
return modalElement;
|
||||
}
|
||||
|
||||
@@ -147,6 +147,7 @@ In most scenarios, setting a ref on `IonRouterOutlet` and passing that ref's `cu
|
||||
isOpen={show2ndModal}
|
||||
cssClass='my-custom-class'
|
||||
presentingElement={firstModalRef.current}
|
||||
swipeToClose={true}
|
||||
onDidDismiss={() => setShow2ndModal(false)}>
|
||||
<p>This is more modal content</p>
|
||||
<IonButton onClick={() => setShow2ndModal(false)}>Close Modal</IonButton>
|
||||
|
||||
@@ -93,3 +93,44 @@ export default defineComponent({
|
||||
```
|
||||
|
||||
> If you need a wrapper element inside of your modal component, we recommend using an `<ion-page>` so that the component dimensions are still computed properly.
|
||||
|
||||
### Swipeable Modals
|
||||
|
||||
Modals in iOS mode have the ability to be presented in a card-style and swiped to close. The card-style presentation and swipe to close gesture are not mutually exclusive, meaning you can pick and choose which features you want to use. For example, you can have a card-style modal that cannot be swiped or a full sized modal that can be swiped.
|
||||
|
||||
> Card style modals when running on iPhone-sized devices do not have backdrops. As a result, the `--backdrop-opacity` variable will not have any effect.
|
||||
|
||||
```html
|
||||
<template>
|
||||
<ion-page>
|
||||
<ion-content>
|
||||
<ion-button @click="setOpen(true)">Show Modal</ion-button>
|
||||
<ion-modal
|
||||
:is-open="isOpenRef"
|
||||
css-class="my-custom-class"
|
||||
:swipe-to-close="true"
|
||||
:presenting-element="$parent.$refs.ionRouterOutlet"
|
||||
@didDismiss="setOpen(false)"
|
||||
>
|
||||
<Modal :data="data"></Modal>
|
||||
</ion-modal>
|
||||
</ion-content>
|
||||
</ion-page>
|
||||
</template>
|
||||
|
||||
<script lang="ts">
|
||||
import { IonModal, IonButton, IonContent, IonPage } from '@ionic/vue';
|
||||
import { defineComponent, ref } from 'vue';
|
||||
import Modal from './modal.vue'
|
||||
|
||||
export default defineComponent({
|
||||
components: { IonModal, IonButton, Modal, IonContent, IonPage },
|
||||
setup() {
|
||||
const isOpenRef = ref(false);
|
||||
const setOpen = (state: boolean) => isOpenRef.value = state;
|
||||
const data = { content: 'New Content' };
|
||||
return { isOpenRef, setOpen, data }
|
||||
}
|
||||
});
|
||||
</script>
|
||||
```
|
||||
@@ -872,14 +872,15 @@ export class Nav implements NavOutlet {
|
||||
mode,
|
||||
showGoBack: this.canGoBackSync(enteringView),
|
||||
baseEl: this.el,
|
||||
animationBuilder: this.animation || opts.animationBuilder || config.get('navAnimation'),
|
||||
progressCallback,
|
||||
animated: this.animated && config.getBoolean('animated', true),
|
||||
|
||||
enteringEl,
|
||||
leavingEl,
|
||||
|
||||
...opts
|
||||
...opts,
|
||||
|
||||
animationBuilder: opts.animationBuilder || this.animation || config.get('navAnimation')
|
||||
};
|
||||
const { hasCompleted } = await transition(animationOpts);
|
||||
return this.transitionFinish(hasCompleted, enteringView, leavingView, opts);
|
||||
|
||||
@@ -169,7 +169,7 @@ describe('NavController', () => {
|
||||
|
||||
describe('insert', () => {
|
||||
|
||||
it('should insert at the begining with no async transition', async () => {
|
||||
it('should insert at the beginning with no async transition', async () => {
|
||||
const view4 = mockView(MockView4);
|
||||
const instance4 = spyOnLifecycles(view4);
|
||||
const opts: NavOptions = {};
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
import { JSXBase } from '@stencil/core/internal';
|
||||
|
||||
import { AnimationBuilder, Mode } from '../../interface';
|
||||
|
||||
export interface PickerOptions {
|
||||
@@ -11,11 +13,14 @@ export interface PickerOptions {
|
||||
mode?: Mode;
|
||||
keyboardClose?: boolean;
|
||||
id?: string;
|
||||
htmlAttributes?: PickerAttributes;
|
||||
|
||||
enterAnimation?: AnimationBuilder;
|
||||
leaveAnimation?: AnimationBuilder;
|
||||
}
|
||||
|
||||
export interface PickerAttributes extends JSXBase.HTMLAttributes<HTMLElement> {}
|
||||
|
||||
export interface PickerButton {
|
||||
text?: string;
|
||||
role?: string;
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import { Component, ComponentInterface, Element, Event, EventEmitter, Host, Method, Prop, State, h } from '@stencil/core';
|
||||
|
||||
import { getIonMode } from '../../global/ionic-global';
|
||||
import { AnimationBuilder, CssClassMap, OverlayEventDetail, OverlayInterface, PickerButton, PickerColumn } from '../../interface';
|
||||
import { AnimationBuilder, CssClassMap, OverlayEventDetail, OverlayInterface, PickerAttributes, PickerButton, PickerColumn } from '../../interface';
|
||||
import { BACKDROP, dismiss, eventMethod, isCancel, prepareOverlay, present, safeCall } from '../../utils/overlays';
|
||||
import { getClassMap } from '../../utils/theme';
|
||||
|
||||
@@ -81,6 +81,11 @@ export class Picker implements ComponentInterface, OverlayInterface {
|
||||
*/
|
||||
@Prop() animated = true;
|
||||
|
||||
/**
|
||||
* Additional attributes to pass to the picker.
|
||||
*/
|
||||
@Prop() htmlAttributes?: PickerAttributes;
|
||||
|
||||
/**
|
||||
* Emitted after the picker has presented.
|
||||
*/
|
||||
@@ -213,11 +218,16 @@ export class Picker implements ComponentInterface, OverlayInterface {
|
||||
}
|
||||
|
||||
render() {
|
||||
const { htmlAttributes } = this;
|
||||
const mode = getIonMode(this);
|
||||
return (
|
||||
<Host
|
||||
aria-modal="true"
|
||||
tabindex="-1"
|
||||
{...htmlAttributes as any}
|
||||
style={{
|
||||
zIndex: `${20000 + this.overlayIndex}`
|
||||
}}
|
||||
class={{
|
||||
[mode]: true,
|
||||
|
||||
@@ -226,9 +236,6 @@ export class Picker implements ComponentInterface, OverlayInterface {
|
||||
|
||||
...getClassMap(this.cssClass)
|
||||
}}
|
||||
style={{
|
||||
zIndex: `${20000 + this.overlayIndex}`
|
||||
}}
|
||||
onIonBackdropTap={this.onBackdropTap}
|
||||
onIonPickerWillDismiss={this.dispatchCancelHandler}
|
||||
>
|
||||
|
||||
@@ -2,7 +2,78 @@
|
||||
|
||||
A Picker is a dialog that displays a row of buttons and columns underneath. It appears on top of the app's content, and at the bottom of the viewport.
|
||||
|
||||
## Interfaces
|
||||
|
||||
### PickerButton
|
||||
|
||||
```typescript
|
||||
interface PickerButton {
|
||||
text?: string;
|
||||
role?: string;
|
||||
cssClass?: string | string[];
|
||||
handler?: (value: any) => boolean | void;
|
||||
}
|
||||
```
|
||||
|
||||
### PickerColumn
|
||||
|
||||
```typescript
|
||||
interface PickerColumn {
|
||||
name: string;
|
||||
align?: string;
|
||||
selectedIndex?: number;
|
||||
prevSelected?: number;
|
||||
prefix?: string;
|
||||
suffix?: string;
|
||||
options: PickerColumnOption[];
|
||||
cssClass?: string | string[];
|
||||
columnWidth?: string;
|
||||
prefixWidth?: string;
|
||||
suffixWidth?: string;
|
||||
optionsWidth?: string;
|
||||
refresh?: () => void;
|
||||
}
|
||||
```
|
||||
|
||||
### PickerColumnOption
|
||||
|
||||
```typescript
|
||||
interface PickerColumnOption {
|
||||
text?: string;
|
||||
value?: any;
|
||||
disabled?: boolean;
|
||||
duration?: number;
|
||||
transform?: string;
|
||||
selected?: boolean;
|
||||
}
|
||||
```
|
||||
|
||||
### PickerOptions
|
||||
|
||||
```typescript
|
||||
interface PickerOptions {
|
||||
columns: PickerColumn[];
|
||||
buttons?: PickerButton[];
|
||||
cssClass?: string | string[];
|
||||
showBackdrop?: boolean;
|
||||
backdropDismiss?: boolean;
|
||||
animated?: boolean;
|
||||
|
||||
mode?: Mode;
|
||||
keyboardClose?: boolean;
|
||||
id?: string;
|
||||
htmlAttributes?: PickerAttributes;
|
||||
|
||||
enterAnimation?: AnimationBuilder;
|
||||
leaveAnimation?: AnimationBuilder;
|
||||
}
|
||||
```
|
||||
|
||||
### PickerAttributes
|
||||
|
||||
```typescript
|
||||
interface PickerAttributes extends JSXBase.HTMLAttributes<HTMLElement> {}
|
||||
```
|
||||
|
||||
<!-- Auto Generated Below -->
|
||||
|
||||
@@ -95,6 +166,63 @@ const PickerExample: React.FC = () => {
|
||||
```
|
||||
|
||||
|
||||
### Vue
|
||||
|
||||
```vue
|
||||
<template>
|
||||
<div>
|
||||
<ion-button @click="openPicker">SHOW PICKER</ion-button>
|
||||
<p v-if="picked.animal">picked: {{ picked.animal.text }}</p>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { IonButton, pickerController } from "@ionic/vue";
|
||||
export default {
|
||||
components: {
|
||||
IonButton,
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
pickingOptions: {
|
||||
name: "animal",
|
||||
options: [
|
||||
{ text: "Dog", value: "dog" },
|
||||
{ text: "Cat", value: "cat" },
|
||||
{ text: "Bird", value: "bird" },
|
||||
],
|
||||
},
|
||||
picked: {
|
||||
animal: "",
|
||||
},
|
||||
};
|
||||
},
|
||||
methods: {
|
||||
async openPicker() {
|
||||
const picker = await pickerController.create({
|
||||
columns: [this.pickingOptions],
|
||||
buttons: [
|
||||
{
|
||||
text: "Cancel",
|
||||
role: "cancel",
|
||||
},
|
||||
{
|
||||
text: "Confirm",
|
||||
handler: (value) => {
|
||||
this.picked = value;
|
||||
console.log(`Got Value ${value}`);
|
||||
},
|
||||
},
|
||||
],
|
||||
});
|
||||
await picker.present();
|
||||
},
|
||||
},
|
||||
};
|
||||
</script>
|
||||
```
|
||||
|
||||
|
||||
|
||||
## Properties
|
||||
|
||||
@@ -107,6 +235,7 @@ const PickerExample: React.FC = () => {
|
||||
| `cssClass` | `css-class` | Additional classes to apply for custom CSS. If multiple classes are provided they should be separated by spaces. | `string \| string[] \| undefined` | `undefined` |
|
||||
| `duration` | `duration` | Number of milliseconds to wait before dismissing the picker. | `number` | `0` |
|
||||
| `enterAnimation` | -- | Animation to use when the picker is presented. | `((baseEl: any, opts?: any) => Animation) \| undefined` | `undefined` |
|
||||
| `htmlAttributes` | -- | Additional attributes to pass to the picker. | `PickerAttributes \| undefined` | `undefined` |
|
||||
| `keyboardClose` | `keyboard-close` | If `true`, the keyboard will be automatically dismissed when the overlay is presented. | `boolean` | `true` |
|
||||
| `leaveAnimation` | -- | Animation to use when the picker is dismissed. | `((baseEl: any, opts?: any) => Animation) \| undefined` | `undefined` |
|
||||
| `mode` | `mode` | The mode determines which platform styles to use. | `"ios" \| "md"` | `undefined` |
|
||||
|
||||
@@ -115,6 +115,9 @@
|
||||
value: '12'
|
||||
}]
|
||||
}],
|
||||
htmlAttributes: {
|
||||
'data-testid': 'basic-picker'
|
||||
}
|
||||
cssClass: customClass
|
||||
});
|
||||
|
||||
|
||||
53
core/src/components/picker/usage/vue.md
Normal file
53
core/src/components/picker/usage/vue.md
Normal file
@@ -0,0 +1,53 @@
|
||||
```vue
|
||||
<template>
|
||||
<div>
|
||||
<ion-button @click="openPicker">SHOW PICKER</ion-button>
|
||||
<p v-if="picked.animal">picked: {{ picked.animal.text }}</p>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { IonButton, pickerController } from "@ionic/vue";
|
||||
export default {
|
||||
components: {
|
||||
IonButton,
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
pickingOptions: {
|
||||
name: "animal",
|
||||
options: [
|
||||
{ text: "Dog", value: "dog" },
|
||||
{ text: "Cat", value: "cat" },
|
||||
{ text: "Bird", value: "bird" },
|
||||
],
|
||||
},
|
||||
picked: {
|
||||
animal: "",
|
||||
},
|
||||
};
|
||||
},
|
||||
methods: {
|
||||
async openPicker() {
|
||||
const picker = await pickerController.create({
|
||||
columns: [this.pickingOptions],
|
||||
buttons: [
|
||||
{
|
||||
text: "Cancel",
|
||||
role: "cancel",
|
||||
},
|
||||
{
|
||||
text: "Confirm",
|
||||
handler: (value) => {
|
||||
this.picked = value;
|
||||
console.log(`Got Value ${value}`);
|
||||
},
|
||||
},
|
||||
],
|
||||
});
|
||||
await picker.present();
|
||||
},
|
||||
},
|
||||
};
|
||||
</script>
|
||||
```
|
||||
@@ -1,3 +1,5 @@
|
||||
import { JSXBase } from '@stencil/core/internal';
|
||||
|
||||
import { AnimationBuilder, ComponentProps, ComponentRef, FrameworkDelegate, Mode } from '../../interface';
|
||||
|
||||
export interface PopoverOptions<T extends ComponentRef = ComponentRef> {
|
||||
@@ -14,7 +16,10 @@ export interface PopoverOptions<T extends ComponentRef = ComponentRef> {
|
||||
mode?: Mode;
|
||||
keyboardClose?: boolean;
|
||||
id?: string;
|
||||
htmlAttributes?: PopoverAttributes;
|
||||
|
||||
enterAnimation?: AnimationBuilder;
|
||||
leaveAnimation?: AnimationBuilder;
|
||||
}
|
||||
|
||||
export interface PopoverAttributes extends JSXBase.HTMLAttributes<HTMLElement> {}
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import { Component, ComponentInterface, Element, Event, EventEmitter, Host, Method, Prop, h } from '@stencil/core';
|
||||
|
||||
import { getIonMode } from '../../global/ionic-global';
|
||||
import { AnimationBuilder, ComponentProps, ComponentRef, FrameworkDelegate, OverlayEventDetail, OverlayInterface } from '../../interface';
|
||||
import { AnimationBuilder, ComponentProps, ComponentRef, FrameworkDelegate, OverlayEventDetail, OverlayInterface, PopoverAttributes } from '../../interface';
|
||||
import { attachComponent, detachComponent } from '../../utils/framework-delegate';
|
||||
import { BACKDROP, dismiss, eventMethod, prepareOverlay, present } from '../../utils/overlays';
|
||||
import { getClassMap } from '../../utils/theme';
|
||||
@@ -96,6 +96,11 @@ export class Popover implements ComponentInterface, OverlayInterface {
|
||||
*/
|
||||
@Prop() animated = true;
|
||||
|
||||
/**
|
||||
* Additional attributes to pass to the popover.
|
||||
*/
|
||||
@Prop() htmlAttributes?: PopoverAttributes;
|
||||
|
||||
/**
|
||||
* Emitted after the popover has presented.
|
||||
*/
|
||||
@@ -198,12 +203,13 @@ export class Popover implements ComponentInterface, OverlayInterface {
|
||||
|
||||
render() {
|
||||
const mode = getIonMode(this);
|
||||
const { onLifecycle } = this;
|
||||
const { onLifecycle, htmlAttributes } = this;
|
||||
return (
|
||||
<Host
|
||||
aria-modal="true"
|
||||
no-router
|
||||
tabindex="-1"
|
||||
{...htmlAttributes as any}
|
||||
style={{
|
||||
zIndex: `${20000 + this.overlayIndex}`,
|
||||
}}
|
||||
|
||||
@@ -34,6 +34,36 @@ Any of the defined [CSS Custom Properties](#css-custom-properties) can be used t
|
||||
|
||||
> If you are building an Ionic Angular app, the styles need to be added to a global stylesheet file. Read [Style Placement](#style-placement) in the Angular section below for more information.
|
||||
|
||||
## Interfaces
|
||||
|
||||
### PopoverOptions
|
||||
|
||||
```typescript
|
||||
interface PopoverOptions {
|
||||
component: any;
|
||||
componentProps?: { [key: string]: any };
|
||||
showBackdrop?: boolean;
|
||||
backdropDismiss?: boolean;
|
||||
translucent?: boolean;
|
||||
cssClass?: string | string[];
|
||||
event?: Event;
|
||||
animated?: boolean;
|
||||
|
||||
mode?: 'ios' | 'md';
|
||||
keyboardClose?: boolean;
|
||||
id?: string;
|
||||
htmlAttributes?: PopoverAttributes;
|
||||
|
||||
enterAnimation?: AnimationBuilder;
|
||||
leaveAnimation?: AnimationBuilder;
|
||||
}
|
||||
```
|
||||
|
||||
### PopoverAttributes
|
||||
|
||||
```typescript
|
||||
interface PopoverAttributes extends JSXBase.HTMLAttributes<HTMLElement> {}
|
||||
```
|
||||
|
||||
<!-- Auto Generated Below -->
|
||||
|
||||
@@ -346,8 +376,8 @@ export default defineComponent({
|
||||
setup() {
|
||||
const isOpenRef = ref(false);
|
||||
const event = ref();
|
||||
const setOpen = (state: boolean, event?: Event) => {
|
||||
event.value = event;
|
||||
const setOpen = (state: boolean, ev?: Event) => {
|
||||
event.value = ev;
|
||||
isOpenRef.value = state;
|
||||
}
|
||||
return { isOpenRef, setOpen, event }
|
||||
@@ -369,6 +399,7 @@ export default defineComponent({
|
||||
| `cssClass` | `css-class` | Additional classes to apply for custom CSS. If multiple classes are provided they should be separated by spaces. | `string \| string[] \| undefined` | `undefined` |
|
||||
| `enterAnimation` | -- | Animation to use when the popover is presented. | `((baseEl: any, opts?: any) => Animation) \| undefined` | `undefined` |
|
||||
| `event` | `event` | The event to pass to the popover animation. | `any` | `undefined` |
|
||||
| `htmlAttributes` | -- | Additional attributes to pass to the popover. | `PopoverAttributes \| undefined` | `undefined` |
|
||||
| `keyboardClose` | `keyboard-close` | If `true`, the keyboard will be automatically dismissed when the overlay is presented. | `boolean` | `true` |
|
||||
| `leaveAnimation` | -- | Animation to use when the popover is dismissed. | `((baseEl: any, opts?: any) => Animation) \| undefined` | `undefined` |
|
||||
| `mode` | `mode` | The mode determines which platform styles to use. | `"ios" \| "md"` | `undefined` |
|
||||
|
||||
@@ -80,3 +80,19 @@ test('popover:rtl: no event', async () => {
|
||||
test('popover:rtl: custom class', async () => {
|
||||
await testPopover(DIRECTORY, '#custom-class-popover', true);
|
||||
});
|
||||
|
||||
test('popover: htmlAttributes', async () => {
|
||||
const page = await newE2EPage({ url: '/src/components/popover/test/basic?ionic:_testing=true' });
|
||||
|
||||
await page.click('#basic-popover');
|
||||
await page.waitForSelector('#basic-popover');
|
||||
|
||||
let alert = await page.find('ion-popover');
|
||||
|
||||
expect(alert).not.toBe(null);
|
||||
await alert.waitForVisible();
|
||||
|
||||
const attribute = await page.evaluate((el) => document.querySelector('ion-popover').getAttribute('data-testid'));
|
||||
|
||||
expect(attribute).toEqual('basic-popover');
|
||||
});
|
||||
|
||||
@@ -29,7 +29,7 @@
|
||||
</ion-header>
|
||||
|
||||
<ion-content class="ion-padding" id="content">
|
||||
<ion-button id="basic-popover" expand="block" onclick="presentPopover({ component: 'profile-page', event: event })">Show Popover</ion-button>
|
||||
<ion-button id="basic-popover" expand="block" onclick="presentPopover({ component: 'profile-page', event: event, htmlAttributes: { 'data-testid': 'basic-popover' } })">Show Popover</ion-button>
|
||||
<ion-button id="translucent-popover" expand="block" onclick="presentPopover({ component: 'translucent-page', event: event, translucent: true })">Show Translucent Popover</ion-button>
|
||||
<ion-button id="long-list-popover" expand="block" color="secondary" onclick="presentPopover({ component: 'list-page', event: event })">Show Long List Popover</ion-button>
|
||||
<ion-button id="no-event-popover" expand="block" color="danger" onclick="presentPopover({ component: 'profile-page' })">No Event Popover</ion-button>
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user