mirror of
https://github.com/ionic-team/ionic-framework.git
synced 2026-03-13 10:22:08 +08:00
Compare commits
44 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
fdfe0b10d7 | ||
|
|
b839e6fd97 | ||
|
|
eb3cbe45a7 | ||
|
|
6fbb90896b | ||
|
|
73e2123ce8 | ||
|
|
70db7080b1 | ||
|
|
9e63947e3c | ||
|
|
0dd2f34dfa | ||
|
|
07e739a364 | ||
|
|
e5c8c10029 | ||
|
|
38ae3620a2 | ||
|
|
72be80cb58 | ||
|
|
cc60b60135 | ||
|
|
447497427e | ||
|
|
18b347b4e9 | ||
|
|
29bb4fcb05 | ||
|
|
11aa48c83c | ||
|
|
f13722cc20 | ||
|
|
983382c327 | ||
|
|
1b16e1f378 | ||
|
|
494991e9fb | ||
|
|
1199c53437 | ||
|
|
6e1a8f1df2 | ||
|
|
52e5a8d3e3 | ||
|
|
0d17e05edc | ||
|
|
fa1317359a | ||
|
|
d87170db3a | ||
|
|
5756789b42 | ||
|
|
b081ca4dd0 | ||
|
|
77c980b032 | ||
|
|
05eb5ddaf8 | ||
|
|
9de09bd4f5 | ||
|
|
2f34f52536 | ||
|
|
ec3e19e66c | ||
|
|
a512287e4b | ||
|
|
48814ab134 | ||
|
|
28249924a8 | ||
|
|
e620d813b3 | ||
|
|
0db905a871 | ||
|
|
c87e26131a | ||
|
|
06c4233a54 | ||
|
|
9585723dda | ||
|
|
046ca8f732 | ||
|
|
fdd2978774 |
2
.github/ISSUE_TEMPLATE/bug_report.md
vendored
2
.github/ISSUE_TEMPLATE/bug_report.md
vendored
@@ -1,7 +1,7 @@
|
||||
---
|
||||
name: Bug Report
|
||||
about: Create a report to help us improve
|
||||
title: ''
|
||||
title: 'bug: '
|
||||
labels: ''
|
||||
assignees: ''
|
||||
---
|
||||
|
||||
2
.github/ISSUE_TEMPLATE/feature_request.md
vendored
2
.github/ISSUE_TEMPLATE/feature_request.md
vendored
@@ -1,7 +1,7 @@
|
||||
---
|
||||
name: Feature Request
|
||||
about: Suggest an idea for this project
|
||||
title: ''
|
||||
title: 'feat: '
|
||||
labels: ''
|
||||
assignees: ''
|
||||
---
|
||||
|
||||
2
.github/ISSUE_TEMPLATE/support_question.md
vendored
2
.github/ISSUE_TEMPLATE/support_question.md
vendored
@@ -1,7 +1,7 @@
|
||||
---
|
||||
name: Support Question
|
||||
about: Question on how to use this project
|
||||
title: ''
|
||||
title: 'support: '
|
||||
labels: 'ionitron: support'
|
||||
assignees: ''
|
||||
---
|
||||
|
||||
18
.github/PROCESS.md
vendored
18
.github/PROCESS.md
vendored
@@ -140,6 +140,14 @@ Once the release is ready to ship, it will get merged into `stable` and `master`
|
||||
|
||||
See the [steps for releasing](#releasing) below for detailed information on how to publish a release.
|
||||
|
||||
### Version Branches
|
||||
|
||||
Once a release has shipped and the release branch has been merged into `stable` and `master` it should also be merged into its corrsponding version branch. These version branches allow us to ship updates for specific versions of the framework (i.e. Lets us ship a bug fix that only affects 4.2.x).
|
||||
|
||||
Patch releases should be merged into their corresponding version branches. For example, a `release-4.1.1` branch should be merged into the `4.1.x` version branch and a `release-5.0.1` branch should be merged into the `5.0.x` version branch.
|
||||
|
||||
When releasing a major version such as `5.0.0 ` or a minor version such as `4.1.0` , the version branch will not exist. The version branch should be created once the release branch has been merged into `stable` and `master`. For example, when releasing `4.1.0`, the `release-4.1.0` release branch should be merged into `stable` and `master` and then the `4.1.x` version branch should be created off the latest `stable`.
|
||||
|
||||
|
||||
### Hotfix Branches
|
||||
|
||||
@@ -214,19 +222,29 @@ Hotfixes bypass `master` and should only be used for urgent fixes that can't wai
|
||||
## Releasing
|
||||
|
||||
1. Create the release branch from `master`, for example: `release-4.1.0`.
|
||||
|
||||
1. Submit a pull request from the release branch into `stable`. Do not merge this pull request yet.
|
||||
|
||||
1. Verify all tests are passing, fix any bugs if needed and make sure no undesired commits are in.
|
||||
|
||||
1. Navigate to the root of the repository while on the release branch.
|
||||
|
||||
1. Run `npm i` if it hasn't already been done.
|
||||
|
||||
1. Run `npm run release.prepare`
|
||||
- Select the version based on the type of commits and the [Ionic Versioning](https://ionicframework.com/docs/intro/versioning)
|
||||
- After the process completes, verify the version number in all packages (`core`, `docs`, `angular`)
|
||||
- Verify the changelog commits are accurate and follow the [proper format]((https://github.com/ionic-team/ionic/blob/master/.github/CONTRIBUTING.md#commit-message-format))
|
||||
- Commit these changes with the version number as the message, e.g. `git commit -m "4.1.0"`
|
||||
|
||||
1. Run `npm run release`
|
||||
|
||||
1. Click **Merge pull request**. Use the dropdown to select this option if necessary.
|
||||
|
||||
<img width="191" alt="Merge pull request button" src="https://user-images.githubusercontent.com/236501/47032669-8be1b980-d138-11e8-9a90-d1518c223184.png">
|
||||
|
||||
1. Rewrite the commit message to `merge release-4.1.0` with the proper release branch.
|
||||
|
||||
1. Create a pull request and merge the release branch back into `master` using the same commit format in the last step, to ensure any changes made on the release branch get added to future releases.
|
||||
|
||||
1. Merge the release branch into its corresponding version branch. If this is a major or minor release, create the version branch off the latest `stable`.
|
||||
|
||||
47
.github/PULL_REQUEST_TEMPLATE.md
vendored
47
.github/PULL_REQUEST_TEMPLATE.md
vendored
@@ -1,12 +1,51 @@
|
||||
#### Short description of what this resolves:
|
||||
<!-- Please refer to our contributing documentation for any questions on submitting a pull request, or let us know here if you need any help: https://ionicframework.com/docs/building/contributing -->
|
||||
|
||||
## Pull request checklist
|
||||
|
||||
Please check if your PR fulfills the following requirements:
|
||||
- [ ] Tests for the changes have been added (for bug fixes / features)
|
||||
- [ ] Docs have been reviewed and added / updated if needed (for bug fixes / features)
|
||||
- [ ] Build (`npm run build`) was run locally and any changes were pushed
|
||||
- [ ] Lint (`npm run lint`) has passed locally and any fixes were made for failures
|
||||
|
||||
|
||||
#### Changes proposed in this pull request:
|
||||
## Pull request type
|
||||
|
||||
<!-- Please do not submit updates to dependencies unless it fixes an issue. -->
|
||||
|
||||
<!-- Please try to limit your pull request to one type, submit multiple pull requests if needed. -->
|
||||
|
||||
Please check the type of change your PR introduces:
|
||||
- [ ] Bugfix
|
||||
- [ ] Feature
|
||||
- [ ] Code style update (formatting, renaming)
|
||||
- [ ] Refactoring (no functional changes, no api changes)
|
||||
- [ ] Build related changes
|
||||
- [ ] Documentation content changes
|
||||
- [ ] Other (please describe):
|
||||
|
||||
|
||||
## What is the current behavior?
|
||||
<!-- Please describe the current behavior that you are modifying, or link to a relevant issue. -->
|
||||
|
||||
Issue Number: N/A
|
||||
|
||||
|
||||
## What is the new behavior?
|
||||
<!-- Please describe the behavior or changes that are being added by this PR. -->
|
||||
|
||||
-
|
||||
-
|
||||
-
|
||||
|
||||
**Ionic Version**:
|
||||
## Does this introduce a breaking change?
|
||||
|
||||
**Fixes**: #
|
||||
- [ ] Yes
|
||||
- [ ] No
|
||||
|
||||
<!-- If this introduces a breaking change, please describe the impact and migration path for existing applications below. -->
|
||||
|
||||
|
||||
## Other information
|
||||
|
||||
<!-- Any other information that is important to this PR such as screenshots of how the component looks before and after the change. -->
|
||||
|
||||
9
.github/ionic-issue-bot.yml
vendored
9
.github/ionic-issue-bot.yml
vendored
@@ -118,6 +118,15 @@ labelPullRequest:
|
||||
|
||||
wrongRepo:
|
||||
repos:
|
||||
- label: "ionitron: capacitor"
|
||||
repo: capacitor
|
||||
message: >
|
||||
Thanks for the issue! We use this issue tracker exclusively for bug reports and feature requests
|
||||
associated with the Ionic Framework. It appears that this issue is associated with Capacitor.
|
||||
I am moving this issue to the Capacitor repository. Please track this issue over there.
|
||||
|
||||
|
||||
Thank you for using Ionic!
|
||||
- label: "ionitron: v3"
|
||||
repo: ionic-v3
|
||||
message: >
|
||||
|
||||
38
CHANGELOG.md
38
CHANGELOG.md
@@ -1,4 +1,40 @@
|
||||
# [4.2.0](https://github.com/ionic-team/ionic/compare/v4.1.2...v4.2.0) (2019-04-03)
|
||||
## [4.3.1](https://github.com/ionic-team/ionic/compare/v4.3.0...v4.3.1) (2019-04-26)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* **angular:** support replaceUrl with angular <7.2 ([#18106](https://github.com/ionic-team/ionic/issues/18106)) ([eb3cbe4](https://github.com/ionic-team/ionic/commit/eb3cbe4))
|
||||
* sanitize components using innerHTML ([#18146](https://github.com/ionic-team/ionic/issues/18146)) ([b839e6f](https://github.com/ionic-team/ionic/commit/b839e6f))
|
||||
|
||||
|
||||
|
||||
# [4.3.0 Lithium](https://github.com/ionic-team/ionic/compare/v4.2.0...v4.3.0) (2019-04-17)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* **action-sheet:** default buttons to empty array ([9e63947](https://github.com/ionic-team/ionic/commit/9e63947))
|
||||
* **angular:** back button correctly goes back to proper tab ([#18005](https://github.com/ionic-team/ionic/issues/18005)) ([52e5a8d](https://github.com/ionic-team/ionic/commit/52e5a8d)), closes [#17278](https://github.com/ionic-team/ionic/issues/17278) [#15216](https://github.com/ionic-team/ionic/issues/15216)
|
||||
* **components:** add mode classes to components for use in shadow elements ([#17838](https://github.com/ionic-team/ionic/issues/17838)) ([e5c8c10](https://github.com/ionic-team/ionic/commit/e5c8c10)), closes [#17608](https://github.com/ionic-team/ionic/issues/17608)
|
||||
* **datetime:** date strings no longer revert to previous day ([#18018](https://github.com/ionic-team/ionic/issues/18018)) ([cc60b60](https://github.com/ionic-team/ionic/commit/cc60b60)), closes [#17977](https://github.com/ionic-team/ionic/issues/17977)
|
||||
* **input:** prevent input from losing focus when tapping clear button ([#18004](https://github.com/ionic-team/ionic/issues/18004)) ([29bb4fc](https://github.com/ionic-team/ionic/commit/29bb4fc)), closes [#18002](https://github.com/ionic-team/ionic/issues/18002)
|
||||
* **item:** use the correct input highlight for an inset line item ([#18052](https://github.com/ionic-team/ionic/issues/18052)) ([72be80c](https://github.com/ionic-team/ionic/commit/72be80c)), closes [#18051](https://github.com/ionic-team/ionic/issues/18051)
|
||||
* **item-sliding:** hide closed side options while dragging side options open ([#17986](https://github.com/ionic-team/ionic/issues/17986)) ([f13722c](https://github.com/ionic-team/ionic/commit/f13722c)), closes [#17822](https://github.com/ionic-team/ionic/issues/17822)
|
||||
* **slides:** allow zoom to work ([18b347b](https://github.com/ionic-team/ionic/commit/18b347b)), closes [#17981](https://github.com/ionic-team/ionic/issues/17981)
|
||||
* **slides:** expose interface to provide custom animations ([#17959](https://github.com/ionic-team/ionic/issues/17959)) ([4474974](https://github.com/ionic-team/ionic/commit/4474974)), closes [#16616](https://github.com/ionic-team/ionic/issues/16616)
|
||||
* **textarea:** float label when a value is changed async ([#18024](https://github.com/ionic-team/ionic/issues/18024)) ([494991e](https://github.com/ionic-team/ionic/commit/494991e)), closes [#17555](https://github.com/ionic-team/ionic/issues/17555) [#17559](https://github.com/ionic-team/ionic/issues/17559)
|
||||
* **textarea:** update label alignment for inputs and textareas ([#18042](https://github.com/ionic-team/ionic/issues/18042)) ([38ae362](https://github.com/ionic-team/ionic/commit/38ae362)), closes [#16187](https://github.com/ionic-team/ionic/issues/16187)
|
||||
* **vue:** use direction type from core ([#17901](https://github.com/ionic-team/ionic/issues/17901)) ([fa13173](https://github.com/ionic-team/ionic/commit/fa13173))
|
||||
|
||||
|
||||
### Features
|
||||
|
||||
* **toast:** add header and additional custom toast buttons ([#17147](https://github.com/ionic-team/ionic/issues/17147)) ([6e1a8f1](https://github.com/ionic-team/ionic/commit/6e1a8f1)), closes [#16791](https://github.com/ionic-team/ionic/issues/16791) [#16237](https://github.com/ionic-team/ionic/issues/16237) [#17611](https://github.com/ionic-team/ionic/issues/17611)
|
||||
* **toast:** add variables to change position start/end of toast ([#17961](https://github.com/ionic-team/ionic/issues/17961)) ([07e739a](https://github.com/ionic-team/ionic/commit/07e739a)), closes [#17854](https://github.com/ionic-team/ionic/issues/17854)
|
||||
|
||||
|
||||
|
||||
# [4.2.0 Helium](https://github.com/ionic-team/ionic/compare/v4.1.2...v4.2.0) (2019-04-03)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
@@ -182,13 +182,14 @@ These have been renamed to the following, and moved from the button element to t
|
||||
|
||||
In addition, several sets of mutually exclusive boolean attributes have been combined into a single string attribute.
|
||||
|
||||
The `small` and `large` attributes are now combined under the `size` attribute. The `clear`, `outline`, and `solid` attributes have been combined under `fill`. And, lastly, the `full` and `block` attributes have been combined under `expand`.
|
||||
The `small` and `large` attributes are now combined under the `size` attribute. The `clear`, `outline`, and `solid` attributes have been combined under `fill`. The `full` and `block` attributes have been combined under `expand`. And, lastly, the `round` attribute is now used under `shape`.
|
||||
|
||||
| Old Property | New Property | Property Behavior |
|
||||
| --------------------------- | ------------ | --------------------------- |
|
||||
| `small`, `large` | `size` | Sets the button size. |
|
||||
| `clear`, `outline`, `solid` | `fill` | Sets the button fill style. |
|
||||
| `full`, `block` | `expand` | Sets the button width. |
|
||||
| `round` | `shape` | Sets the button shape. |
|
||||
|
||||
|
||||
**Old Usage Example:**
|
||||
@@ -225,6 +226,10 @@ The `small` and `large` attributes are now combined under the `size` attribute.
|
||||
<ion-button full>
|
||||
Full-width Button
|
||||
</ion-button>
|
||||
|
||||
<ion-button round>
|
||||
Round Button
|
||||
</ion-button>
|
||||
```
|
||||
|
||||
**New Usage Example:**
|
||||
@@ -251,6 +256,10 @@ The `small` and `large` attributes are now combined under the `size` attribute.
|
||||
<ion-button expand="full">
|
||||
Full-width Button
|
||||
</ion-button>
|
||||
|
||||
<ion-button shape="round">
|
||||
Round Button
|
||||
</ion-button>
|
||||
```
|
||||
|
||||
|
||||
@@ -1065,11 +1074,11 @@ async openLoading() {
|
||||
let loading = this.loadingCtrl.create({
|
||||
content: 'Loading...'
|
||||
});
|
||||
|
||||
|
||||
await loading.present();
|
||||
|
||||
|
||||
const { role, data } = await loading.onDidDismiss();
|
||||
|
||||
|
||||
console.log('Loading dismissed!');
|
||||
}
|
||||
```
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@ionic/angular",
|
||||
"version": "4.2.0",
|
||||
"version": "4.3.1",
|
||||
"description": "Angular specific wrappers for @ionic/core",
|
||||
"keywords": [
|
||||
"ionic",
|
||||
@@ -45,7 +45,7 @@
|
||||
"css/"
|
||||
],
|
||||
"dependencies": {
|
||||
"@ionic/core": "4.2.0",
|
||||
"@ionic/core": "4.3.1",
|
||||
"tslib": "^1.9.3"
|
||||
},
|
||||
"peerDependencies": {
|
||||
|
||||
@@ -59,7 +59,22 @@ export class StackController {
|
||||
}
|
||||
const viewsSnapshot = this.views.slice();
|
||||
|
||||
const currentNavigation = this.router.getCurrentNavigation();
|
||||
let currentNavigation;
|
||||
|
||||
const router = (this.router as any);
|
||||
|
||||
// Angular >= 7.2.0
|
||||
if (router.getCurrentNavigation) {
|
||||
currentNavigation = router.getCurrentNavigation();
|
||||
|
||||
// Angular < 7.2.0
|
||||
} else if (
|
||||
router.navigations &&
|
||||
router.navigations.value
|
||||
) {
|
||||
currentNavigation = router.navigations.value;
|
||||
}
|
||||
|
||||
/**
|
||||
* If the navigation action
|
||||
* sets `replaceUrl: true`
|
||||
@@ -101,7 +116,23 @@ export class StackController {
|
||||
return Promise.resolve(false);
|
||||
}
|
||||
const view = views[views.length - deep - 1];
|
||||
return this.navCtrl.navigateBack(view.url).then(() => true);
|
||||
let url = view.url;
|
||||
|
||||
const viewSavedData = view.savedData;
|
||||
if (viewSavedData) {
|
||||
const primaryOutlet = viewSavedData.get('primary');
|
||||
if (
|
||||
primaryOutlet &&
|
||||
primaryOutlet.route &&
|
||||
primaryOutlet.route._routerState &&
|
||||
primaryOutlet.route._routerState.snapshot &&
|
||||
primaryOutlet.route._routerState.snapshot.url
|
||||
) {
|
||||
url = primaryOutlet.route._routerState.snapshot.url;
|
||||
}
|
||||
}
|
||||
|
||||
return this.navCtrl.navigateBack(url).then(() => true);
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
@@ -130,6 +130,25 @@ describe('tabs', () => {
|
||||
expect(await tab.$('ion-back-button').isDisplayed()).toBe(false);
|
||||
});
|
||||
});
|
||||
|
||||
describe('enter url - /tabs/contact/one', () => {
|
||||
beforeEach(async () => {
|
||||
await browser.get('/tabs/contact/one');
|
||||
});
|
||||
|
||||
it('should return to correct tab after going to page in different outlet', async () => {
|
||||
const tab = await getSelectedTab();
|
||||
await tab.$('#goto-nested-page1').click();
|
||||
|
||||
await testStack('app-nested-outlet ion-router-outlet', ['app-nested-outlet-page']);
|
||||
|
||||
const nestedOutlet = await element(by.css('app-nested-outlet'));
|
||||
const backButton = await nestedOutlet.$('ion-back-button');
|
||||
await backButton.click();
|
||||
|
||||
await testTabTitle('Tab 2 - Page 1');
|
||||
});
|
||||
})
|
||||
});
|
||||
|
||||
async function testState(count: number, tab: string) {
|
||||
|
||||
@@ -1,5 +1,8 @@
|
||||
<ion-header>
|
||||
<ion-toolbar>
|
||||
<ion-buttons slot="start">
|
||||
<ion-back-button></ion-back-button>
|
||||
</ion-buttons>
|
||||
<ion-title>
|
||||
NESTED OUTLET
|
||||
</ion-title>
|
||||
|
||||
@@ -9,5 +9,6 @@
|
||||
<p>
|
||||
<ion-button routerLink="/tabs/account" id="goto-tab1-page1">Go to Tab 1 - Page 1</ion-button>
|
||||
<ion-button routerLink="/tabs/account/nested/12" id="goto-tab1-page2">Go to Tab 1 - Page 2</ion-button>
|
||||
<ion-button routerLink="/nested-outlet/page" id="goto-nested-page1">Go to nested</ion-button>
|
||||
</p>
|
||||
</ion-content>
|
||||
|
||||
@@ -23,8 +23,8 @@ The Ionic Core package contains the Web Components that make up the reusable UI
|
||||
Easiest way to start using Ionic Core is by adding a script tag to the CDN:
|
||||
|
||||
```html
|
||||
<link href="https://unpkg.com/@ionic/core@4.2.0/css/ionic.bundle.css" rel="stylesheet">
|
||||
<script src="https://unpkg.com/@ionic/core@4.2.0/dist/ionic.js"></script>
|
||||
<link href="https://unpkg.com/@ionic/core@4.3.1/css/ionic.bundle.css" rel="stylesheet">
|
||||
<script src="https://unpkg.com/@ionic/core@4.3.1/dist/ionic.js"></script>
|
||||
```
|
||||
|
||||
Any Ionic component added to the webpage will automatically load. This includes writing the component tag directly in HTML, or using JavaScript such as `document.createElement('ion-toggle')`.
|
||||
|
||||
@@ -7,7 +7,7 @@ ion-action-sheet-controller,method,getTop,getTop() => Promise<HTMLIonActionSheet
|
||||
ion-action-sheet,scoped
|
||||
ion-action-sheet,prop,animated,boolean,true,false,false
|
||||
ion-action-sheet,prop,backdropDismiss,boolean,true,false,false
|
||||
ion-action-sheet,prop,buttons,(string | ActionSheetButton)[],undefined,true,false
|
||||
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,((Animation: Animation, baseEl: any, opts?: any) => Promise<Animation>) | undefined,undefined,false,false
|
||||
ion-action-sheet,prop,header,string | undefined,undefined,false,false
|
||||
@@ -1135,11 +1135,13 @@ ion-toast-controller,method,getTop,getTop() => Promise<HTMLIonToastElement | und
|
||||
|
||||
ion-toast,shadow
|
||||
ion-toast,prop,animated,boolean,true,false,false
|
||||
ion-toast,prop,buttons,(string | ToastButton)[] | undefined,undefined,false,false
|
||||
ion-toast,prop,closeButtonText,string | undefined,undefined,false,false
|
||||
ion-toast,prop,color,string | undefined,undefined,false,false
|
||||
ion-toast,prop,cssClass,string | string[] | undefined,undefined,false,false
|
||||
ion-toast,prop,duration,number,0,false,false
|
||||
ion-toast,prop,enterAnimation,((Animation: Animation, baseEl: any, opts?: any) => Promise<Animation>) | undefined,undefined,false,false
|
||||
ion-toast,prop,header,string | undefined,undefined,false,false
|
||||
ion-toast,prop,keyboardClose,boolean,false,false,false
|
||||
ion-toast,prop,leaveAnimation,((Animation: Animation, baseEl: any, opts?: any) => Promise<Animation>) | undefined,undefined,false,false
|
||||
ion-toast,prop,message,string | undefined,undefined,false,false
|
||||
@@ -1163,11 +1165,13 @@ ion-toast,css-prop,--border-width
|
||||
ion-toast,css-prop,--box-shadow
|
||||
ion-toast,css-prop,--button-color
|
||||
ion-toast,css-prop,--color
|
||||
ion-toast,css-prop,--end
|
||||
ion-toast,css-prop,--height
|
||||
ion-toast,css-prop,--max-height
|
||||
ion-toast,css-prop,--max-width
|
||||
ion-toast,css-prop,--min-height
|
||||
ion-toast,css-prop,--min-width
|
||||
ion-toast,css-prop,--start
|
||||
ion-toast,css-prop,--width
|
||||
|
||||
ion-toggle,shadow
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@ionic/core",
|
||||
"version": "4.2.0",
|
||||
"version": "4.3.1",
|
||||
"description": "Base components for Ionic",
|
||||
"keywords": [
|
||||
"ionic",
|
||||
@@ -30,7 +30,7 @@
|
||||
"loader/"
|
||||
],
|
||||
"dependencies": {
|
||||
"ionicons": "4.5.5"
|
||||
"ionicons": "4.5.6"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@stencil/core": "0.17.3-0",
|
||||
|
||||
39
core/src/components.d.ts
vendored
39
core/src/components.d.ts
vendored
@@ -68,6 +68,7 @@ import {
|
||||
TabButtonLayout,
|
||||
TextareaChangeEventDetail,
|
||||
TextFieldTypes,
|
||||
ToastButton,
|
||||
ToastOptions,
|
||||
ToggleChangeEventDetail,
|
||||
TransitionDoneFn,
|
||||
@@ -175,7 +176,7 @@ export namespace Components {
|
||||
/**
|
||||
* An array of buttons for the action sheet.
|
||||
*/
|
||||
'buttons': (ActionSheetButton | string)[];
|
||||
'buttons'?: (ActionSheetButton | string)[];
|
||||
/**
|
||||
* Additional classes to apply for custom CSS. If multiple classes are provided they should be separated by spaces.
|
||||
*/
|
||||
@@ -284,7 +285,7 @@ export namespace Components {
|
||||
*/
|
||||
'leaveAnimation'?: AnimationBuilder;
|
||||
/**
|
||||
* The main message to be displayed in the alert.
|
||||
* The main message to be displayed in the alert. `message` can accept either plaintext or HTML as a string. To display characters normally reserved for HTML, they must be escaped. For example `<Ionic>` would become `<Ionic>` For more information: [Security Documentation](https://ionicframework.com/docs/faq/security)
|
||||
*/
|
||||
'message'?: string;
|
||||
/**
|
||||
@@ -351,7 +352,7 @@ export namespace Components {
|
||||
*/
|
||||
'leaveAnimation'?: AnimationBuilder;
|
||||
/**
|
||||
* The main message to be displayed in the alert.
|
||||
* The main message to be displayed in the alert. `message` can accept either plaintext or HTML as a string. To display characters normally reserved for HTML, they must be escaped. For example `<Ionic>` would become `<Ionic>` For more information: [Security Documentation](https://ionicframework.com/docs/faq/security)
|
||||
*/
|
||||
'message'?: string;
|
||||
/**
|
||||
@@ -1565,7 +1566,7 @@ export namespace Components {
|
||||
*/
|
||||
'loadingSpinner'?: SpinnerTypes | null;
|
||||
/**
|
||||
* Optional text to display while loading.
|
||||
* Optional text to display while loading. `loadingText` can accept either plaintext or HTML as a string. To display characters normally reserved for HTML, they must be escaped. For example `<Ionic>` would become `<Ionic>` For more information: [Security Documentation](https://ionicframework.com/docs/faq/security)
|
||||
*/
|
||||
'loadingText'?: string;
|
||||
}
|
||||
@@ -1575,7 +1576,7 @@ export namespace Components {
|
||||
*/
|
||||
'loadingSpinner'?: SpinnerTypes | null;
|
||||
/**
|
||||
* Optional text to display while loading.
|
||||
* Optional text to display while loading. `loadingText` can accept either plaintext or HTML as a string. To display characters normally reserved for HTML, they must be escaped. For example `<Ionic>` would become `<Ionic>` For more information: [Security Documentation](https://ionicframework.com/docs/faq/security)
|
||||
*/
|
||||
'loadingText'?: string;
|
||||
}
|
||||
@@ -3417,7 +3418,7 @@ export namespace Components {
|
||||
*/
|
||||
'pullingIcon'?: string | null;
|
||||
/**
|
||||
* The text you want to display when you begin to pull down
|
||||
* The text you want to display when you begin to pull down. `pullingText` can accept either plaintext or HTML as a string. To display characters normally reserved for HTML, they must be escaped. For example `<Ionic>` would become `<Ionic>` For more information: [Security Documentation](https://ionicframework.com/docs/faq/security)
|
||||
*/
|
||||
'pullingText'?: string;
|
||||
/**
|
||||
@@ -3425,7 +3426,7 @@ export namespace Components {
|
||||
*/
|
||||
'refreshingSpinner'?: SpinnerTypes | null;
|
||||
/**
|
||||
* The text you want to display when performing a refresh
|
||||
* The text you want to display when performing a refresh. `refreshingText` can accept either plaintext or HTML as a string. To display characters normally reserved for HTML, they must be escaped. For example `<Ionic>` would become `<Ionic>` For more information: [Security Documentation](https://ionicframework.com/docs/faq/security)
|
||||
*/
|
||||
'refreshingText'?: string;
|
||||
}
|
||||
@@ -3435,7 +3436,7 @@ export namespace Components {
|
||||
*/
|
||||
'pullingIcon'?: string | null;
|
||||
/**
|
||||
* The text you want to display when you begin to pull down
|
||||
* The text you want to display when you begin to pull down. `pullingText` can accept either plaintext or HTML as a string. To display characters normally reserved for HTML, they must be escaped. For example `<Ionic>` would become `<Ionic>` For more information: [Security Documentation](https://ionicframework.com/docs/faq/security)
|
||||
*/
|
||||
'pullingText'?: string;
|
||||
/**
|
||||
@@ -3443,7 +3444,7 @@ export namespace Components {
|
||||
*/
|
||||
'refreshingSpinner'?: SpinnerTypes | null;
|
||||
/**
|
||||
* The text you want to display when performing a refresh
|
||||
* The text you want to display when performing a refresh. `refreshingText` can accept either plaintext or HTML as a string. To display characters normally reserved for HTML, they must be escaped. For example `<Ionic>` would become `<Ionic>` For more information: [Security Documentation](https://ionicframework.com/docs/faq/security)
|
||||
*/
|
||||
'refreshingText'?: string;
|
||||
}
|
||||
@@ -3727,7 +3728,7 @@ export namespace Components {
|
||||
*/
|
||||
'mode': Mode;
|
||||
/**
|
||||
* Set the input's placeholder.
|
||||
* Set the input's placeholder. `placeholder` can accept either plaintext or HTML as a string. To display characters normally reserved for HTML, they must be escaped. For example `<Ionic>` would become `<Ionic>` For more information: [Security Documentation](https://ionicframework.com/docs/faq/security)
|
||||
*/
|
||||
'placeholder': string;
|
||||
/**
|
||||
@@ -3817,7 +3818,7 @@ export namespace Components {
|
||||
*/
|
||||
'onIonInput'?: (event: CustomEvent<KeyboardEvent>) => void;
|
||||
/**
|
||||
* Set the input's placeholder.
|
||||
* Set the input's placeholder. `placeholder` can accept either plaintext or HTML as a string. To display characters normally reserved for HTML, they must be escaped. For example `<Ionic>` would become `<Ionic>` For more information: [Security Documentation](https://ionicframework.com/docs/faq/security)
|
||||
*/
|
||||
'placeholder'?: string;
|
||||
/**
|
||||
@@ -4757,6 +4758,10 @@ export namespace Components {
|
||||
*/
|
||||
'animated': boolean;
|
||||
/**
|
||||
* An array of buttons for the toast.
|
||||
*/
|
||||
'buttons'?: (ToastButton | string)[];
|
||||
/**
|
||||
* Text to display in the close button.
|
||||
*/
|
||||
'closeButtonText'?: string;
|
||||
@@ -4781,6 +4786,10 @@ export namespace Components {
|
||||
*/
|
||||
'enterAnimation'?: AnimationBuilder;
|
||||
/**
|
||||
* Header to be shown in the toast.
|
||||
*/
|
||||
'header'?: string;
|
||||
/**
|
||||
* If `true`, the keyboard will be automatically dismissed when the overlay is presented.
|
||||
*/
|
||||
'keyboardClose': boolean;
|
||||
@@ -4828,6 +4837,10 @@ export namespace Components {
|
||||
*/
|
||||
'animated'?: boolean;
|
||||
/**
|
||||
* An array of buttons for the toast.
|
||||
*/
|
||||
'buttons'?: (ToastButton | string)[];
|
||||
/**
|
||||
* Text to display in the close button.
|
||||
*/
|
||||
'closeButtonText'?: string;
|
||||
@@ -4848,6 +4861,10 @@ export namespace Components {
|
||||
*/
|
||||
'enterAnimation'?: AnimationBuilder;
|
||||
/**
|
||||
* Header to be shown in the toast.
|
||||
*/
|
||||
'header'?: string;
|
||||
/**
|
||||
* If `true`, the keyboard will be automatically dismissed when the overlay is presented.
|
||||
*/
|
||||
'keyboardClose'?: boolean;
|
||||
|
||||
@@ -51,7 +51,7 @@ export class ActionSheet implements ComponentInterface, OverlayInterface {
|
||||
/**
|
||||
* An array of buttons for the action sheet.
|
||||
*/
|
||||
@Prop() buttons!: (ActionSheetButton | string)[];
|
||||
@Prop() buttons: (ActionSheetButton | string)[] = [];
|
||||
|
||||
/**
|
||||
* Additional classes to apply for custom CSS. If multiple classes are
|
||||
@@ -196,6 +196,8 @@ export class ActionSheet implements ComponentInterface, OverlayInterface {
|
||||
zIndex: 20000 + this.overlayIndex,
|
||||
},
|
||||
class: {
|
||||
[`${this.mode}`]: true,
|
||||
|
||||
...getClassMap(this.cssClass),
|
||||
'action-sheet-translucent': this.translucent
|
||||
}
|
||||
|
||||
@@ -257,19 +257,19 @@ export default {
|
||||
|
||||
## Properties
|
||||
|
||||
| Property | Attribute | Description | Type | Default |
|
||||
| ---------------------- | ------------------ | ------------------------------------------------------------------------------------------------------------------------------- | -------------------------------------------------------------------------------------- | ----------- |
|
||||
| `animated` | `animated` | If `true`, the action sheet will animate. | `boolean` | `true` |
|
||||
| `backdropDismiss` | `backdrop-dismiss` | If `true`, the action sheet will be dismissed when the backdrop is clicked. | `boolean` | `true` |
|
||||
| `buttons` _(required)_ | -- | An array of buttons for the action sheet. | `(string \| ActionSheetButton)[]` | `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 action sheet is presented. | `((Animation: Animation, baseEl: any, opts?: any) => Promise<Animation>) \| undefined` | `undefined` |
|
||||
| `header` | `header` | Title for the action sheet. | `string \| 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. | `((Animation: Animation, baseEl: any, opts?: any) => Promise<Animation>) \| undefined` | `undefined` |
|
||||
| `mode` | `mode` | The mode determines which platform styles to use. | `"ios" \| "md"` | `undefined` |
|
||||
| `subHeader` | `sub-header` | Subtitle for the action sheet. | `string \| undefined` | `undefined` |
|
||||
| `translucent` | `translucent` | If `true`, the action sheet will be translucent. Only applies when the mode is `"ios"` and the device supports backdrop-filter. | `boolean` | `false` |
|
||||
| Property | Attribute | Description | Type | Default |
|
||||
| ----------------- | ------------------ | ------------------------------------------------------------------------------------------------------------------------------- | -------------------------------------------------------------------------------------- | ----------- |
|
||||
| `animated` | `animated` | If `true`, the action sheet will animate. | `boolean` | `true` |
|
||||
| `backdropDismiss` | `backdrop-dismiss` | If `true`, the action sheet will be dismissed when the backdrop is clicked. | `boolean` | `true` |
|
||||
| `buttons` | -- | An array of buttons for the action sheet. | `(string \| ActionSheetButton)[]` | `[]` |
|
||||
| `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. | `((Animation: Animation, baseEl: any, opts?: any) => Promise<Animation>) \| undefined` | `undefined` |
|
||||
| `header` | `header` | Title for the action sheet. | `string \| 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. | `((Animation: Animation, baseEl: any, opts?: any) => Promise<Animation>) \| undefined` | `undefined` |
|
||||
| `mode` | `mode` | The mode determines which platform styles to use. | `"ios" \| "md"` | `undefined` |
|
||||
| `subHeader` | `sub-header` | Subtitle for the action sheet. | `string \| undefined` | `undefined` |
|
||||
| `translucent` | `translucent` | If `true`, the action sheet will be translucent. Only applies when the mode is `"ios"` and the device supports backdrop-filter. | `boolean` | `false` |
|
||||
|
||||
|
||||
## Events
|
||||
|
||||
@@ -38,34 +38,34 @@ test('action-sheet: basic, scroll without cancel', async () => {
|
||||
* RTL Tests
|
||||
*/
|
||||
|
||||
test('action-sheet: basic', async () => {
|
||||
test('action-sheet:rtl: basic', async () => {
|
||||
await testActionSheet(DIRECTORY, '#basic', true);
|
||||
});
|
||||
|
||||
test('action-sheet: basic, alert from action sheet', async () => {
|
||||
test('action-sheet:rtl: basic, alert from action sheet', async () => {
|
||||
await testActionSheet(DIRECTORY, '#alertFromActionSheet', true, testActionSheetAlert);
|
||||
});
|
||||
|
||||
test('action-sheet: basic, cancel only', async () => {
|
||||
test('action-sheet:rtl: basic, cancel only', async () => {
|
||||
await testActionSheet(DIRECTORY, '#cancelOnly', true);
|
||||
});
|
||||
|
||||
test('action-sheet: basic, custom', async () => {
|
||||
test('action-sheet:rtl: basic, custom', async () => {
|
||||
await testActionSheet(DIRECTORY, '#custom', true);
|
||||
});
|
||||
|
||||
test('action-sheet: basic, icons', async () => {
|
||||
test('action-sheet:rtl: basic, icons', async () => {
|
||||
await testActionSheet(DIRECTORY, '#icons', true);
|
||||
});
|
||||
|
||||
test('action-sheet: basic, no backdrop dismiss', async () => {
|
||||
test('action-sheet:rtl: basic, no backdrop dismiss', async () => {
|
||||
await testActionSheet(DIRECTORY, '#noBackdropDismiss', true, testActionSheetBackdrop);
|
||||
});
|
||||
|
||||
test('action-sheet: basic, scrollable options', async () => {
|
||||
test('action-sheet:rtl: basic, scrollable options', async () => {
|
||||
await testActionSheet(DIRECTORY, '#scrollableOptions', true);
|
||||
});
|
||||
|
||||
test('action-sheet: basic, scroll without cancel', async () => {
|
||||
test('action-sheet:rtl: basic, scroll without cancel', async () => {
|
||||
await testActionSheet(DIRECTORY, '#scrollWithoutCancel', true);
|
||||
});
|
||||
|
||||
@@ -1,19 +1,15 @@
|
||||
import { newE2EPage } from '@stencil/core/testing';
|
||||
|
||||
import { cleanScreenshotName, generateE2EUrl } from '../../../utils/test/utils';
|
||||
import { generateE2EUrl } from '../../../utils/test/utils';
|
||||
|
||||
export async function testActionSheet(
|
||||
type: string,
|
||||
selector: string,
|
||||
rtl = false,
|
||||
afterScreenshotHook = async (..._args: any[]): Promise<void> => {/**/},
|
||||
screenshotName: string = cleanScreenshotName(selector)
|
||||
afterScreenshotHook = async (..._args: any[]): Promise<void> => {/**/}
|
||||
) {
|
||||
try {
|
||||
const pageUrl = generateE2EUrl('action-sheet', type, rtl);
|
||||
if (rtl) {
|
||||
screenshotName = `${screenshotName} rtl`;
|
||||
}
|
||||
|
||||
const page = await newE2EPage({
|
||||
url: pageUrl
|
||||
@@ -27,14 +23,14 @@ export async function testActionSheet(
|
||||
let actionSheet = await page.find('ion-action-sheet');
|
||||
await actionSheet.waitForVisible();
|
||||
|
||||
screenshotCompares.push(await page.compareScreenshot(screenshotName));
|
||||
screenshotCompares.push(await page.compareScreenshot());
|
||||
|
||||
await afterScreenshotHook(page, screenshotName, screenshotCompares, actionSheet);
|
||||
await afterScreenshotHook(page, screenshotCompares, actionSheet);
|
||||
|
||||
await actionSheet.callMethod('dismiss');
|
||||
await actionSheet.waitForNotVisible();
|
||||
|
||||
screenshotCompares.push(await page.compareScreenshot(`dismissed ${screenshotName}`));
|
||||
screenshotCompares.push(await page.compareScreenshot('dismiss'));
|
||||
|
||||
actionSheet = await page.find('ion-action-sheet');
|
||||
expect(actionSheet).toBe(null);
|
||||
@@ -50,7 +46,6 @@ export async function testActionSheet(
|
||||
|
||||
export async function testActionSheetBackdrop(
|
||||
page: any,
|
||||
screenshotName: string,
|
||||
screenshotCompares: any,
|
||||
actionSheet: any
|
||||
) {
|
||||
@@ -59,7 +54,7 @@ export async function testActionSheetBackdrop(
|
||||
const backdrop = await page.find('ion-backdrop');
|
||||
await backdrop.click();
|
||||
|
||||
screenshotCompares.push(await page.compareScreenshot(`dismissed backdrop ${screenshotName}`));
|
||||
screenshotCompares.push(await page.compareScreenshot(`dismiss backdrop`));
|
||||
|
||||
const isVisible = await actionSheet.isVisible();
|
||||
expect(isVisible).toBe(true);
|
||||
@@ -70,7 +65,6 @@ export async function testActionSheetBackdrop(
|
||||
|
||||
export async function testActionSheetAlert(
|
||||
page: any,
|
||||
screenshotName: string,
|
||||
screenshotCompares: any
|
||||
) {
|
||||
try {
|
||||
@@ -81,7 +75,7 @@ export async function testActionSheetAlert(
|
||||
await alert.waitForVisible();
|
||||
await page.waitFor(250);
|
||||
|
||||
screenshotCompares.push(await page.compareScreenshot(`alert open ${screenshotName}`));
|
||||
screenshotCompares.push(await page.compareScreenshot(`alert open`));
|
||||
|
||||
const alertOkayBtn = await page.find({ contains: 'Okay' });
|
||||
await alertOkayBtn.click();
|
||||
|
||||
@@ -2,6 +2,7 @@ import { Component, ComponentInterface, Element, Event, EventEmitter, Listen, Me
|
||||
|
||||
import { AlertButton, AlertInput, Animation, AnimationBuilder, Config, CssClassMap, Mode, OverlayEventDetail, OverlayInterface } from '../../interface';
|
||||
import { BACKDROP, dismiss, eventMethod, isCancel, present } from '../../utils/overlays';
|
||||
import { sanitizeDOMString } from '../../utils/sanitization';
|
||||
import { getClassMap } from '../../utils/theme';
|
||||
|
||||
import { iosEnterAnimation } from './animations/ios.enter';
|
||||
@@ -72,6 +73,12 @@ export class Alert implements ComponentInterface, OverlayInterface {
|
||||
|
||||
/**
|
||||
* The main message to be displayed in the alert.
|
||||
* `message` can accept either plaintext or HTML as a string.
|
||||
* To display characters normally reserved for HTML, they
|
||||
* must be escaped. For example `<Ionic>` would become
|
||||
* `<Ionic>`
|
||||
*
|
||||
* For more information: [Security Documentation](https://ionicframework.com/docs/faq/security)
|
||||
*/
|
||||
@Prop() message?: string;
|
||||
|
||||
@@ -392,6 +399,7 @@ export class Alert implements ComponentInterface, OverlayInterface {
|
||||
},
|
||||
class: {
|
||||
...getClassMap(this.cssClass),
|
||||
[`${this.mode}`]: true,
|
||||
'alert-translucent': this.translucent
|
||||
}
|
||||
};
|
||||
@@ -439,7 +447,7 @@ export class Alert implements ComponentInterface, OverlayInterface {
|
||||
{this.subHeader && <h2 id={subHdrId} class="alert-sub-title">{this.subHeader}</h2>}
|
||||
</div>
|
||||
|
||||
<div id={msgId} class="alert-message" innerHTML={this.message}></div>
|
||||
<div id={msgId} class="alert-message" innerHTML={sanitizeDOMString(this.message)}></div>
|
||||
|
||||
{this.renderAlertInputs(labelledById)}
|
||||
{this.renderAlertButtons()}
|
||||
|
||||
@@ -1055,21 +1055,21 @@ export default {
|
||||
|
||||
## Properties
|
||||
|
||||
| Property | Attribute | Description | Type | Default |
|
||||
| ----------------- | ------------------ | ---------------------------------------------------------------------------------------------------------------- | -------------------------------------------------------------------------------------- | ----------- |
|
||||
| `animated` | `animated` | If `true`, the alert will animate. | `boolean` | `true` |
|
||||
| `backdropDismiss` | `backdrop-dismiss` | If `true`, the alert will be dismissed when the backdrop is clicked. | `boolean` | `true` |
|
||||
| `buttons` | -- | Array of buttons to be added to the alert. | `(string \| AlertButton)[]` | `[]` |
|
||||
| `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. | `((Animation: Animation, baseEl: any, opts?: any) => Promise<Animation>) \| undefined` | `undefined` |
|
||||
| `header` | `header` | The main title in the heading of the alert. | `string \| 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. | `((Animation: Animation, baseEl: any, opts?: any) => Promise<Animation>) \| undefined` | `undefined` |
|
||||
| `message` | `message` | The main message to be displayed in the alert. | `string \| undefined` | `undefined` |
|
||||
| `mode` | `mode` | The mode determines which platform styles to use. | `"ios" \| "md"` | `undefined` |
|
||||
| `subHeader` | `sub-header` | The subtitle in the heading of the alert. Displayed under the title. | `string \| undefined` | `undefined` |
|
||||
| `translucent` | `translucent` | If `true`, the alert will be translucent. | `boolean` | `false` |
|
||||
| Property | Attribute | Description | Type | Default |
|
||||
| ----------------- | ------------------ | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -------------------------------------------------------------------------------------- | ----------- |
|
||||
| `animated` | `animated` | If `true`, the alert will animate. | `boolean` | `true` |
|
||||
| `backdropDismiss` | `backdrop-dismiss` | If `true`, the alert will be dismissed when the backdrop is clicked. | `boolean` | `true` |
|
||||
| `buttons` | -- | Array of buttons to be added to the alert. | `(string \| AlertButton)[]` | `[]` |
|
||||
| `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. | `((Animation: Animation, baseEl: any, opts?: any) => Promise<Animation>) \| undefined` | `undefined` |
|
||||
| `header` | `header` | The main title in the heading of the alert. | `string \| 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. | `((Animation: Animation, baseEl: any, opts?: any) => Promise<Animation>) \| undefined` | `undefined` |
|
||||
| `message` | `message` | The main message to be displayed in the alert. `message` can accept either plaintext or HTML as a string. To display characters normally reserved for HTML, they must be escaped. For example `<Ionic>` would become `<Ionic>` For more information: [Security Documentation](https://ionicframework.com/docs/faq/security) | `string \| undefined` | `undefined` |
|
||||
| `mode` | `mode` | The mode determines which platform styles to use. | `"ios" \| "md"` | `undefined` |
|
||||
| `subHeader` | `sub-header` | The subtitle in the heading of the alert. Displayed under the title. | `string \| undefined` | `undefined` |
|
||||
| `translucent` | `translucent` | If `true`, the alert will be translucent. | `boolean` | `false` |
|
||||
|
||||
|
||||
## Events
|
||||
|
||||
@@ -37,34 +37,34 @@ test(`alert: basic, checkbox`, async () => {
|
||||
// Right to Left tests
|
||||
// ------------------------------------------------------
|
||||
|
||||
test(`alert: basic`, async () => {
|
||||
test(`alert:rtl: basic`, async () => {
|
||||
await testAlert(DIRECTORY, '#basic', true);
|
||||
});
|
||||
|
||||
test(`alert: basic, long message`, async () => {
|
||||
test(`alert:rtl: basic, long message`, async () => {
|
||||
await testAlert(DIRECTORY, '#longMessage', true);
|
||||
});
|
||||
|
||||
test(`alert: basic, multiple buttons`, async () => {
|
||||
test(`alert:rtl: basic, multiple buttons`, async () => {
|
||||
await testAlert(DIRECTORY, '#multipleButtons', true);
|
||||
});
|
||||
|
||||
test(`alert: basic, no message`, async () => {
|
||||
test(`alert:rtl: basic, no message`, async () => {
|
||||
await testAlert(DIRECTORY, '#noMessage', true);
|
||||
});
|
||||
|
||||
test(`alert: basic, confirm`, async () => {
|
||||
test(`alert:rtl: basic, confirm`, async () => {
|
||||
await testAlert(DIRECTORY, '#confirm', true);
|
||||
});
|
||||
|
||||
test(`alert: basic, prompt`, async () => {
|
||||
test(`alert:rtl: basic, prompt`, async () => {
|
||||
await testAlert(DIRECTORY, '#prompt', true);
|
||||
});
|
||||
|
||||
test(`alert: basic, radio`, async () => {
|
||||
test(`alert:rtl: basic, radio`, async () => {
|
||||
await testAlert(DIRECTORY, '#radio', true);
|
||||
});
|
||||
|
||||
test(`alert: basic, checkbox`, async () => {
|
||||
test(`alert:rtl: basic, checkbox`, async () => {
|
||||
await testAlert(DIRECTORY, '#checkbox', true);
|
||||
});
|
||||
|
||||
@@ -1,18 +1,14 @@
|
||||
import { newE2EPage } from '@stencil/core/testing';
|
||||
|
||||
import { cleanScreenshotName, generateE2EUrl } from '../../../utils/test/utils';
|
||||
import { generateE2EUrl } from '../../../utils/test/utils';
|
||||
|
||||
export async function testAlert(
|
||||
type: string,
|
||||
selector: string,
|
||||
rtl = false,
|
||||
screenshotName: string = cleanScreenshotName(selector)
|
||||
rtl = false
|
||||
) {
|
||||
try {
|
||||
const pageUrl = generateE2EUrl('alert', type, rtl);
|
||||
if (rtl) {
|
||||
screenshotName = `${screenshotName} rtl`;
|
||||
}
|
||||
|
||||
const page = await newE2EPage({
|
||||
url: pageUrl
|
||||
@@ -28,12 +24,12 @@ export async function testAlert(
|
||||
expect(alert).not.toBe(null);
|
||||
await alert.waitForVisible();
|
||||
|
||||
screenshotCompares.push(await page.compareScreenshot(screenshotName));
|
||||
screenshotCompares.push(await page.compareScreenshot());
|
||||
|
||||
await alert.callMethod('dismiss');
|
||||
await alert.waitForNotVisible();
|
||||
|
||||
screenshotCompares.push(await page.compareScreenshot(`dismiss ${screenshotName}`));
|
||||
screenshotCompares.push(await page.compareScreenshot('dismiss'));
|
||||
|
||||
alert = await page.find('ion-alert');
|
||||
expect(alert).toBe(null);
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import { Component, ComponentInterface, Listen, Prop } from '@stencil/core';
|
||||
|
||||
import { Color, RouterDirection } from '../../interface';
|
||||
import { Color, Mode, RouterDirection } from '../../interface';
|
||||
import { createColorClasses, openURL } from '../../utils/theme';
|
||||
|
||||
@Component({
|
||||
@@ -9,6 +9,7 @@ import { createColorClasses, openURL } from '../../utils/theme';
|
||||
shadow: true
|
||||
})
|
||||
export class Anchor implements ComponentInterface {
|
||||
mode!: Mode;
|
||||
|
||||
@Prop({ context: 'window' }) win!: Window;
|
||||
|
||||
@@ -40,6 +41,7 @@ export class Anchor implements ComponentInterface {
|
||||
return {
|
||||
class: {
|
||||
...createColorClasses(this.color),
|
||||
[`${this.mode}`]: true,
|
||||
'ion-activatable': true
|
||||
}
|
||||
};
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import { Component, ComponentInterface, Element, Prop, QueueApi } from '@stencil/core';
|
||||
|
||||
import { Config } from '../../interface';
|
||||
import { Config, Mode } from '../../interface';
|
||||
import { rIC } from '../../utils/helpers';
|
||||
import { isPlatform } from '../../utils/platform';
|
||||
|
||||
@@ -9,6 +9,7 @@ import { isPlatform } from '../../utils/platform';
|
||||
styleUrl: 'app.scss'
|
||||
})
|
||||
export class App implements ComponentInterface {
|
||||
mode!: Mode;
|
||||
|
||||
@Element() el!: HTMLElement;
|
||||
|
||||
@@ -34,6 +35,7 @@ export class App implements ComponentInterface {
|
||||
hostData() {
|
||||
return {
|
||||
class: {
|
||||
[`${this.mode}`]: true,
|
||||
'ion-page': true,
|
||||
'force-statusbar-padding': this.config.getBoolean('_forceStatusbarPadding')
|
||||
}
|
||||
|
||||
@@ -1,5 +1,7 @@
|
||||
import { Component, ComponentInterface } from '@stencil/core';
|
||||
|
||||
import { Mode } from '../../interface';
|
||||
|
||||
@Component({
|
||||
tag: 'ion-avatar',
|
||||
styleUrls: {
|
||||
@@ -9,6 +11,15 @@ import { Component, ComponentInterface } from '@stencil/core';
|
||||
shadow: true
|
||||
})
|
||||
export class Avatar implements ComponentInterface {
|
||||
mode!: Mode;
|
||||
|
||||
hostData() {
|
||||
return {
|
||||
class: {
|
||||
[`${this.mode}`]: true,
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
render() {
|
||||
return <slot></slot>;
|
||||
|
||||
@@ -62,6 +62,7 @@ export class BackButton implements ComponentInterface {
|
||||
return {
|
||||
class: {
|
||||
...createColorClasses(this.color),
|
||||
[`${this.mode}`]: true,
|
||||
|
||||
'button': true, // ion-buttons target .button
|
||||
'ion-activatable': true,
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
import { Component, ComponentInterface, Event, EventEmitter, Listen, Prop } from '@stencil/core';
|
||||
|
||||
import { Mode } from '../../interface';
|
||||
import { GESTURE_CONTROLLER } from '../../utils/gesture';
|
||||
import { now } from '../../utils/helpers';
|
||||
|
||||
@@ -12,6 +13,7 @@ import { now } from '../../utils/helpers';
|
||||
shadow: true
|
||||
})
|
||||
export class Backdrop implements ComponentInterface {
|
||||
mode!: Mode;
|
||||
|
||||
private lastClick = -10000;
|
||||
private blocker = GESTURE_CONTROLLER.createBlocker({
|
||||
@@ -78,6 +80,7 @@ export class Backdrop implements ComponentInterface {
|
||||
return {
|
||||
tabindex: '-1',
|
||||
class: {
|
||||
[`${this.mode}`]: true,
|
||||
'backdrop-hide': !this.visible,
|
||||
'backdrop-no-tappable': !this.tappable,
|
||||
}
|
||||
|
||||
@@ -26,7 +26,10 @@ export class Badge implements ComponentInterface {
|
||||
|
||||
hostData() {
|
||||
return {
|
||||
class: createColorClasses(this.color)
|
||||
class: {
|
||||
...createColorClasses(this.color),
|
||||
[`${this.mode}`]: true
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
@@ -148,6 +148,7 @@ export class Button implements ComponentInterface {
|
||||
'aria-disabled': disabled ? 'true' : null,
|
||||
class: {
|
||||
...createColorClasses(color),
|
||||
[`${this.mode}`]: true,
|
||||
[buttonType]: true,
|
||||
[`${buttonType}-${expand}`]: expand !== undefined,
|
||||
[`${buttonType}-${size}`]: size !== undefined,
|
||||
|
||||
@@ -1,5 +1,7 @@
|
||||
import { Component, ComponentInterface } from '@stencil/core';
|
||||
|
||||
import { Mode } from '../../interface';
|
||||
|
||||
@Component({
|
||||
tag: 'ion-buttons',
|
||||
styleUrls: {
|
||||
@@ -8,4 +10,14 @@ import { Component, ComponentInterface } from '@stencil/core';
|
||||
},
|
||||
scoped: true,
|
||||
})
|
||||
export class Buttons implements ComponentInterface {}
|
||||
export class Buttons implements ComponentInterface {
|
||||
mode!: Mode;
|
||||
|
||||
hostData() {
|
||||
return {
|
||||
class: {
|
||||
[`${this.mode}`]: true
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
import { Component, ComponentInterface, Prop } from '@stencil/core';
|
||||
|
||||
import { Mode } from '../../interface';
|
||||
import { createThemedClasses } from '../../utils/theme';
|
||||
|
||||
@Component({
|
||||
tag: 'ion-card-content',
|
||||
@@ -19,7 +18,12 @@ export class CardContent implements ComponentInterface {
|
||||
|
||||
hostData() {
|
||||
return {
|
||||
class: createThemedClasses(this.mode, 'card-content')
|
||||
class: {
|
||||
[`${this.mode}`]: true,
|
||||
|
||||
// Used internally for styling
|
||||
[`card-content-${this.mode}`]: true
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
@@ -34,6 +34,7 @@ export class CardHeader implements ComponentInterface {
|
||||
class: {
|
||||
...createColorClasses(this.color),
|
||||
'card-header-translucent': this.translucent,
|
||||
[`${this.mode}`]: true
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
@@ -26,7 +26,10 @@ export class CardSubtitle implements ComponentInterface {
|
||||
|
||||
hostData() {
|
||||
return {
|
||||
class: createColorClasses(this.color),
|
||||
class: {
|
||||
...createColorClasses(this.color),
|
||||
[`${this.mode}`]: true
|
||||
},
|
||||
'role': 'heading',
|
||||
'aria-level': '3'
|
||||
};
|
||||
|
||||
@@ -26,7 +26,10 @@ export class CardTitle implements ComponentInterface {
|
||||
|
||||
hostData() {
|
||||
return {
|
||||
class: createColorClasses(this.color),
|
||||
class: {
|
||||
...createColorClasses(this.color),
|
||||
[`${this.mode}`]: true
|
||||
},
|
||||
'role': 'heading',
|
||||
'aria-level': '2'
|
||||
};
|
||||
|
||||
@@ -27,7 +27,10 @@ export class Card implements ComponentInterface {
|
||||
|
||||
hostData() {
|
||||
return {
|
||||
class: createColorClasses(this.color)
|
||||
class: {
|
||||
...createColorClasses(this.color),
|
||||
[`${this.mode}`]: true
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
@@ -137,6 +137,7 @@ export class Checkbox implements ComponentInterface {
|
||||
'aria-labelledby': labelId,
|
||||
class: {
|
||||
...createColorClasses(color),
|
||||
[`${this.mode}`]: true,
|
||||
'in-item': hostContext('ion-item', el),
|
||||
'checkbox-checked': checked,
|
||||
'checkbox-disabled': disabled,
|
||||
|
||||
@@ -33,6 +33,7 @@ export class Chip implements ComponentInterface {
|
||||
return {
|
||||
class: {
|
||||
...createColorClasses(this.color),
|
||||
[`${this.mode}`]: true,
|
||||
'chip-outline': this.outline,
|
||||
'ion-activatable': true,
|
||||
}
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
import { Component, ComponentInterface, Element, Listen, Prop } from '@stencil/core';
|
||||
|
||||
import { Mode } from '../../interface';
|
||||
import { matchBreakpoint } from '../../utils/media';
|
||||
|
||||
const win = window as any;
|
||||
@@ -12,6 +13,8 @@ const BREAKPOINTS = ['', 'xs', 'sm', 'md', 'lg', 'xl'];
|
||||
shadow: true
|
||||
})
|
||||
export class Col implements ComponentInterface {
|
||||
mode!: Mode;
|
||||
|
||||
@Prop({ context: 'window' }) win!: Window;
|
||||
|
||||
@Element() el!: HTMLStencilElement;
|
||||
@@ -247,6 +250,9 @@ export class Col implements ComponentInterface {
|
||||
hostData() {
|
||||
const isRTL = this.win.document.dir === 'rtl';
|
||||
return {
|
||||
class: {
|
||||
[`${this.mode}`]: true
|
||||
},
|
||||
style: {
|
||||
...this.calculateOffset(isRTL),
|
||||
...this.calculatePull(isRTL),
|
||||
|
||||
@@ -293,6 +293,7 @@ export class Content implements ComponentInterface {
|
||||
return {
|
||||
class: {
|
||||
...createColorClasses(this.color),
|
||||
[`${this.mode}`]: true,
|
||||
'content-sizing': hostContext('ion-popover', this.el),
|
||||
'overscroll': !!this.forceOverscroll,
|
||||
},
|
||||
|
||||
@@ -2,7 +2,7 @@ import { convertDataToISO, parseDate } from './datetime-util';
|
||||
|
||||
describe('datetime-util', () => {
|
||||
describe('convertDataToISO', () => {
|
||||
it('prints an emptry string for an empty datetime', () => {
|
||||
it('prints an empty string for an empty datetime', () => {
|
||||
expect(convertDataToISO({})).toEqual('');
|
||||
});
|
||||
|
||||
|
||||
@@ -248,8 +248,20 @@ export function parseDate(val: string | undefined | null): DatetimeData | undefi
|
||||
* such as "01:47"
|
||||
*/
|
||||
export const getLocalDateTime = (dateString: any = ''): Date => {
|
||||
const date = (typeof dateString === 'string' && dateString.length > 0) ? new Date(dateString) : new Date();
|
||||
/**
|
||||
* Ensures that YYYY-MM-DD, YYYY-MM,
|
||||
* YYYY-DD, etc does not get affected
|
||||
* by timezones and stays on the day/month
|
||||
* that the user provided
|
||||
*/
|
||||
if (
|
||||
dateString.length === 10 ||
|
||||
dateString.length === 7
|
||||
) {
|
||||
dateString += ' ';
|
||||
}
|
||||
|
||||
const date = (typeof dateString === 'string' && dateString.length > 0) ? new Date(dateString) : new Date();
|
||||
return new Date(
|
||||
Date.UTC(
|
||||
date.getFullYear(),
|
||||
@@ -267,7 +279,6 @@ export function updateDate(existingData: DatetimeData, newData: any): boolean {
|
||||
|
||||
if (!newData || typeof newData === 'string') {
|
||||
const localDateTime = getLocalDateTime(newData);
|
||||
|
||||
if (!Number.isNaN(localDateTime.getTime())) {
|
||||
newData = localDateTime.toISOString();
|
||||
}
|
||||
|
||||
@@ -615,6 +615,7 @@ export class Datetime implements ComponentInterface {
|
||||
'aria-haspopup': 'true',
|
||||
'aria-labelledby': labelId,
|
||||
class: {
|
||||
[`${this.mode}`]: true,
|
||||
'datetime-disabled': disabled,
|
||||
'datetime-readonly': readonly,
|
||||
'datetime-placeholder': addPlaceholderClass,
|
||||
|
||||
@@ -52,6 +52,23 @@ describe('Datetime', () => {
|
||||
expect(convertToLocal.toISOString()).toEqual(expectedDateString);
|
||||
});
|
||||
});
|
||||
|
||||
it('should format a date string and not get affected by the timezone offset', () => {
|
||||
|
||||
const dateStringTests = [
|
||||
{ input: '2019-03-20', expectedOutput: '2019-03-20' },
|
||||
{ input: '1994-04-15', expectedOutput: '1994-04-15' },
|
||||
{ input: '2008-09-02', expectedOutput: '2008-09-02' },
|
||||
{ input: '1995-02', expectedOutput: '1995-02' },
|
||||
{ input: '1994-03-14', expectedOutput: '1994-03-14' },
|
||||
{ input: '9 01:47', expectedOutput: '09-01T01:47' }
|
||||
];
|
||||
|
||||
dateStringTests.forEach(test => {
|
||||
const convertToLocal = getLocalDateTime(test.input);
|
||||
expect(convertToLocal.toISOString()).toContain(test.expectedOutput);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe('daysInMonth()', () => {
|
||||
|
||||
@@ -95,6 +95,7 @@ export class FabButton implements ComponentInterface {
|
||||
'aria-disabled': disabled ? 'true' : null,
|
||||
class: {
|
||||
...createColorClasses(color),
|
||||
[`${this.mode}`]: true,
|
||||
'fab-button-in-list': inList,
|
||||
'fab-button-translucent-in-list': inList && translucent,
|
||||
'fab-button-close-active': activated,
|
||||
|
||||
@@ -1,11 +1,15 @@
|
||||
import { Component, ComponentInterface, Element, Prop, Watch } from '@stencil/core';
|
||||
|
||||
import { Mode } from '../../interface';
|
||||
|
||||
@Component({
|
||||
tag: 'ion-fab-list',
|
||||
styleUrl: 'fab-list.scss',
|
||||
shadow: true
|
||||
})
|
||||
export class FabList implements ComponentInterface {
|
||||
mode!: Mode;
|
||||
|
||||
@Element() el!: HTMLIonFabElement;
|
||||
|
||||
/**
|
||||
@@ -32,6 +36,7 @@ export class FabList implements ComponentInterface {
|
||||
hostData() {
|
||||
return {
|
||||
class: {
|
||||
[`${this.mode}`]: true,
|
||||
'fab-list-active': this.activated,
|
||||
[`fab-list-side-${this.side}`]: true
|
||||
}
|
||||
|
||||
@@ -1,11 +1,14 @@
|
||||
import { Component, ComponentInterface, Element, Listen, Method, Prop, Watch } from '@stencil/core';
|
||||
|
||||
import { Mode } from '../../interface';
|
||||
|
||||
@Component({
|
||||
tag: 'ion-fab',
|
||||
styleUrl: 'fab.scss',
|
||||
shadow: true
|
||||
})
|
||||
export class Fab implements ComponentInterface {
|
||||
mode!: Mode;
|
||||
|
||||
@Element() el!: HTMLElement;
|
||||
|
||||
@@ -75,6 +78,7 @@ export class Fab implements ComponentInterface {
|
||||
hostData() {
|
||||
return {
|
||||
class: {
|
||||
[`${this.mode}`]: true,
|
||||
[`fab-horizontal-${this.horizontal}`]: this.horizontal !== undefined,
|
||||
[`fab-vertical-${this.vertical}`]: this.vertical !== undefined,
|
||||
'fab-edge': this.edge
|
||||
|
||||
@@ -1,25 +1,21 @@
|
||||
import { newE2EPage } from '@stencil/core/testing';
|
||||
|
||||
import { cleanScreenshotName, generateE2EUrl } from '../../../utils/test/utils';
|
||||
import { generateE2EUrl } from '../../../utils/test/utils';
|
||||
|
||||
export async function testFab(
|
||||
type: string,
|
||||
selector: string,
|
||||
rtl = false,
|
||||
screenshotName: string = cleanScreenshotName(selector)
|
||||
rtl = false
|
||||
) {
|
||||
try {
|
||||
const pageUrl = generateE2EUrl('fab', type, rtl);
|
||||
if (rtl) {
|
||||
screenshotName = `${screenshotName} rtl`;
|
||||
}
|
||||
|
||||
const page = await newE2EPage({
|
||||
url: pageUrl
|
||||
});
|
||||
|
||||
const screenshotCompares = [];
|
||||
screenshotCompares.push(await page.compareScreenshot(`${screenshotName}`));
|
||||
screenshotCompares.push(await page.compareScreenshot());
|
||||
|
||||
const fab = await getFabComponent(page, selector);
|
||||
await fab.click();
|
||||
@@ -28,7 +24,7 @@ export async function testFab(
|
||||
|
||||
await ensureFabState(fab, 'active');
|
||||
|
||||
screenshotCompares.push(await page.compareScreenshot(`${screenshotName} open`));
|
||||
screenshotCompares.push(await page.compareScreenshot('open'));
|
||||
|
||||
const fabButton = await getFabButton(fab);
|
||||
await fabButton.click();
|
||||
@@ -37,7 +33,7 @@ export async function testFab(
|
||||
|
||||
await ensureFabState(fab, 'inactive');
|
||||
|
||||
screenshotCompares.push(await page.compareScreenshot(`${screenshotName} close`));
|
||||
screenshotCompares.push(await page.compareScreenshot('close'));
|
||||
|
||||
for (const screenshotCompare of screenshotCompares) {
|
||||
expect(screenshotCompare).toMatchScreenshot();
|
||||
@@ -50,28 +46,24 @@ export async function testFab(
|
||||
export async function testDisabledFab(
|
||||
type: string,
|
||||
selector: string,
|
||||
rtl = false,
|
||||
screenshotName: string = cleanScreenshotName(selector)
|
||||
rtl = false
|
||||
) {
|
||||
try {
|
||||
const pageUrl = generateE2EUrl('fab', type, rtl);
|
||||
if (rtl) {
|
||||
screenshotName = `${screenshotName} rtl`;
|
||||
}
|
||||
|
||||
const page = await newE2EPage({
|
||||
url: pageUrl
|
||||
});
|
||||
|
||||
const screenshotCompares = [];
|
||||
screenshotCompares.push(await page.compareScreenshot(`disabled ${screenshotName}`));
|
||||
screenshotCompares.push(await page.compareScreenshot('disabled'));
|
||||
|
||||
const fab = await getFabComponent(page, selector);
|
||||
await fab.click();
|
||||
|
||||
await ensureFabState(fab, 'inactive');
|
||||
|
||||
screenshotCompares.push(await page.compareScreenshot(`disabled ${screenshotName} attempt open`));
|
||||
screenshotCompares.push(await page.compareScreenshot('disabled, attempt open'));
|
||||
|
||||
for (const screenshotCompare of screenshotCompares) {
|
||||
expect(screenshotCompare).toMatchScreenshot();
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
import { Component, ComponentInterface, Prop } from '@stencil/core';
|
||||
|
||||
import { Mode } from '../../interface';
|
||||
import { createThemedClasses } from '../../utils/theme';
|
||||
|
||||
@Component({
|
||||
tag: 'ion-footer',
|
||||
@@ -25,13 +24,15 @@ export class Footer implements ComponentInterface {
|
||||
@Prop() translucent = false;
|
||||
|
||||
hostData() {
|
||||
const themedClasses = createThemedClasses(this.mode, 'footer');
|
||||
const translucentClasses = this.translucent ? createThemedClasses(this.mode, 'footer-translucent') : null;
|
||||
|
||||
return {
|
||||
class: {
|
||||
...themedClasses,
|
||||
...translucentClasses
|
||||
[`${this.mode}`]: true,
|
||||
|
||||
// Used internally for styling
|
||||
[`footer-${this.mode}`]: true,
|
||||
|
||||
[`footer-translucent`]: this.translucent,
|
||||
[`footer-translucent-${this.mode}`]: this.translucent,
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
14
core/src/components/footer/test/translucent/e2e.ts
Normal file
14
core/src/components/footer/test/translucent/e2e.ts
Normal file
@@ -0,0 +1,14 @@
|
||||
import { newE2EPage } from '@stencil/core/testing';
|
||||
|
||||
import { checkComponentModeClasses } from '../../../../utils/test/utils';
|
||||
|
||||
test('footer: translucent', async () => {
|
||||
const page = await newE2EPage({
|
||||
url: '/src/components/footer/test/translucent?ionic:_testing=true'
|
||||
});
|
||||
|
||||
await checkComponentModeClasses(await page.find('ion-footer'), 'footer-translucent');
|
||||
|
||||
const compare = await page.compareScreenshot();
|
||||
expect(compare).toMatchScreenshot();
|
||||
});
|
||||
@@ -1,11 +1,14 @@
|
||||
import { Component, ComponentInterface, Prop } from '@stencil/core';
|
||||
|
||||
import { Mode } from '../../interface';
|
||||
|
||||
@Component({
|
||||
tag: 'ion-grid',
|
||||
styleUrl: 'grid.scss',
|
||||
shadow: true
|
||||
})
|
||||
export class Grid implements ComponentInterface {
|
||||
mode!: Mode;
|
||||
|
||||
/**
|
||||
* If `true`, the grid will have a fixed width based on the screen size.
|
||||
@@ -15,6 +18,7 @@ export class Grid implements ComponentInterface {
|
||||
hostData() {
|
||||
return {
|
||||
class: {
|
||||
[`${this.mode}`]: true,
|
||||
'grid-fixed': this.fixed
|
||||
}
|
||||
};
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
import { Component, ComponentInterface, Prop } from '@stencil/core';
|
||||
|
||||
import { Mode } from '../../interface';
|
||||
import { createThemedClasses } from '../../utils/theme';
|
||||
|
||||
@Component({
|
||||
tag: 'ion-header',
|
||||
@@ -25,13 +24,15 @@ export class Header implements ComponentInterface {
|
||||
@Prop() translucent = false;
|
||||
|
||||
hostData() {
|
||||
const themedClasses = createThemedClasses(this.mode, 'header');
|
||||
const translucentClasses = this.translucent ? createThemedClasses(this.mode, 'header-translucent') : null;
|
||||
|
||||
return {
|
||||
class: {
|
||||
...themedClasses,
|
||||
...translucentClasses
|
||||
[`${this.mode}`]: true,
|
||||
|
||||
// Used internally for styling
|
||||
[`header-${this.mode}`]: true,
|
||||
|
||||
[`header-translucent`]: this.translucent,
|
||||
[`header-translucent-${this.mode}`]: this.translucent,
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
14
core/src/components/header/test/translucent/e2e.ts
Normal file
14
core/src/components/header/test/translucent/e2e.ts
Normal file
@@ -0,0 +1,14 @@
|
||||
import { newE2EPage } from '@stencil/core/testing';
|
||||
|
||||
import { checkComponentModeClasses } from '../../../../utils/test/utils';
|
||||
|
||||
test('header: translucent', async () => {
|
||||
const page = await newE2EPage({
|
||||
url: '/src/components/header/test/translucent?ionic:_testing=true'
|
||||
});
|
||||
|
||||
await checkComponentModeClasses(await page.find('ion-header'), 'header-translucent');
|
||||
|
||||
const compare = await page.compareScreenshot();
|
||||
expect(compare).toMatchScreenshot();
|
||||
});
|
||||
@@ -1,11 +1,14 @@
|
||||
import { Component, ComponentInterface, Element, Event, EventEmitter, Prop, State, Watch } from '@stencil/core';
|
||||
|
||||
import { Mode } from '../../interface';
|
||||
|
||||
@Component({
|
||||
tag: 'ion-img',
|
||||
styleUrl: 'img.scss',
|
||||
shadow: true
|
||||
})
|
||||
export class Img implements ComponentInterface {
|
||||
mode!: Mode;
|
||||
|
||||
private io?: IntersectionObserver;
|
||||
|
||||
@@ -81,6 +84,14 @@ export class Img implements ComponentInterface {
|
||||
}
|
||||
}
|
||||
|
||||
hostData() {
|
||||
return {
|
||||
class: {
|
||||
[`${this.mode}`]: true,
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
render() {
|
||||
return (
|
||||
<img
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import { Component, ComponentInterface, Prop } from '@stencil/core';
|
||||
|
||||
import { Config, Mode, SpinnerTypes } from '../../interface';
|
||||
import { createThemedClasses } from '../../utils/theme';
|
||||
import { sanitizeDOMString } from '../../utils/sanitization';
|
||||
|
||||
@Component({
|
||||
tag: 'ion-infinite-scroll-content',
|
||||
@@ -23,6 +23,12 @@ export class InfiniteScrollContent implements ComponentInterface {
|
||||
|
||||
/**
|
||||
* Optional text to display while loading.
|
||||
* `loadingText` can accept either plaintext or HTML as a string.
|
||||
* To display characters normally reserved for HTML, they
|
||||
* must be escaped. For example `<Ionic>` would become
|
||||
* `<Ionic>`
|
||||
*
|
||||
* For more information: [Security Documentation](https://ionicframework.com/docs/faq/security)
|
||||
*/
|
||||
@Prop() loadingText?: string;
|
||||
|
||||
@@ -37,7 +43,12 @@ export class InfiniteScrollContent implements ComponentInterface {
|
||||
|
||||
hostData() {
|
||||
return {
|
||||
class: createThemedClasses(this.mode, 'infinite-scroll-content')
|
||||
class: {
|
||||
[`${this.mode}`]: true,
|
||||
|
||||
// Used internally for styling
|
||||
[`infinite-scroll-content-${this.mode}`]: true
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
@@ -50,7 +61,7 @@ export class InfiniteScrollContent implements ComponentInterface {
|
||||
</div>
|
||||
)}
|
||||
{this.loadingText && (
|
||||
<div class="infinite-loading-text" innerHTML={this.loadingText} />
|
||||
<div class="infinite-loading-text" innerHTML={sanitizeDOMString(this.loadingText)} />
|
||||
)}
|
||||
</div>
|
||||
);
|
||||
|
||||
@@ -76,10 +76,10 @@ export default Example
|
||||
|
||||
## Properties
|
||||
|
||||
| Property | Attribute | Description | Type | Default |
|
||||
| ---------------- | ----------------- | ------------------------------------------------- | ------------------------------------------------------------------------------------------------- | ----------- |
|
||||
| `loadingSpinner` | `loading-spinner` | An animated SVG spinner that shows while loading. | `"bubbles" \| "circles" \| "crescent" \| "dots" \| "lines" \| "lines-small" \| null \| undefined` | `undefined` |
|
||||
| `loadingText` | `loading-text` | Optional text to display while loading. | `string \| undefined` | `undefined` |
|
||||
| Property | Attribute | Description | Type | Default |
|
||||
| ---------------- | ----------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------- | ----------- |
|
||||
| `loadingSpinner` | `loading-spinner` | An animated SVG spinner that shows while loading. | `"bubbles" \| "circles" \| "crescent" \| "dots" \| "lines" \| "lines-small" \| null \| undefined` | `undefined` |
|
||||
| `loadingText` | `loading-text` | Optional text to display while loading. `loadingText` can accept either plaintext or HTML as a string. To display characters normally reserved for HTML, they must be escaped. For example `<Ionic>` would become `<Ionic>` For more information: [Security Documentation](https://ionicframework.com/docs/faq/security) | `string \| undefined` | `undefined` |
|
||||
|
||||
|
||||
----------------------------------------------
|
||||
|
||||
@@ -1,10 +1,13 @@
|
||||
import { Component, ComponentInterface, Element, Event, EventEmitter, EventListenerEnable, Listen, Method, Prop, QueueApi, State, Watch } from '@stencil/core';
|
||||
|
||||
import { Mode } from '../../interface';
|
||||
|
||||
@Component({
|
||||
tag: 'ion-infinite-scroll',
|
||||
styleUrl: 'infinite-scroll.scss'
|
||||
})
|
||||
export class InfiniteScroll implements ComponentInterface {
|
||||
mode!: Mode;
|
||||
|
||||
private thrPx = 0;
|
||||
private thrPc = 0;
|
||||
@@ -212,6 +215,7 @@ export class InfiniteScroll implements ComponentInterface {
|
||||
hostData() {
|
||||
return {
|
||||
class: {
|
||||
[`${this.mode}`]: true,
|
||||
'infinite-scroll-loading': this.isLoading,
|
||||
'infinite-scroll-enabled': !this.disabled
|
||||
}
|
||||
|
||||
@@ -307,7 +307,12 @@ export class Input implements ComponentInterface {
|
||||
}
|
||||
}
|
||||
|
||||
private clearTextInput = () => {
|
||||
private clearTextInput = (ev?: Event) => {
|
||||
if (this.clearInput && !this.readonly && !this.disabled && ev) {
|
||||
ev.preventDefault();
|
||||
ev.stopPropagation();
|
||||
}
|
||||
|
||||
this.value = '';
|
||||
}
|
||||
|
||||
@@ -327,6 +332,7 @@ export class Input implements ComponentInterface {
|
||||
'aria-disabled': this.disabled ? 'true' : null,
|
||||
class: {
|
||||
...createColorClasses(this.color),
|
||||
[`${this.mode}`]: true,
|
||||
'has-value': this.hasValue(),
|
||||
'has-focus': this.hasFocus
|
||||
}
|
||||
|
||||
15
core/src/components/input/test/spec/e2e.ts
Normal file
15
core/src/components/input/test/spec/e2e.ts
Normal file
@@ -0,0 +1,15 @@
|
||||
import { newE2EPage } from '@stencil/core/testing';
|
||||
|
||||
test('input: spec', async () => {
|
||||
const page = await newE2EPage({
|
||||
url: '/src/components/input/test/spec?ionic:_testing=true'
|
||||
});
|
||||
|
||||
const compares = [];
|
||||
|
||||
compares.push(await page.compareScreenshot());
|
||||
|
||||
for (const compare of compares) {
|
||||
expect(compare).toMatchScreenshot();
|
||||
}
|
||||
});
|
||||
61
core/src/components/input/test/spec/index.html
Normal file
61
core/src/components/input/test/spec/index.html
Normal file
@@ -0,0 +1,61 @@
|
||||
<!DOCTYPE html>
|
||||
<html dir="ltr">
|
||||
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<title>Input - Spec</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">
|
||||
<script src="../../../../../scripts/testing/scripts.js"></script>
|
||||
<script src="../../../../../dist/ionic.js"></script>
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<ion-app>
|
||||
<ion-content class="ion-padding">
|
||||
<ion-item>
|
||||
<ion-label position="floating">Standard</ion-label>
|
||||
<ion-input></ion-input>
|
||||
</ion-item>
|
||||
<ion-item>
|
||||
<ion-label position="floating">Standard</ion-label>
|
||||
<ion-input value="value"></ion-input>
|
||||
</ion-item>
|
||||
<ion-item>
|
||||
<ion-label position="stacked">Stacked</ion-label>
|
||||
<ion-input></ion-input>
|
||||
</ion-item>
|
||||
<ion-item>
|
||||
<ion-label position="stacked">Stacked</ion-label>
|
||||
<ion-input value="value"></ion-input>
|
||||
</ion-item>
|
||||
<ion-item>
|
||||
<ion-label position="floating">Floating</ion-label>
|
||||
<ion-textarea></ion-textarea>
|
||||
</ion-item>
|
||||
<ion-item>
|
||||
<ion-label position="floating">Floating</ion-label>
|
||||
<ion-textarea value="value"></ion-textarea>
|
||||
</ion-item>
|
||||
<ion-item>
|
||||
<ion-label position="stacked">Stacked</ion-label>
|
||||
<ion-textarea></ion-textarea>
|
||||
</ion-item>
|
||||
<ion-item>
|
||||
<ion-label position="stacked">Stacked</ion-label>
|
||||
<ion-textarea value="value"></ion-textarea>
|
||||
</ion-item>
|
||||
|
||||
</ion-content>
|
||||
|
||||
<style>
|
||||
ion-item {
|
||||
--background: #f5f5f5;
|
||||
}
|
||||
|
||||
</style>
|
||||
</ion-app>
|
||||
</body>
|
||||
|
||||
</html>
|
||||
@@ -55,6 +55,7 @@ export class ItemDivider implements ComponentInterface {
|
||||
return {
|
||||
class: {
|
||||
...createColorClasses(this.color),
|
||||
[`${this.mode}`]: true,
|
||||
'item-divider-sticky': this.sticky,
|
||||
'item': true,
|
||||
}
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
import { Component, ComponentInterface } from '@stencil/core';
|
||||
|
||||
import { Mode } from '../../interface';
|
||||
import { createThemedClasses } from '../../utils/theme';
|
||||
|
||||
@Component({
|
||||
tag: 'ion-item-group',
|
||||
@@ -18,8 +17,12 @@ export class ItemGroup implements ComponentInterface {
|
||||
return {
|
||||
'role': 'group',
|
||||
class: {
|
||||
...createThemedClasses(this.mode, 'item-group'),
|
||||
'item': true,
|
||||
[`${this.mode}`]: true,
|
||||
|
||||
// Used internally for styling
|
||||
[`item-group-${this.mode}`]: true,
|
||||
|
||||
'item': true
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
@@ -64,6 +64,8 @@ export class ItemOption implements ComponentInterface {
|
||||
return {
|
||||
class: {
|
||||
...createColorClasses(this.color),
|
||||
[`${this.mode}`]: true,
|
||||
|
||||
'item-option-disabled': disabled,
|
||||
'item-option-expandable': expandable,
|
||||
'ion-activatable': true,
|
||||
|
||||
@@ -77,6 +77,8 @@ ion-item-options {
|
||||
|
||||
ion-item-options {
|
||||
display: flex;
|
||||
|
||||
visibility: hidden;
|
||||
}
|
||||
|
||||
&.item-sliding-active-options-start .item-options-start,
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import { Component, ComponentInterface, Element, Event, EventEmitter, Method, Prop } from '@stencil/core';
|
||||
|
||||
import { Side } from '../../interface';
|
||||
import { Mode, Side } from '../../interface';
|
||||
import { isEndSide } from '../../utils/helpers';
|
||||
|
||||
@Component({
|
||||
@@ -11,6 +11,8 @@ import { isEndSide } from '../../utils/helpers';
|
||||
}
|
||||
})
|
||||
export class ItemOptions implements ComponentInterface {
|
||||
mode!: Mode;
|
||||
|
||||
@Element() el!: HTMLElement;
|
||||
|
||||
@Prop({ context: 'window' }) win!: Window;
|
||||
@@ -38,6 +40,11 @@ export class ItemOptions implements ComponentInterface {
|
||||
const isEnd = isEndSide(this.win, this.side);
|
||||
return {
|
||||
class: {
|
||||
[`${this.mode}`]: true,
|
||||
|
||||
// Used internally for styling
|
||||
[`item-options-${this.mode}`]: true,
|
||||
|
||||
'item-options-start': !isEnd,
|
||||
'item-options-end': isEnd
|
||||
}
|
||||
|
||||
@@ -33,7 +33,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 */
|
||||
padding-left: 90%;
|
||||
padding-left: 100%;
|
||||
}
|
||||
|
||||
@include ltr() {
|
||||
@@ -51,7 +51,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 */
|
||||
padding-right: 90%;
|
||||
padding-right: 100%;
|
||||
}
|
||||
|
||||
@include ltr() {
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import { Component, ComponentInterface, Element, Event, EventEmitter, Method, Prop, QueueApi, State, Watch } from '@stencil/core';
|
||||
|
||||
import { Gesture, GestureDetail } from '../../interface';
|
||||
import { Gesture, GestureDetail, Mode } from '../../interface';
|
||||
|
||||
const SWIPE_MARGIN = 30;
|
||||
const ELASTIC_FACTOR = 0.55;
|
||||
@@ -29,6 +29,7 @@ let openSlidingItem: HTMLIonItemSlidingElement | undefined;
|
||||
styleUrl: 'item-sliding.scss'
|
||||
})
|
||||
export class ItemSliding implements ComponentInterface {
|
||||
mode!: Mode;
|
||||
|
||||
private item: HTMLIonItemElement | null = null;
|
||||
private openAmount = 0;
|
||||
@@ -307,6 +308,7 @@ export class ItemSliding implements ComponentInterface {
|
||||
hostData() {
|
||||
return {
|
||||
class: {
|
||||
[`${this.mode}`]: true,
|
||||
'item-sliding-active-slide': (this.state !== SlidingState.Disabled),
|
||||
'item-sliding-active-options-end': (this.state & SlidingState.End) !== 0,
|
||||
'item-sliding-active-options-start': (this.state & SlidingState.Start) !== 0,
|
||||
|
||||
@@ -310,6 +310,44 @@
|
||||
</ion-item>
|
||||
</ion-item-sliding>
|
||||
|
||||
<ion-item-sliding id="item10">
|
||||
<ion-item detail>
|
||||
<ion-label text-wrap>
|
||||
<h2>RIGHT/LEFT side - many buttons</h2>
|
||||
<p>Use mobile emulator to check</p>
|
||||
</ion-label>
|
||||
</ion-item>
|
||||
<ion-item-options side="start" class="sliding-enabled">
|
||||
<ion-item-option color="primary" expandable>
|
||||
<ion-icon name="ios-checkmark"></ion-icon>Btn 1
|
||||
</ion-item-option>
|
||||
<ion-item-option color="secondary" expandable>
|
||||
<ion-icon name="ios-checkmark"></ion-icon>Btn 2
|
||||
</ion-item-option>
|
||||
<ion-item-option color="danger" expandable>
|
||||
<ion-icon name="ios-checkmark"></ion-icon>Btn 3
|
||||
</ion-item-option>
|
||||
<ion-item-option color="tertiary" expandable>
|
||||
<ion-icon name="ios-checkmark"></ion-icon>Btn 4
|
||||
</ion-item-option>
|
||||
</ion-item-options>
|
||||
|
||||
<ion-item-options side="end" class="sliding-enabled">
|
||||
<ion-item-option color="primary" expandable>
|
||||
<ion-icon name="mail"></ion-icon>Btn 5
|
||||
</ion-item-option>
|
||||
<ion-item-option color="secondary" expandable>
|
||||
<ion-icon name="mail"></ion-icon>Btn 6
|
||||
</ion-item-option>
|
||||
<ion-item-option color="danger" expandable>
|
||||
<ion-icon name="mail"></ion-icon>Btn 7
|
||||
</ion-item-option>
|
||||
<ion-item-option color="tertiary" expandable>
|
||||
<ion-icon name="mail"></ion-icon>Btn 8
|
||||
</ion-item-option>
|
||||
</ion-item-options>
|
||||
</ion-item-sliding>
|
||||
|
||||
<ion-item>
|
||||
<ion-label text-wrap>
|
||||
<h2>Normal ion-item (no sliding)</h2>
|
||||
|
||||
@@ -245,7 +245,7 @@
|
||||
|
||||
:host(.item-label-floating),
|
||||
:host(.item-label-stacked) {
|
||||
--min-height: 65px;
|
||||
--min-height: 55px;
|
||||
}
|
||||
|
||||
// TODO: refactor, ion-item and ion-textarea have the same CSS
|
||||
|
||||
@@ -181,6 +181,9 @@ button, a {
|
||||
|
||||
display: flex;
|
||||
|
||||
/* This is required to work with an inset highlight */
|
||||
position: relative;
|
||||
|
||||
flex: 1;
|
||||
flex-direction: inherit;
|
||||
align-items: inherit;
|
||||
|
||||
@@ -136,10 +136,11 @@ export class Item implements ComponentInterface {
|
||||
class: {
|
||||
...childStyles,
|
||||
...createColorClasses(this.color),
|
||||
'item': true,
|
||||
[`${this.mode}`]: true,
|
||||
[`item-lines-${this.lines}`]: this.lines !== undefined,
|
||||
'item-disabled': this.disabled,
|
||||
'in-list': hostContext('ion-list', this.el),
|
||||
'item': true,
|
||||
'item-multiple-inputs': this.multipleInputs,
|
||||
'ion-activatable': this.isClickable(),
|
||||
'ion-focusable': true,
|
||||
|
||||
@@ -33,6 +33,12 @@
|
||||
color: $label-ios-text-color-focused;
|
||||
}
|
||||
|
||||
:host-context(.item-has-focus).label-floating,
|
||||
:host-context(.item-has-placeholder).label-floating,
|
||||
:host-context(.item-has-value).label-floating {
|
||||
@include transform(translate3d(0, 0, 0), scale(.8));
|
||||
}
|
||||
|
||||
|
||||
// iOS Typography
|
||||
// --------------------------------------------------
|
||||
|
||||
@@ -13,19 +13,30 @@
|
||||
// --------------------------------------------------
|
||||
|
||||
:host(.label-stacked) {
|
||||
font-size: 12.8px;
|
||||
@include transform-origin(start, top);
|
||||
@include transform(translate3d(0, 50%, 0), scale(.75));
|
||||
}
|
||||
|
||||
:host(.label-floating) {
|
||||
@include transform(translate3d(0, 27px, 0));
|
||||
@include transform(translate3d(0, 96%, 0));
|
||||
@include transform-origin(start, top);
|
||||
|
||||
transition: transform 150ms ease-in-out;
|
||||
transition: transform 150ms cubic-bezier(.4,0,.2,1);
|
||||
}
|
||||
|
||||
:host(.label-stacked),
|
||||
:host(.label-floating) {
|
||||
@include margin(null, null, 0, 0);
|
||||
@include margin(0, 0, 0, 0);
|
||||
}
|
||||
|
||||
:host-context(.item-select).label-floating {
|
||||
@include transform(translate3d(0, 130%, 0));
|
||||
}
|
||||
|
||||
:host-context(.item-has-focus).label-floating,
|
||||
:host-context(.item-has-placeholder).label-floating,
|
||||
:host-context(.item-has-value).label-floating {
|
||||
@include transform(translate3d(0, 50%, 0), scale(.75));
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -46,6 +46,10 @@
|
||||
pointer-events: none;
|
||||
}
|
||||
|
||||
:host-context(.item-textarea) {
|
||||
align-self: baseline;
|
||||
}
|
||||
|
||||
|
||||
// Fixed Inputs
|
||||
// --------------------------------------------------
|
||||
@@ -71,12 +75,6 @@
|
||||
max-width: 100%;
|
||||
}
|
||||
|
||||
:host-context(.item-has-focus).label-floating,
|
||||
:host-context(.item-has-placeholder).label-floating,
|
||||
:host-context(.item-has-value).label-floating {
|
||||
@include transform(translate3d(0, 0, 0), scale(.8));
|
||||
}
|
||||
|
||||
:host(.label-no-animate.label-floating) {
|
||||
transition: none;
|
||||
}
|
||||
|
||||
@@ -70,6 +70,7 @@ export class Label implements ComponentInterface {
|
||||
return {
|
||||
class: {
|
||||
...createColorClasses(this.color),
|
||||
[`${this.mode}`]: true,
|
||||
[`label-${position}`]: position !== undefined,
|
||||
[`label-no-animate`]: (this.noAnimate)
|
||||
}
|
||||
|
||||
@@ -27,7 +27,10 @@ export class ListHeader implements ComponentInterface {
|
||||
|
||||
hostData() {
|
||||
return {
|
||||
class: createColorClasses(this.color)
|
||||
class: {
|
||||
...createColorClasses(this.color),
|
||||
[`${this.mode}`]: true,
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
import { Component, ComponentInterface, Element, Method, Prop } from '@stencil/core';
|
||||
|
||||
import { Mode } from '../../interface';
|
||||
import { createThemedClasses } from '../../utils/theme';
|
||||
|
||||
@Component({
|
||||
tag: 'ion-list',
|
||||
@@ -47,9 +46,13 @@ export class List implements ComponentInterface {
|
||||
hostData() {
|
||||
return {
|
||||
class: {
|
||||
...createThemedClasses(this.mode, 'list'),
|
||||
[`list-lines-${this.lines}`]: this.lines !== undefined,
|
||||
[`${this.mode}`]: true,
|
||||
|
||||
// Used internally for styling
|
||||
[`list-${this.mode}`]: true,
|
||||
|
||||
'list-inset': this.inset,
|
||||
[`list-lines-${this.lines}`]: this.lines !== undefined,
|
||||
[`list-${this.mode}-lines-${this.lines}`]: this.lines !== undefined
|
||||
}
|
||||
};
|
||||
|
||||
@@ -174,6 +174,7 @@ export class Loading implements ComponentInterface, OverlayInterface {
|
||||
},
|
||||
class: {
|
||||
...getClassMap(this.cssClass),
|
||||
[`${this.mode}`]: true,
|
||||
'loading-translucent': this.translucent
|
||||
}
|
||||
};
|
||||
|
||||
@@ -1,18 +1,14 @@
|
||||
import { newE2EPage } from '@stencil/core/testing';
|
||||
|
||||
import { cleanScreenshotName, generateE2EUrl } from '../../../utils/test/utils';
|
||||
import { generateE2EUrl } from '../../../utils/test/utils';
|
||||
|
||||
export async function testLoading(
|
||||
type: string,
|
||||
selector: string,
|
||||
rtl = false,
|
||||
screenshotName: string = cleanScreenshotName(selector)
|
||||
rtl = false
|
||||
) {
|
||||
try {
|
||||
const pageUrl = generateE2EUrl('loading', type, rtl);
|
||||
if (rtl) {
|
||||
screenshotName = `${screenshotName} rtl`;
|
||||
}
|
||||
|
||||
const page = await newE2EPage({
|
||||
url: pageUrl
|
||||
@@ -28,12 +24,12 @@ export async function testLoading(
|
||||
|
||||
await loading.waitForVisible();
|
||||
|
||||
screenshotCompares.push(await page.compareScreenshot(screenshotName));
|
||||
screenshotCompares.push(await page.compareScreenshot());
|
||||
|
||||
await loading.callMethod('dismiss');
|
||||
await loading.waitForNotVisible();
|
||||
|
||||
screenshotCompares.push(await page.compareScreenshot(`dismiss ${screenshotName}`));
|
||||
screenshotCompares.push(await page.compareScreenshot('dismiss'));
|
||||
|
||||
loading = await page.find('ion-loading');
|
||||
expect(loading).toBeNull();
|
||||
|
||||
@@ -39,6 +39,7 @@ export class MenuButton implements ComponentInterface {
|
||||
hostData() {
|
||||
return {
|
||||
class: {
|
||||
[`${this.mode}`]: true,
|
||||
'button': true, // ion-buttons target .button
|
||||
'ion-activatable': true,
|
||||
}
|
||||
|
||||
@@ -1,11 +1,14 @@
|
||||
import { Component, ComponentInterface, Listen, Prop, State } from '@stencil/core';
|
||||
|
||||
import { Mode } from '../../interface';
|
||||
|
||||
@Component({
|
||||
tag: 'ion-menu-toggle',
|
||||
styleUrl: 'menu-toggle.scss',
|
||||
shadow: true
|
||||
})
|
||||
export class MenuToggle implements ComponentInterface {
|
||||
mode!: Mode;
|
||||
|
||||
@Prop({ context: 'document' }) doc!: Document;
|
||||
|
||||
@@ -63,6 +66,7 @@ export class MenuToggle implements ComponentInterface {
|
||||
return {
|
||||
'aria-hidden': hidden ? 'true' : null,
|
||||
class: {
|
||||
[`${this.mode}`]: true,
|
||||
'menu-toggle-hidden': hidden,
|
||||
}
|
||||
};
|
||||
|
||||
@@ -510,6 +510,7 @@ export class Menu implements ComponentInterface, MenuI {
|
||||
return {
|
||||
role: 'complementary',
|
||||
class: {
|
||||
[`${this.mode}`]: true,
|
||||
[`menu-type-${type}`]: true,
|
||||
'menu-enabled': !disabled,
|
||||
'menu-side-end': isEndSide,
|
||||
|
||||
@@ -1,19 +1,15 @@
|
||||
import { newE2EPage } from '@stencil/core/testing';
|
||||
|
||||
import { cleanScreenshotName, generateE2EUrl } from '../../../utils/test/utils';
|
||||
import { generateE2EUrl } from '../../../utils/test/utils';
|
||||
|
||||
export async function testMenu(
|
||||
type: string,
|
||||
selector: string,
|
||||
menuId = '',
|
||||
rtl = false,
|
||||
screenshotName: string = cleanScreenshotName(selector)
|
||||
rtl = false
|
||||
) {
|
||||
try {
|
||||
const pageUrl = generateE2EUrl('menu', type, rtl);
|
||||
if (rtl) {
|
||||
screenshotName = `${screenshotName} rtl`;
|
||||
}
|
||||
|
||||
const page = await newE2EPage({
|
||||
url: pageUrl
|
||||
@@ -32,12 +28,12 @@ export async function testMenu(
|
||||
await menu.callMethod('open');
|
||||
await page.waitFor(250);
|
||||
|
||||
screenshotCompares.push(await page.compareScreenshot(screenshotName));
|
||||
screenshotCompares.push(await page.compareScreenshot());
|
||||
|
||||
await menu.callMethod('close');
|
||||
await page.waitFor(250);
|
||||
|
||||
screenshotCompares.push(await page.compareScreenshot(`dismiss ${screenshotName}`));
|
||||
screenshotCompares.push(await page.compareScreenshot('dismiss'));
|
||||
|
||||
for (const screenshotCompare of screenshotCompares) {
|
||||
expect(screenshotCompare).toMatchScreenshot();
|
||||
|
||||
@@ -3,7 +3,7 @@ import { Component, ComponentInterface, Element, Event, EventEmitter, Listen, Me
|
||||
import { Animation, AnimationBuilder, ComponentProps, ComponentRef, Config, FrameworkDelegate, Mode, OverlayEventDetail, OverlayInterface } from '../../interface';
|
||||
import { attachComponent, detachComponent } from '../../utils/framework-delegate';
|
||||
import { BACKDROP, dismiss, eventMethod, present } from '../../utils/overlays';
|
||||
import { createThemedClasses, getClassMap } from '../../utils/theme';
|
||||
import { getClassMap } from '../../utils/theme';
|
||||
import { deepReady } from '../../utils/transition';
|
||||
|
||||
import { iosEnterAnimation } from './animations/ios.enter';
|
||||
@@ -193,7 +193,7 @@ export class Modal implements ComponentInterface, OverlayInterface {
|
||||
'no-router': true,
|
||||
'aria-modal': 'true',
|
||||
class: {
|
||||
...createThemedClasses(this.mode, 'modal'),
|
||||
[`${this.mode}`]: true,
|
||||
...getClassMap(this.cssClass)
|
||||
},
|
||||
style: {
|
||||
@@ -203,7 +203,10 @@ export class Modal implements ComponentInterface, OverlayInterface {
|
||||
}
|
||||
|
||||
render() {
|
||||
const dialogClasses = createThemedClasses(this.mode, 'modal-wrapper');
|
||||
const dialogClasses = {
|
||||
[`modal-wrapper`]: true,
|
||||
[`${this.mode}`]: true,
|
||||
};
|
||||
|
||||
return [
|
||||
<ion-backdrop visible={this.showBackdrop} tappable={this.backdropDismiss}/>,
|
||||
|
||||
@@ -8,9 +8,9 @@ A Modal is a dialog that appears on top of the app's content, and must be dismis
|
||||
Modals can be created using a [Modal Controller](../modal-controller). They can be customized by passing modal options in the modal controller's create method.
|
||||
|
||||
|
||||
### Passing paramaters
|
||||
### Passing parameters
|
||||
|
||||
When a modal is created, paramaters might be passed to the newly created modal:
|
||||
When a modal is created, parameters might be passed to the newly created modal:
|
||||
|
||||
```ts
|
||||
// Create a modal using MyModalComponent with some initial data
|
||||
@@ -53,7 +53,6 @@ modalController.dismiss({
|
||||
})
|
||||
```
|
||||
|
||||
|
||||
<!-- Auto Generated Below -->
|
||||
|
||||
|
||||
@@ -84,7 +83,7 @@ export class ModalExample {
|
||||
```
|
||||
|
||||
```typescript
|
||||
import { Component } from '@angular/core';
|
||||
import { Component, Input } from '@angular/core';
|
||||
import { NavParams } from '@ionic/angular';
|
||||
|
||||
@Component({
|
||||
@@ -102,6 +101,37 @@ export class ModalExample {
|
||||
}
|
||||
```
|
||||
|
||||
#### Lazy Loading
|
||||
|
||||
When lazy loading a modal, it's important to note that the modal will not be loaded when it is opened, but rather when the module that imports the modal's module is loaded.
|
||||
|
||||
For example, say there exists a `CalendarComponent` and an `EventModal`. The modal is presented by clicking a button in the `CalendarComponent`. In Angular, the `EventModalModule` would need to be included in the `CalendarComponentModule` since the modal is created in the `CalendarComponent`:
|
||||
|
||||
```typescript
|
||||
import { NgModule } from '@angular/core';
|
||||
import { CommonModule } from '@angular/common';
|
||||
import { IonicModule } from '@ionic/angular';
|
||||
|
||||
import { CalendarComponent } from './calendar.component';
|
||||
import { EventModalModule } from '../modals/event/event.module';
|
||||
|
||||
@NgModule({
|
||||
declarations: [
|
||||
CalendarComponent
|
||||
],
|
||||
imports: [
|
||||
IonicModule,
|
||||
CommonModule,
|
||||
EventModalModule
|
||||
],
|
||||
exports: [
|
||||
CalendarComponent
|
||||
]
|
||||
})
|
||||
|
||||
export class CalendarComponentModule {}
|
||||
```
|
||||
|
||||
|
||||
### Javascript
|
||||
|
||||
|
||||
@@ -1,18 +1,14 @@
|
||||
import { newE2EPage } from '@stencil/core/testing';
|
||||
|
||||
import { cleanScreenshotName, generateE2EUrl } from '../../../utils/test/utils';
|
||||
import { generateE2EUrl } from '../../../utils/test/utils';
|
||||
|
||||
export async function testModal(
|
||||
type: string,
|
||||
selector: string,
|
||||
rtl = false,
|
||||
screenshotName: string = cleanScreenshotName(selector)
|
||||
rtl = false
|
||||
) {
|
||||
try {
|
||||
const pageUrl = generateE2EUrl('modal', type, rtl);
|
||||
if (rtl) {
|
||||
screenshotName = `${screenshotName} rtl`;
|
||||
}
|
||||
|
||||
const page = await newE2EPage({
|
||||
url: pageUrl
|
||||
@@ -23,18 +19,18 @@ export async function testModal(
|
||||
await page.click(selector);
|
||||
await page.waitForSelector(selector);
|
||||
|
||||
let popover = await page.find('ion-modal');
|
||||
await popover.waitForVisible();
|
||||
let modal = await page.find('ion-modal');
|
||||
await modal.waitForVisible();
|
||||
|
||||
screenshotCompares.push(await page.compareScreenshot(screenshotName));
|
||||
screenshotCompares.push(await page.compareScreenshot());
|
||||
|
||||
await popover.callMethod('dismiss');
|
||||
await popover.waitForNotVisible();
|
||||
await modal.callMethod('dismiss');
|
||||
await modal.waitForNotVisible();
|
||||
|
||||
screenshotCompares.push(await page.compareScreenshot(`dismiss ${screenshotName}`));
|
||||
screenshotCompares.push(await page.compareScreenshot('dismiss'));
|
||||
|
||||
popover = await page.find('ion-modal');
|
||||
expect(popover).toBeNull();
|
||||
modal = await page.find('ion-modal');
|
||||
expect(modal).toBeNull();
|
||||
|
||||
for (const screenshotCompare of screenshotCompares) {
|
||||
expect(screenshotCompare).toMatchScreenshot();
|
||||
|
||||
@@ -21,7 +21,7 @@ export class ModalExample {
|
||||
```
|
||||
|
||||
```typescript
|
||||
import { Component } from '@angular/core';
|
||||
import { Component, Input } from '@angular/core';
|
||||
import { NavParams } from '@ionic/angular';
|
||||
|
||||
@Component({
|
||||
@@ -38,3 +38,34 @@ export class ModalExample {
|
||||
|
||||
}
|
||||
```
|
||||
|
||||
#### Lazy Loading
|
||||
|
||||
When lazy loading a modal, it's important to note that the modal will not be loaded when it is opened, but rather when the module that imports the modal's module is loaded.
|
||||
|
||||
For example, say there exists a `CalendarComponent` and an `EventModal`. The modal is presented by clicking a button in the `CalendarComponent`. In Angular, the `EventModalModule` would need to be included in the `CalendarComponentModule` since the modal is created in the `CalendarComponent`:
|
||||
|
||||
```typescript
|
||||
import { NgModule } from '@angular/core';
|
||||
import { CommonModule } from '@angular/common';
|
||||
import { IonicModule } from '@ionic/angular';
|
||||
|
||||
import { CalendarComponent } from './calendar.component';
|
||||
import { EventModalModule } from '../modals/event/event.module';
|
||||
|
||||
@NgModule({
|
||||
declarations: [
|
||||
CalendarComponent
|
||||
],
|
||||
imports: [
|
||||
IonicModule,
|
||||
CommonModule,
|
||||
EventModalModule
|
||||
],
|
||||
exports: [
|
||||
CalendarComponent
|
||||
]
|
||||
})
|
||||
|
||||
export class CalendarComponentModule {}
|
||||
```
|
||||
@@ -26,7 +26,10 @@ export class Note implements ComponentInterface {
|
||||
|
||||
hostData() {
|
||||
return {
|
||||
class: createColorClasses(this.color)
|
||||
class: {
|
||||
...createColorClasses(this.color),
|
||||
[`${this.mode}`]: true,
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
@@ -349,6 +349,7 @@ export class PickerColumnCmp implements ComponentInterface {
|
||||
hostData() {
|
||||
return {
|
||||
class: {
|
||||
[`${this.mode}`]: true,
|
||||
'picker-col': true,
|
||||
'picker-opts-left': this.col.align === 'left',
|
||||
'picker-opts-right': this.col.align === 'right'
|
||||
|
||||
@@ -1,18 +1,14 @@
|
||||
import { newE2EPage } from '@stencil/core/testing';
|
||||
|
||||
import { cleanScreenshotName, dragElementBy, generateE2EUrl, listenForEvent, waitForFunctionTestContext } from '../../../utils/test/utils';
|
||||
import { dragElementBy, generateE2EUrl, listenForEvent, waitForFunctionTestContext } from '../../../utils/test/utils';
|
||||
|
||||
export async function testPickerColumn(
|
||||
type: string,
|
||||
selector: string,
|
||||
rtl = false,
|
||||
screenshotName: string = cleanScreenshotName(selector)
|
||||
rtl = false
|
||||
) {
|
||||
try {
|
||||
const pageUrl = generateE2EUrl('picker-column', type, rtl);
|
||||
if (rtl) {
|
||||
screenshotName = `${screenshotName} rtl`;
|
||||
}
|
||||
|
||||
const page = await newE2EPage({
|
||||
url: pageUrl
|
||||
@@ -24,7 +20,7 @@ export async function testPickerColumn(
|
||||
await openButton.click();
|
||||
await page.waitFor(250);
|
||||
|
||||
screenshotCompares.push(await page.compareScreenshot(`${screenshotName}`));
|
||||
screenshotCompares.push(await page.compareScreenshot());
|
||||
|
||||
// Setup counter
|
||||
let colChangeCounter: any;
|
||||
|
||||
@@ -2,7 +2,7 @@ import { Component, ComponentInterface, Element, Event, EventEmitter, Listen, Me
|
||||
|
||||
import { Animation, AnimationBuilder, Config, CssClassMap, Mode, OverlayEventDetail, OverlayInterface, PickerButton, PickerColumn } from '../../interface';
|
||||
import { dismiss, eventMethod, present } from '../../utils/overlays';
|
||||
import { createThemedClasses, getClassMap } from '../../utils/theme';
|
||||
import { getClassMap } from '../../utils/theme';
|
||||
|
||||
import { iosEnterAnimation } from './animations/ios.enter';
|
||||
import { iosLeaveAnimation } from './animations/ios.leave';
|
||||
@@ -204,7 +204,11 @@ export class Picker implements ComponentInterface, OverlayInterface {
|
||||
return {
|
||||
'aria-modal': 'true',
|
||||
class: {
|
||||
...createThemedClasses(this.mode, 'picker'),
|
||||
[`${this.mode}`]: true,
|
||||
|
||||
// Used internally for styling
|
||||
[`picker-${this.mode}`]: true,
|
||||
|
||||
...getClassMap(this.cssClass)
|
||||
},
|
||||
style: {
|
||||
|
||||
@@ -205,6 +205,7 @@ export class Popover implements ComponentInterface, OverlayInterface {
|
||||
},
|
||||
class: {
|
||||
...getClassMap(this.cssClass),
|
||||
[`${this.mode}`]: true,
|
||||
'popover-translucent': this.translucent
|
||||
}
|
||||
};
|
||||
|
||||
@@ -1,18 +1,14 @@
|
||||
import { newE2EPage } from '@stencil/core/testing';
|
||||
|
||||
import { cleanScreenshotName, generateE2EUrl } from '../../../utils/test/utils';
|
||||
import { generateE2EUrl } from '../../../utils/test/utils';
|
||||
|
||||
export async function testPopover(
|
||||
type: string,
|
||||
selector: string,
|
||||
rtl = false,
|
||||
screenshotName: string = cleanScreenshotName(selector)
|
||||
rtl = false
|
||||
) {
|
||||
try {
|
||||
const pageUrl = generateE2EUrl('popover', type, rtl);
|
||||
if (rtl) {
|
||||
screenshotName = `${screenshotName} rtl`;
|
||||
}
|
||||
|
||||
const page = await newE2EPage({
|
||||
url: pageUrl
|
||||
@@ -26,12 +22,12 @@ export async function testPopover(
|
||||
let popover = await page.find('ion-popover');
|
||||
await popover.waitForVisible();
|
||||
|
||||
screenshotCompares.push(await page.compareScreenshot(screenshotName));
|
||||
screenshotCompares.push(await page.compareScreenshot());
|
||||
|
||||
await popover.callMethod('dismiss');
|
||||
await popover.waitForNotVisible();
|
||||
|
||||
screenshotCompares.push(await page.compareScreenshot(`dismiss ${screenshotName}`));
|
||||
screenshotCompares.push(await page.compareScreenshot('dismiss'));
|
||||
|
||||
popover = await page.find('ion-popover');
|
||||
expect(popover).toBeNull();
|
||||
|
||||
@@ -62,6 +62,7 @@ export class ProgressBar implements ComponentInterface {
|
||||
'aria-valuemax': 1,
|
||||
class: {
|
||||
...createColorClasses(color),
|
||||
[`${this.mode}`]: true,
|
||||
[`progress-bar-${type}`]: true,
|
||||
'progress-paused': paused,
|
||||
'progress-bar-reversed': document.dir === 'rtl' ? !reversed : reversed
|
||||
|
||||
@@ -1,11 +1,12 @@
|
||||
import { Component, ComponentInterface, Element, Event, EventEmitter, Listen, Prop, Watch } from '@stencil/core';
|
||||
|
||||
import { RadioGroupChangeEventDetail } from '../../interface';
|
||||
import { Mode, RadioGroupChangeEventDetail } from '../../interface';
|
||||
|
||||
@Component({
|
||||
tag: 'ion-radio-group'
|
||||
})
|
||||
export class RadioGroup implements ComponentInterface {
|
||||
mode!: Mode;
|
||||
|
||||
private inputId = `ion-rg-${radioGroupIds++}`;
|
||||
private labelId = `${this.inputId}-lbl`;
|
||||
@@ -122,7 +123,10 @@ export class RadioGroup implements ComponentInterface {
|
||||
hostData() {
|
||||
return {
|
||||
'role': 'radiogroup',
|
||||
'aria-labelledby': this.labelId
|
||||
'aria-labelledby': this.labelId,
|
||||
class: {
|
||||
[`${this.mode}`]: true,
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
@@ -163,6 +163,7 @@ export class Radio implements ComponentInterface {
|
||||
'aria-labelledby': labelId,
|
||||
class: {
|
||||
...createColorClasses(color),
|
||||
[`${this.mode}`]: true,
|
||||
'in-item': hostContext('ion-item', el),
|
||||
'interactive': true,
|
||||
'radio-checked': checked,
|
||||
|
||||
@@ -379,6 +379,7 @@ export class Range implements ComponentInterface {
|
||||
return {
|
||||
class: {
|
||||
...createColorClasses(this.color),
|
||||
[`${this.mode}`]: true,
|
||||
'in-item': hostContext('ion-item', this.el),
|
||||
'range-disabled': this.disabled,
|
||||
'range-pressed': this.pressedKnob !== undefined,
|
||||
|
||||
@@ -9,12 +9,12 @@ The refresher content contains the text, icon and spinner to display during a pu
|
||||
|
||||
## Properties
|
||||
|
||||
| Property | Attribute | Description | Type | Default |
|
||||
| ------------------- | -------------------- | --------------------------------------------------------- | ------------------------------------------------------------------------------------------------- | ----------- |
|
||||
| `pullingIcon` | `pulling-icon` | A static icon to display when you begin to pull down | `null \| string \| undefined` | `undefined` |
|
||||
| `pullingText` | `pulling-text` | The text you want to display when you begin to pull down | `string \| undefined` | `undefined` |
|
||||
| `refreshingSpinner` | `refreshing-spinner` | An animated SVG spinner that shows when refreshing begins | `"bubbles" \| "circles" \| "crescent" \| "dots" \| "lines" \| "lines-small" \| null \| undefined` | `undefined` |
|
||||
| `refreshingText` | `refreshing-text` | The text you want to display when performing a refresh | `string \| undefined` | `undefined` |
|
||||
| Property | Attribute | Description | Type | Default |
|
||||
| ------------------- | -------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------- | ----------- |
|
||||
| `pullingIcon` | `pulling-icon` | A static icon to display when you begin to pull down | `null \| string \| undefined` | `undefined` |
|
||||
| `pullingText` | `pulling-text` | The text you want to display when you begin to pull down. `pullingText` can accept either plaintext or HTML as a string. To display characters normally reserved for HTML, they must be escaped. For example `<Ionic>` would become `<Ionic>` For more information: [Security Documentation](https://ionicframework.com/docs/faq/security) | `string \| undefined` | `undefined` |
|
||||
| `refreshingSpinner` | `refreshing-spinner` | An animated SVG spinner that shows when refreshing begins | `"bubbles" \| "circles" \| "crescent" \| "dots" \| "lines" \| "lines-small" \| null \| undefined` | `undefined` |
|
||||
| `refreshingText` | `refreshing-text` | The text you want to display when performing a refresh. `refreshingText` can accept either plaintext or HTML as a string. To display characters normally reserved for HTML, they must be escaped. For example `<Ionic>` would become `<Ionic>` For more information: [Security Documentation](https://ionicframework.com/docs/faq/security) | `string \| undefined` | `undefined` |
|
||||
|
||||
|
||||
----------------------------------------------
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user