mirror of
https://github.com/ionic-team/ionic-framework.git
synced 2026-03-13 10:22:08 +08:00
Compare commits
232 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
c463b065c7 | ||
|
|
5883da20fd | ||
|
|
b224a65f22 | ||
|
|
e1948be1f8 | ||
|
|
248a1ceced | ||
|
|
75cf887f91 | ||
|
|
32c5bed546 | ||
|
|
4f3e91bdfa | ||
|
|
236e7f8393 | ||
|
|
ea710044ef | ||
|
|
efd6605f98 | ||
|
|
aaa3cac917 | ||
|
|
4cc54eeb5d | ||
|
|
cfdba88754 | ||
|
|
7c583938a2 | ||
|
|
d659676ba2 | ||
|
|
e555eae1f5 | ||
|
|
5742540a36 | ||
|
|
6978bb551f | ||
|
|
e7ac15f9be | ||
|
|
2ab8385ee0 | ||
|
|
616786b387 | ||
|
|
6b5f9f113f | ||
|
|
2bba548253 | ||
|
|
1497d83a0e | ||
|
|
7f7f60ede5 | ||
|
|
73f6a82446 | ||
|
|
893ef725e9 | ||
|
|
4ea843440b | ||
|
|
f2946e77e6 | ||
|
|
ebdf22d2d3 | ||
|
|
dd66f9a7a9 | ||
|
|
6b848a04b3 | ||
|
|
af363581da | ||
|
|
33960f1a5a | ||
|
|
e5df0625b2 | ||
|
|
22747e3588 | ||
|
|
dc280b4199 | ||
|
|
fae5365b12 | ||
|
|
ecde0ae70f | ||
|
|
c8be8e254c | ||
|
|
356240883e | ||
|
|
c4e9b5d343 | ||
|
|
9f17b388d2 | ||
|
|
49e0c3701a | ||
|
|
ee766e1de8 | ||
|
|
74c5871ac4 | ||
|
|
8ec70ee02a | ||
|
|
ae4be669bb | ||
|
|
c91223bfb2 | ||
|
|
b1803510e3 | ||
|
|
70809caa8d | ||
|
|
88b2e8316d | ||
|
|
199cb00444 | ||
|
|
9bfd286dfa | ||
|
|
ac4dd6fea2 | ||
|
|
2646ebedf1 | ||
|
|
a77bb2c1d5 | ||
|
|
c963745888 | ||
|
|
2bd89feb0f | ||
|
|
c38cc28c5f | ||
|
|
9d4c94a7ac | ||
|
|
ad8d8ed2c3 | ||
|
|
0ba33d943f | ||
|
|
e0c830962c | ||
|
|
dac887092e | ||
|
|
e5b3eb7c8b | ||
|
|
c60588a290 | ||
|
|
77fcaef436 | ||
|
|
9c2181b8f9 | ||
|
|
4db20a648c | ||
|
|
f6d6596912 | ||
|
|
39e7da3840 | ||
|
|
9b3fb78a68 | ||
|
|
559f4d3bd5 | ||
|
|
f1a676e4c2 | ||
|
|
1573043f4e | ||
|
|
0a49648fe8 | ||
|
|
599bf3df5e | ||
|
|
fce5d8a04f | ||
|
|
108fc0fc3f | ||
|
|
521402b548 | ||
|
|
921ccbb79e | ||
|
|
c08de08d5f | ||
|
|
4199accdc2 | ||
|
|
70ab2a4e74 | ||
|
|
eacc5d4f23 | ||
|
|
112d4f5490 | ||
|
|
f42e81b02b | ||
|
|
9b5c0e035b | ||
|
|
4e56458b5c | ||
|
|
b5bfda2c42 | ||
|
|
200fa935b8 | ||
|
|
66faa1d959 | ||
|
|
b248eb7508 | ||
|
|
c7b2b186ec | ||
|
|
86210750d5 | ||
|
|
794d88d455 | ||
|
|
a48d02a966 | ||
|
|
d028a29d0e | ||
|
|
288c00a641 | ||
|
|
3b5c34c801 | ||
|
|
f2dc8b24b1 | ||
|
|
547ab8d8ef | ||
|
|
e2b3d753a7 | ||
|
|
3fb0371927 | ||
|
|
59f97e780d | ||
|
|
468dcd32fa | ||
|
|
cfd9e3b3a9 | ||
|
|
86e2742d58 | ||
|
|
8c207e827e | ||
|
|
fdacbbf1d0 | ||
|
|
ac04710b8a | ||
|
|
d0cad6b31e | ||
|
|
f5ef1ca552 | ||
|
|
830f885a06 | ||
|
|
318737535f | ||
|
|
04fe92cd58 | ||
|
|
b809665944 | ||
|
|
4d786b30ba | ||
|
|
4f49f27824 | ||
|
|
7e8bd5a8fe | ||
|
|
f4539aacc9 | ||
|
|
4911d9f01a | ||
|
|
6e64b8d915 | ||
|
|
e3216da03e | ||
|
|
bd0c265978 | ||
|
|
846eb09991 | ||
|
|
ac4a043314 | ||
|
|
106950533c | ||
|
|
295fe783b0 | ||
|
|
0a6bb3bb21 | ||
|
|
1b9c3daef1 | ||
|
|
54cdf00454 | ||
|
|
5bb3e73296 | ||
|
|
ae94f5ecea | ||
|
|
b87d212829 | ||
|
|
26b09f1d49 | ||
|
|
1e9539b9df | ||
|
|
17b3a39f0d | ||
|
|
475b722c7d | ||
|
|
50beafae6a | ||
|
|
f605f0a74c | ||
|
|
e401997a42 | ||
|
|
16f2ebe241 | ||
|
|
584afd040f | ||
|
|
de0f9d5f28 | ||
|
|
4596dbe5c0 | ||
|
|
400aa549d4 | ||
|
|
add0c4ecfe | ||
|
|
519d657e6e | ||
|
|
a8ceee467b | ||
|
|
97f9522110 | ||
|
|
961bfc3ebb | ||
|
|
5b9fe5e81a | ||
|
|
c4e7552b56 | ||
|
|
cec718c6c7 | ||
|
|
ab511c4744 | ||
|
|
2d49e10da4 | ||
|
|
ce46c24413 | ||
|
|
f7fce5fa16 | ||
|
|
d23b9f7d49 | ||
|
|
4c13535416 | ||
|
|
889b49f372 | ||
|
|
acb6facc7b | ||
|
|
2153940de8 | ||
|
|
6d8da0ae32 | ||
|
|
347c260950 | ||
|
|
9ffc52b582 | ||
|
|
08be9dc58b | ||
|
|
ad25cd1cd7 | ||
|
|
693c1c56d1 | ||
|
|
b5aa304e7e | ||
|
|
3e3a00b2fb | ||
|
|
923e3b2e26 | ||
|
|
e079f7777f | ||
|
|
5a4b351794 | ||
|
|
d22d77b485 | ||
|
|
efd54750bf | ||
|
|
eb830d4202 | ||
|
|
3f39e14f76 | ||
|
|
fce4422ab1 | ||
|
|
04e78d8c22 | ||
|
|
48b3243689 | ||
|
|
486bff036d | ||
|
|
a7e5fa7ea7 | ||
|
|
5771543c3b | ||
|
|
048af1b329 | ||
|
|
a92d805e89 | ||
|
|
8dc08f9c1f | ||
|
|
bc7bb21f1a | ||
|
|
016b90da47 | ||
|
|
0f5c47db15 | ||
|
|
86495e111d | ||
|
|
fba6ff0638 | ||
|
|
30f69c8a16 | ||
|
|
1beef75c80 | ||
|
|
58e1d79518 | ||
|
|
0480f73f8e | ||
|
|
f39c3811c5 | ||
|
|
6f7acdbddf | ||
|
|
bcc85d9144 | ||
|
|
00fbded168 | ||
|
|
5cad96570f | ||
|
|
e3a8d27ec1 | ||
|
|
d8b65da6ac | ||
|
|
70b5b6b5e5 | ||
|
|
5094feec89 | ||
|
|
1ca7df75ed | ||
|
|
877d8211d5 | ||
|
|
a8731dfc98 | ||
|
|
7803998542 | ||
|
|
8bd2f24d06 | ||
|
|
63f728f517 | ||
|
|
61935602a1 | ||
|
|
1a4aacf8be | ||
|
|
5a5da39a1e | ||
|
|
c7645ee59d | ||
|
|
2743c63537 | ||
|
|
7a1342caa1 | ||
|
|
3564bcfe1b | ||
|
|
f149c5ee95 | ||
|
|
2791c40c29 | ||
|
|
54ac2e393f | ||
|
|
dc958c3e2c | ||
|
|
9f86e10f46 | ||
|
|
8041eedf22 | ||
|
|
ef85ba6c1f | ||
|
|
6dee17b89b | ||
|
|
c10f72b1e2 | ||
|
|
47e3c70bf3 | ||
|
|
a91a68e198 |
16
.github/CONTRIBUTING.md
vendored
16
.github/CONTRIBUTING.md
vendored
@@ -70,7 +70,21 @@ Please see our [Contributor Code of Conduct](https://github.com/ionic-team/ionic
|
||||
|
||||
#### Adding Documentation
|
||||
|
||||
1. To add or modify API Documentation for a component, it should be added/changed in the `readme.md` file in the component's directory. If the updates are to a specific `@Prop`, `@Event` or `@Method`, then please make the changes to the component's TypeScript (`*.ts`). Properties, events and methods information within the `readme.md` file are auto generated directly from the JSDoc comments within the TypeScript file.
|
||||
1. To add or modify API Documentation for a component, it should be added/changed in the component's TypeScript (`*.ts`) file, prior to the Class definition. For example, `Badge` looks similar to this:
|
||||
|
||||
```
|
||||
/**
|
||||
* @name Badge
|
||||
* @module ionic
|
||||
* @description
|
||||
* Badges are simple components in Ionic containing numbers or text.
|
||||
*
|
||||
* @see {@link /docs/v2/components/#badges Badges Component Docs}
|
||||
* @demo /docs/v2/demos/badge/
|
||||
**/
|
||||
```
|
||||
|
||||
where `@name` is the Class name, `@description` is the description displayed on the documentation page, `@see` links to any related pages, and `@demo` links to the API demo located in the `demos` folder.
|
||||
2. In order to run API documentation locally, you will need to clone the `ionic-site` repo as a sibling to the `ionic` repo and then run it: https://github.com/ionic-team/ionic-site#local-build
|
||||
3. Then, run `gulp docs` in the `ionic` repo every time you make a change and the site will update.
|
||||
4. If the change affects the component documentation, create an issue on the `ionic-site` repo: https://github.com/ionic-team/ionic-site/issues
|
||||
|
||||
4
.github/ISSUE_TEMPLATE.md
vendored
4
.github/ISSUE_TEMPLATE.md
vendored
@@ -12,7 +12,7 @@
|
||||
[ ] bug report
|
||||
[ ] feature request
|
||||
|
||||
<!-- Please do not submit support requests or "How to" questions here. Instead, please use one of these channels: https://forum.ionicframework.com/ or http://ionicworldwide.herokuapp.com/ -->
|
||||
Please do not submit support requests or "How to" questions here. Instead, please use one of these channels: https://forum.ionicframework.com/ or http://ionicworldwide.herokuapp.com/
|
||||
|
||||
**Current behavior:**
|
||||
<!-- Describe how the bug manifests. -->
|
||||
@@ -47,3 +47,5 @@ insert short code snippets here
|
||||
```
|
||||
insert the output from ionic info here
|
||||
```
|
||||
|
||||
|
||||
|
||||
2
.github/PULL_REQUEST_TEMPLATE.md
vendored
2
.github/PULL_REQUEST_TEMPLATE.md
vendored
@@ -7,6 +7,6 @@
|
||||
-
|
||||
-
|
||||
|
||||
**Ionic Version**: 1.x / 2.x / 3.x / 4.x
|
||||
**Ionic Version**: 1.x / 2.x / 3.x
|
||||
|
||||
**Fixes**: #
|
||||
|
||||
70
.github/ionic-issue-bot.yml
vendored
70
.github/ionic-issue-bot.yml
vendored
@@ -1,70 +0,0 @@
|
||||
triage:
|
||||
label: triage
|
||||
dryRun: false
|
||||
|
||||
closeAndLock:
|
||||
labels:
|
||||
- label: "ionitron: support"
|
||||
message: >
|
||||
Thanks for the issue! This issue appears to be a support request. We use this issue tracker exclusively for
|
||||
bug reports and feature requests. Please use our [forum](https://forum.ionicframework.com) or our
|
||||
[slack channel](https://ionicworldwide.herokuapp.com/) for questions about the framework.
|
||||
|
||||
|
||||
Thank you for using Ionic!
|
||||
- label: "ionitron: missing template"
|
||||
message: >
|
||||
Thanks for the issue! It appears that you have not filled out the provided issue template. We use this issue
|
||||
template in order to gather more information and further assist you. Please create a new issue and ensure the
|
||||
template is fully filled out.
|
||||
|
||||
|
||||
Thank you for using Ionic!
|
||||
close: true
|
||||
lock: true
|
||||
dryRun: false
|
||||
|
||||
stale:
|
||||
days: 365
|
||||
maxIssuesPerRun: 100
|
||||
exemptLabels:
|
||||
- good first issue
|
||||
- triage
|
||||
exemptProjects: true
|
||||
exemptMilestones: true
|
||||
label: "ionitron: stale issue"
|
||||
message: >
|
||||
Thanks for the issue! This issue is being closed due to inactivity. 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
|
||||
dryRun: false
|
||||
|
||||
wrongRepo:
|
||||
repos:
|
||||
- label: "ionitron: cli"
|
||||
repo: ionic-cli
|
||||
message: >
|
||||
Thanks for the issue! We use this issue tracker exclusively for bug reports and feature requests
|
||||
associated with the Ionic Framework. It appears that this issue is associated with the Ionic CLI.
|
||||
I am moving this issue to the Ionic CLI repository. Please track this issue over there.
|
||||
|
||||
|
||||
Thank you for using Ionic!
|
||||
- label: "ionitron: stencil"
|
||||
repo: stencil
|
||||
message: >
|
||||
Thanks for the issue! We use this issue tracker exclusively for bug reports and feature requests
|
||||
associated with the Ionic Framework. It appears that this issue is associated with Stencil.
|
||||
I am moving this issue to the Stencil repository. Please track this issue over there.
|
||||
|
||||
|
||||
Thank you for using Ionic!
|
||||
close: true
|
||||
lock: true
|
||||
dryRun: false
|
||||
|
||||
6
.gitignore
vendored
6
.gitignore
vendored
@@ -9,17 +9,15 @@ log.txt
|
||||
*.sublime-workspace
|
||||
|
||||
.idea/
|
||||
.sourcemaps/
|
||||
.vscode/
|
||||
.sass-cache/
|
||||
.versions/
|
||||
coverage/
|
||||
collection/
|
||||
dist/
|
||||
node_modules/
|
||||
tmp/
|
||||
temp/
|
||||
core/theme-builder/
|
||||
core/test-components/
|
||||
$RECYCLE.BIN/
|
||||
|
||||
.DS_Store
|
||||
@@ -34,8 +32,6 @@ scripts/e2e/webpackEntryPoints.json
|
||||
scripts/build/e2e-generated-tsconfig.json
|
||||
*.css.ts
|
||||
|
||||
stencil-stats.json
|
||||
|
||||
# demo stuff
|
||||
demos/node_modules
|
||||
demos/polyfills
|
||||
|
||||
@@ -1,26 +0,0 @@
|
||||
# Build Scripts
|
||||
|
||||
## Release
|
||||
|
||||
The deploy scripts at the root, make a new release of all the packages in this monorepo.
|
||||
All packages will be released with the same version.
|
||||
|
||||
In order to make a new release:
|
||||
|
||||
1. `npm run release.prepare`
|
||||
2. Review/update changelog
|
||||
3. Commit updates using the package name and version number as the commit message.
|
||||
4. `npm run release`
|
||||
5. :tada:
|
||||
|
||||
|
||||
## Prerelease
|
||||
|
||||
It's also possible to make prereleases of individual packages (@ionic/core, @ionic/angular).
|
||||
In order to do so, move to the package you want to make a new release and execute:
|
||||
```
|
||||
npm run prerelease
|
||||
```
|
||||
|
||||
It will publish a new prerelease in NPM, but it will not create any new git tag
|
||||
or update the CHANGELOG.
|
||||
@@ -1,73 +0,0 @@
|
||||
const fs = require('fs-extra');
|
||||
const path = require('path');
|
||||
const execa = require('execa');
|
||||
const Listr = require('listr');
|
||||
const semver = require('semver');
|
||||
|
||||
const rootDir = path.join(__dirname, '../');
|
||||
|
||||
const packages = [
|
||||
'core',
|
||||
'angular'
|
||||
];
|
||||
|
||||
function readPkg(project) {
|
||||
const packageJsonPath = packagePath(project);
|
||||
return JSON.parse(fs.readFileSync(packageJsonPath, 'utf-8'));
|
||||
}
|
||||
|
||||
function writePkg(project, pkg) {
|
||||
const packageJsonPath = packagePath(project);
|
||||
const text = JSON.stringify(pkg, null, 2);
|
||||
return fs.writeFileSync(packageJsonPath, text);
|
||||
}
|
||||
|
||||
function packagePath(project) {
|
||||
return path.join(rootDir, project, 'package.json');
|
||||
}
|
||||
|
||||
function projectPath(project) {
|
||||
return path.join(rootDir, project);
|
||||
}
|
||||
|
||||
function checkGit(tasks) {
|
||||
tasks.push(
|
||||
{
|
||||
title: 'Check current branch',
|
||||
task: () => execa.stdout('git', ['symbolic-ref', '--short', 'HEAD']).then(branch => {
|
||||
if (branch !== 'master') {
|
||||
throw new Error(`Not on "master" branch`);
|
||||
}
|
||||
})
|
||||
},
|
||||
{
|
||||
title: 'Check local working tree',
|
||||
task: () => execa.stdout('git', ['status', '--porcelain']).then(status => {
|
||||
if (status !== '') {
|
||||
throw new Error(`Unclean working tree. Commit or stash changes first.`);
|
||||
}
|
||||
})
|
||||
},
|
||||
{
|
||||
title: 'Check remote history',
|
||||
task: () => execa.stdout('git', ['rev-list', '--count', '--left-only', '@{u}...HEAD']).then(result => {
|
||||
if (result !== '0') {
|
||||
throw new Error(`Remote history differs. Please pull changes.`);
|
||||
}
|
||||
})
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
const isValidVersion = input => Boolean(semver.valid(input));
|
||||
|
||||
|
||||
module.exports = {
|
||||
isValidVersion,
|
||||
readPkg,
|
||||
writePkg,
|
||||
rootDir,
|
||||
projectPath,
|
||||
checkGit,
|
||||
packages
|
||||
};
|
||||
@@ -1,307 +0,0 @@
|
||||
/**
|
||||
* Deploy script adopted from https://github.com/sindresorhus/np
|
||||
* MIT License (c) Sindre Sorhus (sindresorhus.com)
|
||||
*/
|
||||
const chalk = require('chalk');
|
||||
const execa = require('execa');
|
||||
const inquirer = require('inquirer');
|
||||
const Listr = require('listr');
|
||||
const fs = require('fs-extra');
|
||||
const semver = require('semver');
|
||||
const common = require('./common');
|
||||
const path = require('path');
|
||||
|
||||
|
||||
async function main() {
|
||||
try {
|
||||
const version = await askVersion();
|
||||
|
||||
// compile and verify packages
|
||||
await preparePackages(common.packages, version);
|
||||
|
||||
console.log(`\nionic ${version} prepared 🤖\n`);
|
||||
console.log(`Next steps:`);
|
||||
console.log(` Verify CHANGELOG.md`);
|
||||
console.log(` git commit -m "${version}"`);
|
||||
console.log(` git push`);
|
||||
console.log(` npm run release\n`);
|
||||
|
||||
} catch(err) {
|
||||
console.log('\n', chalk.red(err), '\n');
|
||||
process.exit(1);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
async function askVersion() {
|
||||
const pkg = common.readPkg('core');
|
||||
const oldVersion = pkg.version;
|
||||
|
||||
const prompts = [
|
||||
{
|
||||
type: 'list',
|
||||
name: 'version',
|
||||
message: 'Select semver increment or specify new version',
|
||||
pageSize: SEMVER_INCREMENTS.length + 2,
|
||||
choices: SEMVER_INCREMENTS
|
||||
.map(inc => ({
|
||||
name: `${inc} ${prettyVersionDiff(oldVersion, inc)}`,
|
||||
value: inc
|
||||
}))
|
||||
.concat([
|
||||
new inquirer.Separator(),
|
||||
{
|
||||
name: 'Other (specify)',
|
||||
value: null
|
||||
}
|
||||
]),
|
||||
filter: input => isValidVersionInput(input) ? getNewVersion(oldVersion, input) : input
|
||||
},
|
||||
{
|
||||
type: 'input',
|
||||
name: 'version',
|
||||
message: 'Version',
|
||||
when: answers => !answers.version,
|
||||
filter: input => isValidVersionInput(input) ? getNewVersion(pkg.version, input) : input,
|
||||
validate: input => {
|
||||
if (!isValidVersionInput(input)) {
|
||||
return 'Please specify a valid semver, for example, `1.2.3`. See http://semver.org';
|
||||
} else if (!isVersionGreater(oldVersion, input)) {
|
||||
return `Version must be greater than ${oldVersion}`;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
},
|
||||
{
|
||||
type: 'confirm',
|
||||
name: 'confirm',
|
||||
message: answers => {
|
||||
return `Will bump from ${chalk.cyan(oldVersion)} to ${chalk.cyan(answers.version)}. Continue?`;
|
||||
}
|
||||
}
|
||||
];
|
||||
|
||||
const {version} = await inquirer.prompt(prompts);
|
||||
return version;
|
||||
}
|
||||
|
||||
|
||||
async function preparePackages(packages, version) {
|
||||
// execution order matters
|
||||
const tasks = [];
|
||||
|
||||
// check git is nice and clean local and remote
|
||||
common.checkGit(tasks);
|
||||
|
||||
// test we're good with git
|
||||
validateGit(tasks, version);
|
||||
|
||||
// add all the prepare scripts
|
||||
// run all these tasks before updating package.json version
|
||||
packages.forEach(package => {
|
||||
preparePackage(tasks, package, version);
|
||||
});
|
||||
|
||||
// add update package.json of each project
|
||||
packages.forEach(package => {
|
||||
updatePackageVersion(tasks, package, version);
|
||||
});
|
||||
|
||||
// generate changelog
|
||||
generateChangeLog(tasks);
|
||||
|
||||
const listr = new Listr(tasks, { showSubtasks: true });
|
||||
await listr.run();
|
||||
}
|
||||
|
||||
|
||||
function validateGit(tasks, version) {
|
||||
tasks.push(
|
||||
{
|
||||
title: `Validate git tag ${chalk.dim(`(v${version})`)}`,
|
||||
task: () => execa('git', ['fetch'])
|
||||
.then(() => {
|
||||
return execa.stdout('npm', ['config', 'get', 'tag-version-prefix']);
|
||||
})
|
||||
.then(
|
||||
output => {
|
||||
tagPrefix = output;
|
||||
},
|
||||
() => {}
|
||||
)
|
||||
.then(() => execa.stdout('git', ['rev-parse', '--quiet', '--verify', `refs/tags/${tagPrefix}${version}`]))
|
||||
.then(
|
||||
output => {
|
||||
if (output) {
|
||||
throw new Error(`Git tag \`${tagPrefix}${version}\` already exists.`);
|
||||
}
|
||||
},
|
||||
err => {
|
||||
// Command fails with code 1 and no output if the tag does not exist, even though `--quiet` is provided
|
||||
// https://github.com/sindresorhus/np/pull/73#discussion_r72385685
|
||||
if (err.stdout !== '' || err.stderr !== '') {
|
||||
throw err;
|
||||
}
|
||||
}
|
||||
)
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
function preparePackage(tasks, package, version) {
|
||||
const projectRoot = common.projectPath(package);
|
||||
const pkg = common.readPkg(package);
|
||||
|
||||
const projectTasks = [
|
||||
{
|
||||
title: `${pkg.name}: validate new version`,
|
||||
task: () => {
|
||||
if (!isVersionGreater(pkg.version, version)) {
|
||||
throw new Error(`New version \`${version}\` should be higher than current version \`${pkg.version}\``);
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
title: `${pkg.name}: install npm dependencies`,
|
||||
task: async () => {
|
||||
await fs.remove(path.join(projectRoot, 'node_modules'))
|
||||
await execa('npm', ['ci'], { cwd: projectRoot });
|
||||
}
|
||||
}
|
||||
];
|
||||
|
||||
if (package !== 'core') {
|
||||
projectTasks.push(
|
||||
{
|
||||
title: `${pkg.name}: npm link @ionic/core`,
|
||||
task: () => execa('npm', ['link', '@ionic/core'], { cwd: projectRoot })
|
||||
},
|
||||
{
|
||||
title: `${pkg.name}: update ionic/core dep to ${version}`,
|
||||
task: () => {
|
||||
updateDependency(pkg, "@ionic/core", version);
|
||||
common.writePkg(package, pkg);
|
||||
}
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
projectTasks.push(
|
||||
{
|
||||
title: `${pkg.name}: lint`,
|
||||
task: () => execa('npm', ['run', 'lint'], { cwd: projectRoot })
|
||||
},
|
||||
{
|
||||
title: `${pkg.name}: build`,
|
||||
task: () => execa('npm', ['run', 'build'], { cwd: projectRoot })
|
||||
},
|
||||
{
|
||||
title: `${pkg.name}: test`,
|
||||
task: () => execa('npm', ['test'], { cwd: projectRoot })
|
||||
}
|
||||
);
|
||||
|
||||
if (package === 'core') {
|
||||
projectTasks.push(
|
||||
{
|
||||
title: `${pkg.name}: npm link`,
|
||||
task: () => execa('npm', ['link'], { cwd: projectRoot })
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
// Add project tasks
|
||||
tasks.push({
|
||||
title: `Prepare ${chalk.bold(pkg.name)}`,
|
||||
task: () => new Listr(projectTasks)
|
||||
});
|
||||
}
|
||||
|
||||
function updateDependency(pkg, dependency, version) {
|
||||
if (pkg.dependencies && pkg.dependencies[dependency]) {
|
||||
pkg.dependencies[dependency] = version;
|
||||
}
|
||||
if (pkg.devDependencies && pkg.devDependencies[dependency]) {
|
||||
pkg.devDependencies[dependency] = version;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
function updatePackageVersion(tasks, package, version) {
|
||||
const projectRoot = common.projectPath(package);
|
||||
const pkg = common.readPkg(package);
|
||||
|
||||
tasks.push(
|
||||
{
|
||||
title: `${pkg.name}: update package.json ${chalk.dim(`(${version})`)}`,
|
||||
task: async () => {
|
||||
await execa('npm', ['version', version], { cwd: projectRoot });
|
||||
|
||||
const pkgLock = path.join(projectRoot, 'package-lock.json');
|
||||
const pkgLockData = JSON.parse(fs.readFileSync(pkgLock, 'utf-8'));
|
||||
pkgLockData.version = version;
|
||||
|
||||
fs.writeFileSync(pkgLock, JSON.stringify(pkgLockData));
|
||||
}
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
async function generateChangeLog(tasks) {
|
||||
tasks.push(
|
||||
{
|
||||
title: `Generate CHANGELOG.md`,
|
||||
task: () => execa('npm', ['run', 'changelog'], { cwd: common.rootDir }),
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
const SEMVER_INCREMENTS = ['patch', 'minor', 'major'];
|
||||
|
||||
const isValidVersion = input => Boolean(semver.valid(input));
|
||||
|
||||
const isValidVersionInput = input => SEMVER_INCREMENTS.indexOf(input) !== -1 || common.isValidVersion(input);
|
||||
|
||||
function getNewVersion(oldVersion, input) {
|
||||
if (!isValidVersionInput(input)) {
|
||||
throw new Error(`Version should be either ${SEMVER_INCREMENTS.join(', ')} or a valid semver version.`);
|
||||
}
|
||||
|
||||
return SEMVER_INCREMENTS.indexOf(input) === -1 ? input : semver.inc(oldVersion, input);
|
||||
};
|
||||
|
||||
const isVersionGreater = (oldVersion, newVersion) => {
|
||||
if (!common.isValidVersion(newVersion)) {
|
||||
throw new Error('Version should be a valid semver version.');
|
||||
}
|
||||
|
||||
return semver.gt(newVersion, oldVersion);
|
||||
};
|
||||
|
||||
|
||||
function prettyVersionDiff(oldVersion, inc) {
|
||||
const newVersion = getNewVersion(oldVersion, inc).split('.');
|
||||
oldVersion = oldVersion.split('.');
|
||||
let firstVersionChange = false;
|
||||
const output = [];
|
||||
|
||||
for (let i = 0; i < newVersion.length; i++) {
|
||||
if ((newVersion[i] !== oldVersion[i] && !firstVersionChange)) {
|
||||
output.push(`${chalk.dim.cyan(newVersion[i])}`);
|
||||
firstVersionChange = true;
|
||||
} else if (newVersion[i].indexOf('-') >= 1) {
|
||||
let preVersion = [];
|
||||
preVersion = newVersion[i].split('-');
|
||||
output.push(`${chalk.dim.cyan(`${preVersion[0]}-${preVersion[1]}`)}`);
|
||||
} else {
|
||||
output.push(chalk.reset.dim(newVersion[i]));
|
||||
}
|
||||
}
|
||||
return output.join(chalk.reset.dim('.'));
|
||||
}
|
||||
|
||||
main();
|
||||
@@ -1,92 +0,0 @@
|
||||
/**
|
||||
* Deploy script adopted from https://github.com/sindresorhus/np
|
||||
* MIT License (c) Sindre Sorhus (sindresorhus.com)
|
||||
*/
|
||||
const chalk = require('chalk');
|
||||
const execa = require('execa');
|
||||
const Listr = require('listr');
|
||||
const common = require('./common');
|
||||
|
||||
|
||||
async function main() {
|
||||
try {
|
||||
const {version} = common.readPkg('core');
|
||||
|
||||
// publish each package in NPM
|
||||
await publishPackages(common.packages, version);
|
||||
|
||||
console.log(`\nionic ${version} published!! 🎉\n`);
|
||||
|
||||
} catch (err) {
|
||||
console.log('\n', chalk.red(err), '\n');
|
||||
process.exit(1);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
async function publishPackages(packages, version) {
|
||||
const tasks = [];
|
||||
|
||||
// repo must be clean
|
||||
common.checkGit(tasks);
|
||||
|
||||
// first verify version
|
||||
packages.forEach(package => {
|
||||
if (package === 'core') return;
|
||||
|
||||
const pkg = common.readPkg(package);
|
||||
|
||||
tasks.push(
|
||||
{
|
||||
title: `${pkg.name}: check version (must match: ${version})`,
|
||||
task: () => {
|
||||
if (version !== pkg.version) {
|
||||
throw new Error(`${pkg.name} version ${pkg.version} must match ${version}`);
|
||||
}
|
||||
}
|
||||
}
|
||||
);
|
||||
});
|
||||
|
||||
// next publish
|
||||
packages.forEach(package => {
|
||||
const pkg = common.readPkg(package);
|
||||
const projectRoot = common.projectPath(package);
|
||||
|
||||
tasks.push(
|
||||
{
|
||||
title: `${pkg.name}: publish ${pkg.version}`,
|
||||
task: () =>execa('npm', ['publish', '--tag', 'latest'], { cwd: projectRoot })
|
||||
}
|
||||
);
|
||||
});
|
||||
|
||||
// push tag to git remote
|
||||
publishGitTag(tasks, version);
|
||||
|
||||
const listr = new Listr(tasks);
|
||||
await listr.run();
|
||||
}
|
||||
|
||||
|
||||
function publishGitTag(tasks, version) {
|
||||
const tag = `v${version}`;
|
||||
|
||||
tasks.push(
|
||||
{
|
||||
title: `Tag latest commit ${chalk.dim(`(${tag})`)}`,
|
||||
task: () => execa('git', ['tag', `${tag}`], { cwd: common.rootDir })
|
||||
},
|
||||
{
|
||||
title: 'Push branches to Github',
|
||||
task: () => execa('git', ['push'], { cwd: common.rootDir })
|
||||
},
|
||||
{
|
||||
title: 'Push tags to Github',
|
||||
task: () => execa('git', ['push', '--tags'], { cwd: common.rootDir })
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
main();
|
||||
@@ -4,18 +4,12 @@
|
||||
|
||||
plugin_directories: ['.scss-linters']
|
||||
|
||||
scss_files: 'src/**/*.scss'
|
||||
|
||||
exclude:
|
||||
- '*.css'
|
||||
- 'src/themes/ionic.functions.color.scss'
|
||||
- 'src/themes/ionic.mixins.scss'
|
||||
- 'src/themes/license.scss'
|
||||
- 'src/themes/normalize.scss'
|
||||
- 'src/themes/util.scss'
|
||||
- 'src/themes/version.scss'
|
||||
- 'src/platform/cordova.*.scss'
|
||||
- 'src/components/slides/slides-vendor.scss'
|
||||
|
||||
|
||||
linters:
|
||||
@@ -41,16 +35,12 @@ linters:
|
||||
|
||||
# Box
|
||||
|
||||
- box-sizing
|
||||
- position
|
||||
- top
|
||||
- right
|
||||
- bottom
|
||||
- left
|
||||
- z-index
|
||||
- display
|
||||
- overflow
|
||||
- overscroll-behavior
|
||||
- clear
|
||||
-
|
||||
- flex
|
||||
@@ -117,13 +107,10 @@ linters:
|
||||
- font
|
||||
- font-family
|
||||
- font-size
|
||||
- -moz-osx-font-smoothing
|
||||
- -webkit-font-smoothing
|
||||
- font-smooth
|
||||
- font-smoothing
|
||||
- font-style
|
||||
- font-variant
|
||||
- font-weight
|
||||
- src
|
||||
|
||||
- letter-spacing
|
||||
- line-height
|
||||
@@ -201,8 +188,6 @@ linters:
|
||||
PropertySpelling:
|
||||
extra_properties:
|
||||
- contain
|
||||
- overscroll-behavior
|
||||
- overscroll-behavior-y
|
||||
disabled_properties:
|
||||
- background-position
|
||||
- direction
|
||||
1091
BREAKING.md
1091
BREAKING.md
File diff suppressed because it is too large
Load Diff
3498
CHANGELOG.md
3498
CHANGELOG.md
File diff suppressed because it is too large
Load Diff
2
LICENSE
2
LICENSE
@@ -20,4 +20,4 @@ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
||||
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
||||
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
||||
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
32
README.md
32
README.md
@@ -1,16 +1,17 @@
|
||||
[](https://badge.fury.io/js/ionic-angular)
|
||||
[](https://circleci.com/gh/ionic-team/ionic)
|
||||
|
||||
# Ionic
|
||||
|
||||
[Ionic](https://ionicframework.com/) is the open-source mobile app development framework that makes it easy to
|
||||
build top quality native and progressive web apps with web technologies.
|
||||
|
||||
Ionic is based on [Web Components](https://www.webcomponents.org/introduction) and comes with many significant performance, usability, and feature improvements over the past versions.
|
||||
|
||||
|
||||
# Packages
|
||||
|
||||
- [Core](core/README.md)
|
||||
- [Ionic Angular](angular/README.md)
|
||||
Ionic is based on [Angular](https://angular.io/) and comes with many significant performance, usability, and
|
||||
feature improvements over the past versions.
|
||||
|
||||
See the [Building Apps with Ionic](https://adamdbradley.github.io/building-with-ionic2) slides for a quick
|
||||
overview or watch our [Crash Course](https://youtu.be/O2WiI9QrS5s) video for a quick walkthrough on how to get
|
||||
started using Ionic.
|
||||
|
||||
### Getting Started
|
||||
|
||||
@@ -18,7 +19,6 @@ Start a new project by following our quick [Getting Started guide](https://ionic
|
||||
We would love to hear from you! If you have any feedback or run into issues using our framework, please file
|
||||
an [issue](https://github.com/ionic-team/ionic/issues/new) on this repository.
|
||||
|
||||
|
||||
### Contributing
|
||||
|
||||
Thanks for your interest in contributing! Read up on our guidelines for
|
||||
@@ -26,28 +26,12 @@ Thanks for your interest in contributing! Read up on our guidelines for
|
||||
and then look through our issues with a [help wanted](https://github.com/ionic-team/ionic/issues?q=is%3Aopen+is%3Aissue+label%3A%22help+wanted%22)
|
||||
label.
|
||||
|
||||
|
||||
### Examples
|
||||
|
||||
The [Ionic Conference App](https://github.com/ionic-team/ionic-conference-app) is a full featured Ionic app.
|
||||
It is the perfect starting point for learning and building your own app.
|
||||
|
||||
|
||||
### Future Goals
|
||||
|
||||
As Ionic components migrate to the web component standard, a goal of ours is to have Ionic components easily work within all of the popular frameworks.
|
||||
|
||||
[](https://badge.fury.io/js/ionic-angular)
|
||||
[](https://circleci.com/gh/ionic-team/ionic)
|
||||
[](https://www.codetriage.com/ionic-team/ionic)
|
||||
|
||||
|
||||
### Ionic V1
|
||||
|
||||
The source code for Ionic V1 has been moved to [ionic-team/ionic-v1](https://github.com/ionic-team/ionic-v1).
|
||||
Please open any issues and pull requests related to Ionic V1 on that repository.
|
||||
|
||||
|
||||
### Ionic V3
|
||||
|
||||
The source code for Ionic V3 has been moved to the [v3 branch](https://github.com/ionic-team/ionic/tree/v3).
|
||||
|
||||
@@ -1,19 +0,0 @@
|
||||
# @ionic/angular
|
||||
|
||||
Ionic Angular specific building blocks on top of [@ionic/core](https://www.npmjs.com/package/@ionic/core) components.
|
||||
|
||||
|
||||
## Related
|
||||
|
||||
* [Ionic Core Components](https://www.npmjs.com/package/@ionic/core)
|
||||
* [Ionic Documentation](https://ionicframework.com/docs/)
|
||||
* [Ionic Worldwide Slack](http://ionicworldwide.herokuapp.com/)
|
||||
* [Ionic Forum](https://forum.ionicframework.com/)
|
||||
* [Ionicons](http://ionicons.com/)
|
||||
* [Stencil](https://stenciljs.com/)
|
||||
* [Stencil Worldwide Slack](https://stencil-worldwide.slack.com)
|
||||
|
||||
|
||||
## License
|
||||
|
||||
* [MIT](https://raw.githubusercontent.com/ionic-team/ionic/master/LICENSE)
|
||||
1
angular/package-lock.json
generated
1
angular/package-lock.json
generated
File diff suppressed because one or more lines are too long
@@ -1,66 +0,0 @@
|
||||
{
|
||||
"name": "@ionic/angular",
|
||||
"version": "0.2.2",
|
||||
"description": "Angular specific wrappers for @ionic/core",
|
||||
"keywords": [
|
||||
"ionic",
|
||||
"framework",
|
||||
"angular",
|
||||
"mobile",
|
||||
"app",
|
||||
"webapp",
|
||||
"capacitor",
|
||||
"cordova",
|
||||
"progressive web app",
|
||||
"pwa"
|
||||
],
|
||||
"license": "MIT",
|
||||
"repository": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/ionic-team/ionic.git"
|
||||
},
|
||||
"scripts": {
|
||||
"build": "npm run clean && npm run compile && npm run clean-generated && npm run ionic-core",
|
||||
"build.link": "npm run build && node scripts/link-copy.js",
|
||||
"clean": "node scripts/clean.js",
|
||||
"clean-generated": "node ./scripts/clean-generated.js",
|
||||
"compile": "./node_modules/.bin/ngc",
|
||||
"ionic-core": "node ../core/node_modules/.bin/stencil build",
|
||||
"ionic-core-dev": "node ../core/node_modules/.bin/stencil build --dev",
|
||||
"lint": "tslint --project .",
|
||||
"prerelease": "npm run validate && np prerelease --yolo --any-branch --tag next",
|
||||
"test": "echo 'angular no tests yet'",
|
||||
"tsc": "tsc -p .",
|
||||
"validate": "npm i && npm run lint && npm run test && npm run build"
|
||||
},
|
||||
"main": "./dist/index.js",
|
||||
"types": "./dist/index.d.ts",
|
||||
"files": [
|
||||
"dist/"
|
||||
],
|
||||
"dependencies": {
|
||||
"@ionic/core": "0.2.2"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@angular/common": "5.2.9",
|
||||
"@angular/compiler": "5.2.9",
|
||||
"@angular/compiler-cli": "5.2.9",
|
||||
"@angular/core": "5.2.9",
|
||||
"@angular/forms": "5.2.9",
|
||||
"@angular/platform-browser": "5.2.9",
|
||||
"@angular/platform-browser-dynamic": "5.2.9",
|
||||
"@angular/router": "5.2.9",
|
||||
"chalk": "^2.3.2",
|
||||
"execa": "^0.10.0",
|
||||
"fs-extra": "^5.0.0",
|
||||
"glob": "7.1.2",
|
||||
"inquirer": "^5.2.0",
|
||||
"listr": "^0.13.0",
|
||||
"rxjs": "5.5.8",
|
||||
"semver": "^5.5.0",
|
||||
"tslint": "^5.8.0",
|
||||
"tslint-ionic-rules": "0.0.14",
|
||||
"typescript": "2.7.2",
|
||||
"zone.js": "^0.8.20"
|
||||
}
|
||||
}
|
||||
@@ -1,19 +0,0 @@
|
||||
# Local @ionic/angular test app development
|
||||
|
||||
1. `npm install` at the root of `angular`
|
||||
2. `npm run build` to build local `@ionic/angular`
|
||||
3. `npm link` to locally link `@ionic/angular`
|
||||
4. `cd` to the test app, such as `angular/test/nav`
|
||||
5. `npm install` in the test app directory
|
||||
6. `npm link @ionic/angular` in the test app directory
|
||||
7. `ng serve` in the test app directory
|
||||
8. [http://localhost:4200/](http://localhost:4200/)
|
||||
|
||||
|
||||
# npm link local development
|
||||
|
||||
`npm link` doesn't work as expected due to the `devDependency` on `@angular/core`. This is the work around...
|
||||
|
||||
npm run build.link ../ionic-conference-app
|
||||
|
||||
When the command above is ran from the `angular` directory, it will build `@ionic/angular` and copy the `dist` directory to the correct location of another local project. In the example above, the end result is that it copies the `dist` directory to `../ionic-conference-app/node_modules/@ionic/angular/dist`. The path given should be relative to the root of this mono repo.
|
||||
42
angular/scripts/clean-generated.js
vendored
42
angular/scripts/clean-generated.js
vendored
@@ -1,42 +0,0 @@
|
||||
const path = require('path');
|
||||
const cwd = process.cwd();
|
||||
|
||||
const glob = require('glob');
|
||||
const fs = require('fs-extra');
|
||||
|
||||
const distDir = path.join(__dirname, '../dist');
|
||||
|
||||
const distGeneratedNodeModules = path.join(distDir, 'node_modules');
|
||||
|
||||
function doGlob(globString) {
|
||||
return new Promise((resolve, reject) => {
|
||||
glob(globString, (err, matches) => {
|
||||
if (err) {
|
||||
return reject(err);
|
||||
}
|
||||
resolve(matches);
|
||||
})
|
||||
});
|
||||
}
|
||||
|
||||
function getCodegenedFilesToDelete() {
|
||||
const ngFactoryGlob = path.join(distDir, '**', '*ngfactory*');
|
||||
const ngSummaryGlob = path.join(distDir, '**', '*ngsummary*');
|
||||
const promises = [];
|
||||
promises.push(doGlob(ngFactoryGlob));
|
||||
promises.push(doGlob(ngSummaryGlob));
|
||||
return Promise.all(promises).then(listOfGlobResults => {
|
||||
const deleteFilePromises = [];
|
||||
listOfGlobResults.forEach(fileMatches => {
|
||||
fileMatches.forEach(filePath => {
|
||||
deleteFilePromises.push(fs.remove(filePath));
|
||||
})
|
||||
})
|
||||
return Promise.all(deleteFilePromises);
|
||||
});
|
||||
}
|
||||
|
||||
Promise.all([
|
||||
getCodegenedFilesToDelete(),
|
||||
fs.remove(distGeneratedNodeModules)
|
||||
]);
|
||||
12
angular/scripts/clean.js
vendored
12
angular/scripts/clean.js
vendored
@@ -1,12 +0,0 @@
|
||||
const fs = require('fs-extra');
|
||||
const path = require('path');
|
||||
|
||||
|
||||
const cleanDirs = [
|
||||
'dist'
|
||||
];
|
||||
|
||||
cleanDirs.forEach(dir => {
|
||||
const cleanDir = path.join(__dirname, '../', dir);
|
||||
fs.removeSync(cleanDir);
|
||||
});
|
||||
31
angular/scripts/link-copy.js
vendored
31
angular/scripts/link-copy.js
vendored
@@ -1,31 +0,0 @@
|
||||
const fs = require('fs-extra');
|
||||
const path = require('path');
|
||||
|
||||
|
||||
let prjDir = process.argv[2];
|
||||
if (!prjDir) {
|
||||
throw new Error('local path required as last argument to "npm run build.link" command');
|
||||
}
|
||||
prjDir = path.join(__dirname, '../../../', prjDir);
|
||||
const prjIonicAngular = path.join(prjDir, 'node_modules/@ionic/angular');
|
||||
|
||||
const ionicAngularDir = path.join(__dirname, '..');
|
||||
const ionicAngularDist = path.join(ionicAngularDir, 'dist');
|
||||
const ionicAngularPkgJsonPath = path.join(ionicAngularDir, 'package.json');
|
||||
const ionicAngularPkgJson = require(ionicAngularPkgJsonPath);
|
||||
|
||||
// make sure this local project exists
|
||||
fs.emptyDirSync(prjIonicAngular);
|
||||
|
||||
ionicAngularPkgJson.files.push('package.json');
|
||||
|
||||
ionicAngularPkgJson.files.forEach(f => {
|
||||
const src = path.join(ionicAngularDir, f);
|
||||
const dest = path.join(prjIonicAngular, f);
|
||||
|
||||
console.log('copying:', src, 'to', dest);
|
||||
fs.copySync(src, dest);
|
||||
});
|
||||
|
||||
const prjReadme = path.join(prjIonicAngular, 'README.md');
|
||||
fs.writeFileSync(prjReadme, '@ionic/angular copied from ' + ionicAngularDir);
|
||||
28
angular/src/components.d.ts
vendored
28
angular/src/components.d.ts
vendored
@@ -1,28 +0,0 @@
|
||||
/**
|
||||
* This is an autogenerated file created by the Stencil build process.
|
||||
* It contains typing information for all components that exist in this project
|
||||
* and imports for stencil collections that might be configured in your stencil.config.js file
|
||||
*/
|
||||
|
||||
import '@stencil/core';
|
||||
|
||||
declare global {
|
||||
namespace JSX {
|
||||
interface Element {}
|
||||
export interface IntrinsicElements {}
|
||||
}
|
||||
namespace JSXElements {}
|
||||
|
||||
interface HTMLStencilElement extends HTMLElement {
|
||||
componentOnReady(): Promise<this>;
|
||||
componentOnReady(done: (ele?: this) => void): void;
|
||||
|
||||
forceUpdate(): void;
|
||||
}
|
||||
|
||||
interface HTMLAttributes {}
|
||||
}
|
||||
|
||||
import 'ionicons';
|
||||
import '@ionic/core';
|
||||
|
||||
@@ -1,61 +0,0 @@
|
||||
import { Directive, ElementRef, HostListener } from '@angular/core';
|
||||
import { ControlValueAccessor, NG_VALUE_ACCESSOR } from '@angular/forms';
|
||||
|
||||
import { setIonicClasses } from './util/set-ionic-classes';
|
||||
|
||||
@Directive({
|
||||
/* tslint:disable-next-line:directive-selector */
|
||||
selector: 'ion-checkbox,ion-toggle',
|
||||
providers: [
|
||||
{
|
||||
provide: NG_VALUE_ACCESSOR,
|
||||
useExisting: BooleanValueAccessor,
|
||||
multi: true
|
||||
}
|
||||
]
|
||||
})
|
||||
export class BooleanValueAccessor implements ControlValueAccessor {
|
||||
|
||||
constructor(private element: ElementRef) {
|
||||
this.onChange = () => {/**/};
|
||||
this.onTouched = () => {/**/};
|
||||
}
|
||||
|
||||
onChange: (value: any) => void;
|
||||
onTouched: () => void;
|
||||
|
||||
writeValue(value: any) {
|
||||
this.element.nativeElement.checked = value;
|
||||
setIonicClasses(this.element);
|
||||
}
|
||||
|
||||
@HostListener('ionChange', ['$event.target.checked'])
|
||||
_handleIonChange(value: any) {
|
||||
this.onChange(value);
|
||||
|
||||
requestAnimationFrame(() => {
|
||||
setIonicClasses(this.element);
|
||||
});
|
||||
}
|
||||
|
||||
@HostListener('ionBlur')
|
||||
_handleBlurEvent() {
|
||||
this.onTouched();
|
||||
|
||||
requestAnimationFrame(() => {
|
||||
setIonicClasses(this.element);
|
||||
});
|
||||
}
|
||||
|
||||
registerOnChange(fn: (value: any) => void) {
|
||||
this.onChange = fn;
|
||||
}
|
||||
|
||||
registerOnTouched(fn: () => void) {
|
||||
this.onTouched = fn;
|
||||
}
|
||||
|
||||
setDisabledState(isDisabled: boolean) {
|
||||
this.element.nativeElement.disabled = isDisabled;
|
||||
}
|
||||
}
|
||||
@@ -1,65 +0,0 @@
|
||||
import { Directive, ElementRef, HostListener } from '@angular/core';
|
||||
import { ControlValueAccessor, NG_VALUE_ACCESSOR } from '@angular/forms';
|
||||
|
||||
import { setIonicClasses } from './util/set-ionic-classes';
|
||||
|
||||
@Directive({
|
||||
/* tslint:disable-next-line:directive-selector */
|
||||
selector: 'ion-input[type=number]',
|
||||
providers: [
|
||||
{
|
||||
provide: NG_VALUE_ACCESSOR,
|
||||
useExisting: NumericValueAccessor,
|
||||
multi: true
|
||||
}
|
||||
]
|
||||
})
|
||||
export class NumericValueAccessor implements ControlValueAccessor {
|
||||
|
||||
constructor(private element: ElementRef) {
|
||||
this.onChange = () => {/**/};
|
||||
this.onTouched = () => {/**/};
|
||||
}
|
||||
|
||||
onChange: (value: any) => void;
|
||||
onTouched: () => void;
|
||||
|
||||
writeValue(value: any) {
|
||||
// The value needs to be normalized for IE9, otherwise it is set to 'null' when null
|
||||
// Probably not an issue for us, but it doesn't really cost anything either
|
||||
this.element.nativeElement.value = value == null ? '' : value;
|
||||
setIonicClasses(this.element);
|
||||
}
|
||||
|
||||
@HostListener('input', ['$event.target.value'])
|
||||
_handleInputEvent(value: any) {
|
||||
this.onChange(value);
|
||||
|
||||
requestAnimationFrame(() => {
|
||||
setIonicClasses(this.element);
|
||||
});
|
||||
}
|
||||
|
||||
@HostListener('ionBlur')
|
||||
_handleBlurEvent() {
|
||||
this.onTouched();
|
||||
|
||||
requestAnimationFrame(() => {
|
||||
setIonicClasses(this.element);
|
||||
});
|
||||
}
|
||||
|
||||
registerOnChange(fn: (_: number | null) => void) {
|
||||
this.onChange = value => {
|
||||
fn(value === '' ? null : parseFloat(value));
|
||||
};
|
||||
}
|
||||
|
||||
registerOnTouched(fn: () => void) {
|
||||
this.onTouched = fn;
|
||||
}
|
||||
|
||||
setDisabledState(isDisabled: boolean) {
|
||||
this.element.nativeElement.disabled = isDisabled;
|
||||
}
|
||||
}
|
||||
@@ -1,67 +0,0 @@
|
||||
import { Directive, ElementRef, HostListener, Input } from '@angular/core';
|
||||
import { ControlValueAccessor, NG_VALUE_ACCESSOR } from '@angular/forms';
|
||||
|
||||
import { setIonicClasses } from './util/set-ionic-classes';
|
||||
|
||||
@Directive({
|
||||
/* tslint:disable-next-line:directive-selector */
|
||||
selector: 'ion-radio',
|
||||
providers: [
|
||||
{
|
||||
provide: NG_VALUE_ACCESSOR,
|
||||
useExisting: RadioValueAccessor,
|
||||
multi: true
|
||||
}
|
||||
]
|
||||
})
|
||||
export class RadioValueAccessor implements ControlValueAccessor {
|
||||
@Input() value: any;
|
||||
|
||||
onChange: (value: any) => void;
|
||||
onTouched: () => void;
|
||||
|
||||
constructor(private element: ElementRef) {
|
||||
this.onChange = () => {/**/};
|
||||
this.onTouched = () => {/**/};
|
||||
}
|
||||
|
||||
writeValue(value: any) {
|
||||
this.element.nativeElement.checked = this.value = value;
|
||||
|
||||
requestAnimationFrame(() => {
|
||||
setIonicClasses(this.element);
|
||||
});
|
||||
}
|
||||
|
||||
@HostListener('ionSelect', ['$event.target.checked'])
|
||||
_handleIonSelect(value: any) {
|
||||
this.onChange(value);
|
||||
|
||||
requestAnimationFrame(() => {
|
||||
setIonicClasses(this.element);
|
||||
});
|
||||
}
|
||||
|
||||
@HostListener('ionBlur')
|
||||
_handleBlurEvent() {
|
||||
this.onTouched();
|
||||
|
||||
requestAnimationFrame(() => {
|
||||
setIonicClasses(this.element);
|
||||
});
|
||||
}
|
||||
|
||||
registerOnChange(fn: (value: any) => void) {
|
||||
this.onChange = () => {
|
||||
fn(this.value);
|
||||
};
|
||||
}
|
||||
|
||||
registerOnTouched(fn: () => void) {
|
||||
this.onTouched = fn;
|
||||
}
|
||||
|
||||
setDisabledState(isDisabled: boolean) {
|
||||
this.element.nativeElement.disabled = isDisabled;
|
||||
}
|
||||
}
|
||||
@@ -1,64 +0,0 @@
|
||||
import { Directive, ElementRef, HostListener } from '@angular/core';
|
||||
import { ControlValueAccessor, NG_VALUE_ACCESSOR } from '@angular/forms';
|
||||
|
||||
import { setIonicClasses } from './util/set-ionic-classes';
|
||||
|
||||
@Directive({
|
||||
/* tslint:disable-next-line:directive-selector */
|
||||
selector: 'ion-range, ion-select, ion-radio-group, ion-segment, ion-datetime',
|
||||
providers: [
|
||||
{
|
||||
provide: NG_VALUE_ACCESSOR,
|
||||
useExisting: SelectValueAccessor,
|
||||
multi: true
|
||||
}
|
||||
]
|
||||
})
|
||||
export class SelectValueAccessor implements ControlValueAccessor {
|
||||
|
||||
constructor(private element: ElementRef) {
|
||||
this.onChange = () => {/**/};
|
||||
this.onTouched = () => {/**/};
|
||||
}
|
||||
|
||||
onChange: (value: any) => void;
|
||||
onTouched: () => void;
|
||||
|
||||
writeValue(value: any) {
|
||||
this.element.nativeElement.value = value;
|
||||
|
||||
requestAnimationFrame(() => {
|
||||
setIonicClasses(this.element);
|
||||
});
|
||||
}
|
||||
|
||||
@HostListener('ionChange', ['$event.target.value'])
|
||||
_handleChangeEvent(value: any) {
|
||||
this.onChange(value);
|
||||
|
||||
requestAnimationFrame(() => {
|
||||
setIonicClasses(this.element);
|
||||
});
|
||||
}
|
||||
|
||||
@HostListener('ionBlur')
|
||||
_handleBlurEvent() {
|
||||
this.onTouched();
|
||||
|
||||
requestAnimationFrame(() => {
|
||||
setIonicClasses(this.element);
|
||||
});
|
||||
}
|
||||
|
||||
registerOnChange(fn: (value: any) => void) {
|
||||
this.onChange = fn;
|
||||
}
|
||||
|
||||
registerOnTouched(fn: () => void) {
|
||||
this.onTouched = fn;
|
||||
}
|
||||
|
||||
setDisabledState(isDisabled: boolean) {
|
||||
this.element.nativeElement.disabled = isDisabled;
|
||||
}
|
||||
}
|
||||
@@ -1,64 +0,0 @@
|
||||
import { Directive, ElementRef, HostListener } from '@angular/core';
|
||||
import { ControlValueAccessor, NG_VALUE_ACCESSOR } from '@angular/forms';
|
||||
|
||||
import { setIonicClasses } from './util/set-ionic-classes';
|
||||
|
||||
@Directive({
|
||||
/* tslint:disable-next-line:directive-selector */
|
||||
selector: 'ion-input:not([type=number]),ion-textarea,ion-searchbar',
|
||||
providers: [
|
||||
{
|
||||
provide: NG_VALUE_ACCESSOR,
|
||||
useExisting: TextValueAccessor,
|
||||
multi: true
|
||||
}
|
||||
]
|
||||
})
|
||||
export class TextValueAccessor implements ControlValueAccessor {
|
||||
|
||||
constructor(private element: ElementRef) {
|
||||
this.onChange = () => {/**/};
|
||||
this.onTouched = () => {/**/};
|
||||
}
|
||||
|
||||
onChange: (value: any) => void;
|
||||
onTouched: () => void;
|
||||
|
||||
writeValue(value: any) {
|
||||
this.element.nativeElement.value = value;
|
||||
|
||||
requestAnimationFrame(() => {
|
||||
setIonicClasses(this.element);
|
||||
});
|
||||
}
|
||||
|
||||
@HostListener('input', ['$event.target.value'])
|
||||
_handleInputEvent(value: any) {
|
||||
this.onChange(value);
|
||||
|
||||
requestAnimationFrame(() => {
|
||||
setIonicClasses(this.element);
|
||||
});
|
||||
}
|
||||
|
||||
@HostListener('ionBlur')
|
||||
_handleBlurEvent() {
|
||||
this.onTouched();
|
||||
|
||||
requestAnimationFrame(() => {
|
||||
setIonicClasses(this.element);
|
||||
});
|
||||
}
|
||||
|
||||
registerOnChange(fn: (value: any) => void) {
|
||||
this.onChange = fn;
|
||||
}
|
||||
|
||||
registerOnTouched(fn: () => void) {
|
||||
this.onTouched = fn;
|
||||
}
|
||||
|
||||
setDisabledState(isDisabled: boolean) {
|
||||
this.element.nativeElement.disabled = isDisabled;
|
||||
}
|
||||
}
|
||||
@@ -1,20 +0,0 @@
|
||||
import { ElementRef } from '@angular/core';
|
||||
|
||||
export function setIonicClasses(element: ElementRef) {
|
||||
const classList = element.nativeElement.classList;
|
||||
|
||||
classList.remove('ion-invalid');
|
||||
classList.remove('ion-valid');
|
||||
classList.remove('ion-touched');
|
||||
classList.remove('ion-untouched');
|
||||
classList.remove('ion-dirty');
|
||||
classList.remove('ion-pristine');
|
||||
classList.forEach((cls: string) => {
|
||||
if (cls === 'ng-invalid') { classList.add('ion-invalid'); }
|
||||
if (cls === 'ng-valid') { classList.add('ion-valid'); }
|
||||
if (cls === 'ng-touched') { classList.add('ion-touched'); }
|
||||
if (cls === 'ng-untouched') { classList.add('ion-untouched'); }
|
||||
if (cls === 'ng-dirty') { classList.add('ion-dirty'); }
|
||||
if (cls === 'ng-pristine') { classList.add('ion-pristine'); }
|
||||
});
|
||||
}
|
||||
@@ -1,45 +0,0 @@
|
||||
import { Directive, ElementRef, Input } from '@angular/core';
|
||||
import { inputs } from './proxies';
|
||||
|
||||
|
||||
@Directive({ selector: 'ion-icon' })
|
||||
export class Icon {
|
||||
|
||||
/**
|
||||
* The color to use from your Sass `$colors` map.
|
||||
* Default options are: `"primary"`, `"secondary"`, `"danger"`, `"light"`, and `"dark"`.
|
||||
* For more information, see [Theming your App](/docs/theming/theming-your-app).
|
||||
*/
|
||||
@Input() color: string;
|
||||
|
||||
/**
|
||||
* Specifies the label to use for accessibility. Defaults to the icon name.
|
||||
*/
|
||||
@Input() ariaLabel = '';
|
||||
|
||||
/**
|
||||
* Specifies which icon to use on `ios` mode.
|
||||
*/
|
||||
@Input() ios = '';
|
||||
|
||||
/**
|
||||
* Specifies which icon to use on `md` mode.
|
||||
*/
|
||||
@Input() md = '';
|
||||
|
||||
/**
|
||||
* Specifies which icon to use. The appropriate icon will be used based on the mode.
|
||||
* For more information, see [Ionicons](/docs/ionicons/).
|
||||
*/
|
||||
@Input() name = '';
|
||||
|
||||
/**
|
||||
* The size of the icon.
|
||||
* Available options are: `"small"` and `"large"`.
|
||||
*/
|
||||
@Input() size: string;
|
||||
|
||||
constructor(el: ElementRef) {
|
||||
inputs(this, el, ['color', 'ariaLabel', 'ios', 'md', 'name', 'size']);
|
||||
}
|
||||
}
|
||||
@@ -1,20 +0,0 @@
|
||||
|
||||
export { BooleanValueAccessor } from './control-value-accessors/boolean-value-accessor';
|
||||
export { NumericValueAccessor } from './control-value-accessors/numeric-value-accesssor';
|
||||
export { RadioValueAccessor } from './control-value-accessors/radio-value-accessor';
|
||||
export { SelectValueAccessor } from './control-value-accessors/select-value-accessor';
|
||||
export { TextValueAccessor } from './control-value-accessors/text-value-accessor';
|
||||
|
||||
export { GoBack } from './navigation/go-back';
|
||||
export { IonBackButton } from './navigation/ion-back-button';
|
||||
export { NavDelegate } from './navigation/nav-delegate';
|
||||
export { TabDelegate } from './navigation/tab-delegate';
|
||||
export { TabsDelegate } from './navigation/tabs-delegate';
|
||||
export { IonRouterOutlet } from './navigation/ion-router-outlet';
|
||||
export { HrefDelegate } from './navigation/href-delegate';
|
||||
|
||||
export { Icon } from './icon';
|
||||
export { VirtualScroll } from './virtual-scroll/virtual-scroll';
|
||||
export { VirtualItem } from './virtual-scroll/virtual-item';
|
||||
export { VirtualHeader } from './virtual-scroll/virtual-header';
|
||||
export { VirtualFooter } from './virtual-scroll/virtual-footer';
|
||||
@@ -1,17 +0,0 @@
|
||||
import { Directive, HostListener } from '@angular/core';
|
||||
import { NavController } from '../../providers/nav-controller';
|
||||
|
||||
@Directive({
|
||||
selector: '[goBack]',
|
||||
})
|
||||
export class GoBack {
|
||||
|
||||
constructor(
|
||||
private navCtrl: NavController,
|
||||
) {}
|
||||
|
||||
@HostListener('click')
|
||||
onClick() {
|
||||
this.navCtrl.setGoback();
|
||||
}
|
||||
}
|
||||
@@ -1,30 +0,0 @@
|
||||
import { Directive, ElementRef, HostListener, Input, Optional } from '@angular/core';
|
||||
import { Router } from '@angular/router';
|
||||
|
||||
@Directive({
|
||||
selector: 'ion-anchor,ion-button,ion-item'
|
||||
})
|
||||
export class HrefDelegate {
|
||||
|
||||
@Input()
|
||||
set href(value: string) {
|
||||
this.elementRef.nativeElement.href = value;
|
||||
}
|
||||
get href() {
|
||||
return this.elementRef.nativeElement.href;
|
||||
}
|
||||
|
||||
constructor(
|
||||
@Optional() private router: Router,
|
||||
private elementRef: ElementRef
|
||||
) {}
|
||||
|
||||
@HostListener('click', ['$event'])
|
||||
onClick(ev: Event) {
|
||||
const url = this.href;
|
||||
if (this.router && url != null && url[0] !== '#' && url.indexOf('://') === -1) {
|
||||
ev.preventDefault();
|
||||
this.router.navigateByUrl(url);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,37 +0,0 @@
|
||||
import { Directive, ElementRef, HostListener, Input, Optional } from '@angular/core';
|
||||
import { IonRouterOutlet } from './ion-router-outlet';
|
||||
import { Router } from '@angular/router';
|
||||
import { NavController } from '../..';
|
||||
|
||||
@Directive({
|
||||
selector: 'ion-back-button'
|
||||
})
|
||||
export class IonBackButton {
|
||||
|
||||
@Input()
|
||||
set defaultHref(value: string) {
|
||||
this.elementRef.nativeElement.defaultHref = value;
|
||||
}
|
||||
get defaultHref() {
|
||||
return this.elementRef.nativeElement.defaultHref;
|
||||
}
|
||||
|
||||
constructor(
|
||||
@Optional() private router: Router,
|
||||
@Optional() private routerOutlet: IonRouterOutlet,
|
||||
private navCtrl: NavController,
|
||||
private elementRef: ElementRef,
|
||||
) {}
|
||||
|
||||
@HostListener('click', ['$event'])
|
||||
onClick(ev: Event) {
|
||||
if (this.routerOutlet && this.routerOutlet.canGoBack()) {
|
||||
this.routerOutlet.pop();
|
||||
ev.preventDefault();
|
||||
} else if (this.router && this.defaultHref != null) {
|
||||
this.navCtrl.setGoback();
|
||||
this.router.navigateByUrl(this.defaultHref);
|
||||
ev.preventDefault();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,185 +0,0 @@
|
||||
import { Attribute, ChangeDetectorRef, ComponentFactoryResolver, ComponentRef, Directive, ElementRef, EventEmitter, Injector, OnDestroy, OnInit, Optional, Output, ViewContainerRef } from '@angular/core';
|
||||
import { ActivatedRoute, ChildrenOutletContexts, PRIMARY_OUTLET, Router } from '@angular/router';
|
||||
import { StackController } from './router-controller';
|
||||
import { NavController } from '../../providers/nav-controller';
|
||||
import { bindLifecycleEvents } from '../../providers/angular-delegate';
|
||||
|
||||
@Directive({
|
||||
selector: 'ion-router-outlet',
|
||||
exportAs: 'outlet'
|
||||
})
|
||||
export class IonRouterOutlet implements OnDestroy, OnInit {
|
||||
|
||||
private activated: ComponentRef<any>|null = null;
|
||||
|
||||
private _activatedRoute: ActivatedRoute|null = null;
|
||||
private name: string;
|
||||
private stackCtrl: StackController;
|
||||
|
||||
@Output('activate') activateEvents = new EventEmitter<any>();
|
||||
@Output('deactivate') deactivateEvents = new EventEmitter<any>();
|
||||
|
||||
constructor(
|
||||
private parentContexts: ChildrenOutletContexts,
|
||||
private location: ViewContainerRef,
|
||||
private resolver: ComponentFactoryResolver,
|
||||
private elementRef: ElementRef,
|
||||
@Attribute('name') name: string,
|
||||
@Optional() @Attribute('stack') stack: any,
|
||||
private changeDetector: ChangeDetectorRef,
|
||||
private navCtrl: NavController,
|
||||
router: Router
|
||||
) {
|
||||
this.name = name || PRIMARY_OUTLET;
|
||||
parentContexts.onChildOutletCreated(this.name, this as any);
|
||||
this.stackCtrl = new StackController(stack != null, elementRef.nativeElement, router, this.navCtrl);
|
||||
}
|
||||
|
||||
ngOnDestroy(): void {
|
||||
this.parentContexts.onChildOutletDestroyed(this.name);
|
||||
}
|
||||
|
||||
ngOnInit(): void {
|
||||
if (!this.activated) {
|
||||
// If the outlet was not instantiated at the time the route got activated we need to populate
|
||||
// the outlet when it is initialized (ie inside a NgIf)
|
||||
const context = this.parentContexts.getContext(this.name);
|
||||
if (context && context.route) {
|
||||
if (context.attachRef) {
|
||||
// `attachRef` is populated when there is an existing component to mount
|
||||
this.attach(context.attachRef, context.route);
|
||||
} else {
|
||||
// otherwise the component defined in the configuration is created
|
||||
this.activateWith(context.route, context.resolver || null);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
get isActivated(): boolean { return !!this.activated; }
|
||||
|
||||
get component(): Object {
|
||||
if (!this.activated) {
|
||||
throw new Error('Outlet is not activated');
|
||||
}
|
||||
return this.activated.instance;
|
||||
}
|
||||
|
||||
get activatedRoute(): ActivatedRoute {
|
||||
if (!this.activated) {
|
||||
throw new Error('Outlet is not activated');
|
||||
}
|
||||
return this._activatedRoute as ActivatedRoute;
|
||||
}
|
||||
|
||||
get activatedRouteData() {
|
||||
if (this._activatedRoute) {
|
||||
return this._activatedRoute.snapshot.data;
|
||||
}
|
||||
return {};
|
||||
}
|
||||
|
||||
/**
|
||||
* Called when the `RouteReuseStrategy` instructs to detach the subtree
|
||||
*/
|
||||
detach(): ComponentRef<any> {
|
||||
if (!this.activated) {
|
||||
throw new Error('Outlet is not activated');
|
||||
}
|
||||
this.location.detach();
|
||||
const cmp = this.activated;
|
||||
this.activated = null;
|
||||
this._activatedRoute = null;
|
||||
return cmp;
|
||||
}
|
||||
|
||||
/**
|
||||
* Called when the `RouteReuseStrategy` instructs to re-attach a previously detached subtree
|
||||
*/
|
||||
attach(ref: ComponentRef<any>, activatedRoute: ActivatedRoute) {
|
||||
this.activated = ref;
|
||||
this._activatedRoute = activatedRoute;
|
||||
this.location.insert(ref.hostView);
|
||||
}
|
||||
|
||||
deactivate(): void {
|
||||
if (this.activated) {
|
||||
const c = this.component;
|
||||
this.activated = null;
|
||||
this._activatedRoute = null;
|
||||
this.deactivateEvents.emit(c);
|
||||
}
|
||||
}
|
||||
|
||||
async activateWith(activatedRoute: ActivatedRoute, resolver: ComponentFactoryResolver|null) {
|
||||
if (this.isActivated) {
|
||||
throw new Error('Cannot activate an already activated outlet');
|
||||
}
|
||||
this._activatedRoute = activatedRoute;
|
||||
|
||||
let enteringView = this.stackCtrl.getExistingView(activatedRoute);
|
||||
if (enteringView) {
|
||||
this.activated = enteringView.ref;
|
||||
} else {
|
||||
const snapshot = (activatedRoute as any)._futureSnapshot;
|
||||
const component = <any>snapshot.routeConfig !.component;
|
||||
resolver = resolver || this.resolver;
|
||||
|
||||
const factory = resolver.resolveComponentFactory(component);
|
||||
const childContexts = this.parentContexts.getOrCreateContext(this.name).children;
|
||||
|
||||
const injector = new OutletInjector(activatedRoute, childContexts, this.location.injector);
|
||||
const cmp = this.activated = this.location.createComponent(factory, this.location.length, injector);
|
||||
|
||||
bindLifecycleEvents(cmp.instance, cmp.location.nativeElement);
|
||||
|
||||
// Calling `markForCheck` to make sure we will run the change detection when the
|
||||
// `RouterOutlet` is inside a `ChangeDetectionStrategy.OnPush` component.
|
||||
this.changeDetector.markForCheck();
|
||||
enteringView = this.stackCtrl.createView(this.activated, activatedRoute);
|
||||
}
|
||||
|
||||
const direction = this.navCtrl.consumeDirection();
|
||||
await this.stackCtrl.setActive(enteringView, direction);
|
||||
this.activateEvents.emit(this.activated.instance);
|
||||
|
||||
emitEvent(this.elementRef.nativeElement);
|
||||
}
|
||||
|
||||
canGoBack(deep = 1) {
|
||||
return this.stackCtrl.canGoBack(deep);
|
||||
}
|
||||
|
||||
pop(deep = 1) {
|
||||
return this.stackCtrl.pop(deep);
|
||||
}
|
||||
}
|
||||
|
||||
function emitEvent(el: HTMLElement) {
|
||||
console.log('ionRouterOutletActivated');
|
||||
const event = new CustomEvent('ionRouterOutletActivated', {
|
||||
bubbles: true,
|
||||
cancelable: true,
|
||||
});
|
||||
el.dispatchEvent(event);
|
||||
}
|
||||
|
||||
class OutletInjector implements Injector {
|
||||
constructor(
|
||||
private route: ActivatedRoute,
|
||||
private childContexts: ChildrenOutletContexts,
|
||||
private parent: Injector
|
||||
) {}
|
||||
|
||||
get(token: any, notFoundValue?: any): any {
|
||||
if (token === ActivatedRoute) {
|
||||
return this.route;
|
||||
}
|
||||
|
||||
if (token === ChildrenOutletContexts) {
|
||||
return this.childContexts;
|
||||
}
|
||||
|
||||
return this.parent.get(token, notFoundValue);
|
||||
}
|
||||
}
|
||||
@@ -1,16 +0,0 @@
|
||||
import { ComponentFactoryResolver, Directive, ElementRef, Injector } from '@angular/core';
|
||||
import { AngularDelegate } from '../../providers/angular-delegate';
|
||||
|
||||
@Directive({
|
||||
selector: 'ion-nav',
|
||||
})
|
||||
export class NavDelegate {
|
||||
constructor(
|
||||
ref: ElementRef,
|
||||
cfr: ComponentFactoryResolver,
|
||||
injector: Injector,
|
||||
angularDelegate: AngularDelegate,
|
||||
) {
|
||||
ref.nativeElement.delegate = angularDelegate.create(cfr, injector);
|
||||
}
|
||||
}
|
||||
@@ -1,138 +0,0 @@
|
||||
import { ComponentRef } from '@angular/core';
|
||||
import { ActivatedRoute, Router } from '@angular/router';
|
||||
import { NavDirection } from '@ionic/core';
|
||||
|
||||
import { NavController } from '../../providers/nav-controller';
|
||||
|
||||
|
||||
export class StackController {
|
||||
|
||||
private viewsSnapshot: RouteView[] = [];
|
||||
private views: RouteView[] = [];
|
||||
|
||||
constructor(
|
||||
private stack: boolean,
|
||||
private containerEl: HTMLIonRouterOutletElement,
|
||||
private router: Router,
|
||||
private navCtrl: NavController,
|
||||
) {}
|
||||
|
||||
createView(enteringRef: ComponentRef<any>, route: ActivatedRoute): RouteView {
|
||||
return {
|
||||
ref: enteringRef,
|
||||
element: (enteringRef && enteringRef.location && enteringRef.location.nativeElement) as HTMLElement,
|
||||
url: this.getUrl(route),
|
||||
deactivatedId: -1
|
||||
};
|
||||
}
|
||||
|
||||
getExistingView(activatedRoute: ActivatedRoute): RouteView|null {
|
||||
const activatedUrlKey = this.getUrl(activatedRoute);
|
||||
return this.views.find(vw => vw.url === activatedUrlKey);
|
||||
}
|
||||
|
||||
canGoBack(deep: number): boolean {
|
||||
return this.views.length > deep;
|
||||
}
|
||||
|
||||
async setActive(enteringView: RouteView, direction: number | undefined) {
|
||||
const leavingView = this.getActive();
|
||||
const forcedGoBack = direction === -1;
|
||||
const reused = this.insertView(enteringView, forcedGoBack);
|
||||
direction = direction != null ? direction : (reused ? -1 : 1);
|
||||
await this.transition(enteringView, leavingView, direction, this.canGoBack(1));
|
||||
|
||||
this.cleanup();
|
||||
}
|
||||
|
||||
pop(deep: number) {
|
||||
const view = this.views[this.views.length - deep - 1];
|
||||
this.navCtrl.setGoback();
|
||||
this.router.navigateByUrl(view.url);
|
||||
}
|
||||
|
||||
private insertView(enteringView: RouteView, forcedGoBack: boolean): boolean {
|
||||
if (this.stack) {
|
||||
const index = this.views.indexOf(enteringView);
|
||||
if (index >= 0) {
|
||||
this.views = this.views.slice(0, index + 1);
|
||||
return true;
|
||||
} else {
|
||||
if (forcedGoBack) {
|
||||
this.views = [enteringView];
|
||||
} else {
|
||||
this.views.push(enteringView);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
} else {
|
||||
this.views = [enteringView];
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
private cleanup() {
|
||||
this.viewsSnapshot
|
||||
.filter(view => !this.views.includes(view))
|
||||
.forEach(view => destroyView(view));
|
||||
|
||||
for (let i = 0; i < this.views.length - 1; i++) {
|
||||
this.views[i].element.hidden = true;
|
||||
}
|
||||
this.viewsSnapshot = this.views.slice();
|
||||
}
|
||||
|
||||
getActive(): RouteView | null {
|
||||
return this.views.length > 0 ? this.views[this.views.length - 1] : null;
|
||||
}
|
||||
|
||||
private async transition(enteringView: RouteView, leavingView: RouteView, direction: number, showGoBack: boolean) {
|
||||
const enteringEl = enteringView ? enteringView.element : undefined;
|
||||
const leavingEl = leavingView ? leavingView.element : undefined;
|
||||
const containerEl = this.containerEl;
|
||||
if (enteringEl && enteringEl !== leavingEl) {
|
||||
enteringEl.classList.add('ion-page', 'hide-page');
|
||||
containerEl.appendChild(enteringEl);
|
||||
|
||||
await containerEl.componentOnReady();
|
||||
await containerEl.commit(enteringEl, leavingEl, {
|
||||
duration: direction === 0 ? 0 : undefined,
|
||||
direction: direction === -1 ? NavDirection.Back : NavDirection.Forward,
|
||||
deepWait: true,
|
||||
showGoBack
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
private getUrl(activatedRoute: ActivatedRoute) {
|
||||
const urlTree = this.router.createUrlTree(['.'], { relativeTo: activatedRoute });
|
||||
return this.router.serializeUrl(urlTree);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
export function destroyView(view: RouteView) {
|
||||
if (view) {
|
||||
// TODO lifecycle event
|
||||
view.ref.destroy();
|
||||
}
|
||||
}
|
||||
|
||||
export function getLastDeactivatedRef(views: RouteView[]) {
|
||||
if (views.length < 2) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return views.sort((a, b) => {
|
||||
if (a.deactivatedId > b.deactivatedId) return -1;
|
||||
if (a.deactivatedId < b.deactivatedId) return 1;
|
||||
return 0;
|
||||
})[0].ref;
|
||||
}
|
||||
|
||||
export interface RouteView {
|
||||
url: string;
|
||||
element: HTMLElement;
|
||||
ref: ComponentRef<any>;
|
||||
deactivatedId: number;
|
||||
}
|
||||
@@ -1,31 +0,0 @@
|
||||
import { ComponentFactoryResolver, Directive, ElementRef, HostListener, Injector } from '@angular/core';
|
||||
import { AngularDelegate } from '../../providers/angular-delegate';
|
||||
|
||||
|
||||
@Directive({
|
||||
selector: 'ion-tab'
|
||||
})
|
||||
export class TabDelegate {
|
||||
|
||||
constructor(
|
||||
private elementRef: ElementRef,
|
||||
cfr: ComponentFactoryResolver,
|
||||
injector: Injector,
|
||||
angularDelegate: AngularDelegate,
|
||||
) {
|
||||
elementRef.nativeElement.delegate = angularDelegate.create(cfr, injector);
|
||||
}
|
||||
|
||||
@HostListener('ionRouterOutletActivated', ['$event'])
|
||||
async onNavChanged() {
|
||||
const tab = this.elementRef.nativeElement as HTMLIonTabElement;
|
||||
await tab.componentOnReady();
|
||||
const tabs = tab.closest('ion-tabs');
|
||||
if (tabs) {
|
||||
await tabs.componentOnReady();
|
||||
await tabs.select(tab);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -1,25 +0,0 @@
|
||||
import { Directive, ElementRef, HostListener, Optional } from '@angular/core';
|
||||
import { Router } from '@angular/router';
|
||||
|
||||
@Directive({
|
||||
selector: 'ion-tabs'
|
||||
})
|
||||
export class TabsDelegate {
|
||||
|
||||
constructor(
|
||||
@Optional() private router: Router,
|
||||
elementRef: ElementRef
|
||||
) {
|
||||
if (router) {
|
||||
elementRef.nativeElement.useRouter = true;
|
||||
}
|
||||
}
|
||||
|
||||
@HostListener('ionTabbarClick', ['$event'])
|
||||
onTabbarClick(ev: UIEvent) {
|
||||
const tabElm: HTMLIonTabElement = ev.detail as any;
|
||||
if (this.router && tabElm && tabElm.href) {
|
||||
this.router.navigateByUrl(tabElm.href);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,79 +0,0 @@
|
||||
|
||||
import * as d from './proxies';
|
||||
|
||||
export const DIRECTIVES = [
|
||||
d.App,
|
||||
d.Avatar,
|
||||
d.BackButton,
|
||||
d.Badge,
|
||||
d.Button,
|
||||
d.Buttons,
|
||||
d.Card,
|
||||
d.CardContent,
|
||||
d.CardHeader,
|
||||
d.CardSubtitle,
|
||||
d.CardTitle,
|
||||
d.Checkbox,
|
||||
d.Chip,
|
||||
d.ChipButton,
|
||||
d.Col,
|
||||
d.Content,
|
||||
d.Datetime,
|
||||
d.Fab,
|
||||
d.FabButton,
|
||||
d.FabList,
|
||||
d.Footer,
|
||||
d.Grid,
|
||||
d.Header,
|
||||
d.HideWhen,
|
||||
d.InfiniteScroll,
|
||||
d.InfiniteScrollContent,
|
||||
d.Input,
|
||||
d.Item,
|
||||
d.ItemDivider,
|
||||
d.ItemGroup,
|
||||
d.ItemOption,
|
||||
d.ItemOptions,
|
||||
d.ItemSliding,
|
||||
d.Label,
|
||||
d.List,
|
||||
d.ListHeader,
|
||||
d.Menu,
|
||||
d.MenuButton,
|
||||
d.MenuToggle,
|
||||
d.Nav,
|
||||
d.NavPop,
|
||||
d.NavPush,
|
||||
d.NavSetRoot,
|
||||
d.Note,
|
||||
d.Radio,
|
||||
d.RadioGroup,
|
||||
d.Range,
|
||||
d.Refresher,
|
||||
d.RefresherContent,
|
||||
d.Reorder,
|
||||
d.ReorderGroup,
|
||||
d.RippleEffect,
|
||||
d.Row,
|
||||
d.Scroll,
|
||||
d.Searchbar,
|
||||
d.Segment,
|
||||
d.SegmentButton,
|
||||
d.Select,
|
||||
d.SelectOption,
|
||||
d.SelectPopover,
|
||||
d.ShowWhen,
|
||||
d.SkeletonText,
|
||||
d.Slide,
|
||||
d.Slides,
|
||||
d.Spinner,
|
||||
d.SplitPane,
|
||||
d.Tab,
|
||||
d.Tabs,
|
||||
d.Text,
|
||||
d.Textarea,
|
||||
d.Thumbnail,
|
||||
d.Toggle,
|
||||
d.Toolbar,
|
||||
d.ToolbarTitle
|
||||
];
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,59 +0,0 @@
|
||||
import { ChangeDetectorRef, ContentChild, Directive, ElementRef, EmbeddedViewRef } from '@angular/core';
|
||||
import { VirtualItem } from './virtual-item';
|
||||
import { VirtualHeader } from './virtual-header';
|
||||
import { VirtualFooter } from './virtual-footer';
|
||||
import { VirtualContext } from './virtual-utils';
|
||||
|
||||
@Directive({
|
||||
selector: 'ion-virtual-scroll'
|
||||
})
|
||||
export class VirtualScroll {
|
||||
|
||||
@ContentChild(VirtualItem) itmTmp: VirtualItem;
|
||||
@ContentChild(VirtualHeader) hdrTmp: VirtualHeader;
|
||||
@ContentChild(VirtualFooter) ftrTmp: VirtualFooter;
|
||||
|
||||
constructor(
|
||||
private el: ElementRef,
|
||||
public cd: ChangeDetectorRef,
|
||||
) {
|
||||
this.el.nativeElement.itemRender = this.itemRender.bind(this);
|
||||
}
|
||||
|
||||
private itemRender(el: HTMLElement|null, cell: any, index?: number) {
|
||||
if (!el) {
|
||||
const node = this.itmTmp.viewContainer.createEmbeddedView(
|
||||
this.getComponent(cell.type),
|
||||
new VirtualContext(null, null, null),
|
||||
index
|
||||
);
|
||||
el = getElement(node);
|
||||
(el as any)['$ionView'] = node;
|
||||
}
|
||||
const node = (el as any)['$ionView'];
|
||||
const ctx = node.context;
|
||||
ctx.$implicit = cell.value;
|
||||
ctx.index = cell.index;
|
||||
node.detectChanges();
|
||||
return el;
|
||||
}
|
||||
|
||||
private getComponent(type: number) {
|
||||
switch (type) {
|
||||
case 0: return this.itmTmp.templateRef;
|
||||
case 1: return this.hdrTmp.templateRef;
|
||||
case 2: return this.ftrTmp.templateRef;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
function getElement(view: EmbeddedViewRef<VirtualContext>): HTMLElement {
|
||||
const rootNodes = view.rootNodes;
|
||||
for (let i = 0; i < rootNodes.length; i++) {
|
||||
if (rootNodes[i].nodeType === 1) {
|
||||
return rootNodes[i];
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
@@ -1,14 +0,0 @@
|
||||
|
||||
export class VirtualContext {
|
||||
|
||||
constructor(public $implicit: any, public index: number, public count: number) { }
|
||||
|
||||
get first(): boolean { return this.index === 0; }
|
||||
|
||||
get last(): boolean { return this.index === this.count - 1; }
|
||||
|
||||
get even(): boolean { return this.index % 2 === 0; }
|
||||
|
||||
get odd(): boolean { return !this.even; }
|
||||
|
||||
}
|
||||
@@ -1,17 +0,0 @@
|
||||
// export module
|
||||
export { IonicModule } from './module';
|
||||
|
||||
// export auto generated directive
|
||||
export * from './directives/proxies';
|
||||
|
||||
// export custom directives
|
||||
export * from './directives';
|
||||
|
||||
// export custom providers
|
||||
export * from './providers';
|
||||
|
||||
// ionic types
|
||||
export * from './types/interfaces';
|
||||
|
||||
/*tslint:disable*/
|
||||
import './ionic-angular';
|
||||
@@ -1,32 +0,0 @@
|
||||
/*tslint:disable*/
|
||||
import './ionic';
|
||||
import { IonicWindow } from './types/interfaces';
|
||||
|
||||
const win = (window as IonicWindow);
|
||||
const Ionic = win.Ionic;
|
||||
|
||||
if (Ionic) {
|
||||
Ionic.ael = function ngAddEventListener(elm, eventName, cb, opts) {
|
||||
if (elm.__zone_symbol__addEventListener) {
|
||||
elm.__zone_symbol__addEventListener(eventName, cb, opts);
|
||||
} else {
|
||||
elm.addEventListener(eventName, cb, opts);
|
||||
}
|
||||
};
|
||||
|
||||
Ionic.rel = function ngRemoveEventListener(elm, eventName, cb, opts) {
|
||||
if (elm.__zone_symbol__removeEventListener) {
|
||||
elm.__zone_symbol__removeEventListener(eventName, cb, opts);
|
||||
} else {
|
||||
elm.removeEventListener(eventName, cb, opts);
|
||||
}
|
||||
};
|
||||
|
||||
Ionic.raf = function ngRequestAnimationFrame(cb: any) {
|
||||
if (win.__zone_symbol__requestAnimationFrame) {
|
||||
win.__zone_symbol__requestAnimationFrame(cb);
|
||||
} else {
|
||||
win.requestAnimationFrame(cb);
|
||||
}
|
||||
};
|
||||
}
|
||||
@@ -1,3 +0,0 @@
|
||||
|
||||
// placeholder for ionic loader js
|
||||
// created by the stencil build process
|
||||
@@ -1,145 +0,0 @@
|
||||
import { ModuleWithProviders, NgModule } from '@angular/core';
|
||||
import { CommonModule } from '@angular/common';
|
||||
|
||||
import * as c from './directives';
|
||||
import * as d from './directives/proxies';
|
||||
import * as p from './providers';
|
||||
|
||||
|
||||
const DECLARATIONS = [
|
||||
// proxies
|
||||
d.App,
|
||||
d.Avatar,
|
||||
d.BackButton,
|
||||
d.Badge,
|
||||
d.Button,
|
||||
d.Buttons,
|
||||
d.Card,
|
||||
d.CardContent,
|
||||
d.CardHeader,
|
||||
d.CardSubtitle,
|
||||
d.CardTitle,
|
||||
d.Checkbox,
|
||||
d.Chip,
|
||||
d.ChipButton,
|
||||
d.Col,
|
||||
d.Content,
|
||||
d.Datetime,
|
||||
d.Fab,
|
||||
d.FabButton,
|
||||
d.FabList,
|
||||
d.Footer,
|
||||
d.Grid,
|
||||
d.Header,
|
||||
d.HideWhen,
|
||||
d.InfiniteScroll,
|
||||
d.InfiniteScrollContent,
|
||||
d.Input,
|
||||
d.Item,
|
||||
d.ItemDivider,
|
||||
d.ItemGroup,
|
||||
d.ItemOption,
|
||||
d.ItemOptions,
|
||||
d.ItemSliding,
|
||||
d.Label,
|
||||
d.List,
|
||||
d.ListHeader,
|
||||
d.Menu,
|
||||
d.MenuButton,
|
||||
d.MenuToggle,
|
||||
d.Nav,
|
||||
d.NavPop,
|
||||
d.NavPush,
|
||||
d.NavSetRoot,
|
||||
d.Note,
|
||||
d.Radio,
|
||||
d.RadioGroup,
|
||||
d.Range,
|
||||
d.Refresher,
|
||||
d.RefresherContent,
|
||||
d.Reorder,
|
||||
d.ReorderGroup,
|
||||
d.RippleEffect,
|
||||
d.Row,
|
||||
d.Scroll,
|
||||
d.Searchbar,
|
||||
d.Segment,
|
||||
d.SegmentButton,
|
||||
d.Select,
|
||||
d.SelectOption,
|
||||
d.SelectPopover,
|
||||
d.ShowWhen,
|
||||
d.SkeletonText,
|
||||
d.Slide,
|
||||
d.Slides,
|
||||
d.Spinner,
|
||||
d.SplitPane,
|
||||
d.Tab,
|
||||
d.Tabs,
|
||||
d.Text,
|
||||
d.Textarea,
|
||||
d.Thumbnail,
|
||||
d.Toggle,
|
||||
d.Toolbar,
|
||||
d.ToolbarTitle,
|
||||
|
||||
// custom proxy
|
||||
c.Icon,
|
||||
|
||||
// ngModel accessors
|
||||
c.BooleanValueAccessor,
|
||||
c.NumericValueAccessor,
|
||||
c.RadioValueAccessor,
|
||||
c.SelectValueAccessor,
|
||||
c.TextValueAccessor,
|
||||
|
||||
// navigation
|
||||
c.GoBack,
|
||||
c.IonBackButton,
|
||||
c.IonRouterOutlet,
|
||||
c.NavDelegate,
|
||||
c.TabDelegate,
|
||||
c.TabsDelegate,
|
||||
c.HrefDelegate,
|
||||
|
||||
// virtual scroll
|
||||
c.VirtualFooter,
|
||||
c.VirtualHeader,
|
||||
c.VirtualItem,
|
||||
c.VirtualScroll,
|
||||
];
|
||||
|
||||
const PROVIDERS = [
|
||||
p.ActionSheetController,
|
||||
p.AlertController,
|
||||
p.LoadingController,
|
||||
p.PickerController,
|
||||
p.ToastController,
|
||||
p.MenuController,
|
||||
p.NavController,
|
||||
p.Platform,
|
||||
p.Events,
|
||||
];
|
||||
|
||||
@NgModule({
|
||||
declarations: DECLARATIONS,
|
||||
exports: DECLARATIONS,
|
||||
providers: [
|
||||
p.AngularDelegate,
|
||||
p.ModalController,
|
||||
p.PopoverController,
|
||||
],
|
||||
imports: [
|
||||
CommonModule,
|
||||
]
|
||||
})
|
||||
export class IonicModule {
|
||||
static forRoot(): ModuleWithProviders {
|
||||
return {
|
||||
ngModule: IonicModule,
|
||||
providers: [
|
||||
...PROVIDERS,
|
||||
]
|
||||
};
|
||||
}
|
||||
}
|
||||
@@ -1,10 +0,0 @@
|
||||
import { Injectable } from '@angular/core';
|
||||
import { ActionSheetOptions } from '@ionic/core';
|
||||
import { OverlayBaseController } from '../util/overlay';
|
||||
|
||||
@Injectable()
|
||||
export class ActionSheetController extends OverlayBaseController<ActionSheetOptions, HTMLIonActionSheetElement> {
|
||||
constructor() {
|
||||
super('ion-action-sheet-controller');
|
||||
}
|
||||
}
|
||||
@@ -1,10 +0,0 @@
|
||||
import { Injectable } from '@angular/core';
|
||||
import { AlertOptions } from '@ionic/core';
|
||||
import { OverlayBaseController } from '../util/overlay';
|
||||
|
||||
@Injectable()
|
||||
export class AlertController extends OverlayBaseController<AlertOptions, HTMLIonAlertElement> {
|
||||
constructor() {
|
||||
super('ion-alert-controller');
|
||||
}
|
||||
}
|
||||
@@ -1,81 +0,0 @@
|
||||
import {
|
||||
ApplicationRef,
|
||||
ComponentFactoryResolver,
|
||||
Injectable,
|
||||
Injector,
|
||||
} from '@angular/core';
|
||||
|
||||
import { FrameworkDelegate, ViewLifecycle } from '@ionic/core';
|
||||
|
||||
|
||||
@Injectable()
|
||||
export class AngularDelegate {
|
||||
|
||||
constructor(
|
||||
private appRef: ApplicationRef
|
||||
) {}
|
||||
|
||||
create(cfr: ComponentFactoryResolver, injector: Injector) {
|
||||
return new AngularFrameworkDelegate(cfr, injector, this.appRef);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
export class AngularFrameworkDelegate implements FrameworkDelegate {
|
||||
|
||||
private elRefMap = new WeakMap<HTMLElement, any>();
|
||||
|
||||
constructor(
|
||||
private cfr: ComponentFactoryResolver,
|
||||
private injector: Injector,
|
||||
private appRef: ApplicationRef
|
||||
) {}
|
||||
|
||||
attachViewToDom(container: any, component: any, data?: any, cssClasses?: string[]): Promise<any> {
|
||||
|
||||
const componentFactory = this.cfr.resolveComponentFactory(component);
|
||||
const hostElement = document.createElement(componentFactory.selector);
|
||||
if (data) {
|
||||
Object.assign(hostElement, data);
|
||||
}
|
||||
|
||||
const childInjector = Injector.create([], this.injector);
|
||||
const componentRef = componentFactory.create(childInjector, [], hostElement);
|
||||
for (const clazz of cssClasses) {
|
||||
hostElement.classList.add(clazz);
|
||||
}
|
||||
bindLifecycleEvents(componentRef.instance, hostElement);
|
||||
container.appendChild(hostElement);
|
||||
|
||||
this.appRef.attachView(componentRef.hostView);
|
||||
this.elRefMap.set(hostElement, componentRef);
|
||||
return Promise.resolve(hostElement);
|
||||
}
|
||||
|
||||
removeViewFromDom(_container: any, component: any): Promise<void> {
|
||||
const componentRef = this.elRefMap.get(component);
|
||||
if (componentRef) {
|
||||
componentRef.destroy();
|
||||
this.elRefMap.delete(component);
|
||||
}
|
||||
return Promise.resolve();
|
||||
}
|
||||
}
|
||||
|
||||
const LIFECYCLES = [
|
||||
ViewLifecycle.WillEnter,
|
||||
ViewLifecycle.DidEnter,
|
||||
ViewLifecycle.WillLeave,
|
||||
ViewLifecycle.DidLeave,
|
||||
ViewLifecycle.WillUnload
|
||||
];
|
||||
|
||||
export function bindLifecycleEvents(instance: any, element: HTMLElement) {
|
||||
LIFECYCLES.forEach(eventName => {
|
||||
element.addEventListener(eventName, (ev: CustomEvent) => {
|
||||
if (typeof instance[eventName] === 'function') {
|
||||
instance[eventName](ev.detail);
|
||||
}
|
||||
});
|
||||
});
|
||||
}
|
||||
@@ -1,100 +0,0 @@
|
||||
import { Injectable } from '@angular/core';
|
||||
|
||||
|
||||
@Injectable()
|
||||
export class Events {
|
||||
private c: {[topic: string]: Function[]} = [] as any;
|
||||
|
||||
/**
|
||||
* Subscribe to an event topic. Events that get posted to that topic will trigger the provided handler.
|
||||
*
|
||||
* @param {string} topic the topic to subscribe to
|
||||
* @param {function} handler the event handler
|
||||
*/
|
||||
subscribe(topic: string, ...handlers: Function[]) {
|
||||
if (!this.c[topic]) {
|
||||
this.c[topic] = [];
|
||||
}
|
||||
handlers.forEach((handler) => {
|
||||
this.c[topic].push(handler);
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Unsubscribe from the given topic. Your handler will no longer receive events published to this topic.
|
||||
*
|
||||
* @param {string} topic the topic to unsubscribe from
|
||||
* @param {function} handler the event handler
|
||||
*
|
||||
* @return true if a handler was removed
|
||||
*/
|
||||
unsubscribe(topic: string, handler: Function = null) {
|
||||
const t = this.c[topic];
|
||||
if (!t) {
|
||||
// Wasn't found, wasn't removed
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!handler) {
|
||||
// Remove all handlers for this topic
|
||||
delete this.c[topic];
|
||||
return true;
|
||||
}
|
||||
|
||||
// We need to find and remove a specific handler
|
||||
const i = t.indexOf(handler);
|
||||
|
||||
if (i < 0) {
|
||||
// Wasn't found, wasn't removed
|
||||
return false;
|
||||
}
|
||||
|
||||
t.splice(i, 1);
|
||||
|
||||
// If the channel is empty now, remove it from the channel map
|
||||
if (!t.length) {
|
||||
delete this.c[topic];
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Publish an event to the given topic.
|
||||
*
|
||||
* @param {string} topic the topic to publish to
|
||||
* @param {any} eventData the data to send as the event
|
||||
*/
|
||||
publish(topic: string, ...args: any[]) {
|
||||
const t = this.c[topic];
|
||||
if (!t) {
|
||||
return null;
|
||||
}
|
||||
|
||||
const responses: any[] = [];
|
||||
t.forEach((handler: any) => {
|
||||
responses.push(handler(...args));
|
||||
});
|
||||
return responses;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
export function setupEvents() {
|
||||
const events = new Events();
|
||||
|
||||
window.addEventListener('online', ev => events.publish('app:online', ev));
|
||||
|
||||
window.addEventListener('offline', ev => events.publish('app:offline', ev));
|
||||
|
||||
window.addEventListener('orientationchange', ev => events.publish('app:rotated', ev));
|
||||
|
||||
return events;
|
||||
}
|
||||
|
||||
|
||||
export function setupProvideEvents() {
|
||||
return function() {
|
||||
return setupEvents();
|
||||
};
|
||||
}
|
||||
@@ -1,13 +0,0 @@
|
||||
|
||||
export { AngularDelegate } from './angular-delegate';
|
||||
export { ActionSheetController } from './action-sheet-controller';
|
||||
export { AlertController } from './alert-controller';
|
||||
export { Events } from './events';
|
||||
export { LoadingController } from './loading-controller';
|
||||
export { MenuController } from './menu-controller';
|
||||
export { PickerController } from './picker-controller';
|
||||
export { ModalController } from './modal-controller';
|
||||
export { Platform } from './platform';
|
||||
export { PopoverController } from './popover-controller';
|
||||
export { ToastController } from './toast-controller';
|
||||
export { NavController } from './nav-controller';
|
||||
@@ -1,10 +0,0 @@
|
||||
import { Injectable } from '@angular/core';
|
||||
import { LoadingOptions } from '@ionic/core';
|
||||
import { OverlayBaseController } from '../util/overlay';
|
||||
|
||||
@Injectable()
|
||||
export class LoadingController extends OverlayBaseController<LoadingOptions, HTMLIonLoadingElement> {
|
||||
constructor() {
|
||||
super('ion-loading-controller');
|
||||
}
|
||||
}
|
||||
@@ -1,104 +0,0 @@
|
||||
import { Injectable } from '@angular/core';
|
||||
import { proxyMethod } from '../util/util';
|
||||
|
||||
const CTRL = 'ion-menu-controller';
|
||||
@Injectable()
|
||||
export class MenuController {
|
||||
|
||||
/**
|
||||
* Programatically open the Menu.
|
||||
* @param {string} [menuId] Optionally get the menu by its id, or side.
|
||||
* @return {Promise} returns a promise when the menu is fully opened
|
||||
*/
|
||||
open(menuId?: string): Promise<boolean> {
|
||||
return proxyMethod(CTRL, 'open', menuId);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Programatically close the Menu. If no `menuId` is given as the first
|
||||
* argument then it'll close any menu which is open. If a `menuId`
|
||||
* is given then it'll close that exact menu.
|
||||
* @param {string} [menuId] Optionally get the menu by its id, or side.
|
||||
* @return {Promise} returns a promise when the menu is fully closed
|
||||
*/
|
||||
close(menuId?: string): Promise<boolean> {
|
||||
return proxyMethod(CTRL, 'close', menuId);
|
||||
}
|
||||
|
||||
/**
|
||||
* Toggle the menu. If it's closed, it will open, and if opened, it
|
||||
* will close.
|
||||
* @param {string} [menuId] Optionally get the menu by its id, or side.
|
||||
* @return {Promise} returns a promise when the menu has been toggled
|
||||
*/
|
||||
toggle(menuId?: string): Promise<boolean> {
|
||||
return proxyMethod(CTRL, 'toggle', menuId);
|
||||
}
|
||||
|
||||
/**
|
||||
* Used to enable or disable a menu. For example, there could be multiple
|
||||
* left menus, but only one of them should be able to be opened at the same
|
||||
* time. If there are multiple menus on the same side, then enabling one menu
|
||||
* will also automatically disable all the others that are on the same side.
|
||||
* @param {string} [menuId] Optionally get the menu by its id, or side.
|
||||
* @return {HTMLIonMenuElement} Returns the instance of the menu, which is useful for chaining.
|
||||
*/
|
||||
enable(shouldEnable: boolean, menuId?: string): Promise<HTMLIonMenuElement> {
|
||||
return proxyMethod(CTRL, 'enable', shouldEnable, menuId);
|
||||
}
|
||||
|
||||
/**
|
||||
* Used to enable or disable the ability to swipe open the menu.
|
||||
* @param {boolean} shouldEnable True if it should be swipe-able, false if not.
|
||||
* @param {string} [menuId] Optionally get the menu by its id, or side.
|
||||
* @return {HTMLIonMenuElement} Returns the instance of the menu, which is useful for chaining.
|
||||
*/
|
||||
swipeEnable(shouldEnable: boolean, menuId?: string): Promise<HTMLIonMenuElement> {
|
||||
return proxyMethod(CTRL, 'swipeEnable', shouldEnable, menuId);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {string} [menuId] Optionally get the menu by its id, or side.
|
||||
* @return {boolean} Returns true if the specified menu is currently open, otherwise false.
|
||||
* If the menuId is not specified, it returns true if ANY menu is currenly open.
|
||||
*/
|
||||
isOpen(menuId?: string): Promise<boolean> {
|
||||
return proxyMethod(CTRL, 'isOpen', menuId);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {string} [menuId] Optionally get the menu by its id, or side.
|
||||
* @return {boolean} Returns true if the menu is currently enabled, otherwise false.
|
||||
*/
|
||||
isEnabled(menuId?: string): Promise<boolean> {
|
||||
return proxyMethod(CTRL, 'isEnabled', menuId);
|
||||
}
|
||||
|
||||
/**
|
||||
* Used to get a menu instance. If a `menuId` is not provided then it'll
|
||||
* return the first menu found. If a `menuId` is `left` or `right`, then
|
||||
* it'll return the enabled menu on that side. Otherwise, if a `menuId` is
|
||||
* provided, then it'll try to find the menu using the menu's `id`
|
||||
* property. If a menu is not found then it'll return `null`.
|
||||
* @param {string} [menuId] Optionally get the menu by its id, or side.
|
||||
* @return {HTMLIonMenuElement} Returns the instance of the menu if found, otherwise `null`.
|
||||
*/
|
||||
get(menuId?: string): Promise<HTMLIonMenuElement> {
|
||||
return proxyMethod(CTRL, 'get', menuId);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return {Menu} Returns the instance of the menu already opened, otherwise `null`.
|
||||
*/
|
||||
getOpen(): Promise<HTMLIonMenuElement> {
|
||||
return proxyMethod(CTRL, 'getOpen');
|
||||
}
|
||||
|
||||
/**
|
||||
* @return {Array<HTMLIonMenuElement>} Returns an array of all menu instances.
|
||||
*/
|
||||
getMenus(): Promise<HTMLIonMenuElement[]> {
|
||||
return proxyMethod(CTRL, 'getMenus');
|
||||
}
|
||||
}
|
||||
@@ -1,22 +0,0 @@
|
||||
import { ComponentFactoryResolver, Injectable, Injector } from '@angular/core';
|
||||
import { ModalOptions } from '@ionic/core';
|
||||
import { OverlayBaseController } from '../util/overlay';
|
||||
import { AngularDelegate } from './angular-delegate';
|
||||
|
||||
@Injectable()
|
||||
export class ModalController extends OverlayBaseController<ModalOptions, HTMLIonModalElement> {
|
||||
constructor(
|
||||
private cfr: ComponentFactoryResolver,
|
||||
private injector: Injector,
|
||||
private angularDelegate: AngularDelegate,
|
||||
) {
|
||||
super('ion-modal-controller');
|
||||
}
|
||||
|
||||
create(opts?: ModalOptions): Promise<HTMLIonModalElement> {
|
||||
return super.create({
|
||||
...opts,
|
||||
delegate: this.angularDelegate.create(this.cfr, this.injector)
|
||||
});
|
||||
}
|
||||
}
|
||||
@@ -1,34 +0,0 @@
|
||||
import { Injectable } from '@angular/core';
|
||||
|
||||
@Injectable()
|
||||
export class NavController {
|
||||
|
||||
private direction = 0;
|
||||
private goBack = false;
|
||||
private stack: string[] = [];
|
||||
|
||||
setGoback() {
|
||||
this.goBack = true;
|
||||
}
|
||||
|
||||
consumeDirection() {
|
||||
if (this.direction === 0) {
|
||||
const index = this.stack.indexOf(document.location.href);
|
||||
if (index === -1) {
|
||||
this.stack.push(document.location.href);
|
||||
this.direction = 1;
|
||||
} else if (index < this.stack.length - 1) {
|
||||
this.stack = this.stack.slice(0, index + 1);
|
||||
this.direction = -1;
|
||||
}
|
||||
}
|
||||
|
||||
const direction = this.goBack
|
||||
? -1
|
||||
: this.direction;
|
||||
|
||||
this.goBack = false;
|
||||
this.direction = 0;
|
||||
return direction;
|
||||
}
|
||||
}
|
||||
@@ -1,10 +0,0 @@
|
||||
import { Injectable } from '@angular/core';
|
||||
import { PickerOptions } from '@ionic/core';
|
||||
import { OverlayBaseController } from '../util/overlay';
|
||||
|
||||
@Injectable()
|
||||
export class PickerController extends OverlayBaseController<PickerOptions, HTMLIonPickerElement> {
|
||||
constructor() {
|
||||
super('ion-picker-controller');
|
||||
}
|
||||
}
|
||||
@@ -1,228 +0,0 @@
|
||||
|
||||
import { PlatformConfig } from '@ionic/core';
|
||||
|
||||
export type DocumentDirection = 'ltr' | 'rtl';
|
||||
|
||||
let dir: DocumentDirection = 'ltr';
|
||||
let isRtl = false;
|
||||
let lang = '';
|
||||
|
||||
export class Platform {
|
||||
|
||||
_element: HTMLIonPlatformElement;
|
||||
constructor() {
|
||||
initialize(this);
|
||||
}
|
||||
|
||||
is(platformName: string): boolean {
|
||||
return isImpl(this, platformName);
|
||||
}
|
||||
|
||||
isAsync(platformName: string): Promise<boolean> {
|
||||
return isAsyncImpl(this, platformName);
|
||||
}
|
||||
|
||||
platforms(): string[] {
|
||||
return platformsImpl(this);
|
||||
}
|
||||
|
||||
platformsAsync(): Promise<string[]> {
|
||||
return platformsAsyncImpl(this);
|
||||
}
|
||||
|
||||
versions(): PlatformConfig[] {
|
||||
return versionsImpl(this);
|
||||
}
|
||||
|
||||
versionsAsync(): Promise<PlatformConfig[]> {
|
||||
return versionsAsyncImpl(this);
|
||||
}
|
||||
|
||||
ready(): Promise<any> {
|
||||
return readyImpl(this);
|
||||
}
|
||||
|
||||
get isRTL(): boolean {
|
||||
return isRtl;
|
||||
}
|
||||
|
||||
setDir(_dir: DocumentDirection, updateDocument: boolean) {
|
||||
dir = _dir;
|
||||
isRtl = dir === 'rtl';
|
||||
|
||||
if (updateDocument !== false) {
|
||||
document.documentElement.setAttribute('dir', dir);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns app's language direction.
|
||||
* We recommend the app's `index.html` file already has the correct `dir`
|
||||
* attribute value set, such as `<html dir="ltr">` or `<html dir="rtl">`.
|
||||
* [W3C: Structural markup and right-to-left text in HTML](http://www.w3.org/International/questions/qa-html-dir)
|
||||
* @returns {DocumentDirection}
|
||||
*/
|
||||
dir(): DocumentDirection {
|
||||
return dir;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the app's language and optionally the country code, which will update
|
||||
* the `lang` attribute on the app's root `<html>` element.
|
||||
* We recommend the app's `index.html` file already has the correct `lang`
|
||||
* attribute value set, such as `<html lang="en">`. This method is useful if
|
||||
* the language needs to be dynamically changed per user/session.
|
||||
* [W3C: Declaring language in HTML](http://www.w3.org/International/questions/qa-html-language-declarations)
|
||||
* @param {string} language Examples: `en-US`, `en-GB`, `ar`, `de`, `zh`, `es-MX`
|
||||
* @param {boolean} updateDocument Specifies whether the `lang` attribute of `<html>` should be updated
|
||||
*/
|
||||
setLang(language: string, updateDocument: boolean) {
|
||||
lang = language;
|
||||
if (updateDocument !== false) {
|
||||
document.documentElement.setAttribute('lang', language);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns app's language and optional country code.
|
||||
* We recommend the app's `index.html` file already has the correct `lang`
|
||||
* attribute value set, such as `<html lang="en">`.
|
||||
* [W3C: Declaring language in HTML](http://www.w3.org/International/questions/qa-html-language-declarations)
|
||||
* @returns {string}
|
||||
*/
|
||||
lang(): string {
|
||||
return lang;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the query string parameter
|
||||
*/
|
||||
getQueryParam(key: string): string {
|
||||
return getQueryParamImpl(this, key);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the query string parameter
|
||||
*/
|
||||
getQueryParamAsync(key: string): Promise<string> {
|
||||
return getQueryParamAsyncImpl(this, key);
|
||||
}
|
||||
|
||||
height(): number {
|
||||
return window.innerHeight;
|
||||
}
|
||||
|
||||
isLandscape(): boolean {
|
||||
return !this.isPortrait();
|
||||
}
|
||||
|
||||
isPortrait(): boolean {
|
||||
return window.matchMedia('(orientation: portrait)').matches;
|
||||
}
|
||||
|
||||
testUserAgent(expression: string): boolean {
|
||||
return navigator.userAgent.indexOf(expression) >= 0;
|
||||
}
|
||||
|
||||
url() {
|
||||
return window.location.href;
|
||||
}
|
||||
|
||||
width() {
|
||||
return window.innerWidth;
|
||||
}
|
||||
}
|
||||
|
||||
export function isImpl(platform: Platform, platformName: string) {
|
||||
if (platform._element && platform._element.is) {
|
||||
return platform._element.is(platformName);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
export function isAsyncImpl(platform: Platform, platformName: string) {
|
||||
return getHydratedPlatform(platform).then(() => {
|
||||
return platform._element.is(platformName);
|
||||
});
|
||||
}
|
||||
|
||||
export function platformsImpl(platform: Platform): string[] {
|
||||
if (platform._element && platform._element.platforms) {
|
||||
return platform._element.platforms();
|
||||
}
|
||||
return [];
|
||||
}
|
||||
|
||||
export function platformsAsyncImpl(platform: Platform): Promise<string[]> {
|
||||
return getHydratedPlatform(platform).then(() => {
|
||||
return platform._element.platforms();
|
||||
});
|
||||
}
|
||||
|
||||
export function versionsImpl(platform: Platform): PlatformConfig[] {
|
||||
if (platform._element && platform._element.versions) {
|
||||
return platform._element.versions();
|
||||
}
|
||||
return [];
|
||||
}
|
||||
|
||||
export function versionsAsyncImpl(platform: Platform): Promise<PlatformConfig[]> {
|
||||
return getHydratedPlatform(platform).then(() => {
|
||||
return platform._element.versions();
|
||||
});
|
||||
}
|
||||
|
||||
export function readyImpl(platform: Platform) {
|
||||
return getHydratedPlatform(platform).then(() => {
|
||||
return platform._element.ready();
|
||||
});
|
||||
}
|
||||
|
||||
export function getQueryParamImpl(platform: Platform, key: string): string {
|
||||
if (platform._element && platform._element.getQueryParam) {
|
||||
return platform._element.getQueryParam(key);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
export function getQueryParamAsyncImpl(platform: Platform, key: string) {
|
||||
return getHydratedPlatform(platform).then(() => {
|
||||
return platform._element.getQueryParam(key);
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
export function initialize(platform: Platform) {
|
||||
// first see if there is an ion-app, if there is, platform will eventually show up
|
||||
// if not, add platform to the document.body
|
||||
const ionApp = document.querySelector('ion-app');
|
||||
if (ionApp) {
|
||||
return ionApp.componentOnReady(() => {
|
||||
platform._element = ionApp.querySelector('ion-platform');
|
||||
});
|
||||
}
|
||||
|
||||
// okay, there isn't an ion-app, so add <ion-platform> to the document.body
|
||||
let platformElement = document.querySelector('ion-platform');
|
||||
if (!platformElement) {
|
||||
platformElement = document.createElement('ion-platform');
|
||||
document.body.appendChild(platformElement);
|
||||
}
|
||||
platform._element = platformElement;
|
||||
}
|
||||
|
||||
export function getHydratedPlatform(platform: Platform): Promise<HTMLIonPlatformElement> {
|
||||
if (!platform._element) {
|
||||
const ionApp = document.querySelector('ion-app');
|
||||
return (ionApp as any).componentOnReady(() => {
|
||||
const platformEl = ionApp.querySelector('ion-platform');
|
||||
return platformEl.componentOnReady().then(() => {
|
||||
platform._element = platformEl;
|
||||
return platformEl;
|
||||
});
|
||||
});
|
||||
}
|
||||
return platform._element.componentOnReady();
|
||||
}
|
||||
@@ -1,22 +0,0 @@
|
||||
import { ComponentFactoryResolver, Injectable, Injector } from '@angular/core';
|
||||
import { PopoverOptions } from '@ionic/core';
|
||||
import { OverlayBaseController } from '../util/overlay';
|
||||
import { AngularDelegate } from './angular-delegate';
|
||||
|
||||
@Injectable()
|
||||
export class PopoverController extends OverlayBaseController<PopoverOptions, HTMLIonPopoverElement> {
|
||||
constructor(
|
||||
private cfr: ComponentFactoryResolver,
|
||||
private injector: Injector,
|
||||
private angularDelegate: AngularDelegate,
|
||||
) {
|
||||
super('ion-popover-controller');
|
||||
}
|
||||
|
||||
create(opts?: PopoverOptions): Promise<HTMLIonPopoverElement> {
|
||||
return super.create({
|
||||
...opts,
|
||||
delegate: this.angularDelegate.create(this.cfr, this.injector)
|
||||
});
|
||||
}
|
||||
}
|
||||
@@ -1,10 +0,0 @@
|
||||
import { Injectable } from '@angular/core';
|
||||
import { ToastOptions } from '@ionic/core';
|
||||
import { OverlayBaseController } from '../util/overlay';
|
||||
|
||||
@Injectable()
|
||||
export class ToastController extends OverlayBaseController<ToastOptions, HTMLIonToastElement> {
|
||||
constructor() {
|
||||
super('ion-toast-controller');
|
||||
}
|
||||
}
|
||||
@@ -1,12 +0,0 @@
|
||||
|
||||
export interface IonicGlobal {
|
||||
config: any;
|
||||
ael: (elm: any, eventName: string, cb: Function, opts: any) => void;
|
||||
raf: Function;
|
||||
rel: (elm: any, eventName: string, cb: Function, opts: any) => void;
|
||||
}
|
||||
|
||||
export interface IonicWindow extends Window {
|
||||
Ionic: IonicGlobal;
|
||||
__zone_symbol__requestAnimationFrame: Function;
|
||||
}
|
||||
@@ -1,17 +0,0 @@
|
||||
import { proxyMethod } from '../util/util';
|
||||
|
||||
export class OverlayBaseController<Opts, Overlay> {
|
||||
constructor(private ctrl: string) {}
|
||||
|
||||
create(opts?: Opts): Promise<Overlay> {
|
||||
return proxyMethod(this.ctrl, 'create', opts);
|
||||
}
|
||||
|
||||
dismiss(data?: any, role?: string, id = -1): Promise<void> {
|
||||
return proxyMethod(this.ctrl, 'dismiss', data, role, id);
|
||||
}
|
||||
|
||||
getTop(): Promise<Overlay> {
|
||||
return proxyMethod(this.ctrl, 'getTop');
|
||||
}
|
||||
}
|
||||
@@ -1,22 +0,0 @@
|
||||
import { ElementRef } from '@angular/core';
|
||||
|
||||
export function proxyMethod(ctrlName: string, methodName: string, ...args: any[]) {
|
||||
const controller = ensureElementInBody(ctrlName);
|
||||
return controller.componentOnReady()
|
||||
.then(() => (controller as any)[methodName].apply(controller, args));
|
||||
}
|
||||
|
||||
export function proxyEl(ref: ElementRef, methodName: string, ...args: any[]) {
|
||||
return ref.nativeElement.componentOnReady()
|
||||
.then((el: any) => el[methodName].apply(el, args));
|
||||
}
|
||||
|
||||
|
||||
export function ensureElementInBody(elementName: string) {
|
||||
let element = document.querySelector(elementName);
|
||||
if (!element) {
|
||||
element = document.createElement(elementName);
|
||||
document.body.appendChild(element);
|
||||
}
|
||||
return element as HTMLStencilElement;
|
||||
}
|
||||
@@ -1,69 +0,0 @@
|
||||
const path = require('path');
|
||||
|
||||
// use ionic/core's stencil config
|
||||
exports.config = require('../core/stencil.config.js').config;
|
||||
|
||||
// update where to find the original ionic/core src
|
||||
exports.config.srcDir = '../core/src';
|
||||
exports.config.globalScript = '../core/src/global/ionic-global.ts';
|
||||
|
||||
// update the output targets
|
||||
exports.config.outputTargets = [
|
||||
{
|
||||
type: 'angular',
|
||||
directivesProxyFile: 'src/directives/proxies.ts',
|
||||
directivesArrayFile: 'src/directives/proxies-list.txt',
|
||||
empty: false,
|
||||
excludeComponents: [
|
||||
// overlays
|
||||
'ion-action-sheet',
|
||||
'ion-action-sheet-controller',
|
||||
'ion-alert',
|
||||
'ion-alert-controller',
|
||||
'ion-loading',
|
||||
'ion-loading-controller',
|
||||
'ion-modal',
|
||||
'ion-modal-controller',
|
||||
'ion-picker',
|
||||
'ion-picker-controller',
|
||||
'ion-popover',
|
||||
'ion-popover-controller',
|
||||
'ion-toast',
|
||||
'ion-toast-controller',
|
||||
'ion-toast',
|
||||
|
||||
// controllers
|
||||
'ion-menu-controller',
|
||||
'ion-animation-controller',
|
||||
'ion-animation-controller',
|
||||
'ion-gesture-controller',
|
||||
'ion-platform',
|
||||
'ion-cordova-platform',
|
||||
|
||||
// navigation
|
||||
'ion-router',
|
||||
'ion-route',
|
||||
'ion-route-redirect',
|
||||
'ion-router-outlet',
|
||||
'ion-anchor',
|
||||
'ion-tabbar',
|
||||
'ion-tab-button',
|
||||
|
||||
// auxiliar
|
||||
'ion-gesture',
|
||||
'ion-status-tap',
|
||||
'ion-tap-click',
|
||||
'ion-picker-column',
|
||||
'ion-range-knob',
|
||||
'ion-input-shims',
|
||||
'ion-backdrop',
|
||||
'ion-anchor',
|
||||
'ion-virtual-scroll'
|
||||
]
|
||||
}
|
||||
]
|
||||
|
||||
exports.devServer = {
|
||||
root: '.',
|
||||
watchGlob: ['dist/*.*', 'dist/ionic/**/**', 'src/**/*.html']
|
||||
};
|
||||
@@ -1,68 +0,0 @@
|
||||
{
|
||||
"$schema": "./node_modules/@angular/cli/lib/config/schema.json",
|
||||
"project": {
|
||||
"name": "demo"
|
||||
},
|
||||
"apps": [
|
||||
{
|
||||
"root": "src",
|
||||
"outDir": "dist",
|
||||
"assets": [
|
||||
"assets",
|
||||
"favicon.ico",
|
||||
{
|
||||
"glob": "**/*",
|
||||
"input": "../node_modules/@ionic/angular/dist/ionic",
|
||||
"output": "./ionic"
|
||||
}
|
||||
],
|
||||
"index": "index.html",
|
||||
"main": "main.ts",
|
||||
"polyfills": "polyfills.ts",
|
||||
"test": "test.ts",
|
||||
"tsconfig": "tsconfig.app.json",
|
||||
"testTsconfig": "tsconfig.spec.json",
|
||||
"prefix": "app",
|
||||
"styles": [
|
||||
"styles.scss"
|
||||
],
|
||||
"scripts": [],
|
||||
"environmentSource": "environments/environment.ts",
|
||||
"environments": {
|
||||
"dev": "environments/environment.ts",
|
||||
"prod": "environments/environment.prod.ts"
|
||||
}
|
||||
}
|
||||
],
|
||||
"e2e": {
|
||||
"protractor": {
|
||||
"config": "./protractor.conf.js"
|
||||
}
|
||||
},
|
||||
"lint": [
|
||||
{
|
||||
"project": "src/tsconfig.app.json",
|
||||
"exclude": "**/node_modules/**"
|
||||
},
|
||||
{
|
||||
"project": "src/tsconfig.spec.json",
|
||||
"exclude": "**/node_modules/**"
|
||||
},
|
||||
{
|
||||
"project": "e2e/tsconfig.e2e.json",
|
||||
"exclude": "**/node_modules/**"
|
||||
}
|
||||
],
|
||||
"test": {
|
||||
"karma": {
|
||||
"config": "./karma.conf.js"
|
||||
}
|
||||
},
|
||||
"defaults": {
|
||||
"styleExt": "scss",
|
||||
"component": {}
|
||||
},
|
||||
"warnings": {
|
||||
"typescriptMismatch": false
|
||||
}
|
||||
}
|
||||
@@ -1,13 +0,0 @@
|
||||
# Editor configuration, see http://editorconfig.org
|
||||
root = true
|
||||
|
||||
[*]
|
||||
charset = utf-8
|
||||
indent_style = space
|
||||
indent_size = 2
|
||||
insert_final_newline = true
|
||||
trim_trailing_whitespace = true
|
||||
|
||||
[*.md]
|
||||
max_line_length = off
|
||||
trim_trailing_whitespace = false
|
||||
42
angular/test/nav/.gitignore
vendored
42
angular/test/nav/.gitignore
vendored
@@ -1,42 +0,0 @@
|
||||
# See http://help.github.com/ignore-files/ for more about ignoring files.
|
||||
|
||||
# compiled output
|
||||
/dist
|
||||
/tmp
|
||||
/out-tsc
|
||||
|
||||
# dependencies
|
||||
/node_modules
|
||||
|
||||
# IDEs and editors
|
||||
/.idea
|
||||
.project
|
||||
.classpath
|
||||
.c9/
|
||||
*.launch
|
||||
.settings/
|
||||
*.sublime-workspace
|
||||
|
||||
# IDE - VSCode
|
||||
.vscode/*
|
||||
!.vscode/settings.json
|
||||
!.vscode/tasks.json
|
||||
!.vscode/launch.json
|
||||
!.vscode/extensions.json
|
||||
|
||||
# misc
|
||||
/.sass-cache
|
||||
/connect.lock
|
||||
/coverage
|
||||
/libpeerconnection.log
|
||||
npm-debug.log
|
||||
testem.log
|
||||
/typings
|
||||
|
||||
# e2e
|
||||
/e2e/*.js
|
||||
/e2e/*.map
|
||||
|
||||
# System Files
|
||||
.DS_Store
|
||||
Thumbs.db
|
||||
@@ -1,34 +0,0 @@
|
||||
import { browser, ElementFinder } from 'protractor/built';
|
||||
|
||||
import { ActionSheetPage } from './action-sheet.po';
|
||||
import { sleep } from './utils/helpers';
|
||||
|
||||
describe('Action Sheet Page', () => {
|
||||
let page: ActionSheetPage;
|
||||
|
||||
beforeEach(() => {
|
||||
page = new ActionSheetPage();
|
||||
});
|
||||
|
||||
it('should open page', async (done) => {
|
||||
await page.navigateTo();
|
||||
done();
|
||||
});
|
||||
|
||||
it('should open the action sheet, then close it using the close button', async (done) => {
|
||||
const button = await page.getButton();
|
||||
await sleep(100);
|
||||
await button.click();
|
||||
await sleep(500);
|
||||
let actionSheet = await page.getActionSheet();
|
||||
expect(await actionSheet.isPresent()).toBeTruthy();
|
||||
const closeButton = await page.getActionSheetCloseButton();
|
||||
await closeButton.click();
|
||||
await sleep(500);
|
||||
actionSheet = null;
|
||||
actionSheet = await page.getActionSheet();
|
||||
expect(await actionSheet.isPresent()).toBeFalsy();
|
||||
done();
|
||||
});
|
||||
|
||||
});
|
||||
@@ -1,19 +0,0 @@
|
||||
import { browser, by, element } from 'protractor';
|
||||
|
||||
export class ActionSheetPage {
|
||||
navigateTo() {
|
||||
return browser.get('/actionSheet');
|
||||
}
|
||||
|
||||
getButton() {
|
||||
return element(by.css('ion-button'));
|
||||
}
|
||||
|
||||
getActionSheet() {
|
||||
return element(by.css('ion-action-sheet'));
|
||||
}
|
||||
|
||||
getActionSheetCloseButton() {
|
||||
return element(by.css('.action-sheet-cancel'));
|
||||
}
|
||||
}
|
||||
@@ -1,33 +0,0 @@
|
||||
import { browser, ElementFinder } from 'protractor/built';
|
||||
|
||||
import { AlertPage } from './alert.po';
|
||||
import { sleep } from './utils/helpers';
|
||||
|
||||
describe('Alert Page', () => {
|
||||
let page: AlertPage;
|
||||
|
||||
beforeEach(() => {
|
||||
page = new AlertPage();
|
||||
});
|
||||
|
||||
it('should open page', async (done) => {
|
||||
await page.navigateTo();
|
||||
done();
|
||||
});
|
||||
|
||||
it('should open the alert, then close it using the close button', async (done) => {
|
||||
const button = await page.getButton();
|
||||
await sleep(100);
|
||||
await button.click();
|
||||
await sleep(500);
|
||||
let alert = await page.getAlert();
|
||||
expect(await alert.isPresent()).toBeTruthy();
|
||||
const closeButton = await page.getCloseButton();
|
||||
await closeButton.click();
|
||||
await sleep(500);
|
||||
alert = null;
|
||||
alert = await page.getAlert();
|
||||
expect(await alert.isPresent()).toBeFalsy();
|
||||
done();
|
||||
});
|
||||
});
|
||||
@@ -1,19 +0,0 @@
|
||||
import { browser, by, element } from 'protractor';
|
||||
|
||||
export class AlertPage {
|
||||
navigateTo() {
|
||||
return browser.get('/alert');
|
||||
}
|
||||
|
||||
getButton() {
|
||||
return element(by.css('ion-button'));
|
||||
}
|
||||
|
||||
getAlert() {
|
||||
return element(by.css('ion-alert'));
|
||||
}
|
||||
|
||||
getCloseButton() {
|
||||
return element(by.css('.alert-button'));
|
||||
}
|
||||
}
|
||||
@@ -1,183 +0,0 @@
|
||||
import { browser, ElementFinder } from 'protractor/built';
|
||||
|
||||
import { BasicInputsPage } from './basic-inputs.po';
|
||||
|
||||
describe('Basic Inputs Page', () => {
|
||||
let page: BasicInputsPage;
|
||||
|
||||
beforeEach(() => {
|
||||
page = new BasicInputsPage();
|
||||
});
|
||||
|
||||
it('should display title', () => {
|
||||
page.navigateTo();
|
||||
expect(page.getTitleText()).toEqual('Ionic Core Basic Inputs Demo');
|
||||
});
|
||||
|
||||
describe('search input', () => {
|
||||
it('should display the starting text', () => {
|
||||
page.navigateTo();
|
||||
const el = page.getIonicSearchInput();
|
||||
expect(el.getAttribute('value')).toEqual(null);
|
||||
});
|
||||
|
||||
it('should reflect back the entered data', () => {
|
||||
page.navigateTo();
|
||||
const el = page.getIonicSearchInputEditable();
|
||||
el.clear();
|
||||
el.sendKeys('I am new text');
|
||||
expect(page.getSearchOutput()).toEqual('I am new text');
|
||||
});
|
||||
|
||||
// it('should disable', () => {
|
||||
// page.navigateTo();
|
||||
// const inp = page.getIonicSearchInputEditable();
|
||||
// const cb = page.getDisableButton();
|
||||
// cb.click();
|
||||
// expect(inp.isEnabled()).toEqual(false);
|
||||
// });
|
||||
});
|
||||
|
||||
describe('text input', () => {
|
||||
it('should display the starting text', () => {
|
||||
page.navigateTo();
|
||||
const el = page.getIonicTextInput();
|
||||
expect(el.getAttribute('value')).toEqual('This is the Text Input');
|
||||
});
|
||||
|
||||
it('should reflect back the entered data', () => {
|
||||
page.navigateTo();
|
||||
const el = page.getIonicTextInputEditable();
|
||||
el.clear();
|
||||
el.sendKeys('I am new text');
|
||||
expect(page.getTextOutput()).toEqual('I am new text');
|
||||
});
|
||||
|
||||
it('should trigger validation errors', () => {
|
||||
page.navigateTo();
|
||||
const el = page.getIonicTextInput();
|
||||
const inp = page.getIonicTextInputEditable();
|
||||
expect(hasClass(el, 'ng-invalid')).toEqual(false);
|
||||
inp.clear();
|
||||
inp.sendKeys('ninechars');
|
||||
expect(hasClass(el, 'ng-invalid')).toEqual(true);
|
||||
inp.sendKeys('X');
|
||||
expect(hasClass(el, 'ng-invalid')).toEqual(false);
|
||||
});
|
||||
|
||||
it('should disable', () => {
|
||||
page.navigateTo();
|
||||
const inp = page.getIonicTextInputEditable();
|
||||
const cb = page.getDisableButton();
|
||||
cb.click();
|
||||
expect(inp.isEnabled()).toEqual(false);
|
||||
});
|
||||
});
|
||||
|
||||
describe('numeric input', () => {
|
||||
it('should remain type number with modifications', () => {
|
||||
page.navigateTo();
|
||||
const el = page.getIonicNumericInput();
|
||||
const inp = page.getIonicNumericInputEditable();
|
||||
expect(page.getNumericOutputType()).toEqual('number');
|
||||
inp.sendKeys('318');
|
||||
expect(page.getNumericOutputType()).toEqual('number');
|
||||
inp.clear();
|
||||
inp.sendKeys('-0');
|
||||
expect(page.getNumericOutputType()).toEqual('number');
|
||||
inp.sendKeys('.48859');
|
||||
expect(page.getNumericOutputType()).toEqual('number');
|
||||
});
|
||||
|
||||
it('should disable', () => {
|
||||
page.navigateTo();
|
||||
const inp = page.getIonicNumericInputEditable();
|
||||
const cb = page.getDisableButton();
|
||||
cb.click();
|
||||
expect(inp.isEnabled()).toEqual(false);
|
||||
});
|
||||
});
|
||||
|
||||
describe('textarea input', () => {
|
||||
it('should display the starting text', () => {
|
||||
page.navigateTo();
|
||||
const el = page.getIonicTextareaInput();
|
||||
expect(el.getAttribute('value')).toEqual('This is the Textarea Input');
|
||||
});
|
||||
|
||||
it('should reflect back the entered data', () => {
|
||||
page.navigateTo();
|
||||
const el = page.getIonicTextareaInputEditable();
|
||||
el.clear();
|
||||
el.sendKeys('I am new text');
|
||||
expect(page.getTextareaOutput()).toEqual('I am new text');
|
||||
});
|
||||
|
||||
it('should trigger validation errors', () => {
|
||||
page.navigateTo();
|
||||
const el = page.getIonicTextareaInput();
|
||||
const inp = page.getIonicTextareaInputEditable();
|
||||
expect(hasClass(el, 'ng-invalid')).toEqual(false);
|
||||
inp.clear();
|
||||
inp.sendKeys('ninechars');
|
||||
expect(hasClass(el, 'ng-invalid')).toEqual(true);
|
||||
inp.sendKeys('X');
|
||||
expect(hasClass(el, 'ng-invalid')).toEqual(false);
|
||||
});
|
||||
|
||||
it('should disable', () => {
|
||||
page.navigateTo();
|
||||
const inp = page.getIonicTextareaInputEditable();
|
||||
const cb = page.getDisableButton();
|
||||
cb.click();
|
||||
expect(inp.isEnabled()).toEqual(false);
|
||||
});
|
||||
});
|
||||
|
||||
describe('checkbox input', () => {
|
||||
it('should be set the initial value', () => {
|
||||
page.navigateTo();
|
||||
const el = page.getIonicCheckbox();
|
||||
expect(el.getAttribute('checked')).toEqual('true');
|
||||
});
|
||||
|
||||
it('should reflect toggling the value', () => {
|
||||
page.navigateTo();
|
||||
return browser.executeScript('window.scrollTo(0, 500);').then(function() {
|
||||
const el = page.getIonicCheckbox();
|
||||
el.click();
|
||||
expect(page.getCheckboxOutput()).toEqual('false');
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe('toggle input', () => {
|
||||
it('should be set the initial value', () => {
|
||||
page.navigateTo();
|
||||
const el = page.getIonicToggle();
|
||||
expect(el.getAttribute('checked')).toBeNull();
|
||||
});
|
||||
|
||||
it('should reflect toggling the value', () => {
|
||||
page.navigateTo();
|
||||
return browser.executeScript('window.scrollTo(0, 500);').then(function() {
|
||||
const el = page.getIonicToggle();
|
||||
el.click();
|
||||
expect(page.getToggleOutput()).toEqual('true');
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe('date time picker', () => {
|
||||
it('should be set the initial value', () => {
|
||||
page.navigateTo();
|
||||
const el = page.getIonicDatetime();
|
||||
expect(el.getAttribute('value')).toEqual('2017-11-18T14:17:45-06:00');
|
||||
});
|
||||
});
|
||||
|
||||
async function hasClass(el: ElementFinder, cls: string): Promise<boolean> {
|
||||
const classes = await el.getAttribute('class');
|
||||
return classes.split(' ').indexOf(cls) !== -1;
|
||||
}
|
||||
});
|
||||
@@ -1,91 +0,0 @@
|
||||
import { browser, by, element } from 'protractor';
|
||||
|
||||
export class BasicInputsPage {
|
||||
navigateTo() {
|
||||
return browser.get('/basic-inputs');
|
||||
}
|
||||
|
||||
getIonicCheckbox() {
|
||||
return element(by.id('ionCheckbox'));
|
||||
}
|
||||
|
||||
getCheckboxOutput() {
|
||||
return element(by.id('checkboxOutput')).getText();
|
||||
}
|
||||
|
||||
getIonicDatetime() {
|
||||
return element(by.id('ionDatetimeInput'));
|
||||
}
|
||||
|
||||
getDatetimeOutput() {
|
||||
return element(by.id('datetimeOutput')).getText();
|
||||
}
|
||||
|
||||
getIonicToggle() {
|
||||
return element(by.id('ionToggle'));
|
||||
}
|
||||
|
||||
getToggleOutput() {
|
||||
return element(by.id('toggleOutput')).getText();
|
||||
}
|
||||
|
||||
getTitleText() {
|
||||
return element(by.css('.title')).getText();
|
||||
}
|
||||
|
||||
getIonicTextareaInput() {
|
||||
return element(by.id('ionTextareaInput'));
|
||||
}
|
||||
|
||||
getIonicTextareaInputEditable() {
|
||||
const parent = this.getIonicTextareaInput();
|
||||
return parent.all(by.css('textarea')).first();
|
||||
}
|
||||
|
||||
getTextareaOutput() {
|
||||
return element(by.id('textareaOutput')).getText();
|
||||
}
|
||||
|
||||
getIonicSearchInput() {
|
||||
return element(by.id('ionSearchInput'));
|
||||
}
|
||||
|
||||
getIonicSearchInputEditable() {
|
||||
const parent = this.getIonicSearchInput();
|
||||
return parent.all(by.css('input')).first();
|
||||
}
|
||||
|
||||
getSearchOutput() {
|
||||
return element(by.id('searchOutput')).getText();
|
||||
}
|
||||
|
||||
getIonicTextInput() {
|
||||
return element(by.id('ionTextInput'));
|
||||
}
|
||||
|
||||
getIonicTextInputEditable() {
|
||||
const parent = this.getIonicTextInput();
|
||||
return parent.all(by.css('input')).first();
|
||||
}
|
||||
|
||||
getIonicNumericInput() {
|
||||
return element(by.id('ionNumericInput'));
|
||||
}
|
||||
|
||||
getIonicNumericInputEditable() {
|
||||
const parent = this.getIonicNumericInput();
|
||||
return parent.all(by.css('input')).first();
|
||||
}
|
||||
|
||||
getTextOutput() {
|
||||
return element(by.id('textOutput')).getText();
|
||||
}
|
||||
|
||||
getNumericOutputType() {
|
||||
return element(by.id('numericOutputType')).getText();
|
||||
}
|
||||
|
||||
getDisableButton() {
|
||||
return element(by.id('disableCheckbox'));
|
||||
}
|
||||
}
|
||||
@@ -1,111 +0,0 @@
|
||||
import { browser, ElementFinder, promise } from 'protractor/built';
|
||||
|
||||
import { GroupInputsPage } from './group-inputs.po';
|
||||
|
||||
describe('Group Inputs Page', () => {
|
||||
let page: GroupInputsPage;
|
||||
|
||||
beforeEach(() => {
|
||||
page = new GroupInputsPage();
|
||||
});
|
||||
|
||||
it('should display title', () => {
|
||||
page.navigateTo();
|
||||
expect(page.getTitleText()).toEqual('Ionic Core Group Inputs Demo');
|
||||
});
|
||||
|
||||
describe('radio group', () => {
|
||||
it('should have the proper initial value', () => {
|
||||
page.navigateTo();
|
||||
const el = page.getRaioGroup();
|
||||
expect(el.getAttribute('value')).toEqual('tripe');
|
||||
});
|
||||
|
||||
it('should check the proper initial radio button', () => {
|
||||
page.navigateTo();
|
||||
const btns = page.getGroupedRadioButtons();
|
||||
expect(btns.tripe.getAttribute('checked')).toEqual('true');
|
||||
expect(btns.beef.getAttribute('checked')).toEqual(null);
|
||||
expect(btns.chicken.getAttribute('checked')).toEqual(null);
|
||||
expect(btns.brains.getAttribute('checked')).toEqual(null);
|
||||
expect(btns.tongue.getAttribute('checked')).toEqual(null);
|
||||
});
|
||||
|
||||
it('should reflect back the changed value', () => {
|
||||
page.navigateTo();
|
||||
const btns = page.getGroupedRadioButtons();
|
||||
btns.chicken.click();
|
||||
expect(page.getRadioOutputText()).toEqual('chicken');
|
||||
});
|
||||
|
||||
it('should check and uncheck the proper buttons on a changed value', () => {
|
||||
page.navigateTo();
|
||||
const btns = page.getGroupedRadioButtons();
|
||||
btns.chicken.click();
|
||||
expect(btns.chicken.getAttribute('checked')).toEqual('true');
|
||||
expect(btns.beef.getAttribute('checked')).toEqual(null);
|
||||
expect(btns.tripe.getAttribute('checked')).toEqual(null);
|
||||
expect(btns.brains.getAttribute('checked')).toEqual(null);
|
||||
expect(btns.tongue.getAttribute('checked')).toEqual(null);
|
||||
});
|
||||
});
|
||||
|
||||
describe('non-grouped radios', () => {
|
||||
it('should check the proper initial radio button', () => {
|
||||
page.navigateTo();
|
||||
const btns = page.getUngroupedRadioButtons();
|
||||
expect(btns.tripe.getAttribute('checked')).toEqual('true');
|
||||
expect(btns.beef.getAttribute('checked')).toEqual(null);
|
||||
expect(btns.chicken.getAttribute('checked')).toEqual(null);
|
||||
expect(btns.brains.getAttribute('checked')).toEqual(null);
|
||||
expect(btns.tongue.getAttribute('checked')).toEqual(null);
|
||||
});
|
||||
|
||||
it('should reflect back the changed value', () => {
|
||||
page.navigateTo();
|
||||
return browser.executeScript('window.scrollTo(0, 500);').then(function() {
|
||||
const btns = page.getUngroupedRadioButtons();
|
||||
btns.chicken.click();
|
||||
expect(page.getRadioOutputText()).toEqual('chicken');
|
||||
});
|
||||
});
|
||||
|
||||
it('should check and uncheck the proper buttons on a changed value', () => {
|
||||
page.navigateTo();
|
||||
return browser.executeScript('window.scrollTo(0, 500);').then(function() {
|
||||
const btns = page.getUngroupedRadioButtons();
|
||||
btns.chicken.click();
|
||||
expect(btns.chicken.getAttribute('checked')).toEqual('true');
|
||||
expect(btns.beef.getAttribute('checked')).toEqual(null);
|
||||
expect(btns.tripe.getAttribute('checked')).toEqual(null);
|
||||
expect(btns.brains.getAttribute('checked')).toEqual(null);
|
||||
expect(btns.tongue.getAttribute('checked')).toEqual(null);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe('segments', () => {
|
||||
it('should have the proper initial value', () => {
|
||||
page.navigateTo();
|
||||
const el = page.getSegment();
|
||||
expect(el.getAttribute('value')).toEqual('tripe');
|
||||
});
|
||||
|
||||
it('should reflect back the changed value', () => {
|
||||
page.navigateTo();
|
||||
return browser.executeScript('window.scrollTo(0, 500);').then(function() {
|
||||
const btns = page.getSegmentButtons();
|
||||
btns.chicken.click();
|
||||
expect(page.getRadioOutputText()).toEqual('chicken');
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe('select input', () => {
|
||||
it('should be set the initial value', () => {
|
||||
page.navigateTo();
|
||||
const el = page.getIonicSelect();
|
||||
expect(el.getAttribute('value')).toEqual('brains');
|
||||
});
|
||||
});
|
||||
});
|
||||
@@ -1,61 +0,0 @@
|
||||
import { browser, by, element } from 'protractor';
|
||||
|
||||
export class GroupInputsPage {
|
||||
navigateTo() {
|
||||
return browser.get('/group-inputs');
|
||||
}
|
||||
|
||||
getTitleText() {
|
||||
return element(by.css('.title')).getText();
|
||||
}
|
||||
|
||||
getRaioGroup() {
|
||||
return element(by.id('radio-group'));
|
||||
}
|
||||
|
||||
getGroupedRadioButtons() {
|
||||
return {
|
||||
beef: element(by.id('ion-grp-beef')),
|
||||
tongue: element(by.id('ion-grp-tongue')),
|
||||
brains: element(by.id('ion-grp-brains')),
|
||||
tripe: element(by.id('ion-grp-tripe')),
|
||||
chicken: element(by.id('ion-grp-chicken'))
|
||||
};
|
||||
}
|
||||
|
||||
getSegmentButtons() {
|
||||
return {
|
||||
beef: element(by.id('ion-seg-beef')),
|
||||
tongue: element(by.id('ion-seg-tongue')),
|
||||
brains: element(by.id('ion-seg-brains')),
|
||||
tripe: element(by.id('ion-seg-tripe')),
|
||||
chicken: element(by.id('ion-seg-chicken'))
|
||||
};
|
||||
}
|
||||
|
||||
getUngroupedRadioButtons() {
|
||||
return {
|
||||
beef: element(by.id('ion-beef')),
|
||||
tongue: element(by.id('ion-tongue')),
|
||||
brains: element(by.id('ion-brains')),
|
||||
tripe: element(by.id('ion-tripe')),
|
||||
chicken: element(by.id('ion-chicken'))
|
||||
};
|
||||
}
|
||||
|
||||
getSegment() {
|
||||
return element(by.id('segment'));
|
||||
}
|
||||
|
||||
getRadioOutputText() {
|
||||
return element(by.id('radioOutput')).getText();
|
||||
}
|
||||
|
||||
getIonicSelect() {
|
||||
return element(by.id('ionSelect'));
|
||||
}
|
||||
|
||||
getSelectOutput() {
|
||||
return element(by.id('selectOutput')).getText();
|
||||
}
|
||||
}
|
||||
@@ -1,19 +0,0 @@
|
||||
import { HomePage } from './home.po';
|
||||
|
||||
describe('Demo Home Page', () => {
|
||||
let page: HomePage;
|
||||
|
||||
beforeEach(() => {
|
||||
page = new HomePage();
|
||||
});
|
||||
|
||||
it('should display title', () => {
|
||||
page.navigateTo();
|
||||
expect(page.getTitleText()).toEqual('Ionic Core Angular Demo Application');
|
||||
});
|
||||
|
||||
it('should navigate to home for root', () => {
|
||||
page.navigateToRoot();
|
||||
expect(page.getTitleText()).toEqual('Ionic Core Angular Demo Application');
|
||||
});
|
||||
});
|
||||
@@ -1,15 +0,0 @@
|
||||
import { browser, by, element } from 'protractor';
|
||||
|
||||
export class HomePage {
|
||||
navigateTo() {
|
||||
return browser.get('/home');
|
||||
}
|
||||
|
||||
navigateToRoot() {
|
||||
return browser.get('/');
|
||||
}
|
||||
|
||||
getTitleText() {
|
||||
return element(by.css('.title')).getText();
|
||||
}
|
||||
}
|
||||
@@ -1,31 +0,0 @@
|
||||
import { browser, ElementFinder } from 'protractor/built';
|
||||
|
||||
import { LoadingPage } from './loading.po';
|
||||
import { sleep } from './utils/helpers';
|
||||
|
||||
describe('Loading Page', () => {
|
||||
let page: LoadingPage;
|
||||
|
||||
beforeEach(() => {
|
||||
page = new LoadingPage();
|
||||
});
|
||||
|
||||
it('should open page', async (done) => {
|
||||
await page.navigateTo();
|
||||
done();
|
||||
});
|
||||
|
||||
it('should open the loading indicator, then close it', async (done) => {
|
||||
const button = await page.getButton();
|
||||
await sleep(100);
|
||||
await button.click();
|
||||
await sleep(500);
|
||||
let loading = await page.getLoading();
|
||||
expect(loading).toBeTruthy();
|
||||
await sleep(1000);
|
||||
loading = null;
|
||||
loading = await page.getLoading();
|
||||
expect(await loading.isPresent()).toBeFalsy();
|
||||
done();
|
||||
});
|
||||
});
|
||||
@@ -1,16 +0,0 @@
|
||||
import { browser, by, element } from 'protractor';
|
||||
|
||||
export class LoadingPage {
|
||||
navigateTo() {
|
||||
return browser.get('/loading');
|
||||
}
|
||||
|
||||
getButton() {
|
||||
return element(by.css('ion-button'));
|
||||
}
|
||||
|
||||
getLoading() {
|
||||
return element(by.css('ion-loading'));
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,49 +0,0 @@
|
||||
import { browser, ElementFinder } from 'protractor/built';
|
||||
|
||||
import { ModalPage } from './modal.po';
|
||||
import { sleep } from './utils/helpers';
|
||||
|
||||
describe('Modal Page', () => {
|
||||
let page: ModalPage;
|
||||
|
||||
beforeEach(() => {
|
||||
page = new ModalPage();
|
||||
});
|
||||
|
||||
it('should open page', async (done) => {
|
||||
await page.navigateTo();
|
||||
done();
|
||||
});
|
||||
|
||||
it('should open the modal', async (done) => {
|
||||
/*const button = await page.getButton();
|
||||
await button.click();
|
||||
await sleep(500);
|
||||
const blah = page.getModal();
|
||||
blah.isPresent().then((present) => {
|
||||
console.log('boom boom boom: ', present);
|
||||
done();
|
||||
}).catch((ex) => {
|
||||
console.log('caught it: ', ex);
|
||||
done();
|
||||
});
|
||||
*/
|
||||
// console.log('blah: ', await blah.isPresent());
|
||||
/*page.getModal().then((modal) => {
|
||||
return modal.isPresent();
|
||||
}).then((present) => {
|
||||
console.log('boom boom boom: ', present);
|
||||
done();
|
||||
}).catch(() => {
|
||||
console.log('caught it');
|
||||
done();
|
||||
})
|
||||
*/
|
||||
done();
|
||||
/*console.log('modal: ', modal);
|
||||
console.log('modal.isPresent: ', modal.isPresent);
|
||||
console.log('Got the modal: ', await modal.isPresent());
|
||||
expect(await modal.isPresent()).toBeTruthy();
|
||||
*/
|
||||
});
|
||||
});
|
||||
@@ -1,20 +0,0 @@
|
||||
import { browser, by, element } from 'protractor';
|
||||
|
||||
export class ModalPage {
|
||||
navigateTo() {
|
||||
return browser.get('/modal');
|
||||
}
|
||||
|
||||
getButton() {
|
||||
return element(by.css('ion-button'));
|
||||
}
|
||||
|
||||
getModal() {
|
||||
return element(by.css('page-one'));
|
||||
}
|
||||
|
||||
getDismissButton() {
|
||||
return element(by.css('button.dismiss-btn'));
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,33 +0,0 @@
|
||||
import { browser, ElementFinder } from 'protractor/built';
|
||||
|
||||
import { PopoverPage } from './popover.po';
|
||||
import { sleep } from './utils/helpers';
|
||||
|
||||
describe('Popover Page', () => {
|
||||
let page: PopoverPage;
|
||||
|
||||
beforeEach(() => {
|
||||
page = new PopoverPage();
|
||||
});
|
||||
|
||||
it('should open page', async (done) => {
|
||||
await page.navigateTo();
|
||||
done();
|
||||
});
|
||||
|
||||
it('should open the popover, then close it using the close button', async (done) => {
|
||||
const button = await page.getButton();
|
||||
await sleep(100);
|
||||
await button.click();
|
||||
await sleep(500);
|
||||
let popover = await page.getPopover();
|
||||
expect(await popover.isPresent()).toBeTruthy();
|
||||
const closeButton = await page.getCloseButton();
|
||||
await closeButton.click();
|
||||
await sleep(500);
|
||||
popover = null;
|
||||
popover = await page.getPopover();
|
||||
expect(await popover.isPresent()).toBeFalsy();
|
||||
done();
|
||||
});
|
||||
});
|
||||
@@ -1,19 +0,0 @@
|
||||
import { browser, by, element } from 'protractor';
|
||||
|
||||
export class PopoverPage {
|
||||
navigateTo() {
|
||||
return browser.get('/popover');
|
||||
}
|
||||
|
||||
getButton() {
|
||||
return element(by.css('ion-button'));
|
||||
}
|
||||
|
||||
getPopover() {
|
||||
return element(by.css('ion-popover'));
|
||||
}
|
||||
|
||||
getCloseButton() {
|
||||
return element(by.css('.popover-button'));
|
||||
}
|
||||
}
|
||||
@@ -1,14 +0,0 @@
|
||||
{
|
||||
"extends": "../tsconfig.json",
|
||||
"compilerOptions": {
|
||||
"outDir": "../out-tsc/e2e",
|
||||
"baseUrl": "./",
|
||||
"module": "commonjs",
|
||||
"target": "es5",
|
||||
"types": [
|
||||
"jasmine",
|
||||
"jasminewd2",
|
||||
"node"
|
||||
]
|
||||
}
|
||||
}
|
||||
@@ -1,6 +0,0 @@
|
||||
|
||||
export function sleep(duration: number = 300) {
|
||||
return new Promise(resolve => {
|
||||
setTimeout(resolve, duration);
|
||||
});
|
||||
}
|
||||
@@ -1,34 +0,0 @@
|
||||
// Karma configuration file, see link for more information
|
||||
// https://karma-runner.github.io/1.0/config/configuration-file.html
|
||||
|
||||
module.exports = function(config) {
|
||||
config.set({
|
||||
basePath: '',
|
||||
frameworks: ['jasmine', '@angular/cli'],
|
||||
plugins: [
|
||||
require('karma-jasmine'),
|
||||
require('karma-chrome-launcher'),
|
||||
require('karma-jasmine-html-reporter'),
|
||||
require('karma-coverage-istanbul-reporter'),
|
||||
require('@angular/cli/plugins/karma')
|
||||
],
|
||||
client: {
|
||||
clearContext: false // leave Jasmine Spec Runner output visible in browser
|
||||
},
|
||||
coverageIstanbulReporter: {
|
||||
reports: ['html', 'lcovonly'],
|
||||
fixWebpackSourcePaths: true
|
||||
},
|
||||
angularCli: {
|
||||
environment: 'dev'
|
||||
},
|
||||
files: [],
|
||||
reporters: ['progress', 'kjhtml'],
|
||||
port: 9876,
|
||||
colors: true,
|
||||
logLevel: config.LOG_INFO,
|
||||
autoWatch: true,
|
||||
browsers: ['Chrome'],
|
||||
singleRun: false
|
||||
});
|
||||
};
|
||||
11063
angular/test/nav/package-lock.json
generated
11063
angular/test/nav/package-lock.json
generated
File diff suppressed because it is too large
Load Diff
@@ -1,52 +0,0 @@
|
||||
{
|
||||
"name": "@ionic/angular-test-nav",
|
||||
"private": true,
|
||||
"version": "0.0.1",
|
||||
"license": "MIT",
|
||||
"scripts": {
|
||||
"ng": "ng",
|
||||
"start": "ng serve",
|
||||
"build": "ng build",
|
||||
"test": "ng test",
|
||||
"lint": "ng lint",
|
||||
"e2e": "ng e2e"
|
||||
},
|
||||
"dependencies": {
|
||||
"@angular/animations": "latest",
|
||||
"@angular/common": "latest",
|
||||
"@angular/compiler": "latest",
|
||||
"@angular/core": "latest",
|
||||
"@angular/forms": "latest",
|
||||
"@angular/http": "latest",
|
||||
"@angular/platform-browser": "latest",
|
||||
"@angular/platform-browser-dynamic": "latest",
|
||||
"@angular/router": "latest",
|
||||
"@ionic/angular": "next",
|
||||
"body-parser": "^1.18.2",
|
||||
"core-js": "^2.4.1",
|
||||
"express": "^4.16.2",
|
||||
"rxjs": "^5.5.2",
|
||||
"zone.js": "^0.8.14"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@angular/cli": "latest",
|
||||
"@angular/compiler-cli": "latest",
|
||||
"@angular/language-service": "latest",
|
||||
"@types/jasmine": "~2.5.53",
|
||||
"@types/jasminewd2": "~2.0.2",
|
||||
"@types/node": "~6.0.60",
|
||||
"codelyzer": "~3.2.0",
|
||||
"jasmine-core": "~2.6.2",
|
||||
"jasmine-spec-reporter": "~4.1.0",
|
||||
"karma": "~1.7.0",
|
||||
"karma-chrome-launcher": "~2.1.1",
|
||||
"karma-cli": "~1.0.1",
|
||||
"karma-coverage-istanbul-reporter": "^1.2.1",
|
||||
"karma-jasmine": "~1.1.0",
|
||||
"karma-jasmine-html-reporter": "^0.2.2",
|
||||
"protractor": "~5.1.2",
|
||||
"ts-node": "^3.2.2",
|
||||
"tslint": "~5.7.0",
|
||||
"typescript": "^2.5.2"
|
||||
}
|
||||
}
|
||||
@@ -1,28 +0,0 @@
|
||||
// Protractor configuration file, see link for more information
|
||||
// https://github.com/angular/protractor/blob/master/lib/config.ts
|
||||
|
||||
const { SpecReporter } = require('jasmine-spec-reporter');
|
||||
|
||||
exports.config = {
|
||||
allScriptsTimeout: 11000,
|
||||
specs: [
|
||||
'./e2e/**/*.e2e-spec.ts'
|
||||
],
|
||||
capabilities: {
|
||||
'browserName': 'chrome'
|
||||
},
|
||||
directConnect: true,
|
||||
baseUrl: 'http://localhost:4200/',
|
||||
framework: 'jasmine',
|
||||
jasmineNodeOpts: {
|
||||
showColors: true,
|
||||
defaultTimeoutInterval: 30000,
|
||||
print: function() {}
|
||||
},
|
||||
onPrepare() {
|
||||
require('ts-node').register({
|
||||
project: 'e2e/tsconfig.e2e.json'
|
||||
});
|
||||
jasmine.getEnv().addReporter(new SpecReporter({ spec: { displayStacktrace: true } }));
|
||||
}
|
||||
};
|
||||
@@ -1,66 +0,0 @@
|
||||
import { Component } from '@angular/core';
|
||||
|
||||
import { ActionSheetController } from '@ionic/angular';
|
||||
|
||||
@Component({
|
||||
selector: 'app-action-sheet-page',
|
||||
template: `
|
||||
<ion-app>
|
||||
<ion-header>
|
||||
<ion-toolbar>
|
||||
<ion-title>Action Sheet</ion-title>
|
||||
</ion-toolbar>
|
||||
</ion-header>
|
||||
<ion-content padding>
|
||||
<ion-button (click)="clickMe()">Open Basic ActionSheet</ion-button>
|
||||
</ion-content>
|
||||
</ion-app>
|
||||
`
|
||||
})
|
||||
export class ActionSheetPageComponent {
|
||||
|
||||
constructor(private actionSheetController: ActionSheetController) {
|
||||
|
||||
}
|
||||
|
||||
async clickMe() {
|
||||
const actionSheet = await this.actionSheetController.create({
|
||||
header: 'Albums',
|
||||
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: 'arrow-dropright-circle',
|
||||
handler: () => {
|
||||
console.log('Play clicked');
|
||||
}
|
||||
}, {
|
||||
text: 'Favorite',
|
||||
icon: 'heart',
|
||||
handler: () => {
|
||||
console.log('Favorite clicked');
|
||||
}
|
||||
}, {
|
||||
text: 'Cancel',
|
||||
role: 'cancel',
|
||||
icon: 'close',
|
||||
handler: () => {
|
||||
console.log('Cancel clicked');
|
||||
}
|
||||
}]
|
||||
});
|
||||
return actionSheet.present();
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,14 +0,0 @@
|
||||
import { NgModule } from '@angular/core';
|
||||
import { Routes, RouterModule } from '@angular/router';
|
||||
|
||||
import { ActionSheetPageComponent } from './action-sheet-page.component';
|
||||
|
||||
const routes: Routes = [
|
||||
{ path: '', component: ActionSheetPageComponent }
|
||||
];
|
||||
|
||||
@NgModule({
|
||||
imports: [RouterModule.forChild(routes)],
|
||||
exports: [RouterModule]
|
||||
})
|
||||
export class ActionSheetRoutingModule { }
|
||||
@@ -1,16 +0,0 @@
|
||||
import { NgModule } from '@angular/core';
|
||||
import { CommonModule } from '@angular/common';
|
||||
|
||||
import { IonicModule } from '@ionic/angular';
|
||||
import { ActionSheetPageComponent } from './action-sheet-page.component';
|
||||
import { ActionSheetRoutingModule } from './action-sheet-routing.module';
|
||||
|
||||
@NgModule({
|
||||
imports: [
|
||||
CommonModule,
|
||||
IonicModule,
|
||||
ActionSheetRoutingModule
|
||||
],
|
||||
declarations: [ActionSheetPageComponent]
|
||||
})
|
||||
export class ActionSheetModule { }
|
||||
@@ -1,48 +0,0 @@
|
||||
import { Component } from '@angular/core';
|
||||
|
||||
import { AlertController } from '@ionic/angular';
|
||||
|
||||
@Component({
|
||||
selector: 'app-alert-page',
|
||||
template: `
|
||||
<ion-app>
|
||||
<ion-header>
|
||||
<ion-toolbar>
|
||||
<ion-title>Alert</ion-title>
|
||||
</ion-toolbar>
|
||||
</ion-header>
|
||||
<ion-content padding>
|
||||
<ion-button (click)="clickMe()">Open Basic Alert</ion-button>
|
||||
</ion-content>
|
||||
</ion-app>
|
||||
`
|
||||
})
|
||||
export class AlertPageComponent {
|
||||
|
||||
constructor(private alertController: AlertController) {}
|
||||
|
||||
async clickMe() {
|
||||
const alert = await this.alertController.create({
|
||||
header: 'ohhhh snap',
|
||||
message: 'Ive been injected via Angular keeping the old api',
|
||||
buttons: [
|
||||
{
|
||||
text: 'Cancel',
|
||||
role: 'Cancel',
|
||||
handler: () => {
|
||||
// console.log('cancel');
|
||||
}
|
||||
},
|
||||
{
|
||||
text: 'Okay',
|
||||
role: 'Okay',
|
||||
handler: () => {
|
||||
// console.log('okay');
|
||||
}
|
||||
}
|
||||
]
|
||||
});
|
||||
return alert.present();
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,14 +0,0 @@
|
||||
import { NgModule } from '@angular/core';
|
||||
import { Routes, RouterModule } from '@angular/router';
|
||||
|
||||
import { AlertPageComponent } from './alert-page.component';
|
||||
|
||||
const routes: Routes = [
|
||||
{ path: '', component: AlertPageComponent }
|
||||
];
|
||||
|
||||
@NgModule({
|
||||
imports: [RouterModule.forChild(routes)],
|
||||
exports: [RouterModule]
|
||||
})
|
||||
export class AlertRoutingModule { }
|
||||
@@ -1,16 +0,0 @@
|
||||
import { NgModule } from '@angular/core';
|
||||
import { CommonModule } from '@angular/common';
|
||||
|
||||
import { IonicModule } from '@ionic/angular';
|
||||
import { AlertPageComponent } from './alert-page.component';
|
||||
import { AlertRoutingModule } from './alert-routing.module';
|
||||
|
||||
@NgModule({
|
||||
imports: [
|
||||
CommonModule,
|
||||
IonicModule,
|
||||
AlertRoutingModule
|
||||
],
|
||||
declarations: [AlertPageComponent]
|
||||
})
|
||||
export class AlertModule { }
|
||||
@@ -1,35 +0,0 @@
|
||||
import { NgModule } from '@angular/core';
|
||||
import { Routes, RouterModule } from '@angular/router';
|
||||
|
||||
const routes: Routes = [
|
||||
{ path: '', redirectTo: '/home', pathMatch: 'full' },
|
||||
{ path: 'basic-inputs', loadChildren: './basic-inputs-page/basic-inputs-page.module#BasicInputsPageModule' },
|
||||
{ path: 'show-hide-when', loadChildren: './show-hide-when/show-hide-when.module#ShowHideWhenModule' },
|
||||
{ path: 'form-sample', loadChildren: './form-sample-page/form-sample-page.module#FormSamplePageModule' },
|
||||
{ path: 'group-inputs', loadChildren: './group-inputs-page/group-inputs-page.module#GroupInputsPageModule' },
|
||||
{ path: 'home', loadChildren: './home-page/home-page.module#HomePageModule' },
|
||||
{ path: 'alert', loadChildren: './alert/alert.module#AlertModule' },
|
||||
{ path: 'actionSheet', loadChildren: './action-sheet/action-sheet.module#ActionSheetModule' },
|
||||
{ path: 'badge', loadChildren: './badge/badge.module#BadgeModule' },
|
||||
{ path: 'card', loadChildren: './card/card.module#CardModule' },
|
||||
{ path: 'content', loadChildren: './content/content.module#ContentModule' },
|
||||
{ path: 'toast', loadChildren: './toast/toast.module#ToastModule' },
|
||||
{ path: 'loading', loadChildren: './loading/loading.module#LoadingModule' },
|
||||
{ path: 'modal', loadChildren: './modal/modal.module#ModalModule' },
|
||||
{ path: 'ng-if', loadChildren: './ng-if/ng-if.module#NgIfModule' },
|
||||
{ path: 'popover', loadChildren: './popover/popover.module#PopoverModule' },
|
||||
{ path: 'segment', loadChildren: './segment/segment.module#SegmentModule' },
|
||||
{ path: 'virtual-scroll', loadChildren: './virtual-scroll/virtual-scroll.module#VirtualScrollModule' },
|
||||
|
||||
{ path: 'no-routing-nav', loadChildren: './no-routing-nav/no-routing-nav.module#NoRoutingNavModule' },
|
||||
{ path: 'simple-nav', loadChildren: './simple-nav/simple-nav.module#SimpleNavModule' },
|
||||
{ path: 'lazy-load-tabs', loadChildren: './lazy-load-tabs/tabs.module#TabsModule' },
|
||||
{ path: 'simple-tabs', loadChildren: './simple-tabs/tabs.module#TabsModule' },
|
||||
{ path: 'static-tabs', loadChildren: './static-tabs/tabs.module#TabsModule' },
|
||||
];
|
||||
|
||||
@NgModule({
|
||||
imports: [RouterModule.forRoot(routes, { enableTracing: true })],
|
||||
exports: [RouterModule]
|
||||
})
|
||||
export class AppRoutingModule { }
|
||||
@@ -1,2 +0,0 @@
|
||||
|
||||
<router-outlet></router-outlet>
|
||||
@@ -1,20 +0,0 @@
|
||||
import { TestBed, async } from '@angular/core/testing';
|
||||
|
||||
import { RouterOutletStubComponent } from '../../testing/router-stubs';
|
||||
import { AppComponent } from './app.component';
|
||||
|
||||
describe('AppComponent', () => {
|
||||
beforeEach( async(() => {
|
||||
TestBed.configureTestingModule({
|
||||
declarations: [AppComponent, RouterOutletStubComponent]
|
||||
}).compileComponents();
|
||||
})
|
||||
);
|
||||
|
||||
it('should create the app', async(() => {
|
||||
const fixture = TestBed.createComponent(AppComponent);
|
||||
const app = fixture.debugElement.componentInstance;
|
||||
expect(app).toBeTruthy();
|
||||
})
|
||||
);
|
||||
});
|
||||
@@ -1,10 +0,0 @@
|
||||
import { Component } from '@angular/core';
|
||||
|
||||
@Component({
|
||||
selector: 'app-root',
|
||||
templateUrl: './app.component.html',
|
||||
styleUrls: ['./app.component.css']
|
||||
})
|
||||
export class AppComponent {
|
||||
title = 'app';
|
||||
}
|
||||
@@ -1,22 +0,0 @@
|
||||
import { BrowserModule } from '@angular/platform-browser';
|
||||
import { NgModule } from '@angular/core';
|
||||
import { HttpClientModule } from '@angular/common/http';
|
||||
|
||||
import { AppComponent } from './app.component';
|
||||
import { AppRoutingModule } from './app-routing.module';
|
||||
import { PostTestService } from './post-test/post-test.service';
|
||||
|
||||
import { IonicModule } from '@ionic/angular';
|
||||
|
||||
@NgModule({
|
||||
declarations: [AppComponent],
|
||||
imports: [
|
||||
AppRoutingModule,
|
||||
BrowserModule,
|
||||
HttpClientModule,
|
||||
IonicModule.forRoot(),
|
||||
],
|
||||
bootstrap: [AppComponent],
|
||||
providers: [PostTestService]
|
||||
})
|
||||
export class AppModule { }
|
||||
@@ -1,95 +0,0 @@
|
||||
import { Component, ViewChild } from '@angular/core';
|
||||
import { Badge } from '@ionic/angular';
|
||||
|
||||
@Component({
|
||||
selector: 'app-badge-page',
|
||||
template: `
|
||||
<ion-app>
|
||||
<ion-header>
|
||||
<ion-toolbar>
|
||||
<ion-title>Badges</ion-title>
|
||||
</ion-toolbar>
|
||||
</ion-header>
|
||||
<ion-content>
|
||||
<ion-list>
|
||||
<ion-list-header>Badges Right</ion-list-header>
|
||||
<ion-item>
|
||||
<ion-badge slot="end" color="primary">99</ion-badge>
|
||||
<ion-label>Default Badge</ion-label>
|
||||
</ion-item>
|
||||
<ion-item>
|
||||
<ion-badge slot="end" color="primary">99</ion-badge>
|
||||
<ion-label>Primary Badge</ion-label>
|
||||
</ion-item>
|
||||
<ion-item>
|
||||
<ion-badge slot="end" color="secondary">99</ion-badge>
|
||||
<ion-label>Secondary Badge</ion-label>
|
||||
</ion-item>
|
||||
<ion-item>
|
||||
<ion-badge slot="end" color="danger">99</ion-badge>
|
||||
<ion-label>Danger Badge</ion-label>
|
||||
</ion-item>
|
||||
<ion-item>
|
||||
<ion-badge slot="end" color="light">99</ion-badge>
|
||||
<ion-label>Light Badge</ion-label>
|
||||
</ion-item>
|
||||
<ion-item>
|
||||
<ion-badge slot="end" color="dark">99</ion-badge>
|
||||
<ion-label>Dark Badge</ion-label>
|
||||
</ion-item>
|
||||
<ion-item (click)="toggleColor()">
|
||||
<ion-badge slot="end" [color]="dynamicColor">{{dynamicColor}}</ion-badge>
|
||||
<ion-label>Dynamic Badge Color (toggle)</ion-label>
|
||||
</ion-item>
|
||||
</ion-list>
|
||||
|
||||
<ion-list>
|
||||
<ion-list-header>Badges Left</ion-list-header>
|
||||
<ion-item>
|
||||
<ion-badge slot="start" color="primary">99</ion-badge>
|
||||
<ion-label>Default Badge</ion-label>
|
||||
</ion-item>
|
||||
<ion-item>
|
||||
<ion-badge slot="start" color="primary">99</ion-badge>
|
||||
<ion-label>Primary Badge</ion-label>
|
||||
</ion-item>
|
||||
<ion-item>
|
||||
<ion-badge slot="start" color="secondary">99</ion-badge>
|
||||
<ion-label>Secondary Badge</ion-label>
|
||||
</ion-item>
|
||||
<ion-item>
|
||||
<ion-badge slot="start" color="danger">99</ion-badge>
|
||||
<ion-label>Danger Badge</ion-label>
|
||||
</ion-item>
|
||||
<ion-item>
|
||||
<ion-badge slot="start" color="light">99</ion-badge>
|
||||
<ion-label>Light Badge</ion-label>
|
||||
</ion-item>
|
||||
<ion-item>
|
||||
<ion-badge slot="start" color="dark">99</ion-badge>
|
||||
<ion-label>Dark Badge</ion-label>
|
||||
</ion-item>
|
||||
</ion-list>
|
||||
</ion-content>
|
||||
</ion-app>
|
||||
`
|
||||
})
|
||||
export class BadgePageComponent {
|
||||
dynamicColor = 'primary';
|
||||
|
||||
@ViewChild(Badge) badge: Badge;
|
||||
|
||||
ngOnInit() {
|
||||
console.log(this.badge);
|
||||
}
|
||||
|
||||
toggleColor() {
|
||||
if (this.dynamicColor === 'primary') {
|
||||
this.dynamicColor = 'secondary';
|
||||
} else if (this.dynamicColor === 'secondary') {
|
||||
this.dynamicColor = 'danger';
|
||||
} else {
|
||||
this.dynamicColor = 'primary';
|
||||
}
|
||||
}
|
||||
}
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user