mirror of
https://github.com/ionic-team/ionic-framework.git
synced 2026-03-13 10:22:08 +08:00
Compare commits
273 Commits
v5.0.0-rc.
...
motion
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
ede6289bc6 | ||
|
|
f077f0aac7 | ||
|
|
9c64308f0d | ||
|
|
795783311a | ||
|
|
f3e8d4c31d | ||
|
|
7fb38d1e12 | ||
|
|
9f9ba235ee | ||
|
|
187917c746 | ||
|
|
137c49d70b | ||
|
|
5bf83b80d7 | ||
|
|
c7e94a1f23 | ||
|
|
1ed81693f2 | ||
|
|
5f2001c43c | ||
|
|
882f8fef07 | ||
|
|
323e15003f | ||
|
|
53fc8e37c8 | ||
|
|
29d208de88 | ||
|
|
5285824da5 | ||
|
|
2dac12c577 | ||
|
|
7703da28f8 | ||
|
|
1ea5ce5839 | ||
|
|
33be1f061e | ||
|
|
e53f0241e2 | ||
|
|
4af54a2fea | ||
|
|
4fd7c0cc5a | ||
|
|
32906048a4 | ||
|
|
829a0d9be5 | ||
|
|
c680705162 | ||
|
|
60be68ca6d | ||
|
|
28c5e14434 | ||
|
|
237748049c | ||
|
|
a4be67aeb8 | ||
|
|
ec4c0fe5bd | ||
|
|
cc780c80b2 | ||
|
|
eaf4fb6b2a | ||
|
|
94c3d481e9 | ||
|
|
3937101e5c | ||
|
|
16a03d58ec | ||
|
|
448dfa0a69 | ||
|
|
39bfaeaa79 | ||
|
|
f954d40453 | ||
|
|
dd4cb706ff | ||
|
|
50678c03c9 | ||
|
|
898401a7e0 | ||
|
|
687122127c | ||
|
|
703ef5c992 | ||
|
|
85cc35ee91 | ||
|
|
7166a290cc | ||
|
|
1e6f92377a | ||
|
|
8e11ecc136 | ||
|
|
1fbdb2255e | ||
|
|
0c13f25bbb | ||
|
|
9d0dcbbd31 | ||
|
|
f23f1cb37e | ||
|
|
f334e83a43 | ||
|
|
bb62023a0c | ||
|
|
cae389bd12 | ||
|
|
9308f0329c | ||
|
|
042686c7a4 | ||
|
|
43f9d24824 | ||
|
|
ae5f1ddff0 | ||
|
|
dea9248763 | ||
|
|
eab3373213 | ||
|
|
bcf0fa17a9 | ||
|
|
a261cb1f67 | ||
|
|
6bc62e1da5 | ||
|
|
04ace4c983 | ||
|
|
83dcc7168a | ||
|
|
c53b136dbe | ||
|
|
fc2be8d08b | ||
|
|
c54911f451 | ||
|
|
fa9ddc91bc | ||
|
|
578ab93d29 | ||
|
|
64144960b0 | ||
|
|
3821c0463a | ||
|
|
429edb053b | ||
|
|
15203de08b | ||
|
|
671802f9a2 | ||
|
|
14c226ce75 | ||
|
|
66e8e6404d | ||
|
|
4bd9134473 | ||
|
|
1b11ff7fb9 | ||
|
|
32ecdd6753 | ||
|
|
32ee040e3f | ||
|
|
1622d9bb3c | ||
|
|
a75e8f34d6 | ||
|
|
e585a22ac9 | ||
|
|
395d7ec5a3 | ||
|
|
71c7284ed5 | ||
|
|
0a33a095f1 | ||
|
|
50bc212d0b | ||
|
|
76ca475734 | ||
|
|
63c75edd21 | ||
|
|
d4b9151396 | ||
|
|
228ca2b093 | ||
|
|
ba20209604 | ||
|
|
619f67a00b | ||
|
|
d2b772f19f | ||
|
|
15a603b397 | ||
|
|
30a1c89688 | ||
|
|
63d8f6239c | ||
|
|
ae0a98924f | ||
|
|
e442324753 | ||
|
|
57b2a6b0cc | ||
|
|
497380743d | ||
|
|
6a167172ff | ||
|
|
fe175380d2 | ||
|
|
e90683a713 | ||
|
|
3efaf43821 | ||
|
|
102a842bd2 | ||
|
|
7a21708d24 | ||
|
|
8a02b28efe | ||
|
|
6f13b8c792 | ||
|
|
acaa1d9ef7 | ||
|
|
5b9840508f | ||
|
|
4e28445ecb | ||
|
|
e23dec5eb9 | ||
|
|
e0f3c09bab | ||
|
|
6fac5ff7fc | ||
|
|
3123a318b6 | ||
|
|
e5e02d4f88 | ||
|
|
bd64509bae | ||
|
|
9b534bd43f | ||
|
|
8a161f053f | ||
|
|
af1a6d6d6d | ||
|
|
5816cf52a7 | ||
|
|
7c5661fcfb | ||
|
|
2b854ec2cc | ||
|
|
3a269e27b6 | ||
|
|
576da29ac6 | ||
|
|
6ed1c51321 | ||
|
|
75bae403e9 | ||
|
|
321140ff73 | ||
|
|
d3d7de121b | ||
|
|
43fbd9d2f2 | ||
|
|
dff3816c04 | ||
|
|
3bd6b5def2 | ||
|
|
2707289b36 | ||
|
|
d91e22d820 | ||
|
|
5a20f84aa4 | ||
|
|
71f118201b | ||
|
|
8bd5bace73 | ||
|
|
a3fc77be91 | ||
|
|
14ac8ae24c | ||
|
|
b1a87c8892 | ||
|
|
cdfd50b554 | ||
|
|
7bc51911f6 | ||
|
|
253cd96164 | ||
|
|
12932dd202 | ||
|
|
f23ac44c9a | ||
|
|
2d5d2515be | ||
|
|
e24060ecd9 | ||
|
|
0514b421ec | ||
|
|
0897c3f9c2 | ||
|
|
f2dbe1ff3b | ||
|
|
2ece194a08 | ||
|
|
ab146c96ec | ||
|
|
364a0a63da | ||
|
|
ae7fe543fe | ||
|
|
794c3d4e96 | ||
|
|
e2cba41e32 | ||
|
|
f340cb64c8 | ||
|
|
645578c66b | ||
|
|
df27793702 | ||
|
|
8680c2e83b | ||
|
|
8660e61b96 | ||
|
|
976e68da5b | ||
|
|
7a4ddde5ce | ||
|
|
2796e9453f | ||
|
|
c68160ecd3 | ||
|
|
879b90c3c4 | ||
|
|
dae1ce8526 | ||
|
|
f86c82639f | ||
|
|
de28bd3b79 | ||
|
|
0b134dfebf | ||
|
|
8b6536098a | ||
|
|
39e6c8f55b | ||
|
|
3514dd8362 | ||
|
|
e2df046eff | ||
|
|
0e91c6c502 | ||
|
|
cfc6773cb9 | ||
|
|
2982c95993 | ||
|
|
bfb78abda0 | ||
|
|
5049d19917 | ||
|
|
13e4e5b03d | ||
|
|
ac229528eb | ||
|
|
f9f3095eb4 | ||
|
|
572f7b6934 | ||
|
|
4d34ce6a31 | ||
|
|
d53595eb16 | ||
|
|
a1bf2f5b8f | ||
|
|
7ecde36f9d | ||
|
|
87a27216d0 | ||
|
|
f6c3ba7e5a | ||
|
|
f796074f33 | ||
|
|
7d260b96a7 | ||
|
|
22d5256810 | ||
|
|
b6c2a77deb | ||
|
|
ec4878ac08 | ||
|
|
314dbb1a4d | ||
|
|
44993b7987 | ||
|
|
f64b1420ae | ||
|
|
21774612d8 | ||
|
|
a360ea6d19 | ||
|
|
36f98eda1b | ||
|
|
b11ae5da67 | ||
|
|
dff1ffd124 | ||
|
|
c1d7bf229d | ||
|
|
0e0e401d86 | ||
|
|
b84822e674 | ||
|
|
8e71317de4 | ||
|
|
5a87a728e1 | ||
|
|
fe8d74d08c | ||
|
|
11d8c14d72 | ||
|
|
686325e0ec | ||
|
|
926ac3fb47 | ||
|
|
20af652a1b | ||
|
|
e3e5c69681 | ||
|
|
fcf97465f5 | ||
|
|
b5310effe3 | ||
|
|
0224bed0c9 | ||
|
|
cefb08fe32 | ||
|
|
71875417f2 | ||
|
|
6b2a929cd7 | ||
|
|
8d3ce8d29c | ||
|
|
3a2d82814b | ||
|
|
ad6fac83cb | ||
|
|
714ecaae65 | ||
|
|
972e361bdc | ||
|
|
fa9b78e775 | ||
|
|
a826b6dff5 | ||
|
|
34f8576b95 | ||
|
|
59fa340650 | ||
|
|
06b828b4ff | ||
|
|
3252c2f8dc | ||
|
|
800a9339bc | ||
|
|
dd32a5e278 | ||
|
|
ce41d90715 | ||
|
|
4d50064764 | ||
|
|
7a461c59c5 | ||
|
|
9b5854d797 | ||
|
|
e42c85d641 | ||
|
|
45d03baf98 | ||
|
|
82670fe4d0 | ||
|
|
c0aadd6007 | ||
|
|
b6fbe98812 | ||
|
|
27a219874c | ||
|
|
c4fb31403e | ||
|
|
89bf08b627 | ||
|
|
abf594aa61 | ||
|
|
86ab77a6e2 | ||
|
|
c16de96633 | ||
|
|
4d6e15ab18 | ||
|
|
f61b671844 | ||
|
|
99d6069ecb | ||
|
|
e3364f283f | ||
|
|
054223b79c | ||
|
|
6bfdaeed86 | ||
|
|
0b182a9c66 | ||
|
|
d21b5df523 | ||
|
|
0daca31f38 | ||
|
|
fd9c7a9601 | ||
|
|
61f0faccdb | ||
|
|
f303acc99a | ||
|
|
3d6f287d87 | ||
|
|
3403574f31 | ||
|
|
a6764c4724 | ||
|
|
aa663b76cc | ||
|
|
e8886e98f1 | ||
|
|
fd1b44a40b | ||
|
|
916f6670a0 | ||
|
|
11d39457d5 | ||
|
|
cfcdd97cc0 |
30
.github/CONTRIBUTING.md
vendored
30
.github/CONTRIBUTING.md
vendored
@@ -4,6 +4,7 @@ Thanks for your interest in contributing to the Ionic Framework! :tada:
|
||||
|
||||
- [Contributing Etiquette](#contributing-etiquette)
|
||||
- [Creating an Issue](#creating-an-issue)
|
||||
* [Creating a Good Code Reproduction](#creating-a-good-code-reproduction)
|
||||
- [Creating a Pull Request](#creating-a-pull-request)
|
||||
* [Setup](#setup)
|
||||
* [Core](#core)
|
||||
@@ -40,13 +41,40 @@ Please see our [Contributor Code of Conduct](https://github.com/ionic-team/ionic
|
||||
|
||||
* The issue list of this repository is exclusively for bug reports and feature requests. Non-conforming issues will be closed immediately.
|
||||
|
||||
* Issues with no clear steps to reproduce will not be triaged. If an issue is labeled with "needs: reply" and receives no further replies from the author of the issue for more than 30 days, it will be closed.
|
||||
* Issues with no clear steps to reproduce will not be triaged. If an issue is labeled with "needs: reply" and receives no further replies from the author of the issue for more than 14 days, it will be closed.
|
||||
|
||||
* If you think you have found a bug, or have a new feature idea, please start by making sure it hasn't already been [reported](https://github.com/ionic-team/ionic/issues?utf8=%E2%9C%93&q=is%3Aissue). You can search through existing issues to see if there is a similar one reported. Include closed issues as it may have been closed with a solution.
|
||||
|
||||
* Next, [create a new issue](https://github.com/ionic-team/ionic/issues/new/choose) that thoroughly explains the problem. Please fill out the populated issue form before submitting the issue.
|
||||
|
||||
|
||||
## Creating a Good Code Reproduction
|
||||
|
||||
### What is a Code Reproduction?
|
||||
|
||||
A code reproduction is a small application that is built to demonstrate a particular issue. The code reproduction should contain the minimum amount of code needed to recreate the issue and should focus on a single issue.
|
||||
|
||||
### Why Should You Create a Reproduction?
|
||||
|
||||
A code reproduction of the issue you are experiencing helps us better isolate the cause of the problem. This is an important first step to getting any bug fixed!
|
||||
|
||||
Without a reliable code reproduction, it is unlikely we will be able to resolve the issue, leading to it being closed. In other words, creating a code reproduction of the issue helps us help you.
|
||||
|
||||
### How to Create a Reproduction
|
||||
|
||||
* Create a new Ionic application using one of our starter templates. The `blank` starter application is a great choice for this. You can create one using the following Ionic CLI command: `ionic start myApp blank`
|
||||
* Add the minimum amount of code needed to recreate the issue you are experiencing. Do not include anything that is not required to reproduce the issue. This includes any 3rd party plugins you have installed.
|
||||
* Publish the application on GitHub and include a link to it when [creating an issue](#creating-an-issue).
|
||||
* Be sure to include steps to reproduce the issue. These steps should be clear and easy to follow.
|
||||
|
||||
### Benefits of Creating a Reproduction
|
||||
|
||||
* **Uses the latest version of Ionic:** By creating a new Ionic application, you are ensuring that you are testing against the latest version of the framework. Sometimes the issues you are experiencing have already been resolved in a newer version of the framework!
|
||||
* **Minimal surface area:** By removing code that is not needed in order to reproduce the issue, it makes it easier to identify the cause of the issue.
|
||||
* **No secret code needed:** Creating a minimal reproduction of the issue prevents you from having to publish any proprietary code used in your project.
|
||||
* **Get help fixing the issue:** If we can reliably reproduce an issue, there is a good chance we will be able to address it.
|
||||
|
||||
|
||||
## Creating a Pull Request
|
||||
|
||||
* We appreciate you taking the time to contribute! Before submitting a pull request, we ask that you please [create an issue](#creating-an-issue) that explains the bug or feature request and let us know that you plan on creating a pull request for it. If an issue already exists, please comment on that issue letting us know you would like to submit a pull request for it. This helps us to keep track of the pull request and make sure there isn't duplicated effort.
|
||||
|
||||
36
.github/ionic-issue-bot.yml
vendored
36
.github/ionic-issue-bot.yml
vendored
@@ -21,6 +21,16 @@ comment:
|
||||
|
||||
|
||||
Thank you!
|
||||
- label: "ionitron: needs reproduction"
|
||||
message: >
|
||||
Thanks for the issue! This issue has been labeled as `needs reproduction`. This label
|
||||
is added to issues that need a code reproduction.
|
||||
|
||||
|
||||
Please provide a reproduction with the minimum amount of code required to reproduce the issue. Without a reliable code reproduction, it is unlikely we will be able to resolve the issue, leading to it being closed.
|
||||
|
||||
|
||||
For a guide on how to create a good reproduction, see our [Contributing Guide](https://ionicframework.com/docs/contributing/how-to-contribute#creating-a-good-code-reproduction).
|
||||
dryRun: false
|
||||
|
||||
closeAndLock:
|
||||
@@ -65,8 +75,10 @@ stale:
|
||||
days: 365
|
||||
maxIssuesPerRun: 100
|
||||
exemptLabels:
|
||||
- good first issue
|
||||
- triage
|
||||
- "good first issue"
|
||||
- "triage"
|
||||
- "type: bug"
|
||||
- "type: feature request"
|
||||
exemptAssigned: true
|
||||
exemptProjects: true
|
||||
exemptMilestones: true
|
||||
@@ -83,7 +95,7 @@ stale:
|
||||
dryRun: false
|
||||
|
||||
noReply:
|
||||
days: 30
|
||||
days: 14
|
||||
maxIssuesPerRun: 100
|
||||
label: "needs: reply"
|
||||
responseLabel: triage
|
||||
@@ -95,6 +107,24 @@ noReply:
|
||||
template is fully filled out.
|
||||
|
||||
|
||||
Thank you for using Ionic!
|
||||
close: true
|
||||
lock: true
|
||||
dryRun: false
|
||||
|
||||
noReproduction:
|
||||
days: 14
|
||||
maxIssuesPerRun: 100
|
||||
label: "ionitron: needs reproduction"
|
||||
responseLabel: triage
|
||||
exemptProjects: true
|
||||
exemptMilestones: true
|
||||
message: >
|
||||
Thanks for the issue! This issue is being closed due to the lack of a code reproduction. If this is still
|
||||
an issue with the latest version of Ionic, please create a new issue and ensure the
|
||||
template is fully filled out.
|
||||
|
||||
|
||||
Thank you for using Ionic!
|
||||
close: true
|
||||
lock: true
|
||||
|
||||
7
.github/weekly-digest.yml
vendored
7
.github/weekly-digest.yml
vendored
@@ -1,7 +0,0 @@
|
||||
# Configuration for weekly-digest - https://github.com/apps/weekly-digest
|
||||
publishDay: wed
|
||||
canPublishIssues: true
|
||||
canPublishPullRequests: true
|
||||
canPublishContributors: true
|
||||
canPublishStargazers: true
|
||||
canPublishCommits: true
|
||||
@@ -4,7 +4,7 @@ const execa = require('execa');
|
||||
const inquirer = require('inquirer');
|
||||
const Listr = require('listr');
|
||||
const semver = require('semver');
|
||||
const tc = require('turbocolor');
|
||||
const { bold, cyan, dim } = require('colorette');
|
||||
|
||||
const rootDir = path.join(__dirname, '../');
|
||||
|
||||
@@ -36,13 +36,13 @@ function projectPath(project) {
|
||||
return path.join(rootDir, project);
|
||||
}
|
||||
|
||||
async function askTag() {
|
||||
async function askNpmTag(version) {
|
||||
const prompts = [
|
||||
{
|
||||
type: 'list',
|
||||
name: 'tag',
|
||||
name: 'npmTag',
|
||||
message: 'Select npm tag or specify a new tag',
|
||||
choices: ['latest', 'next']
|
||||
choices: ['latest', 'next', 'v4-lts']
|
||||
.concat([
|
||||
new inquirer.Separator(),
|
||||
{
|
||||
@@ -55,13 +55,13 @@ async function askTag() {
|
||||
type: 'confirm',
|
||||
name: 'confirm',
|
||||
message: answers => {
|
||||
return `Will publish to ${tc.cyan(answers.tag)}. Continue?`;
|
||||
return `Will publish ${cyan(version)} to ${cyan(answers.npmTag)}. Continue?`;
|
||||
}
|
||||
}
|
||||
];
|
||||
|
||||
const { tag, confirm } = await inquirer.prompt(prompts);
|
||||
return { tag, confirm };
|
||||
const { npmTag, confirm } = await inquirer.prompt(prompts);
|
||||
return { npmTag, confirm };
|
||||
}
|
||||
|
||||
function checkGit(tasks) {
|
||||
@@ -192,7 +192,7 @@ function preparePackage(tasks, package, version, install) {
|
||||
|
||||
// Add project tasks
|
||||
tasks.push({
|
||||
title: `Prepare ${tc.bold(pkg.name)}`,
|
||||
title: `Prepare ${bold(pkg.name)}`,
|
||||
task: () => new Listr(projectTasks)
|
||||
});
|
||||
}
|
||||
@@ -234,7 +234,7 @@ function prepareDevPackage(tasks, package, version) {
|
||||
|
||||
// Add project tasks
|
||||
tasks.push({
|
||||
title: `Prepare dev build: ${tc.bold(pkg.name)}`,
|
||||
title: `Prepare dev build: ${bold(pkg.name)}`,
|
||||
task: () => new Listr(projectTasks)
|
||||
});
|
||||
}
|
||||
@@ -244,7 +244,7 @@ function updatePackageVersions(tasks, packages, version) {
|
||||
updatePackageVersion(tasks, package, version);
|
||||
|
||||
tasks.push({
|
||||
title: `${package} update @ionic/core dependency, if present ${tc.dim(`(${version})`)}`,
|
||||
title: `${package} update @ionic/core dependency, if present ${dim(`(${version})`)}`,
|
||||
task: async () => {
|
||||
if (package !== 'core') {
|
||||
const pkg = readPkg(package);
|
||||
@@ -261,7 +261,7 @@ function updatePackageVersions(tasks, packages, version) {
|
||||
updatePackageVersion(tasks, distPackage, version);
|
||||
|
||||
tasks.push({
|
||||
title: `${package} update @ionic/core dependency, if present ${tc.dim(`(${version})`)}`,
|
||||
title: `${package} update @ionic/core dependency, if present ${dim(`(${version})`)}`,
|
||||
task: async () => {
|
||||
const pkg = readPkg(distPackage);
|
||||
updateDependency(pkg, '@ionic/core', version);
|
||||
@@ -272,7 +272,7 @@ function updatePackageVersions(tasks, packages, version) {
|
||||
|
||||
if (package === 'packages/react-router') {
|
||||
tasks.push({
|
||||
title: `${package} update @ionic/react dependency, if present ${tc.dim(`(${version})`)}`,
|
||||
title: `${package} update @ionic/react dependency, if present ${dim(`(${version})`)}`,
|
||||
task: async () => {
|
||||
const pkg = readPkg(package);
|
||||
updateDependency(pkg, '@ionic/react', version);
|
||||
@@ -287,7 +287,7 @@ function updatePackageVersion(tasks, package, version) {
|
||||
const projectRoot = projectPath(package);
|
||||
|
||||
tasks.push({
|
||||
title: `${package}: update package.json ${tc.dim(`(${version})`)}`,
|
||||
title: `${package}: update package.json ${dim(`(${version})`)}`,
|
||||
task: async () => {
|
||||
await execa('npm', ['version', version], { cwd: projectRoot });
|
||||
}
|
||||
@@ -310,7 +310,7 @@ function copyPackageToDist(tasks, packages) {
|
||||
});
|
||||
}
|
||||
|
||||
function publishPackages(tasks, packages, version, tag = 'latest') {
|
||||
function publishPackages(tasks, packages, version, npmTag = 'latest') {
|
||||
// first verify version
|
||||
packages.forEach(package => {
|
||||
if (package === 'core') {
|
||||
@@ -338,9 +338,9 @@ function publishPackages(tasks, packages, version, tag = 'latest') {
|
||||
}
|
||||
|
||||
tasks.push({
|
||||
title: `${package}: publish to ${tag} tag`,
|
||||
title: `${package}: publish to ${npmTag} tag`,
|
||||
task: async () => {
|
||||
await execa('npm', ['publish', '--tag', tag], { cwd: projectRoot });
|
||||
await execa('npm', ['publish', '--tag', npmTag], { cwd: projectRoot });
|
||||
}
|
||||
});
|
||||
});
|
||||
@@ -375,7 +375,7 @@ function copyCDNLoader(tasks, version) {
|
||||
module.exports = {
|
||||
checkTestDist,
|
||||
checkGit,
|
||||
askTag,
|
||||
askNpmTag,
|
||||
isValidVersion,
|
||||
isVersionGreater,
|
||||
copyCDNLoader,
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
* Deploy script adopted from https://github.com/sindresorhus/np
|
||||
* MIT License (c) Sindre Sorhus (sindresorhus.com)
|
||||
*/
|
||||
const tc = require('turbocolor');
|
||||
const { cyan, dim, red, reset } = require('colorette');
|
||||
const execa = require('execa');
|
||||
const inquirer = require('inquirer');
|
||||
const Listr = require('listr');
|
||||
@@ -34,7 +34,7 @@ async function main() {
|
||||
console.log(` npm run release\n`);
|
||||
|
||||
} catch(err) {
|
||||
console.log('\n', tc.red(err), '\n');
|
||||
console.log('\n', red(err), '\n');
|
||||
process.exit(1);
|
||||
}
|
||||
}
|
||||
@@ -84,7 +84,7 @@ async function askVersion() {
|
||||
type: 'confirm',
|
||||
name: 'confirm',
|
||||
message: answers => {
|
||||
return `Will bump from ${tc.cyan(oldVersion)} to ${tc.cyan(answers.version)}. Continue?`;
|
||||
return `Will bump from ${cyan(oldVersion)} to ${cyan(answers.version)}. Continue?`;
|
||||
}
|
||||
}
|
||||
];
|
||||
@@ -131,7 +131,7 @@ async function preparePackages(packages, version, install) {
|
||||
function validateGit(tasks, version) {
|
||||
tasks.push(
|
||||
{
|
||||
title: `Validate git tag ${tc.dim(`(v${version})`)}`,
|
||||
title: `Validate git tag ${dim(`(v${version})`)}`,
|
||||
task: () => execa('git', ['fetch'])
|
||||
.then(() => {
|
||||
return execa.stdout('npm', ['config', 'get', 'tag-version-prefix']);
|
||||
@@ -198,17 +198,17 @@ function prettyVersionDiff(oldVersion, inc) {
|
||||
|
||||
for (let i = 0; i < newVersion.length; i++) {
|
||||
if ((newVersion[i] !== oldVersion[i] && !firstVersionChange)) {
|
||||
output.push(`${tc.dim.cyan(newVersion[i])}`);
|
||||
output.push(`${dim(cyan(newVersion[i]))}`);
|
||||
firstVersionChange = true;
|
||||
} else if (newVersion[i].indexOf('-') >= 1) {
|
||||
let preVersion = [];
|
||||
preVersion = newVersion[i].split('-');
|
||||
output.push(`${tc.dim.cyan(`${preVersion[0]}-${preVersion[1]}`)}`);
|
||||
output.push(`${dim(cyan(`${preVersion[0]}-${preVersion[1]}`))}`);
|
||||
} else {
|
||||
output.push(tc.reset.dim(newVersion[i]));
|
||||
output.push(reset(dim(newVersion[i])));
|
||||
}
|
||||
}
|
||||
return output.join(tc.reset.dim('.'));
|
||||
return output.join(reset(dim('.')));
|
||||
}
|
||||
|
||||
main();
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
const tc = require('turbocolor');
|
||||
const { cyan, red } = require('colorette');
|
||||
const semver = require('semver');
|
||||
const execa = require('execa');
|
||||
const inquirer = require('inquirer');
|
||||
@@ -47,7 +47,7 @@ async function main() {
|
||||
console.log(`\nionic ${devVersion} published!! 🎉\n`);
|
||||
|
||||
} catch (err) {
|
||||
console.log('\n', tc.red(err), '\n');
|
||||
console.log('\n', red(err), '\n');
|
||||
process.exit(1);
|
||||
}
|
||||
|
||||
@@ -64,7 +64,7 @@ async function askDevVersion(devVersion) {
|
||||
name: 'confirm',
|
||||
value: true,
|
||||
message: () => {
|
||||
return `Publish the dev build ${tc.cyan(devVersion)}?`;
|
||||
return `Publish the dev build ${cyan(devVersion)}?`;
|
||||
}
|
||||
}
|
||||
];
|
||||
|
||||
@@ -2,11 +2,11 @@
|
||||
* Deploy script adopted from https://github.com/sindresorhus/np
|
||||
* MIT License (c) Sindre Sorhus (sindresorhus.com)
|
||||
*/
|
||||
const tc = require('turbocolor');
|
||||
const { cyan, dim, green, red, yellow } = require('colorette');
|
||||
const execa = require('execa');
|
||||
const Listr = require('listr');
|
||||
const path = require('path');
|
||||
const octokit = require('@octokit/rest')()
|
||||
const { Octokit } = require('@octokit/rest');
|
||||
const common = require('./common');
|
||||
const fs = require('fs-extra');
|
||||
|
||||
@@ -28,7 +28,7 @@ async function main() {
|
||||
// repo must be clean
|
||||
common.checkGit(tasks);
|
||||
|
||||
const { tag, confirm } = await common.askTag();
|
||||
const { npmTag, confirm } = await common.askNpmTag(version);
|
||||
|
||||
if (!confirm) {
|
||||
return;
|
||||
@@ -36,10 +36,10 @@ async function main() {
|
||||
|
||||
if(!dryRun) {
|
||||
// publish each package in NPM
|
||||
common.publishPackages(tasks, common.packages, version, tag);
|
||||
common.publishPackages(tasks, common.packages, version, npmTag);
|
||||
|
||||
// push tag to git remote
|
||||
publishGit(tasks, version, changelog);
|
||||
publishGit(tasks, version, changelog, npmTag);
|
||||
}
|
||||
|
||||
const listr = new Listr(tasks);
|
||||
@@ -48,14 +48,14 @@ async function main() {
|
||||
// Dry run doesn't publish to npm or git
|
||||
if (dryRun) {
|
||||
console.log(`
|
||||
\n${tc.yellow('Did not publish. Remove the "--dry-run" flag to publish:')}\n${tc.green(version)} to ${tc.cyan(tag)}\n
|
||||
\n${yellow('Did not publish. Remove the "--dry-run" flag to publish:')}\n${green(version)} to ${cyan(npmTag)}\n
|
||||
`);
|
||||
} else {
|
||||
console.log(`\nionic ${version} published to ${tag}!! 🎉\n`);
|
||||
console.log(`\nionic ${version} published to ${npmTag}!! 🎉\n`);
|
||||
}
|
||||
|
||||
} catch (err) {
|
||||
console.log('\n', tc.red(err), '\n');
|
||||
console.log('\n', red(err), '\n');
|
||||
process.exit(1);
|
||||
}
|
||||
}
|
||||
@@ -70,13 +70,13 @@ function checkProductionRelease() {
|
||||
}
|
||||
}
|
||||
|
||||
function publishGit(tasks, version, changelog) {
|
||||
const tag = `v${version}`;
|
||||
function publishGit(tasks, version, changelog, npmTag) {
|
||||
const gitTag = `v${version}`;
|
||||
|
||||
tasks.push(
|
||||
{
|
||||
title: `Tag latest commit ${tc.dim(`(${tag})`)}`,
|
||||
task: () => execa('git', ['tag', `${tag}`], { cwd: common.rootDir })
|
||||
title: `Tag latest commit ${dim(`(${gitTag})`)}`,
|
||||
task: () => execa('git', ['tag', `${gitTag}`], { cwd: common.rootDir })
|
||||
},
|
||||
{
|
||||
title: 'Push branches to remote',
|
||||
@@ -88,7 +88,7 @@ function publishGit(tasks, version, changelog) {
|
||||
},
|
||||
{
|
||||
title: 'Publish Github release',
|
||||
task: () => publishGithub(version, tag, changelog)
|
||||
task: () => publishGithub(version, gitTag, changelog, npmTag)
|
||||
}
|
||||
);
|
||||
}
|
||||
@@ -100,7 +100,7 @@ function findChangelog() {
|
||||
|
||||
for (let i = 0; i < lines.length; i++) {
|
||||
const line = lines[i];
|
||||
if (line.startsWith('# [')) {
|
||||
if (line.startsWith('## [') || line.startsWith('# [')) {
|
||||
if (start === -1) {
|
||||
start = i + 1;
|
||||
} else {
|
||||
@@ -116,10 +116,12 @@ function findChangelog() {
|
||||
return lines.slice(start, end).join('\n').trim();
|
||||
}
|
||||
|
||||
async function publishGithub(version, tag, changelog) {
|
||||
octokit.authenticate({
|
||||
type: 'oauth',
|
||||
token: process.env.GH_TOKEN
|
||||
async function publishGithub(version, gitTag, changelog, npmTag) {
|
||||
// If the npm tag is next then publish as a prerelease
|
||||
const prerelease = npmTag === 'next' ? true : false;
|
||||
|
||||
const octokit = new Octokit({
|
||||
auth: process.env.GH_TOKEN
|
||||
});
|
||||
|
||||
let branch = await execa.stdout('git', ['symbolic-ref', '--short', 'HEAD']);
|
||||
@@ -132,9 +134,10 @@ async function publishGithub(version, tag, changelog) {
|
||||
owner: 'ionic-team',
|
||||
repo: 'ionic',
|
||||
target_commitish: branch,
|
||||
tag_name: tag,
|
||||
tag_name: gitTag,
|
||||
name: version,
|
||||
body: changelog,
|
||||
prerelease: prerelease
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
@@ -418,7 +418,7 @@ The `inputmode` property for `ion-searchbar` now defaults to `undefined`. To get
|
||||
|
||||
Segment was completely revamped to use the new iOS design including an all new gesture that applies for both Material Design and iOS. Due to these changes, some breaking changes were inevitably introduced in order to support the new design.
|
||||
|
||||
##### Events
|
||||
##### Renamed Events
|
||||
|
||||
`ion-segment` no longer emits an `ionSelect` event. Developers should listen for an `ionChange` event to be emitted on `ion-segment` instead.
|
||||
|
||||
|
||||
270
CHANGELOG.md
270
CHANGELOG.md
@@ -1,3 +1,273 @@
|
||||
## [5.1.1](https://github.com/ionic-team/ionic/compare/v5.1.0...v5.1.1) (2020-05-13)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* **all:** improve scroll assist reliability for below the fold inputs ([#21206](https://github.com/ionic-team/ionic/issues/21206)) ([7166a29](https://github.com/ionic-team/ionic/commit/7166a290cc1dd728e5bab2f7e39b8d41954e3808))
|
||||
* **all:** overlay components no longer display outline when focused ([#21226](https://github.com/ionic-team/ionic/issues/21226)) ([bb62023](https://github.com/ionic-team/ionic/commit/bb62023a0cdc5a64e956766c7d1704797fc8c9ae))
|
||||
* **display:** remove 1px gap between mutually exclusive breakpoints ([#21276](https://github.com/ionic-team/ionic/issues/21276)) ([703ef5c](https://github.com/ionic-team/ionic/commit/703ef5c99284f1e2b8d63c3af411c945dc756e20)), closes [#20993](https://github.com/ionic-team/ionic/issues/20993) [#20743](https://github.com/ionic-team/ionic/issues/20743)
|
||||
* **header:** do not error on collapsible header on devices that do not support IntersectionObserve ([#21222](https://github.com/ionic-team/ionic/issues/21222)) ([0c13f25](https://github.com/ionic-team/ionic/commit/0c13f25bbb4d4674e76cd19b098900f698e7146e))
|
||||
* **input:** check for tabindex and pass it properly to native input ([#21170](https://github.com/ionic-team/ionic/issues/21170)) ([dd4cb70](https://github.com/ionic-team/ionic/commit/dd4cb706ffeebc2069645ea03f0e7a96d6b14d43)), closes [#17515](https://github.com/ionic-team/ionic/issues/17515)
|
||||
* **ios:** position page transition shadow properly under footer ([#21095](https://github.com/ionic-team/ionic/issues/21095)) ([50678c0](https://github.com/ionic-team/ionic/commit/50678c03c9829a87408633dabd77b21da1650a84))
|
||||
* **md:** do not hide page when swipe gesture is cancelled ([#21247](https://github.com/ionic-team/ionic/issues/21247)) ([f334e83](https://github.com/ionic-team/ionic/commit/f334e83a43f855ac1e36eaf73954df6ee27a03af))
|
||||
* **overlays:** respect keyboardClose property when opening overlays ([#21240](https://github.com/ionic-team/ionic/issues/21240)) ([9d0dcbb](https://github.com/ionic-team/ionic/commit/9d0dcbbd31fc34ad8952eacb9864ad1b31636113))
|
||||
* **picker:** haptics now work properly ([#21268](https://github.com/ionic-team/ionic/issues/21268)) ([8e11ecc](https://github.com/ionic-team/ionic/commit/8e11ecc136c61e925e76c0e48ab21611e09b5898))
|
||||
* **refresher:** correctly select shadow root on older browsers ([#21237](https://github.com/ionic-team/ionic/issues/21237)) ([f23f1cb](https://github.com/ionic-team/ionic/commit/f23f1cb37eef02307c357fbb48c0db729974cdc4))
|
||||
* **refresher:** refresher completes even after switching to a new tab ([#21236](https://github.com/ionic-team/ionic/issues/21236)) ([1e6f923](https://github.com/ionic-team/ionic/commit/1e6f92377aaf0804cfd0ddb9b06da7b4c9dc355f))
|
||||
* **segment-button:** screen readers now announce selected state properly ([#21273](https://github.com/ionic-team/ionic/issues/21273)) ([85cc35e](https://github.com/ionic-team/ionic/commit/85cc35ee9163a38c48c6df466a3c036906437804))
|
||||
* **toggle:** screen readers now announce toggle properly ([#21168](https://github.com/ionic-team/ionic/issues/21168)) ([1fbdb22](https://github.com/ionic-team/ionic/commit/1fbdb2255e4ff7fccf22d9ccc12b7f9bb4c3a064))
|
||||
|
||||
|
||||
|
||||
# [5.1.0 Aluminum](https://github.com/ionic-team/ionic/compare/v5.0.7...v5.1.0) (2020-04-30)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* **action-sheet:** show correct cancel button background on dark mode ([#21084](https://github.com/ionic-team/ionic/issues/21084)) ([e442324](https://github.com/ionic-team/ionic/commit/e4423247537cbcda174305ab9fdde4a57c50a88e)), closes [#21082](https://github.com/ionic-team/ionic/issues/21082)
|
||||
* **all:** correctly default gestures to use a passive listener ([#21038](https://github.com/ionic-team/ionic/issues/21038)) ([dea9248](https://github.com/ionic-team/ionic/commit/dea9248763737164e17678119c775cdfc0e53ccd))
|
||||
* **angular:** do not navigate to the same tab if already active ([#21085](https://github.com/ionic-team/ionic/issues/21085)) ([15203de](https://github.com/ionic-team/ionic/commit/15203de08bf97f27e33f35994444c2c4843b3a44)), closes [#21074](https://github.com/ionic-team/ionic/issues/21074) [#19943](https://github.com/ionic-team/ionic/issues/19943)
|
||||
* **back-button:** announce back button text correctly by screen readers ([#21053](https://github.com/ionic-team/ionic/issues/21053)) ([14c226c](https://github.com/ionic-team/ionic/commit/14c226ce75958da14b66821028d6f3a6852d695c)), closes [#21043](https://github.com/ionic-team/ionic/issues/21043)
|
||||
* **datetime:** locale inputs are now reactive ([#20826](https://github.com/ionic-team/ionic/issues/20826)) ([a75e8f3](https://github.com/ionic-team/ionic/commit/a75e8f34d608c167f8d429ddbf39e94173204a61)), closes [#20367](https://github.com/ionic-team/ionic/issues/20367)
|
||||
* **ios:** account for nested tabs with page transition ([#20955](https://github.com/ionic-team/ionic/issues/20955)) ([e23dec5](https://github.com/ionic-team/ionic/commit/e23dec5eb9fbb58eedffabefca8d7d643f49f7b9)), closes [#20948](https://github.com/ionic-team/ionic/issues/20948)
|
||||
* **ios:** properly animate content when navigating from a tabbed page ([#20918](https://github.com/ionic-team/ionic/issues/20918)) ([8a02b28](https://github.com/ionic-team/ionic/commit/8a02b28efeca81c25176ff52508b4005441e8314)), closes [#20912](https://github.com/ionic-team/ionic/issues/20912)
|
||||
* **loading:** correctly announce spinner by screen readers ([#21116](https://github.com/ionic-team/ionic/issues/21116)) ([63d8f62](https://github.com/ionic-team/ionic/commit/63d8f6239cc39e6a111108bd1a2557c297a256ae)), closes [#21107](https://github.com/ionic-team/ionic/issues/21107)
|
||||
* **md:** do not display blank screen when using MD page transition and swipe gesture ([#21058](https://github.com/ionic-team/ionic/issues/21058)) ([4973807](https://github.com/ionic-team/ionic/commit/497380743df4461688455bc8b8440d2f3cc7c247)), closes [#21056](https://github.com/ionic-team/ionic/issues/220800)
|
||||
* **modal:** properly inherit border radius for modals on Safari ([#20887](https://github.com/ionic-team/ionic/issues/20887)) ([bd64509](https://github.com/ionic-team/ionic/commit/bd64509bae9dd4c960134d986ce8150dc1a9d3b4)), closes [#20878](https://github.com/ionic-team/ionic/issues/20878)
|
||||
* **modal:** swipeToClose property is now reactive ([#21073](https://github.com/ionic-team/ionic/issues/21073)) ([4bd9134](https://github.com/ionic-team/ionic/commit/4bd91344730bd26c66a8d838436d94045dc21f78)), closes [#21072](https://github.com/ionic-team/ionic/issues/21072)
|
||||
* **overlays:** focus overlay when presented ([#20997](https://github.com/ionic-team/ionic/issues/20997)) ([fc2be8d](https://github.com/ionic-team/ionic/commit/fc2be8d08bbb495df911783f808d7ca511942172)), closes [#19882](https://github.com/ionic-team/ionic/issues/19882) [#17126](https://github.com/ionic-team/ionic/issues/17126)
|
||||
* **overlays:** prevent accidental clicks when dismissing overlays ([#21093](https://github.com/ionic-team/ionic/issues/21093)) ([671802f](https://github.com/ionic-team/ionic/commit/671802f9a2050d9942e9dfb2db9f9c58bdc58620)), closes [#21092](https://github.com/ionic-team/ionic/issues/21092)
|
||||
* **react:** IonTabBar properly extends IonicReactProps ([#21009](https://github.com/ionic-team/ionic/issues/21009)) ([102a842](https://github.com/ionic-team/ionic/commit/102a842bd2a967c04a3cf42ed4e0811929bd4d99)), closes [#21006](https://github.com/ionic-team/ionic/issues/21006)
|
||||
* **refresher:** properly check for Haptics plugin on web ([#21156](https://github.com/ionic-team/ionic/issues/21156)) ([c53b136](https://github.com/ionic-team/ionic/commit/c53b136dbe7ed7fc0fc298593f8b677a66c77910)), closes [#21148](https://github.com/ionic-team/ionic/issues/21148)
|
||||
* **refresher:** properly calculate content dimensions in native ion-refresher ([#21157](https://github.com/ionic-team/ionic/issues/21157)) ([83dcc71](https://github.com/ionic-team/ionic/commit/83dcc7168a48bc5b05583fb7c01b5eff9d1a67f8))
|
||||
* **router:** account for query string when pushing page ([#21071](https://github.com/ionic-team/ionic/issues/21071)) ([eab3373](https://github.com/ionic-team/ionic/commit/eab33732133bd43ca6788bba6e93a9b545ee058a))
|
||||
* **searchbar:** correctly announce the cancel button text by screen readers ([#21049](https://github.com/ionic-team/ionic/issues/21049)) ([15a603b](https://github.com/ionic-team/ionic/commit/15a603b39797dee6baf7e33d58907f98ced7e86d)), closes [#21013](https://github.com/ionic-team/ionic/issues/21013)
|
||||
* **select:** account for MutationObserver when performing SSR ([#21068](https://github.com/ionic-team/ionic/issues/21068)) ([66e8e64](https://github.com/ionic-team/ionic/commit/66e8e6404d87a2767e71b13bed19706b29ad1b9c)), closes [#21063](https://github.com/ionic-team/ionic/issues/21063)
|
||||
* **slides:** slides no longer break with Angular Ivy enabled ([#20899](https://github.com/ionic-team/ionic/issues/20899)) ([3123a31](https://github.com/ionic-team/ionic/commit/3123a318b6755dbf8fde8476f81c37e6ffa9b70e)), closes [#20356](https://github.com/ionic-team/ionic/issues/20356)
|
||||
* **split-pane:** properly show border in rtl mode ([#20995](https://github.com/ionic-team/ionic/issues/20995)) ([7a21708](https://github.com/ionic-team/ionic/commit/7a21708d24bab6a388e1b55c88337e3d0f7922eb)), closes [#20994](https://github.com/ionic-team/ionic/issues/20994)
|
||||
* **textarea:** height is set correctly when using autoGrow in modals ([#20971](https://github.com/ionic-team/ionic/issues/20971)) ([32ee040](https://github.com/ionic-team/ionic/commit/32ee040e3f0d7012790f190856097d0c6fa0eaa2)), closes [#18993](https://github.com/ionic-team/ionic/issues/18993)
|
||||
|
||||
### Features
|
||||
|
||||
* **all:** add ability to continue processing hardware back button events ([#20613](https://github.com/ionic-team/ionic/issues/20613)) ([3821c04](https://github.com/ionic-team/ionic/commit/3821c0463ae9a02e67c835a221c4ea01fab306d1)), closes [#17824](https://github.com/ionic-team/ionic/issues/17824)
|
||||
* **all:** add ability to eject from Ionic sanitizer ([#20457](https://github.com/ionic-team/ionic/issues/20457)) ([fa9ddc9](https://github.com/ionic-team/ionic/commit/fa9ddc91bc9fefc2bb247cfe7511384f77335476)), closes [#18277](https://github.com/ionic-team/ionic/issues/18277)
|
||||
* **angular:** support multi-app for ng-add schematic ([#20768](https://github.com/ionic-team/ionic/issues/20768)) ([39e6c8f](https://github.com/ionic-team/ionic/commit/39e6c8f55b514b0c7330dd3a790c859bb3410404))
|
||||
* **animation:** add option to clean up old animation stylesheets ([#20940](https://github.com/ionic-team/ionic/issues/20940)) ([5b98405](https://github.com/ionic-team/ionic/commit/5b9840508faf6a2c985726be889c1f2fca0e0733)), closes [#20610](https://github.com/ionic-team/ionic/issues/20610)
|
||||
* **app:** add keyboard open and close events (ionKeyboardDidShow and ionKeyboardDidHide) ([#18478](https://github.com/ionic-team/ionic/issues/18478)) ([ae5f1dd](https://github.com/ionic-team/ionic/commit/ae5f1ddff0c0799167a154abbb418b2ad3434d47))
|
||||
* **back-button:** add backButtonDefaultHref property to Ionic Config ([#20491](https://github.com/ionic-team/ionic/issues/20491)) ([1b11ff7](https://github.com/ionic-team/ionic/commit/1b11ff7fb92b75f5c869c79d5e0d5dfd8889597f)), closes [#19305](https://github.com/ionic-team/ionic/issues/19305)
|
||||
* **checkbox:** add parts support for container, mark ([#20950](https://github.com/ionic-team/ionic/issues/20950)) ([d4b9151](https://github.com/ionic-team/ionic/commit/d4b9151396aed6d7a29d8f40d6e607bf6258b4ef))
|
||||
* **content:** add parts support for background, scroll ([#20929](https://github.com/ionic-team/ionic/issues/20929)) ([578ab93](https://github.com/ionic-team/ionic/commit/578ab93d297f101ac899b6b6b099445ac679c71f))
|
||||
* **datetime:** add parts support for placeholder, text ([#20930](https://github.com/ionic-team/ionic/issues/20930)) ([76ca475](https://github.com/ionic-team/ionic/commit/76ca475734e13404886bdf70117c0c39bbd7ce70))
|
||||
* **gesture:** add option to run inside NgZone for Angular apps ([#20685](https://github.com/ionic-team/ionic/issues/20685)) ([429edb0](https://github.com/ionic-team/ionic/commit/429edb053bf2a5e778665770c373e31fc7d3bfd2)), closes [#20529](https://github.com/ionic-team/ionic/issues/20529)
|
||||
* **gesture:** add support for blurring active inputs on gesture start ([#20638](https://github.com/ionic-team/ionic/issues/20638)) ([32ecdd6](https://github.com/ionic-team/ionic/commit/32ecdd67536f07f9d95e331e44661afb2cf7b470)), closes [#20588](https://github.com/ionic-team/ionic/issues/20588)
|
||||
* **img:** add parts support for image ([#20943](https://github.com/ionic-team/ionic/issues/20943)) ([63c75ed](https://github.com/ionic-team/ionic/commit/63c75edd21387f28387c8a8529ba638317a9d9b8))
|
||||
* **input:** add support for enterkeyhint ([#21035](https://github.com/ionic-team/ionic/issues/21035)) ([3efaf43](https://github.com/ionic-team/ionic/commit/3efaf4382175d40902968cabb7edd672ffc7cc2b)), closes [#21034](https://github.com/ionic-team/ionic/issues/21034)
|
||||
* **item:** add parts support for detail-icon ([#20979](https://github.com/ionic-team/ionic/issues/20979)) ([6414496](https://github.com/ionic-team/ionic/commit/64144960b06e056a99aa3d352486a495b6bb43ed))
|
||||
* **menu:** add parts support for backdrop, container ([#20978](https://github.com/ionic-team/ionic/issues/20978)) ([50bc212](https://github.com/ionic-team/ionic/commit/50bc212d0b30919c136d6be60a9d458ec7d50dde))
|
||||
* **radio:** add parts support for container, mark ([#20952](https://github.com/ionic-team/ionic/issues/20952)) ([228ca2b](https://github.com/ionic-team/ionic/commit/228ca2b093215aba91fe925b301049471ffaa169))
|
||||
* **range:** add parts support for bar, bar-active, knob, pin, tick, tick-active ([#20961](https://github.com/ionic-team/ionic/issues/20961)) ([619f67a](https://github.com/ionic-team/ionic/commit/619f67a00baa387d0f2bf3f6219e21bc87c03313))
|
||||
* **react:** expose selectTab method and activeTab, closes [#19935](https://github.com/ionic-team/ionic/issues/19935) ([#21171](https://github.com/ionic-team/ionic/issues/21171)) ([43f9d24](https://github.com/ionic-team/ionic/commit/43f9d24824e4c1b679b350b3db05a6830d98fc0a))
|
||||
* **reorder:** add parts support for icon ([#20960](https://github.com/ionic-team/ionic/issues/20960)) ([ba20209](https://github.com/ionic-team/ionic/commit/ba20209604666048619ae5f4358be0e65ef36e4f))
|
||||
* **searchbar:** add border-radius css variable ([#20662](https://github.com/ionic-team/ionic/issues/20662)) ([acaa1d9](https://github.com/ionic-team/ionic/commit/acaa1d9ef7e4037913159c0d32829183ddc1860b)), closes [#17426](https://github.com/ionic-team/ionic/issues/17426) [#18247](https://github.com/ionic-team/ionic/issues/18247)
|
||||
* **searchbar:** add support for enterkeyhint ([#21036](https://github.com/ionic-team/ionic/issues/21036)) ([e90683a](https://github.com/ionic-team/ionic/commit/e90683a713cb45d1e1283dd41343ea6b672a9e3a)), closes [#21034](https://github.com/ionic-team/ionic/issues/21034)
|
||||
* **select:** add parts support for placeholder, icon, text ([#21108](https://github.com/ionic-team/ionic/issues/21108)) ([30a1c89](https://github.com/ionic-team/ionic/commit/30a1c896883e971ab87ef7d5d8790e9a60632fc2))
|
||||
* **slides:** update to swiper 5 ([#20917](https://github.com/ionic-team/ionic/issues/20917)) ([4e28445](https://github.com/ionic-team/ionic/commit/4e28445ecb029f8d225acf9313209e5f61114dc4)), closes [#20033](https://github.com/ionic-team/ionic/issues/20033)
|
||||
* **textarea:** add support for inputmode and enterkeyhint ([#21106](https://github.com/ionic-team/ionic/issues/21106)) ([1622d9b](https://github.com/ionic-team/ionic/commit/1622d9bb3c7f2aeed7dc823620204737619a5b0d))
|
||||
* **toast:** add white-space variable for toast message ([#20729](https://github.com/ionic-team/ionic/issues/20729)) ([e5e02d4](https://github.com/ionic-team/ionic/commit/e5e02d4f88abbcc7dbc626db6d5adf4292d8e776)), closes [#20727](https://github.com/ionic-team/ionic/issues/20727)
|
||||
* **toggle:** add parts support for handle, track ([#20962](https://github.com/ionic-team/ionic/issues/20962)) ([d2b772f](https://github.com/ionic-team/ionic/commit/d2b772f19fde71bcec72300cb4cf8234321b35bc))
|
||||
* **toggle:** improve customization with css vars and auto-adjust handle width and height ([#21050](https://github.com/ionic-team/ionic/issues/21050)) ([04ace4c](https://github.com/ionic-team/ionic/commit/04ace4c98346fde5bad343224657f049beb3e868)), closes [#19868](https://github.com/ionic-team/ionic/issues/19868) [#20474](https://github.com/ionic-team/ionic/issues/20474)
|
||||
|
||||
|
||||
### Performance Improvements
|
||||
|
||||
* **all:** improve scroll assist responsiveness ([#20987](https://github.com/ionic-team/ionic/issues/20987)) ([6f13b8c](https://github.com/ionic-team/ionic/commit/6f13b8c7922f638cac4eb3b111ff9643e6995491)), closes [#20922](https://github.com/ionic-team/ionic/issues/20922)
|
||||
|
||||
|
||||
|
||||
|
||||
## [5.0.7](https://github.com/ionic-team/ionic/compare/v5.0.6...v5.0.7) (2020-03-26)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* **modal:** properly target card modal for iPadOS styles ([#20884](https://github.com/ionic-team/ionic/issues/20884)) ([5816cf5](https://github.com/ionic-team/ionic/commit/5816cf52a779acc4613c2d2da28b97c511360cc2))
|
||||
|
||||
|
||||
|
||||
## [5.0.6](https://github.com/ionic-team/ionic/compare/v5.0.5...v5.0.6) (2020-03-25)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
|
||||
* **all** only warn invalid mode if used on an ionic component ([#20828](https://github.com/ionic-team/ionic/issues/20828)) ([6ed1c51](https://github.com/ionic-team/ionic/commit/6ed1c51321d781ff92efbf623790af91cb16a5af)), closes [#20055](https://github.com/ionic-team/ionic/issues/20055)
|
||||
* **all** properly scroll to input with scroll assist ([#20742](https://github.com/ionic-team/ionic/issues/20742)) ([e24060e](https://github.com/ionic-team/ionic/commit/e24060ecd9d803ece4bbb9c6beae23e761d7fb5e)), closes [#19589](https://github.com/ionic-team/ionic/issues/19589)
|
||||
* **angular:** export Animation and Gesture related types ([#20766](https://github.com/ionic-team/ionic/issues/20766)) ([2ece194](https://github.com/ionic-team/ionic/commit/2ece194a085742b919cc68f643b1b365f7d85594))
|
||||
* **angular:** respect animation property for ion-router-outlet ([#20767](https://github.com/ionic-team/ionic/issues/20767)) ([f2dbe1f](https://github.com/ionic-team/ionic/commit/f2dbe1ff3be44e6697b791de392a9ef46dbf27e8)), closes [#20764](https://github.com/ionic-team/ionic/issues/20764)
|
||||
* **content:** apply --offset-top and --offset-bottom values correctly ([#20790](https://github.com/ionic-team/ionic/issues/20790)) ([2707289](https://github.com/ionic-team/ionic/commit/2707289b36883ae495f86cfb2f2b6c84e090551b)), closes [#20735](https://github.com/ionic-team/ionic/issues/20735)
|
||||
* **content:** set overscroll-behavior based on the scroll direction ([#20011](https://github.com/ionic-team/ionic/issues/20011)) ([a3fc77b](https://github.com/ionic-team/ionic/commit/a3fc77be91ead6edc3f07c6127879753a063bd18)), closes [#20010](https://github.com/ionic-team/ionic/issues/20010)
|
||||
* **item-divider:** update design to match native iOS ([#20854](https://github.com/ionic-team/ionic/issues/20854)) ([d91e22d](https://github.com/ionic-team/ionic/commit/d91e22d820f170ecfdfad835ca56701ad70e6f3d))
|
||||
* **item-sliding:** account for swipe to go back gesture when opening item-options ([#20777](https://github.com/ionic-team/ionic/issues/20777)) ([f23ac44](https://github.com/ionic-team/ionic/commit/f23ac44c9a6646129762bb861cae6145690ca5a1)), closes [#20773](https://github.com/ionic-team/ionic/issues/20773)
|
||||
* **list:** show bottom border on last item in a list followed by a list ([#20798](https://github.com/ionic-team/ionic/issues/20798)) ([7bc5191](https://github.com/ionic-team/ionic/commit/7bc51911f6c538be8b91d1e569675b19832cb000))
|
||||
* **modal:** backdrop and box shadows no longer stack when opening multiple modals ([#20801](https://github.com/ionic-team/ionic/issues/20801)) ([253cd96](https://github.com/ionic-team/ionic/commit/253cd96164914a803f6bb42ff95ca74880c940d0)), closes [#20800](https://github.com/ionic-team/ionic/issues/20800)
|
||||
* **modal:** backdrop is no longer tappable on card-style modal on smaller screens ([#20802](https://github.com/ionic-team/ionic/issues/20802)) ([12932dd](https://github.com/ionic-team/ionic/commit/12932dd20212bec7d780650166c70819d125f75a)), closes [#20783](https://github.com/ionic-team/ionic/issues/20783)
|
||||
* **modal:** properly apply border radius on card-style modal ([#20852](https://github.com/ionic-team/ionic/issues/20852)) ([dff3816](https://github.com/ionic-team/ionic/commit/dff3816c049a1c051f94d3176c8b903a69603912)), closes [#20851](https://github.com/ionic-team/ionic/issues/20851)
|
||||
* **modal:** properly remove safe area padding on card-modal ([#20853](https://github.com/ionic-team/ionic/issues/20853)) ([71f1182](https://github.com/ionic-team/ionic/commit/71f118201b0918f60c1a078d55afd10b39f17e86)), closes [#20799](https://github.com/ionic-team/ionic/issues/20799)
|
||||
* **modal:** respect card-style modal spec for iPadOS ([#20750](https://github.com/ionic-team/ionic/issues/20750)) ([75bae40](https://github.com/ionic-team/ionic/commit/75bae403e917b20645675343734440ee95d31634)), closes [#20700](https://github.com/ionic-team/ionic/issues/20700)
|
||||
* **react:** expose correct type for CreateAnimation ([#20775](https://github.com/ionic-team/ionic/issues/20775)) ([0897c3f](https://github.com/ionic-team/ionic/commit/0897c3f9c2591442b3f80d28a25ec4471da3c9d7)), closes [#20771](https://github.com/ionic-team/ionic/issues/20771)
|
||||
* **refresher:** properly dismiss refresher when completed synchronously ([#20815](https://github.com/ionic-team/ionic/issues/20815)) ([b1a87c8](https://github.com/ionic-team/ionic/commit/b1a87c88923201fd0b31bf55d81b97acc09ddf1c)), closes [#20803](https://github.com/ionic-team/ionic/issues/20803)
|
||||
* **segment:** automatically expand width for scrollable segment buttons ([#20763](https://github.com/ionic-team/ionic/issues/20763)) ([cdfd50b](https://github.com/ionic-team/ionic/commit/cdfd50b554d1d8f89c3d9948c7613ce75ede1e52)), closes [#20566](https://github.com/ionic-team/ionic/issues/20566)
|
||||
* **segment:** scrollable segments only show scrollbar if they overflow ([#20760](https://github.com/ionic-team/ionic/issues/20760)) ([ab146c9](https://github.com/ionic-team/ionic/commit/ab146c96ec5cbc962eed629c30b2c5c446f3098d)), closes [#20758](https://github.com/ionic-team/ionic/issues/20758)
|
||||
* **slides:** check that mutation observer is defined for ssr ([#20791](https://github.com/ionic-team/ionic/issues/20791)) ([2d5d251](https://github.com/ionic-team/ionic/commit/2d5d2515be86496a280d93847185ab332e5d47a2))
|
||||
* **textarea:** properly adjust auto-grow textarea in scrolled content ([#19776](https://github.com/ionic-team/ionic/issues/19776)) ([8bd5bac](https://github.com/ionic-team/ionic/commit/8bd5bace73670dfe351b3734b51cbf3aa87517dc)), closes [#19193](https://github.com/ionic-team/ionic/issues/19193)
|
||||
* **title:** improve reliability of large title ios nav transition ([#20861](https://github.com/ionic-team/ionic/issues/20861)) ([3bd6b5d](https://github.com/ionic-team/ionic/commit/3bd6b5def2877f6a918c587de25a10ccc82f88f1))
|
||||
* **title:** large title now inherits global color styling during nav transition ([#20862](https://github.com/ionic-team/ionic/issues/20862)) ([321140f](https://github.com/ionic-team/ionic/commit/321140ff736b46d2631a9e87a7b070009c5e1b2c))
|
||||
|
||||
|
||||
|
||||
## [5.0.5](https://github.com/ionic-team/ionic/compare/v5.0.4...v5.0.5) (2020-03-11)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* **button:** allow overflow to be overridden by the CSS variable ([#20738](https://github.com/ionic-team/ionic/issues/20738)) ([7ecde36](https://github.com/ionic-team/ionic/commit/7ecde36f9d31327a45f7b5023ed533edbb9cc709)), closes [#20726](https://github.com/ionic-team/ionic/issues/20726)
|
||||
* **datetime:** account for max property when hour, minute, or second is set to 0 ([#20665](https://github.com/ionic-team/ionic/issues/20665)) ([2177461](https://github.com/ionic-team/ionic/commit/21774612d8d70ab7eda3eab0e6e9ac039b5c87d8)), closes [#20652](https://github.com/ionic-team/ionic/issues/20652)
|
||||
* **header:** collapsable header should default to using content background ([#20736](https://github.com/ionic-team/ionic/issues/20736)) ([f6c3ba7](https://github.com/ionic-team/ionic/commit/f6c3ba7e5af2af9e32f75306cde7704509e82263)), closes [#20691](https://github.com/ionic-team/ionic/issues/20691)
|
||||
* **header:** resolve undefined error on collapsible header when navigating quickly ([#20728](https://github.com/ionic-team/ionic/issues/20728)) ([87a2721](https://github.com/ionic-team/ionic/commit/87a27216d011f1d02ac0fc0aeb3ae0400ecfbd8c)), closes [#20725](https://github.com/ionic-team/ionic/issues/20725)
|
||||
* **ios:** large title animation now works properly in a modal ([#20703](https://github.com/ionic-team/ionic/issues/20703)) ([ec4878a](https://github.com/ionic-team/ionic/commit/ec4878ac085d8ff92cb8b2ea0852523f174ab01b)), closes [#20696](https://github.com/ionic-team/ionic/issues/20696)
|
||||
* **item:** apply proper margin left for slotted icon in RTL ([#20684](https://github.com/ionic-team/ionic/issues/20684)) ([d53595e](https://github.com/ionic-team/ionic/commit/d53595eb1629e0d60f7e832414e84c544e184346)), closes [#20653](https://github.com/ionic-team/ionic/issues/20653)
|
||||
* **label:** text overflow for slotted headings ([#20690](https://github.com/ionic-team/ionic/issues/20690)) ([4d34ce6](https://github.com/ionic-team/ionic/commit/4d34ce6a31eaa19859699646cc614f5be6239e10)), closes [#17087](https://github.com/ionic-team/ionic/issues/17087)
|
||||
* **modal:** leave animation transitions modal completely out of viewport on ipad ([#20702](https://github.com/ionic-team/ionic/issues/20702)) ([22d5256](https://github.com/ionic-team/ionic/commit/22d52568100d8096ee36e3a61a19614f0d63d45f)), closes [#20697](https://github.com/ionic-team/ionic/issues/20697)
|
||||
* **angular** exclude components from ssr ([#20674](https://github.com/ionic-team/ionic/issues/20674)) ([f64b142](https://github.com/ionic-team/ionic/commit/f64b1420aead39b9056dc25cfdbcf95bc4f6f621))
|
||||
* **modal:** swipeable modal now works in firefox ([#20714](https://github.com/ionic-team/ionic/issues/20714)) ([7d260b9](https://github.com/ionic-team/ionic/commit/7d260b96a73958709fa93a4fe58f816a445471ee)), closes [#20706](https://github.com/ionic-team/ionic/issues/20706)
|
||||
* **overlays:** prevent accidental dismiss of overlays when tapping screen twice ([#20683](https://github.com/ionic-team/ionic/issues/20683)) ([b6c2a77](https://github.com/ionic-team/ionic/commit/b6c2a77deb1c09eb1fd414f7737794e208ab5081)), closes [#20608](https://github.com/ionic-team/ionic/issues/20608)
|
||||
* **segment:** allow routerLink to work on segment buttons ([#20682](https://github.com/ionic-team/ionic/issues/20682)) ([314dbb1](https://github.com/ionic-team/ionic/commit/314dbb1a4d970327fcbb2f3fbdec0627c626fe4d)), closes [#20678](https://github.com/ionic-team/ionic/issues/20678)
|
||||
* **segment:** iOS mode segment now works on older Android devices ([#20673](https://github.com/ionic-team/ionic/issues/20673)) ([44993b7](https://github.com/ionic-team/ionic/commit/44993b7987031b6618409675fdbb1f15ec4ea343)), closes [#20648](https://github.com/ionic-team/ionic/issues/20648)
|
||||
|
||||
|
||||
|
||||
## [5.0.4](https://github.com/ionic-team/ionic/compare/v5.0.3...v5.0.4) (2020-02-27)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* **animation:** reset all temporary flags when interrupting an animation ([#20627](https://github.com/ionic-team/ionic/issues/20627)) ([0e0e401](https://github.com/ionic-team/ionic/commit/0e0e401d86dabaa1dc804656e4d384154d6fdd05)), closes [#20602](https://github.com/ionic-team/ionic/issues/20602)
|
||||
* **buttons:** use proper button colors based on CSS variables when inside of a toolbar ([#20633](https://github.com/ionic-team/ionic/issues/20633)) ([c1d7bf2](https://github.com/ionic-team/ionic/commit/c1d7bf229d10d0a12f90b6d2730d6d8ac78b48cd))
|
||||
|
||||
|
||||
|
||||
## [5.0.3](https://github.com/ionic-team/ionic/compare/v5.0.2...v5.0.3) (2020-02-26)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* **menu:** allow ssr to work properly with hardware back button updates ([#20629](https://github.com/ionic-team/ionic/issues/20629)) ([fe8d74d](https://github.com/ionic-team/ionic/commit/fe8d74d08cb919ed1c685262f0aed4a544c3a7e1))
|
||||
|
||||
|
||||
|
||||
## [5.0.2](https://github.com/ionic-team/ionic/compare/v5.0.1...v5.0.2) (2020-02-26)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* **ios:** large title transition works properly in tabbed applications ([#20555](https://github.com/ionic-team/ionic/issues/20555)) ([7187541](https://github.com/ionic-team/ionic/commit/71875417f207d26bd7115655f239251460a1e3d8)), closes [#20482](https://github.com/ionic-team/ionic/issues/20482)
|
||||
* **menu:** hardware back button now dismisses side menu if open in Cordova/Capacitor app ([#20558](https://github.com/ionic-team/ionic/issues/20558)) ([6b2a929](https://github.com/ionic-team/ionic/commit/6b2a929cd7e70b16383cb3336b399a1aee2d6101)), closes [#20559](https://github.com/ionic-team/ionic/issues/20559)
|
||||
* **modal:** allow swipe to close animation to be overridden ([#20585](https://github.com/ionic-team/ionic/issues/20585)) ([8d3ce8d](https://github.com/ionic-team/ionic/commit/8d3ce8d29c9abd89ce47c882e0d7b2ac0f861966)), closes [#20577](https://github.com/ionic-team/ionic/issues/20577)
|
||||
* **modal:** card style modal now adds appropriate contrast ([#20604](https://github.com/ionic-team/ionic/issues/20604)) ([b5310ef](https://github.com/ionic-team/ionic/commit/b5310effe3f9b47459f22221da1853a55dbb0279))
|
||||
* **modal:** allow swipeable modal background to be overridden ([#20584](https://github.com/ionic-team/ionic/issues/20584)) ([ad6fac8](https://github.com/ionic-team/ionic/commit/ad6fac83cb7c4acb377b4b1620ab1a3f852bc6d3)), closes [#20572](https://github.com/ionic-team/ionic/issues/20572)
|
||||
* **modal:** swipeable modal styles only apply to ios ([#20571](https://github.com/ionic-team/ionic/issues/20571)) ([3a2d828](https://github.com/ionic-team/ionic/commit/3a2d82814b22a3987a5abfe4412d83a93a97b6b7)), closes [#20569](https://github.com/ionic-team/ionic/issues/20569)
|
||||
* **refresher:** ensure that translate is cleaned up to avoid stacking context ([#20621](https://github.com/ionic-team/ionic/issues/20621)) ([e3e5c69](https://github.com/ionic-team/ionic/commit/e3e5c69681f376cbc4b1305f719fc6895b21a9b7)), closes [#17949](https://github.com/ionic-team/ionic/issues/17949)
|
||||
* **segment:** segment functions properly on older versions of Android ([#20554](https://github.com/ionic-team/ionic/issues/20554)) ([0224bed](https://github.com/ionic-team/ionic/commit/0224bed0c9f91bcb54bb4b3064df56928cf5ed8a)), closes [#20466](https://github.com/ionic-team/ionic/issues/20466)
|
||||
* **select:** properly align text, add icon-inner and placeholder part ([#20605](https://github.com/ionic-team/ionic/issues/20605)) ([926ac3f](https://github.com/ionic-team/ionic/commit/926ac3fb47228be19146ccdfab92a05cf6677ff4))
|
||||
* **slides:** set height to 100% for vertical slides ([#20603](https://github.com/ionic-team/ionic/issues/20603)) ([20af652](https://github.com/ionic-team/ionic/commit/20af652a1be5e1aff2836422489642c8baed6939)), closes [#17341](https://github.com/ionic-team/ionic/issues/17341)
|
||||
|
||||
|
||||
|
||||
## [5.0.1](https://github.com/ionic-team/ionic/compare/v5.0.0...v5.0.1) (2020-02-19)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* **button:** reduce font size of icon only button in toolbar on iOS ([#20547](https://github.com/ionic-team/ionic/issues/20547)) ([59fa340](https://github.com/ionic-team/ionic/commit/59fa340650840b2abf86bd643350da7064ee9ead))
|
||||
* **card:** inherit background in inner button ([#20461](https://github.com/ionic-team/ionic/issues/20461)) ([c16de96](https://github.com/ionic-team/ionic/commit/c16de9663329993698c10e4251dbb0b75167701f)), closes [#20458](https://github.com/ionic-team/ionic/issues/20458)
|
||||
* **fab:** add close icon to internal icons for react ([#20490](https://github.com/ionic-team/ionic/issues/20490)) ([c4fb314](https://github.com/ionic-team/ionic/commit/c4fb31403eb4704bcf04e6c32bfa46422f08bf4f)), closes [#20489](https://github.com/ionic-team/ionic/issues/20489)
|
||||
* **fab:** show close icon on hover, focused, activated ([#20497](https://github.com/ionic-team/ionic/issues/20497)) ([e42c85d](https://github.com/ionic-team/ionic/commit/e42c85d64161b7fac7147325cb6c2ceff990042b))
|
||||
* **input:** do not clear input if "Enter" key pressed ([#20462](https://github.com/ionic-team/ionic/issues/20462)) ([89bf08b](https://github.com/ionic-team/ionic/commit/89bf08b6276f2a25d66fc0e74ba3303f923af652)), closes [#20442](https://github.com/ionic-team/ionic/issues/20442)
|
||||
* **ios:** clamp out of bounds values for swipe to go back ([#20540](https://github.com/ionic-team/ionic/issues/20540)) ([dd32a5e](https://github.com/ionic-team/ionic/commit/dd32a5e2788a11a5c2be0d1840f5775c7307c57f)), closes [#20505](https://github.com/ionic-team/ionic/issues/20505)
|
||||
* **menu:** swipe gesture should not open menu when a modal is displayed ([#20546](https://github.com/ionic-team/ionic/issues/20546)) ([3252c2f](https://github.com/ionic-team/ionic/commit/3252c2f8dc46e0853a7f626baa6023a01ac21a25)), closes [#20467](https://github.com/ionic-team/ionic/issues/20467)
|
||||
* **modal:** presenting multiple card-style modals now adds border radius properly ([#20476](https://github.com/ionic-team/ionic/issues/20476)) ([abf594a](https://github.com/ionic-team/ionic/commit/abf594aa611562a76e3baecfa38456d41a1410f3)), closes [#20475](https://github.com/ionic-team/ionic/issues/20475)
|
||||
* **modal:** prevent card style modal styles from being overridden ([#20470](https://github.com/ionic-team/ionic/issues/20470)) ([86ab77a](https://github.com/ionic-team/ionic/commit/86ab77a6e2cb124510c244110fc78a4bc0654cd1)), closes [#20469](https://github.com/ionic-team/ionic/issues/20469)
|
||||
* **react:** do a better job matching up route to sync ([#20446](https://github.com/ionic-team/ionic/issues/20446)) ([c0aadd6](https://github.com/ionic-team/ionic/commit/c0aadd60077e5ba379959d93006e3a9c1418263c)), closes [#20363](https://github.com/ionic-team/ionic/issues/20363)
|
||||
* **react:** do not remove pages when navigating between tabs ([#20431](https://github.com/ionic-team/ionic/issues/20431)) ([b6fbe98](https://github.com/ionic-team/ionic/commit/b6fbe98812fbab5ef9e0723802605c0711581dd2)), closes [#20398](https://github.com/ionic-team/ionic/issues/20398)
|
||||
* **react:** icons with MD set should work in browser ([#20463](https://github.com/ionic-team/ionic/issues/20463)) ([82670fe](https://github.com/ionic-team/ionic/commit/82670fe4d0592451cbc243b3008beb3f8f483c30))
|
||||
* **react:** update paths of tab buttons when href changes in ion buttons ([#20480](https://github.com/ionic-team/ionic/issues/20480)) ([45d03ba](https://github.com/ionic-team/ionic/commit/45d03baf981d0e10eb1fe689908532adef2ba31d)), closes [#20321](https://github.com/ionic-team/ionic/issues/20321)
|
||||
* **searchbar:** properly align placeholder ([#20460](https://github.com/ionic-team/ionic/issues/20460)) ([4d6e15a](https://github.com/ionic-team/ionic/commit/4d6e15ab18fc894c3826b89362163256adc227f4)), closes [#20456](https://github.com/ionic-team/ionic/issues/20456)
|
||||
* **segment:** border radius applies to indicator on ios ([#20541](https://github.com/ionic-team/ionic/issues/20541)) ([9b5854d](https://github.com/ionic-team/ionic/commit/9b5854d79712356f8a3772442c0cc412db09d5e0)), closes [#20539](https://github.com/ionic-team/ionic/issues/20539)
|
||||
* **segment:** do not show ripple effect if disabled via config ([#20542](https://github.com/ionic-team/ionic/issues/20542)) ([7a461c5](https://github.com/ionic-team/ionic/commit/7a461c59c5d9a23de0bcdd53397f452d17251fd6)), closes [#20533](https://github.com/ionic-team/ionic/issues/20533)
|
||||
* **segment:** inner div no longer interferes with click events ([#20522](https://github.com/ionic-team/ionic/issues/20522)) ([06b828b](https://github.com/ionic-team/ionic/commit/06b828b4ffb12b076b0805274f53fa158ee65c5a)), closes [#20381](https://github.com/ionic-team/ionic/issues/20381)
|
||||
* **segment:** only emit ionChange when user releases pointer from screen ([#20495](https://github.com/ionic-team/ionic/issues/20495)) ([4d50064](https://github.com/ionic-team/ionic/commit/4d5006476479bc376d3bb4edad6db0b3ce806ef7)), closes [#20500](https://github.com/ionic-team/ionic/issues/20500) [#20257](https://github.com/ionic-team/ionic/issues/20257)
|
||||
* **tab-bar:** update ios icon and label design to match native ([#20548](https://github.com/ionic-team/ionic/issues/20548)) ([34f8576](https://github.com/ionic-team/ionic/commit/34f8576b959d41896502e4f7b0c4240156e001eb))
|
||||
|
||||
|
||||
|
||||
# [5.0.0 Magnesium](https://github.com/ionic-team/ionic/compare/v4.11.10...v5.0.0) (2020-02-11)
|
||||
|
||||
Enjoy! :fire:
|
||||
|
||||
> We recommend updating to version `4.11.10` before updating to this version in order to see deprecation warnings related to your app [in the developer console](https://javascript.info/devtools).
|
||||
|
||||
Run the following commands based on your project type:
|
||||
|
||||
```
|
||||
# for an angular app
|
||||
npm i @ionic/angular@latest --save
|
||||
|
||||
# for a react app
|
||||
npm i @ionic/react@latest --save
|
||||
npm i @ionic/react-router@latest --save
|
||||
npm i ionicons@latest --save
|
||||
|
||||
# for a stencil / vanilla JS app
|
||||
npm i @ionic/core@latest --save
|
||||
```
|
||||
|
||||
Then take a look at the [Breaking Changes](./BREAKING.md) file for API changes.
|
||||
|
||||
|
||||
# [5.0.0-rc.5](https://github.com/ionic-team/ionic/compare/v5.0.0-rc.4...v5.0.0-rc.5) (2020-02-11)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* **angular:** correct path for angular projects ([#20436](https://github.com/ionic-team/ionic/issues/20436)) ([fd9c7a9](https://github.com/ionic-team/ionic/commit/fd9c7a9601e7f21b74c76be1f8bb305bf008915c)), closes [#20435](https://github.com/ionic-team/ionic/issues/20435)
|
||||
|
||||
|
||||
|
||||
# [5.0.0-rc.4](https://github.com/ionic-team/ionic/compare/v5.0.0-rc.3...v5.0.0-rc.4) (2020-02-10)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* **content:** only emit scroll events if enabled ([#20401](https://github.com/ionic-team/ionic/issues/20401)) ([fd1b44a](https://github.com/ionic-team/ionic/commit/fd1b44a40b741088e099f6538dd14caa0dc5540c))
|
||||
* **header:** backdrop filter no longer distorts content with collapsible header ([#20388](https://github.com/ionic-team/ionic/issues/20388)) ([11d3945](https://github.com/ionic-team/ionic/commit/11d39457d56c091e9c41c180391d27464ae748b5)), closes [#20385](https://github.com/ionic-team/ionic/issues/20385)
|
||||
* **item:** remove unneeded box-shadow CSS variable ([#20412](https://github.com/ionic-team/ionic/issues/20412)) ([a6764c4](https://github.com/ionic-team/ionic/commit/a6764c4724e1e7eed19a1902b563aeb61bfde38e)), closes [#20392](https://github.com/ionic-team/ionic/issues/20392)
|
||||
* **label:** remove subpixel font-size to prevent visual glitches ([#20415](https://github.com/ionic-team/ionic/issues/20415)) ([3d6f287](https://github.com/ionic-team/ionic/commit/3d6f287d87bfaa0d81a34182baf38192e08fb3c1)), closes [#20407](https://github.com/ionic-team/ionic/issues/20407)
|
||||
* **segment:** add activated class directly to segment button ([#20400](https://github.com/ionic-team/ionic/issues/20400)) ([e8886e9](https://github.com/ionic-team/ionic/commit/e8886e98f188044227bf5757892341cb598fdd27))
|
||||
|
||||
|
||||
|
||||
# [5.0.0-rc.3](https://github.com/ionic-team/ionic/compare/v5.0.0-rc.2...v5.0.0-rc.3) (2020-02-05)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* **refresher:** ensure gesture does not interfere with item-sliding ([#20380](https://github.com/ionic-team/ionic/issues/20380)) ([8983c70](https://github.com/ionic-team/ionic/commit/8983c7006e54743873cd45ae1acdfa974d74547a)), closes [#20379](https://github.com/ionic-team/ionic/issues/20379)
|
||||
* **refresher:** translate background content when refreshing ([#20378](https://github.com/ionic-team/ionic/issues/20378)) ([cf70916](https://github.com/ionic-team/ionic/commit/cf7091625ecb46c3f9882ae9eff5c946523fab75)), closes [#20377](https://github.com/ionic-team/ionic/issues/20377)
|
||||
* **segment:** allow background to be set on iOS segment in a toolbar ([#20350](https://github.com/ionic-team/ionic/issues/20350)) ([0f31624](https://github.com/ionic-team/ionic/commit/0f31624104d195367df197eda9b8d6c5bda4cf75))
|
||||
* **toolbar:** properly apply safe area and border ([#20375](https://github.com/ionic-team/ionic/issues/20375)) ([4971499](https://github.com/ionic-team/ionic/commit/4971499026fcee70a32cc9480302bb14a1bebcb7)), closes [#20354](https://github.com/ionic-team/ionic/issues/20354)
|
||||
|
||||
|
||||
|
||||
# [5.0.0-rc.2](https://github.com/ionic-team/ionic/compare/v5.0.0-rc.1...v5.0.0-rc.2) (2020-01-30)
|
||||
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@ionic/angular",
|
||||
"version": "5.0.0-rc.2",
|
||||
"version": "5.1.1",
|
||||
"description": "Angular specific wrappers for @ionic/core",
|
||||
"keywords": [
|
||||
"ionic",
|
||||
@@ -42,7 +42,7 @@
|
||||
"validate": "npm i && npm run lint && npm run test && npm run build"
|
||||
},
|
||||
"dependencies": {
|
||||
"@ionic/core": "5.0.0-rc.2",
|
||||
"@ionic/core": "5.1.1",
|
||||
"tslib": "^1.9.3"
|
||||
},
|
||||
"peerDependencies": {
|
||||
@@ -64,7 +64,7 @@
|
||||
"@types/node": "12.12.5",
|
||||
"fs-extra": "^7.0.0",
|
||||
"glob": "^7.1.4",
|
||||
"ng-packagr": "5.7.1",
|
||||
"ng-packagr": "^9.1.5",
|
||||
"rollup": "~1.17.0",
|
||||
"rollup-plugin-node-resolve": "~5.2.0",
|
||||
"rxjs": "^6.5.2",
|
||||
|
||||
@@ -12,6 +12,13 @@ export class ValueAccessor implements ControlValueAccessor {
|
||||
constructor(protected el: ElementRef) {}
|
||||
|
||||
writeValue(value: any) {
|
||||
/**
|
||||
* TODO for Ionic 6:
|
||||
* Change `value == null ? '' : value;`
|
||||
* to `value`. This was a fix for IE9, but IE9
|
||||
* is no longer supported; however, this change
|
||||
* is potentially a breaking change
|
||||
*/
|
||||
this.el.nativeElement.value = this.lastValue = value == null ? '' : value;
|
||||
setIonicClasses(this.el);
|
||||
}
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
import { Directive, HostListener, Optional } from '@angular/core';
|
||||
|
||||
import { Config } from '../../providers/config';
|
||||
import { NavController } from '../../providers/nav-controller';
|
||||
|
||||
import { IonRouterOutlet } from './ion-router-outlet';
|
||||
@@ -14,7 +15,8 @@ export class IonBackButtonDelegate {
|
||||
|
||||
constructor(
|
||||
@Optional() private routerOutlet: IonRouterOutlet,
|
||||
private navCtrl: NavController
|
||||
private navCtrl: NavController,
|
||||
private config: Config
|
||||
) {}
|
||||
|
||||
/**
|
||||
@@ -22,11 +24,13 @@ export class IonBackButtonDelegate {
|
||||
*/
|
||||
@HostListener('click', ['$event'])
|
||||
onClick(ev: Event) {
|
||||
const defaultHref = this.defaultHref || this.config.get('backButtonDefaultHref');
|
||||
|
||||
if (this.routerOutlet && this.routerOutlet.canGoBack()) {
|
||||
this.routerOutlet.pop();
|
||||
ev.preventDefault();
|
||||
} else if (this.defaultHref != null) {
|
||||
this.navCtrl.navigateBack(this.defaultHref);
|
||||
} else if (defaultHref != null) {
|
||||
this.navCtrl.navigateBack(defaultHref);
|
||||
ev.preventDefault();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -4,6 +4,7 @@ import { ActivatedRoute, ChildrenOutletContexts, OutletContext, PRIMARY_OUTLET,
|
||||
import { BehaviorSubject, Observable } from 'rxjs';
|
||||
import { distinctUntilChanged, filter, switchMap } from 'rxjs/operators';
|
||||
|
||||
import { AnimationBuilder } from '../../';
|
||||
import { Config } from '../../providers/config';
|
||||
import { NavController } from '../../providers/nav-controller';
|
||||
|
||||
@@ -13,13 +14,13 @@ import { RouteView, getUrl } from './stack-utils';
|
||||
@Directive({
|
||||
selector: 'ion-router-outlet',
|
||||
exportAs: 'outlet',
|
||||
inputs: ['animated', 'swipeGesture']
|
||||
inputs: ['animated', 'animation', 'swipeGesture']
|
||||
})
|
||||
export class IonRouterOutlet implements OnDestroy, OnInit {
|
||||
nativeEl: HTMLIonRouterOutletElement;
|
||||
|
||||
private activated: ComponentRef<any> | null = null;
|
||||
private activatedView: RouteView | null = null;
|
||||
activatedView: RouteView | null = null;
|
||||
|
||||
private _activatedRoute: ActivatedRoute | null = null;
|
||||
private _swipeGesture?: boolean;
|
||||
@@ -38,6 +39,10 @@ export class IonRouterOutlet implements OnDestroy, OnInit {
|
||||
@Output('activate') activateEvents = new EventEmitter<any>();
|
||||
@Output('deactivate') deactivateEvents = new EventEmitter<any>();
|
||||
|
||||
set animation(animation: AnimationBuilder) {
|
||||
this.nativeEl.animation = animation;
|
||||
}
|
||||
|
||||
set animated(animated: boolean) {
|
||||
this.nativeEl.animated = animated;
|
||||
}
|
||||
|
||||
@@ -91,6 +91,12 @@ export class IonTabs {
|
||||
const alreadySelected = this.outlet.getActiveStackId() === tab;
|
||||
const tabRootUrl = `${this.outlet.tabsPrefix}/${tab}`;
|
||||
if (alreadySelected) {
|
||||
const activeStackId = this.outlet.getActiveStackId();
|
||||
const activeView = this.outlet.getLastRouteView(activeStackId);
|
||||
|
||||
// If on root tab, do not navigate to root tab again
|
||||
if (activeView.url === tabRootUrl) { return; }
|
||||
|
||||
const rootView = this.outlet.getRootView(tab);
|
||||
const navigationExtras = rootView && tabRootUrl === rootView.url && rootView.savedExtras;
|
||||
return this.navCtrl.navigateRoot(tabRootUrl, {
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
import * as d from './proxies';
|
||||
|
||||
export const DIRECTIVES = [
|
||||
d.IonApp,
|
||||
d.IonApp,
|
||||
d.IonAvatar,
|
||||
d.IonBackButton,
|
||||
d.IonBackdrop,
|
||||
|
||||
@@ -1,29 +1,30 @@
|
||||
/* eslint-disable */
|
||||
/* tslint:disable */
|
||||
import { fromEvent } from 'rxjs';
|
||||
|
||||
export const proxyInputs = (Cmp: any, inputs: string[]) => {
|
||||
const Prototype = Cmp.prototype;
|
||||
inputs.forEach(item => {
|
||||
Object.defineProperty(Prototype, item, {
|
||||
get() {
|
||||
return this.el[item];
|
||||
},
|
||||
set(val: any) {
|
||||
this.z.runOutsideAngular(() => (this.el[item] = val));
|
||||
}
|
||||
});
|
||||
Object.defineProperty(Prototype, item, {
|
||||
get() {
|
||||
return this.el[item];
|
||||
},
|
||||
set(val: any) {
|
||||
this.z.runOutsideAngular(() => (this.el[item] = val));
|
||||
}
|
||||
});
|
||||
});
|
||||
};
|
||||
|
||||
export const proxyMethods = (Cmp: any, methods: string[]) => {
|
||||
const Prototype = Cmp.prototype;
|
||||
methods.forEach(methodName => {
|
||||
Prototype[methodName] = function () {
|
||||
const args = arguments;
|
||||
return this.z.runOutsideAngular(() =>
|
||||
this.el[methodName].apply(this.el, args)
|
||||
);
|
||||
};
|
||||
Prototype[methodName] = function () {
|
||||
const args = arguments;
|
||||
return this.z.runOutsideAngular(() =>
|
||||
this.el[methodName].apply(this.el, args)
|
||||
);
|
||||
};
|
||||
});
|
||||
};
|
||||
|
||||
@@ -31,16 +32,15 @@ export const proxyOutputs = (instance: any, el: any, events: string[]) => {
|
||||
events.forEach(eventName => instance[eventName] = fromEvent(el, eventName));
|
||||
}
|
||||
|
||||
// tslint:disable-next-line: only-arrow-functions
|
||||
export function ProxyCmp(opts: { inputs?: any; methods?: any }) {
|
||||
const decorator = function(cls: any){
|
||||
if (opts.inputs) {
|
||||
proxyInputs(cls, opts.inputs);
|
||||
}
|
||||
if (opts.methods) {
|
||||
proxyMethods(cls, opts.methods);
|
||||
}
|
||||
return cls;
|
||||
if (opts.inputs) {
|
||||
proxyInputs(cls, opts.inputs);
|
||||
}
|
||||
if (opts.methods) {
|
||||
proxyMethods(cls, opts.methods);
|
||||
}
|
||||
return cls;
|
||||
};
|
||||
return decorator;
|
||||
}
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -36,5 +36,14 @@ export { GestureController } from './providers/gesture-controller';
|
||||
// ROUTER STRATEGY
|
||||
export { IonicRouteStrategy } from './util/ionic-router-reuse-strategy';
|
||||
|
||||
// TYPES
|
||||
export * from './types/ionic-lifecycle-hooks';
|
||||
|
||||
// PACKAGE MODULE
|
||||
export { IonicModule } from './ionic-module';
|
||||
|
||||
// UTILS
|
||||
export { IonicSafeString, getPlatforms, isPlatform } from '@ionic/core';
|
||||
|
||||
// CORE TYPES
|
||||
export { Animation, AnimationBuilder, AnimationCallbackOptions, AnimationDirection, AnimationFill, AnimationKeyFrames, AnimationLifecycle, Gesture, GestureConfig, GestureDetail, mdTransitionAnimation, iosTransitionAnimation } from '@ionic/core';
|
||||
|
||||
@@ -1,14 +1,24 @@
|
||||
import { Injectable } from '@angular/core';
|
||||
import { Injectable, NgZone } from '@angular/core';
|
||||
import { Gesture, GestureConfig, createGesture } from '@ionic/core';
|
||||
|
||||
@Injectable({
|
||||
providedIn: 'root',
|
||||
})
|
||||
export class GestureController {
|
||||
constructor(private zone: NgZone) {}
|
||||
/**
|
||||
* Create a new gesture
|
||||
*/
|
||||
create(opts: GestureConfig): Gesture {
|
||||
create(opts: GestureConfig, runInsideAngularZone = false): Gesture {
|
||||
if (runInsideAngularZone) {
|
||||
Object.getOwnPropertyNames(opts).forEach(key => {
|
||||
if (typeof opts[key] === 'function') {
|
||||
const fn = opts[key];
|
||||
opts[key] = (...props) => this.zone.run(() => fn(...props));
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
return createGesture(opts);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -45,7 +45,10 @@ export class NavController {
|
||||
}
|
||||
|
||||
// Subscribe to backButton events
|
||||
platform.backButton.subscribeWithPriority(0, () => this.pop());
|
||||
platform.backButton.subscribeWithPriority(0, processNextHandler => {
|
||||
this.pop();
|
||||
processNextHandler();
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -1,10 +1,10 @@
|
||||
import { DOCUMENT } from '@angular/common';
|
||||
import { Inject, Injectable, NgZone } from '@angular/core';
|
||||
import { BackButtonEventDetail, Platforms, getPlatforms, isPlatform } from '@ionic/core';
|
||||
import { BackButtonEventDetail, KeyboardEventDetail, Platforms, getPlatforms, isPlatform } from '@ionic/core';
|
||||
import { Subject, Subscription } from 'rxjs';
|
||||
|
||||
export interface BackButtonEmitter extends Subject<BackButtonEventDetail> {
|
||||
subscribeWithPriority(priority: number, callback: () => Promise<any> | void): Subscription;
|
||||
subscribeWithPriority(priority: number, callback: (processNextHandler: () => void) => Promise<any> | void): Subscription;
|
||||
}
|
||||
|
||||
@Injectable({
|
||||
@@ -20,6 +20,18 @@ export class Platform {
|
||||
*/
|
||||
backButton: BackButtonEmitter = new Subject<BackButtonEventDetail>() as any;
|
||||
|
||||
/**
|
||||
* The keyboardDidShow event emits when the
|
||||
* on-screen keyboard is presented.
|
||||
*/
|
||||
keyboardDidShow = new Subject<KeyboardEventDetail>() as any;
|
||||
|
||||
/**
|
||||
* The keyboardDidHide event emits when the
|
||||
* on-screen keyboard is hidden.
|
||||
*/
|
||||
keyboardDidHide = new Subject<void>();
|
||||
|
||||
/**
|
||||
* The pause event emits when the native platform puts the application
|
||||
* into the background, typically when the user switches to a different
|
||||
@@ -46,15 +58,17 @@ export class Platform {
|
||||
zone.run(() => {
|
||||
this.win = doc.defaultView;
|
||||
this.backButton.subscribeWithPriority = function(priority, callback) {
|
||||
return this.subscribe(ev => (
|
||||
ev.register(priority, () => zone.run(callback))
|
||||
));
|
||||
return this.subscribe(ev => {
|
||||
return ev.register(priority, processNextHandler => zone.run(() => callback(processNextHandler)));
|
||||
});
|
||||
};
|
||||
|
||||
proxyEvent(this.pause, doc, 'pause');
|
||||
proxyEvent(this.resume, doc, 'resume');
|
||||
proxyEvent(this.backButton, doc, 'ionBackButton');
|
||||
proxyEvent(this.resize, this.win, 'resize');
|
||||
proxyEvent(this.keyboardDidShow, this.win, 'ionKeyboardDidShow');
|
||||
proxyEvent(this.keyboardDidHide, this.win, 'ionKeyboardDidHide');
|
||||
|
||||
let readyResolve: (value: string) => void;
|
||||
this._readyPromise = new Promise(res => { readyResolve = res; });
|
||||
|
||||
@@ -2,7 +2,7 @@ import { join, Path } from '@angular-devkit/core';
|
||||
import { apply, chain, mergeWith, move, Rule, SchematicContext, SchematicsException, template, Tree, url } from '@angular-devkit/schematics';
|
||||
import { NodePackageInstallTask } from '@angular-devkit/schematics/tasks';
|
||||
import { addModuleImportToRootModule } from './../utils/ast';
|
||||
import { addArchitectBuilder, addStyle, getWorkspace, addAsset, WorkspaceProject, WorkspaceSchema } from './../utils/config';
|
||||
import { addArchitectBuilder, addAsset, addStyle, getDefaultAngularAppName, getWorkspace, WorkspaceProject, WorkspaceSchema } from './../utils/config';
|
||||
import { addPackageToPackageJson } from './../utils/package';
|
||||
import { Schema as IonAddOptions } from './schema';
|
||||
|
||||
@@ -37,7 +37,7 @@ function addIonicAngularModuleToAppModule(projectSourceRoot: Path): Rule {
|
||||
};
|
||||
}
|
||||
|
||||
function addIonicStyles(projectSourceRoot: Path): Rule {
|
||||
function addIonicStyles(projectName: string, projectSourceRoot: Path): Rule {
|
||||
return (host: Tree) => {
|
||||
const ionicStyles = [
|
||||
'node_modules/@ionic/angular/css/normalize.css',
|
||||
@@ -51,27 +51,27 @@ function addIonicStyles(projectSourceRoot: Path): Rule {
|
||||
'node_modules/@ionic/angular/css/flex-utils.css',
|
||||
`${projectSourceRoot}/theme/variables.css`
|
||||
].forEach(entry => {
|
||||
addStyle(host, entry);
|
||||
addStyle(host, projectName, entry);
|
||||
});
|
||||
return host;
|
||||
};
|
||||
}
|
||||
|
||||
function addIonicons(): Rule {
|
||||
function addIonicons(projectName: string): Rule {
|
||||
return (host: Tree) => {
|
||||
const ioniconsGlob = {
|
||||
glob: '**/*.svg',
|
||||
input: 'node_modules/ionicons/dist/ionicons/svg',
|
||||
output: './svg'
|
||||
};
|
||||
addAsset(host, ioniconsGlob);
|
||||
addAsset(host, projectName, ioniconsGlob);
|
||||
return host;
|
||||
};
|
||||
}
|
||||
|
||||
function addIonicBuilder(projectName: string): Rule {
|
||||
return (host: Tree) => {
|
||||
addArchitectBuilder(host, 'ionic-cordova-serve', {
|
||||
addArchitectBuilder(host, projectName, 'ionic-cordova-serve', {
|
||||
builder: '@ionic/angular-toolkit:cordova-serve',
|
||||
options: {
|
||||
cordovaBuildTarget: `${projectName}:ionic-cordova-build`,
|
||||
@@ -84,7 +84,7 @@ function addIonicBuilder(projectName: string): Rule {
|
||||
}
|
||||
}
|
||||
});
|
||||
addArchitectBuilder(host, 'ionic-cordova-build', {
|
||||
addArchitectBuilder(host, projectName, 'ionic-cordova-build', {
|
||||
builder: '@ionic/angular-toolkit:cordova-build',
|
||||
options: {
|
||||
browserTarget: `${projectName}:build`
|
||||
@@ -109,7 +109,7 @@ export default function ngAdd(options: IonAddOptions): Rule {
|
||||
return (host: Tree) => {
|
||||
const workspace: WorkspaceSchema = getWorkspace(host);
|
||||
if (!options.project) {
|
||||
options.project = Object.keys(workspace.projects)[0];
|
||||
options.project = getDefaultAngularAppName(workspace);
|
||||
}
|
||||
const project: WorkspaceProject = workspace.projects[options.project];
|
||||
if (project.projectType !== 'application') {
|
||||
@@ -117,7 +117,7 @@ export default function ngAdd(options: IonAddOptions): Rule {
|
||||
`Ionic Add requires a project type of "application".`
|
||||
);
|
||||
}
|
||||
const sourcePath: Path = join(project.root as Path, project.sourceRoot as Path);
|
||||
const sourcePath: Path = join(project.sourceRoot as Path);
|
||||
const rootTemplateSource = apply(url('./files/root'), [
|
||||
template({ ...options }),
|
||||
move(sourcePath)
|
||||
@@ -128,8 +128,8 @@ export default function ngAdd(options: IonAddOptions): Rule {
|
||||
addIonicAngularToolkitToPackageJson(),
|
||||
addIonicAngularModuleToAppModule(sourcePath),
|
||||
addIonicBuilder(options.project),
|
||||
addIonicStyles(sourcePath),
|
||||
addIonicons(),
|
||||
addIonicStyles(options.project, sourcePath),
|
||||
addIonicons(options.project),
|
||||
mergeWith(rootTemplateSource),
|
||||
// install freshly added dependencies
|
||||
installNodeDeps()
|
||||
|
||||
@@ -27,7 +27,7 @@ export function getSourceFile(host: Tree, path: string): ts.SourceFile {
|
||||
*/
|
||||
export function addModuleImportToRootModule(
|
||||
host: Tree,
|
||||
projectSourceRoot,
|
||||
projectSourceRoot: string,
|
||||
moduleName: string,
|
||||
importSrc: string
|
||||
) {
|
||||
|
||||
@@ -21,7 +21,7 @@ function isAngularBrowserProject(projectConfig: any) {
|
||||
return false;
|
||||
}
|
||||
|
||||
export function getAngularAppName(config: any): string | null {
|
||||
export function getDefaultAngularAppName(config: any): string {
|
||||
const projects = config.projects;
|
||||
const projectNames = Object.keys(projects);
|
||||
|
||||
@@ -32,60 +32,48 @@ export function getAngularAppName(config: any): string | null {
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
return projectNames[0];
|
||||
}
|
||||
|
||||
export function getAngularAppConfig(config: any): any | null {
|
||||
const projects = config.projects;
|
||||
const projectNames = Object.keys(projects);
|
||||
|
||||
for (const projectName of projectNames) {
|
||||
const projectConfig = projects[projectName];
|
||||
if (isAngularBrowserProject(projectConfig)) {
|
||||
return projectConfig;
|
||||
}
|
||||
export function getAngularAppConfig(config: any, projectName: string): any | never {
|
||||
if (!config.projects.hasOwnProperty(projectName)) {
|
||||
throw new SchematicsException(`Could not find project: ${projectName}`);
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
const projectConfig = config.projects[projectName];
|
||||
if (isAngularBrowserProject(projectConfig)) {
|
||||
return projectConfig;
|
||||
}
|
||||
|
||||
export function addStyle(host: Tree, stylePath: string) {
|
||||
const config = readConfig(host);
|
||||
const appConfig = getAngularAppConfig(config);
|
||||
|
||||
if (appConfig) {
|
||||
appConfig.architect.build.options.styles.push({
|
||||
input: stylePath
|
||||
});
|
||||
|
||||
writeConfig(host, config);
|
||||
if (config.projectType !== 'application') {
|
||||
throw new SchematicsException(`Invalid projectType for ${projectName}: ${config.projectType}`);
|
||||
} else {
|
||||
throw new SchematicsException(`Cannot find valid app`);
|
||||
const buildConfig = projectConfig.architect.build;
|
||||
throw new SchematicsException(`Invalid builder for ${projectName}: ${buildConfig.builder}`);
|
||||
}
|
||||
}
|
||||
|
||||
export function addAsset(host: Tree, asset: string | {glob: string; input: string; output: string}) {
|
||||
export function addStyle(host: Tree, projectName: string, stylePath: string) {
|
||||
const config = readConfig(host);
|
||||
const appConfig = getAngularAppConfig(config);
|
||||
|
||||
if (appConfig) {
|
||||
appConfig.architect.build.options.assets.push(asset);
|
||||
writeConfig(host, config);
|
||||
} else {
|
||||
throw new SchematicsException(`Cannot find valid app`);
|
||||
}
|
||||
const appConfig = getAngularAppConfig(config, projectName);
|
||||
appConfig.architect.build.options.styles.push({
|
||||
input: stylePath
|
||||
});
|
||||
writeConfig(host, config);
|
||||
}
|
||||
|
||||
export function addArchitectBuilder(host: Tree, builderName: string, builderOpts: any){
|
||||
export function addAsset(host: Tree, projectName: string, asset: string | {glob: string; input: string; output: string}) {
|
||||
const config = readConfig(host);
|
||||
const appConfig = getAngularAppConfig(config);
|
||||
const appConfig = getAngularAppConfig(config, projectName);
|
||||
appConfig.architect.build.options.assets.push(asset);
|
||||
writeConfig(host, config);
|
||||
}
|
||||
|
||||
if (appConfig) {
|
||||
appConfig.architect[builderName] = builderOpts
|
||||
writeConfig(host, config);
|
||||
} else {
|
||||
throw new SchematicsException(`Cannot find valid app`);
|
||||
}
|
||||
export function addArchitectBuilder(host: Tree, projectName: string, builderName: string, builderOpts: any): void | never {
|
||||
const config = readConfig(host);
|
||||
const appConfig = getAngularAppConfig(config, projectName);
|
||||
appConfig.architect[builderName] = builderOpts;
|
||||
writeConfig(host, config);
|
||||
}
|
||||
|
||||
export type WorkspaceSchema = experimental.workspace.WorkspaceSchema;
|
||||
|
||||
31
angular/src/types/ionic-lifecycle-hooks.ts
Normal file
31
angular/src/types/ionic-lifecycle-hooks.ts
Normal file
@@ -0,0 +1,31 @@
|
||||
/**
|
||||
* https://ionicframework.com/docs/api/router-outlet#life-cycle-hooks
|
||||
*/
|
||||
|
||||
export interface ViewWillEnter {
|
||||
/**
|
||||
* Fired when the component routing to is about to animate into view.
|
||||
*/
|
||||
ionViewWillEnter(): void;
|
||||
}
|
||||
|
||||
export interface ViewDidEnter {
|
||||
/**
|
||||
* Fired when the component routing to has finished animating.
|
||||
*/
|
||||
ionViewDidEnter(): void;
|
||||
}
|
||||
|
||||
export interface ViewWillLeave {
|
||||
/**
|
||||
* Fired when the component routing from is about to animate.
|
||||
*/
|
||||
ionViewWillLeave(): void;
|
||||
}
|
||||
|
||||
export interface ViewDidLeave {
|
||||
/**
|
||||
* Fired when the component routing to has finished animating.
|
||||
*/
|
||||
ionViewDidLeave(): void;
|
||||
}
|
||||
@@ -41,7 +41,7 @@
|
||||
"@angular/cli": "^9.0.0-rc.2",
|
||||
"@angular/compiler-cli": "^9.0.0-rc.2",
|
||||
"@angular/language-service": "^9.0.0-rc.2",
|
||||
"@nguniversal/builders": "^9.0.0-next.9",
|
||||
"@nguniversal/builders": "9.0.0-next.9",
|
||||
"@types/express": "^4.17.0",
|
||||
"@types/jasmine": "3.4.1",
|
||||
"@types/node": "^12.11.1",
|
||||
|
||||
@@ -1,11 +1,11 @@
|
||||
import { Component, Input, NgZone, OnInit, Optional } from '@angular/core';
|
||||
import { ModalController, NavParams, IonNav } from '@ionic/angular';
|
||||
import { ModalController, NavParams, IonNav, ViewWillLeave, ViewDidEnter, ViewDidLeave } from '@ionic/angular';
|
||||
|
||||
@Component({
|
||||
selector: 'app-modal-example',
|
||||
templateUrl: './modal-example.component.html',
|
||||
})
|
||||
export class ModalExampleComponent implements OnInit {
|
||||
export class ModalExampleComponent implements OnInit, ViewWillLeave, ViewDidEnter, ViewWillLeave, ViewDidLeave {
|
||||
|
||||
@Input() value: string;
|
||||
|
||||
|
||||
@@ -1,11 +1,11 @@
|
||||
import { Component, OnInit, NgZone } from '@angular/core';
|
||||
import { IonRouterOutlet } from '@ionic/angular';
|
||||
import { IonRouterOutlet, ViewDidEnter, ViewDidLeave, ViewWillLeave } from '@ionic/angular';
|
||||
|
||||
@Component({
|
||||
selector: 'app-router-link-page',
|
||||
templateUrl: './router-link-page.component.html',
|
||||
})
|
||||
export class RouterLinkPageComponent implements OnInit {
|
||||
export class RouterLinkPageComponent implements OnInit, ViewWillLeave, ViewDidEnter, ViewWillLeave, ViewDidLeave {
|
||||
|
||||
onInit = 0;
|
||||
willEnter = 0;
|
||||
|
||||
@@ -1,12 +1,12 @@
|
||||
import { Component, NgZone, OnInit } from '@angular/core';
|
||||
import { NavController } from '@ionic/angular';
|
||||
import { NavController, ViewDidEnter, ViewDidLeave, ViewWillEnter, ViewWillLeave } from '@ionic/angular';
|
||||
import { Router } from '@angular/router';
|
||||
|
||||
@Component({
|
||||
selector: 'app-router-link',
|
||||
templateUrl: './router-link.component.html',
|
||||
})
|
||||
export class RouterLinkComponent implements OnInit {
|
||||
export class RouterLinkComponent implements OnInit, ViewWillEnter, ViewDidEnter, ViewWillLeave, ViewDidLeave {
|
||||
|
||||
onInit = 0;
|
||||
willEnter = 0;
|
||||
|
||||
@@ -1,11 +1,12 @@
|
||||
import { Component, NgZone, OnInit } from '@angular/core';
|
||||
import { ActivatedRoute } from '@angular/router';
|
||||
import { ViewDidEnter, ViewDidLeave, ViewWillEnter, ViewWillLeave } from '@ionic/angular';
|
||||
|
||||
@Component({
|
||||
selector: 'app-virtual-scroll-detail',
|
||||
templateUrl: './virtual-scroll-detail.component.html',
|
||||
})
|
||||
export class VirtualScrollDetailComponent implements OnInit {
|
||||
export class VirtualScrollDetailComponent implements OnInit, ViewWillEnter, ViewDidEnter, ViewWillLeave, ViewDidLeave {
|
||||
|
||||
onInit = 0;
|
||||
willEnter = 0;
|
||||
|
||||
@@ -23,9 +23,9 @@ 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
|
||||
<script type="module" src="https://cdn.jsdelivr.net/npm/@ionic/core@4.6.2/dist/ionic/ionic.esm.js"></script>
|
||||
<script nomodule src="https://cdn.jsdelivr.net/npm/@ionic/core@4.6.2/dist/ionic/ionic.js"></script>
|
||||
<link href="https://cdn.jsdelivr.net/npm/@ionic/core@4.6.2/css/ionic.bundle.css" rel="stylesheet">
|
||||
<script type="module" src="https://cdn.jsdelivr.net/npm/@ionic/core/dist/ionic/ionic.esm.js"></script>
|
||||
<script nomodule src="https://cdn.jsdelivr.net/npm/@ionic/core/dist/ionic/ionic.js"></script>
|
||||
<link href="https://cdn.jsdelivr.net/npm/@ionic/core/css/ionic.bundle.css" rel="stylesheet">
|
||||
```
|
||||
|
||||
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')`.
|
||||
|
||||
83
core/api.txt
83
core/api.txt
@@ -12,8 +12,8 @@ ion-action-sheet,prop,mode,"ios" | "md",undefined,false,false
|
||||
ion-action-sheet,prop,subHeader,string | undefined,undefined,false,false
|
||||
ion-action-sheet,prop,translucent,boolean,false,false,false
|
||||
ion-action-sheet,method,dismiss,dismiss(data?: any, role?: string | undefined) => Promise<boolean>
|
||||
ion-action-sheet,method,onDidDismiss,onDidDismiss() => Promise<OverlayEventDetail<any>>
|
||||
ion-action-sheet,method,onWillDismiss,onWillDismiss() => Promise<OverlayEventDetail<any>>
|
||||
ion-action-sheet,method,onDidDismiss,onDidDismiss<T = any>() => Promise<OverlayEventDetail<T>>
|
||||
ion-action-sheet,method,onWillDismiss,onWillDismiss<T = any>() => Promise<OverlayEventDetail<T>>
|
||||
ion-action-sheet,method,present,present() => Promise<void>
|
||||
ion-action-sheet,event,ionActionSheetDidDismiss,OverlayEventDetail<any>,true
|
||||
ion-action-sheet,event,ionActionSheetDidPresent,void,true
|
||||
@@ -53,13 +53,13 @@ ion-alert,prop,header,string | undefined,undefined,false,false
|
||||
ion-alert,prop,inputs,AlertInput[],[],false,false
|
||||
ion-alert,prop,keyboardClose,boolean,true,false,false
|
||||
ion-alert,prop,leaveAnimation,((baseEl: any, opts?: any) => Animation) | undefined,undefined,false,false
|
||||
ion-alert,prop,message,string | undefined,undefined,false,false
|
||||
ion-alert,prop,message,IonicSafeString | string | undefined,undefined,false,false
|
||||
ion-alert,prop,mode,"ios" | "md",undefined,false,false
|
||||
ion-alert,prop,subHeader,string | undefined,undefined,false,false
|
||||
ion-alert,prop,translucent,boolean,false,false,false
|
||||
ion-alert,method,dismiss,dismiss(data?: any, role?: string | undefined) => Promise<boolean>
|
||||
ion-alert,method,onDidDismiss,onDidDismiss() => Promise<OverlayEventDetail<any>>
|
||||
ion-alert,method,onWillDismiss,onWillDismiss() => Promise<OverlayEventDetail<any>>
|
||||
ion-alert,method,onDidDismiss,onDidDismiss<T = any>() => Promise<OverlayEventDetail<T>>
|
||||
ion-alert,method,onWillDismiss,onWillDismiss<T = any>() => Promise<OverlayEventDetail<T>>
|
||||
ion-alert,method,present,present() => Promise<void>
|
||||
ion-alert,event,ionAlertDidDismiss,OverlayEventDetail<any>,true
|
||||
ion-alert,event,ionAlertDidPresent,void,true
|
||||
@@ -235,6 +235,8 @@ ion-checkbox,css-prop,--checkmark-color
|
||||
ion-checkbox,css-prop,--checkmark-width
|
||||
ion-checkbox,css-prop,--size
|
||||
ion-checkbox,css-prop,--transition
|
||||
ion-checkbox,part,container
|
||||
ion-checkbox,part,mark
|
||||
|
||||
ion-chip,shadow
|
||||
ion-chip,prop,color,string | undefined,undefined,false,false
|
||||
@@ -300,6 +302,8 @@ ion-content,css-prop,--padding-bottom
|
||||
ion-content,css-prop,--padding-end
|
||||
ion-content,css-prop,--padding-start
|
||||
ion-content,css-prop,--padding-top
|
||||
ion-content,part,background
|
||||
ion-content,part,scroll
|
||||
|
||||
ion-datetime,shadow
|
||||
ion-datetime,prop,cancelText,string,'Cancel',false,false
|
||||
@@ -320,7 +324,7 @@ ion-datetime,prop,monthShortNames,string | string[] | undefined,undefined,false,
|
||||
ion-datetime,prop,monthValues,number | number[] | string | undefined,undefined,false,false
|
||||
ion-datetime,prop,name,string,this.inputId,false,false
|
||||
ion-datetime,prop,pickerFormat,string | undefined,undefined,false,false
|
||||
ion-datetime,prop,pickerOptions,undefined | { columns?: PickerColumn[] | undefined; buttons?: PickerButton[] | undefined; cssClass?: string | string[] | undefined; backdropDismiss?: boolean | undefined; animated?: boolean | undefined; mode?: "ios" | "md" | undefined; keyboardClose?: boolean | undefined; id?: string | undefined; enterAnimation?: AnimationBuilder | undefined; leaveAnimation?: AnimationBuilder | undefined; },undefined,false,false
|
||||
ion-datetime,prop,pickerOptions,undefined | { columns?: PickerColumn[] | undefined; buttons?: PickerButton[] | undefined; cssClass?: string | string[] | undefined; showBackdrop?: boolean | undefined; backdropDismiss?: boolean | undefined; animated?: boolean | undefined; mode?: "ios" | "md" | undefined; keyboardClose?: boolean | undefined; id?: string | undefined; enterAnimation?: AnimationBuilder | undefined; leaveAnimation?: AnimationBuilder | undefined; },undefined,false,false
|
||||
ion-datetime,prop,placeholder,null | string | undefined,undefined,false,false
|
||||
ion-datetime,prop,readonly,boolean,false,false,false
|
||||
ion-datetime,prop,value,null | string | undefined,undefined,false,false
|
||||
@@ -335,6 +339,8 @@ ion-datetime,css-prop,--padding-end
|
||||
ion-datetime,css-prop,--padding-start
|
||||
ion-datetime,css-prop,--padding-top
|
||||
ion-datetime,css-prop,--placeholder-color
|
||||
ion-datetime,part,placeholder
|
||||
ion-datetime,part,text
|
||||
|
||||
ion-fab,shadow
|
||||
ion-fab,prop,activated,boolean,false,false,false
|
||||
@@ -416,6 +422,7 @@ ion-img,prop,src,string | undefined,undefined,false,false
|
||||
ion-img,event,ionError,void,true
|
||||
ion-img,event,ionImgDidLoad,void,true
|
||||
ion-img,event,ionImgWillLoad,void,true
|
||||
ion-img,part,image
|
||||
|
||||
ion-infinite-scroll,none
|
||||
ion-infinite-scroll,prop,disabled,boolean,false,false,false
|
||||
@@ -426,12 +433,12 @@ ion-infinite-scroll,event,ionInfinite,void,true
|
||||
|
||||
ion-infinite-scroll-content,none
|
||||
ion-infinite-scroll-content,prop,loadingSpinner,"bubbles" | "circles" | "circular" | "crescent" | "dots" | "lines" | "lines-small" | null | undefined,undefined,false,false
|
||||
ion-infinite-scroll-content,prop,loadingText,string | undefined,undefined,false,false
|
||||
ion-infinite-scroll-content,prop,loadingText,IonicSafeString | string | undefined,undefined,false,false
|
||||
|
||||
ion-input,scoped
|
||||
ion-input,prop,accept,string | undefined,undefined,false,false
|
||||
ion-input,prop,autocapitalize,string,'off',false,false
|
||||
ion-input,prop,autocomplete,"off" | "on",'off',false,false
|
||||
ion-input,prop,autocomplete,"on" | "off" | "name" | "honorific-prefix" | "given-name" | "additional-name" | "family-name" | "honorific-suffix" | "nickname" | "email" | "username" | "new-password" | "current-password" | "one-time-code" | "organization-title" | "organization" | "street-address" | "address-line1" | "address-line2" | "address-line3" | "address-level4" | "address-level3" | "address-level2" | "address-level1" | "country" | "country-name" | "postal-code" | "cc-name" | "cc-given-name" | "cc-additional-name" | "cc-family-name" | "cc-number" | "cc-exp" | "cc-exp-month" | "cc-exp-year" | "cc-csc" | "cc-type" | "transaction-currency" | "transaction-amount" | "language" | "bday" | "bday-day" | "bday-month" | "bday-year" | "sex" | "tel" | "tel-country-code" | "tel-national" | "tel-area-code" | "tel-local" | "tel-extension" | "impp" | "url" | "photo",'off',false,false
|
||||
ion-input,prop,autocorrect,"off" | "on",'off',false,false
|
||||
ion-input,prop,autofocus,boolean,false,false,false
|
||||
ion-input,prop,clearInput,boolean,false,false,false
|
||||
@@ -439,6 +446,7 @@ ion-input,prop,clearOnEdit,boolean | undefined,undefined,false,false
|
||||
ion-input,prop,color,string | undefined,undefined,false,false
|
||||
ion-input,prop,debounce,number,0,false,false
|
||||
ion-input,prop,disabled,boolean,false,false,false
|
||||
ion-input,prop,enterkeyhint,"done" | "enter" | "go" | "next" | "previous" | "search" | "send" | undefined,undefined,false,false
|
||||
ion-input,prop,inputmode,"decimal" | "email" | "none" | "numeric" | "search" | "tel" | "text" | "url" | undefined,undefined,false,false
|
||||
ion-input,prop,max,string | undefined,undefined,false,false
|
||||
ion-input,prop,maxlength,number | undefined,undefined,false,false
|
||||
@@ -498,7 +506,6 @@ ion-item,css-prop,--border-color
|
||||
ion-item,css-prop,--border-radius
|
||||
ion-item,css-prop,--border-style
|
||||
ion-item,css-prop,--border-width
|
||||
ion-item,css-prop,--box-shadow
|
||||
ion-item,css-prop,--color
|
||||
ion-item,css-prop,--color-activated
|
||||
ion-item,css-prop,--color-focused
|
||||
@@ -523,6 +530,7 @@ ion-item,css-prop,--padding-start
|
||||
ion-item,css-prop,--padding-top
|
||||
ion-item,css-prop,--ripple-color
|
||||
ion-item,css-prop,--transition
|
||||
ion-item,part,detail-icon
|
||||
|
||||
ion-item-divider,shadow
|
||||
ion-item-divider,prop,color,string | undefined,undefined,false,false
|
||||
@@ -598,14 +606,14 @@ ion-loading,prop,duration,number,0,false,false
|
||||
ion-loading,prop,enterAnimation,((baseEl: any, opts?: any) => Animation) | undefined,undefined,false,false
|
||||
ion-loading,prop,keyboardClose,boolean,true,false,false
|
||||
ion-loading,prop,leaveAnimation,((baseEl: any, opts?: any) => Animation) | undefined,undefined,false,false
|
||||
ion-loading,prop,message,string | undefined,undefined,false,false
|
||||
ion-loading,prop,message,IonicSafeString | string | undefined,undefined,false,false
|
||||
ion-loading,prop,mode,"ios" | "md",undefined,false,false
|
||||
ion-loading,prop,showBackdrop,boolean,true,false,false
|
||||
ion-loading,prop,spinner,"bubbles" | "circles" | "circular" | "crescent" | "dots" | "lines" | "lines-small" | null | undefined,undefined,false,false
|
||||
ion-loading,prop,translucent,boolean,false,false,false
|
||||
ion-loading,method,dismiss,dismiss(data?: any, role?: string | undefined) => Promise<boolean>
|
||||
ion-loading,method,onDidDismiss,onDidDismiss() => Promise<OverlayEventDetail<any>>
|
||||
ion-loading,method,onWillDismiss,onWillDismiss() => Promise<OverlayEventDetail<any>>
|
||||
ion-loading,method,onDidDismiss,onDidDismiss<T = any>() => Promise<OverlayEventDetail<T>>
|
||||
ion-loading,method,onWillDismiss,onWillDismiss<T = any>() => Promise<OverlayEventDetail<T>>
|
||||
ion-loading,method,present,present() => Promise<void>
|
||||
ion-loading,event,ionLoadingDidDismiss,OverlayEventDetail<any>,true
|
||||
ion-loading,event,ionLoadingDidPresent,void,true
|
||||
@@ -646,6 +654,8 @@ ion-menu,css-prop,--max-width
|
||||
ion-menu,css-prop,--min-height
|
||||
ion-menu,css-prop,--min-width
|
||||
ion-menu,css-prop,--width
|
||||
ion-menu,part,backdrop
|
||||
ion-menu,part,container
|
||||
|
||||
ion-menu-button,shadow
|
||||
ion-menu-button,prop,autoHide,boolean,true,false,false
|
||||
@@ -685,8 +695,8 @@ ion-modal,prop,presentingElement,HTMLElement | undefined,undefined,false,false
|
||||
ion-modal,prop,showBackdrop,boolean,true,false,false
|
||||
ion-modal,prop,swipeToClose,boolean,false,false,false
|
||||
ion-modal,method,dismiss,dismiss(data?: any, role?: string | undefined) => Promise<boolean>
|
||||
ion-modal,method,onDidDismiss,onDidDismiss() => Promise<OverlayEventDetail<any>>
|
||||
ion-modal,method,onWillDismiss,onWillDismiss() => Promise<OverlayEventDetail<any>>
|
||||
ion-modal,method,onDidDismiss,onDidDismiss<T = any>() => Promise<OverlayEventDetail<T>>
|
||||
ion-modal,method,onWillDismiss,onWillDismiss<T = any>() => Promise<OverlayEventDetail<T>>
|
||||
ion-modal,method,present,present() => Promise<void>
|
||||
ion-modal,event,ionModalDidDismiss,OverlayEventDetail<any>,true
|
||||
ion-modal,event,ionModalDidPresent,void,true
|
||||
@@ -751,8 +761,8 @@ ion-picker,prop,mode,"ios" | "md",undefined,false,false
|
||||
ion-picker,prop,showBackdrop,boolean,true,false,false
|
||||
ion-picker,method,dismiss,dismiss(data?: any, role?: string | undefined) => Promise<boolean>
|
||||
ion-picker,method,getColumn,getColumn(name: string) => Promise<PickerColumn | undefined>
|
||||
ion-picker,method,onDidDismiss,onDidDismiss() => Promise<OverlayEventDetail<any>>
|
||||
ion-picker,method,onWillDismiss,onWillDismiss() => Promise<OverlayEventDetail<any>>
|
||||
ion-picker,method,onDidDismiss,onDidDismiss<T = any>() => Promise<OverlayEventDetail<T>>
|
||||
ion-picker,method,onWillDismiss,onWillDismiss<T = any>() => Promise<OverlayEventDetail<T>>
|
||||
ion-picker,method,present,present() => Promise<void>
|
||||
ion-picker,event,ionPickerDidDismiss,OverlayEventDetail<any>,true
|
||||
ion-picker,event,ionPickerDidPresent,void,true
|
||||
@@ -786,8 +796,8 @@ ion-popover,prop,mode,"ios" | "md",undefined,false,false
|
||||
ion-popover,prop,showBackdrop,boolean,true,false,false
|
||||
ion-popover,prop,translucent,boolean,false,false,false
|
||||
ion-popover,method,dismiss,dismiss(data?: any, role?: string | undefined) => Promise<boolean>
|
||||
ion-popover,method,onDidDismiss,onDidDismiss() => Promise<OverlayEventDetail<any>>
|
||||
ion-popover,method,onWillDismiss,onWillDismiss() => Promise<OverlayEventDetail<any>>
|
||||
ion-popover,method,onDidDismiss,onDidDismiss<T = any>() => Promise<OverlayEventDetail<T>>
|
||||
ion-popover,method,onWillDismiss,onWillDismiss<T = any>() => Promise<OverlayEventDetail<T>>
|
||||
ion-popover,method,present,present() => Promise<void>
|
||||
ion-popover,event,ionPopoverDidDismiss,OverlayEventDetail<any>,true
|
||||
ion-popover,event,ionPopoverDidPresent,void,true
|
||||
@@ -826,6 +836,8 @@ ion-radio,css-prop,--border-radius
|
||||
ion-radio,css-prop,--color
|
||||
ion-radio,css-prop,--color-checked
|
||||
ion-radio,css-prop,--inner-border-radius
|
||||
ion-radio,part,container
|
||||
ion-radio,part,mark
|
||||
|
||||
ion-radio-group,none
|
||||
ion-radio-group,prop,allowEmptySelection,boolean,false,false,false
|
||||
@@ -861,6 +873,12 @@ ion-range,css-prop,--knob-box-shadow
|
||||
ion-range,css-prop,--knob-size
|
||||
ion-range,css-prop,--pin-background
|
||||
ion-range,css-prop,--pin-color
|
||||
ion-range,part,bar
|
||||
ion-range,part,bar-active
|
||||
ion-range,part,knob
|
||||
ion-range,part,pin
|
||||
ion-range,part,tick
|
||||
ion-range,part,tick-active
|
||||
|
||||
ion-refresher,none
|
||||
ion-refresher,prop,closeDuration,string,'280ms',false,false
|
||||
@@ -878,11 +896,12 @@ ion-refresher,event,ionStart,void,true
|
||||
|
||||
ion-refresher-content,none
|
||||
ion-refresher-content,prop,pullingIcon,null | string | undefined,undefined,false,false
|
||||
ion-refresher-content,prop,pullingText,string | undefined,undefined,false,false
|
||||
ion-refresher-content,prop,pullingText,IonicSafeString | string | undefined,undefined,false,false
|
||||
ion-refresher-content,prop,refreshingSpinner,"bubbles" | "circles" | "circular" | "crescent" | "dots" | "lines" | "lines-small" | null | undefined,undefined,false,false
|
||||
ion-refresher-content,prop,refreshingText,string | undefined,undefined,false,false
|
||||
ion-refresher-content,prop,refreshingText,IonicSafeString | string | undefined,undefined,false,false
|
||||
|
||||
ion-reorder,shadow
|
||||
ion-reorder,part,icon
|
||||
|
||||
ion-reorder-group,none
|
||||
ion-reorder-group,prop,disabled,boolean,true,false,false
|
||||
@@ -930,7 +949,7 @@ ion-row,shadow
|
||||
|
||||
ion-searchbar,scoped
|
||||
ion-searchbar,prop,animated,boolean,false,false,false
|
||||
ion-searchbar,prop,autocomplete,"off" | "on",'off',false,false
|
||||
ion-searchbar,prop,autocomplete,"on" | "off" | "name" | "honorific-prefix" | "given-name" | "additional-name" | "family-name" | "honorific-suffix" | "nickname" | "email" | "username" | "new-password" | "current-password" | "one-time-code" | "organization-title" | "organization" | "street-address" | "address-line1" | "address-line2" | "address-line3" | "address-level4" | "address-level3" | "address-level2" | "address-level1" | "country" | "country-name" | "postal-code" | "cc-name" | "cc-given-name" | "cc-additional-name" | "cc-family-name" | "cc-number" | "cc-exp" | "cc-exp-month" | "cc-exp-year" | "cc-csc" | "cc-type" | "transaction-currency" | "transaction-amount" | "language" | "bday" | "bday-day" | "bday-month" | "bday-year" | "sex" | "tel" | "tel-country-code" | "tel-national" | "tel-area-code" | "tel-local" | "tel-extension" | "impp" | "url" | "photo",'off',false,false
|
||||
ion-searchbar,prop,autocorrect,"off" | "on",'off',false,false
|
||||
ion-searchbar,prop,cancelButtonIcon,string,config.get('backButtonIcon', 'arrow-back-sharp') as string,false,false
|
||||
ion-searchbar,prop,cancelButtonText,string,'Cancel',false,false
|
||||
@@ -938,6 +957,7 @@ ion-searchbar,prop,clearIcon,string | undefined,undefined,false,false
|
||||
ion-searchbar,prop,color,string | undefined,undefined,false,false
|
||||
ion-searchbar,prop,debounce,number,250,false,false
|
||||
ion-searchbar,prop,disabled,boolean,false,false,false
|
||||
ion-searchbar,prop,enterkeyhint,"done" | "enter" | "go" | "next" | "previous" | "search" | "send" | undefined,undefined,false,false
|
||||
ion-searchbar,prop,inputmode,"decimal" | "email" | "none" | "numeric" | "search" | "tel" | "text" | "url" | undefined,undefined,false,false
|
||||
ion-searchbar,prop,mode,"ios" | "md",undefined,false,false
|
||||
ion-searchbar,prop,placeholder,string,'Search',false,false
|
||||
@@ -955,6 +975,7 @@ ion-searchbar,event,ionClear,void,true
|
||||
ion-searchbar,event,ionFocus,void,true
|
||||
ion-searchbar,event,ionInput,KeyboardEvent,true
|
||||
ion-searchbar,css-prop,--background
|
||||
ion-searchbar,css-prop,--border-radius
|
||||
ion-searchbar,css-prop,--box-shadow
|
||||
ion-searchbar,css-prop,--cancel-button-color
|
||||
ion-searchbar,css-prop,--clear-button-color
|
||||
@@ -1033,6 +1054,9 @@ ion-select,css-prop,--padding-start
|
||||
ion-select,css-prop,--padding-top
|
||||
ion-select,css-prop,--placeholder-color
|
||||
ion-select,css-prop,--placeholder-opacity
|
||||
ion-select,part,icon
|
||||
ion-select,part,placeholder
|
||||
ion-select,part,text
|
||||
|
||||
ion-select-option,shadow
|
||||
ion-select-option,prop,disabled,boolean,false,false,false
|
||||
@@ -1163,6 +1187,8 @@ ion-textarea,prop,color,string | undefined,undefined,false,false
|
||||
ion-textarea,prop,cols,number | undefined,undefined,false,false
|
||||
ion-textarea,prop,debounce,number,0,false,false
|
||||
ion-textarea,prop,disabled,boolean,false,false,false
|
||||
ion-textarea,prop,enterkeyhint,"done" | "enter" | "go" | "next" | "previous" | "search" | "send" | undefined,undefined,false,false
|
||||
ion-textarea,prop,inputmode,"decimal" | "email" | "none" | "numeric" | "search" | "tel" | "text" | "url" | undefined,undefined,false,false
|
||||
ion-textarea,prop,maxlength,number | undefined,undefined,false,false
|
||||
ion-textarea,prop,minlength,number | undefined,undefined,false,false
|
||||
ion-textarea,prop,mode,"ios" | "md",undefined,false,false
|
||||
@@ -1211,13 +1237,13 @@ ion-toast,prop,enterAnimation,((baseEl: any, opts?: any) => Animation) | undefin
|
||||
ion-toast,prop,header,string | undefined,undefined,false,false
|
||||
ion-toast,prop,keyboardClose,boolean,false,false,false
|
||||
ion-toast,prop,leaveAnimation,((baseEl: any, opts?: any) => Animation) | undefined,undefined,false,false
|
||||
ion-toast,prop,message,string | undefined,undefined,false,false
|
||||
ion-toast,prop,message,IonicSafeString | string | undefined,undefined,false,false
|
||||
ion-toast,prop,mode,"ios" | "md",undefined,false,false
|
||||
ion-toast,prop,position,"bottom" | "middle" | "top",'bottom',false,false
|
||||
ion-toast,prop,translucent,boolean,false,false,false
|
||||
ion-toast,method,dismiss,dismiss(data?: any, role?: string | undefined) => Promise<boolean>
|
||||
ion-toast,method,onDidDismiss,onDidDismiss() => Promise<OverlayEventDetail<any>>
|
||||
ion-toast,method,onWillDismiss,onWillDismiss() => Promise<OverlayEventDetail<any>>
|
||||
ion-toast,method,onDidDismiss,onDidDismiss<T = any>() => Promise<OverlayEventDetail<T>>
|
||||
ion-toast,method,onWillDismiss,onWillDismiss<T = any>() => Promise<OverlayEventDetail<T>>
|
||||
ion-toast,method,present,present() => Promise<void>
|
||||
ion-toast,event,ionToastDidDismiss,OverlayEventDetail<any>,true
|
||||
ion-toast,event,ionToastDidPresent,void,true
|
||||
@@ -1238,6 +1264,7 @@ 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,--white-space
|
||||
ion-toast,css-prop,--width
|
||||
|
||||
ion-toggle,shadow
|
||||
@@ -1256,6 +1283,14 @@ ion-toggle,css-prop,--border-radius
|
||||
ion-toggle,css-prop,--handle-background
|
||||
ion-toggle,css-prop,--handle-background-checked
|
||||
ion-toggle,css-prop,--handle-border-radius
|
||||
ion-toggle,css-prop,--handle-box-shadow
|
||||
ion-toggle,css-prop,--handle-height
|
||||
ion-toggle,css-prop,--handle-max-height
|
||||
ion-toggle,css-prop,--handle-spacing
|
||||
ion-toggle,css-prop,--handle-transition
|
||||
ion-toggle,css-prop,--handle-width
|
||||
ion-toggle,part,handle
|
||||
ion-toggle,part,track
|
||||
|
||||
ion-toolbar,shadow
|
||||
ion-toolbar,prop,color,string | undefined,undefined,false,false
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@ionic/core",
|
||||
"version": "5.0.0-rc.2",
|
||||
"version": "5.1.1",
|
||||
"description": "Base components for Ionic",
|
||||
"keywords": [
|
||||
"ionic",
|
||||
@@ -30,16 +30,16 @@
|
||||
"loader/"
|
||||
],
|
||||
"dependencies": {
|
||||
"ionicons": "5.0.0-17",
|
||||
"ionicons": "^5.0.1",
|
||||
"tslib": "^1.10.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@stencil/core": "1.8.3",
|
||||
"@stencil/sass": "1.0.1",
|
||||
"@types/jest": "24.0.21",
|
||||
"@stencil/core": "1.13.0",
|
||||
"@stencil/sass": "1.3.1",
|
||||
"@types/jest": "24.9.1",
|
||||
"@types/node": "12.12.3",
|
||||
"@types/puppeteer": "1.19.1",
|
||||
"@types/swiper": "4.4.4",
|
||||
"@types/swiper": "5.3.1",
|
||||
"aws-sdk": "^2.497.0",
|
||||
"clean-css-cli": "^4.1.11",
|
||||
"domino": "^2.1.3",
|
||||
@@ -49,13 +49,13 @@
|
||||
"np": "^5.0.3",
|
||||
"pixelmatch": "4.0.2",
|
||||
"puppeteer": "1.20.0",
|
||||
"rollup": "1.19.4",
|
||||
"rollup": "1.32.0",
|
||||
"rollup-plugin-node-resolve": "5.2.0",
|
||||
"rollup-plugin-virtual": "^1.0.1",
|
||||
"sass": "^1.22.9",
|
||||
"stylelint": "10.1.0",
|
||||
"stylelint-order": "3.0.1",
|
||||
"swiper": "4.5.1",
|
||||
"swiper": "5.4.1",
|
||||
"tslint": "^5.10.0",
|
||||
"tslint-ionic-rules": "0.0.21",
|
||||
"tslint-react": "^3.6.0"
|
||||
@@ -65,6 +65,7 @@
|
||||
"build.vendor": "rollup --config ./scripts/swiper.rollup.config.js",
|
||||
"build.css": "npm run css.sass && npm run css.minify",
|
||||
"build.debug": "npm run clean && stencil build --debug",
|
||||
"build.docs": "stencil build --docs",
|
||||
"build.docs.json": "stencil build --docs-json dist/docs.json",
|
||||
"clean": "node scripts/clean.js",
|
||||
"cdnloader": "node scripts/copy-cdn-loader.js",
|
||||
|
||||
@@ -35,6 +35,9 @@ function generateComponent(component, content) {
|
||||
component.styles.forEach(prop => {
|
||||
content.push(`${component.tag},css-prop,${prop.name}`);
|
||||
});
|
||||
component.parts.forEach(part => {
|
||||
content.push(`${component.tag},part,${part.name}`);
|
||||
});
|
||||
}
|
||||
|
||||
exports.apiSpecGenerator = apiSpecGenerator;
|
||||
|
||||
12002
core/src/components.d.ts
vendored
12002
core/src/components.d.ts
vendored
File diff suppressed because it is too large
Load Diff
@@ -21,5 +21,5 @@ export interface ActionSheetButton {
|
||||
role?: 'cancel' | 'destructive' | 'selected' | string;
|
||||
icon?: string;
|
||||
cssClass?: string | string[];
|
||||
handler?: () => boolean | void | Promise<boolean>;
|
||||
handler?: () => boolean | void | Promise<boolean | void>;
|
||||
}
|
||||
|
||||
@@ -134,6 +134,8 @@
|
||||
@include margin-horizontal(null, $action-sheet-ios-button-icon-padding-right);
|
||||
|
||||
font-size: $action-sheet-ios-button-icon-font-size;
|
||||
|
||||
pointer-events: none;
|
||||
}
|
||||
|
||||
.action-sheet-button:last-child {
|
||||
|
||||
@@ -121,7 +121,7 @@ $action-sheet-ios-button-background: linear-gradien
|
||||
$action-sheet-ios-button-background-activated: $text-color !default;
|
||||
|
||||
/// @prop - Background color of the selected action sheet button
|
||||
$action-sheet-ios-button-background-selected: $background-color !default;
|
||||
$action-sheet-ios-button-background-selected: var(--ion-color-step-150, $background-color) !default;
|
||||
|
||||
/// @prop - Destructive text color of the action sheet button
|
||||
$action-sheet-ios-button-destructive-text-color: ion-color(danger, base) !default;
|
||||
|
||||
@@ -52,6 +52,8 @@
|
||||
display: block;
|
||||
position: fixed;
|
||||
|
||||
outline: none;
|
||||
|
||||
font-family: $font-family-base;
|
||||
|
||||
touch-action: none;
|
||||
@@ -110,6 +112,7 @@
|
||||
flex-shrink: 0;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
pointer-events: none;
|
||||
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
@@ -210,4 +213,4 @@
|
||||
opacity: var(--button-background-hover-opacity);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,7 +1,9 @@
|
||||
import { Component, ComponentInterface, Element, Event, EventEmitter, Host, Method, Prop, h } from '@stencil/core';
|
||||
import { Component, ComponentInterface, Element, Event, EventEmitter, Host, Method, Prop, h, readTask } from '@stencil/core';
|
||||
|
||||
import { getIonMode } from '../../global/ionic-global';
|
||||
import { ActionSheetButton, AnimationBuilder, CssClassMap, OverlayEventDetail, OverlayInterface } from '../../interface';
|
||||
import { Gesture } from '../../utils/gesture';
|
||||
import { createButtonActiveGesture } from '../../utils/gesture/button-active';
|
||||
import { BACKDROP, dismiss, eventMethod, isCancel, prepareOverlay, present, safeCall } from '../../utils/overlays';
|
||||
import { getClassMap } from '../../utils/theme';
|
||||
|
||||
@@ -25,7 +27,9 @@ export class ActionSheet implements ComponentInterface, OverlayInterface {
|
||||
|
||||
presented = false;
|
||||
animation?: any;
|
||||
mode = getIonMode(this);
|
||||
private wrapperEl?: HTMLElement;
|
||||
private groupEl?: HTMLElement;
|
||||
private gesture?: Gesture;
|
||||
|
||||
@Element() el!: HTMLIonActionSheetElement;
|
||||
|
||||
@@ -135,7 +139,7 @@ export class ActionSheet implements ComponentInterface, OverlayInterface {
|
||||
* Returns a promise that resolves when the action sheet did dismiss.
|
||||
*/
|
||||
@Method()
|
||||
onDidDismiss(): Promise<OverlayEventDetail> {
|
||||
onDidDismiss<T = any>(): Promise<OverlayEventDetail<T>> {
|
||||
return eventMethod(this.el, 'ionActionSheetDidDismiss');
|
||||
}
|
||||
|
||||
@@ -144,7 +148,7 @@ export class ActionSheet implements ComponentInterface, OverlayInterface {
|
||||
*
|
||||
*/
|
||||
@Method()
|
||||
onWillDismiss(): Promise<OverlayEventDetail> {
|
||||
onWillDismiss<T = any>(): Promise<OverlayEventDetail<T>> {
|
||||
return eventMethod(this.el, 'ionActionSheetWillDismiss');
|
||||
}
|
||||
|
||||
@@ -193,6 +197,35 @@ export class ActionSheet implements ComponentInterface, OverlayInterface {
|
||||
}
|
||||
}
|
||||
|
||||
componentDidUnload() {
|
||||
if (this.gesture) {
|
||||
this.gesture.destroy();
|
||||
this.gesture = undefined;
|
||||
}
|
||||
}
|
||||
|
||||
componentDidLoad() {
|
||||
/**
|
||||
* Do not create gesture if:
|
||||
* 1. A gesture already exists
|
||||
* 2. App is running in MD mode
|
||||
* 3. A wrapper ref does not exist
|
||||
*/
|
||||
const { groupEl, wrapperEl } = this;
|
||||
if (this.gesture || getIonMode(this) === 'md' || !wrapperEl || !groupEl) { return; }
|
||||
|
||||
readTask(() => {
|
||||
const isScrollable = groupEl.scrollHeight > groupEl.clientHeight;
|
||||
if (!isScrollable) {
|
||||
this.gesture = createButtonActiveGesture(
|
||||
wrapperEl,
|
||||
(refEl: HTMLElement) => refEl.classList.contains('action-sheet-button')
|
||||
);
|
||||
this.gesture.enable(true);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
render() {
|
||||
const mode = getIonMode(this);
|
||||
const allButtons = this.getButtons();
|
||||
@@ -203,6 +236,7 @@ export class ActionSheet implements ComponentInterface, OverlayInterface {
|
||||
<Host
|
||||
role="dialog"
|
||||
aria-modal="true"
|
||||
tabindex="-1"
|
||||
style={{
|
||||
zIndex: `${20000 + this.overlayIndex}`,
|
||||
}}
|
||||
@@ -216,9 +250,9 @@ export class ActionSheet implements ComponentInterface, OverlayInterface {
|
||||
onIonBackdropTap={this.onBackdropTap}
|
||||
>
|
||||
<ion-backdrop tappable={this.backdropDismiss}/>
|
||||
<div class="action-sheet-wrapper" role="dialog">
|
||||
<div class="action-sheet-wrapper ion-wrapper" role="dialog" ref={el => this.wrapperEl = el}>
|
||||
<div class="action-sheet-container">
|
||||
<div class="action-sheet-group">
|
||||
<div class="action-sheet-group" ref={el => this.groupEl = el}>
|
||||
{this.header !== undefined &&
|
||||
<div class="action-sheet-title">
|
||||
{this.header}
|
||||
|
||||
@@ -11,7 +11,11 @@ export const iosEnterAnimation = (baseEl: HTMLElement): Animation => {
|
||||
|
||||
backdropAnimation
|
||||
.addElement(baseEl.querySelector('ion-backdrop')!)
|
||||
.fromTo('opacity', 0.01, 'var(--backdrop-opacity)');
|
||||
.fromTo('opacity', 0.01, 'var(--backdrop-opacity)')
|
||||
.beforeStyles({
|
||||
'pointer-events': 'none'
|
||||
})
|
||||
.afterClearStyles(['pointer-events']);
|
||||
|
||||
wrapperAnimation
|
||||
.addElement(baseEl.querySelector('.action-sheet-wrapper')!)
|
||||
|
||||
@@ -11,7 +11,11 @@ export const mdEnterAnimation = (baseEl: HTMLElement): Animation => {
|
||||
|
||||
backdropAnimation
|
||||
.addElement(baseEl.querySelector('ion-backdrop')!)
|
||||
.fromTo('opacity', 0.01, 'var(--backdrop-opacity)');
|
||||
.fromTo('opacity', 0.01, 'var(--backdrop-opacity)')
|
||||
.beforeStyles({
|
||||
'pointer-events': 'none'
|
||||
})
|
||||
.afterClearStyles(['pointer-events']);
|
||||
|
||||
wrapperAnimation
|
||||
.addElement(baseEl.querySelector('.action-sheet-wrapper')!)
|
||||
|
||||
@@ -2,14 +2,38 @@
|
||||
|
||||
An Action Sheet is a dialog that displays a set of options. It appears on top of the app's content, and must be manually dismissed by the user before they can resume interaction with the app. Destructive options are made obvious in `ios` mode. There are multiple ways to dismiss the action sheet, including tapping the backdrop or hitting the escape key on desktop.
|
||||
|
||||
### Creating
|
||||
|
||||
An action sheet can be created by the [Action Sheet Controller](../action-sheet-controller) from an array of `buttons`, with each button including properties for its `text`, and optionally a `handler` and `role`. If a handler returns `false` then the action sheet will not be dismissed. An action sheet can also optionally have a `header` and a `subHeader`.
|
||||
|
||||
### Buttons
|
||||
## Buttons
|
||||
|
||||
A button's `role` property can either be `destructive` or `cancel`. Buttons without a role property will have the default look for the platform. Buttons with the `cancel` role will always load as the bottom button, no matter where they are in the array. All other buttons will be displayed in the order they have been added to the `buttons` array. Note: We recommend that `destructive` buttons are always the first button in the array, making them the top button. Additionally, if the action sheet is dismissed by tapping the backdrop, then it will fire the handler from the button with the cancel role.
|
||||
|
||||
## Customization
|
||||
|
||||
Action Sheet uses scoped encapsulation, which means it will automatically scope its CSS by appending each of the styles with an additional class at runtime. Overriding scoped selectors in CSS requires a [higher specificity](https://developer.mozilla.org/en-US/docs/Web/CSS/Specificity) selector.
|
||||
|
||||
We recommend passing a custom class to `cssClass` in the `create` method and using that to add custom styles to the host and inner elements. This property can also accept multiple classes separated by spaces. View the [Usage](#usage) section for an example of how to pass a class using `cssClass`.
|
||||
|
||||
```css
|
||||
/* DOES NOT WORK - not specific enough */
|
||||
.action-sheet-group {
|
||||
background: #e5e5e5;
|
||||
}
|
||||
|
||||
/* Works - pass "my-custom-class" in cssClass to increase specificity */
|
||||
.my-custom-class .action-sheet-group {
|
||||
background: #e5e5e5;
|
||||
}
|
||||
```
|
||||
|
||||
Any of the defined [CSS Custom Properties](#css-custom-properties) can be used to style the Action Sheet without needing to target individual elements:
|
||||
|
||||
```css
|
||||
.my-custom-class {
|
||||
--background: #e5e5e5;
|
||||
}
|
||||
```
|
||||
|
||||
> If you are building an Ionic Angular app, the styles need to be added to a global stylesheet file. Read [Style Placement](#style-placement) in the Angular section below for more information.
|
||||
|
||||
|
||||
<!-- Auto Generated Below -->
|
||||
|
||||
@@ -34,6 +58,7 @@ export class ActionSheetExample {
|
||||
async presentActionSheet() {
|
||||
const actionSheet = await this.actionSheetController.create({
|
||||
header: 'Albums',
|
||||
cssClass: 'my-custom-class',
|
||||
buttons: [{
|
||||
text: 'Delete',
|
||||
role: 'destructive',
|
||||
@@ -49,7 +74,7 @@ export class ActionSheetExample {
|
||||
}
|
||||
}, {
|
||||
text: 'Play (open modal)',
|
||||
icon: 'arrow-dropright-circle',
|
||||
icon: 'caret-forward-circle',
|
||||
handler: () => {
|
||||
console.log('Play clicked');
|
||||
}
|
||||
@@ -75,14 +100,19 @@ export class ActionSheetExample {
|
||||
```
|
||||
|
||||
|
||||
### Style Placement
|
||||
|
||||
In Angular, the CSS of a specific page is scoped only to elements of that page. Even though the Action Sheet can be presented from within a page, the `ion-action-sheet` element is appended outside of the current page. This means that any custom styles need to go in a global stylesheet file. In an Ionic Angular starter this can be the `src/global.scss` file or you can register a new global style file by [adding to the `styles` build option in `angular.json`](https://angular.io/guide/workspace-config#style-script-config).
|
||||
|
||||
|
||||
### Javascript
|
||||
|
||||
```javascript
|
||||
async function presentActionSheet() {
|
||||
|
||||
const actionSheet = document.createElement('ion-action-sheet');
|
||||
|
||||
actionSheet.header = "Albums";
|
||||
actionSheet.header = 'Albums';
|
||||
actionSheet.cssClass = 'my-custom-class';
|
||||
actionSheet.buttons = [{
|
||||
text: 'Delete',
|
||||
role: 'destructive',
|
||||
@@ -98,7 +128,7 @@ async function presentActionSheet() {
|
||||
}
|
||||
}, {
|
||||
text: 'Play (open modal)',
|
||||
icon: 'arrow-dropright-circle',
|
||||
icon: 'caret-forward-circle',
|
||||
handler: () => {
|
||||
console.log('Play clicked');
|
||||
}
|
||||
@@ -124,48 +154,51 @@ async function presentActionSheet() {
|
||||
|
||||
### React
|
||||
|
||||
```typescript
|
||||
import React, { useState } from 'react'
|
||||
```tsx
|
||||
import React, { useState } from 'react';
|
||||
import { IonActionSheet, IonContent, IonButton } from '@ionic/react';
|
||||
import { trash, share, caretForwardCircle, heart, close } from 'ionicons/icons';
|
||||
|
||||
export const ActionSheetExample: React.FC = () => {
|
||||
|
||||
const [showActionSheet, setShowActionSheet] = useState(false);
|
||||
|
||||
return (
|
||||
<IonContent>
|
||||
<IonButton onClick={() => setShowActionSheet(true)} expand="block">Show Action Sheet</IonButton>
|
||||
<IonButton onClick={() => setShowActionSheet(true)} expand="block">
|
||||
Show Action Sheet
|
||||
</IonButton>
|
||||
<IonActionSheet
|
||||
isOpen={showActionSheet}
|
||||
onDidDismiss={() => setShowActionSheet(false)}
|
||||
cssClass='my-custom-class'
|
||||
buttons={[{
|
||||
text: 'Delete',
|
||||
role: 'destructive',
|
||||
icon: 'trash',
|
||||
icon: trash,
|
||||
handler: () => {
|
||||
console.log('Delete clicked');
|
||||
}
|
||||
}, {
|
||||
text: 'Share',
|
||||
icon: 'share',
|
||||
icon: share,
|
||||
handler: () => {
|
||||
console.log('Share clicked');
|
||||
}
|
||||
}, {
|
||||
text: 'Play (open modal)',
|
||||
icon: 'arrow-dropright-circle',
|
||||
icon: caretForwardCircle,
|
||||
handler: () => {
|
||||
console.log('Play clicked');
|
||||
}
|
||||
}, {
|
||||
text: 'Favorite',
|
||||
icon: 'heart',
|
||||
icon: heart,
|
||||
handler: () => {
|
||||
console.log('Favorite clicked');
|
||||
}
|
||||
}, {
|
||||
text: 'Cancel',
|
||||
icon: 'close',
|
||||
icon: close,
|
||||
role: 'cancel',
|
||||
handler: () => {
|
||||
console.log('Cancel clicked');
|
||||
@@ -174,11 +207,72 @@ export const ActionSheetExample: React.FC = () => {
|
||||
>
|
||||
</IonActionSheet>
|
||||
</IonContent>
|
||||
|
||||
);
|
||||
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
### Stencil
|
||||
|
||||
```tsx
|
||||
import { Component, h } from '@stencil/core';
|
||||
|
||||
import { actionSheetController } from '@ionic/core';
|
||||
|
||||
@Component({
|
||||
tag: 'action-sheet-example',
|
||||
styleUrl: 'action-sheet-example.css'
|
||||
})
|
||||
export class ActionSheetExample {
|
||||
async presentActionSheet() {
|
||||
const actionSheet = await actionSheetController.create({
|
||||
header: 'Albums',
|
||||
cssClass: 'my-custom-class',
|
||||
buttons: [{
|
||||
text: 'Delete',
|
||||
role: 'destructive',
|
||||
icon: 'trash',
|
||||
handler: () => {
|
||||
console.log('Delete clicked');
|
||||
}
|
||||
}, {
|
||||
text: 'Share',
|
||||
icon: 'share',
|
||||
handler: () => {
|
||||
console.log('Share clicked');
|
||||
}
|
||||
}, {
|
||||
text: 'Play (open modal)',
|
||||
icon: 'caret-forward-circle',
|
||||
handler: () => {
|
||||
console.log('Play clicked');
|
||||
}
|
||||
}, {
|
||||
text: 'Favorite',
|
||||
icon: 'heart',
|
||||
handler: () => {
|
||||
console.log('Favorite clicked');
|
||||
}
|
||||
}, {
|
||||
text: 'Cancel',
|
||||
icon: 'close',
|
||||
role: 'cancel',
|
||||
handler: () => {
|
||||
console.log('Cancel clicked');
|
||||
}
|
||||
}]
|
||||
});
|
||||
await actionSheet.present();
|
||||
}
|
||||
|
||||
render() {
|
||||
return [
|
||||
<ion-content>
|
||||
<ion-button onClick={() => this.presentActionSheet()}>Present Action Sheet</ion-button>
|
||||
</ion-content>
|
||||
];
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
@@ -198,6 +292,7 @@ export default {
|
||||
return this.$ionic.actionSheetController
|
||||
.create({
|
||||
header: 'Albums',
|
||||
cssClass: 'my-custom-class',
|
||||
buttons: [
|
||||
{
|
||||
text: 'Delete',
|
||||
@@ -216,7 +311,7 @@ export default {
|
||||
},
|
||||
{
|
||||
text: 'Play (open modal)',
|
||||
icon: 'arrow-dropright-circle',
|
||||
icon: 'caret-forward-circle',
|
||||
handler: () => {
|
||||
console.log('Play clicked')
|
||||
},
|
||||
@@ -286,23 +381,23 @@ Type: `Promise<boolean>`
|
||||
|
||||
|
||||
|
||||
### `onDidDismiss() => Promise<OverlayEventDetail<any>>`
|
||||
### `onDidDismiss<T = any>() => Promise<OverlayEventDetail<T>>`
|
||||
|
||||
Returns a promise that resolves when the action sheet did dismiss.
|
||||
|
||||
#### Returns
|
||||
|
||||
Type: `Promise<OverlayEventDetail<any>>`
|
||||
Type: `Promise<OverlayEventDetail<T>>`
|
||||
|
||||
|
||||
|
||||
### `onWillDismiss() => Promise<OverlayEventDetail<any>>`
|
||||
### `onWillDismiss<T = any>() => Promise<OverlayEventDetail<T>>`
|
||||
|
||||
Returns a promise that resolves when the action sheet will dismiss.
|
||||
|
||||
#### Returns
|
||||
|
||||
Type: `Promise<OverlayEventDetail<any>>`
|
||||
Type: `Promise<OverlayEventDetail<T>>`
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -14,6 +14,7 @@ export class ActionSheetExample {
|
||||
async presentActionSheet() {
|
||||
const actionSheet = await this.actionSheetController.create({
|
||||
header: 'Albums',
|
||||
cssClass: 'my-custom-class',
|
||||
buttons: [{
|
||||
text: 'Delete',
|
||||
role: 'destructive',
|
||||
@@ -29,7 +30,7 @@ export class ActionSheetExample {
|
||||
}
|
||||
}, {
|
||||
text: 'Play (open modal)',
|
||||
icon: 'arrow-dropright-circle',
|
||||
icon: 'caret-forward-circle',
|
||||
handler: () => {
|
||||
console.log('Play clicked');
|
||||
}
|
||||
@@ -53,3 +54,8 @@ export class ActionSheetExample {
|
||||
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
### Style Placement
|
||||
|
||||
In Angular, the CSS of a specific page is scoped only to elements of that page. Even though the Action Sheet can be presented from within a page, the `ion-action-sheet` element is appended outside of the current page. This means that any custom styles need to go in a global stylesheet file. In an Ionic Angular starter this can be the `src/global.scss` file or you can register a new global style file by [adding to the `styles` build option in `angular.json`](https://angular.io/guide/workspace-config#style-script-config).
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
```javascript
|
||||
async function presentActionSheet() {
|
||||
|
||||
const actionSheet = document.createElement('ion-action-sheet');
|
||||
|
||||
actionSheet.header = "Albums";
|
||||
actionSheet.header = 'Albums';
|
||||
actionSheet.cssClass = 'my-custom-class';
|
||||
actionSheet.buttons = [{
|
||||
text: 'Delete',
|
||||
role: 'destructive',
|
||||
@@ -19,7 +19,7 @@ async function presentActionSheet() {
|
||||
}
|
||||
}, {
|
||||
text: 'Play (open modal)',
|
||||
icon: 'arrow-dropright-circle',
|
||||
icon: 'caret-forward-circle',
|
||||
handler: () => {
|
||||
console.log('Play clicked');
|
||||
}
|
||||
|
||||
@@ -1,45 +1,48 @@
|
||||
```typescript
|
||||
import React, { useState } from 'react'
|
||||
```tsx
|
||||
import React, { useState } from 'react';
|
||||
import { IonActionSheet, IonContent, IonButton } from '@ionic/react';
|
||||
import { trash, share, caretForwardCircle, heart, close } from 'ionicons/icons';
|
||||
|
||||
export const ActionSheetExample: React.FC = () => {
|
||||
|
||||
const [showActionSheet, setShowActionSheet] = useState(false);
|
||||
|
||||
return (
|
||||
<IonContent>
|
||||
<IonButton onClick={() => setShowActionSheet(true)} expand="block">Show Action Sheet</IonButton>
|
||||
<IonButton onClick={() => setShowActionSheet(true)} expand="block">
|
||||
Show Action Sheet
|
||||
</IonButton>
|
||||
<IonActionSheet
|
||||
isOpen={showActionSheet}
|
||||
onDidDismiss={() => setShowActionSheet(false)}
|
||||
cssClass='my-custom-class'
|
||||
buttons={[{
|
||||
text: 'Delete',
|
||||
role: 'destructive',
|
||||
icon: 'trash',
|
||||
icon: trash,
|
||||
handler: () => {
|
||||
console.log('Delete clicked');
|
||||
}
|
||||
}, {
|
||||
text: 'Share',
|
||||
icon: 'share',
|
||||
icon: share,
|
||||
handler: () => {
|
||||
console.log('Share clicked');
|
||||
}
|
||||
}, {
|
||||
text: 'Play (open modal)',
|
||||
icon: 'arrow-dropright-circle',
|
||||
icon: caretForwardCircle,
|
||||
handler: () => {
|
||||
console.log('Play clicked');
|
||||
}
|
||||
}, {
|
||||
text: 'Favorite',
|
||||
icon: 'heart',
|
||||
icon: heart,
|
||||
handler: () => {
|
||||
console.log('Favorite clicked');
|
||||
}
|
||||
}, {
|
||||
text: 'Cancel',
|
||||
icon: 'close',
|
||||
icon: close,
|
||||
role: 'cancel',
|
||||
handler: () => {
|
||||
console.log('Cancel clicked');
|
||||
@@ -48,9 +51,6 @@ export const ActionSheetExample: React.FC = () => {
|
||||
>
|
||||
</IonActionSheet>
|
||||
</IonContent>
|
||||
|
||||
);
|
||||
|
||||
}
|
||||
|
||||
```
|
||||
|
||||
60
core/src/components/action-sheet/usage/stencil.md
Normal file
60
core/src/components/action-sheet/usage/stencil.md
Normal file
@@ -0,0 +1,60 @@
|
||||
```tsx
|
||||
import { Component, h } from '@stencil/core';
|
||||
|
||||
import { actionSheetController } from '@ionic/core';
|
||||
|
||||
@Component({
|
||||
tag: 'action-sheet-example',
|
||||
styleUrl: 'action-sheet-example.css'
|
||||
})
|
||||
export class ActionSheetExample {
|
||||
async presentActionSheet() {
|
||||
const actionSheet = await actionSheetController.create({
|
||||
header: 'Albums',
|
||||
cssClass: 'my-custom-class',
|
||||
buttons: [{
|
||||
text: 'Delete',
|
||||
role: 'destructive',
|
||||
icon: 'trash',
|
||||
handler: () => {
|
||||
console.log('Delete clicked');
|
||||
}
|
||||
}, {
|
||||
text: 'Share',
|
||||
icon: 'share',
|
||||
handler: () => {
|
||||
console.log('Share clicked');
|
||||
}
|
||||
}, {
|
||||
text: 'Play (open modal)',
|
||||
icon: 'caret-forward-circle',
|
||||
handler: () => {
|
||||
console.log('Play clicked');
|
||||
}
|
||||
}, {
|
||||
text: 'Favorite',
|
||||
icon: 'heart',
|
||||
handler: () => {
|
||||
console.log('Favorite clicked');
|
||||
}
|
||||
}, {
|
||||
text: 'Cancel',
|
||||
icon: 'close',
|
||||
role: 'cancel',
|
||||
handler: () => {
|
||||
console.log('Cancel clicked');
|
||||
}
|
||||
}]
|
||||
});
|
||||
await actionSheet.present();
|
||||
}
|
||||
|
||||
render() {
|
||||
return [
|
||||
<ion-content>
|
||||
<ion-button onClick={() => this.presentActionSheet()}>Present Action Sheet</ion-button>
|
||||
</ion-content>
|
||||
];
|
||||
}
|
||||
}
|
||||
```
|
||||
@@ -12,6 +12,7 @@ export default {
|
||||
return this.$ionic.actionSheetController
|
||||
.create({
|
||||
header: 'Albums',
|
||||
cssClass: 'my-custom-class',
|
||||
buttons: [
|
||||
{
|
||||
text: 'Delete',
|
||||
@@ -30,7 +31,7 @@ export default {
|
||||
},
|
||||
{
|
||||
text: 'Play (open modal)',
|
||||
icon: 'arrow-dropright-circle',
|
||||
icon: 'caret-forward-circle',
|
||||
handler: () => {
|
||||
console.log('Play clicked')
|
||||
},
|
||||
|
||||
@@ -1,9 +1,12 @@
|
||||
import { JSXBase } from '@stencil/core/internal';
|
||||
|
||||
import { AnimationBuilder, Mode, TextFieldTypes } from '../../interface';
|
||||
import { IonicSafeString } from '../../utils/sanitization';
|
||||
|
||||
export interface AlertOptions {
|
||||
header?: string;
|
||||
subHeader?: string;
|
||||
message?: string;
|
||||
message?: string | IonicSafeString;
|
||||
cssClass?: string | string[];
|
||||
inputs?: AlertInput[];
|
||||
buttons?: (AlertButton | string)[];
|
||||
@@ -31,8 +34,13 @@ export interface AlertInput {
|
||||
handler?: (input: AlertInput) => void;
|
||||
min?: string | number;
|
||||
max?: string | number;
|
||||
cssClass?: string | string[];
|
||||
attributes?: AlertInputAttributes | AlertTextareaAttributes;
|
||||
}
|
||||
|
||||
export interface AlertTextareaAttributes extends JSXBase.TextareaHTMLAttributes<HTMLTextAreaElement> {}
|
||||
export interface AlertInputAttributes extends JSXBase.InputHTMLAttributes<HTMLInputElement> {}
|
||||
|
||||
export interface AlertButton {
|
||||
text: string;
|
||||
role?: string;
|
||||
|
||||
@@ -19,6 +19,10 @@
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.alert-button .alert-button-inner {
|
||||
pointer-events: none;
|
||||
}
|
||||
|
||||
|
||||
// iOS Translucent Alert
|
||||
// -----------------------------------------
|
||||
@@ -301,3 +305,12 @@
|
||||
.alert-button.ion-activated {
|
||||
background-color: $alert-ios-button-background-color-activated;
|
||||
}
|
||||
|
||||
// iOS Action Sheet Button: Destructive
|
||||
// ---------------------------------------------------
|
||||
|
||||
.alert-button-role-destructive,
|
||||
.alert-button-role-destructive.ion-activated,
|
||||
.alert-button-role-destructive.ion-focused {
|
||||
color: $alert-ios-button-destructive-text-color;
|
||||
}
|
||||
|
||||
@@ -145,6 +145,9 @@ $alert-ios-button-font-size: 17px !default;
|
||||
/// @prop - Color of the text in the alert button
|
||||
$alert-ios-button-text-color: ion-color(primary, base) !default;
|
||||
|
||||
/// @prop - Destructive text color of the alert button
|
||||
$alert-ios-button-destructive-text-color: ion-color(danger, base) !default;
|
||||
|
||||
/// @prop - Background color of the alert button
|
||||
$alert-ios-button-background-color: transparent !default;
|
||||
|
||||
|
||||
@@ -32,6 +32,8 @@
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
|
||||
outline: none;
|
||||
|
||||
font-family: $font-family-base;
|
||||
|
||||
contain: strict;
|
||||
|
||||
@@ -1,9 +1,11 @@
|
||||
import { Component, ComponentInterface, Element, Event, EventEmitter, Host, Method, Prop, Watch, h } from '@stencil/core';
|
||||
import { Component, ComponentInterface, Element, Event, EventEmitter, Host, Method, Prop, Watch, forceUpdate, h } from '@stencil/core';
|
||||
|
||||
import { getIonMode } from '../../global/ionic-global';
|
||||
import { AlertButton, AlertInput, AnimationBuilder, CssClassMap, OverlayEventDetail, OverlayInterface } from '../../interface';
|
||||
import { AlertButton, AlertInput, AlertInputAttributes, AlertTextareaAttributes, AnimationBuilder, CssClassMap, OverlayEventDetail, OverlayInterface } from '../../interface';
|
||||
import { Gesture } from '../../utils/gesture';
|
||||
import { createButtonActiveGesture } from '../../utils/gesture/button-active';
|
||||
import { BACKDROP, dismiss, eventMethod, isCancel, prepareOverlay, present, safeCall } from '../../utils/overlays';
|
||||
import { sanitizeDOMString } from '../../utils/sanitization';
|
||||
import { IonicSafeString, sanitizeDOMString } from '../../utils/sanitization';
|
||||
import { getClassMap } from '../../utils/theme';
|
||||
|
||||
import { iosEnterAnimation } from './animations/ios.enter';
|
||||
@@ -28,9 +30,10 @@ export class Alert implements ComponentInterface, OverlayInterface {
|
||||
private inputType?: string;
|
||||
private processedInputs: AlertInput[] = [];
|
||||
private processedButtons: AlertButton[] = [];
|
||||
private wrapperEl?: HTMLElement;
|
||||
private gesture?: Gesture;
|
||||
|
||||
presented = false;
|
||||
mode = getIonMode(this);
|
||||
|
||||
@Element() el!: HTMLIonAlertElement;
|
||||
|
||||
@@ -77,7 +80,7 @@ export class Alert implements ComponentInterface, OverlayInterface {
|
||||
*
|
||||
* For more information: [Security Documentation](https://ionicframework.com/docs/faq/security)
|
||||
*/
|
||||
@Prop() message?: string;
|
||||
@Prop() message?: string | IonicSafeString;
|
||||
|
||||
/**
|
||||
* Array of buttons to be added to the alert.
|
||||
@@ -158,7 +161,9 @@ export class Alert implements ComponentInterface, OverlayInterface {
|
||||
id: i.id || `alert-input-${this.overlayIndex}-${index}`,
|
||||
handler: i.handler,
|
||||
min: i.min,
|
||||
max: i.max
|
||||
max: i.max,
|
||||
cssClass: i.cssClass || '',
|
||||
attributes: i.attributes || {},
|
||||
}) as AlertInput);
|
||||
}
|
||||
|
||||
@@ -171,6 +176,29 @@ export class Alert implements ComponentInterface, OverlayInterface {
|
||||
this.buttonsChanged();
|
||||
}
|
||||
|
||||
componentDidUnload() {
|
||||
if (this.gesture) {
|
||||
this.gesture.destroy();
|
||||
this.gesture = undefined;
|
||||
}
|
||||
}
|
||||
|
||||
componentDidLoad() {
|
||||
/**
|
||||
* Do not create gesture if:
|
||||
* 1. A gesture already exists
|
||||
* 2. App is running in MD mode
|
||||
* 3. A wrapper ref does not exist
|
||||
*/
|
||||
if (this.gesture || getIonMode(this) === 'md' || !this.wrapperEl) { return; }
|
||||
|
||||
this.gesture = createButtonActiveGesture(
|
||||
this.wrapperEl,
|
||||
(refEl: HTMLElement) => refEl.classList.contains('alert-button')
|
||||
);
|
||||
this.gesture.enable(true);
|
||||
}
|
||||
|
||||
/**
|
||||
* Present the alert overlay after it has been created.
|
||||
*/
|
||||
@@ -197,7 +225,7 @@ export class Alert implements ComponentInterface, OverlayInterface {
|
||||
* Returns a promise that resolves when the alert did dismiss.
|
||||
*/
|
||||
@Method()
|
||||
onDidDismiss(): Promise<OverlayEventDetail> {
|
||||
onDidDismiss<T = any>(): Promise<OverlayEventDetail<T>> {
|
||||
return eventMethod(this.el, 'ionAlertDidDismiss');
|
||||
}
|
||||
|
||||
@@ -205,7 +233,7 @@ export class Alert implements ComponentInterface, OverlayInterface {
|
||||
* Returns a promise that resolves when the alert will dismiss.
|
||||
*/
|
||||
@Method()
|
||||
onWillDismiss(): Promise<OverlayEventDetail> {
|
||||
onWillDismiss<T = any>(): Promise<OverlayEventDetail<T>> {
|
||||
return eventMethod(this.el, 'ionAlertWillDismiss');
|
||||
}
|
||||
|
||||
@@ -215,13 +243,13 @@ export class Alert implements ComponentInterface, OverlayInterface {
|
||||
}
|
||||
this.activeId = selectedInput.id;
|
||||
safeCall(selectedInput.handler, selectedInput);
|
||||
this.el.forceUpdate();
|
||||
forceUpdate(this);
|
||||
}
|
||||
|
||||
private cbClick(selectedInput: AlertInput) {
|
||||
selectedInput.checked = !selectedInput.checked;
|
||||
safeCall(selectedInput.handler, selectedInput);
|
||||
this.el.forceUpdate();
|
||||
forceUpdate(this);
|
||||
}
|
||||
|
||||
private buttonClick(button: AlertButton) {
|
||||
@@ -307,6 +335,7 @@ export class Alert implements ComponentInterface, OverlayInterface {
|
||||
tabIndex={0}
|
||||
role="checkbox"
|
||||
class={{
|
||||
...getClassMap(i.cssClass),
|
||||
'alert-tappable': true,
|
||||
'alert-checkbox': true,
|
||||
'alert-checkbox-button': true,
|
||||
@@ -345,6 +374,7 @@ export class Alert implements ComponentInterface, OverlayInterface {
|
||||
id={i.id}
|
||||
tabIndex={0}
|
||||
class={{
|
||||
...getClassMap(i.cssClass),
|
||||
'alert-radio-button': true,
|
||||
'alert-tappable': true,
|
||||
'alert-radio': true,
|
||||
@@ -379,13 +409,14 @@ export class Alert implements ComponentInterface, OverlayInterface {
|
||||
<textarea
|
||||
placeholder={i.placeholder}
|
||||
value={i.value}
|
||||
onInput={e => i.value = (e.target as any).value}
|
||||
id={i.id}
|
||||
disabled={i.disabled}
|
||||
tabIndex={0}
|
||||
class={{
|
||||
'alert-input': true,
|
||||
'alert-input-disabled': i.disabled || false
|
||||
{...i.attributes as AlertTextareaAttributes}
|
||||
disabled={i.attributes?.disabled ?? i.disabled}
|
||||
class={inputClass(i)}
|
||||
onInput={e => {
|
||||
i.value = (e.target as any).value;
|
||||
if (i.attributes?.onInput) { i.attributes.onInput(e); }
|
||||
}}
|
||||
/>
|
||||
</div>
|
||||
@@ -395,17 +426,18 @@ export class Alert implements ComponentInterface, OverlayInterface {
|
||||
<div class="alert-input-wrapper">
|
||||
<input
|
||||
placeholder={i.placeholder}
|
||||
value={i.value}
|
||||
type={i.type}
|
||||
min={i.min}
|
||||
max={i.max}
|
||||
onInput={e => i.value = (e.target as any).value}
|
||||
value={i.value}
|
||||
id={i.id}
|
||||
disabled={i.disabled}
|
||||
tabIndex={0}
|
||||
class={{
|
||||
'alert-input': true,
|
||||
'alert-input-disabled': i.disabled || false
|
||||
{...i.attributes as AlertInputAttributes}
|
||||
disabled={i.attributes?.disabled ?? i.disabled}
|
||||
class={inputClass(i)}
|
||||
onInput={e => {
|
||||
i.value = (e.target as any).value;
|
||||
if (i.attributes?.onInput) { i.attributes.onInput(e); }
|
||||
}}
|
||||
/>
|
||||
</div>
|
||||
@@ -467,6 +499,7 @@ export class Alert implements ComponentInterface, OverlayInterface {
|
||||
<Host
|
||||
role="dialog"
|
||||
aria-modal="true"
|
||||
tabindex="-1"
|
||||
style={{
|
||||
zIndex: `${20000 + overlayIndex}`,
|
||||
}}
|
||||
@@ -481,7 +514,7 @@ export class Alert implements ComponentInterface, OverlayInterface {
|
||||
|
||||
<ion-backdrop tappable={this.backdropDismiss}/>
|
||||
|
||||
<div class="alert-wrapper">
|
||||
<div class="alert-wrapper ion-wrapper" ref={el => this.wrapperEl = el}>
|
||||
|
||||
<div class="alert-head">
|
||||
{header && <h2 id={hdrId} class="alert-title">{header}</h2>}
|
||||
@@ -499,11 +532,21 @@ export class Alert implements ComponentInterface, OverlayInterface {
|
||||
}
|
||||
}
|
||||
|
||||
const inputClass = (input: AlertInput): CssClassMap => {
|
||||
return {
|
||||
'alert-input': true,
|
||||
'alert-input-disabled': (input.attributes?.disabled ?? input.disabled) || false,
|
||||
...getClassMap(input.cssClass),
|
||||
...getClassMap(input.attributes ? input.attributes.class?.toString() : ''),
|
||||
};
|
||||
};
|
||||
|
||||
const buttonClass = (button: AlertButton): CssClassMap => {
|
||||
return {
|
||||
'alert-button': true,
|
||||
'ion-focusable': true,
|
||||
'ion-activatable': true,
|
||||
[`alert-button-role-${button.role}`]: button.role !== undefined,
|
||||
...getClassMap(button.cssClass)
|
||||
};
|
||||
};
|
||||
|
||||
@@ -11,7 +11,11 @@ export const iosEnterAnimation = (baseEl: HTMLElement): Animation => {
|
||||
|
||||
backdropAnimation
|
||||
.addElement(baseEl.querySelector('ion-backdrop')!)
|
||||
.fromTo('opacity', 0.01, 'var(--backdrop-opacity)');
|
||||
.fromTo('opacity', 0.01, 'var(--backdrop-opacity)')
|
||||
.beforeStyles({
|
||||
'pointer-events': 'none'
|
||||
})
|
||||
.afterClearStyles(['pointer-events']);
|
||||
|
||||
wrapperAnimation
|
||||
.addElement(baseEl.querySelector('.alert-wrapper')!)
|
||||
|
||||
@@ -11,7 +11,11 @@ export const mdEnterAnimation = (baseEl: HTMLElement): Animation => {
|
||||
|
||||
backdropAnimation
|
||||
.addElement(baseEl.querySelector('ion-backdrop')!)
|
||||
.fromTo('opacity', 0.01, 'var(--backdrop-opacity)');
|
||||
.fromTo('opacity', 0.01, 'var(--backdrop-opacity)')
|
||||
.beforeStyles({
|
||||
'pointer-events': 'none'
|
||||
})
|
||||
.afterClearStyles(['pointer-events']);
|
||||
|
||||
wrapperAnimation
|
||||
.addElement(baseEl.querySelector('.alert-wrapper')!)
|
||||
|
||||
@@ -2,23 +2,45 @@
|
||||
|
||||
An Alert is a dialog that presents users with information or collects information from the user using inputs. An alert appears on top of the app's content, and must be manually dismissed by the user before they can resume interaction with the app. It can also optionally have a `header`, `subHeader` and `message`.
|
||||
|
||||
|
||||
### Creating
|
||||
|
||||
Alerts can be created using an [Alert Controller](../alert-controller). They can be customized by passing alert options in the alert controller's create method.
|
||||
|
||||
|
||||
### Buttons
|
||||
## Buttons
|
||||
|
||||
In the array of `buttons`, each button includes properties for its `text`, and optionally a `handler`. If a handler returns `false` then the alert will not automatically be dismissed when the button is clicked. All buttons will show up in the order they have been added to the `buttons` array from left to right. Note: The right most button (the last one in the array) is the main button.
|
||||
|
||||
Optionally, a `role` property can be added to a button, such as `cancel`. If a `cancel` role is on one of the buttons, then if the alert is dismissed by tapping the backdrop, then it will fire the handler from the button with a cancel role.
|
||||
|
||||
|
||||
### Inputs
|
||||
## Inputs
|
||||
|
||||
Alerts can also include several different inputs whose data can be passed back to the app. Inputs can be used as a simple way to prompt users for information. Radios, checkboxes and text inputs are all accepted, but they cannot be mixed. For example, an alert could have all radio button inputs, or all checkbox inputs, but the same alert cannot mix radio and checkbox inputs. Do note however, different types of "text" inputs can be mixed, such as `url`, `email`, `text`, `textarea` etc. If you require a complex form UI which doesn't fit within the guidelines of an alert then we recommend building the form within a modal instead.
|
||||
|
||||
## Customization
|
||||
|
||||
Alert uses scoped encapsulation, which means it will automatically scope its CSS by appending each of the styles with an additional class at runtime. Overriding scoped selectors in CSS requires a [higher specificity](https://developer.mozilla.org/en-US/docs/Web/CSS/Specificity) selector.
|
||||
|
||||
We recommend passing a custom class to `cssClass` in the `create` method and using that to add custom styles to the host and inner elements. This property can also accept multiple classes separated by spaces. View the [Usage](#usage) section for an example of how to pass a class using `cssClass`.
|
||||
|
||||
```css
|
||||
/* DOES NOT WORK - not specific enough */
|
||||
.alert-wrapper {
|
||||
background: #e5e5e5;
|
||||
}
|
||||
|
||||
/* Works - pass "my-custom-class" in cssClass to increase specificity */
|
||||
.my-custom-class .alert-wrapper {
|
||||
background: #e5e5e5;
|
||||
}
|
||||
```
|
||||
|
||||
Any of the defined [CSS Custom Properties](#css-custom-properties) can be used to style the Alert without needing to target individual elements:
|
||||
|
||||
```css
|
||||
.my-custom-class {
|
||||
--background: #e5e5e5;
|
||||
}
|
||||
```
|
||||
|
||||
> If you are building an Ionic Angular app, the styles need to be added to a global stylesheet file. Read [Style Placement](#style-placement) in the Angular section below for more information.
|
||||
|
||||
|
||||
<!-- Auto Generated Below -->
|
||||
|
||||
@@ -42,6 +64,7 @@ export class AlertExample {
|
||||
|
||||
async presentAlert() {
|
||||
const alert = await this.alertController.create({
|
||||
cssClass: 'my-custom-class',
|
||||
header: 'Alert',
|
||||
subHeader: 'Subtitle',
|
||||
message: 'This is an alert message.',
|
||||
@@ -53,6 +76,7 @@ export class AlertExample {
|
||||
|
||||
async presentAlertMultipleButtons() {
|
||||
const alert = await this.alertController.create({
|
||||
cssClass: 'my-custom-class',
|
||||
header: 'Alert',
|
||||
subHeader: 'Subtitle',
|
||||
message: 'This is an alert message.',
|
||||
@@ -64,6 +88,7 @@ export class AlertExample {
|
||||
|
||||
async presentAlertConfirm() {
|
||||
const alert = await this.alertController.create({
|
||||
cssClass: 'my-custom-class',
|
||||
header: 'Confirm!',
|
||||
message: 'Message <strong>text</strong>!!!',
|
||||
buttons: [
|
||||
@@ -88,6 +113,7 @@ export class AlertExample {
|
||||
|
||||
async presentAlertPrompt() {
|
||||
const alert = await this.alertController.create({
|
||||
cssClass: 'my-custom-class',
|
||||
header: 'Prompt!',
|
||||
inputs: [
|
||||
{
|
||||
@@ -136,6 +162,16 @@ export class AlertExample {
|
||||
{
|
||||
name: 'name7',
|
||||
type: 'number'
|
||||
},
|
||||
{
|
||||
name: 'name8',
|
||||
type: 'password',
|
||||
placeholder: 'Advanced Attributes',
|
||||
cssClass: 'specialClass',
|
||||
attributes: {
|
||||
maxlength: 4,
|
||||
inputmode: 'decimal'
|
||||
}
|
||||
}
|
||||
],
|
||||
buttons: [
|
||||
@@ -160,6 +196,7 @@ export class AlertExample {
|
||||
|
||||
async presentAlertRadio() {
|
||||
const alert = await this.alertController.create({
|
||||
cssClass: 'my-custom-class',
|
||||
header: 'Radio',
|
||||
inputs: [
|
||||
{
|
||||
@@ -222,6 +259,7 @@ export class AlertExample {
|
||||
|
||||
async presentAlertCheckbox() {
|
||||
const alert = await this.alertController.create({
|
||||
cssClass: 'my-custom-class',
|
||||
header: 'Checkbox',
|
||||
inputs: [
|
||||
{
|
||||
@@ -286,16 +324,21 @@ export class AlertExample {
|
||||
|
||||
await alert.present();
|
||||
}
|
||||
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
### Style Placement
|
||||
|
||||
In Angular, the CSS of a specific page is scoped only to elements of that page. Even though the Alert can be presented from within a page, the `ion-alert` element is appended outside of the current page. This means that any custom styles need to go in a global stylesheet file. In an Ionic Angular starter this can be the `src/global.scss` file or you can register a new global style file by [adding to the `styles` build option in `angular.json`](https://angular.io/guide/workspace-config#style-script-config).
|
||||
|
||||
|
||||
### Javascript
|
||||
|
||||
```javascript
|
||||
function presentAlert() {
|
||||
const alert = document.createElement('ion-alert');
|
||||
alert.cssClass = 'my-custom-class';
|
||||
alert.header = 'Alert';
|
||||
alert.subHeader = 'Subtitle';
|
||||
alert.message = 'This is an alert message.';
|
||||
@@ -307,6 +350,7 @@ function presentAlert() {
|
||||
|
||||
function presentAlertMultipleButtons() {
|
||||
const alert = document.createElement('ion-alert');
|
||||
alert.cssClass = 'my-custom-class';
|
||||
alert.header = 'Alert';
|
||||
alert.subHeader = 'Subtitle';
|
||||
alert.message = 'This is an alert message.';
|
||||
@@ -318,6 +362,7 @@ function presentAlertMultipleButtons() {
|
||||
|
||||
function presentAlertConfirm() {
|
||||
const alert = document.createElement('ion-alert');
|
||||
alert.cssClass = 'my-custom-class';
|
||||
alert.header = 'Confirm!';
|
||||
alert.message = 'Message <strong>text</strong>!!!';
|
||||
alert.buttons = [
|
||||
@@ -342,6 +387,7 @@ function presentAlertConfirm() {
|
||||
|
||||
function presentAlertPrompt() {
|
||||
const alert = document.createElement('ion-alert');
|
||||
alert.cssClass = 'my-custom-class';
|
||||
alert.header = 'Prompt!';
|
||||
alert.inputs = [
|
||||
{
|
||||
@@ -387,6 +433,16 @@ function presentAlertPrompt() {
|
||||
{
|
||||
name: 'name7',
|
||||
type: 'number'
|
||||
},
|
||||
{
|
||||
name: 'name8',
|
||||
type: 'password',
|
||||
placeholder: 'Advanced Attributes',
|
||||
cssClass: 'specialClass',
|
||||
attributes: {
|
||||
maxlength: 4,
|
||||
inputmode: 'decimal'
|
||||
}
|
||||
}
|
||||
];
|
||||
alert.buttons = [
|
||||
@@ -411,6 +467,7 @@ function presentAlertPrompt() {
|
||||
|
||||
function presentAlertRadio() {
|
||||
const alert = document.createElement('ion-alert');
|
||||
alert.cssClass = 'my-custom-class';
|
||||
alert.header = 'Radio';
|
||||
alert.inputs = [
|
||||
{
|
||||
@@ -466,6 +523,7 @@ function presentAlertRadio() {
|
||||
|
||||
function presentAlertCheckbox() {
|
||||
const alert = document.createElement('ion-alert');
|
||||
alert.cssClass = 'my-custom-class';
|
||||
alert.header = 'Checkbox';
|
||||
alert.inputs = [
|
||||
{
|
||||
@@ -553,6 +611,7 @@ export const AlertExample: React.FC = () => {
|
||||
<IonAlert
|
||||
isOpen={showAlert1}
|
||||
onDidDismiss={() => setShowAlert1(false)}
|
||||
cssClass='my-custom-class'
|
||||
header={'Alert'}
|
||||
subHeader={'Subtitle'}
|
||||
message={'This is an alert message.'}
|
||||
@@ -562,6 +621,7 @@ export const AlertExample: React.FC = () => {
|
||||
<IonAlert
|
||||
isOpen={showAlert2}
|
||||
onDidDismiss={() => setShowAlert2(false)}
|
||||
cssClass='my-custom-class'
|
||||
header={'Alert'}
|
||||
subHeader={'Subtitle'}
|
||||
message={'This is an alert message.'}
|
||||
@@ -571,6 +631,7 @@ export const AlertExample: React.FC = () => {
|
||||
<IonAlert
|
||||
isOpen={showAlert3}
|
||||
onDidDismiss={() => setShowAlert3(false)}
|
||||
cssClass='my-custom-class'
|
||||
header={'Confirm!'}
|
||||
message={'Message <strong>text</strong>!!!'}
|
||||
buttons={[
|
||||
@@ -594,6 +655,7 @@ export const AlertExample: React.FC = () => {
|
||||
<IonAlert
|
||||
isOpen={showAlert4}
|
||||
onDidDismiss={() => setShowAlert4(false)}
|
||||
cssClass='my-custom-class'
|
||||
header={'Prompt!'}
|
||||
inputs={[
|
||||
{
|
||||
@@ -635,6 +697,16 @@ export const AlertExample: React.FC = () => {
|
||||
{
|
||||
name: 'name7',
|
||||
type: 'number'
|
||||
},
|
||||
{
|
||||
name: 'name8',
|
||||
type: 'password',
|
||||
placeholder: 'Advanced Attributes',
|
||||
cssClass: 'specialClass',
|
||||
attributes: {
|
||||
maxlength: 4,
|
||||
inputmode: 'decimal'
|
||||
}
|
||||
}
|
||||
]}
|
||||
buttons={[
|
||||
@@ -658,6 +730,7 @@ export const AlertExample: React.FC = () => {
|
||||
<IonAlert
|
||||
isOpen={showAlert5}
|
||||
onDidDismiss={() => setShowAlert5(false)}
|
||||
cssClass='my-custom-class'
|
||||
header={'Radio'}
|
||||
inputs={[
|
||||
{
|
||||
@@ -719,6 +792,7 @@ export const AlertExample: React.FC = () => {
|
||||
<IonAlert
|
||||
isOpen={showAlert6}
|
||||
onDidDismiss={() => setShowAlert6(false)}
|
||||
cssClass='my-custom-class'
|
||||
header={'Checkbox'}
|
||||
inputs={[
|
||||
{
|
||||
@@ -785,6 +859,298 @@ export default AlertExample;
|
||||
```
|
||||
|
||||
|
||||
### Stencil
|
||||
|
||||
```tsx
|
||||
import { Component, h } from '@stencil/core';
|
||||
|
||||
import { alertController } from '@ionic/core';
|
||||
|
||||
@Component({
|
||||
tag: 'alert-example',
|
||||
styleUrl: 'alert-example.css'
|
||||
})
|
||||
export class AlertExample {
|
||||
async presentAlert() {
|
||||
const alert = await alertController.create({
|
||||
cssClass: 'my-custom-class',
|
||||
header: 'Alert',
|
||||
subHeader: 'Subtitle',
|
||||
message: 'This is an alert message.',
|
||||
buttons: ['OK']
|
||||
});
|
||||
|
||||
await alert.present();
|
||||
}
|
||||
|
||||
async presentAlertMultipleButtons() {
|
||||
const alert = await alertController.create({
|
||||
cssClass: 'my-custom-class',
|
||||
header: 'Alert',
|
||||
subHeader: 'Subtitle',
|
||||
message: 'This is an alert message.',
|
||||
buttons: ['Cancel', 'Open Modal', 'Delete']
|
||||
});
|
||||
|
||||
await alert.present();
|
||||
}
|
||||
|
||||
async presentAlertConfirm() {
|
||||
const alert = await alertController.create({
|
||||
cssClass: 'my-custom-class',
|
||||
header: 'Confirm!',
|
||||
message: 'Message <strong>text</strong>!!!',
|
||||
buttons: [
|
||||
{
|
||||
text: 'Cancel',
|
||||
role: 'cancel',
|
||||
cssClass: 'secondary',
|
||||
handler: (blah) => {
|
||||
console.log('Confirm Cancel: blah');
|
||||
}
|
||||
}, {
|
||||
text: 'Okay',
|
||||
handler: () => {
|
||||
console.log('Confirm Okay');
|
||||
}
|
||||
}
|
||||
]
|
||||
});
|
||||
|
||||
await alert.present();
|
||||
}
|
||||
|
||||
async presentAlertPrompt() {
|
||||
const alert = await alertController.create({
|
||||
cssClass: 'my-custom-class',
|
||||
header: 'Prompt!',
|
||||
inputs: [
|
||||
{
|
||||
name: 'name1',
|
||||
type: 'text',
|
||||
placeholder: 'Placeholder 1'
|
||||
},
|
||||
{
|
||||
name: 'name2',
|
||||
type: 'text',
|
||||
id: 'name2-id',
|
||||
value: 'hello',
|
||||
placeholder: 'Placeholder 2'
|
||||
},
|
||||
// multiline input.
|
||||
{
|
||||
name: 'paragraph',
|
||||
id: 'paragraph',
|
||||
type: 'textarea',
|
||||
placeholder: 'Placeholder 3'
|
||||
},
|
||||
{
|
||||
name: 'name3',
|
||||
value: 'http://ionicframework.com',
|
||||
type: 'url',
|
||||
placeholder: 'Favorite site ever'
|
||||
},
|
||||
// input date with min & max
|
||||
{
|
||||
name: 'name4',
|
||||
type: 'date',
|
||||
min: '2017-03-01',
|
||||
max: '2018-01-12'
|
||||
},
|
||||
// input date without min nor max
|
||||
{
|
||||
name: 'name5',
|
||||
type: 'date'
|
||||
},
|
||||
{
|
||||
name: 'name6',
|
||||
type: 'number',
|
||||
min: -5,
|
||||
max: 10
|
||||
},
|
||||
{
|
||||
name: 'name7',
|
||||
type: 'number'
|
||||
},
|
||||
{
|
||||
name: 'name8',
|
||||
type: 'password',
|
||||
placeholder: 'Advanced Attributes',
|
||||
cssClass: 'specialClass',
|
||||
attributes: {
|
||||
maxlength: 4,
|
||||
inputmode: 'decimal'
|
||||
}
|
||||
}
|
||||
],
|
||||
buttons: [
|
||||
{
|
||||
text: 'Cancel',
|
||||
role: 'cancel',
|
||||
cssClass: 'secondary',
|
||||
handler: () => {
|
||||
console.log('Confirm Cancel');
|
||||
}
|
||||
}, {
|
||||
text: 'Ok',
|
||||
handler: () => {
|
||||
console.log('Confirm Ok');
|
||||
}
|
||||
}
|
||||
]
|
||||
});
|
||||
|
||||
await alert.present();
|
||||
}
|
||||
|
||||
async presentAlertRadio() {
|
||||
const alert = await alertController.create({
|
||||
cssClass: 'my-custom-class',
|
||||
header: 'Radio',
|
||||
inputs: [
|
||||
{
|
||||
name: 'radio1',
|
||||
type: 'radio',
|
||||
label: 'Radio 1',
|
||||
value: 'value1',
|
||||
checked: true
|
||||
},
|
||||
{
|
||||
name: 'radio2',
|
||||
type: 'radio',
|
||||
label: 'Radio 2',
|
||||
value: 'value2'
|
||||
},
|
||||
{
|
||||
name: 'radio3',
|
||||
type: 'radio',
|
||||
label: 'Radio 3',
|
||||
value: 'value3'
|
||||
},
|
||||
{
|
||||
name: 'radio4',
|
||||
type: 'radio',
|
||||
label: 'Radio 4',
|
||||
value: 'value4'
|
||||
},
|
||||
{
|
||||
name: 'radio5',
|
||||
type: 'radio',
|
||||
label: 'Radio 5',
|
||||
value: 'value5'
|
||||
},
|
||||
{
|
||||
name: 'radio6',
|
||||
type: 'radio',
|
||||
label: 'Radio 6 Radio 6 Radio 6 Radio 6 Radio 6 Radio 6 Radio 6 Radio 6 Radio 6 Radio 6 ',
|
||||
value: 'value6'
|
||||
}
|
||||
],
|
||||
buttons: [
|
||||
{
|
||||
text: 'Cancel',
|
||||
role: 'cancel',
|
||||
cssClass: 'secondary',
|
||||
handler: () => {
|
||||
console.log('Confirm Cancel');
|
||||
}
|
||||
}, {
|
||||
text: 'Ok',
|
||||
handler: () => {
|
||||
console.log('Confirm Ok');
|
||||
}
|
||||
}
|
||||
]
|
||||
});
|
||||
|
||||
await alert.present();
|
||||
}
|
||||
|
||||
async presentAlertCheckbox() {
|
||||
const alert = await alertController.create({
|
||||
cssClass: 'my-custom-class',
|
||||
header: 'Checkbox',
|
||||
inputs: [
|
||||
{
|
||||
name: 'checkbox1',
|
||||
type: 'checkbox',
|
||||
label: 'Checkbox 1',
|
||||
value: 'value1',
|
||||
checked: true
|
||||
},
|
||||
|
||||
{
|
||||
name: 'checkbox2',
|
||||
type: 'checkbox',
|
||||
label: 'Checkbox 2',
|
||||
value: 'value2'
|
||||
},
|
||||
|
||||
{
|
||||
name: 'checkbox3',
|
||||
type: 'checkbox',
|
||||
label: 'Checkbox 3',
|
||||
value: 'value3'
|
||||
},
|
||||
|
||||
{
|
||||
name: 'checkbox4',
|
||||
type: 'checkbox',
|
||||
label: 'Checkbox 4',
|
||||
value: 'value4'
|
||||
},
|
||||
|
||||
{
|
||||
name: 'checkbox5',
|
||||
type: 'checkbox',
|
||||
label: 'Checkbox 5',
|
||||
value: 'value5'
|
||||
},
|
||||
|
||||
{
|
||||
name: 'checkbox6',
|
||||
type: 'checkbox',
|
||||
label: 'Checkbox 6 Checkbox 6 Checkbox 6 Checkbox 6 Checkbox 6 Checkbox 6 Checkbox 6 Checkbox 6 Checkbox 6 Checkbox 6',
|
||||
value: 'value6'
|
||||
}
|
||||
],
|
||||
buttons: [
|
||||
{
|
||||
text: 'Cancel',
|
||||
role: 'cancel',
|
||||
cssClass: 'secondary',
|
||||
handler: () => {
|
||||
console.log('Confirm Cancel');
|
||||
}
|
||||
}, {
|
||||
text: 'Ok',
|
||||
handler: () => {
|
||||
console.log('Confirm Ok');
|
||||
}
|
||||
}
|
||||
]
|
||||
});
|
||||
|
||||
await alert.present();
|
||||
}
|
||||
|
||||
|
||||
render() {
|
||||
return [
|
||||
<ion-content>
|
||||
<ion-button onClick={() => this.presentAlert()}>Present Alert</ion-button>
|
||||
<ion-button onClick={() => this.presentAlertMultipleButtons()}>Present Alert: Multiple Buttons</ion-button>
|
||||
<ion-button onClick={() => this.presentAlertConfirm()}>Present Alert: Confirm</ion-button>
|
||||
<ion-button onClick={() => this.presentAlertPrompt()}>Present Alert: Prompt</ion-button>
|
||||
<ion-button onClick={() => this.presentAlertRadio()}>Present Alert: Radio</ion-button>
|
||||
<ion-button onClick={() => this.presentAlertCheckbox()}>Present Alert: Checkbox</ion-button>
|
||||
</ion-content>
|
||||
];
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
### Vue
|
||||
|
||||
```html
|
||||
@@ -805,6 +1171,7 @@ export default {
|
||||
presentAlert() {
|
||||
return this.$ionic.alertController
|
||||
.create({
|
||||
cssClass: 'my-custom-class',
|
||||
header: 'Alert',
|
||||
subHeader: 'Subtitle',
|
||||
message: 'This is an alert message.',
|
||||
@@ -816,6 +1183,7 @@ export default {
|
||||
presentAlertMultipleButtons() {
|
||||
return this.$ionic.alertController
|
||||
.create({
|
||||
cssClass: 'my-custom-class',
|
||||
header: 'Alert',
|
||||
subHeader: 'Subtitle',
|
||||
message: 'This is an alert message.',
|
||||
@@ -827,6 +1195,7 @@ export default {
|
||||
presentAlertConfirm() {
|
||||
return this.$ionic.alertController
|
||||
.create({
|
||||
cssClass: 'my-custom-class',
|
||||
header: 'Confirm!',
|
||||
message: 'Message <strong>text</strong>!!!',
|
||||
buttons: [
|
||||
@@ -852,6 +1221,7 @@ export default {
|
||||
presentAlertPrompt() {
|
||||
return this.$ionic.alertController
|
||||
.create({
|
||||
cssClass: 'my-custom-class',
|
||||
header: 'Prompt!',
|
||||
inputs: [
|
||||
{
|
||||
@@ -891,6 +1261,16 @@ export default {
|
||||
name: 'name7',
|
||||
type: 'number',
|
||||
},
|
||||
{
|
||||
name: 'name8',
|
||||
type: 'password',
|
||||
placeholder: 'Advanced Attributes',
|
||||
cssClass: 'specialClass',
|
||||
attributes: {
|
||||
maxlength: 4,
|
||||
inputmode: 'decimal'
|
||||
}
|
||||
}
|
||||
],
|
||||
buttons: [
|
||||
{
|
||||
@@ -915,6 +1295,7 @@ export default {
|
||||
presentAlertRadio() {
|
||||
return this.$ionic.alertController
|
||||
.create({
|
||||
cssClass: 'my-custom-class',
|
||||
header: 'Radio',
|
||||
inputs: [
|
||||
{
|
||||
@@ -972,6 +1353,7 @@ export default {
|
||||
presentAlertCheckbox() {
|
||||
return this.$ionic.alertController
|
||||
.create({
|
||||
cssClass: 'my-custom-class',
|
||||
header: 'Checkbox',
|
||||
inputs: [
|
||||
{
|
||||
@@ -1050,7 +1432,7 @@ export default {
|
||||
| `inputs` | -- | Array of input to show in the alert. | `AlertInput[]` | `[]` |
|
||||
| `keyboardClose` | `keyboard-close` | If `true`, the keyboard will be automatically dismissed when the overlay is presented. | `boolean` | `true` |
|
||||
| `leaveAnimation` | -- | Animation to use when the alert is dismissed. | `((baseEl: any, opts?: any) => Animation) \| undefined` | `undefined` |
|
||||
| `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` |
|
||||
| `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) | `IonicSafeString \| 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. Only applies when the mode is `"ios"` and the device supports [`backdrop-filter`](https://developer.mozilla.org/en-US/docs/Web/CSS/backdrop-filter#Browser_compatibility). | `boolean` | `false` |
|
||||
@@ -1078,23 +1460,23 @@ Type: `Promise<boolean>`
|
||||
|
||||
|
||||
|
||||
### `onDidDismiss() => Promise<OverlayEventDetail<any>>`
|
||||
### `onDidDismiss<T = any>() => Promise<OverlayEventDetail<T>>`
|
||||
|
||||
Returns a promise that resolves when the alert did dismiss.
|
||||
|
||||
#### Returns
|
||||
|
||||
Type: `Promise<OverlayEventDetail<any>>`
|
||||
Type: `Promise<OverlayEventDetail<T>>`
|
||||
|
||||
|
||||
|
||||
### `onWillDismiss() => Promise<OverlayEventDetail<any>>`
|
||||
### `onWillDismiss<T = any>() => Promise<OverlayEventDetail<T>>`
|
||||
|
||||
Returns a promise that resolves when the alert will dismiss.
|
||||
|
||||
#### Returns
|
||||
|
||||
Type: `Promise<OverlayEventDetail<any>>`
|
||||
Type: `Promise<OverlayEventDetail<T>>`
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -14,7 +14,7 @@
|
||||
import { alertController } from '../../../../dist/ionic/index.esm.js';
|
||||
window.alertController = alertController;
|
||||
</script>
|
||||
|
||||
|
||||
<body>
|
||||
<ion-app>
|
||||
|
||||
@@ -75,7 +75,14 @@
|
||||
header: 'Alert',
|
||||
subHeader: 'Subtitle',
|
||||
message: 'This is an alert message.',
|
||||
buttons: ['Cancel', 'Open Modal', 'Delete']
|
||||
buttons: [
|
||||
'Open Modal',
|
||||
{
|
||||
text: 'Delete',
|
||||
role: 'destructive',
|
||||
},
|
||||
'Cancel',
|
||||
]
|
||||
});
|
||||
}
|
||||
|
||||
@@ -161,6 +168,16 @@
|
||||
{
|
||||
name: 'name7',
|
||||
type: 'number'
|
||||
},
|
||||
{
|
||||
name: 'name8',
|
||||
type: 'text',
|
||||
placeholder: 'Advanced Attributes',
|
||||
cssClass: 'specialClass',
|
||||
attributes: {
|
||||
maxlength: 4,
|
||||
inputmode: 'decimal'
|
||||
}
|
||||
}
|
||||
],
|
||||
buttons: [
|
||||
|
||||
@@ -13,6 +13,7 @@ export class AlertExample {
|
||||
|
||||
async presentAlert() {
|
||||
const alert = await this.alertController.create({
|
||||
cssClass: 'my-custom-class',
|
||||
header: 'Alert',
|
||||
subHeader: 'Subtitle',
|
||||
message: 'This is an alert message.',
|
||||
@@ -24,6 +25,7 @@ export class AlertExample {
|
||||
|
||||
async presentAlertMultipleButtons() {
|
||||
const alert = await this.alertController.create({
|
||||
cssClass: 'my-custom-class',
|
||||
header: 'Alert',
|
||||
subHeader: 'Subtitle',
|
||||
message: 'This is an alert message.',
|
||||
@@ -35,6 +37,7 @@ export class AlertExample {
|
||||
|
||||
async presentAlertConfirm() {
|
||||
const alert = await this.alertController.create({
|
||||
cssClass: 'my-custom-class',
|
||||
header: 'Confirm!',
|
||||
message: 'Message <strong>text</strong>!!!',
|
||||
buttons: [
|
||||
@@ -59,6 +62,7 @@ export class AlertExample {
|
||||
|
||||
async presentAlertPrompt() {
|
||||
const alert = await this.alertController.create({
|
||||
cssClass: 'my-custom-class',
|
||||
header: 'Prompt!',
|
||||
inputs: [
|
||||
{
|
||||
@@ -107,6 +111,16 @@ export class AlertExample {
|
||||
{
|
||||
name: 'name7',
|
||||
type: 'number'
|
||||
},
|
||||
{
|
||||
name: 'name8',
|
||||
type: 'password',
|
||||
placeholder: 'Advanced Attributes',
|
||||
cssClass: 'specialClass',
|
||||
attributes: {
|
||||
maxlength: 4,
|
||||
inputmode: 'decimal'
|
||||
}
|
||||
}
|
||||
],
|
||||
buttons: [
|
||||
@@ -131,6 +145,7 @@ export class AlertExample {
|
||||
|
||||
async presentAlertRadio() {
|
||||
const alert = await this.alertController.create({
|
||||
cssClass: 'my-custom-class',
|
||||
header: 'Radio',
|
||||
inputs: [
|
||||
{
|
||||
@@ -193,6 +208,7 @@ export class AlertExample {
|
||||
|
||||
async presentAlertCheckbox() {
|
||||
const alert = await this.alertController.create({
|
||||
cssClass: 'my-custom-class',
|
||||
header: 'Checkbox',
|
||||
inputs: [
|
||||
{
|
||||
@@ -257,6 +273,10 @@ export class AlertExample {
|
||||
|
||||
await alert.present();
|
||||
}
|
||||
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
### Style Placement
|
||||
|
||||
In Angular, the CSS of a specific page is scoped only to elements of that page. Even though the Alert can be presented from within a page, the `ion-alert` element is appended outside of the current page. This means that any custom styles need to go in a global stylesheet file. In an Ionic Angular starter this can be the `src/global.scss` file or you can register a new global style file by [adding to the `styles` build option in `angular.json`](https://angular.io/guide/workspace-config#style-script-config).
|
||||
@@ -1,6 +1,7 @@
|
||||
```javascript
|
||||
function presentAlert() {
|
||||
const alert = document.createElement('ion-alert');
|
||||
alert.cssClass = 'my-custom-class';
|
||||
alert.header = 'Alert';
|
||||
alert.subHeader = 'Subtitle';
|
||||
alert.message = 'This is an alert message.';
|
||||
@@ -12,6 +13,7 @@ function presentAlert() {
|
||||
|
||||
function presentAlertMultipleButtons() {
|
||||
const alert = document.createElement('ion-alert');
|
||||
alert.cssClass = 'my-custom-class';
|
||||
alert.header = 'Alert';
|
||||
alert.subHeader = 'Subtitle';
|
||||
alert.message = 'This is an alert message.';
|
||||
@@ -23,6 +25,7 @@ function presentAlertMultipleButtons() {
|
||||
|
||||
function presentAlertConfirm() {
|
||||
const alert = document.createElement('ion-alert');
|
||||
alert.cssClass = 'my-custom-class';
|
||||
alert.header = 'Confirm!';
|
||||
alert.message = 'Message <strong>text</strong>!!!';
|
||||
alert.buttons = [
|
||||
@@ -47,6 +50,7 @@ function presentAlertConfirm() {
|
||||
|
||||
function presentAlertPrompt() {
|
||||
const alert = document.createElement('ion-alert');
|
||||
alert.cssClass = 'my-custom-class';
|
||||
alert.header = 'Prompt!';
|
||||
alert.inputs = [
|
||||
{
|
||||
@@ -92,6 +96,16 @@ function presentAlertPrompt() {
|
||||
{
|
||||
name: 'name7',
|
||||
type: 'number'
|
||||
},
|
||||
{
|
||||
name: 'name8',
|
||||
type: 'password',
|
||||
placeholder: 'Advanced Attributes',
|
||||
cssClass: 'specialClass',
|
||||
attributes: {
|
||||
maxlength: 4,
|
||||
inputmode: 'decimal'
|
||||
}
|
||||
}
|
||||
];
|
||||
alert.buttons = [
|
||||
@@ -116,6 +130,7 @@ function presentAlertPrompt() {
|
||||
|
||||
function presentAlertRadio() {
|
||||
const alert = document.createElement('ion-alert');
|
||||
alert.cssClass = 'my-custom-class';
|
||||
alert.header = 'Radio';
|
||||
alert.inputs = [
|
||||
{
|
||||
@@ -171,6 +186,7 @@ function presentAlertRadio() {
|
||||
|
||||
function presentAlertCheckbox() {
|
||||
const alert = document.createElement('ion-alert');
|
||||
alert.cssClass = 'my-custom-class';
|
||||
alert.header = 'Checkbox';
|
||||
alert.inputs = [
|
||||
{
|
||||
|
||||
@@ -22,6 +22,7 @@ export const AlertExample: React.FC = () => {
|
||||
<IonAlert
|
||||
isOpen={showAlert1}
|
||||
onDidDismiss={() => setShowAlert1(false)}
|
||||
cssClass='my-custom-class'
|
||||
header={'Alert'}
|
||||
subHeader={'Subtitle'}
|
||||
message={'This is an alert message.'}
|
||||
@@ -31,6 +32,7 @@ export const AlertExample: React.FC = () => {
|
||||
<IonAlert
|
||||
isOpen={showAlert2}
|
||||
onDidDismiss={() => setShowAlert2(false)}
|
||||
cssClass='my-custom-class'
|
||||
header={'Alert'}
|
||||
subHeader={'Subtitle'}
|
||||
message={'This is an alert message.'}
|
||||
@@ -40,6 +42,7 @@ export const AlertExample: React.FC = () => {
|
||||
<IonAlert
|
||||
isOpen={showAlert3}
|
||||
onDidDismiss={() => setShowAlert3(false)}
|
||||
cssClass='my-custom-class'
|
||||
header={'Confirm!'}
|
||||
message={'Message <strong>text</strong>!!!'}
|
||||
buttons={[
|
||||
@@ -63,6 +66,7 @@ export const AlertExample: React.FC = () => {
|
||||
<IonAlert
|
||||
isOpen={showAlert4}
|
||||
onDidDismiss={() => setShowAlert4(false)}
|
||||
cssClass='my-custom-class'
|
||||
header={'Prompt!'}
|
||||
inputs={[
|
||||
{
|
||||
@@ -104,6 +108,16 @@ export const AlertExample: React.FC = () => {
|
||||
{
|
||||
name: 'name7',
|
||||
type: 'number'
|
||||
},
|
||||
{
|
||||
name: 'name8',
|
||||
type: 'password',
|
||||
placeholder: 'Advanced Attributes',
|
||||
cssClass: 'specialClass',
|
||||
attributes: {
|
||||
maxlength: 4,
|
||||
inputmode: 'decimal'
|
||||
}
|
||||
}
|
||||
]}
|
||||
buttons={[
|
||||
@@ -127,6 +141,7 @@ export const AlertExample: React.FC = () => {
|
||||
<IonAlert
|
||||
isOpen={showAlert5}
|
||||
onDidDismiss={() => setShowAlert5(false)}
|
||||
cssClass='my-custom-class'
|
||||
header={'Radio'}
|
||||
inputs={[
|
||||
{
|
||||
@@ -188,6 +203,7 @@ export const AlertExample: React.FC = () => {
|
||||
<IonAlert
|
||||
isOpen={showAlert6}
|
||||
onDidDismiss={() => setShowAlert6(false)}
|
||||
cssClass='my-custom-class'
|
||||
header={'Checkbox'}
|
||||
inputs={[
|
||||
{
|
||||
|
||||
288
core/src/components/alert/usage/stencil.md
Normal file
288
core/src/components/alert/usage/stencil.md
Normal file
@@ -0,0 +1,288 @@
|
||||
```tsx
|
||||
import { Component, h } from '@stencil/core';
|
||||
|
||||
import { alertController } from '@ionic/core';
|
||||
|
||||
@Component({
|
||||
tag: 'alert-example',
|
||||
styleUrl: 'alert-example.css'
|
||||
})
|
||||
export class AlertExample {
|
||||
async presentAlert() {
|
||||
const alert = await alertController.create({
|
||||
cssClass: 'my-custom-class',
|
||||
header: 'Alert',
|
||||
subHeader: 'Subtitle',
|
||||
message: 'This is an alert message.',
|
||||
buttons: ['OK']
|
||||
});
|
||||
|
||||
await alert.present();
|
||||
}
|
||||
|
||||
async presentAlertMultipleButtons() {
|
||||
const alert = await alertController.create({
|
||||
cssClass: 'my-custom-class',
|
||||
header: 'Alert',
|
||||
subHeader: 'Subtitle',
|
||||
message: 'This is an alert message.',
|
||||
buttons: ['Cancel', 'Open Modal', 'Delete']
|
||||
});
|
||||
|
||||
await alert.present();
|
||||
}
|
||||
|
||||
async presentAlertConfirm() {
|
||||
const alert = await alertController.create({
|
||||
cssClass: 'my-custom-class',
|
||||
header: 'Confirm!',
|
||||
message: 'Message <strong>text</strong>!!!',
|
||||
buttons: [
|
||||
{
|
||||
text: 'Cancel',
|
||||
role: 'cancel',
|
||||
cssClass: 'secondary',
|
||||
handler: (blah) => {
|
||||
console.log('Confirm Cancel: blah');
|
||||
}
|
||||
}, {
|
||||
text: 'Okay',
|
||||
handler: () => {
|
||||
console.log('Confirm Okay');
|
||||
}
|
||||
}
|
||||
]
|
||||
});
|
||||
|
||||
await alert.present();
|
||||
}
|
||||
|
||||
async presentAlertPrompt() {
|
||||
const alert = await alertController.create({
|
||||
cssClass: 'my-custom-class',
|
||||
header: 'Prompt!',
|
||||
inputs: [
|
||||
{
|
||||
name: 'name1',
|
||||
type: 'text',
|
||||
placeholder: 'Placeholder 1'
|
||||
},
|
||||
{
|
||||
name: 'name2',
|
||||
type: 'text',
|
||||
id: 'name2-id',
|
||||
value: 'hello',
|
||||
placeholder: 'Placeholder 2'
|
||||
},
|
||||
// multiline input.
|
||||
{
|
||||
name: 'paragraph',
|
||||
id: 'paragraph',
|
||||
type: 'textarea',
|
||||
placeholder: 'Placeholder 3'
|
||||
},
|
||||
{
|
||||
name: 'name3',
|
||||
value: 'http://ionicframework.com',
|
||||
type: 'url',
|
||||
placeholder: 'Favorite site ever'
|
||||
},
|
||||
// input date with min & max
|
||||
{
|
||||
name: 'name4',
|
||||
type: 'date',
|
||||
min: '2017-03-01',
|
||||
max: '2018-01-12'
|
||||
},
|
||||
// input date without min nor max
|
||||
{
|
||||
name: 'name5',
|
||||
type: 'date'
|
||||
},
|
||||
{
|
||||
name: 'name6',
|
||||
type: 'number',
|
||||
min: -5,
|
||||
max: 10
|
||||
},
|
||||
{
|
||||
name: 'name7',
|
||||
type: 'number'
|
||||
},
|
||||
{
|
||||
name: 'name8',
|
||||
type: 'password',
|
||||
placeholder: 'Advanced Attributes',
|
||||
cssClass: 'specialClass',
|
||||
attributes: {
|
||||
maxlength: 4,
|
||||
inputmode: 'decimal'
|
||||
}
|
||||
}
|
||||
],
|
||||
buttons: [
|
||||
{
|
||||
text: 'Cancel',
|
||||
role: 'cancel',
|
||||
cssClass: 'secondary',
|
||||
handler: () => {
|
||||
console.log('Confirm Cancel');
|
||||
}
|
||||
}, {
|
||||
text: 'Ok',
|
||||
handler: () => {
|
||||
console.log('Confirm Ok');
|
||||
}
|
||||
}
|
||||
]
|
||||
});
|
||||
|
||||
await alert.present();
|
||||
}
|
||||
|
||||
async presentAlertRadio() {
|
||||
const alert = await alertController.create({
|
||||
cssClass: 'my-custom-class',
|
||||
header: 'Radio',
|
||||
inputs: [
|
||||
{
|
||||
name: 'radio1',
|
||||
type: 'radio',
|
||||
label: 'Radio 1',
|
||||
value: 'value1',
|
||||
checked: true
|
||||
},
|
||||
{
|
||||
name: 'radio2',
|
||||
type: 'radio',
|
||||
label: 'Radio 2',
|
||||
value: 'value2'
|
||||
},
|
||||
{
|
||||
name: 'radio3',
|
||||
type: 'radio',
|
||||
label: 'Radio 3',
|
||||
value: 'value3'
|
||||
},
|
||||
{
|
||||
name: 'radio4',
|
||||
type: 'radio',
|
||||
label: 'Radio 4',
|
||||
value: 'value4'
|
||||
},
|
||||
{
|
||||
name: 'radio5',
|
||||
type: 'radio',
|
||||
label: 'Radio 5',
|
||||
value: 'value5'
|
||||
},
|
||||
{
|
||||
name: 'radio6',
|
||||
type: 'radio',
|
||||
label: 'Radio 6 Radio 6 Radio 6 Radio 6 Radio 6 Radio 6 Radio 6 Radio 6 Radio 6 Radio 6 ',
|
||||
value: 'value6'
|
||||
}
|
||||
],
|
||||
buttons: [
|
||||
{
|
||||
text: 'Cancel',
|
||||
role: 'cancel',
|
||||
cssClass: 'secondary',
|
||||
handler: () => {
|
||||
console.log('Confirm Cancel');
|
||||
}
|
||||
}, {
|
||||
text: 'Ok',
|
||||
handler: () => {
|
||||
console.log('Confirm Ok');
|
||||
}
|
||||
}
|
||||
]
|
||||
});
|
||||
|
||||
await alert.present();
|
||||
}
|
||||
|
||||
async presentAlertCheckbox() {
|
||||
const alert = await alertController.create({
|
||||
cssClass: 'my-custom-class',
|
||||
header: 'Checkbox',
|
||||
inputs: [
|
||||
{
|
||||
name: 'checkbox1',
|
||||
type: 'checkbox',
|
||||
label: 'Checkbox 1',
|
||||
value: 'value1',
|
||||
checked: true
|
||||
},
|
||||
|
||||
{
|
||||
name: 'checkbox2',
|
||||
type: 'checkbox',
|
||||
label: 'Checkbox 2',
|
||||
value: 'value2'
|
||||
},
|
||||
|
||||
{
|
||||
name: 'checkbox3',
|
||||
type: 'checkbox',
|
||||
label: 'Checkbox 3',
|
||||
value: 'value3'
|
||||
},
|
||||
|
||||
{
|
||||
name: 'checkbox4',
|
||||
type: 'checkbox',
|
||||
label: 'Checkbox 4',
|
||||
value: 'value4'
|
||||
},
|
||||
|
||||
{
|
||||
name: 'checkbox5',
|
||||
type: 'checkbox',
|
||||
label: 'Checkbox 5',
|
||||
value: 'value5'
|
||||
},
|
||||
|
||||
{
|
||||
name: 'checkbox6',
|
||||
type: 'checkbox',
|
||||
label: 'Checkbox 6 Checkbox 6 Checkbox 6 Checkbox 6 Checkbox 6 Checkbox 6 Checkbox 6 Checkbox 6 Checkbox 6 Checkbox 6',
|
||||
value: 'value6'
|
||||
}
|
||||
],
|
||||
buttons: [
|
||||
{
|
||||
text: 'Cancel',
|
||||
role: 'cancel',
|
||||
cssClass: 'secondary',
|
||||
handler: () => {
|
||||
console.log('Confirm Cancel');
|
||||
}
|
||||
}, {
|
||||
text: 'Ok',
|
||||
handler: () => {
|
||||
console.log('Confirm Ok');
|
||||
}
|
||||
}
|
||||
]
|
||||
});
|
||||
|
||||
await alert.present();
|
||||
}
|
||||
|
||||
|
||||
render() {
|
||||
return [
|
||||
<ion-content>
|
||||
<ion-button onClick={() => this.presentAlert()}>Present Alert</ion-button>
|
||||
<ion-button onClick={() => this.presentAlertMultipleButtons()}>Present Alert: Multiple Buttons</ion-button>
|
||||
<ion-button onClick={() => this.presentAlertConfirm()}>Present Alert: Confirm</ion-button>
|
||||
<ion-button onClick={() => this.presentAlertPrompt()}>Present Alert: Prompt</ion-button>
|
||||
<ion-button onClick={() => this.presentAlertRadio()}>Present Alert: Radio</ion-button>
|
||||
<ion-button onClick={() => this.presentAlertCheckbox()}>Present Alert: Checkbox</ion-button>
|
||||
</ion-content>
|
||||
];
|
||||
}
|
||||
}
|
||||
```
|
||||
@@ -16,6 +16,7 @@ export default {
|
||||
presentAlert() {
|
||||
return this.$ionic.alertController
|
||||
.create({
|
||||
cssClass: 'my-custom-class',
|
||||
header: 'Alert',
|
||||
subHeader: 'Subtitle',
|
||||
message: 'This is an alert message.',
|
||||
@@ -27,6 +28,7 @@ export default {
|
||||
presentAlertMultipleButtons() {
|
||||
return this.$ionic.alertController
|
||||
.create({
|
||||
cssClass: 'my-custom-class',
|
||||
header: 'Alert',
|
||||
subHeader: 'Subtitle',
|
||||
message: 'This is an alert message.',
|
||||
@@ -38,6 +40,7 @@ export default {
|
||||
presentAlertConfirm() {
|
||||
return this.$ionic.alertController
|
||||
.create({
|
||||
cssClass: 'my-custom-class',
|
||||
header: 'Confirm!',
|
||||
message: 'Message <strong>text</strong>!!!',
|
||||
buttons: [
|
||||
@@ -63,6 +66,7 @@ export default {
|
||||
presentAlertPrompt() {
|
||||
return this.$ionic.alertController
|
||||
.create({
|
||||
cssClass: 'my-custom-class',
|
||||
header: 'Prompt!',
|
||||
inputs: [
|
||||
{
|
||||
@@ -102,6 +106,16 @@ export default {
|
||||
name: 'name7',
|
||||
type: 'number',
|
||||
},
|
||||
{
|
||||
name: 'name8',
|
||||
type: 'password',
|
||||
placeholder: 'Advanced Attributes',
|
||||
cssClass: 'specialClass',
|
||||
attributes: {
|
||||
maxlength: 4,
|
||||
inputmode: 'decimal'
|
||||
}
|
||||
}
|
||||
],
|
||||
buttons: [
|
||||
{
|
||||
@@ -126,6 +140,7 @@ export default {
|
||||
presentAlertRadio() {
|
||||
return this.$ionic.alertController
|
||||
.create({
|
||||
cssClass: 'my-custom-class',
|
||||
header: 'Radio',
|
||||
inputs: [
|
||||
{
|
||||
@@ -183,6 +198,7 @@ export default {
|
||||
presentAlertCheckbox() {
|
||||
return this.$ionic.alertController
|
||||
.create({
|
||||
cssClass: 'my-custom-class',
|
||||
header: 'Checkbox',
|
||||
inputs: [
|
||||
{
|
||||
|
||||
@@ -6,10 +6,9 @@ import { isPlatform } from '../../utils/platform';
|
||||
|
||||
@Component({
|
||||
tag: 'ion-app',
|
||||
styleUrl: 'app.scss'
|
||||
styleUrl: 'app.scss',
|
||||
})
|
||||
export class App implements ComponentInterface {
|
||||
|
||||
@Element() el!: HTMLElement;
|
||||
|
||||
componentDidLoad() {
|
||||
@@ -28,6 +27,9 @@ export class App implements ComponentInterface {
|
||||
if (config.getBoolean('hardwareBackButton', isHybrid)) {
|
||||
import('../../utils/hardware-back-button').then(module => module.startHardwareBackButton());
|
||||
}
|
||||
if (typeof (window as any) !== 'undefined') {
|
||||
import('../../utils/keyboard/keyboard').then(module => module.startKeyboardAssist(window));
|
||||
}
|
||||
import('../../utils/focus-visible').then(module => module.startFocusVisible());
|
||||
});
|
||||
}
|
||||
@@ -40,7 +42,7 @@ export class App implements ComponentInterface {
|
||||
class={{
|
||||
[mode]: true,
|
||||
'ion-page': true,
|
||||
'force-statusbar-padding': config.getBoolean('_forceStatusbarPadding')
|
||||
'force-statusbar-padding': config.getBoolean('_forceStatusbarPadding'),
|
||||
}}
|
||||
>
|
||||
</Host>
|
||||
|
||||
@@ -36,7 +36,7 @@ Avatars can be used by themselves or inside of any element. If placed inside of
|
||||
### React
|
||||
|
||||
```tsx
|
||||
import React from 'react'
|
||||
import React from 'react';
|
||||
import { IonAvatar, IonChip, IonItem, IonLabel, IonContent } from '@ionic/react';
|
||||
|
||||
export const AvatarExample: React.FC = () => (
|
||||
@@ -63,6 +63,41 @@ export const AvatarExample: React.FC = () => (
|
||||
```
|
||||
|
||||
|
||||
### Stencil
|
||||
|
||||
```tsx
|
||||
import { Component, h } from '@stencil/core';
|
||||
|
||||
@Component({
|
||||
tag: 'avatar-example',
|
||||
styleUrl: 'avatar-example.css'
|
||||
})
|
||||
export class AvatarExample {
|
||||
render() {
|
||||
return [
|
||||
<ion-avatar>
|
||||
<img src="https://gravatar.com/avatar/dba6bae8c566f9d4041fb9cd9ada7741?d=identicon&f=y"/>
|
||||
</ion-avatar>,
|
||||
|
||||
<ion-chip>
|
||||
<ion-avatar>
|
||||
<img src="https://gravatar.com/avatar/dba6bae8c566f9d4041fb9cd9ada7741?d=identicon&f=y"/>
|
||||
</ion-avatar>
|
||||
<ion-label>Chip Avatar</ion-label>
|
||||
</ion-chip>,
|
||||
|
||||
<ion-item>
|
||||
<ion-avatar slot="start">
|
||||
<img src="https://gravatar.com/avatar/dba6bae8c566f9d4041fb9cd9ada7741?d=identicon&f=y"/>
|
||||
</ion-avatar>
|
||||
<ion-label>Item Avatar</ion-label>
|
||||
</ion-item>
|
||||
];
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
### Vue
|
||||
|
||||
```html
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
```tsx
|
||||
import React from 'react'
|
||||
import React from 'react';
|
||||
import { IonAvatar, IonChip, IonItem, IonLabel, IonContent } from '@ionic/react';
|
||||
|
||||
export const AvatarExample: React.FC = () => (
|
||||
|
||||
31
core/src/components/avatar/usage/stencil.md
Normal file
31
core/src/components/avatar/usage/stencil.md
Normal file
@@ -0,0 +1,31 @@
|
||||
```tsx
|
||||
import { Component, h } from '@stencil/core';
|
||||
|
||||
@Component({
|
||||
tag: 'avatar-example',
|
||||
styleUrl: 'avatar-example.css'
|
||||
})
|
||||
export class AvatarExample {
|
||||
render() {
|
||||
return [
|
||||
<ion-avatar>
|
||||
<img src="https://gravatar.com/avatar/dba6bae8c566f9d4041fb9cd9ada7741?d=identicon&f=y"/>
|
||||
</ion-avatar>,
|
||||
|
||||
<ion-chip>
|
||||
<ion-avatar>
|
||||
<img src="https://gravatar.com/avatar/dba6bae8c566f9d4041fb9cd9ada7741?d=identicon&f=y"/>
|
||||
</ion-avatar>
|
||||
<ion-label>Chip Avatar</ion-label>
|
||||
</ion-chip>,
|
||||
|
||||
<ion-item>
|
||||
<ion-avatar slot="start">
|
||||
<img src="https://gravatar.com/avatar/dba6bae8c566f9d4041fb9cd9ada7741?d=identicon&f=y"/>
|
||||
</ion-avatar>
|
||||
<ion-label>Item Avatar</ion-label>
|
||||
</ion-item>
|
||||
];
|
||||
}
|
||||
}
|
||||
```
|
||||
@@ -239,6 +239,6 @@ ion-icon {
|
||||
// Back Button in Toolbar: Global Theming
|
||||
// --------------------------------------------------
|
||||
|
||||
:host(.in-toolbar) {
|
||||
:host(.in-toolbar:not(.in-toolbar-color)) {
|
||||
color: #{var(--ion-toolbar-color, var(--color))};
|
||||
}
|
||||
@@ -19,7 +19,6 @@ import { createColorClasses, hostContext, openURL } from '../../utils/theme';
|
||||
})
|
||||
export class BackButton implements ComponentInterface, ButtonInterface {
|
||||
|
||||
mode = getIonMode(this);
|
||||
@Element() el!: HTMLElement;
|
||||
|
||||
/**
|
||||
@@ -32,7 +31,7 @@ export class BackButton implements ComponentInterface, ButtonInterface {
|
||||
/**
|
||||
* The url to navigate back to by default when there is no history.
|
||||
*/
|
||||
@Prop() defaultHref?: string;
|
||||
@Prop({ mutable: true }) defaultHref?: string;
|
||||
|
||||
/**
|
||||
* If `true`, the user cannot interact with the button.
|
||||
@@ -54,6 +53,12 @@ export class BackButton implements ComponentInterface, ButtonInterface {
|
||||
*/
|
||||
@Prop() type: 'submit' | 'reset' | 'button' = 'button';
|
||||
|
||||
componentWillLoad() {
|
||||
if (this.defaultHref === undefined) {
|
||||
this.defaultHref = config.get('backButtonDefaultHref');
|
||||
}
|
||||
}
|
||||
|
||||
get backButtonIcon() {
|
||||
const icon = this.icon;
|
||||
if (icon != null) {
|
||||
@@ -61,7 +66,7 @@ export class BackButton implements ComponentInterface, ButtonInterface {
|
||||
return icon;
|
||||
}
|
||||
|
||||
if (this.mode === 'ios') {
|
||||
if (getIonMode(this) === 'ios') {
|
||||
// default ios back button icon
|
||||
return config.get('backButtonIcon', 'chevron-back');
|
||||
}
|
||||
@@ -71,7 +76,7 @@ export class BackButton implements ComponentInterface, ButtonInterface {
|
||||
}
|
||||
|
||||
get backButtonText() {
|
||||
const defaultBackButtonText = this.mode === 'ios' ? 'Back' : null;
|
||||
const defaultBackButtonText = getIonMode(this) === 'ios' ? 'Back' : null;
|
||||
return this.text != null ? this.text : config.get('backButtonText', defaultBackButtonText);
|
||||
}
|
||||
|
||||
@@ -100,8 +105,9 @@ export class BackButton implements ComponentInterface, ButtonInterface {
|
||||
}
|
||||
|
||||
render() {
|
||||
const { color, defaultHref, disabled, type, mode, hasIconOnly, backButtonIcon, backButtonText } = this;
|
||||
const { color, defaultHref, disabled, type, hasIconOnly, backButtonIcon, backButtonText } = this;
|
||||
const showBackButton = defaultHref !== undefined;
|
||||
const mode = getIonMode(this);
|
||||
|
||||
return (
|
||||
<Host
|
||||
@@ -114,15 +120,16 @@ export class BackButton implements ComponentInterface, ButtonInterface {
|
||||
'back-button-disabled': disabled,
|
||||
'back-button-has-icon-only': hasIconOnly,
|
||||
'in-toolbar': hostContext('ion-toolbar', this.el),
|
||||
'in-toolbar-color': hostContext('ion-toolbar[color]', this.el),
|
||||
'ion-activatable': true,
|
||||
'ion-focusable': true,
|
||||
'show-back-button': showBackButton
|
||||
}}
|
||||
>
|
||||
<button type={type} disabled={disabled} class="button-native" part="button">
|
||||
<button type={type} disabled={disabled} class="button-native" aria-label={backButtonText || 'back'}>
|
||||
<span class="button-inner">
|
||||
{backButtonIcon && <ion-icon icon={backButtonIcon} lazy={false} part="icon"></ion-icon>}
|
||||
{backButtonText && <span class="button-text" part="text">{backButtonText}</span>}
|
||||
{backButtonIcon && <ion-icon icon={backButtonIcon} aria-hidden="true" lazy={false}></ion-icon>}
|
||||
{backButtonText && <span aria-hidden="true" class="button-text">{backButtonText}</span>}
|
||||
</span>
|
||||
{mode === 'md' && <ion-ripple-effect type={this.rippleType}></ion-ripple-effect>}
|
||||
</button>
|
||||
|
||||
@@ -173,6 +173,75 @@ export const BackButtonExample: React.FC = () => (
|
||||
```
|
||||
|
||||
|
||||
### Stencil
|
||||
|
||||
```tsx
|
||||
import { Component, h } from '@stencil/core';
|
||||
|
||||
@Component({
|
||||
tag: 'back-button-example',
|
||||
styleUrl: 'back-button-example.css'
|
||||
})
|
||||
export class BackButtonExample {
|
||||
render() {
|
||||
const buttonText = "Custom";
|
||||
const buttonIcon = "add";
|
||||
|
||||
return [
|
||||
// Default back button
|
||||
<ion-header>
|
||||
<ion-toolbar>
|
||||
<ion-buttons slot="start">
|
||||
<ion-back-button></ion-back-button>
|
||||
</ion-buttons>
|
||||
</ion-toolbar>
|
||||
</ion-header>,
|
||||
|
||||
// Back button with a default href
|
||||
<ion-header>
|
||||
<ion-toolbar>
|
||||
<ion-buttons slot="start">
|
||||
<ion-back-button defaultHref="home"></ion-back-button>
|
||||
</ion-buttons>
|
||||
</ion-toolbar>
|
||||
</ion-header>,
|
||||
|
||||
// Back button with custom text and icon
|
||||
<ion-header>
|
||||
<ion-toolbar>
|
||||
<ion-buttons slot="start">
|
||||
<ion-back-button
|
||||
text={buttonText}
|
||||
icon={buttonIcon}>
|
||||
</ion-back-button>
|
||||
</ion-buttons>
|
||||
</ion-toolbar>
|
||||
</ion-header>,
|
||||
|
||||
// Back button with no text and custom icon
|
||||
<ion-header>
|
||||
<ion-toolbar>
|
||||
<ion-buttons slot="start">
|
||||
<ion-back-button text="" icon="add"></ion-back-button>
|
||||
</ion-buttons>
|
||||
</ion-toolbar>
|
||||
</ion-header>,
|
||||
|
||||
// Danger back button next to a menu button
|
||||
<ion-header>
|
||||
<ion-toolbar>
|
||||
<ion-buttons slot="start">
|
||||
<ion-menu-button></ion-menu-button>
|
||||
<ion-back-button color="danger"></ion-back-button>
|
||||
</ion-buttons>
|
||||
</ion-toolbar>
|
||||
</ion-header>
|
||||
];
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
### Vue
|
||||
|
||||
```html
|
||||
|
||||
@@ -1,18 +1,28 @@
|
||||
import { newSpecPage } from '@stencil/core/testing';
|
||||
import { BackButton } from "../back-button";
|
||||
import { config } from "../../../global/config";
|
||||
import { setMode } from '@stencil/core';
|
||||
|
||||
|
||||
describe('back button', () => {
|
||||
let bb: BackButton;
|
||||
|
||||
beforeEach(() => {
|
||||
config.reset({});
|
||||
bb = new BackButton();
|
||||
});
|
||||
|
||||
const newBackButton = async (mode: string = 'md'): Promise<BackButton> => {
|
||||
setMode(() => mode);
|
||||
const { rootInstance } = await newSpecPage({
|
||||
components: [BackButton],
|
||||
html: `<ion-back-button></ion-back-button>`
|
||||
})
|
||||
return rootInstance;
|
||||
};
|
||||
|
||||
|
||||
describe('backButtonIcon', () => {
|
||||
|
||||
it('set custom icon on the instance, override config', () => {
|
||||
it('set custom icon on the instance, override config', async () => {
|
||||
const bb = await newBackButton();
|
||||
bb.icon = 'custom-icon-instance';
|
||||
config.reset({
|
||||
backButtonIcon: 'custom-icon-config'
|
||||
@@ -20,24 +30,27 @@ describe('back button', () => {
|
||||
expect(bb.backButtonIcon).toBe('custom-icon-instance');
|
||||
});
|
||||
|
||||
it('set custom icon in the config', () => {
|
||||
it('set custom icon in the config', async () => {
|
||||
const bb = await newBackButton();
|
||||
config.reset({
|
||||
backButtonIcon: 'custom-icon-config'
|
||||
});
|
||||
expect(bb.backButtonIcon).toBe('custom-icon-config');
|
||||
});
|
||||
|
||||
it('set custom icon on the instance', () => {
|
||||
it('set custom icon on the instance', async () => {
|
||||
const bb = await newBackButton();
|
||||
bb.icon = 'custom-icon-instance';
|
||||
expect(bb.backButtonIcon).toBe('custom-icon-instance');
|
||||
});
|
||||
|
||||
it('default icon for ios mode', () => {
|
||||
bb.mode = 'ios';
|
||||
it('default icon for ios mode', async () => {
|
||||
const bb = await newBackButton('ios');
|
||||
expect(bb.backButtonIcon).toBe('chevron-back');
|
||||
});
|
||||
|
||||
it('default icon', () => {
|
||||
it('default icon', async () => {
|
||||
const bb = await newBackButton();
|
||||
expect(bb.backButtonIcon).toBe('arrow-back-sharp');
|
||||
});
|
||||
|
||||
@@ -45,15 +58,49 @@ describe('back button', () => {
|
||||
|
||||
describe('backButtonText', () => {
|
||||
|
||||
it('default text for ios mode', () => {
|
||||
bb.mode = 'ios';
|
||||
it('default text for ios mode', async () => {
|
||||
const bb = await newBackButton('ios');
|
||||
expect(bb.backButtonText).toBe('Back');
|
||||
});
|
||||
|
||||
it('default text', () => {
|
||||
it('default text', async () => {
|
||||
const bb = await newBackButton();
|
||||
expect(bb.backButtonText).toBe(null);
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
describe('backButtonDefaultHref', () => {
|
||||
|
||||
it('set custom defaultHref in the config', async () => {
|
||||
config.reset({
|
||||
backButtonDefaultHref: 'custom-default-href-config'
|
||||
});
|
||||
const bb = await newBackButton();
|
||||
expect(bb.defaultHref).toBe('custom-default-href-config');
|
||||
});
|
||||
|
||||
it('set custom defaultHref on the instance', async () => {
|
||||
const bb = await newBackButton();
|
||||
bb.defaultHref = 'custom-default-href';
|
||||
expect(bb.defaultHref).toBe('custom-default-href');
|
||||
});
|
||||
|
||||
it('set custom defaultHref on the instance, override config', async () => {
|
||||
const bb = await newBackButton();
|
||||
bb.defaultHref = 'custom-default-href';
|
||||
|
||||
config.reset({
|
||||
backButtonDefaultHref: 'custom-default-href-config'
|
||||
});
|
||||
|
||||
expect(bb.defaultHref).toBe('custom-default-href');
|
||||
|
||||
const bb2 = await newBackButton();
|
||||
bb2.defaultHref = 'custom-default-href-second';
|
||||
expect(bb2.defaultHref).toBe('custom-default-href-second');
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
65
core/src/components/back-button/usage/stencil.md
Normal file
65
core/src/components/back-button/usage/stencil.md
Normal file
@@ -0,0 +1,65 @@
|
||||
```tsx
|
||||
import { Component, h } from '@stencil/core';
|
||||
|
||||
@Component({
|
||||
tag: 'back-button-example',
|
||||
styleUrl: 'back-button-example.css'
|
||||
})
|
||||
export class BackButtonExample {
|
||||
render() {
|
||||
const buttonText = "Custom";
|
||||
const buttonIcon = "add";
|
||||
|
||||
return [
|
||||
// Default back button
|
||||
<ion-header>
|
||||
<ion-toolbar>
|
||||
<ion-buttons slot="start">
|
||||
<ion-back-button></ion-back-button>
|
||||
</ion-buttons>
|
||||
</ion-toolbar>
|
||||
</ion-header>,
|
||||
|
||||
// Back button with a default href
|
||||
<ion-header>
|
||||
<ion-toolbar>
|
||||
<ion-buttons slot="start">
|
||||
<ion-back-button defaultHref="home"></ion-back-button>
|
||||
</ion-buttons>
|
||||
</ion-toolbar>
|
||||
</ion-header>,
|
||||
|
||||
// Back button with custom text and icon
|
||||
<ion-header>
|
||||
<ion-toolbar>
|
||||
<ion-buttons slot="start">
|
||||
<ion-back-button
|
||||
text={buttonText}
|
||||
icon={buttonIcon}>
|
||||
</ion-back-button>
|
||||
</ion-buttons>
|
||||
</ion-toolbar>
|
||||
</ion-header>,
|
||||
|
||||
// Back button with no text and custom icon
|
||||
<ion-header>
|
||||
<ion-toolbar>
|
||||
<ion-buttons slot="start">
|
||||
<ion-back-button text="" icon="add"></ion-back-button>
|
||||
</ion-buttons>
|
||||
</ion-toolbar>
|
||||
</ion-header>,
|
||||
|
||||
// Danger back button next to a menu button
|
||||
<ion-header>
|
||||
<ion-toolbar>
|
||||
<ion-buttons slot="start">
|
||||
<ion-menu-button></ion-menu-button>
|
||||
<ion-back-button color="danger"></ion-back-button>
|
||||
</ion-buttons>
|
||||
</ion-toolbar>
|
||||
</ion-header>
|
||||
];
|
||||
}
|
||||
}
|
||||
```
|
||||
@@ -2,7 +2,6 @@ import { Component, ComponentInterface, Event, EventEmitter, Host, Listen, Prop,
|
||||
|
||||
import { getIonMode } from '../../global/ionic-global';
|
||||
import { GESTURE_CONTROLLER } from '../../utils/gesture';
|
||||
import { now } from '../../utils/helpers';
|
||||
|
||||
@Component({
|
||||
tag: 'ion-backdrop',
|
||||
@@ -14,7 +13,6 @@ import { now } from '../../utils/helpers';
|
||||
})
|
||||
export class Backdrop implements ComponentInterface {
|
||||
|
||||
private lastClick = -10000;
|
||||
private blocker = GESTURE_CONTROLLER.createBlocker({
|
||||
disableScroll: true
|
||||
});
|
||||
@@ -49,18 +47,9 @@ export class Backdrop implements ComponentInterface {
|
||||
this.blocker.unblock();
|
||||
}
|
||||
|
||||
@Listen('touchstart', { passive: false, capture: true })
|
||||
protected onTouchStart(ev: TouchEvent) {
|
||||
this.lastClick = now(ev);
|
||||
this.emitTap(ev);
|
||||
}
|
||||
|
||||
@Listen('click', { passive: false, capture: true })
|
||||
@Listen('mousedown', { passive: false, capture: true })
|
||||
protected onMouseDown(ev: TouchEvent) {
|
||||
if (this.lastClick < now(ev) - 2500) {
|
||||
this.emitTap(ev);
|
||||
}
|
||||
this.emitTap(ev);
|
||||
}
|
||||
|
||||
private emitTap(ev: Event) {
|
||||
|
||||
@@ -40,7 +40,7 @@ import { Component } from '@angular/core';
|
||||
styleUrls: ['./backdrop-example.css'],
|
||||
})
|
||||
export class BackdropExample {
|
||||
backdropDismiss = false;
|
||||
enableBackdropDismiss = false;
|
||||
showBackdrop = false;
|
||||
shouldPropagate = false;
|
||||
}
|
||||
@@ -100,6 +100,46 @@ export const BackdropExample: React.FC = () => (
|
||||
```
|
||||
|
||||
|
||||
### Stencil
|
||||
|
||||
```tsx
|
||||
import { Component, h } from '@stencil/core';
|
||||
|
||||
@Component({
|
||||
tag: 'backdrop-example',
|
||||
styleUrl: 'backdrop-example.css'
|
||||
})
|
||||
export class BackdropExample {
|
||||
render() {
|
||||
const enableBackdropDismiss = false;
|
||||
const showBackdrop = false;
|
||||
const shouldPropagate = false;
|
||||
|
||||
return [
|
||||
// Default backdrop
|
||||
<ion-backdrop></ion-backdrop>,
|
||||
|
||||
// Backdrop that is not tappable
|
||||
<ion-backdrop tappable={false}></ion-backdrop>,
|
||||
|
||||
// Backdrop that is not visible
|
||||
<ion-backdrop visible={false}></ion-backdrop>,
|
||||
|
||||
// Backdrop with propagation
|
||||
<ion-backdrop stopPropagation={false}></ion-backdrop>,
|
||||
|
||||
// Backdrop that sets dynamic properties
|
||||
<ion-backdrop
|
||||
tappable={enableBackdropDismiss}
|
||||
visible={showBackdrop}
|
||||
stopPropagation={shouldPropagate}>
|
||||
</ion-backdrop>
|
||||
];
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
### Vue
|
||||
|
||||
```html
|
||||
@@ -129,7 +169,7 @@ export const BackdropExample: React.FC = () => (
|
||||
|
||||
@Component()
|
||||
export default class Example extends Vue {
|
||||
backdropDismiss = false;
|
||||
enableBackdropDismiss = false;
|
||||
showBackdrop = false;
|
||||
shouldPropagate = false;
|
||||
}
|
||||
|
||||
@@ -28,7 +28,7 @@ import { Component } from '@angular/core';
|
||||
styleUrls: ['./backdrop-example.css'],
|
||||
})
|
||||
export class BackdropExample {
|
||||
backdropDismiss = false;
|
||||
enableBackdropDismiss = false;
|
||||
showBackdrop = false;
|
||||
shouldPropagate = false;
|
||||
}
|
||||
|
||||
36
core/src/components/backdrop/usage/stencil.md
Normal file
36
core/src/components/backdrop/usage/stencil.md
Normal file
@@ -0,0 +1,36 @@
|
||||
```tsx
|
||||
import { Component, h } from '@stencil/core';
|
||||
|
||||
@Component({
|
||||
tag: 'backdrop-example',
|
||||
styleUrl: 'backdrop-example.css'
|
||||
})
|
||||
export class BackdropExample {
|
||||
render() {
|
||||
const enableBackdropDismiss = false;
|
||||
const showBackdrop = false;
|
||||
const shouldPropagate = false;
|
||||
|
||||
return [
|
||||
// Default backdrop
|
||||
<ion-backdrop></ion-backdrop>,
|
||||
|
||||
// Backdrop that is not tappable
|
||||
<ion-backdrop tappable={false}></ion-backdrop>,
|
||||
|
||||
// Backdrop that is not visible
|
||||
<ion-backdrop visible={false}></ion-backdrop>,
|
||||
|
||||
// Backdrop with propagation
|
||||
<ion-backdrop stopPropagation={false}></ion-backdrop>,
|
||||
|
||||
// Backdrop that sets dynamic properties
|
||||
<ion-backdrop
|
||||
tappable={enableBackdropDismiss}
|
||||
visible={showBackdrop}
|
||||
stopPropagation={shouldPropagate}>
|
||||
</ion-backdrop>
|
||||
];
|
||||
}
|
||||
}
|
||||
```
|
||||
@@ -25,7 +25,7 @@
|
||||
|
||||
@Component()
|
||||
export default class Example extends Vue {
|
||||
backdropDismiss = false;
|
||||
enableBackdropDismiss = false;
|
||||
showBackdrop = false;
|
||||
shouldPropagate = false;
|
||||
}
|
||||
|
||||
@@ -67,6 +67,44 @@ export const BadgeExample: React.FC = () => (
|
||||
```
|
||||
|
||||
|
||||
### Stencil
|
||||
|
||||
```tsx
|
||||
import { Component, h } from '@stencil/core';
|
||||
|
||||
@Component({
|
||||
tag: 'badge-example',
|
||||
styleUrl: 'badge-example.css'
|
||||
})
|
||||
export class BadgeExample {
|
||||
render() {
|
||||
return [
|
||||
// Default
|
||||
<ion-badge>99</ion-badge>,
|
||||
|
||||
// Colors
|
||||
<ion-badge color="primary">11</ion-badge>,
|
||||
<ion-badge color="secondary">22</ion-badge>,
|
||||
<ion-badge color="tertiary">33</ion-badge>,
|
||||
<ion-badge color="success">44</ion-badge>,
|
||||
<ion-badge color="warning">55</ion-badge>,
|
||||
<ion-badge color="danger">66</ion-badge>,
|
||||
<ion-badge color="light">77</ion-badge>,
|
||||
<ion-badge color="medium">88</ion-badge>,
|
||||
<ion-badge color="dark">99</ion-badge>,
|
||||
|
||||
// Item with badge on left and right
|
||||
<ion-item>
|
||||
<ion-badge slot="start">11</ion-badge>
|
||||
<ion-label>My Item</ion-label>
|
||||
<ion-badge slot="end">22</ion-badge>
|
||||
</ion-item>
|
||||
];
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
### Vue
|
||||
|
||||
```html
|
||||
|
||||
34
core/src/components/badge/usage/stencil.md
Normal file
34
core/src/components/badge/usage/stencil.md
Normal file
@@ -0,0 +1,34 @@
|
||||
```tsx
|
||||
import { Component, h } from '@stencil/core';
|
||||
|
||||
@Component({
|
||||
tag: 'badge-example',
|
||||
styleUrl: 'badge-example.css'
|
||||
})
|
||||
export class BadgeExample {
|
||||
render() {
|
||||
return [
|
||||
// Default
|
||||
<ion-badge>99</ion-badge>,
|
||||
|
||||
// Colors
|
||||
<ion-badge color="primary">11</ion-badge>,
|
||||
<ion-badge color="secondary">22</ion-badge>,
|
||||
<ion-badge color="tertiary">33</ion-badge>,
|
||||
<ion-badge color="success">44</ion-badge>,
|
||||
<ion-badge color="warning">55</ion-badge>,
|
||||
<ion-badge color="danger">66</ion-badge>,
|
||||
<ion-badge color="light">77</ion-badge>,
|
||||
<ion-badge color="medium">88</ion-badge>,
|
||||
<ion-badge color="dark">99</ion-badge>,
|
||||
|
||||
// Item with badge on left and right
|
||||
<ion-item>
|
||||
<ion-badge slot="start">11</ion-badge>
|
||||
<ion-label>My Item</ion-label>
|
||||
<ion-badge slot="end">22</ion-badge>
|
||||
</ion-item>
|
||||
];
|
||||
}
|
||||
}
|
||||
```
|
||||
@@ -175,4 +175,12 @@
|
||||
:host(.button-solid.ion-color:hover) .button-native::after {
|
||||
background: #{current-color(tint)};
|
||||
}
|
||||
|
||||
// Solid buttons inside of a toolbar should use a tint of the current
|
||||
// background so use white to tint it
|
||||
:host(:hover.button-solid.in-toolbar:not(.ion-color):not(.in-toolbar-color)) .button-native::after {
|
||||
background: #fff;
|
||||
|
||||
opacity: 0.10;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -179,13 +179,13 @@
|
||||
line-height: 1;
|
||||
|
||||
box-shadow: var(--box-shadow);
|
||||
|
||||
contain: layout style;
|
||||
cursor: pointer;
|
||||
|
||||
opacity: var(--opacity);
|
||||
overflow: var(--overflow);
|
||||
|
||||
overflow: hidden;
|
||||
|
||||
z-index: 0;
|
||||
box-sizing: border-box;
|
||||
appearance: none;
|
||||
@@ -305,3 +305,19 @@ ion-ripple-effect {
|
||||
background: transparent;
|
||||
color: current-color(base);
|
||||
}
|
||||
|
||||
// Button in Toolbar
|
||||
// --------------------------------------------------
|
||||
|
||||
:host(.in-toolbar:not(.ion-color):not(.in-toolbar-color)) .button-native {
|
||||
color: #{var(--ion-toolbar-color, var(--color))};
|
||||
}
|
||||
|
||||
:host(.button-outline.in-toolbar:not(.ion-color):not(.in-toolbar-color)) .button-native {
|
||||
border-color: #{var(--ion-toolbar-color, var(--color, var(--border-color)))};
|
||||
}
|
||||
|
||||
:host(.button-solid.in-toolbar:not(.ion-color):not(.in-toolbar-color)) .button-native {
|
||||
background: #{var(--ion-toolbar-color, var(--background))};
|
||||
color: #{var(--ion-toolbar-background, var(--color))};
|
||||
}
|
||||
|
||||
@@ -4,7 +4,7 @@ import { getIonMode } from '../../global/ionic-global';
|
||||
import { Color, RouterDirection } from '../../interface';
|
||||
import { AnchorInterface, ButtonInterface } from '../../utils/element-interface';
|
||||
import { hasShadowDom } from '../../utils/helpers';
|
||||
import { createColorClasses, openURL } from '../../utils/theme';
|
||||
import { createColorClasses, hostContext, openURL } from '../../utils/theme';
|
||||
|
||||
/**
|
||||
* @virtualProp {"ios" | "md"} mode - The mode determines which platform styles to use.
|
||||
@@ -13,9 +13,6 @@ import { createColorClasses, openURL } from '../../utils/theme';
|
||||
* @slot icon-only - Should be used on an icon in a button that has no text.
|
||||
* @slot start - Content is placed to the left of the button text in LTR, and to the right in RTL.
|
||||
* @slot end - Content is placed to the right of the button text in LTR, and to the left in RTL.
|
||||
*
|
||||
* @part button - The native button or anchor tag that is rendered.
|
||||
* @part button-inner - The span inside of the native button or anchor.
|
||||
*/
|
||||
@Component({
|
||||
tag: 'ion-button',
|
||||
@@ -208,7 +205,8 @@ export class Button implements ComponentInterface, AnchorInterface, ButtonInterf
|
||||
[`${buttonType}-${shape}`]: shape !== undefined,
|
||||
[`${buttonType}-${fill}`]: true,
|
||||
[`${buttonType}-strong`]: strong,
|
||||
|
||||
'in-toolbar': hostContext('ion-toolbar', this.el),
|
||||
'in-toolbar-color': hostContext('ion-toolbar[color]', this.el),
|
||||
'button-has-icon-only': hasIconOnly,
|
||||
'button-disabled': disabled,
|
||||
'ion-activatable': true,
|
||||
@@ -221,9 +219,8 @@ export class Button implements ComponentInterface, AnchorInterface, ButtonInterf
|
||||
disabled={disabled}
|
||||
onFocus={this.onFocus}
|
||||
onBlur={this.onBlur}
|
||||
part="button"
|
||||
>
|
||||
<span class="button-inner" part="button-inner">
|
||||
<span class="button-inner">
|
||||
<slot name="icon-only"></slot>
|
||||
<slot name="start"></slot>
|
||||
<slot></slot>
|
||||
|
||||
@@ -97,6 +97,7 @@ This attribute specifies the size of the button. Setting this attribute will cha
|
||||
import React from 'react';
|
||||
|
||||
import { IonButton, IonIcon, IonContent } from '@ionic/react';
|
||||
import { star } from 'ionicons/icons';
|
||||
|
||||
export const ButtonExample: React.FC = () => (
|
||||
<IonContent>
|
||||
@@ -131,17 +132,17 @@ export const ButtonExample: React.FC = () => (
|
||||
|
||||
{/*-- Icons --*/}
|
||||
<IonButton>
|
||||
<IonIcon slot="start" name="star" />
|
||||
<IonIcon slot="start" icon={star} />
|
||||
Left Icon
|
||||
</IonButton>
|
||||
|
||||
<IonButton>
|
||||
Right Icon
|
||||
<IonIcon slot="end" name="star" />
|
||||
<IonIcon slot="end" icon={star} />
|
||||
</IonButton>
|
||||
|
||||
<IonButton>
|
||||
<IonIcon slot="icon-only" name="star" />
|
||||
<IonIcon slot="icon-only" icon={star} />
|
||||
</IonButton>
|
||||
|
||||
{/*-- Sizes --*/}
|
||||
@@ -154,6 +155,72 @@ export const ButtonExample: React.FC = () => (
|
||||
```
|
||||
|
||||
|
||||
### Stencil
|
||||
|
||||
```tsx
|
||||
import { Component, h } from '@stencil/core';
|
||||
|
||||
@Component({
|
||||
tag: 'button-example',
|
||||
styleUrl: 'button-example.css'
|
||||
})
|
||||
export class ButtonExample {
|
||||
render() {
|
||||
return [
|
||||
// Default
|
||||
<ion-button>Default</ion-button>,
|
||||
|
||||
// Anchor
|
||||
<ion-button href="#">Anchor</ion-button>,
|
||||
|
||||
// Colors
|
||||
<ion-button color="primary">Primary</ion-button>,
|
||||
<ion-button color="secondary">Secondary</ion-button>,
|
||||
<ion-button color="tertiary">Tertiary</ion-button>,
|
||||
<ion-button color="success">Success</ion-button>,
|
||||
<ion-button color="warning">Warning</ion-button>,
|
||||
<ion-button color="danger">Danger</ion-button>,
|
||||
<ion-button color="light">Light</ion-button>,
|
||||
<ion-button color="medium">Medium</ion-button>,
|
||||
<ion-button color="dark">Dark</ion-button>,
|
||||
|
||||
// Expand
|
||||
<ion-button expand="full">Full Button</ion-button>,
|
||||
<ion-button expand="block">Block Button</ion-button>,
|
||||
|
||||
// Round
|
||||
<ion-button shape="round">Round Button</ion-button>,
|
||||
|
||||
// Fill
|
||||
<ion-button expand="full" fill="outline">Outline + Full</ion-button>,
|
||||
<ion-button expand="block" fill="outline">Outline + Block</ion-button>,
|
||||
<ion-button shape="round" fill="outline">Outline + Round</ion-button>,
|
||||
|
||||
// Icons
|
||||
<ion-button>
|
||||
<ion-icon slot="start" name="star"></ion-icon>
|
||||
Left Icon
|
||||
</ion-button>,
|
||||
|
||||
<ion-button>
|
||||
Right Icon
|
||||
<ion-icon slot="end" name="star"></ion-icon>
|
||||
</ion-button>,
|
||||
|
||||
<ion-button>
|
||||
<ion-icon slot="icon-only" name="star"></ion-icon>
|
||||
</ion-button>,
|
||||
|
||||
// Sizes
|
||||
<ion-button size="large">Large</ion-button>,
|
||||
<ion-button>Default</ion-button>,
|
||||
<ion-button size="small">Small</ion-button>
|
||||
];
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
### Vue
|
||||
|
||||
```html
|
||||
|
||||
@@ -23,7 +23,7 @@
|
||||
<ion-button fill="clear">Clear</ion-button>
|
||||
<ion-button color="secondary">Default</ion-button>
|
||||
<ion-button color="tertiary"><ion-icon slot="icon-only" name="star"></ion-icon></ion-button>
|
||||
<ion-button color="danger" shape="round">Round</ion-button>
|
||||
<ion-button color="danger" shape="round" fill="outline">Round</ion-button>
|
||||
<ion-button color="warning" fill="outline">Outline</ion-button>
|
||||
<ion-button color="dark" fill="clear">Clear</ion-button>
|
||||
</p>
|
||||
@@ -37,7 +37,7 @@
|
||||
<ion-button class="ion-focused" fill="clear">Clear</ion-button>
|
||||
<ion-button class="ion-focused" color="secondary">Default</ion-button>
|
||||
<ion-button class="ion-focused" color="tertiary"><ion-icon slot="icon-only" name="star"></ion-icon></ion-button>
|
||||
<ion-button class="ion-focused" color="danger" shape="round">Round</ion-button>
|
||||
<ion-button class="ion-focused" color="danger" shape="round" fill="outline">Round</ion-button>
|
||||
<ion-button class="ion-focused" color="warning" fill="outline">Outline</ion-button>
|
||||
<ion-button class="ion-focused" color="dark" fill="clear">Clear</ion-button>
|
||||
</p>
|
||||
@@ -51,7 +51,7 @@
|
||||
<ion-button class="ion-activated" fill="clear">Clear</ion-button>
|
||||
<ion-button class="ion-activated" color="secondary">Default</ion-button>
|
||||
<ion-button class="ion-activated" color="tertiary"><ion-icon slot="icon-only" name="star"></ion-icon></ion-button>
|
||||
<ion-button class="ion-activated" color="danger" shape="round">Round</ion-button>
|
||||
<ion-button class="ion-activated" color="danger" shape="round" fill="outline">Round</ion-button>
|
||||
<ion-button class="ion-activated" color="warning" fill="outline">Outline</ion-button>
|
||||
<ion-button class="ion-activated" color="dark" fill="clear">Clear</ion-button>
|
||||
</p>
|
||||
@@ -65,7 +65,7 @@
|
||||
<ion-button class="custom" fill="clear">Clear</ion-button>
|
||||
<ion-button class="custom" color="secondary">Default</ion-button>
|
||||
<ion-button class="custom" color="tertiary"><ion-icon slot="icon-only" name="star"></ion-icon></ion-button>
|
||||
<ion-button class="custom" color="danger" shape="round">Round</ion-button>
|
||||
<ion-button class="custom" color="danger" shape="round" fill="outline">Round</ion-button>
|
||||
<ion-button class="custom" color="warning" fill="outline">Outline</ion-button>
|
||||
<ion-button class="custom" color="dark" fill="clear">Clear</ion-button>
|
||||
<ion-button class="custom ion-focused">Default</ion-button>
|
||||
@@ -75,7 +75,7 @@
|
||||
<ion-button class="custom ion-focused" fill="clear">Clear</ion-button>
|
||||
<ion-button class="custom ion-focused" color="secondary">Default</ion-button>
|
||||
<ion-button class="custom ion-focused" color="tertiary"><ion-icon slot="icon-only" name="star"></ion-icon></ion-button>
|
||||
<ion-button class="custom ion-focused" color="danger" shape="round">Round</ion-button>
|
||||
<ion-button class="custom ion-focused" color="danger" shape="round" fill="outline">Round</ion-button>
|
||||
<ion-button class="custom ion-focused" color="warning" fill="outline">Outline</ion-button>
|
||||
<ion-button class="custom ion-focused" color="dark" fill="clear">Clear</ion-button>
|
||||
<ion-button class="custom ion-activated">Default</ion-button>
|
||||
@@ -85,7 +85,7 @@
|
||||
<ion-button class="custom ion-activated" fill="clear">Clear</ion-button>
|
||||
<ion-button class="custom ion-activated" color="secondary">Default</ion-button>
|
||||
<ion-button class="custom ion-activated" color="tertiary"><ion-icon slot="icon-only" name="star"></ion-icon></ion-button>
|
||||
<ion-button class="custom ion-activated" color="danger" shape="round">Round</ion-button>
|
||||
<ion-button class="custom ion-activated" color="danger" shape="round" fill="outline">Round</ion-button>
|
||||
<ion-button class="custom ion-activated" color="warning" fill="outline">Outline</ion-button>
|
||||
<ion-button class="custom ion-activated" color="dark" fill="clear">Clear</ion-button>
|
||||
</p>
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
import React from 'react';
|
||||
|
||||
import { IonButton, IonIcon, IonContent } from '@ionic/react';
|
||||
import { star } from 'ionicons/icons';
|
||||
|
||||
export const ButtonExample: React.FC = () => (
|
||||
<IonContent>
|
||||
@@ -36,17 +37,17 @@ export const ButtonExample: React.FC = () => (
|
||||
|
||||
{/*-- Icons --*/}
|
||||
<IonButton>
|
||||
<IonIcon slot="start" name="star" />
|
||||
<IonIcon slot="start" icon={star} />
|
||||
Left Icon
|
||||
</IonButton>
|
||||
|
||||
<IonButton>
|
||||
Right Icon
|
||||
<IonIcon slot="end" name="star" />
|
||||
<IonIcon slot="end" icon={star} />
|
||||
</IonButton>
|
||||
|
||||
<IonButton>
|
||||
<IonIcon slot="icon-only" name="star" />
|
||||
<IonIcon slot="icon-only" icon={star} />
|
||||
</IonButton>
|
||||
|
||||
{/*-- Sizes --*/}
|
||||
|
||||
62
core/src/components/button/usage/stencil.md
Normal file
62
core/src/components/button/usage/stencil.md
Normal file
@@ -0,0 +1,62 @@
|
||||
```tsx
|
||||
import { Component, h } from '@stencil/core';
|
||||
|
||||
@Component({
|
||||
tag: 'button-example',
|
||||
styleUrl: 'button-example.css'
|
||||
})
|
||||
export class ButtonExample {
|
||||
render() {
|
||||
return [
|
||||
// Default
|
||||
<ion-button>Default</ion-button>,
|
||||
|
||||
// Anchor
|
||||
<ion-button href="#">Anchor</ion-button>,
|
||||
|
||||
// Colors
|
||||
<ion-button color="primary">Primary</ion-button>,
|
||||
<ion-button color="secondary">Secondary</ion-button>,
|
||||
<ion-button color="tertiary">Tertiary</ion-button>,
|
||||
<ion-button color="success">Success</ion-button>,
|
||||
<ion-button color="warning">Warning</ion-button>,
|
||||
<ion-button color="danger">Danger</ion-button>,
|
||||
<ion-button color="light">Light</ion-button>,
|
||||
<ion-button color="medium">Medium</ion-button>,
|
||||
<ion-button color="dark">Dark</ion-button>,
|
||||
|
||||
// Expand
|
||||
<ion-button expand="full">Full Button</ion-button>,
|
||||
<ion-button expand="block">Block Button</ion-button>,
|
||||
|
||||
// Round
|
||||
<ion-button shape="round">Round Button</ion-button>,
|
||||
|
||||
// Fill
|
||||
<ion-button expand="full" fill="outline">Outline + Full</ion-button>,
|
||||
<ion-button expand="block" fill="outline">Outline + Block</ion-button>,
|
||||
<ion-button shape="round" fill="outline">Outline + Round</ion-button>,
|
||||
|
||||
// Icons
|
||||
<ion-button>
|
||||
<ion-icon slot="start" name="star"></ion-icon>
|
||||
Left Icon
|
||||
</ion-button>,
|
||||
|
||||
<ion-button>
|
||||
Right Icon
|
||||
<ion-icon slot="end" name="star"></ion-icon>
|
||||
</ion-button>,
|
||||
|
||||
<ion-button>
|
||||
<ion-icon slot="icon-only" name="star"></ion-icon>
|
||||
</ion-button>,
|
||||
|
||||
// Sizes
|
||||
<ion-button size="large">Large</ion-button>,
|
||||
<ion-button>Default</ion-button>,
|
||||
<ion-button size="small">Small</ion-button>
|
||||
];
|
||||
}
|
||||
}
|
||||
```
|
||||
@@ -17,12 +17,11 @@
|
||||
font-weight: 400;
|
||||
}
|
||||
|
||||
|
||||
|
||||
::slotted(*) ion-button:not(.button-round) {
|
||||
--border-radius: #{$toolbar-ios-button-border-radius};
|
||||
}
|
||||
|
||||
|
||||
// iOS Toolbar with Color: Default Buttons
|
||||
// --------------------------------------------------
|
||||
|
||||
@@ -38,6 +37,8 @@
|
||||
--background-focused-opacity: .12;
|
||||
--background-activated: #000;
|
||||
--background-activated-opacity: .12;
|
||||
--background-hover: #{current-color(base)};
|
||||
--background-hover-opacity: 0.45;
|
||||
--color: #{current-color(base)};
|
||||
--color-focused: #{current-color(base)};
|
||||
}
|
||||
@@ -53,38 +54,21 @@
|
||||
}
|
||||
|
||||
|
||||
// iOS Toolbar Button Clear
|
||||
// iOS Toolbar Button Clear / Outline
|
||||
// --------------------------------------------------
|
||||
|
||||
:host-context(ion-toolbar:not(.ion-color))::slotted(*) .button-clear:not(.ion-color) {
|
||||
--color: #{var(--ion-toolbar-color, ion-color(primary, base))};
|
||||
--color-focused: #{var(--ion-toolbar-color, ion-color(primary, base))};
|
||||
--background-focused: #{var(--ion-toolbar-color, ion-color(primary, base))};
|
||||
}
|
||||
|
||||
|
||||
// iOS Toolbar Button Outline
|
||||
// --------------------------------------------------
|
||||
|
||||
:host-context(ion-toolbar:not(.ion-color))::slotted(*) .button-outline:not(.ion-color) {
|
||||
--color: #{var(--ion-toolbar-color, ion-color(primary, base))};
|
||||
--color-activated: #{var(--ion-toolbar-background, ion-color(primary, contrast))};
|
||||
--color-focused: #{var(--ion-toolbar-color, ion-color(primary, base))};
|
||||
--border-color: #{var(--ion-toolbar-color, ion-color(primary, base))};
|
||||
--background-focused: #{var(--ion-toolbar-color, ion-color(primary, base))};
|
||||
::slotted(*) .button-clear,
|
||||
::slotted(*) .button-outline {
|
||||
--background-activated: transparent;
|
||||
--background-focused: currentColor;
|
||||
--background-hover: transparent;
|
||||
}
|
||||
|
||||
|
||||
// iOS Toolbar Button Solid
|
||||
// --------------------------------------------------
|
||||
|
||||
:host-context(ion-toolbar:not(.ion-color))::slotted(*) .button-solid:not(.ion-color) {
|
||||
--color: #{$toolbar-ios-background};
|
||||
--color-activated: #{$toolbar-ios-background};
|
||||
--color-focused: #{$toolbar-ios-background};
|
||||
--background: #{var(--ion-toolbar-color, ion-color(primary, base))};
|
||||
--background-hover: #{var(--ion-toolbar-background, ion-color(primary, contrast))};
|
||||
--background-hover-opacity: 0.1;
|
||||
::slotted(*) .button-solid:not(.ion-color) {
|
||||
--background-focused: #000;
|
||||
--background-focused-opacity: .12;
|
||||
--background-activated: #000;
|
||||
@@ -117,29 +101,7 @@
|
||||
@include padding(0);
|
||||
@include margin(0);
|
||||
|
||||
font-size: 31px;
|
||||
font-size: 28px;
|
||||
|
||||
line-height: .67;
|
||||
}
|
||||
|
||||
|
||||
// iOS Toolbar Menu Toggle
|
||||
// --------------------------------------------------
|
||||
|
||||
// .button-menutoggle-ios {
|
||||
// order: map-get($toolbar-order-ios, menu-toggle-start);
|
||||
|
||||
// min-width: 36px;
|
||||
|
||||
// --padding-top: 0;
|
||||
// --padding-bottom: 0;
|
||||
// --padding-start: 0;
|
||||
// --padding-end: 0;
|
||||
|
||||
// ion-icon {
|
||||
// @include padding(0, 6px);
|
||||
|
||||
// font-size: 28px;
|
||||
// }
|
||||
// }
|
||||
|
||||
|
||||
@@ -77,7 +77,6 @@
|
||||
|
||||
::slotted(*) .button-solid {
|
||||
--color: #{$toolbar-md-background};
|
||||
--color-activated: #{$toolbar-md-background};
|
||||
--background: #{$toolbar-md-color};
|
||||
--background-activated: transparent;
|
||||
--background-focused: currentColor;
|
||||
@@ -89,13 +88,11 @@
|
||||
|
||||
::slotted(*) .button-outline {
|
||||
--color: initial;
|
||||
--color-activated: currentColor;
|
||||
--color-focused: #{$toolbar-md-color};
|
||||
--background: transparent;
|
||||
--background-activated: transparent;
|
||||
--background-focused: currentColor;
|
||||
--background-hover: currentColor;
|
||||
--border-color: #{$toolbar-md-color};
|
||||
--border-color: currentColor;
|
||||
}
|
||||
|
||||
|
||||
@@ -104,8 +101,6 @@
|
||||
|
||||
::slotted(*) .button-clear {
|
||||
--color: initial;
|
||||
--color-focused: #{$toolbar-md-color};
|
||||
--color-activated: currentColor;
|
||||
--background: transparent;
|
||||
--background-activated: transparent;
|
||||
--background-focused: currentColor;
|
||||
|
||||
@@ -125,16 +125,8 @@ The `<ion-buttons>` element can be positioned inside of the toolbar using a name
|
||||
|
||||
```tsx
|
||||
import React from 'react';
|
||||
import {
|
||||
IonButtons,
|
||||
IonToolbar,
|
||||
IonBackButton,
|
||||
IonTitle,
|
||||
IonButton,
|
||||
IonIcon,
|
||||
IonMenuButton,
|
||||
IonContent
|
||||
} from '@ionic/react';
|
||||
import { IonButtons, IonToolbar, IonBackButton, IonTitle, IonButton, IonIcon, IonMenuButton, IonContent } from '@ionic/react';
|
||||
import { personCircle, search, star, ellipsisHorizontal, ellipsisVertical } from 'ionicons/icons';
|
||||
|
||||
export const ButtonsExample: React.FC = () => (
|
||||
<IonContent>
|
||||
@@ -148,16 +140,16 @@ export const ButtonsExample: React.FC = () => (
|
||||
<IonToolbar>
|
||||
<IonButtons slot="secondary">
|
||||
<IonButton>
|
||||
<IonIcon slot="icon-only" name="person-circle" />
|
||||
<IonIcon slot="icon-only" icon={personCircle} />
|
||||
</IonButton>
|
||||
<IonButton>
|
||||
<IonIcon slot="icon-only" name="search" />
|
||||
<IonIcon slot="icon-only" icon={search} />
|
||||
</IonButton>
|
||||
</IonButtons>
|
||||
<IonTitle>Default Buttons</IonTitle>
|
||||
<IonButtons slot="primary">
|
||||
<IonButton color="secondary">
|
||||
<IonIcon slot="icon-only" ios="ellipsis-horizontal" md="ellipsis-vertical" />
|
||||
<IonIcon slot="icon-only" ios={ellipsisHorizontal} md={ellipsisVertical} />
|
||||
</IonButton>
|
||||
</IonButtons>
|
||||
</IonToolbar>
|
||||
@@ -165,7 +157,7 @@ export const ButtonsExample: React.FC = () => (
|
||||
<IonToolbar>
|
||||
<IonButtons slot="primary">
|
||||
<IonButton onClick={() => {}}>
|
||||
<IonIcon slot="icon-only" name="star" />
|
||||
<IonIcon slot="icon-only" icon={star} />
|
||||
</IonButton>
|
||||
</IonButtons>
|
||||
<IonTitle>Right side menu toggle</IonTitle>
|
||||
@@ -177,7 +169,7 @@ export const ButtonsExample: React.FC = () => (
|
||||
<IonToolbar>
|
||||
<IonButtons collapse="true">
|
||||
<IonButton>
|
||||
<IonIcon slot="icon-only" name="star" />
|
||||
<IonIcon slot="icon-only" icon={star} />
|
||||
</IonButton>
|
||||
</IonButtons>
|
||||
<IonTitle>Collapsible Buttons</IonTitle>
|
||||
@@ -187,6 +179,73 @@ export const ButtonsExample: React.FC = () => (
|
||||
```
|
||||
|
||||
|
||||
### Stencil
|
||||
|
||||
```tsx
|
||||
import { Component, h } from '@stencil/core';
|
||||
|
||||
@Component({
|
||||
tag: 'buttons-example',
|
||||
styleUrl: 'buttons-example.css'
|
||||
})
|
||||
export class ButtonsExample {
|
||||
|
||||
clickedStar() {
|
||||
console.log("Clicked star button");
|
||||
}
|
||||
|
||||
render() {
|
||||
return [
|
||||
<ion-toolbar>
|
||||
<ion-buttons slot="start">
|
||||
<ion-back-button></ion-back-button>
|
||||
</ion-buttons>
|
||||
<ion-title>Back Button</ion-title>
|
||||
</ion-toolbar>,
|
||||
|
||||
<ion-toolbar>
|
||||
<ion-buttons slot="secondary">
|
||||
<ion-button>
|
||||
<ion-icon slot="icon-only" name="person-circle"></ion-icon>
|
||||
</ion-button>
|
||||
<ion-button>
|
||||
<ion-icon slot="icon-only" name="search"></ion-icon>
|
||||
</ion-button>
|
||||
</ion-buttons>
|
||||
<ion-title>Default Buttons</ion-title>
|
||||
<ion-buttons slot="primary">
|
||||
<ion-button color="secondary">
|
||||
<ion-icon slot="icon-only" ios="ellipsis-horizontal" md="ellipsis-vertical"></ion-icon>
|
||||
</ion-button>
|
||||
</ion-buttons>
|
||||
</ion-toolbar>,
|
||||
|
||||
<ion-toolbar>
|
||||
<ion-buttons slot="primary">
|
||||
<ion-button onClick={() => this.clickedStar()}>
|
||||
<ion-icon slot="icon-only" name="star"></ion-icon>
|
||||
</ion-button>
|
||||
</ion-buttons>
|
||||
<ion-title>Right side menu toggle</ion-title>
|
||||
<ion-buttons slot="end">
|
||||
<ion-menu-button autoHide={false}></ion-menu-button>
|
||||
</ion-buttons>
|
||||
</ion-toolbar>,
|
||||
|
||||
<ion-toolbar>
|
||||
<ion-buttons collapse={true}>
|
||||
<ion-button>
|
||||
<ion-icon slot="icon-only" name="star"></ion-icon>
|
||||
</ion-button>
|
||||
</ion-buttons>
|
||||
<ion-title>Collapsible Buttons</ion-title>
|
||||
</ion-toolbar>
|
||||
];
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
### Vue
|
||||
|
||||
```html
|
||||
|
||||
@@ -1,15 +1,7 @@
|
||||
```tsx
|
||||
import React from 'react';
|
||||
import {
|
||||
IonButtons,
|
||||
IonToolbar,
|
||||
IonBackButton,
|
||||
IonTitle,
|
||||
IonButton,
|
||||
IonIcon,
|
||||
IonMenuButton,
|
||||
IonContent
|
||||
} from '@ionic/react';
|
||||
import { IonButtons, IonToolbar, IonBackButton, IonTitle, IonButton, IonIcon, IonMenuButton, IonContent } from '@ionic/react';
|
||||
import { personCircle, search, star, ellipsisHorizontal, ellipsisVertical } from 'ionicons/icons';
|
||||
|
||||
export const ButtonsExample: React.FC = () => (
|
||||
<IonContent>
|
||||
@@ -23,16 +15,16 @@ export const ButtonsExample: React.FC = () => (
|
||||
<IonToolbar>
|
||||
<IonButtons slot="secondary">
|
||||
<IonButton>
|
||||
<IonIcon slot="icon-only" name="person-circle" />
|
||||
<IonIcon slot="icon-only" icon={personCircle} />
|
||||
</IonButton>
|
||||
<IonButton>
|
||||
<IonIcon slot="icon-only" name="search" />
|
||||
<IonIcon slot="icon-only" icon={search} />
|
||||
</IonButton>
|
||||
</IonButtons>
|
||||
<IonTitle>Default Buttons</IonTitle>
|
||||
<IonButtons slot="primary">
|
||||
<IonButton color="secondary">
|
||||
<IonIcon slot="icon-only" ios="ellipsis-horizontal" md="ellipsis-vertical" />
|
||||
<IonIcon slot="icon-only" ios={ellipsisHorizontal} md={ellipsisVertical} />
|
||||
</IonButton>
|
||||
</IonButtons>
|
||||
</IonToolbar>
|
||||
@@ -40,7 +32,7 @@ export const ButtonsExample: React.FC = () => (
|
||||
<IonToolbar>
|
||||
<IonButtons slot="primary">
|
||||
<IonButton onClick={() => {}}>
|
||||
<IonIcon slot="icon-only" name="star" />
|
||||
<IonIcon slot="icon-only" icon={star} />
|
||||
</IonButton>
|
||||
</IonButtons>
|
||||
<IonTitle>Right side menu toggle</IonTitle>
|
||||
@@ -52,7 +44,7 @@ export const ButtonsExample: React.FC = () => (
|
||||
<IonToolbar>
|
||||
<IonButtons collapse="true">
|
||||
<IonButton>
|
||||
<IonIcon slot="icon-only" name="star" />
|
||||
<IonIcon slot="icon-only" icon={star} />
|
||||
</IonButton>
|
||||
</IonButtons>
|
||||
<IonTitle>Collapsible Buttons</IonTitle>
|
||||
|
||||
63
core/src/components/buttons/usage/stencil.md
Normal file
63
core/src/components/buttons/usage/stencil.md
Normal file
@@ -0,0 +1,63 @@
|
||||
```tsx
|
||||
import { Component, h } from '@stencil/core';
|
||||
|
||||
@Component({
|
||||
tag: 'buttons-example',
|
||||
styleUrl: 'buttons-example.css'
|
||||
})
|
||||
export class ButtonsExample {
|
||||
|
||||
clickedStar() {
|
||||
console.log("Clicked star button");
|
||||
}
|
||||
|
||||
render() {
|
||||
return [
|
||||
<ion-toolbar>
|
||||
<ion-buttons slot="start">
|
||||
<ion-back-button></ion-back-button>
|
||||
</ion-buttons>
|
||||
<ion-title>Back Button</ion-title>
|
||||
</ion-toolbar>,
|
||||
|
||||
<ion-toolbar>
|
||||
<ion-buttons slot="secondary">
|
||||
<ion-button>
|
||||
<ion-icon slot="icon-only" name="person-circle"></ion-icon>
|
||||
</ion-button>
|
||||
<ion-button>
|
||||
<ion-icon slot="icon-only" name="search"></ion-icon>
|
||||
</ion-button>
|
||||
</ion-buttons>
|
||||
<ion-title>Default Buttons</ion-title>
|
||||
<ion-buttons slot="primary">
|
||||
<ion-button color="secondary">
|
||||
<ion-icon slot="icon-only" ios="ellipsis-horizontal" md="ellipsis-vertical"></ion-icon>
|
||||
</ion-button>
|
||||
</ion-buttons>
|
||||
</ion-toolbar>,
|
||||
|
||||
<ion-toolbar>
|
||||
<ion-buttons slot="primary">
|
||||
<ion-button onClick={() => this.clickedStar()}>
|
||||
<ion-icon slot="icon-only" name="star"></ion-icon>
|
||||
</ion-button>
|
||||
</ion-buttons>
|
||||
<ion-title>Right side menu toggle</ion-title>
|
||||
<ion-buttons slot="end">
|
||||
<ion-menu-button autoHide={false}></ion-menu-button>
|
||||
</ion-buttons>
|
||||
</ion-toolbar>,
|
||||
|
||||
<ion-toolbar>
|
||||
<ion-buttons collapse={true}>
|
||||
<ion-button>
|
||||
<ion-icon slot="icon-only" name="star"></ion-icon>
|
||||
</ion-button>
|
||||
</ion-buttons>
|
||||
<ion-title>Collapsible Buttons</ion-title>
|
||||
</ion-toolbar>
|
||||
];
|
||||
}
|
||||
}
|
||||
```
|
||||
@@ -65,7 +65,7 @@
|
||||
|
||||
outline: none;
|
||||
|
||||
background: var(--background);
|
||||
background: inherit;
|
||||
}
|
||||
|
||||
.card-native::-moz-focus-inner {
|
||||
|
||||
@@ -67,58 +67,133 @@ sub-components to reflect this. Please see `ion-card-content`,
|
||||
|
||||
```tsx
|
||||
import React from 'react';
|
||||
import { IonButton, IonCard, IonCardContent, IonCardHeader, IonCardSubtitle, IonCardTitle, IonContent, IonIcon, IonItem, IonLabel } from '@ionic/react';
|
||||
import { IonContent, IonHeader, IonPage, IonTitle, IonToolbar, IonCard, IonCardHeader, IonCardSubtitle, IonCardTitle, IonCardContent, IonItem, IonIcon, IonLabel, IonButton } from '@ionic/react';
|
||||
import { pin, wifi, wine, warning, walk } from 'ionicons/icons';
|
||||
|
||||
export const CardExample: React.FC = () => (
|
||||
<IonContent>
|
||||
<IonCard>
|
||||
<IonCardHeader>
|
||||
<IonCardSubtitle>Card Subtitle</IonCardSubtitle>
|
||||
<IonCardTitle>Card Title</IonCardTitle>
|
||||
</IonCardHeader>
|
||||
export const CardExamples: React.FC = () => {
|
||||
return (
|
||||
<IonPage>
|
||||
<IonHeader>
|
||||
<IonToolbar>
|
||||
<IonTitle>CardExamples</IonTitle>
|
||||
</IonToolbar>
|
||||
</IonHeader>
|
||||
<IonContent>
|
||||
<IonCard>
|
||||
<IonCardHeader>
|
||||
<IonCardSubtitle>Card Subtitle</IonCardSubtitle>
|
||||
<IonCardTitle>Card Title</IonCardTitle>
|
||||
</IonCardHeader>
|
||||
|
||||
<IonCardContent>
|
||||
Keep close to Nature's heart... and break clear away, once in awhile,
|
||||
and climb a mountain or spend a week in the woods. Wash your spirit clean.
|
||||
<IonCardContent>
|
||||
Keep close to Nature's heart... and break clear away, once in awhile,
|
||||
and climb a mountain or spend a week in the woods. Wash your spirit clean.
|
||||
</IonCardContent>
|
||||
</IonCard>
|
||||
</IonCard>
|
||||
|
||||
<IonCard>
|
||||
<IonItem>
|
||||
<IonIcon name="pin" slot="start" />
|
||||
<IonLabel>ion-item in a card, icon left, button right</IonLabel>
|
||||
<IonButton fill="outline" slot="end">View</IonButton>
|
||||
</IonItem>
|
||||
<IonCard>
|
||||
<IonItem>
|
||||
<IonIcon icon={pin} slot="start" />
|
||||
<IonLabel>ion-item in a card, icon left, button right</IonLabel>
|
||||
<IonButton fill="outline" slot="end">View</IonButton>
|
||||
</IonItem>
|
||||
|
||||
<IonCardContent>
|
||||
This is content, without any paragraph or header tags,
|
||||
within an ion-cardContent element.
|
||||
<IonCardContent>
|
||||
This is content, without any paragraph or header tags,
|
||||
within an ion-cardContent element.
|
||||
</IonCardContent>
|
||||
</IonCard>
|
||||
</IonCard>
|
||||
|
||||
<IonCard>
|
||||
<IonItem href="#" className="ion-activated">
|
||||
<IonIcon name="wifi" slot="start" />
|
||||
<IonLabel>Card Link Item 1 activated</IonLabel>
|
||||
</IonItem>
|
||||
<IonCard>
|
||||
<IonItem href="#" className="ion-activated">
|
||||
<IonIcon icon={wifi} slot="start" />
|
||||
<IonLabel>Card Link Item 1 activated</IonLabel>
|
||||
</IonItem>
|
||||
|
||||
<IonItem href="#">
|
||||
<IonIcon name="wine" slot="start" />
|
||||
<IonLabel>Card Link Item 2</IonLabel>
|
||||
</IonItem>
|
||||
<IonItem href="#">
|
||||
<IonIcon icon={wine} slot="start" />
|
||||
<IonLabel>Card Link Item 2</IonLabel>
|
||||
</IonItem>
|
||||
|
||||
<IonItem className="ion-activated">
|
||||
<IonIcon name="warning" slot="start" />
|
||||
<IonLabel>Card Button Item 1 activated</IonLabel>
|
||||
</IonItem>
|
||||
<IonItem className="ion-activated">
|
||||
<IonIcon icon={warning} slot="start" />
|
||||
<IonLabel>Card Button Item 1 activated</IonLabel>
|
||||
</IonItem>
|
||||
|
||||
<IonItem>
|
||||
<IonIcon name="walk" slot="start" />
|
||||
<IonLabel>Card Button Item 2</IonLabel>
|
||||
</IonItem>
|
||||
</IonCard>
|
||||
</IonContent>
|
||||
);
|
||||
<IonItem>
|
||||
<IonIcon icon={walk} slot="start" />
|
||||
<IonLabel>Card Button Item 2</IonLabel>
|
||||
</IonItem>
|
||||
</IonCard>
|
||||
</IonContent>
|
||||
</IonPage>
|
||||
);
|
||||
};
|
||||
|
||||
```
|
||||
|
||||
|
||||
### Stencil
|
||||
|
||||
```tsx
|
||||
import { Component, h } from '@stencil/core';
|
||||
|
||||
@Component({
|
||||
tag: 'card-example',
|
||||
styleUrl: 'card-example.css'
|
||||
})
|
||||
export class CardExample {
|
||||
render() {
|
||||
return [
|
||||
<ion-card>
|
||||
<ion-card-header>
|
||||
<ion-card-subtitle>Card Subtitle</ion-card-subtitle>
|
||||
<ion-card-title>Card Title</ion-card-title>
|
||||
</ion-card-header>
|
||||
|
||||
<ion-card-content>
|
||||
Keep close to Nature's heart... and break clear away, once in awhile,
|
||||
and climb a mountain or spend a week in the woods. Wash your spirit clean.
|
||||
</ion-card-content>
|
||||
</ion-card>,
|
||||
|
||||
<ion-card>
|
||||
<ion-item>
|
||||
<ion-icon name="pin" slot="start"></ion-icon>
|
||||
<ion-label>ion-item in a card, icon left, button right</ion-label>
|
||||
<ion-button fill="outline" slot="end">View</ion-button>
|
||||
</ion-item>
|
||||
|
||||
<ion-card-content>
|
||||
This is content, without any paragraph or header tags,
|
||||
within an ion-card-content element.
|
||||
</ion-card-content>
|
||||
</ion-card>,
|
||||
|
||||
<ion-card>
|
||||
<ion-item href="#" class="ion-activated">
|
||||
<ion-icon name="wifi" slot="start"></ion-icon>
|
||||
<ion-label>Card Link Item 1 activated</ion-label>
|
||||
</ion-item>
|
||||
|
||||
<ion-item href="#">
|
||||
<ion-icon name="wine" slot="start"></ion-icon>
|
||||
<ion-label>Card Link Item 2</ion-label>
|
||||
</ion-item>
|
||||
|
||||
<ion-item class="ion-activated">
|
||||
<ion-icon name="warning" slot="start"></ion-icon>
|
||||
<ion-label>Card Button Item 1 activated</ion-label>
|
||||
</ion-item>
|
||||
|
||||
<ion-item>
|
||||
<ion-icon name="walk" slot="start"></ion-icon>
|
||||
<ion-label>Card Button Item 2</ion-label>
|
||||
</ion-item>
|
||||
</ion-card>
|
||||
];
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
|
||||
@@ -50,6 +50,33 @@
|
||||
</ion-card-content>
|
||||
</ion-card>
|
||||
|
||||
<ion-card button color="tertiary">
|
||||
<ion-card-header>
|
||||
<ion-card-subtitle>
|
||||
Subtitle
|
||||
</ion-card-subtitle>
|
||||
<ion-card-title>
|
||||
Button Card
|
||||
</ion-card-title>
|
||||
</ion-card-header>
|
||||
|
||||
<ion-card-content>
|
||||
This is content, inside of a card with a button attribute.
|
||||
</ion-card-content>
|
||||
</ion-card>
|
||||
|
||||
<ion-card href="#" color="warning">
|
||||
<ion-card-header>
|
||||
<ion-card-title>
|
||||
Anchor Card
|
||||
</ion-card-title>
|
||||
</ion-card-header>
|
||||
|
||||
<ion-card-content>
|
||||
This is content, inside of a card with a href attribute.
|
||||
</ion-card-content>
|
||||
</ion-card>
|
||||
|
||||
<ion-card button>
|
||||
<div style="position: absolute; top: 0; left:0; right:0; bottom:0;">
|
||||
<img src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAHwAAAB8AQAAAACDZekTAAABMElEQVR4AWLABZjQBdjRBfgb0ATkD6AJ2D9AE6j/gCbw/weAyzk2IwAKwBgIixvNKPaA+P7yXplUZ1/7OO79DkYdjHrIqKeMeskoISXkWkLuBWSMkhGQMYCMAWQMISVkDCBjDCKjZAAZA8gYQMYAUkLGaBAZg8goGYPIGATGIDAGgTEIjEFgDCKjZAwiYxAYg8AYBMYgMAaBMYiMkjGIjEHGSMgYQErIGEDGAAKjZAwyhpAxgIwB5F9nvVsBCAUgDC3Zf2MGuCe1+r6QyBuMwSysg5WyF3bLeXBinCmnzr1wc9wtt08+SBAZI4XklCSTddpAX2gUnaOV9JZm033oAD8gDAyCUnAM0sFCaAlPIS5MhtpwHfLjBuyBXzAQjsJieE4T6kptqm81ss7W6ss/gwMyz60frEbR8QAAAABJRU5ErkJggg==">
|
||||
|
||||
@@ -1,55 +1,66 @@
|
||||
```tsx
|
||||
import React from 'react';
|
||||
import { IonButton, IonCard, IonCardContent, IonCardHeader, IonCardSubtitle, IonCardTitle, IonContent, IonIcon, IonItem, IonLabel } from '@ionic/react';
|
||||
import { IonContent, IonHeader, IonPage, IonTitle, IonToolbar, IonCard, IonCardHeader, IonCardSubtitle, IonCardTitle, IonCardContent, IonItem, IonIcon, IonLabel, IonButton } from '@ionic/react';
|
||||
import { pin, wifi, wine, warning, walk } from 'ionicons/icons';
|
||||
|
||||
export const CardExample: React.FC = () => (
|
||||
<IonContent>
|
||||
<IonCard>
|
||||
<IonCardHeader>
|
||||
<IonCardSubtitle>Card Subtitle</IonCardSubtitle>
|
||||
<IonCardTitle>Card Title</IonCardTitle>
|
||||
</IonCardHeader>
|
||||
export const CardExamples: React.FC = () => {
|
||||
return (
|
||||
<IonPage>
|
||||
<IonHeader>
|
||||
<IonToolbar>
|
||||
<IonTitle>CardExamples</IonTitle>
|
||||
</IonToolbar>
|
||||
</IonHeader>
|
||||
<IonContent>
|
||||
<IonCard>
|
||||
<IonCardHeader>
|
||||
<IonCardSubtitle>Card Subtitle</IonCardSubtitle>
|
||||
<IonCardTitle>Card Title</IonCardTitle>
|
||||
</IonCardHeader>
|
||||
|
||||
<IonCardContent>
|
||||
Keep close to Nature's heart... and break clear away, once in awhile,
|
||||
and climb a mountain or spend a week in the woods. Wash your spirit clean.
|
||||
<IonCardContent>
|
||||
Keep close to Nature's heart... and break clear away, once in awhile,
|
||||
and climb a mountain or spend a week in the woods. Wash your spirit clean.
|
||||
</IonCardContent>
|
||||
</IonCard>
|
||||
</IonCard>
|
||||
|
||||
<IonCard>
|
||||
<IonItem>
|
||||
<IonIcon name="pin" slot="start" />
|
||||
<IonLabel>ion-item in a card, icon left, button right</IonLabel>
|
||||
<IonButton fill="outline" slot="end">View</IonButton>
|
||||
</IonItem>
|
||||
<IonCard>
|
||||
<IonItem>
|
||||
<IonIcon icon={pin} slot="start" />
|
||||
<IonLabel>ion-item in a card, icon left, button right</IonLabel>
|
||||
<IonButton fill="outline" slot="end">View</IonButton>
|
||||
</IonItem>
|
||||
|
||||
<IonCardContent>
|
||||
This is content, without any paragraph or header tags,
|
||||
within an ion-cardContent element.
|
||||
<IonCardContent>
|
||||
This is content, without any paragraph or header tags,
|
||||
within an ion-cardContent element.
|
||||
</IonCardContent>
|
||||
</IonCard>
|
||||
</IonCard>
|
||||
|
||||
<IonCard>
|
||||
<IonItem href="#" className="ion-activated">
|
||||
<IonIcon name="wifi" slot="start" />
|
||||
<IonLabel>Card Link Item 1 activated</IonLabel>
|
||||
</IonItem>
|
||||
<IonCard>
|
||||
<IonItem href="#" className="ion-activated">
|
||||
<IonIcon icon={wifi} slot="start" />
|
||||
<IonLabel>Card Link Item 1 activated</IonLabel>
|
||||
</IonItem>
|
||||
|
||||
<IonItem href="#">
|
||||
<IonIcon name="wine" slot="start" />
|
||||
<IonLabel>Card Link Item 2</IonLabel>
|
||||
</IonItem>
|
||||
<IonItem href="#">
|
||||
<IonIcon icon={wine} slot="start" />
|
||||
<IonLabel>Card Link Item 2</IonLabel>
|
||||
</IonItem>
|
||||
|
||||
<IonItem className="ion-activated">
|
||||
<IonIcon name="warning" slot="start" />
|
||||
<IonLabel>Card Button Item 1 activated</IonLabel>
|
||||
</IonItem>
|
||||
<IonItem className="ion-activated">
|
||||
<IonIcon icon={warning} slot="start" />
|
||||
<IonLabel>Card Button Item 1 activated</IonLabel>
|
||||
</IonItem>
|
||||
|
||||
<IonItem>
|
||||
<IonIcon icon={walk} slot="start" />
|
||||
<IonLabel>Card Button Item 2</IonLabel>
|
||||
</IonItem>
|
||||
</IonCard>
|
||||
</IonContent>
|
||||
</IonPage>
|
||||
);
|
||||
};
|
||||
|
||||
<IonItem>
|
||||
<IonIcon name="walk" slot="start" />
|
||||
<IonLabel>Card Button Item 2</IonLabel>
|
||||
</IonItem>
|
||||
</IonCard>
|
||||
</IonContent>
|
||||
);
|
||||
```
|
||||
60
core/src/components/card/usage/stencil.md
Normal file
60
core/src/components/card/usage/stencil.md
Normal file
@@ -0,0 +1,60 @@
|
||||
```tsx
|
||||
import { Component, h } from '@stencil/core';
|
||||
|
||||
@Component({
|
||||
tag: 'card-example',
|
||||
styleUrl: 'card-example.css'
|
||||
})
|
||||
export class CardExample {
|
||||
render() {
|
||||
return [
|
||||
<ion-card>
|
||||
<ion-card-header>
|
||||
<ion-card-subtitle>Card Subtitle</ion-card-subtitle>
|
||||
<ion-card-title>Card Title</ion-card-title>
|
||||
</ion-card-header>
|
||||
|
||||
<ion-card-content>
|
||||
Keep close to Nature's heart... and break clear away, once in awhile,
|
||||
and climb a mountain or spend a week in the woods. Wash your spirit clean.
|
||||
</ion-card-content>
|
||||
</ion-card>,
|
||||
|
||||
<ion-card>
|
||||
<ion-item>
|
||||
<ion-icon name="pin" slot="start"></ion-icon>
|
||||
<ion-label>ion-item in a card, icon left, button right</ion-label>
|
||||
<ion-button fill="outline" slot="end">View</ion-button>
|
||||
</ion-item>
|
||||
|
||||
<ion-card-content>
|
||||
This is content, without any paragraph or header tags,
|
||||
within an ion-card-content element.
|
||||
</ion-card-content>
|
||||
</ion-card>,
|
||||
|
||||
<ion-card>
|
||||
<ion-item href="#" class="ion-activated">
|
||||
<ion-icon name="wifi" slot="start"></ion-icon>
|
||||
<ion-label>Card Link Item 1 activated</ion-label>
|
||||
</ion-item>
|
||||
|
||||
<ion-item href="#">
|
||||
<ion-icon name="wine" slot="start"></ion-icon>
|
||||
<ion-label>Card Link Item 2</ion-label>
|
||||
</ion-item>
|
||||
|
||||
<ion-item class="ion-activated">
|
||||
<ion-icon name="warning" slot="start"></ion-icon>
|
||||
<ion-label>Card Button Item 1 activated</ion-label>
|
||||
</ion-item>
|
||||
|
||||
<ion-item>
|
||||
<ion-icon name="walk" slot="start"></ion-icon>
|
||||
<ion-label>Card Button Item 2</ion-label>
|
||||
</ion-item>
|
||||
</ion-card>
|
||||
];
|
||||
}
|
||||
}
|
||||
```
|
||||
@@ -7,6 +7,9 @@ import { createColorClasses, hostContext } from '../../utils/theme';
|
||||
|
||||
/**
|
||||
* @virtualProp {"ios" | "md"} mode - The mode determines which platform styles to use.
|
||||
*
|
||||
* @part container - The container for the checkbox mark.
|
||||
* @part mark - The checkmark used to indicate the checked state.
|
||||
*/
|
||||
@Component({
|
||||
tag: 'ion-checkbox',
|
||||
@@ -136,13 +139,13 @@ export class Checkbox implements ComponentInterface {
|
||||
renderHiddenInput(true, el, this.name, (checked ? value : ''), disabled);
|
||||
|
||||
let path = indeterminate
|
||||
? <path d="M6 12L18 12"/>
|
||||
: <path d="M5.9,12.5l3.8,3.8l8.8-8.8" />;
|
||||
? <path d="M6 12L18 12" part="mark" />
|
||||
: <path d="M5.9,12.5l3.8,3.8l8.8-8.8" part="mark" />;
|
||||
|
||||
if (mode === 'md') {
|
||||
path = indeterminate
|
||||
? <path d="M2 12H22"/>
|
||||
: <path d="M1.73,12.91 8.1,19.28 22.79,4.59"/>;
|
||||
? <path d="M2 12H22" part="mark" />
|
||||
: <path d="M1.73,12.91 8.1,19.28 22.79,4.59" part="mark" />;
|
||||
}
|
||||
|
||||
return (
|
||||
@@ -162,7 +165,7 @@ export class Checkbox implements ComponentInterface {
|
||||
'interactive': true
|
||||
}}
|
||||
>
|
||||
<svg class="checkbox-icon" viewBox="0 0 24 24">
|
||||
<svg class="checkbox-icon" viewBox="0 0 24 24" part="container">
|
||||
{path}
|
||||
</svg>
|
||||
<button
|
||||
|
||||
@@ -98,44 +98,107 @@ export class HomePage {
|
||||
### React
|
||||
|
||||
```tsx
|
||||
import React from 'react';
|
||||
import { IonCheckbox, IonList, IonItem, IonLabel, IonContent } from '@ionic/react';
|
||||
import React, { useState } from 'react';
|
||||
import { IonContent, IonHeader, IonPage, IonTitle, IonToolbar, IonCheckbox, IonList, IonItem, IonLabel, IonItemDivider } from '@ionic/react';
|
||||
|
||||
const form = [
|
||||
const checkboxList = [
|
||||
{ val: 'Pepperoni', isChecked: true },
|
||||
{ val: 'Sausage', isChecked: false },
|
||||
{ val: 'Mushroom', isChecked: false }
|
||||
];
|
||||
|
||||
export const CheckboxExample: React.FC = () => (
|
||||
<IonContent>
|
||||
{/*-- Default Checkbox --*/}
|
||||
<IonCheckbox />
|
||||
export const CheckboxExamples: React.FC = () => {
|
||||
|
||||
{/*-- Disabled Checkbox --*/}
|
||||
<IonCheckbox disabled={true} />
|
||||
const [checked, setChecked] = useState(false);
|
||||
|
||||
{/*-- Checked Checkbox --*/}
|
||||
<IonCheckbox checked={true} />
|
||||
return (
|
||||
<IonPage>
|
||||
<IonHeader>
|
||||
<IonToolbar>
|
||||
<IonTitle>CheckboxExamples</IonTitle>
|
||||
</IonToolbar>
|
||||
</IonHeader>
|
||||
<IonContent>
|
||||
<IonList>
|
||||
<IonItemDivider>Default Checkbox</IonItemDivider>
|
||||
<IonItem>
|
||||
<IonLabel>Checked: {JSON.stringify(checked)}</IonLabel>
|
||||
<IonCheckbox checked={checked} onIonChange={e => setChecked(e.detail.checked)} />
|
||||
</IonItem>
|
||||
|
||||
{/*-- Checkbox Colors --*/}
|
||||
<IonCheckbox color="primary" />
|
||||
<IonCheckbox color="secondary" />
|
||||
<IonCheckbox color="danger" />
|
||||
<IonCheckbox color="light" />
|
||||
<IonCheckbox color="dark" />
|
||||
<IonItemDivider>Disabled Checkbox</IonItemDivider>
|
||||
<IonItem><IonCheckbox slot="end" disabled={true} /></IonItem>
|
||||
|
||||
{/*-- Checkboxes in a List --*/}
|
||||
<IonList>
|
||||
{ form.map(({val, isChecked}) => (
|
||||
<IonItem key={val}>
|
||||
<IonLabel>{val}</IonLabel>
|
||||
<IonCheckbox slot="end" value={val} checked={isChecked} />
|
||||
</IonItem>
|
||||
)) }
|
||||
</IonList>
|
||||
</IonContent>
|
||||
);
|
||||
<IonItemDivider>Checkbox Colors</IonItemDivider>
|
||||
<IonItem>
|
||||
<IonCheckbox slot="end" color="primary" />
|
||||
<IonCheckbox slot="end" color="secondary" />
|
||||
<IonCheckbox slot="end" color="danger" />
|
||||
<IonCheckbox slot="end" color="light" />
|
||||
<IonCheckbox slot="end" color="dark" />
|
||||
</IonItem>
|
||||
<IonItemDivider>Checkboxes in a List</IonItemDivider>
|
||||
|
||||
{checkboxList.map(({ val, isChecked }, i) => (
|
||||
<IonItem key={i}>
|
||||
<IonLabel>{val}</IonLabel>
|
||||
<IonCheckbox slot="end" value={val} checked={isChecked} />
|
||||
</IonItem>
|
||||
))}
|
||||
</IonList>
|
||||
</IonContent>
|
||||
</IonPage>
|
||||
);
|
||||
};
|
||||
```
|
||||
|
||||
|
||||
### Stencil
|
||||
|
||||
```tsx
|
||||
import { Component, h } from '@stencil/core';
|
||||
|
||||
@Component({
|
||||
tag: 'checkbox-example',
|
||||
styleUrl: 'checkbox-example.css'
|
||||
})
|
||||
export class CheckboxExample {
|
||||
private form = [
|
||||
{ val: 'Pepperoni', isChecked: true },
|
||||
{ val: 'Sausage', isChecked: false },
|
||||
{ val: 'Mushroom', isChecked: false }
|
||||
];
|
||||
|
||||
render() {
|
||||
return [
|
||||
// Default Checkbox
|
||||
<ion-checkbox></ion-checkbox>,
|
||||
|
||||
// Disabled Checkbox
|
||||
<ion-checkbox disabled={true}></ion-checkbox>,
|
||||
|
||||
// Checked Checkbox
|
||||
<ion-checkbox checked={true}></ion-checkbox>,
|
||||
|
||||
// Checkbox Colors
|
||||
<ion-checkbox color="primary"></ion-checkbox>,
|
||||
<ion-checkbox color="secondary"></ion-checkbox>,
|
||||
<ion-checkbox color="danger"></ion-checkbox>,
|
||||
<ion-checkbox color="light"></ion-checkbox>,
|
||||
<ion-checkbox color="dark"></ion-checkbox>,
|
||||
|
||||
// Checkboxes in a List
|
||||
<ion-list>
|
||||
{this.form.map(entry =>
|
||||
<ion-item>
|
||||
<ion-label>{entry.val}</ion-label>
|
||||
<ion-checkbox slot="end" checked={entry.isChecked}></ion-checkbox>
|
||||
</ion-item>
|
||||
)}
|
||||
</ion-list>
|
||||
];
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
@@ -210,6 +273,14 @@ export const CheckboxExample: React.FC = () => (
|
||||
| `ionFocus` | Emitted when the toggle has focus. | `CustomEvent<void>` |
|
||||
|
||||
|
||||
## Shadow Parts
|
||||
|
||||
| Part | Description |
|
||||
| ------------- | ------------------------------------------------- |
|
||||
| `"container"` | The container for the checkbox mark. |
|
||||
| `"mark"` | The checkmark used to indicate the checked state. |
|
||||
|
||||
|
||||
## CSS Custom Properties
|
||||
|
||||
| Name | Description |
|
||||
|
||||
@@ -10,7 +10,12 @@
|
||||
<script src="../../../../../scripts/testing/scripts.js"></script>
|
||||
<script nomodule src="../../../../../dist/ionic/ionic.js"></script>
|
||||
<script type="module" src="../../../../../dist/ionic/ionic.esm.js"></script></head>
|
||||
|
||||
<style>
|
||||
ion-checkbox.checkbox-part::part(mark) {
|
||||
transform: scale(.5);
|
||||
transform-origin: center;
|
||||
}
|
||||
</style>
|
||||
<body>
|
||||
<ion-app>
|
||||
|
||||
@@ -81,6 +86,11 @@
|
||||
<ion-checkbox checked color="dark" slot="start" style="--checkmark-width: 7;"></ion-checkbox>
|
||||
</ion-item>
|
||||
|
||||
<ion-item>
|
||||
<ion-label>Checkmark ::part</ion-label>
|
||||
<ion-checkbox checked color="dark" slot="start" class="checkbox-part"></ion-checkbox>
|
||||
</ion-item>
|
||||
|
||||
<ion-item>
|
||||
<ion-label>Unchecked by Default</ion-label>
|
||||
<ion-checkbox></ion-checkbox>
|
||||
|
||||
@@ -1,40 +1,54 @@
|
||||
```tsx
|
||||
import React from 'react';
|
||||
import { IonCheckbox, IonList, IonItem, IonLabel, IonContent } from '@ionic/react';
|
||||
import React, { useState } from 'react';
|
||||
import { IonContent, IonHeader, IonPage, IonTitle, IonToolbar, IonCheckbox, IonList, IonItem, IonLabel, IonItemDivider } from '@ionic/react';
|
||||
|
||||
const form = [
|
||||
const checkboxList = [
|
||||
{ val: 'Pepperoni', isChecked: true },
|
||||
{ val: 'Sausage', isChecked: false },
|
||||
{ val: 'Mushroom', isChecked: false }
|
||||
];
|
||||
|
||||
export const CheckboxExample: React.FC = () => (
|
||||
<IonContent>
|
||||
{/*-- Default Checkbox --*/}
|
||||
<IonCheckbox />
|
||||
export const CheckboxExamples: React.FC = () => {
|
||||
|
||||
{/*-- Disabled Checkbox --*/}
|
||||
<IonCheckbox disabled={true} />
|
||||
const [checked, setChecked] = useState(false);
|
||||
|
||||
{/*-- Checked Checkbox --*/}
|
||||
<IonCheckbox checked={true} />
|
||||
return (
|
||||
<IonPage>
|
||||
<IonHeader>
|
||||
<IonToolbar>
|
||||
<IonTitle>CheckboxExamples</IonTitle>
|
||||
</IonToolbar>
|
||||
</IonHeader>
|
||||
<IonContent>
|
||||
<IonList>
|
||||
<IonItemDivider>Default Checkbox</IonItemDivider>
|
||||
<IonItem>
|
||||
<IonLabel>Checked: {JSON.stringify(checked)}</IonLabel>
|
||||
<IonCheckbox checked={checked} onIonChange={e => setChecked(e.detail.checked)} />
|
||||
</IonItem>
|
||||
|
||||
{/*-- Checkbox Colors --*/}
|
||||
<IonCheckbox color="primary" />
|
||||
<IonCheckbox color="secondary" />
|
||||
<IonCheckbox color="danger" />
|
||||
<IonCheckbox color="light" />
|
||||
<IonCheckbox color="dark" />
|
||||
<IonItemDivider>Disabled Checkbox</IonItemDivider>
|
||||
<IonItem><IonCheckbox slot="end" disabled={true} /></IonItem>
|
||||
|
||||
{/*-- Checkboxes in a List --*/}
|
||||
<IonList>
|
||||
{ form.map(({val, isChecked}) => (
|
||||
<IonItem key={val}>
|
||||
<IonLabel>{val}</IonLabel>
|
||||
<IonCheckbox slot="end" value={val} checked={isChecked} />
|
||||
</IonItem>
|
||||
)) }
|
||||
</IonList>
|
||||
</IonContent>
|
||||
);
|
||||
<IonItemDivider>Checkbox Colors</IonItemDivider>
|
||||
<IonItem>
|
||||
<IonCheckbox slot="end" color="primary" />
|
||||
<IonCheckbox slot="end" color="secondary" />
|
||||
<IonCheckbox slot="end" color="danger" />
|
||||
<IonCheckbox slot="end" color="light" />
|
||||
<IonCheckbox slot="end" color="dark" />
|
||||
</IonItem>
|
||||
<IonItemDivider>Checkboxes in a List</IonItemDivider>
|
||||
|
||||
{checkboxList.map(({ val, isChecked }, i) => (
|
||||
<IonItem key={i}>
|
||||
<IonLabel>{val}</IonLabel>
|
||||
<IonCheckbox slot="end" value={val} checked={isChecked} />
|
||||
</IonItem>
|
||||
))}
|
||||
</IonList>
|
||||
</IonContent>
|
||||
</IonPage>
|
||||
);
|
||||
};
|
||||
```
|
||||
45
core/src/components/checkbox/usage/stencil.md
Normal file
45
core/src/components/checkbox/usage/stencil.md
Normal file
@@ -0,0 +1,45 @@
|
||||
```tsx
|
||||
import { Component, h } from '@stencil/core';
|
||||
|
||||
@Component({
|
||||
tag: 'checkbox-example',
|
||||
styleUrl: 'checkbox-example.css'
|
||||
})
|
||||
export class CheckboxExample {
|
||||
private form = [
|
||||
{ val: 'Pepperoni', isChecked: true },
|
||||
{ val: 'Sausage', isChecked: false },
|
||||
{ val: 'Mushroom', isChecked: false }
|
||||
];
|
||||
|
||||
render() {
|
||||
return [
|
||||
// Default Checkbox
|
||||
<ion-checkbox></ion-checkbox>,
|
||||
|
||||
// Disabled Checkbox
|
||||
<ion-checkbox disabled={true}></ion-checkbox>,
|
||||
|
||||
// Checked Checkbox
|
||||
<ion-checkbox checked={true}></ion-checkbox>,
|
||||
|
||||
// Checkbox Colors
|
||||
<ion-checkbox color="primary"></ion-checkbox>,
|
||||
<ion-checkbox color="secondary"></ion-checkbox>,
|
||||
<ion-checkbox color="danger"></ion-checkbox>,
|
||||
<ion-checkbox color="light"></ion-checkbox>,
|
||||
<ion-checkbox color="dark"></ion-checkbox>,
|
||||
|
||||
// Checkboxes in a List
|
||||
<ion-list>
|
||||
{this.form.map(entry =>
|
||||
<ion-item>
|
||||
<ion-label>{entry.val}</ion-label>
|
||||
<ion-checkbox slot="end" checked={entry.isChecked}></ion-checkbox>
|
||||
</ion-item>
|
||||
)}
|
||||
</ion-list>
|
||||
];
|
||||
}
|
||||
}
|
||||
```
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user