mirror of
https://github.com/ionic-team/ionic-framework.git
synced 2026-03-13 10:22:08 +08:00
Compare commits
26 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
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
|
||||
|
||||
31
.github/ISSUE_TEMPLATE.md
vendored
31
.github/ISSUE_TEMPLATE.md
vendored
@@ -1,18 +1,12 @@
|
||||
<!-- Before submitting an issue, please consult our troubleshooting guide (http://ionicframework.com/docs/troubleshooting/) and developer resources (http://ionicframework.com/docs/developer-resources/) -->
|
||||
|
||||
<!-- Please make sure you are posting an issue pertaining to the Ionic Framework. If you are having an issue with the Ionic Pro services (Ionic View, Ionic Deploy, etc.) please consult the Ionic Pro support portal (http://support.ionicjs.com) -->
|
||||
|
||||
**Ionic version:** (check one with "x")
|
||||
(For Ionic 1.x issues, please use https://github.com/ionic-team/ionic-v1)
|
||||
[ ] **1.x** (For Ionic 1.x issues, please use https://github.com/ionic-team/ionic-v1)
|
||||
[ ] **2.x**
|
||||
[ ] **3.x**
|
||||
[ ] **4.x**
|
||||
|
||||
**I'm submitting a ...** (check one with "x")
|
||||
[ ] 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/ -->
|
||||
[ ] support request => Please do not submit support requests here, use one of these channels: https://forum.ionicframework.com/ or http://ionicworldwide.herokuapp.com/
|
||||
|
||||
**Current behavior:**
|
||||
<!-- Describe how the bug manifests. -->
|
||||
@@ -21,22 +15,17 @@
|
||||
<!-- Describe what the behavior would be without the bug. -->
|
||||
|
||||
**Steps to reproduce:**
|
||||
<!-- Please explain the steps required to duplicate the issue, especially if you are able to provide a sample application. -->
|
||||
<!-- If you are able to illustrate the bug or feature request with an example, please provide steps to reproduce and if possible a demo using one of the following templates:
|
||||
|
||||
For Ionic V1 issues - http://plnkr.co/edit/Xo1QyAUx35ny1Xf9ODHx?p=preview
|
||||
|
||||
For Ionic issues - http://plnkr.co/edit/cpeRJs?p=preview
|
||||
-->
|
||||
|
||||
**Related code:**
|
||||
|
||||
<!-- If you are able to illustrate the bug or feature request with an example, please provide a sample application via one of the following means:
|
||||
|
||||
A sample application via GitHub
|
||||
|
||||
StackBlitz (https://stackblitz.com)
|
||||
|
||||
Plunker (http://plnkr.co/edit/cpeRJs?p=preview)
|
||||
|
||||
-->
|
||||
|
||||
```
|
||||
insert short code snippets here
|
||||
insert any relevant code here
|
||||
```
|
||||
|
||||
**Other information:**
|
||||
@@ -47,3 +36,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
|
||||
|
||||
5
.gitignore
vendored
5
.gitignore
vendored
@@ -13,13 +13,10 @@ log.txt
|
||||
.sass-cache/
|
||||
.versions/
|
||||
coverage/
|
||||
collection/
|
||||
dist/
|
||||
node_modules/
|
||||
tmp/
|
||||
temp/
|
||||
core/theme-builder/
|
||||
core/test-components/
|
||||
$RECYCLE.BIN/
|
||||
|
||||
.DS_Store
|
||||
@@ -34,8 +31,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
3058
CHANGELOG.md
3058
CHANGELOG.md
File diff suppressed because it is too large
Load Diff
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';
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,14 +0,0 @@
|
||||
import { NgModule } from '@angular/core';
|
||||
import { Routes, RouterModule } from '@angular/router';
|
||||
|
||||
import { BadgePageComponent } from './badge-page.component';
|
||||
|
||||
const routes: Routes = [
|
||||
{ path: '', component: BadgePageComponent }
|
||||
];
|
||||
|
||||
@NgModule({
|
||||
imports: [RouterModule.forChild(routes)],
|
||||
exports: [RouterModule]
|
||||
})
|
||||
export class BadgeRoutingModule { }
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user