diff --git a/.gitignore b/.gitignore index 35dd5a667ec62e..a79d28de0ca65b 100644 --- a/.gitignore +++ b/.gitignore @@ -35,3 +35,4 @@ node_modules .sublimets .settings/launch.json +yarn.lock diff --git a/CONTRIBUTORS.md b/CONTRIBUTORS.md index 44f0d8e9a03fdf..8b263f19aefbc4 100644 --- a/CONTRIBUTORS.md +++ b/CONTRIBUTORS.md @@ -401,6 +401,7 @@ This document generated by [dt-contributors-generator](https://github.com/vvakam * [:link:](egg.js/egg.js.d.ts) [Egg.js](https://github.com/mikeflynn/egg.js) by [Markus Peloso](https://github.com/ToastHawaii) * [:link:](ejs-locals/ejs-locals.d.ts) [ejs-locals](https://github.com/randometc/ejs-locals) by [jt000](https://github.com/jt000) * [:link:](ejs/ejs.d.ts) [ejs.js](http://ejs.co) by [Ben Liddicott](https://github.com/benliddicott/DefinitelyTyped) +* [:link:](ejson/ejson.d.ts) [ejson](https://www.npmjs.com/package/ejson) by [Shantanu Bhadoria](https://github.com/shantanubhadoria) * [:link:](elasticsearch/elasticsearch.d.ts) [elasticsearch](https://www.elastic.co) by [Casper Skydt](https://github.com/CasperSkydt/DefinitelyTyped), [Blake Smith](https://github.com/bfsmith/DefinitelyTyped) * [:link:](jquery.elang/jquery.elang.d.ts) [eLang](https://github.com/sumegizoltan/ELang) by [Zoltan Sumegi](https://github.com/sumegizoltan) * [:link:](github-electron/github-electron.d.ts) [Electron](http://electron.atom.io) by [jedmao](https://github.com/jedmao), [rhysd](https://rhysd.github.io), [Milan Burda](https://github.com/miniak) @@ -1189,7 +1190,7 @@ This document generated by [dt-contributors-generator](https://github.com/vvakam * [:link:](ng-stomp/ng-stomp.d.ts) [ngStomp](https://github.com/beevelop/ng-stomp) by [Lukasz Potapczuk](https://github.com/lpotapczuk) * [:link:](ngstorage/ngstorage.d.ts) [ngstorage](https://github.com/gsklee/ngStorage) by [Jakub Pistek](https://github.com/kubiq) * [:link:](nightmare/nightmare.d.ts) [Nightmare](https://github.com/segmentio/nightmare) by [horiuchi](https://github.com/horiuchi) -* [:link:](noble/noble.d.ts) [noble](https://github.com/sandeepmistry/noble) by [Seon-Wook Park](https://github.com/swook), [Hans Bakker](https://github.com/wind-rider) +* [:link:](noble/noble.d.ts) [noble](https://github.com/sandeepmistry/noble) by [Seon-Wook Park](https://github.com/swook), [Hans Bakker](https://github.com/wind-rider), [Shantanu Bhadoria](https://github.com/shantanubhadoria) * [:link:](nock/nock.d.ts) [nock](https://github.com/pgte/nock) by [bonnici](https://github.com/bonnici) * [:link:](node-imap/imap.d.ts) [node imap](https://github.com/mscdex/node-imap) by [Steve Fenton](https://github.com/Steve-Fenton) * [:link:](oauth2-server/oauth2-server.d.ts) [Node OAuth2 Server](https://github.com/thomseddon/node-oauth2-server) by [Robbie Van Gorkom](https://github.com/vangorra) diff --git a/PULL_REQUEST_TEMPLATE.md b/PULL_REQUEST_TEMPLATE.md index 730bd78af2b5db..053b2c3eaea9d7 100644 --- a/PULL_REQUEST_TEMPLATE.md +++ b/PULL_REQUEST_TEMPLATE.md @@ -1,8 +1,16 @@ -case 1. Add a new type definition. -- [ ] checked compilation succeeds with `--target es6` and `--noImplicitAny` options. -- [ ] has correct [naming convention](http://definitelytyped.org/guides/contributing.html#naming-the-file) -- [ ] has a [test file](http://definitelytyped.org/guides/contributing.html#tests) with the suffix of `-tests.ts` or `-tests.tsx`. +Please fill in this template. -case 2. Improvement to existing type definition. -- documentation or source code reference which provides context for the suggested changes. url http://api.jquery.com/html . - - it has been reviewed by a DefinitelyTyped member. +- [ ] Prefer to make your PR against the `types-2.0` branch. +- [ ] The package does not provide its own types, and you can not add them. +- [ ] Test the change in your own code. +- [ ] Follow the advice from the [readme](https://github.com/DefinitelyTyped/DefinitelyTyped#make-a-pull-request). +- [ ] Avoid [common mistakes](https://github.com/DefinitelyTyped/DefinitelyTyped#common-mistakes). + +If adding a new definition: +- [ ] If this is for an NPM package, match the name. If not, do not conflict with the name of an NPM package. +- [ ] Run `tsc` without errors. +- [ ] Include the required [files](https://github.com/DefinitelyTyped/DefinitelyTyped#create-a-new-package) and header. + +If changing an existing definition: +- [ ] Provide a URL to documentation or source code which provides context for the suggested changes: <> +- [ ] Increase the version number in the header if appropriate. diff --git a/README.md b/README.md index b188982fbfc3f9..8caef8c8e2b9c1 100644 --- a/README.md +++ b/README.md @@ -4,36 +4,229 @@ > The repository for *high quality* TypeScript type definitions. -For more information see the [definitelytyped.org](http://definitelytyped.org) website. +Also see the [definitelytyped.org](http://definitelytyped.org) website, although information in this README is more up-to-date. -## Usage -Include a line like this: +## What are declaration files? -```typescript -/// +See the [TypeScript handbook](http://www.typescriptlang.org/docs/handbook/declaration-files/introduction.html). + + +## How do I get them? + +### npm + +This is the preferred method. This is only available for TypeScript 2.0+ users. For example: + +```sh +npm install --save-dev @types/node ``` -## Contributions +The types should then be automatically included by the compiler. +See more in the [handbook](http://www.typescriptlang.org/docs/handbook/declaration-files/consumption.html). + +For an NPM package "foo", typings for it will be at "@types/foo". +If you can't find your package, look for it on [TypeSearch](https://microsoft.github.io/TypeSearch/). + +If you still can't find it, check if it [bundles](http://www.typescriptlang.org/docs/handbook/declaration-files/publishing.html) its own typings. +This is usually provided in a `"types"` or `"typings"` field in the `package.json`, +or just look for any ".d.ts" files in the package and manually include them with a `/// `. + + +### Other methods + +These can be used by TypeScript 1.0. + +* [Typings](https://github.com/typings/typings) +* [NuGet](http://nuget.org/Tpackages?q=DefinitelyTyped) +* Manually download from the `master` branch of this repository + +You may need to add manual [references](http://www.typescriptlang.org/docs/handbook/triple-slash-directives.html). + + +## How can I contribute? DefinitelyTyped only works because of contributions by users like you! -Please see the [contribution guide](http://definitelytyped.org/guides/contributing.html) on how to contribute to DefinitelyTyped. +### Test + +Before you share your improvement with the world, use it yourself. + +#### Test editing an exiting package + +To add new features you can use [module augmentation](http://www.typescriptlang.org/docs/handbook/declaration-merging.html). +You can also directly edit the types in `node_modules/@types/foo/index.d.ts`, +or copy them from there and paste inside of `declarations.d.ts` and follow the steps below. + + +#### Test a new package + +* Add a new file `declarations.d.ts` to your project. +* Add it to the compilation, through `"includes"` or `"files"` in your [tsconfig](http://www.typescriptlang.org/docs/handbook/tsconfig-json.html), +or through a `/// ` declaration in your code. +* Inside `declarations.d.ts`, write `declare module "foo" { }`, then write the module declaration inside. +* Test that your code works. +* *Then*, once you've tested your definitions, make a PR contributing the definition. + + +### Make a pull request + +Once you've tested your package, you can share it on DefinitelyTyped. + +First, [fork](https://guides.github.com/activities/forking/) this repository. +Then inside your repository: + +* `git checkout types-2.0` + +New work should generally be done on the `types-2.0` branch. +If you want your changes to be available to `typings` users, then you may edit `master` instead. + + +#### Edit an existing package + +* `cd my-package-to-edit` +* Make changes. Remember to edit tests. +* You may also want to add yourself to "Definitions by" section of the package header. +* `npm install -g typescript@2.0` and run `tsc`. + +When you make a PR to edit an existing package, `dt-bot` should @-mention previous authors. +If it doesn't, you can do so yourself in the comment associated with the PR. + -## How to get the definitions +#### Create a new package -* Directly from the GitHub repos -* [NuGet packages](http://nuget.org/packages?q=DefinitelyTyped) -* [Typings - TypeScript Definition Manager](https://github.com/typings/typings) +If you are the library author, or can make a pull request to the library, [bundle](http://www.typescriptlang.org/docs/handbook/declaration-files/publishing.html) types instead of publishing to DefinitelyTyped. -## List of definitions +If you are adding typings for an NPM package, create a directory with the same name. +If the package you are adding typings for is not on NPM, make sure the name you choose for it does not conflict with the name of a package on NPM. +(You can use `npm info foo` to check for the existence of the `foo` package.) -* See [CONTRIBUTORS.md](CONTRIBUTORS.md) +Your package should have this structure: -## Requested definitions +| File | Purpose | +| --- | --- | +| index.d.ts | This contains the typings for the package. | +| foo-tests.ts | This contains sample code which tests the typings. This code does *not* run, but it is type-checked. | +| tsconfig.json | This allows you to run `tsc` within the package. | + +`index.d.ts` should start with a header looking like: + +```ts +// Type definitions for foo 1.2 +// Project: https://github.com/baz/foo +// Definitions by: My Self +// Definitions: https://github.com/DefinitelyTyped/DefinitelyTyped +``` + +The `Project` link does not have to be to GitHub, but prefer linking to a source code repository rather than to a project website. + +`tsconfig.json` should look like this: + +```json +{ + "compilerOptions": { + "module": "commonjs", + "target": "es6", + "noImplicitAny": true, + "strictNullChecks": true, + "baseUrl": "../", + "typeRoots": [ + "../" + ], + "types": [], + "noEmit": true, + "forceConsistentCasingInFileNames": true + }, + "files": [ + "index.d.ts", + "foo-tests.ts" + ] +} +``` + +These should be identical accross projects except that `foo-tests` will be replaced with the name of your test file, +and you may also add the `"jsx"` compiler option if your library needs it. + +DefinitelyTyped members routinely monitor for new PRs, though keep in mind that the number of other PRs may slow things down. + +For a good example package, see [base64-js](https://github.com/DefinitelyTyped/DefinitelyTyped/tree/types-2.0/base64-js). + +#### Common mistakes + +* First, follow advice from the [handbook](http://www.typescriptlang.org/docs/handbook/declaration-files/do-s-and-don-ts.html). +* Formatting: Either use all tabs, or always use 4 spaces. Also, always use semicolons, and use egyptian braces. +* `interface X {}`: An empty interface is essentially the `{}` type: it places no constraints on an object. +* `interface IFoo {}`: Don't add `I` to the front of an interface name. +* `interface Foo { new(): Foo; }`: + This defines a type of objects that are new-able. You probably want `declare class Foo { constructor(); } +* `const Class: { new(): IClass; }`: + Prefer to use a class declaration `class Class { constructor(); }` instead of a new-able constant. +* `namespace foo {}`: + Do not add a namespace just so that the `import * as foo` syntax will work. + If it is commonJs module with a single export, you should use the `import foo = require("foo")` syntax. + See more explanation [here](https://stackoverflow.com/questions/39415661/why-cant-i-import-a-class-or-function-with-import-as-x-from-y). +* `getMeAT(): T`: + If a type parameter does not appear in the types of any parameters, you don't really have a generic function, you just have a disguised type assertion. + Prefer to use a real type assertion, e.g. `getMeAT() as number`. + Example where a type parameter is acceptable: `function id(value: T): T;`. + Example where it is not acceptable: `function parseJson(json: string): T;`. + Exception: `new Map()` is OK. + + +#### Removing a package + +When a package [bundles](http://www.typescriptlang.org/docs/handbook/declaration-files/publishing.html) its own types, types should be removed from DefinitelyTyped to avoid confusion. +Make a PR doing the following: +* Delete the directory. +* Add a new entry to `notNeededPackages.json`. + - `libraryName`: Descriptive name of the library, e.g. "Angular 2" instead of "angular2". (May be identical to "typingsPackageName".) + - `typingsPackageName`: This is the name of the directory you just deleted. + - `sourceRepoURL`: This should point to the repository that contains the typings. + - `asOfVersion`: A stub will be published to `@types/foo` with this version. Should be higher than any currently published version. +* Any other packages in DefinitelyTyped that referenced the deleted package should be updated to reference the bundled types. + To do this, add a `package.json` with `"dependencies": { "foo": "x.y.z" }`. + + +## FAQ + +#### What exactly is the relationship between this repository and the `@types` packages on NPM? + +The `types-2.0` branch is automatically published to the `@types` scope on NPM thanks to [types-publisher](https://github.com/Microsoft/types-publisher). +This usually happens within an hour of changes being merged. + +Changes to the `master` branch are also manually merged into the `types-2.0` branch, but this takes longer. + +#### I'm writing a definition that depends on another definition. Should I use `` or an import? + +If the module you're referencing is an external module (uses `export`), use an import. +If the module you're referenceing is an ambient module (uses `declare module`, or just declares globals), use ``. + +#### What do I do about older versions of typings? + +Currently we don't support this, though it is [planned](https://github.com/Microsoft/types-publisher/issues/3). +If you're adding a new major version of a library, you can copy `index.d.ts` to `foo-v2.3.d.ts` and edit `index.d.ts` to be the new version. + +#### I notice some packages having a `package.json` here. + +Usually you won't need this. When publishing a package we will normally automatically create a `package.json` for it. +A `package.json` may be included for the sake of specifying dependencies. Here's an [example](https://github.com/DefinitelyTyped/DefinitelyTyped/blob/types-2.0/pikaday/package.json). +We do not allow other fields, such as `"description"`, to be defined manually. +Also, if you need to reference an older version of typings, you must do that by adding `"dependencies": { "@types/foo": "x.y.z" }` to the package.json. + +#### I notice some `tsconfig.json` are missing `"noImplicitAny": true` or `"strictNullChecks": true`. + +Then they are wrong. You can help by submitting a pull request to fix them. + +#### Definitions in types-2.0 seem written differently than in master. + +If you're targeting types-2.0, write it like the types-2.0 definitions. +If you're targeting master, we may change it to the new style when merging from master to types-2.0. + +#### Can I request a definition? Here are the [currently requested definitions](https://github.com/DefinitelyTyped/DefinitelyTyped/labels/Definition%3ARequest). + ## License This project is licensed under the MIT license. diff --git a/ajv/ajv.d.ts b/ajv/ajv.d.ts index d8bfd56ef343fa..304fba2512e511 100644 --- a/ajv/ajv.d.ts +++ b/ajv/ajv.d.ts @@ -82,7 +82,7 @@ declare module "ajv" { passContext?: boolean; loopRequired?: number; ownProperties?: boolean; - multipleOfPrecision?: boolean; + multipleOfPrecision?: boolean | number; errorDataPath?: string, messages?: boolean; beautify?: boolean; diff --git a/amcharts/AmCharts.d.ts b/amcharts/AmCharts.d.ts index 4f5dbe90f79bdf..ae5baad50eb667 100644 --- a/amcharts/AmCharts.d.ts +++ b/amcharts/AmCharts.d.ts @@ -23,6 +23,9 @@ declare namespace AmCharts { /** Set it to true if you want UTC time to be used instead of local time. */ var useUTC: boolean; + + /** Object with themes */ + var themes: any; /** Clears all the charts on page, removes listeners and intervals. */ function clear(); diff --git a/angular-material/angular-material.d.ts b/angular-material/angular-material.d.ts index 31da141bf9db8b..f100fd4d4bab33 100644 --- a/angular-material/angular-material.d.ts +++ b/angular-material/angular-material.d.ts @@ -160,6 +160,7 @@ declare namespace angular.material { hideDelay(delay: number): T; position(position: string): T; parent(parent?: string|Element|JQuery): T; // default: root node + toastClass(toastClass: string): T; } interface ISimpleToastPreset extends IToastPreset { @@ -338,6 +339,7 @@ declare namespace angular.material { onRemoving?: Function; onDomRemoved?: Function; origin?: string|JQuery|Element; + onCloseSuccess?: ((panel: IPanelRef, closeReason: string) => any); } interface IPanelRef { @@ -410,5 +412,15 @@ declare namespace angular.material { interceptorTypes: { CLOSE: string, }; + closeReasons: { + CLICK_OUTSIDE: string, + ESCAPE: string, + }; + absPosition: { + TOP: string, + RIGHT: string, + BOTTOM: string, + LEFT: string, + }; } } diff --git a/angular-protractor/angular-protractor.d.ts b/angular-protractor/angular-protractor.d.ts index d33eeddaced6a9..b05eda4a13329a 100644 --- a/angular-protractor/angular-protractor.d.ts +++ b/angular-protractor/angular-protractor.d.ts @@ -1829,8 +1829,8 @@ declare namespace protractor { function wrapDriver(webdriver: webdriver.WebDriver, opt_baseUrl?: string, opt_rootElement?: string): Protractor; } -interface cssSelectorHelper { - (cssLocator: string): protractor.ElementFinder; +interface selectorHelper { + (cssLocator: string | Function | HTMLElement | Document | Array): protractor.ElementFinder; } interface cssArraySelectorHelper { @@ -1841,7 +1841,7 @@ declare var browser: protractor.IBrowser; declare var by: protractor.IProtractorLocatorStrategy; declare var By: protractor.IProtractorLocatorStrategy; declare var element: protractor.Element; -declare var $: cssSelectorHelper; +declare var $: selectorHelper; declare var $$: cssArraySelectorHelper; declare module 'protractor' { diff --git a/angular-ui-router-default/angular-ui-router-default-tests.ts b/angular-ui-router-default/angular-ui-router-default-tests.ts new file mode 100644 index 00000000000000..2b6bfbe61ec8bc --- /dev/null +++ b/angular-ui-router-default/angular-ui-router-default-tests.ts @@ -0,0 +1,39 @@ +/// + +angular.module("test", [ + "ui.router", + "ui.router.default" +]) + .config(function($stateProvider: angular.ui.IStateProvider) { + $stateProvider + .state('concrete', { + // no abstract or default + }) + .state('string', { + abstract: true, + default: 'concrete' + }) + .state('func_str', { + abstract: true, + default: function($rootScope): string { return $rootScope.test; } + }) + .state('func_promise', { + abstract: true, + default: function($q: ng.IQService): ng.IPromise { + return $q.when("concrete"); + } + }) + .state('injection_str', { + abstract: true, + default: ["$rootScope", function($rootScope) { + return $rootScope.test; + }] + }) + .state('injection_promise', { + abstract: true, + default: ["$q", function($q: ng.IQService) { + return $q.when("concrete"); + }] + }) + ; + }); diff --git a/angular-ui-router-default/angular-ui-router-default.d.ts b/angular-ui-router-default/angular-ui-router-default.d.ts new file mode 100644 index 00000000000000..9d102681cf8a77 --- /dev/null +++ b/angular-ui-router-default/angular-ui-router-default.d.ts @@ -0,0 +1,17 @@ +// Type definitions for angular-ui-router-default 0.5+ +// Project: https://github.com/nonplus/angular-ui-router-default +// Definitions by: Stepan Riha +// Definitions: https://github.com/DefinitelyTyped/DefinitelyTyped + +/// + +declare namespace angular.ui { + export type StateDefaultSpecifier = string + | ((...args: any[]) => string) + | ((...args: any[]) => ng.IPromise) + | (string | ((...args: any[]) => string))[] + | (string | ((...args: any[]) => ng.IPromise))[]; + interface IState { + default?: StateDefaultSpecifier + } +} diff --git a/angular-ui-router-uib-modal/angular-ui-router-uib-modal-tests.ts b/angular-ui-router-uib-modal/angular-ui-router-uib-modal-tests.ts new file mode 100644 index 00000000000000..3f14b2a40fbdc0 --- /dev/null +++ b/angular-ui-router-uib-modal/angular-ui-router-uib-modal-tests.ts @@ -0,0 +1,30 @@ +/// + +angular.module("test", [ + "ui.bootstrap", + "ui.router", + "ui.router.default" +]) + .config(function($stateProvider: angular.ui.IStateProvider) { + $stateProvider + .state('contacts', { + // no modal + resolve: { + a: function() { + return "a"; + }, + b: function() { + return ["a", "b"]; + } + } + }) + .state('contacts.contact', { + // boolean modal + modal: true + }) + .state('contacts.contact.edit', { + // string[] modal + modal: ["a", "b"] + }) + ; + }); diff --git a/angular-ui-router-uib-modal/angular-ui-router-uib-modal.d.ts b/angular-ui-router-uib-modal/angular-ui-router-uib-modal.d.ts new file mode 100644 index 00000000000000..598fe964fe853a --- /dev/null +++ b/angular-ui-router-uib-modal/angular-ui-router-uib-modal.d.ts @@ -0,0 +1,12 @@ +// Type definitions for angular-ui-uib-modal 0.11+ (ui.router module) +// Project: https://github.com/nonplus/angular-ui-router-uib-modal +// Definitions by: Stepan Riha +// Definitions: https://github.com/DefinitelyTyped/DefinitelyTyped + +/// + +declare namespace angular.ui { + interface IState { + modal?: boolean | string[]; + } +} diff --git a/angularjs/angular-tests.ts b/angularjs/angular-tests.ts index 4c03e7c2198369..0b0314b7d6e2d7 100644 --- a/angularjs/angular-tests.ts +++ b/angularjs/angular-tests.ts @@ -192,8 +192,25 @@ mod.controller({ MyCtrl2: function() {}, MyCtrl3: ['$fooService', function($fooService: any) { }] }); -mod.directive('name', function ($scope: ng.IScope) { }) -mod.directive('name', ['$scope', function ($scope: ng.IScope) { }]) +mod.directive('myDirectiveA', ($rootScope: ng.IRootScopeService) => { + return (scope, el, attrs) => { + let foo = 'none'; + el.click(e => { + foo = e.type; + $rootScope.$apply(); + }); + scope.$watch(() => foo, () => el.text(foo)); + }; +}); +mod.directive('myDirectiveB', ['$rootScope', function ($rootScope: ng.IRootScopeService) { + return { + link(scope, el, attrs) { + el.click(e => { + el.hide(); + }); + } + }; +}]); mod.directive({ myFooDir: () => ({ template: 'my-foo-dir.tpl.html' @@ -279,8 +296,14 @@ namespace TestQ { b: string; c: boolean; } + interface TValue { + e: number; + f: boolean; + } var tResult: TResult; var promiseTResult: angular.IPromise; + var tValue: TValue; + var promiseTValue: angular.IPromise; var $q: angular.IQService; var promiseAny: angular.IPromise; @@ -349,6 +372,22 @@ namespace TestQ { let result: angular.IPromise; result = $q.when(tResult); result = $q.when(promiseTResult); + + result = $q.when(tValue, (result: TValue) => tResult); + result = $q.when(tValue, (result: TValue) => tResult, (any) => any); + result = $q.when(tValue, (result: TValue) => tResult, (any) => any, (any) => any); + + result = $q.when(promiseTValue, (result: TValue) => tResult); + result = $q.when(promiseTValue, (result: TValue) => tResult, (any) => any); + result = $q.when(promiseTValue, (result: TValue) => tResult, (any) => any, (any) => any); + + result = $q.when(tValue, (result: TValue) => promiseTResult); + result = $q.when(tValue, (result: TValue) => promiseTResult, (any) => any); + result = $q.when(tValue, (result: TValue) => promiseTResult, (any) => any, (any) => any); + + result = $q.when(promiseTValue, (result: TValue) => promiseTResult); + result = $q.when(promiseTValue, (result: TValue) => promiseTResult, (any) => any); + result = $q.when(promiseTValue, (result: TValue) => promiseTResult, (any) => any, (any) => any); } } diff --git a/angularjs/angular.d.ts b/angularjs/angular.d.ts index e879668039e83c..b16438bdcbacc6 100644 --- a/angularjs/angular.d.ts +++ b/angularjs/angular.d.ts @@ -1041,6 +1041,7 @@ declare namespace angular { * @param value Value or a promise */ when(value: IPromise|T): IPromise; + when(value: IPromise|T, successCallback: (promiseValue: T) => IPromise|TResult, errorCallback?: (reason: any) => any, notifyCallback?: (state: any) => any): IPromise; /** * Wraps an object that might be a value or a (3rd party) then-able promise into a $q promise. This is useful when you are dealing with an object that might or might not be a promise, or if the promise comes from a source that can't be trusted. */ @@ -1769,7 +1770,7 @@ declare namespace angular { /////////////////////////////////////////////////////////////////////////// interface IDirectiveFactory { - (...args: any[]): IDirective; + (...args: any[]): IDirective | IDirectiveLinkFn; } interface IDirectiveLinkFn { @@ -1777,8 +1778,8 @@ declare namespace angular { scope: IScope, instanceElement: JQuery, instanceAttributes: IAttributes, - controller: {}, - transclude: ITranscludeFunction + controller?: IController | IController[] | {[key: string]: IController}, + transclude?: ITranscludeFunction ): void; } @@ -1806,7 +1807,6 @@ declare namespace angular { controller?: string | Injectable; controllerAs?: string; /** - * @deprecated * Deprecation warning: although bindings for non-ES6 class controllers are currently bound to this before * the controller constructor is called, this use is now deprecated. Please place initialization code that * relies upon bindings inside a $onInit method on the controller, instead. diff --git a/archiver/archiver-tests.ts b/archiver/archiver-tests.ts index dcd71ca905bcb6..078236bd20f7ed 100644 --- a/archiver/archiver-tests.ts +++ b/archiver/archiver-tests.ts @@ -11,4 +11,13 @@ var readStream = FS.createReadStream('./archiver.d.ts'); archiver.pipe(writeStream); archiver.append(readStream, {name: 'archiver.d.ts'}); -archiver.finalize(); \ No newline at end of file +archiver.finalize(); + + +archiver.directory('./path', './someOtherPath'); +archiver.directory('./path', { name: "testName"} ); + +archiver.directory('./', "", {}); +archiver.directory('./', {name: 'test'}, {}); + +archiver.bulk({ mappaing: {} }); \ No newline at end of file diff --git a/archiver/archiver.d.ts b/archiver/archiver.d.ts index b31c8ad619e39f..7b80877768d361 100644 --- a/archiver/archiver.d.ts +++ b/archiver/archiver.d.ts @@ -25,6 +25,11 @@ declare module "archiver" { interface Archiver extends STREAM.Transform { pipe(writeStream: FS.WriteStream): void; append(source: FS.ReadStream | Buffer | string, name: nameInterface): void; + + directory(dirpath: string, destpath: nameInterface | string): void; + directory(dirpath: string, destpath: nameInterface | string, data: any | Function): void; + + bulk(mappings: any): void; finalize(): void; } diff --git a/async/async-tests.ts b/async/async-tests.ts index fa0e49c4c1fb0c..63f46c3ae5f51a 100644 --- a/async/async-tests.ts +++ b/async/async-tests.ts @@ -437,3 +437,357 @@ async.dir(function (name, callback) { callback(null, { hello: name }); }, 1000); }, "world"); + +// each + +async.each({ + "a": 1, + "b": 2 +}, function(val: number, next: ErrorCallback): void { + + setTimeout(function(): void { + + console.log(`async.each: ${val}`); + + next(); + + }, 500); + +}, function(err?: Error): void { + + console.log("async.each: done."); + +}); + +async.eachSeries({ + "a": 1, + "b": 2 +}, function(val: number, next: ErrorCallback): void { + + setTimeout(function(): void { + + console.log(`async.eachSeries: ${val}`); + + next(); + + }, 500); + +}, function(err?: Error): void { + + console.log("async.eachSeries: done."); + +}); + +async.eachLimit({ + "a": 1, + "b": 2, + "c": 3, + "d": 4, + "e": 5, + "f": 6 +}, 2, function(val: number, next: ErrorCallback): void { + + setTimeout(function(): void { + + console.log(`async.eachLimit: ${val}`); + + next(); + + }, 500); + +}, function(err?: Error): void { + + console.log("async.eachLimit: done."); + +}); + +// forEachOf/eachOf + +async.eachOf({ + "a": 1, + "b": 2 +}, function(val: number, key: string, next: ErrorCallback): void { + + setTimeout(function(): void { + + console.log(`async.forEachOf/eachOf: ${key} = ${val}`); + + next(); + + }, 500); + +}, function(err?: Error): void { + + console.log("async.forEachOf/eachOf: done."); + +}); + +async.forEachOfSeries({ + "a": 1, + "b": 2 +}, function(val: number, key: string, next: ErrorCallback): void { + + setTimeout(function(): void { + + console.log(`async.forEachOfSeries: ${key} = ${val}`); + + next(); + + }, 500); + +}, function(err?: Error): void { + + console.log("async.forEachOfSeries: done."); + +}); + +async.forEachOfLimit({ + "a": 1, + "b": 2, + "c": 3, + "d": 4, + "e": 5, + "f": 6 +}, 2, function(val: number, key: string, next: ErrorCallback): void { + + setTimeout(function(): void { + + console.log(`async.forEachOfLimit: ${key} = ${val}`); + + next(); + + }, 500); + +}, function(err?: Error): void { + + console.log("async.forEachOfLimit: done."); + +}); + +// map + +async.map({ + "a": 1, + "b": 2, + "c": 3 +}, function(val: number, next: AsyncResultCallback): void { + + setTimeout(function(): void { + + console.log(`async.map: ${val}`); + + next(null, val.toString()); + + }, 500); + +}, function(err: Error, results: string[]): void { + + console.log("async.map: done with results", results); + +}); + +async.mapSeries({ + "a": 1, + "b": 2, + "c": 3 +}, function(val: number, next: AsyncResultCallback): void { + + setTimeout(function(): void { + + console.log(`async.mapSeries: ${val}`); + + next(null, val.toString()); + + }, 500); + +}, function(err: Error, results: string[]): void { + + console.log("async.mapSeries: done with results", results); + +}); + +async.mapLimit({ + "a": 1, + "b": 2, + "c": 3, + "d": 4, + "e": 5, + "f": 6 +}, 2, function(val: number, next: AsyncResultCallback): void { + + setTimeout(function(): void { + + console.log(`async.mapLimit: ${val}`); + + next(null, val.toString()); + + }, 500); + +}, function(err: Error, results: string[]): void { + + console.log("async.mapLimit: done with results", results); + +}); + +// mapValues + +async.mapValues({ + "a": 1, + "b": 2, + "c": 3 +}, function(val: number, key: string, next: AsyncResultCallback): void { + + setTimeout(function(): void { + + console.log(`async.mapValues: ${key} = ${val}`); + + next(null, val.toString()); + + }, 500); + +}, function(err: Error, results: string[]): void { + + console.log("async.mapValues: done with results", results); + +}); + +async.mapValuesSeries({ + "a": 1, + "b": 2, + "c": 3 +}, function(val: number, key: string, next: AsyncResultCallback): void { + + setTimeout(function(): void { + + console.log(`async.mapValuesSeries: ${key} = ${val}`); + + next(null, val.toString()); + + }, 500); + +}, function(err: Error, results: string[]): void { + + console.log("async.mapValuesSeries: done with results", results); + +}); + +// filter/select/reject + +async.filter({ + "a": 1, + "b": 2, + "c": 3 +}, function(val: number, next: AsyncBooleanResultCallback): void { + + setTimeout(function(): void { + + console.log(`async.filter/select: ${val}`); + + next(null, val % 2 === 0); + + }, 500); + +}, function(err: Error, results: number[]): void { + + console.log("async.filter/select: done with results", results); + +}); + +async.reject({ + "a": 1, + "b": 2, + "c": 3 +}, function(val: number, next: AsyncBooleanResultCallback): void { + + setTimeout(function(): void { + + console.log(`async.reject: ${val}`); + + next(null, val % 2 === 0); + + }, 500); + +}, function(err: Error, results: number[]): void { + + console.log("async.reject: done with results", results); + +}); + +// concat + +async.concat({ + "a": "1", + "b": "2", + "c": "3" +}, function(item: string, next: AsyncResultCallback): void { + + console.log(`async.concat: ${item}`); + + next(null, [item, item, item]); + +}, function(err: Error, results: string[]) { + + console.log("async.concat: done with results", results); + +}); + +// detect/find + +async.detect({ + "a": 1, + "b": 2, + "c": 3 +}, function(item: number, next: AsyncBooleanResultCallback): void { + + console.log(`async.detect/find: ${item}`); + + next(null, item > 1); + +}, function(err: Error, result: number) { + + if (err) { + + console.log(err); + + } else { + + console.log("async.detect/find: done with result", result); + } + +}); + +// every/all + +async.every({ + "a": 1, + "b": 2, + "c": 3 +}, function(item: number, next: AsyncBooleanResultCallback): void { + + console.log(`async.every/all: ${item}`); + + next(null, item > 0); + +}, function(err: Error, result: boolean) { + + console.log("async.every/all: done with result", result); + +}); + +// some/any + +async.some({ + "a": 1, + "b": 2, + "c": 3 +}, function(item: number, next: AsyncBooleanResultCallback): void { + + console.log(`async.some/any: ${item}`); + + next(null, item > 2); + +}, function(err: Error, result: boolean) { + + console.log("async.some/any: done with result", result); + +}); diff --git a/async/async.d.ts b/async/async.d.ts index b6830f96433e76..45d39ea955d8e0 100644 --- a/async/async.d.ts +++ b/async/async.d.ts @@ -1,11 +1,13 @@ // Type definitions for Async 2.0.1 // Project: https://github.com/caolan/async -// Definitions by: Boris Yankov , Arseniy Maximov , Joe Herman +// Definitions by: Boris Yankov , Arseniy Maximov , Joe Herman , Angus Fenying // Definitions: https://github.com/DefinitelyTyped/DefinitelyTyped interface Dictionary { [key: string]: T; } interface ErrorCallback { (err?: T): void; } +interface AsyncWaterfallCallback { (err: E, ...args: any[]): void; } +interface AsyncBooleanResultCallback { (err: E, truthValue: boolean): void; } interface AsyncResultCallback { (err: E, result: T): void; } interface AsyncResultArrayCallback { (err: E, results: T[]): void; } interface AsyncResultObjectCallback { (err: E, results: Dictionary): void; } @@ -15,7 +17,7 @@ interface AsyncIterator { (item: T, callback: ErrorCallback): void; } interface AsyncForEachOfIterator { (item: T, key: number|string, callback: ErrorCallback): void; } interface AsyncResultIterator { (item: T, callback: AsyncResultCallback): void; } interface AsyncMemoIterator { (memo: R, item: T, callback: AsyncResultCallback): void; } -interface AsyncBooleanIterator { (item: T, callback: (err: E, truthValue: boolean) => void): void; } +interface AsyncBooleanIterator { (item: T, callback: AsyncBooleanResultCallback): void; } interface AsyncWorker { (task: T, callback: ErrorCallback): void; } interface AsyncVoidFunction { (callback: ErrorCallback): void; } @@ -89,52 +91,74 @@ interface Async { // Collections each(arr: T[], iterator: AsyncIterator, callback?: ErrorCallback): void; - eachSeries(arr: T[], iterator: AsyncIterator, callback?: ErrorCallback): void; + each(arr: Dictionary, iterator: AsyncIterator, callback?: ErrorCallback): void; + eachSeries: typeof async.each; eachLimit(arr: T[], limit: number, iterator: AsyncIterator, callback?: ErrorCallback): void; - forEachOf(obj: any, iterator: (item: any, key: string|number, callback?: ErrorCallback) => void, callback: ErrorCallback): void; + eachLimit(arr: Dictionary, limit: number, iterator: AsyncIterator, callback?: ErrorCallback): void; + forEach: typeof async.each; + forEachSeries: typeof async.each; + forEachLimit: typeof async.eachLimit; forEachOf(obj: T[], iterator: AsyncForEachOfIterator, callback?: ErrorCallback): void; - forEachOfSeries(obj: any, iterator: (item: any, key: string|number, callback?: ErrorCallback) => void, callback: ErrorCallback): void; - forEachOfSeries(obj: T[], iterator: AsyncForEachOfIterator, callback?: ErrorCallback): void; - forEachOfLimit(obj: any, limit: number, iterator: (item: any, key: string|number, callback?: ErrorCallback) => void, callback: ErrorCallback): void; + forEachOf(obj: Dictionary, iterator: AsyncForEachOfIterator, callback?: ErrorCallback): void; + forEachOfSeries: typeof async.forEachOf; forEachOfLimit(obj: T[], limit: number, iterator: AsyncForEachOfIterator, callback?: ErrorCallback): void; - map(arr: T[], iterator: AsyncResultIterator, callback?: AsyncResultArrayCallback): any; - mapSeries(arr: T[], iterator: AsyncResultIterator, callback?: AsyncResultArrayCallback): any; - mapLimit(arr: T[], limit: number, iterator: AsyncResultIterator, callback?: AsyncResultArrayCallback): any; - mapValuesLimit(obj: {[name: string]: T}, limit: number, iteratee: (value: string, key: T, callback: AsyncResultCallback) => void, callback: AsyncResultArrayCallback): void; - mapValues(obj: {[name: string]: T}, iteratee: (value: string, key: T, callback: AsyncResultCallback) => void, callback: AsyncResultArrayCallback): void; + forEachOfLimit(obj: Dictionary, limit: number, iterator: AsyncForEachOfIterator, callback?: ErrorCallback): void; + eachOf: typeof async.forEachOf; + eachOfSeries: typeof async.forEachOf; + eachOfLimit: typeof async.forEachOfLimit; + map(arr: T[], iterator: AsyncResultIterator, callback?: AsyncResultArrayCallback): void; + map(arr: Dictionary, iterator: AsyncResultIterator, callback?: AsyncResultArrayCallback): void; + mapSeries: typeof async.map; + mapLimit(arr: T[], limit: number, iterator: AsyncResultIterator, callback?: AsyncResultArrayCallback): void; + mapLimit(arr: Dictionary, limit: number, iterator: AsyncResultIterator, callback?: AsyncResultArrayCallback): void; + mapValuesLimit(obj: Dictionary, limit: number, iteratee: (value: T, key: string, callback: AsyncResultCallback) => void, callback: AsyncResultCallback): void; + mapValues(obj: Dictionary, iteratee: (value: T, key: string, callback: AsyncResultCallback) => void, callback: AsyncResultCallback): void; mapValuesSeries: typeof async.mapValues; - filter(arr: T[], iterator: AsyncBooleanIterator, callback?: AsyncResultArrayCallback): any; - select(arr: T[], iterator: AsyncBooleanIterator, callback?: AsyncResultArrayCallback): any; - filterSeries(arr: T[], iterator: AsyncBooleanIterator, callback?: AsyncResultArrayCallback): any; - selectSeries(arr: T[], iterator: AsyncBooleanIterator, callback?: AsyncResultArrayCallback): any; - filterLimit(arr: T[], limit: number, iterator: AsyncBooleanIterator, callback?: AsyncResultArrayCallback): any; - selectLimit(arr: T[], limit: number, iterator: AsyncBooleanIterator, callback?: AsyncResultArrayCallback): any; - reject(arr: T[], iterator: AsyncBooleanIterator, callback?: AsyncResultArrayCallback): any; - rejectSeries(arr: T[], iterator: AsyncBooleanIterator, callback?: AsyncResultArrayCallback): any; - rejectLimit(arr: T[], limit: number, iterator: AsyncBooleanIterator, callback?: AsyncResultArrayCallback): any; - reduce(arr: T[], memo: R, iterator: AsyncMemoIterator, callback?: AsyncResultCallback): any; - inject(arr: T[], memo: R, iterator: AsyncMemoIterator, callback?: AsyncResultCallback): any; - foldl(arr: T[], memo: R, iterator: AsyncMemoIterator, callback?: AsyncResultCallback): any; - reduceRight(arr: T[], memo: R, iterator: AsyncMemoIterator, callback: AsyncResultCallback): any; - foldr(arr: T[], memo: R, iterator: AsyncMemoIterator, callback: AsyncResultCallback): any; - detect(arr: T[], iterator: AsyncBooleanIterator, callback?: AsyncResultCallback): any; + filter(arr: T[], iterator: AsyncBooleanIterator, callback?: AsyncResultArrayCallback): void; + filter(arr: Dictionary, iterator: AsyncBooleanIterator, callback?: AsyncResultArrayCallback): void; + filterSeries: typeof async.filter; + filterLimit(arr: T[], limit: number, iterator: AsyncBooleanIterator, callback?: AsyncResultArrayCallback): void; + filterLimit(arr: Dictionary, limit: number, iterator: AsyncBooleanIterator, callback?: AsyncResultArrayCallback): void; + select: typeof async.filter; + selectSeries: typeof async.filter; + selectLimit: typeof async.filterLimit; + reject: typeof async.filter; + rejectSeries: typeof async.filter; + rejectLimit: typeof async.filterLimit; + reduce(arr: T[], memo: R, iterator: AsyncMemoIterator, callback?: AsyncResultCallback): void; + inject: typeof async.reduce; + foldl: typeof async.reduce; + reduceRight: typeof async.reduce; + foldr: typeof async.reduce; + detect(arr: T[], iterator: AsyncBooleanIterator, callback?: AsyncResultCallback): void; + detect(arr: Dictionary, iterator: AsyncBooleanIterator, callback?: AsyncResultCallback): void; + detectSeries: typeof async.detect; + detectLimit(arr: T[], limit: number, iterator: AsyncBooleanIterator, callback?: AsyncResultCallback): void; + detectLimit(arr: Dictionary, limit: number, iterator: AsyncBooleanIterator, callback?: AsyncResultCallback): void; find: typeof async.detect; - detectSeries(arr: T[], iterator: AsyncBooleanIterator, callback?: AsyncResultCallback): any; - findSeries: typeof async.detectSeries; - detectLimit(arr: T[], limit: number, iterator: AsyncBooleanIterator, callback?: AsyncResultCallback): any; + findSeries: typeof async.detect; findLimit: typeof async.detectLimit; - sortBy(arr: T[], iterator: AsyncResultIterator, callback?: AsyncResultArrayCallback): any; - some(arr: T[], iterator: AsyncBooleanIterator, callback?: AsyncResultCallback): any; - someLimit(arr: T[], limit: number, iterator: AsyncBooleanIterator, callback?: AsyncResultCallback): any; - anyLimit: typeof async.someLimit; - someSeries(arr: T[], iterator: AsyncBooleanIterator, callback?: AsyncResultCallback): any; + sortBy(arr: T[], iterator: AsyncResultIterator, callback?: AsyncResultArrayCallback): void; + some(arr: T[], iterator: AsyncBooleanIterator, callback?: AsyncBooleanResultCallback): void; + some(arr: Dictionary, iterator: AsyncBooleanIterator, callback?: AsyncBooleanResultCallback): void; + someSeries: typeof async.some; + someLimit(arr: T[], limit: number, iterator: AsyncBooleanIterator, callback?: AsyncBooleanResultCallback): void; + someLimit(arr: Dictionary, limit: number, iterator: AsyncBooleanIterator, callback?: AsyncBooleanResultCallback): void; + any: typeof async.some; anySeries: typeof async.someSeries; - any(arr: T[], iterator: AsyncBooleanIterator, callback?: AsyncResultCallback): any; - every(arr: T[], iterator: AsyncBooleanIterator, callback?: AsyncResultCallback): any; - everyLimit(arr: T[], limit: number, iterator: AsyncBooleanIterator, callback?: AsyncResultCallback): any; - all(arr: T[], iterator: AsyncBooleanIterator, callback?: AsyncResultCallback): any; - concat(arr: T[], iterator: AsyncResultIterator, callback?: AsyncResultArrayCallback): any; - concatSeries(arr: T[], iterator: AsyncResultIterator, callback?: AsyncResultArrayCallback): any; + anyLimit: typeof async.someLimit; + every(arr: T[], iterator: AsyncBooleanIterator, callback?: AsyncBooleanResultCallback): void; + every(arr: Dictionary, iterator: AsyncBooleanIterator, callback?: AsyncBooleanResultCallback): void; + everySeries: typeof async.every; + everyLimit(arr: T[], limit: number, iterator: AsyncBooleanIterator, callback?: AsyncBooleanResultCallback): void; + everyLimit(arr: Dictionary, limit: number, iterator: AsyncBooleanIterator, callback?: AsyncBooleanResultCallback): void; + all: typeof async.every; + allSeries: typeof async.every; + allLimit: typeof async.everyLimit; + + concat(arr: T[], iterator: AsyncResultIterator, callback?: AsyncResultArrayCallback): void; + concat(arr: Dictionary, iterator: AsyncResultIterator, callback?: AsyncResultArrayCallback): void; + concatSeries: typeof async.concat; // Control Flow series(tasks: AsyncFunction[], callback?: AsyncResultArrayCallback): void; @@ -143,14 +167,14 @@ interface Async { parallel(tasks: Dictionary>, callback?: AsyncResultObjectCallback): void; parallelLimit(tasks: Array>, limit: number, callback?: AsyncResultArrayCallback): void; parallelLimit(tasks: Dictionary>, limit: number, callback?: AsyncResultObjectCallback): void; - whilst(test: () => boolean, fn: AsyncVoidFunction, callback: (err: E) => void): void; - doWhilst(fn: AsyncVoidFunction, test: () => boolean, callback: (err: E) => void): void; - until(test: () => boolean, fn: AsyncVoidFunction, callback: (err: E) => void): void; - doUntil(fn: AsyncVoidFunction, test: () => boolean, callback: (err: E) => void): void; - during(test: (testCallback : (error: Error, truth: boolean) => void) => void, fn: AsyncVoidFunction, callback: (err: E) => void): void; - doDuring(fn: AsyncVoidFunction, test: (testCallback: (error: Error, truth: boolean) => void) => void, callback: (err: E) => void): void; - forever(next: (errCallback : (err: Error) => void) => void, errBack: (err: Error) => void) : void; - waterfall(tasks: Function[], callback?: (err: Error, results?: any) => void): void; + whilst(test: () => boolean, fn: AsyncVoidFunction, callback: ErrorCallback): void; + doWhilst(fn: AsyncVoidFunction, test: () => boolean, callback: ErrorCallback): void; + until(test: () => boolean, fn: AsyncVoidFunction, callback: ErrorCallback): void; + doUntil(fn: AsyncVoidFunction, test: () => boolean, callback: ErrorCallback): void; + during(test: (testCallback : AsyncBooleanResultCallback) => void, fn: AsyncVoidFunction, callback: ErrorCallback): void; + doDuring(fn: AsyncVoidFunction, test: (testCallback: AsyncBooleanResultCallback) => void, callback: ErrorCallback): void; + forever(next: (next : ErrorCallback) => void, errBack: ErrorCallback) : void; + waterfall(tasks: Function[], callback?: AsyncResultCallback): void; compose(...fns: Function[]): Function; seq(...fns: Function[]): Function; applyEach(fns: Function[], argsAndCallback: any[]): void; // applyEach(fns, args..., callback). TS does not support ... for a middle argument. Callback is optional. @@ -158,19 +182,15 @@ interface Async { queue(worker: AsyncWorker, concurrency?: number): AsyncQueue; priorityQueue(worker: AsyncWorker, concurrency: number): AsyncPriorityQueue; cargo(worker : (tasks: any[], callback : ErrorCallback) => void, payload? : number) : AsyncCargo; - auto(tasks: any, concurrency?: number, callback?: (error: Error, results: any) => void): void; - autoInject(tasks: any, callback?: (error: Error, results: any) => void): void; - retry(opts: number, task: (callback : AsyncResultCallback, results: any) => void, callback: (error: Error, results: any) => void): void; - retry(opts: { times: number, interval: number|((retryCount: number) => number) }, task: (callback: AsyncResultCallback, results : any) => void, callback: (error: Error, results: any) => void): void; + auto(tasks: any, concurrency?: number, callback?: AsyncResultCallback): void; + autoInject(tasks: any, callback?: AsyncResultCallback): void; + retry(opts: number, task: (callback : AsyncResultCallback, results: any) => void, callback: AsyncResultCallback): void; + retry(opts: { times: number, interval: number|((retryCount: number) => number) }, task: (callback: AsyncResultCallback, results : any) => void, callback: AsyncResultCallback): void; retryable(opts: number | {times: number, interval: number}, task: AsyncFunction): AsyncFunction; - apply(fn: Function, ...arguments: any[]): AsyncFunction; // TODO: be more specific + apply(fn: Function, ...arguments: any[]): AsyncFunction; nextTick(callback: Function, ...args: any[]): void; setImmediate: typeof async.nextTick; - allLimit(arr: T[], limit: number, iteratee: AsyncBooleanIterator, cb?: AsyncResultCallback) : any; - everySeries(arr: T[], iteratee: AsyncBooleanIterator, cb?: AsyncResultCallback) : any - allSeries: typeof async.everySeries; - reflect(fn: AsyncFunction) : (callback: (err: void, result: {error?: Error, value?: T}) => void) => void; reflectAll(tasks: AsyncFunction[]): ((callback: (err: void, result: {error?: Error, value?: T}) => void) => void)[]; diff --git a/automapper-ts/automapper-ts-tests.ts b/automapper-ts/automapper-ts-tests.ts new file mode 100644 index 00000000000000..5e18f75789a707 --- /dev/null +++ b/automapper-ts/automapper-ts-tests.ts @@ -0,0 +1,1990 @@ +/// +/// + +var globalScope = this; + +declare module jasmine { + interface Matchers { + toEqualData(data: any): boolean; + fail(message: string): boolean; + } +} + +declare function expect(): jasmine.Matchers; + +module AutoMapperJs { + describe('AutoMapper', () => { + beforeEach(() => { + jasmine.addMatchers(ExtendJasmine.addCustomMatchers()); + + // clear mappings (please, don't try this at home!) + for (var key in (automapper)._mappings) { + if (!(automapper)._mappings.hasOwnProperty(key)) { + continue; + } + delete (automapper)._mappings[key]; + } + }); + + it('should validate mapping using strictMode set to \'true\' (with valid mappings)', () => { + // arrange + automapper.createMap(AssertConfigPropertiesProp, AssertConfigPropertiesProp); + + // act and assert + automapper.assertConfigurationIsValid(true); + }); + + it('should set strictMode to \'true\' when no value is provided and validate (with valid mappings)', () => { + // arrange + automapper.createMap(AssertConfigPropertiesProp, AssertConfigPropertiesProp); + + // act and assert + automapper.assertConfigurationIsValid(); + }); + + it('should validate mapping using strictMode set to \'false\'', () => { + // arrange + automapper.createMap(AssertConfigPropertiesProp, AssertConfigPropertiesProp); + automapper.createMap('AssertMappingConfigUntestableA', 'AssertMappingConfigUntestableB'); + + // act and assert + automapper.assertConfigurationIsValid(false); + }); + + it('should fail when validating mappings using strictMode set to \'true\' (with unvalidatable mappings)', () => { + // arrange + automapper.createMap(AssertConfigPropertiesProp, AssertConfigPropertiesProp); + automapper.createMap('AssertMappingConfigUntestableA', 'AssertMappingConfigUntestableB'); + + // act + try { + automapper.assertConfigurationIsValid(true); + } catch (e) { + // assert + var errorMessage: string = e.message; + var dekeyedErrorMessage = + errorMessage.substr(0, errorMessage.indexOf('\'') + 1) + + errorMessage.substr(errorMessage.lastIndexOf('\'')); + + expect(dekeyedErrorMessage).toEqual(`Mapping '' cannot be validated, since mapping.sourceType or mapping.destinationType are unspecified.`); + return; + } + + // assert + expect(null).fail('Expected error was not raised.'); + }); + + it('should fail when auto mapping a property which does not exist on destination', () => { + // arrange + var srcType = AssertConfigPropertiesProp; + var dstType = AssertConfigPropertiesProp2; + + var srcName = AutoMapperHelper.getClassName(srcType); + var dstName = AutoMapperHelper.getClassName(dstType); + + automapper.createMap(srcType, dstType); + + try { + // act + automapper.assertConfigurationIsValid(true); + } catch (e) { + // assert + expect(e.message).toEqual(`Mapping '${srcName}=>${dstName}' is invalid: Source member 'prop' is configured to be mapped, ` + + `but does not exist on destination type (source: '${srcName}', destination: '${dstName}').`); + return; + } + + // assert + expect(null).fail('Expected error was not raised.'); + }); + + it('should succeed when mapping objects with ignored properties not existing on the other side', () => { + // arrange + var srcType = AssertConfigPropertiesProp; + var dstType = AssertConfigPropertiesProp2; + + var srcName = AutoMapperHelper.getClassName(srcType); + var dstName = AutoMapperHelper.getClassName(dstType); + + automapper + .createMap(srcType, dstType) + .forSourceMember('prop', (opts: ISourceMemberConfigurationOptions) => { opts.ignore(); }) + .forMember('prop2', (opts: IMemberConfigurationOptions) => { opts.ignore(); }); + + // act and assert + automapper.assertConfigurationIsValid(true); + }); + + it('should fail when auto mapping a property which does not exist on source', () => { + // arrange + var srcType = AssertConfigPropertiesProp; + var dstType = AssertConfigPropertiesPropProp2; + + var srcName = AutoMapperHelper.getClassName(srcType); + var dstName = AutoMapperHelper.getClassName(dstType); + + automapper.createMap(srcType, dstType); + + try { + // act + automapper.assertConfigurationIsValid(true); + } catch (e) { + // assert + expect(e.message).toEqual(`Mapping '${srcName}=>${dstName}' is invalid: Destination member 'prop2' does not exist on source type (source: '${srcName}', destination: '${dstName}').`); + return; + } + + // assert + expect(null).fail('Expected error was not raised.'); + }); + + it('should fail when providing configuration for a property which does not exist on destination', () => { + // arrange + var srcType = AssertConfigPropertiesProp; + var dstType = AssertConfigPropertiesPropProp2; + + var srcName = AutoMapperHelper.getClassName(srcType); + var dstName = AutoMapperHelper.getClassName(dstType); + + automapper + .createMap(srcType, dstType) + .forMember('prop3', (opts: IMemberConfigurationOptions) => { opts.ignore(); }); + + try { + // act + automapper.assertConfigurationIsValid(true); + } catch (e) { + // assert + expect(e.message).toEqual(`Mapping '${srcName}=>${dstName}' is invalid: Destination member 'prop3' is configured, but does not exist on destination type (source: '${srcName}', destination: '${dstName}').`); + return; + } + + // assert + expect(null).fail('Expected error was not raised.'); + }); + + it('should fail when providing configuration for a property which does not exist on source', () => { + // arrange + var srcType = AssertConfigPropertiesProp; + var dstType = AssertConfigPropertiesPropProp2; + + var srcName = AutoMapperHelper.getClassName(srcType); + var dstName = AutoMapperHelper.getClassName(dstType); + + automapper + .createMap(srcType, dstType) + .forSourceMember('prop2', (opts: ISourceMemberConfigurationOptions) => { opts.ignore(); }); + + try { + // act + automapper.assertConfigurationIsValid(true); + } catch (e) { + // assert + expect(e.message).toEqual(`Mapping '${srcName}=>${dstName}' is invalid: Source member 'prop2' is configured, but does not exist on source type (source: '${srcName}', destination: '${dstName}').`); + return; + } + + // assert + expect(null).fail('Expected error was not raised.'); + }); + }); + + describe('AutoMapper (asynchronous mapping)', () => { + beforeEach(() => { + jasmine.addMatchers(ExtendJasmine.addCustomMatchers()); + }); + + it('should be able to map asynchronous using forMember', (done) => { + // arrange + var objFrom = { prop: 'prop' }; + + var fromKey = 'async-forMember-'; + var toKey = 'valid-1'; + + // act + automapper + .createMap(fromKey, toKey) + .forMember('prop', (opts: IMemberConfigurationOptions, cb: IMemberCallback) => { + var func = (o: IMemberConfigurationOptions, c: IMemberCallback) => { + c(o.intermediatePropertyValue + ' (async)'); + }; + + // do something asynchronous + setTimeout((): void => { + func(opts, cb); + }, 10); + }) + .forMember('prop', (opts: IMemberConfigurationOptions) => { + return opts.intermediatePropertyValue + ' (sync)'; + }); + + automapper.mapAsync(fromKey, toKey, objFrom, (result: any) => { + // assert + expect(result.prop).toEqual(objFrom.prop + ' (async)' + ' (sync)'); + done(); + }); + }); + + it('should be able to map asynchronous using forMember in combination with a constant value', (done: () => void) => { + // arrange + var objFrom = { prop: 'prop' }; + + var fromKey = 'async-forMember-'; + var toKey = 'valid-2'; + + // act + automapper + .createMap(fromKey, toKey) + .forMember('prop', (opts: IMemberConfigurationOptions, cb: IMemberCallback) => { + var func = (o: IMemberConfigurationOptions, c: IMemberCallback) => { + c(o.intermediatePropertyValue + ' (async)'); + }; + + // do something asynchronous + setTimeout((): void => { + func(opts, cb); + }, 10); + }) + .forMember('prop', 'Async With Constant Value'); + + automapper.mapAsync(fromKey, toKey, objFrom, (result: any) => { + // assert + expect(result.prop).toEqual('Async With Constant Value'); + done(); + }); + }); + + it('should be able to map asynchronous using an asynchronous forMember in combination with a synchronous forMember mapping', (done: () => void) => { + // arrange + var objFrom = { prop1: 'prop1', prop2: 'prop2' }; + + var fromKey = 'async-forMember-'; + var toKey = 'valid-3'; + + // act + automapper + .createMap(fromKey, toKey) + .forMember('prop1', (opts: IMemberConfigurationOptions, cb: IMemberCallback) => { + var func = (o: IMemberConfigurationOptions, c: IMemberCallback) => { + c(o.intermediatePropertyValue + ' (async)'); + }; + + // do something asynchronous + setTimeout((): void => { + func(opts, cb); + }, 10); + }) + .forMember('prop2', (opts: IMemberConfigurationOptions): any => opts.intermediatePropertyValue); + + automapper.mapAsync(fromKey, toKey, objFrom, (result: any) => { + // assert + expect(result.prop1).toEqual(objFrom.prop1 + ' (async)'); + expect(result.prop2).toEqual(objFrom.prop2); + done(); + }); + }); + + it('should fail when mapping an asynchronous mapping using synchronous map function', () => { + // arrange + var objFrom = { prop: 'prop' }; + + var fromKey = 'async-forMember-'; + var toKey = 'invalid-1'; + + automapper + .createMap(fromKey, toKey) + .forMember('prop', (opts: IMemberConfigurationOptions, cb: IMemberCallback) => { + var func = (o: IMemberConfigurationOptions, c: IMemberCallback) => { + c(o.intermediatePropertyValue + ' (async)'); + } + + // do something asynchronous + setTimeout((): void => { + func(opts, cb); + }, 10); + }) + .forMember('prop', (opts: IMemberConfigurationOptions) => { + return opts.intermediatePropertyValue + ' (sync)'; + }); + + // act + try { + var objB = automapper.map(fromKey, toKey, objFrom); + } catch (e) { + // assert + expect(e.message).toEqual('Impossible to use asynchronous mapping using automapper.map(); use automapper.mapAsync() instead.'); + return; + } + + // assert + expect(null).fail('Expected error was not raised.'); + }); + + it('should be able to map asynchronous using forSourceMember', (done: () => void) => { + // arrange + var objFrom = { prop: 'prop' }; + + var fromKey = 'async-forSourceMember-'; + var toKey = 'valid-1'; + + automapper + .createMap(fromKey, toKey) + .forSourceMember('prop', (opts: ISourceMemberConfigurationOptions, cb: IMemberCallback) => { + var func = (o: ISourceMemberConfigurationOptions, c: IMemberCallback) => { + c('AsyncValue'); + }; + + // do something asynchronous + setTimeout((): void => { + func(opts, cb); + }, 10); + }); + + // act + automapper.mapAsync(fromKey, toKey, objFrom, (result: any) => { + // assert + expect(result.prop).toEqual('AsyncValue'); + done(); + }); + }); + + it('should be able to use convertUsing to map an object with a custom asynchronous type resolver function', (done: () => void) => { + var objA = { propA: 'propA' }; + + var fromKey = '{D1534A0F-6120-475E-B7E2-BF2489C58571}'; + var toKey = '{1896FF99-1A28-4FE6-800B-072D5616B02D}'; + + automapper + .createMap(fromKey, toKey) + .convertUsing((opts: IResolutionContext, cb: IMapCallback): void => { + var func = (o: IResolutionContext, c: IMapCallback) => { + var res = { propA: o.sourceValue.propA + ' (custom async mapped with resolution context)' }; + c(res); + }; + + // do something asynchronous + setTimeout((): void => { + func(opts, cb); + }, 10); + }); + + // act + automapper.mapAsync(fromKey, toKey, objA, (result: any) => { + // assert + expect(result.propA).toEqual(objA.propA + ' (custom async mapped with resolution context)'); + done(); + }); + }); + + it('should asynchronously map an array', (done: () => void) => { + // arrange + var arrA = [{ prop1: 'From A', prop2: 'From A too' }]; + + var fromKey = '{60D9DGH6-DSEC-48GF-9BAC-0805FCAF91B7}'; + var toKey = '{AC6D5B97-9AE3-BERT-ZB60-AZFEDZXE541A}'; + + automapper.createMap(fromKey, toKey) + .forMember('prop1', (opts: IMemberConfigurationOptions, cb: IMemberCallback) => { + var func = (o: IMemberConfigurationOptions, c: IMemberCallback) => { + c(o.intermediatePropertyValue); + }; + + // do something asynchronous + setTimeout((): void => { + func(opts, cb); + }, 10); + }); + // act + var arrB = automapper.mapAsync(fromKey, toKey, arrA, (result: any) => { + // assert + expect(result).toEqualData(arrA); + done(); + }); + }); + }); + + describe('AutoMapper', () => { + beforeEach(() => { + jasmine.addMatchers(ExtendJasmine.addCustomMatchers()); + }); + + it('should have a global automapper object', () => { + expect(automapper).not.toBeUndefined(); + expect(automapper).not.toBeNull(); + + expect(automapper.createMap).not.toBeUndefined(); + expect(automapper.createMap).not.toBeNull(); + expect(typeof automapper.createMap === 'function').toBeTruthy(); + + expect(automapper.map).not.toBeUndefined(); + expect(automapper.map).not.toBeNull(); + expect(typeof automapper.map === 'function').toBeTruthy(); + }); + + it('should return the Singleton instance when instantiating the Singleton directly', () => { + // arrange + var caught = false; + + // act + var mapper = new AutoMapper(); + expect(automapper).toBe(mapper); + }); + + it('should use created mapping profile', () => { + // arrange + var fromKey = '{5700E351-8D88-4327-A216-3CC94A308EDF}'; + var toKey = '{BB33A261-3CA9-48FC-85E6-2C269F73728D}'; + + automapper.createMap(fromKey, toKey); + + // act + automapper.map(fromKey, toKey, {}); + + // assert + }); + + it('should fail when using a non-existing mapping profile', () => { + // arrange + var caught = false; + + var fromKey = '{5AEFD48C-4472-41E7-BA7E-0977A864E116}'; + var toKey = '{568DCA5E-477E-4739-86B2-38BB237B8EF8}'; + + // act + try { + automapper.map(fromKey, toKey, {}); + } catch (e) { + caught = true; + + // assert + expect(e.message).toEqual('Could not find map object with a source of ' + fromKey + ' and a destination of ' + toKey); + } + + if (!caught) { + // assert + expect().fail('Using a non-existing mapping profile should result in an error.'); + } + }); + + it('should be able to use forAllMemberMappings', () => { + // arrange + var fromKey = '{5700E351-8D88-4327-A216-3CCBHJ808EDF}'; + var toKey = '{BB33A261-3CA9-48FC-85E6-2C269FDFT28D}'; + + var source = { prop1: 'prop1', prop2: 'prop2' }; + var suffix = ' [forAllMembers]'; + + automapper.createMap(fromKey, toKey) + .forMember('prop1', (opts: IMemberConfigurationOptions): any => opts.intermediatePropertyValue) + .forMember('prop2', (opts: IMemberConfigurationOptions): any => opts.intermediatePropertyValue) + .forAllMembers((destinationObject: any, + destinationPropertyName: string, + value: any): void => { + destinationObject[destinationPropertyName] = value + suffix; + }); + + // act + var destination = automapper.map(fromKey, toKey, source); + + // assert + expect(destination.prop1).toEqual(source.prop1 + suffix); + expect(destination.prop2).toEqual(source.prop2 + suffix); + }); + + it('should be able to use forAllMemberMappings when automapping', () => { + // arrange + var fromKey = '{5700E351-8D88-4327-A216-3CCBHJ808EDF}'; + var toKey = '{BB33A261-3CA9-48FC-85E6-2C269FDFT28D}'; + + var source = { prop1: 'prop1', prop2: 'prop2' }; + var suffix = ' [forAllMembers]'; + + automapper.createMap(fromKey, toKey) + .forAllMembers((destinationObject: any, + destinationPropertyName: string, + value: any): void => { + destinationObject[destinationPropertyName] = value + suffix; + }); + + // act + var destination = automapper.map(fromKey, toKey, source); + + // assert + expect(destination.prop1).toEqual(source.prop1 + suffix); + expect(destination.prop2).toEqual(source.prop2 + suffix); + }); + + it('should accept multiple forMember calls for the same destination property and overwrite with the last one specified', () => { + //arrange + var objA = { prop1: 'From A', prop2: 'From A too' }; + + var fromKey = '{7AC4134B-ECC1-464B-B144-5B9D8F5B568E}'; + var toKey = '{2BDE907C-1CE6-4CC5-A601-9A94CC665837}'; + + automapper + .createMap(fromKey, toKey) + .forMember('prop1', (opts: IMemberConfigurationOptions) => { opts.mapFrom('prop2'); }) + .forMember('prop1', (opts: IMemberConfigurationOptions) => { opts.ignore(); }); + + // act + var objB = automapper.map(fromKey, toKey, objA); + + // assert + expect(objB).toEqualData({ prop2: objA.prop2 }); + }); + + it('should be able to ignore a source property using the forSourceMember function', () => { + // arrange + var objA = { prop1: 'From A', prop2: 'From A too' }; + + var fromKey = '{AD88481E-597B-4C1B-967B-3D700B8BAB0F}'; + var toKey = '{2A6714C4-784E-47D3-BBF4-6205834EC8D5}'; + + automapper + .createMap(fromKey, toKey) + .forSourceMember('prop1', (opts: ISourceMemberConfigurationOptions) => { opts.ignore(); }); + + // act + var objB = automapper.map(fromKey, toKey, objA); + + // assert + expect(objB).toEqualData({ prop2: 'From A too' }); + }); + + it('should be able to custom map a source property using the forSourceMember function', () => { + // arrange + var objA = { prop1: 'From A', prop2: 'From A too' }; + + var fromKey = '{AD88481E-597B-4C1B-967B-3D700B8BAB0F}'; + var toKey = '{2A6714C4-784E-47D3-BBF4-6205834EC8D5}'; + + automapper + .createMap(fromKey, toKey) + .forSourceMember('prop1', (opts: ISourceMemberConfigurationOptions) => { return 'Yeah!'; }); + + // act + var objB = automapper.map(fromKey, toKey, objA); + + // assert + expect(objB).toEqualData({ prop1: 'Yeah!', prop2: 'From A too' }); + }); + + it('should be able to ignore a source property already specified (by forMember) using the forSourceMember function', () => { + // arrange + var objA = { prop1: 'From A', prop2: 'From A too' }; + + var fromKey = '{AD88481E-597B-4C1B-967B-3D701B8CAB0A}'; + var toKey = '{2A6714C4-784E-47D3-BBF4-620583DEC86A}'; + + automapper + .createMap(fromKey, toKey) + .forMember('prop1', 12) + .forSourceMember('prop1', (opts: ISourceMemberConfigurationOptions) => { opts.ignore(); }); + + // act + var objB = automapper.map(fromKey, toKey, objA); + + // assert + expect(objB).toEqualData({ prop2: 'From A too' }); + }); + + it('should fail when forSourceMember is used with anything else than a function', () => { + // arrange + var caught = false; + + var fromKey = '{5EE20DF9-84B3-4A6A-8C5D-37AEDC44BE87}'; + var toKey = '{986C959D-2E2E-41FA-9857-8EF519467AEB}'; + + try { + // act + automapper + .createMap(fromKey, toKey) + .forSourceMember('prop1', 12); + } catch (e) { + // assert + caught = true; + expect(e.message).toEqual('Configuration of forSourceMember has to be a function with one (sync) or two (async) options parameters.'); + } + + if (!caught) { + // assert + expect().fail('Using anything else than a function with forSourceMember should result in an error.'); + } + }); + + it('should be able to use forMember to map a source property to a destination property with a different name', () => { + //arrange + var objA = { prop1: 'From A', prop2: 'From A too' }; + + var fromKey = '{7AC4134B-ECC1-464B-B144-5B9D8F5B568E}'; + var toKey = '{2BDE907C-1CE6-4CC5-A601-9A94CC665837}'; + + automapper + .createMap(fromKey, toKey) + .forMember('prop', (opts: IMemberConfigurationOptions) => { opts.mapFrom('prop2'); }); + + // act + var objB = automapper.map(fromKey, toKey, objA); + + // assert + expect(objB).toEqualData({ prop1: objA.prop1, prop: objA.prop2 }); + }); + + it('should use forAllMembers function for each mapped destination property when specified', () => { + // arrange + var objA = { prop1: 'From A', prop2: 'From A too' }; + + var fromKey = '{C4056539-FA86-4398-A10B-C41D3A791F26}'; + var toKey = '{01C64E8D-CDB5-4307-9011-0C7F1E70D115}'; + + var forAllMembersSpy = jasmine.createSpy('forAllMembersSpy').and.callFake((destinationObject: any, destinationProperty: string, value: any) => { + destinationObject[destinationProperty] = value; + }); + + automapper + .createMap(fromKey, toKey) + .forAllMembers(forAllMembersSpy); + + // act + var objB = automapper.map(fromKey, toKey, objA); + + // assert + expect(forAllMembersSpy).toHaveBeenCalled(); + expect(forAllMembersSpy.calls.count()).toBe(Object.keys(objB).length); + }); + + it('should be able to use forMember with a constant value', () => { + // arrange + var objA = { prop: 1 }; + + var fromKey = '{54E67626-B877-4824-82E6-01E9F411B78F}'; + var toKey = '{2D7FDB88-97E9-45EF-A111-C9CC9C188227}'; + + var constantResult = 2; + + automapper + .createMap(fromKey, toKey) + .forMember('prop', constantResult); + + // act + var objB = automapper.map(fromKey, toKey, objA); + + // assert + expect(objB.prop).toBe(constantResult); + }); + + it('should be able to use forMember with a function returning a constant value', () => { + // arrange + var objA = { prop: 1 }; + + var fromKey = '{74C12B56-1DD1-4EA0-A640-D1F814971124}'; + var toKey = '{BBC617B8-26C8-42A0-A204-45CC77073355}'; + + var constantResult = 3; + + automapper + .createMap(fromKey, toKey) + .forMember('prop', () => { return constantResult; }); + + // act + var objB = automapper.map(fromKey, toKey, objA); + + // assert + expect(objB.prop).toBe(constantResult); + }); + + it('should be able to use forMember with a function using the source object', () => { + // arrange + var objA = { prop: { subProp: { value: 1 } } }; + + var fromKey = '{54E67626-B877-4824-82E6-01E9F411B78F}'; + var toKey = '{2D7FDB88-97E9-45EF-A111-C9CC9C188227}'; + + automapper + .createMap(fromKey, toKey) + .forMember('prop', (opts: IMemberConfigurationOptions) => { return opts.sourceObject[opts.sourcePropertyName].subProp.value * 2; }); + + // act + var objB = automapper.map(fromKey, toKey, objA); + + // assert + expect(objB.prop).toBe(objA.prop.subProp.value * 2); + }); + + it('should be able to use forMember to ignore a property', () => { + // arrange + var objA = { prop: 1 }; + + var fromKey = '{76D26B33-888A-4DF7-ABDA-E5B99E944272}'; + var toKey = '{18192391-85FF-4729-9A08-5954FCFE3954}'; + + automapper + .createMap(fromKey, toKey) + .forMember('prop', (opts: IMemberConfigurationOptions) => { opts.ignore(); }); + + // act + var objB = automapper.map(fromKey, toKey, objA); + + // assert + expect(objB.hasOwnProperty('prop')).not.toBeTruthy(); + }); + + it('should be able to use forMember to map a source property to a destination property with a different name', () => { + // arrange + var objA = { propDiff: 1 }; + + var fromKey = '{A317A36A-AD92-4346-A015-AE06FC862DB4}'; + var toKey = '{03B05E43-3028-44FD-909F-652E2DA5E607}'; + + automapper + .createMap(fromKey, toKey) + .forMember('prop', (opts: IMemberConfigurationOptions) => { opts.mapFrom('propDiff'); }); + + // act + var objB = automapper.map(fromKey, toKey, objA); + + // assert + expect(objB.prop).toEqual(objA.propDiff); + }); + + it('should be able to use stack forMember calls to map a source property to a destination property using multiple mapping steps', () => { + // arrange + var birthdayString = '2000-01-01T00:00:00.000Z'; + var objA = { birthdayString: birthdayString }; + + var fromKey = '{564F1F57-FD4F-413C-A9D3-4B1C1333A20B}'; + var toKey = '{F9F45923-2D13-4EF1-9685-4883AD1D2F98}'; + + automapper + .createMap(fromKey, toKey) + .forMember('birthday', (opts: IMemberConfigurationOptions) => { opts.mapFrom('birthdayString'); }) + .forMember('birthday', (opts: IMemberConfigurationOptions) => { return new Date(opts.intermediatePropertyValue); }); + + // act + var objB = automapper.map(fromKey, toKey, objA); + + // assert + expect(objB.birthday instanceof Date).toBeTruthy(); + expect(objB.birthday.toISOString()).toEqual('2000-01-01T00:00:00.000Z'); + }); + + it('should be able to use stack forMember calls to map a source property to a destination property using multiple mapping steps in any order', () => { + // arrange + var birthdayString = '2000-01-01T00:00:00.000Z'; + var objA = { birthdayString: birthdayString }; + + var fromKey = '{1609A9B5-6083-448B-8FD6-51DAD106B63D}'; + var toKey = '{47AF7D2D-A848-4C5B-904F-39402E2DCDD5}'; + + automapper + .createMap(fromKey, toKey) + .forMember('birthday', (opts: IMemberConfigurationOptions) => { return new Date(opts.intermediatePropertyValue); }) + .forMember('birthday', (opts: IMemberConfigurationOptions) => { opts.mapFrom('birthdayString'); }); + + // act + var objB = automapper.map(fromKey, toKey, objA); + + // assert + expect(objB.birthday instanceof Date).toBeTruthy(); + expect(objB.birthday.toISOString()).toEqual('2000-01-01T00:00:00.000Z'); + }); + + it('should not map properties that are not an object\'s own properties', () => { + var objA = new ClassA(); + objA.propA = 'propA'; + + var fromKey = '{A317A36A-AD92-4346-A015-AE06FC862DB4}'; + var toKey = '{03B05E43-3028-44FD-909F-652E2DA5E607}'; + + automapper + .createMap(fromKey, toKey); + + // act + var objB = automapper.map(fromKey, toKey, objA); + + // assert + expect(objB.propA).toEqual(objA.propA); + }); + + it('should be able to use convertUsing to map an object with a custom type resolver function', () => { + var objA = { propA: 'propA' }; + + var fromKey = '{D1534A0F-6120-475E-B7E2-BF2489C58571}'; + var toKey = '{1896FF99-1A28-4FE6-800B-072D5616B02D}'; + + automapper + .createMap(fromKey, toKey) + .convertUsing(function(resolutionContext: IResolutionContext): any { + return { propA: resolutionContext.sourceValue.propA + ' (custom mapped with resolution context)' }; + }); + + // act + var objB = automapper.map(fromKey, toKey, objA); + + // assert + expect(objB.propA).toEqual(objA.propA + ' (custom mapped with resolution context)'); + }); + + it('should be able to use convertUsing to map an object with a custom type resolver class', () => { + // arrange + var objA = { propA: 'propA' }; + + var fromKey = '{6E7F5757-1E55-4B55-BB86-44FF5B33DE2F}'; + var toKey = '{8521AE41-C3AF-4FCD-B7C7-A915C037D69E}'; + + automapper + .createMap(fromKey, toKey) + .convertUsing(CustomTypeConverterDefinition); + + // act + var objB = automapper.map(fromKey, toKey, objA); + + // assert + expect(objB.propA).toEqual(objA.propA + ' (convertUsing with a class definition)'); + }); + + it('should be able to use convertUsing to map an object with a custom type resolver instance', () => { + // arrange + // NOTE BL The CustomTypeConverter class definition is defined at the bottom, since TypeScript + // does not allow classes to be defined inline. + + var objA = { propA: 'propA' }; + + var fromKey = '{BDF3758C-B38E-4343-95B6-AE0F80C8B9C4}'; + var toKey = '{13DD7AE1-4177-4A80-933B-B60A55859E50}'; + + automapper + .createMap(fromKey, toKey) + .convertUsing(new CustomTypeConverterInstance()); + + // act + var objB = automapper.map(fromKey, toKey, objA); + + // assert + expect(objB.propA).toEqual(objA.propA + ' (convertUsing with a class instance)'); + }); + + it('should fail when directly using the type converter base class', () => { + // arrange + var caught = false; + var objA = { propA: 'propA' }; + + var fromKey = 'should fail when directly using '; + var toKey = 'the type converter base class'; + + automapper + .createMap(fromKey, toKey) + .convertUsing(TypeConverter); + + try { + // act + var objB = automapper.map(fromKey, toKey, objA); + } catch (e) { + // assert + caught = true; + expect(e.message).toEqual('The TypeConverter.convert method is abstract. Use a TypeConverter extension class instead.'); + } + + if (!caught) { + // assert + expect().fail('Using the type converter base class directly should fail.'); + } + }); + + it('should fail when convertUsing is used with a function not having exactly one (resolutionContext) parameter.', () => { + // arrange + var caught = false; + + var fromKey = '{1EF9AC11-BAA1-48DB-9C96-9DFC40E33BCA}'; + var toKey = '{C4DA81D3-9072-4140-BFA7-431C35C01F54}'; + + try { + // act + automapper + .createMap(fromKey, toKey) + .convertUsing(() => { + return {}; + }); + + //var objB = automapper.map(fromKey, toKey, objA); + } catch (e) { + // assert + caught = true; + expect(e.message).toEqual('The value provided for typeConverterClassOrFunction is invalid. ' + + 'Error: The function provided does not provide exactly one (resolutionContext) parameter.'); + } + + if (!caught) { + // assert + expect().fail('Using anything else than a function with forSourceMember should result in an error.'); + } + }); + + it('should be able to use convertToType to map a source object to a destination object which is an instance of a given class', () => { + //arrange + var objA = { ApiProperty: 'From A' }; + + + var fromKey = '{7AC4134B-ECC1-464B-B144-5C9D8F5B5A7E}'; + var toKey = '{2BDE907C-1CE6-4CC5-A601-9A94CA6C4737}'; + + automapper + .createMap(fromKey, toKey) + .forMember('property', (opts: IMemberConfigurationOptions) => { opts.mapFrom('ApiProperty'); }) + .convertToType(DemoToBusinessType); + + // act + var objB = automapper.map(fromKey, toKey, objA); + + // assert + expect(objB instanceof DemoToBusinessType).toBeTruthy(); + expect(objB.property).toEqual(objA.ApiProperty); + }); + + it('should be able to use a condition to map or ignore a property', () => { + // arrange + var objA = { prop: 1, prop2: 2 }; + + var fromKey = '{76D23B33-888A-4DF7-BEBE-E5B99E944272}'; + var toKey = '{18192191-85FE-4729-A980-5954FCFE3954}'; + + automapper + .createMap(fromKey, toKey) + .forMember('prop', (opts: IMemberConfigurationOptions) => { opts.condition((sourceObject: any) => sourceObject.prop === 0); }) + .forMember('prop2', (opts: IMemberConfigurationOptions) => { opts.condition((sourceObject: any) => sourceObject.prop2 === 2); }); + + // act + var objB = automapper.map(fromKey, toKey, objA); + + // assert + expect(objB.hasOwnProperty('prop')).not.toBeTruthy(); + expect(objB.hasOwnProperty('prop2')).toBeTruthy(); + }); + + it('should be able to ignore all unmapped members using the ignoreAllNonExisting function', () => { + // arrange + var objA = { + propA: 'Prop A', + propB: 'Prop B', + propC: 'Prop C', + propD: 'Prop D' + }; + + var fromKey = '{AD88481E-597B-4C1C-9A7B-3D70DB8BCB0F}'; + var toKey = '{2A6614C4-784E-47D3-BBF4-6205834EA8D1}'; + + automapper + .createMap(fromKey, toKey) + .forMember('propA', (opts: IMemberConfigurationOptions) => opts.mapFrom('propA')) + .ignoreAllNonExisting(); + + // act + var objB = automapper.map(fromKey, toKey, objA); + + // assert + expect(objB).toEqualData({ propA: 'Prop A' }); + }); + + it('should be able to create a map and use it using class types', () => { + // arrange + var objA = new ClassA(); + objA.propA = 'Value'; + + // act + automapper.createMap(ClassA, ClassB); + var objB = automapper.map(ClassA, ClassB, objA); + + // assert + expect(objB instanceof ClassB).toBeTruthy(); + expect(objB).toEqualData({ propA: 'Value' }); + }); + + it('should throw an error when creating a map using class types and specifying a conflicting destination type', () => { + // arrange + var caught = false; + + // act + try { + automapper + .createMap(ClassA, ClassB) + .convertToType(ClassC); + } catch (e) { + caught = true; + // assert + expect(e.message).toEqual('Destination type class can only be set once.'); + } + + if (!caught) { + // assert + expect(null).fail('AutoMapper should throw an error when creating a map using class types and specifying a conflicting destination type.'); + } + }); + + it('should be able to use forMember to map a nested source property to a destination property', () => { + //arrange + var objA = { prop1: { propProp1: 'From A' }, prop2: 'From A too' }; + + var fromKey = '{7AC4134B-ECC1-464B-B144-5B9D8F5B568E}'; + var toKey = '{2BDE907C-1CE6-4CC5-A601-9A94CC665837}'; + + automapper + .createMap(fromKey, toKey) + .forMember('propFromNestedSource', (opts: IMemberConfigurationOptions) => { opts.mapFrom('prop1.propProp1'); }); + + // act + var objB = automapper.map(fromKey, toKey, objA); + + // assert + expect(objB).toEqualData({ prop2: objA.prop2, propFromNestedSource: objA.prop1.propProp1 }); + }); + + it('should be able to stack forMember calls when mapping a nested source property to a destination property', () => { + //arrange + var objA = { prop1: { propProp1: 'From A' }, prop2: 'From A too' }; + var addition = ' - sure works!'; + + var fromKey = '{7AC4134B-ECC1-464B-B144-5B99CF5B558E}'; + var toKey = '{2BDE907C-1CE6-4CC5-56A1-9A94CC6658C7}'; + + automapper + .createMap(fromKey, toKey) + .forMember('propFromNestedSource', (opts: IMemberConfigurationOptions) => { opts.mapFrom('prop1.propProp1'); }) + .forMember('propFromNestedSource', (opts: IMemberConfigurationOptions) => { return opts.intermediatePropertyValue + addition; }); + + // act + var objB = automapper.map(fromKey, toKey, objA); + + // assert + expect(objB).toEqualData({ prop2: objA.prop2, propFromNestedSource: objA.prop1.propProp1 + addition }); + }); + + it('should be able to stack forMember calls when mapping a nested source property to a destination property in any order', () => { + //arrange + var objA = { prop1: { propProp1: 'From A' }, prop2: 'From A too' }; + var addition = ' - sure works!'; + + var fromKey = '{7AC4134B-ECD1-46EB-B14A-5B9D8F5B5F8E}'; + var toKey = '{BBD6907C-ACE6-4FC8-A60D-1A943C66D83F}'; + + automapper + .createMap(fromKey, toKey) + .forMember('propFromNestedSource', (opts: IMemberConfigurationOptions) => { return opts.intermediatePropertyValue + addition; }) + .forMember('propFromNestedSource', (opts: IMemberConfigurationOptions) => { opts.mapFrom('prop1.propProp1'); }); + + // act + var objB = automapper.map(fromKey, toKey, objA); + + // assert + expect(objB).toEqualData({ prop2: objA.prop2, propFromNestedSource: objA.prop1.propProp1 + addition }); + }); + + it('should be able to stack forMember mapFrom calls when mapping a nested source property to a destination property', () => { + //arrange + var objA = { prop1: { propProp1: 'From A', propProp2: { propProp2Prop: 'From A' } }, prop2: 'From A too' }; + var addition = ' - sure works!'; + + var fromKey = '{7AC4134B-ECD1-46EB-B14A-5B9D8F5B5F8E}'; + var toKey = '{BBD6907C-ACE6-4FC8-A60D-1A943C66D83F}'; + + automapper + .createMap(fromKey, toKey) + .forMember('propFromNestedSource', (opts: IMemberConfigurationOptions) => { return opts.intermediatePropertyValue + addition; }) + .forMember('propFromNestedSource', (opts: IMemberConfigurationOptions) => { opts.mapFrom('prop1.propProp2.propProp2Prop'); }) + .forMember('propFromNestedSource', (opts: IMemberConfigurationOptions) => { opts.mapFrom('prop1.propProp1'); }); + + // act + var objB = automapper.map(fromKey, toKey, objA); + + // assert + expect(objB).toEqualData({ prop2: objA.prop2, propFromNestedSource: objA.prop1.propProp1 + addition }); + }); + + it('should be able to use forMember to map to a nested destination', () => { + //arrange + var objA = { prop1: { propProp1: 'From A', propProp2: { propProp2Prop: 'From A' } }, prop2: 'From A too' }; + var addition = ' - sure works!'; + + var fromKey = '{7AC4134B-ECD1-46EB-B14A-5B9D8F5B5F8E}'; + var toKey = '{BBD6907C-ACE6-4FC8-A60D-1A943C66D83F}'; + + automapper + .createMap(fromKey, toKey) + .forMember('nested.property', (opts: IMemberConfigurationOptions) => { return opts.intermediatePropertyValue + addition; }) + .forMember('nested.property', (opts: IMemberConfigurationOptions) => { opts.mapFrom('prop1.propProp2.propProp2Prop'); }) + .forMember('nested.property', (opts: IMemberConfigurationOptions) => { opts.mapFrom('prop1.propProp1'); }); + + // act + var objB = automapper.map(fromKey, toKey, objA); + + // assert + expect(objB).toEqualData({ prop2: objA.prop2, nested: { property: objA.prop1.propProp1 + addition }}); + }); + + it('should be able to use mapFrom to switch properties and ignore a property as well', () => { + // arrange + var objA = { prop1: 'From A', prop2: 'From A too', prop3: 'Also from A (really)' }; + + var fromKey = 'should be able to use mapFrom to switch '; + var toKey = 'properties and ignore a property as well'; + + // act + automapper + .createMap(fromKey, toKey) + .forMember('prop1', (opts: IMemberConfigurationOptions) => { opts.mapFrom('prop2'); }) + .forMember('prop2', (opts: IMemberConfigurationOptions) => { opts.mapFrom('prop1'); }) + .forSourceMember('prop3', (opts: ISourceMemberConfigurationOptions) => { opts.ignore(); }); + + var objB = automapper.map(fromKey, toKey, objA); + + // assert + expect(objB).toEqualData({ prop1: objA.prop2, prop2: objA.prop1 }); + }); + + it('should be able to create a new property using a constant value', () => { + // arrange + var objA = { }; + + var fromKey = 'should be able to create a new property '; + var toKey = 'using a constant value'; + + // act + automapper + .createMap(fromKey, toKey) + .forMember('prop4', (opts: IMemberConfigurationOptions) => { return 12; }); + + var objB = automapper.map(fromKey, toKey, objA); + + // assert + expect(objB).toEqualData({ prop4: 12 }); + }); + + it('should just return source object when no properties are created using null source object', () => { + // arrange + var objA: any = null; + + var fromKey = 'should just return source object when no '; + var toKey = 'properties created using null source object'; + + // act + automapper + .createMap(fromKey, toKey); + + var objB = automapper.map(fromKey, toKey, objA); + + // assert + expect(objB).toBeNull(); + }); + + it('should be able to create a new property using a constant value (null source object)', () => { + // arrange + var objA: any = null; + + var fromKey = 'should be able to create a new property '; + var toKey = 'using a constant value (null source object)'; + + // act + automapper + .createMap(fromKey, toKey) + .forMember('prop4', (opts: IMemberConfigurationOptions) => { return 12; }); + + var objB = automapper.map(fromKey, toKey, objA); + + // assert + expect(objB).toEqualData({ prop4: 12 }); + }); + }); + + it('should map a source object with empty nested objects', () => { + // arrange + var src: any = { + homeAddress: null /*{ + address1: '200 Main St', + address2: '200 Main St', + city: 'Los Angeles', + state: 'CA', + zip: '90000' + }*/, + businessAddress: { + address1: '200 Main St', + // address2: '200 Main St', + city: 'Los Angeles', + state: 'CA', + zip: '90000' + } + }; + + var fromKey = '{60E9DC56-D6E1-48FF-9BAC-0805FCAF91B7}'; + var toKey = '{AC6D5A97-9AEF-42C7-BD60-A5F3D17E541A}'; + + automapper + .createMap(fromKey, toKey) + // .forMember('homeAddress.address1', (opts: IMemberConfigurationOptions) => { opts.mapFrom('homeAddress.address1'); }) + .forMember('homeAddress.address2', (opts: IMemberConfigurationOptions) => { opts.mapFrom('homeAddress.address2'); }) + // .forMember('homeAddress.city', (opts: IMemberConfigurationOptions) => { opts.mapFrom('homeAddress.city'); }) + // .forMember('homeAddress.state', (opts: IMemberConfigurationOptions) => { opts.mapFrom('homeAddress.state'); }) + // .forMember('homeAddress.zip', (opts: IMemberConfigurationOptions) => { opts.mapFrom('homeAddress.zip'); }) + + .forMember('businessAddress.address1', (opts: IMemberConfigurationOptions) => { opts.mapFrom('businessAddress.address1'); }) + .forMember('businessAddress.address2', (opts: IMemberConfigurationOptions) => null) + .forMember('businessAddress.city', (opts: IMemberConfigurationOptions) => { opts.mapFrom('businessAddress.city'); }) + .forMember('businessAddress.state', (opts: IMemberConfigurationOptions) => { opts.mapFrom('businessAddress.state'); }) + .forMember('businessAddress.zip', (opts: IMemberConfigurationOptions) => { opts.mapFrom('businessAddress.zip'); }) + ; + + // act + var dst = automapper.map(fromKey, toKey, src); + + // assert + expect(dst).not.toBeNull(); + + expect(dst.homeAddress).toBeNull(); + + expect(dst.businessAddress.address1).toBe(src.businessAddress.address1); + expect(dst.businessAddress.address2).toBeUndefined(); + expect(dst.businessAddress.city).toBe(src.businessAddress.city); + expect(dst.businessAddress.state).toBe(src.businessAddress.state); + expect(dst.businessAddress.zip).toBe(src.businessAddress.zip); + }); + + describe('AutoMapper - Currying support', () => { + beforeEach(() => { + jasmine.addMatchers(ExtendJasmine.addCustomMatchers()); + }); + + it('should be able to use currying when calling createMap', () => { + // arrange + var fromKey = '{808D9D7F-AA89-4D07-917E-A528F055EE64}'; + var toKey1 = '{B364C0A0-9E24-4424-A569-A4C14101947C}'; + var toKey2 = '{1055CA5A-4FC4-44CB-B4D8-B004F43D8840}'; + + var source = { prop: 'Value' }; + + // act + var mapFromKeyCurry = automapper.createMap(fromKey); + + mapFromKeyCurry(toKey1) + .forSourceMember('prop', (opts: ISourceMemberConfigurationOptions) => { opts.ignore(); }); + + mapFromKeyCurry(toKey2); + + var result1 = automapper.map(fromKey, toKey1, source); + var result2 = automapper.map(fromKey, toKey2, source); + + // assert + expect(typeof mapFromKeyCurry === 'function').toBeTruthy(); + expect(result1.prop).toBeUndefined(); + expect(result2.prop).toEqual(source.prop); + }); + + it('should be able to use currying (one parameter) when calling map', () => { + // arrange + var fromKey = 'should be able to use currying (one parameter)'; + var toKey1 = 'when calling map (1)'; + var toKey2 = 'when calling map (2)'; + + var source = { prop: 'Value' }; + + // act + var createMapFromKeyCurry = automapper.createMap(fromKey); + + createMapFromKeyCurry(toKey1) + .forSourceMember('prop', (opts: ISourceMemberConfigurationOptions) => { opts.ignore(); }); + + createMapFromKeyCurry(toKey2); + + var result1MapCurry = automapper.map(fromKey); + var result2MapCurry = automapper.map(fromKey); + + var result1 = result1MapCurry(toKey1, source); + var result2 = result2MapCurry(toKey2, source); + + // assert + expect(typeof createMapFromKeyCurry === 'function').toBeTruthy(); + expect(typeof result1MapCurry === 'function').toBeTruthy(); + expect(typeof result2MapCurry === 'function').toBeTruthy(); + + expect(result1.prop).toBeUndefined(); + expect(result2.prop).toEqual(source.prop); + }); + + it('should be able to use currying when calling map', () => { + // arrange + var fromKey = '{FC18523B-5A7C-4193-B938-B6AA2EABB37A}'; + var toKey1 = '{609202F4-15F7-4512-9178-CFAF073800E1}'; + var toKey2 = '{85096AE2-92FB-43D7-8FC3-EC14DDC1DFDD}'; + + var source = { prop: 'Value' }; + + // act + var createMapFromKeyCurry = automapper.createMap(fromKey); + + createMapFromKeyCurry(toKey1) + .forSourceMember('prop', (opts: ISourceMemberConfigurationOptions) => { opts.ignore(); }); + + createMapFromKeyCurry(toKey2); + + var result1MapCurry = automapper.map(fromKey, toKey1); + var result2MapCurry = automapper.map(fromKey, toKey2); + + var result1 = result1MapCurry(source); + var result2 = result2MapCurry(source); + + // assert + expect(typeof createMapFromKeyCurry === 'function').toBeTruthy(); + expect(typeof result1MapCurry === 'function').toBeTruthy(); + expect(typeof result2MapCurry === 'function').toBeTruthy(); + + expect(result1.prop).toBeUndefined(); + expect(result2.prop).toEqual(source.prop); + }); + + it('should be able to use currying when calling mapAsync', (done: () => void) => { + // arrange + var fromKey = '{1CA8523C-5A7C-4193-B938-B6AA2EABB37A}'; + var toKey1 = '{409212FD-15E7-4512-9178-CFAF073800EG}'; + var toKey2 = '{85096AE2-92FA-43N7-8FA3-EC14DDC1DFDE}'; + + var source = { prop: 'Value' }; + + // act + var createMapFromKeyCurry = automapper.createMap(fromKey); + + createMapFromKeyCurry(toKey1) + .forSourceMember('prop', (opts: ISourceMemberConfigurationOptions, cb: IMemberCallback) => { cb('Constant Value 1'); }); + + createMapFromKeyCurry(toKey2) + .forMember('prop', (opts: IMemberConfigurationOptions, cb: IMemberCallback) => { cb('Constant Value 2'); }); + + var result1MapCurry = automapper.mapAsync(fromKey, toKey1); + var result2MapCurry = automapper.mapAsync(fromKey, toKey2); + + // assert + expect(typeof createMapFromKeyCurry === 'function').toBeTruthy(); + expect(typeof result1MapCurry === 'function').toBeTruthy(); + expect(typeof result2MapCurry === 'function').toBeTruthy(); + + var resCount = 0; + var result1 = result1MapCurry(source, (result: any) => { + // assert + expect(result.prop).toEqual('Constant Value 1'); + if (++resCount === 2) { + done(); + } + }); + + var result2 = result2MapCurry(source, (result: any) => { + // assert + expect(result.prop).toEqual('Constant Value 2'); + if (++resCount === 2) { + done(); + } + }); + }); + + it('should be able to use currying when calling mapAsync with one parameter', (done: () => void) => { + // arrange + var fromKey = '{1CA8523C-5AVC-4193-BS38-B6AA2EABB37A}'; + var toKey = '{409212FD-1527-4512-9178-CFAG073800EG}'; + + var source = { prop: 'Value' }; + + // act + automapper.createMap(fromKey, toKey) + .forSourceMember('prop', (opts: ISourceMemberConfigurationOptions, cb: IMemberCallback) => { cb('Constant Value'); }); + + var mapAsyncCurry = automapper.mapAsync(fromKey); + + // assert + expect(typeof mapAsyncCurry === 'function').toBeTruthy(); + + var result = mapAsyncCurry(toKey, source, (result: any) => { + // assert + expect(result.prop).toEqual('Constant Value'); + done(); + }); + }); + + it('should be able to use currying when calling mapAsync with two parameters', (done: () => void) => { + // arrange + var fromKey = '{1CA852SC-5AVC-4193-BS38-B6AA2KABB3LA}'; + var toKey = '{409212FD-1Q27-45G2-9178-CFAG073800EG}'; + + var source = { prop: 'Value' }; + + // act + automapper.createMap(fromKey, toKey) + .forMember('prop', (opts: IMemberConfigurationOptions, cb: IMemberCallback) => { cb('Constant Value'); }); + + var mapAsyncCurry = automapper.mapAsync(fromKey, toKey); + + // assert + expect(typeof mapAsyncCurry === 'function').toBeTruthy(); + + var result = mapAsyncCurry(source, (result: any) => { + // assert + expect(result.prop).toEqual('Constant Value'); + done(); + }); + }); + + it('should be able to use currying when calling mapAsync with three parameters', (done: () => void) => { + // NOTE BL 20151214 I wonder why anyone would like calling this one? Maybe this one will be removed in + // the future. Please get in touch if you need this one to stay in place... + + // arrange + var fromKey = '{1CA852SC-5AVC-ZZ93-BS38-B6AA2KABB3LA}'; + var toKey = '{409212FD-1Q27-45G2-91BB-CFAG0738WCEG}'; + + var source = { prop: 'Value' }; + + // act + automapper.createMap(fromKey, toKey) + .forMember('prop', (opts: IMemberConfigurationOptions, cb: IMemberCallback) => { cb('Constant Value'); }); + + var mapAsyncCurry = automapper.mapAsync(fromKey, toKey, source); + + // assert + expect(typeof mapAsyncCurry === 'function').toBeTruthy(); + + var result = mapAsyncCurry((result: any) => { + // assert + expect(result.prop).toEqual('Constant Value'); + done(); + }); + }); + + it('should fail when calling mapAsync without parameters', () => { + // arrange + + // act + try { + var mapAsyncCurry = (automapper).mapAsync(); + } catch (e) { + // assert + expect(e.message).toEqual('The mapAsync function expects between 1 and 4 parameters, you provided 0.'); + return; + } + + // assert + expect(null).fail('Expected error was not raised.'); + }); + + it('should fail when calling mapAsync with > 4 parameters', () => { + // arrange + + // act + try { + var mapAsyncCurry = (automapper).mapAsync(undefined, undefined, undefined, undefined, undefined); + } catch (e) { + // assert + expect(e.message).toEqual('The mapAsync function expects between 1 and 4 parameters, you provided 5.'); + return; + } + + // assert + expect(null).fail('Expected error was not raised.'); + }); + + + it('should fail when specifying < 2 parameters to the asynchronous map function', () => { + // arrange + + // act + try { + (new AsyncAutoMapper()).map(undefined); + } catch (e) { + // assert + expect(e.message).toEqual('The AsyncAutoMapper.map function expects between 2 and 5 parameters, you provided 1.'); + return; + } + + // assert + expect(null).fail('Expected error was not raised.'); + }); + + it('should fail when specifying > 5 parameters to the asynchronous map function', () => { + // arrange + + // act + try { + (new AsyncAutoMapper()).map(undefined, undefined, undefined, undefined, undefined, undefined); + } catch (e) { + // assert + expect(e.message).toEqual('The AsyncAutoMapper.map function expects between 2 and 5 parameters, you provided 6.'); + return; + } + + // assert + expect(null).fail('Expected error was not raised.'); + }); + }); + + describe('AutoMapper.initialize', () => { + beforeEach(() => { + jasmine.addMatchers(ExtendJasmine.addCustomMatchers()); + }); + + it('should use created mapping profile', () => { + // arrange + var fromKey = '{5700E351-8D88-A327-A216-3CC94A308EDE}'; + var toKey = '{BB33A261-3CA9-A8FC-85E6-2C269F73728C}'; + + automapper.initialize((config: IConfiguration) => { + config.createMap(fromKey, toKey); + }); + + // act + automapper.map(fromKey, toKey, {}); + + // assert + }); + + it('should be able to use a naming convention to convert Pascal case to camel case', () => { + automapper.initialize((config: IConfiguration) => { + config.addProfile(new PascalCaseToCamelCaseMappingProfile()); + }); + + const sourceKey = 'PascalCase'; + const destinationKey = 'CamelCase'; + + const sourceObject = { FullName: 'John Doe' }; + + automapper + .createMap(sourceKey, destinationKey) + .withProfile('PascalCaseToCamelCase'); + + var result = automapper.map(sourceKey, destinationKey, sourceObject); + + expect(result).toEqualData({ fullName: 'John Doe' }); + }); + + it('should be able to use a naming convention to convert camelCase to PascalCase', () => { + automapper.initialize((config: IConfiguration) => { + config.addProfile(new CamelCaseToPascalCaseMappingProfile()); + }); + + const sourceKey = 'CamelCase2'; + const destinationKey = 'PascalCase2'; + + const sourceObject = { fullName: 'John Doe' }; + + automapper + .createMap(sourceKey, destinationKey) + .withProfile('CamelCaseToPascalCase'); + + var result = automapper.map(sourceKey, destinationKey, sourceObject); + + expect(result).toEqualData({ FullName: 'John Doe' }); + }); + + it('should be able to use forMember besides using a profile', () => { + automapper.initialize((config: IConfiguration) => { + config.addProfile(new CamelCaseToPascalCaseMappingProfile()); + }); + + const sourceKey = 'CamelCase'; + const destinationKey = 'PascalCase'; + + const sourceObject = { fullName: 'John Doe', age: 20 }; + + automapper + .createMap(sourceKey, destinationKey) + .forMember('theAge', (opts: IMemberConfigurationOptions) => opts.mapFrom('age')) + .withProfile('CamelCaseToPascalCase'); + + var result = automapper.map(sourceKey, destinationKey, sourceObject); + + expect(result).toEqualData({ FullName: 'John Doe', theAge: sourceObject.age }); + }); + + it('should use profile when only profile properties are specified', () => { + automapper.initialize((config: IConfiguration) => { + config.addProfile(new ValidatedAgeMappingProfile2()); + }); + + const sourceKey = '{918D9D7F-AA89-4D07-917E-A528F07EEF42}'; + const destinationKey = '{908D9D6F-BA89-4D17-915E-A528E988EE64}'; + + const sourceObject = { fullName: 'John Doe', proclaimedAge: 21, ageOnId: 15 }; + + automapper + .createMap(sourceKey, destinationKey) + .withProfile('ValidatedAgeMappingProfile2'); + + var result = automapper.map(sourceKey, destinationKey, sourceObject); + + expect(result).toEqualData({ fullName: 'John Doe', age: sourceObject.ageOnId }); + expect(result instanceof Person).toBeTruthy(); + expect(result instanceof BeerBuyingYoungster).not.toBeTruthy(); + }); + + it('should fail when using a non-existimg profile', () => { + // arrange + var caught = false; + var profileName = 'Non-existing profile'; + const sourceKey = 'should fail when using '; + const destinationKey = 'a non-existimg profile'; + const sourceObject = { }; + + // act + try { + automapper + .createMap(sourceKey, destinationKey) + .withProfile(profileName); + var result = automapper.map(sourceKey, destinationKey, sourceObject); + } catch (e) { + caught = true; + + // assert + expect(e.message).toEqual('Could not find profile with profile name \'' + profileName + '\'.'); + } + + if (!caught) { + // assert + expect().fail('Using a non-existing mapping profile should result in an error.'); + } + }); + + it('should merge forMember calls when specifying the same destination property normally and using profile', () => { + automapper.initialize((config: IConfiguration) => { + config.addProfile(new ValidatedAgeMappingProfile()); + }); + + const sourceKey = '{808D9D7F-AA89-4D07-917E-A528F078E642}'; + const destinationKey = '{808D9D6F-BA89-4D17-915E-A528E178EE64}'; + + const sourceObject = { fullName: 'John Doe', proclaimedAge: 21, ageOnId: 15 }; + + automapper + .createMap(sourceKey, destinationKey) + .forMember('ageOnId', (opts: IMemberConfigurationOptions) => opts.ignore()) + .forMember('age', (opts: IMemberConfigurationOptions) => opts.mapFrom('proclaimedAge')) + .convertToType(BeerBuyingYoungster) + .withProfile('ValidatedAgeMappingProfile'); + + var result = automapper.map(sourceKey, destinationKey, sourceObject); + + expect(result).toEqualData({ fullName: 'John Doe', age: sourceObject.ageOnId }); + expect(result instanceof Person).toBeTruthy(); + expect(result instanceof BeerBuyingYoungster).not.toBeTruthy(); + }); + + it('should be able to use currying when calling initialize(cfg => cfg.createMap)', () => { + // arrange + var fromKey = '{808D9D7F-AA89-4D07-917E-A528F078EE64}'; + var toKey1 = '{B364C0A0-9E24-4424-A569-A4C14102147C}'; + var toKey2 = '{1055CA5A-4FC4-44CA-B4D8-B004F43D4440}'; + + var source = { prop: 'Value' }; + + // act + var mapFromKeyCurry: (destinationKey: string) => ICreateMapFluentFunctions; + + automapper.initialize((config: IConfiguration) => { + mapFromKeyCurry = config.createMap(fromKey); + + mapFromKeyCurry(toKey1) + .forSourceMember('prop', (opts: ISourceMemberConfigurationOptions) => { opts.ignore(); }); + + mapFromKeyCurry(toKey2); + }); + + var result1 = automapper.map(fromKey, toKey1, source); + var result2 = automapper.map(fromKey, toKey2, source); + + // assert + expect(typeof mapFromKeyCurry === 'function').toBeTruthy(); + expect(result1.prop).toBeUndefined(); + expect(result2.prop).toEqual(source.prop); + }); + + }); + + describe('AutoMapper', () => { + beforeEach(() => { + jasmine.addMatchers(ExtendJasmine.addCustomMatchers()); + }); + + it('should auto map matching properties', () => { + // arrange + var objA = { prop1: 'From A', prop2: 'From A too' }; + + var fromKey = '{7F5AF9AC-2E9E-4676-8BE1-3E72866B11E8}'; + var toKey = '{8089EBDC-3BBB-4988-95F2-683CC1AD23A3}'; + + automapper.createMap(fromKey, toKey); + + // act + var objB = automapper.map(fromKey, toKey, objA); + + // assert + expect(objB).toEqualData(objA); + }); + + it('should map an array', () => { + // arrange + var arrA = [{ prop1: 'From A', prop2: 'From A too' }]; + + var fromKey = '{60D9DB56-D6E1-48FF-9BAC-0805FCAF91B7}'; + var toKey = '{AC6D5B97-9AE3-4267-BD60-A5FED17E541A}'; + + automapper.createMap(fromKey, toKey); + + // act + var arrB = automapper.map(fromKey, toKey, arrA); + + // assert + expect(arrB).toEqualData(arrA); + }); + + it('should map an array and handle empty items', () => { + // arrange + var arrA = [{ prop1: 'From A', prop2: 'From A too' }, undefined]; + + var fromKey = '{60D9DB56-D6E1-48FF-9BAC-0805FCAF91B7}'; + var toKey = '{AC6D5B97-9AE3-4267-BD60-A5FED17E541A}'; + + automapper.createMap(fromKey, toKey); + + // act + var arrB = automapper.map(fromKey, toKey, arrA); + + // assert + expect(arrB).toEqualData(arrA); + }); + }); + + /** AutoMapper helper functions */ + class AutoMapperHelper { + public static getClassName(classType: new() => any): string { + if (classType && (classType).name) { + return (classType).name; + } + // source: http://stackoverflow.com/a/13914278/702357 + if (classType && classType.constructor) { + let className = classType.toString(); + if (className) { + // classType.toString() is "function classType (...) { ... }" + let matchParts = className.match(/function\s*(\w+)/); + if (matchParts && matchParts.length === 2) { + return matchParts[1]; + } + } + + // for browsers which have name property in the constructor + // of the object, such as chrome + if ((classType.constructor).name) { + return (classType.constructor).name; + } + + if (classType.constructor.toString()) { + var str = classType.constructor.toString(); + + if (str.charAt(0) === '[') { + // executed if the return of object.constructor.toString() is "[object objectClass]" + var arr = str.match(/\[\w+\s*(\w+)\]/); + } else { + // executed if the return of object.constructor.toString() is "function objectClass () {}" + // (IE and Firefox) + var arr = str.match(/function\s*(\w+)/); + } + + if (arr && arr.length === 2) { + return arr[1]; + } + } + } + + throw new Error(`Unable to extract class name from type '${classType}'`); + } + } + + class AssertConfigPropertiesProp { + prop: string = undefined; // TODO Wiki: properties are only available when initialized: http://stackoverflow.com/a/20534039/702357 + } + + class AssertConfigPropertiesProp2 { + prop2: string = undefined; + } + + class AssertConfigPropertiesPropProp2 { + prop: string = undefined; + prop2: string = undefined; + } + + class ClassA { + public propA: string; + } + + class ClassB { + public propA: string; + } + + class ClassC { + public propA: string; + } + + class DemoToBusinessType { + } + + class CustomTypeConverterInstance extends TypeConverter { + public convert(resolutionContext: IResolutionContext): any { + return { propA: resolutionContext.sourceValue.propA + ' (convertUsing with a class instance)' }; + } + } + + class CustomTypeConverterDefinition extends TypeConverter { + public convert(resolutionContext: IResolutionContext): any { + return { propA: resolutionContext.sourceValue.propA + ' (convertUsing with a class definition)' }; + } + } + + class PascalCaseToCamelCaseMappingProfile extends Profile { + public sourceMemberNamingConvention: INamingConvention; + public destinationMemberNamingConvention: INamingConvention; + + public profileName = 'PascalCaseToCamelCase'; + + public configure() { + this.sourceMemberNamingConvention = new PascalCaseNamingConvention(); + this.destinationMemberNamingConvention = new CamelCaseNamingConvention(); + + super.createMap('a', 'b'); + } + } + + class CamelCaseToPascalCaseMappingProfile extends Profile { + public sourceMemberNamingConvention: INamingConvention; + public destinationMemberNamingConvention: INamingConvention; + + public profileName = 'CamelCaseToPascalCase'; + + public configure() { + this.sourceMemberNamingConvention = new CamelCaseNamingConvention(); + this.destinationMemberNamingConvention = new PascalCaseNamingConvention(); + } + } + + class ValidatedAgeMappingProfile extends Profile { + public profileName = 'ValidatedAgeMappingProfile'; + + public configure() { + const sourceKey = '{808D9D7F-AA89-4D07-917E-A528F078E642}'; + const destinationKey = '{808D9D6F-BA89-4D17-915E-A528E178EE64}'; + + this.createMap(sourceKey, destinationKey) + .forMember('proclaimedAge', (opts: IMemberConfigurationOptions) => opts.ignore()) + .forMember('age', (opts: IMemberConfigurationOptions) => opts.mapFrom('ageOnId')) + .convertToType(Person); + } + } + + class ValidatedAgeMappingProfile2 extends Profile { + public profileName = 'ValidatedAgeMappingProfile2'; + + public configure() { + const sourceKey = '{918D9D7F-AA89-4D07-917E-A528F07EEF42}'; + const destinationKey = '{908D9D6F-BA89-4D17-915E-A528E988EE64}'; + + this.createMap(sourceKey, destinationKey) + .forMember('proclaimedAge', (opts: IMemberConfigurationOptions) => opts.ignore()) + .forMember('age', (opts: IMemberConfigurationOptions) => opts.mapFrom('ageOnId')) + .convertToType(Person); + } + } + + class Person { + fullName: string; + age: number; + } + + class BeerBuyingYoungster extends Person { + } + class ExtendJasmine { + public static addCustomMatchers(): jasmine.CustomMatcherFactories { + var customMatchers: jasmine.CustomMatcherFactories = { + /** toEqualData compares to data objects using property matching */ + toEqualData: (util: jasmine.MatchersUtil, customEqualityTesters: Array): any => { + return { + compare: function (actual: any, expected: any): jasmine.CustomMatcherResult { + var pass = ExtendJasmine.equalsData(actual, expected); + return { + pass: pass, + message: pass + ? 'Data sets do equal. Congratulations ;) !' + : 'Data sets do not equal: expected "' + JSON.stringify(expected) + '", actual "' + JSON.stringify(actual) + '".' + }; + } + }; + }, + "fail": (util: jasmine.MatchersUtil, customEqualityTesters: Array): any => { + return { + compare: function (actual: any, message: string): jasmine.CustomMatcherResult { + return { + pass: false, + message: message || 'Jasmine test failed. Please provide a fix.' + }; + } + } + } + }; + return customMatchers; + } + + public static equalsData(actual: any, expected: any): boolean { + var toClass = {}.toString; + + // check array. + var actualType = toClass.call(actual); + var expectedType = toClass.call(expected); + + if (actualType === '[object Array]') { + // check both are arrays + if (expectedType !== '[object Array]') { + return false; + } + + // check both have same length + if (expected.length !== actual.length) { + return false; + } + + for (var i = 0; i < actual.length; i++) { + // check each item in the array + if (!ExtendJasmine.equalsData(actual[i], expected[i])) + return false; + } + } + else if (actualType === '[object Object]') { + // check both are objects + if (expectedType !== '[object Object]') { + return false; + } + + // check each property in the object + for (var propertyName in expected) { + if (!expected.hasOwnProperty(propertyName)) { + continue; + } + + if (!actual.hasOwnProperty(propertyName)) { + return false; + } + + if (!ExtendJasmine.equalsData(actual[propertyName], expected[propertyName])) + return false; + } + } else { + var actualIsUndefined = typeof actual === 'undefined'; + var expectedIsUndefined = typeof expected === 'undefined'; + if (actualIsUndefined !== expectedIsUndefined) { + return false; + } + + return actual === expected; + } + + return true; + } + } +} \ No newline at end of file diff --git a/automapper-ts/automapper-ts.d.ts b/automapper-ts/automapper-ts.d.ts new file mode 100644 index 00000000000000..b2bf17a966ddc0 --- /dev/null +++ b/automapper-ts/automapper-ts.d.ts @@ -0,0 +1,559 @@ +// Type definitions for automapper-ts +// Project: https://github.com/loedeman/AutoMapper +// Definitions by: Bert Loedeman +// Definitions: https://github.com/borisyankov/DefinitelyTyped + +declare module AutoMapperJs { + /** + * AutoMapper implementation, for both creating maps and performing maps. Comparable usage and functionality to the original + * .NET AutoMapper library is the pursuit of this implementation. + */ + class AutoMapper { + /** + * Initializes the mapper with the supplied configuration. + * @param {(config: IConfiguration) => void} Configuration function to call. + */ + initialize(configFunction: (config: IConfiguration) => void): void; + + /** + * Create a createMap curry function which expects only a destination key. + * @param {string} sourceKey The map source key. + * @returns {(destinationKey: string) => ICreateMapFluentFunctions} + */ + createMap(sourceKey: string | (new() => any)): (destinationKey: string | (new() => any)) => ICreateMapFluentFunctions; + + /** + * Create a mapping profile. + * @param {string} sourceKey The map source key. + * @param {string} destinationKey The map destination key. + * @returns {Core.ICreateMapFluentFunctions} + */ + createMap(sourceKey: string | (new() => any), destinationKey: string | (new() => any)): ICreateMapFluentFunctions; + + /** + * Create a map curry function which expects a destination key and a source object. + * @param sourceKey Source key, for instance the source type name. + * @returns {(destinationKey: string, sourceObject: any) => any} + */ + map(sourceKey: string | (new() => any)): (destinationKey: string | (new() => any), sourceObject: any) => any; + + /** + * Create a map curry function which expects only a source object. + * @param sourceKey Source key, for instance the source type name. + * @param destinationKey Destination key, for instance the destination type name. + * @returns {(sourceObject: any) => any} + */ + map(sourceKey: string | (new() => any), destinationKey: string | (new() => any)): (sourceObject: any) => any; + + /** + * Execute a mapping from the source object to a new destination object with explicit mapping configuration and supplied mapping options (using createMap). + * @param sourceKey Source key, for instance the source type name. + * @param destinationKey Destination key, for instance the destination type name. + * @param sourceObject The source object to map. + * @returns {any} Destination object. + */ + map(sourceKey: string | (new() => any), destinationKey: string | (new() => any), sourceObject: any): any; + + /** + * Create a mapAsync curry function which expects a destination key, a source object and a callback function. + * @param sourceKey Source key, for instance the source type name. + * @returns {(destinationKey: string, sourceObject: any, callback: IMapCallback) => void} + */ + mapAsync(sourceKey: string | (new() => any)): (destinationKey: string | (new() => any), sourceObject: any, callback: IMapCallback) => void; + + /** + * Create a map curry function which expects only a source object and a callback function. + * @param sourceKey Source key, for instance the source type name. + * @param destinationKey Destination key, for instance the destination type name. + * @param sourceObject The source object to map. + * @returns {(callback: IMapCallback) => void} + */ + mapAsync(sourceKey: string | (new() => any), destinationKey: string | (new() => any), sourceObject: any): (callback: IMapCallback) => void; + + /** + * Create a map curry function which expects only a source object and a callback function. + * @param sourceKey Source key, for instance the source type name. + * @param destinationKey Destination key, for instance the destination type name. + * @returns {(sourceObject: any, callback: IMapCallback) => void} + */ + mapAsync(sourceKey: string | (new() => any), destinationKey: string | (new() => any)): (sourceObject: any, callback: IMapCallback) => void; + + /** + * Execute an asynchronous mapping from the source object to a new destination object with explicit mapping configuration and supplied mapping options (using createMap). + * @param sourceKey Source key, for instance the source type name. + * @param destinationKey Destination key, for instance the destination type name. + * @param sourceObject The source object to map. + * @param {IMapCallback} callback The callback to call when asynchronous mapping is complete. + */ + mapAsync(sourceKey: string | (new() => any), destinationKey: string | (new() => any), sourceObject: any, callback: IMapCallback): void; + + /** + * Validates mapping configuration by dry-running. Since JS does not + * fully support typing, it only checks if properties match on both + * sides. The function needs IMapping.sourceTypeClass and + * IMapping.destinationTypeClass to function. + * @param {boolean} strictMode Whether or not to fail when properties + * sourceTypeClass or destinationTypeClass + * are unavailable. + */ + assertConfigurationIsValid(strictMode?: boolean): void; + } + + class AsyncAutoMapper { + /* For Test Purposes Only */ + } + + /** + * Converts source type to destination type instead of normal member mapping + */ + class TypeConverter implements ITypeConverter { + /** + * Performs conversion from source to destination type. + * @param {IResolutionContext} resolutionContext Resolution context. + * @returns {any} Destination object. + */ + convert(resolutionContext: IResolutionContext): any; + } + + export class Profile implements IProfile { + /** Profile name */ + public profileName: string; + + /** Naming convention for source members */ + public sourceMemberNamingConvention: INamingConvention; + + /** Naming convention for destination members */ + public destinationMemberNamingConvention: INamingConvention; + + /** + * Create a createMap curry function which expects only a destination key. + * @param {string} sourceKey The map source key. + * @returns {(destinationKey: string) => ICreateMapFluentFunctions} + */ + protected createMap(sourceKey: string): (destinationKey: string) => ICreateMapFluentFunctions; + + /** + * Create a mapping profile. + * @param {string} sourceKey The map source key. + * @param {string} destinationKey The map destination key. + * @returns {Core.ICreateMapFluentFunctions} + */ + protected createMap(sourceKey: string, destinationKey: string): ICreateMapFluentFunctions; + + /** + * Implement this method in a derived class and call the CreateMap method to associate that map with this profile. + * Avoid calling the AutoMapper class / automapper instance from this method. + */ + public configure(): void; + } + + /** + * Defines the PascalCase naming convention strategy. + */ + class PascalCaseNamingConvention implements INamingConvention { + /** Regular expression on how to tokenize a member. */ + splittingExpression: RegExp; + + /** Character to separate on. */ + separatorCharacter: string; + + /** + * Transformation function called when this convention is the destination naming convention. + * @param {string[]} sourcePropertyNameParts Array containing tokenized source property name parts. + * @returns {string} Destination property name + */ + transformPropertyName(sourcePropertyNameParts: string[]): string; + } + + /** + * Defines the camelCase naming convention strategy. + */ + class CamelCaseNamingConvention implements INamingConvention { + /** Regular expression on how to tokenize a member. */ + splittingExpression: RegExp; + + /** Character to separate on. */ + separatorCharacter: string; + + /** + * Transformation function called when this convention is the destination naming convention. + * @param {string[]} sourcePropertyNameParts Array containing tokenized source property name parts. + * @returns {string} Destination property name + */ + transformPropertyName(sourcePropertyNameParts: string[]): string; + } + + + + interface IProperty { + name: string; + metadata: IPropertyMetadata; + level: number; + sourceMapping: boolean; + ignore: boolean; + async: boolean; + children?: IProperty[]; + destinations?: IProperty[]; + conversionValuesAndFunctions: any[]; + conditionFunction?: (sourceObject: any) => boolean; + } + + interface IPropertyMetadata { + mapping: IMapping; + root: IProperty; + parent: IProperty; + destinations: {[name: string]: IPropertyDestinationMetadata}; + destinationCount: number; + } + + interface IPropertyDestinationMetadata { + source: IProperty; + destination: IProperty; + } + + interface IMemberMappingMetaData { + destination: string; + source: string; + sourceMapping: boolean; + ignore: boolean; + async: boolean; + condition: (sourceObject: any) => boolean; + } + + /** + * Member mapping properties. + */ + interface IForMemberMapping { + /** The source member property name. */ + sourceProperty: string; + /** The destination member property name parts for nested property support (e.g. 'type.name'). */ + destinationProperty: string; + /** Source or destination mapping. */ + sourceMapping: boolean; + /** All mapping values and/or functions resulting from stacked for(Source)Member calls. */ + mappingValuesAndFunctions: Array; + /** Whether or not this destination property must be ignored. */ + ignore: boolean; + /** Whether or not this member mapping has an asynchronous mapping function. */ + async: boolean; + /** + * The object will only be mapped when the condition is met. + * @param {any} sourceObject The source object to check. + * @returns {boolean} + */ + conditionFunction: (sourceObject: any) => boolean; + } + + /** + * Interface for returning an object with available 'sub' functions to enable method chaining (e.g. automapper.createMap().forMember().forMember() ...) + */ + interface ICreateMapFluentFunctions { + /** + * Customize configuration for an individual destination member. + * @param sourceProperty The destination member property name. + * @param valueOrFunction The value or function to use for this individual member. + * @returns {IAutoMapperCreateMapChainingFunctions} + */ + forMember: (sourceProperty: string, valueOrFunction: any | + ((opts: IMemberConfigurationOptions) => any) | + ((opts: IMemberConfigurationOptions, cb: IMemberCallback) => void)) => ICreateMapFluentFunctions; + + /** + * Customize configuration for an individual source member. + * @param sourceProperty The source member property name. + * @param sourceMemberConfigFunction The function to use for this individual member. + * @returns {IAutoMapperCreateMapChainingFunctions} + */ + forSourceMember: (sourceProperty: string, + sourceMemberConfigFunction: ((opts: ISourceMemberConfigurationOptions) => any) | + ((opts: ISourceMemberConfigurationOptions, cb: IMemberCallback) => void) + ) => ICreateMapFluentFunctions; + + /** + * Customize configuration for all destination members. + * @param func The function to use for this individual member. + * @returns {IAutoMapperCreateMapChainingFunctions} + */ + forAllMembers: (func: (destinationObject: any, destinationPropertyName: string, value: any) => void) => ICreateMapFluentFunctions; + + /** + * Ignore all members not specified explicitly. + */ + ignoreAllNonExisting: () => ICreateMapFluentFunctions; + + /** + * Skip normal member mapping and convert using a custom type converter (instantiated during mapping). + * @param typeConverterClassOrFunction The converter class or function to use when converting. + */ + convertUsing: (typeConverterClassOrFunction: ((resolutionContext: IResolutionContext) => any) | + ((resolutionContext: IResolutionContext, callback: IMapCallback) => void) | + ITypeConverter | + (new() => ITypeConverter) + ) => void; + + /** + * Specify to which class type AutoMapper should convert. When specified, AutoMapper will create an instance of the given type, instead of returning a new object literal. + * @param typeClass The destination type class. + * @returns {IAutoMapperCreateMapChainingFunctions} + */ + convertToType: (typeClass: new () => any) => ICreateMapFluentFunctions; + + /** + * Specify which profile should be used when mapping. + * @param {string} profileName The profile name. + * @returns {IAutoMapperCreateMapChainingFunctions} + */ + withProfile: (profileName: string) => void; + } + + /** + * The mapping configuration for the current mapping keys/types. + */ + interface IMapping { + /** The mapping source key. */ + sourceKey: string; + + /** The mapping destination key. */ + destinationKey: string; + + /** The mappings for forAllMembers functions. */ + forAllMemberMappings: Array<(destinationObject: any, destinationPropertyName: string, value: any) => void>; + + properties: IProperty[]; + + /** + * Skip normal member mapping and convert using a type converter. + * @param resolutionContext Context information regarding resolution of a destination value + * @returns {any} Destination object. + */ + typeConverterFunction: ((resolutionContext: IResolutionContext) => any) | + ((resolutionContext: IResolutionContext, callback: IMapCallback) => void); + + /** The source type class to convert from. */ + sourceTypeClass: any; + + /** The destination type class to convert to. */ + destinationTypeClass: any; + + /** The profile used when mapping. */ + profile?: IProfile; + + /** Whether or not to ignore all properties not specified using createMap. */ + ignoreAllNonExisting?: boolean; + + /** Whether or not an mapping has to be asynchronous. */ + async: boolean; + + /* + * PERFORMANCE ENHANCEMENTS + */ + + /** + * Item mapping function to use. + */ + mapItemFunction: IMapItemFunction | IAsyncMapItemFunction; + } + + // export interface IMappingMapOptimized extends IMapping { + // final: boolean; + // forMemberMappingsArray: Array; + // } + + /** + * Context information regarding resolution of a destination value + */ + export interface IResolutionContext { + /** Source value */ + sourceValue: any; + + /** Destination value */ + destinationValue: any; + + /** Source property name */ + sourcePropertyName?: string; + + /** Destination property name */ + destinationPropertyName?: string; + + /** Index of current collection mapping */ + arrayIndex?: number; + } + + /** + * Configuration options for forMember mapping function. + */ + interface IMemberConfigurationOptions { + /** + * Map from a custom source property name. + * @param sourcePropertyName The source property to map. + */ + mapFrom: (sourcePropertyName: string) => void; + + /** + * When this configuration function is used, the (destination) property is ignored + * when mapping. + */ + ignore?: () => void; + + /** + * If specified, the property will only be mapped when the condition is fulfilled. + */ + condition: (predicate: ((sourceObject: any) => boolean)) => void; + + /** The source object to map. */ + sourceObject: any; + + /** The source property to map. */ + sourcePropertyName: string; + + /** + * The intermediate destination property value, used for stacking multiple for(Source)Member calls + * while elaborating the intermediate result. + */ + intermediatePropertyValue: any; + } + + /** + * Configuration options for forSourceMember mapping function. + */ + interface ISourceMemberConfigurationOptions { + /** + * When this configuration function is used, the source property is ignored + * when mapping. + */ + ignore: () => void; + } + + /** + * Member callback interface + */ + interface IMemberCallback { + /** + * Callback function to call when the async operation is executed. + * @param {any} callbackValue Callback value to be used as output for the for(Source)Member call. + */ + (callbackValue: any): void; + } + + /** + * Member callback interface + */ + interface IMapCallback { + /** + * Callback function to call when the async operation is executed. + * @param {any} result Callback value to be used as output for the mapAsync call. + */ + (result: any): void; + } + + /** + * Converts source type to destination type instead of normal member mapping + */ + export interface ITypeConverter { + /** + * Performs conversion from source to destination type. + * @param {IResolutionContext} resolutionContext Resolution context. + * @returns {any} Destination object. + */ + convert: (resolutionContext: IResolutionContext) => any; + } + + /** + * Defines a naming convention strategy. + */ + export interface INamingConvention { + /** Regular expression on how to tokenize a member. */ + splittingExpression: RegExp; + + /** Character to separate on. */ + separatorCharacter: string; + + /** + * Transformation function called when this convention is the destination naming convention. + * @param {string[]} sourcePropertyNameParts Array containing tokenized source property name parts. + * @returns {string} Destination property name + */ + transformPropertyName: (sourcePropertyNameParts: string[]) => string; + } + + /** + * Configuration for profile-specific maps. + */ + export interface IConfiguration { + /** + * Add an existing profile + * @param profile {IProfile} Profile to add. + */ + addProfile(profile: IProfile): void; + + /** + * Create a createMap curry function which expects only a destination key. + * @param {string} sourceKey The map source key. + * @returns {(destinationKey: string) => IAutoMapperCreateMapChainingFunctions} + */ + createMap?(sourceKey: string): (destinationKey: string) => ICreateMapFluentFunctions; + + /** + * Create a mapping profile. + * @param {string} sourceKey The map source key. + * @param {string} destinationKey The map destination key. + * @returns {Core.IAutoMapperCreateMapChainingFunctions} + */ + createMap?(sourceKey: string, destinationKey: string): ICreateMapFluentFunctions; + } + + /** + * Provides a named configuration for maps. Naming conventions become scoped per profile. + */ + export interface IProfile { + /** Profile name */ + profileName: string; + + /** Naming convention for source members */ + sourceMemberNamingConvention: INamingConvention; + + /** Naming convention for destination members */ + destinationMemberNamingConvention: INamingConvention; + + /** + * Implement this method in a derived class and call the CreateMap method to associate that map with this profile. + * Avoid calling the AutoMapper class / automapper instance from this method. + */ + configure: () => void; + } + + export interface IMapItemFunction { + (mapping: IMapping, sourceObject: any, destinationObject: any): any; + } + + export interface IAsyncMapItemFunction { + (mapping: IMapping, sourceObject: any, destinationObject: any, callback: IMapCallback): void; + } + + interface ICreateMapParameters { + mapping: IMapping; + destinationProperty: string; + conversionValueOrFunction: any; + sourceMapping: boolean; + fluentFunctions: ICreateMapFluentFunctions; + } + + interface IGetOrCreatePropertyParameters { + propertyNameParts: string[]; + mapping: IMapping; + parent?: IProperty; + propertyArray: IProperty[]; + destination?: string; + sourceMapping: boolean; + } + + interface ICreatePropertyParameters { + name: string; + mapping: IMapping; + parent: IProperty; + propertyArray: IProperty[]; + sourceMapping: boolean; + } +} + +declare var automapper: AutoMapperJs.AutoMapper; \ No newline at end of file diff --git a/awesomplete/awesomplete-tests.ts b/awesomplete/awesomplete-tests.ts new file mode 100644 index 00000000000000..8132ad45553940 --- /dev/null +++ b/awesomplete/awesomplete-tests.ts @@ -0,0 +1,57 @@ +/// + +var input = document.getElementById("myinput"); +new Awesomplete(input, {list: "#mylist"}); + +new Awesomplete(input, {list: document.querySelector("#mylist")}); + +new Awesomplete(input, { + list: ["Ada", "Java", "JavaScript", "LOLCODE", "Node.js", "Ruby on Rails"] +}); + +var awesomplete = new Awesomplete(input); +awesomplete.list = ["Ada", "Java", "JavaScript", "LOLCODE", "Node.js", "Ruby on Rails"]; + +new Awesomplete(input, { + list: [ + { label: "Belarus", value: "BY" }, + { label: "China", value: "CN" }, + { label: "United States", value: "US" } + ] +}); + +// Same with arrays: +new Awesomplete(input, { + list: [ + [ "Belarus", "BY" ], + [ "China", "CN" ], + [ "United States", "US" ] + ] +}); + +new Awesomplete('input[type="email"]', { + list: ["aol.com", "att.net", "comcast.net", "facebook.com", "gmail.com", "gmx.com", "googlemail.com", "google.com", "hotmail.com", "hotmail.co.uk", "mac.com", "me.com", "mail.com", "msn.com", "live.com", "sbcglobal.net", "verizon.net", "yahoo.com", "yahoo.co.uk"], + data: function (text: string, input: any) { + return input.slice(0, input.indexOf("@")) + "@" + text; + }, + filter: Awesomplete.FILTER_STARTSWITH +}); + +new Awesomplete('input[data-multiple]', { + filter: function(text: string, input: any) { + return Awesomplete.FILTER_CONTAINS(text, input.match(/[^,]*$/)[0]); + }, + + replace: function(text: string) { + var before = this.input.value.match(/^.+,\s*|/)[0]; + this.input.value = before + text + ", "; + } +}); + +var ajax = new XMLHttpRequest(); +ajax.open("GET", "https://restcountries.eu/rest/v1/lang/fr", true); +ajax.onload = function() { + var list = JSON.parse(ajax.responseText).map(function(i: any) { return i.name; }); + new Awesomplete(document.querySelector("#ajax-example input"),{ list: list }); +}; +ajax.send(); \ No newline at end of file diff --git a/awesomplete/awesomplete.d.ts b/awesomplete/awesomplete.d.ts new file mode 100644 index 00000000000000..d39389f008ee95 --- /dev/null +++ b/awesomplete/awesomplete.d.ts @@ -0,0 +1,49 @@ +// Type definitions for Awesomplete v1.1.0 +// Project: https://leaverou.github.io/awesomplete/ +// Definitions by: webbiesdk , Ben Dixon +// Definitions: https://github.com/DefinitelyTyped/DefinitelyTyped + +declare class Awesomplete { + constructor(input: Element | HTMLElement | string, o?: AwesompleteOptions); + static all: Array; + static $$: (expr: string | NodeSelector, con?: any) => NodeList; + static ITEM: (text: string, input: string) => HTMLElement; + static $: { + (expr: string|Element, con?: NodeSelector): string | Element; + regExpEscape: (s: { replace: (arg0: RegExp, arg1: string) => void }) => any; + create: (tag: string, o: any) => HTMLElement; + fire: (target: EventTarget, type: string, properties: any) => any; + siblingIndex: (el: Element) => number; + }; + static FILTER_STARTSWITH: (text: string, input: string) => boolean; + static FILTER_CONTAINS: (text: string, input: string) => boolean; + static SORT_BYLENGTH: (a: number | any[], b: number | any[]) => number; + static REPLACE: (text: any) => void; + next: () => void; + container: HTMLElement; + select: (selected?: HTMLElement, originalTarget?: HTMLElement) => void; + previous: () => void; + index: number; + opened: number; + list: string | string[] | Element | { label: string, value: any }[] | [string, string][]; + input: HTMLElement | string; + goto: (i: number) => void; + ul: HTMLElement; + close: () => void; + evaluate: () => void; + selected: boolean; + open: () => void; + status: HTMLElement; +} + +interface AwesompleteOptions { + list?: string | string[] | Element | { label: string, value: any }[] | [string, string][]; + minChars?: Number; + maxItems?: Number; + autoFirst?: boolean; + data?: Function; + filter?: Function; + sort?: Function; + item?: Function; + replace?: Function; +} diff --git a/aws-lambda/aws-lambda-tests.ts b/aws-lambda/aws-lambda-tests.ts index f562b59d3dd978..3563000e4c5007 100644 --- a/aws-lambda/aws-lambda-tests.ts +++ b/aws-lambda/aws-lambda-tests.ts @@ -2,13 +2,13 @@ import lambda = require('aws-lambda'); -var str: string; -var date: Date; -var anyObj: any; -var num: number; +var str: string = "any string"; +var date: Date = new Date(); +var anyObj: any = { abc: 123 }; +var num: number = 5; var identity: lambda.CognitoIdentity; -var error: Error; -var b: boolean; +var error: Error = new Error(); +var b: boolean = true; var clientCtx: lambda.ClientContext; /* Context */ @@ -37,4 +37,14 @@ function callback(cb: lambda.Callback) { cb(null); cb(error); cb(null, anyObj); -} \ No newline at end of file +} + +/* Compatibility functions */ +context.done(); +context.done(error); +context.done(error, anyObj); +context.succeed(str); +context.succeed(anyObj); +context.succeed(str, anyObj); +context.fail(error); +context.fail(str); \ No newline at end of file diff --git a/aws-lambda/aws-lambda.d.ts b/aws-lambda/aws-lambda.d.ts index c9a66a37839fad..7b5d5ebbfa977f 100644 --- a/aws-lambda/aws-lambda.d.ts +++ b/aws-lambda/aws-lambda.d.ts @@ -23,7 +23,9 @@ declare module "aws-lambda" { getRemainingTimeInMillis(): number; // Functions for compatibility with earlier Node.js Runtime v0.10.42 - log(message: string, object: any): void; + // For more details see http://docs.aws.amazon.com/lambda/latest/dg/nodejs-prog-model-using-old-runtime.html#nodejs-prog-model-oldruntime-context-methods + done(error?: Error, result?: any): void; + fail(error: Error): void; fail(message: string): void; succeed(message: string): void; succeed(object: any): void; diff --git a/aws-sdk/aws-sdk.d.ts b/aws-sdk/aws-sdk.d.ts index d30b3af3058dc3..f484c5fdac1224 100644 --- a/aws-sdk/aws-sdk.d.ts +++ b/aws-sdk/aws-sdk.d.ts @@ -382,7 +382,8 @@ declare module "aws-sdk" { endpoint: Endpoint; getObject(params: s3.GetObjectRequest, callback?: (err: Error, data: any) => void): any; - putObject(params: s3.PutObjectRequest, callback: (err: Error, data: any) => void): void; + putObject(params: s3.PutObjectRequest, callback?: (err: Error, data: any) => void): any; + copyObject(params: s3.CopyObjectRequest, callback?: (err: Error, data: any) => void): any; deleteObject(params: s3.DeleteObjectRequest, callback: (err: Error, data: any) => void): void; headObject(params: s3.HeadObjectRequest, callback: (err: Error, data: any) => void): void; getSignedUrl(operation: string, params: any): string; @@ -527,7 +528,8 @@ declare module "aws-sdk" { interface UpdateParam extends _DDBDC_Writer { Key: _DDBDC_Keys; - AttributeUpdates: { + UpdateExpression?: string; + AttributeUpdates?: { [someKey: string]: { Action: "PUT" | "ADD" | "DELETE"; Value: any @@ -658,7 +660,7 @@ declare module "aws-sdk" { export interface DescribeStackResourcesParams { StackName?: string; // must specify either StackName or PhysicalResourceId - LogicalResourceId?: string; + LogicalResourceId?: string; PhysicalResourceId?: string; // must specify either StackName or PhysicalResourceId } @@ -2262,6 +2264,40 @@ declare module "aws-sdk" { WebsiteRedirectLocation?: string; } + export interface CopyObjectRequest { + Bucket: string; + CopySource: string; + Key: string; + ACL?: string; + CacheControl?: string; + ContentDisposition?: string; + ContentEncoding?: string; + ContentLanguage?: string; + ContentType?: string; + CopySourceIfMatch?: string; + CopySourceIfModifiedSince?: any; + CopySourceIfNoneMatch?: string; + CopySourceIfUnmodifiedSince?: any; + CopySourceSSECustomerAlgorithm?: string; + CopySourceSSECustomerKey?: any; + CopySourceSSECustomerKeyMD5?: string; + Expires?: any; + GrantFullControl?: string; + GrantRead?: string; + GrantReadACP?: string; + GrantWriteACP?: string; + Metadata?: { [key: string]: string; }; + MetadataDirective?: string; + RequestPayer?: string; + SSECustomerAlgorithm?: string; + SSECustomerKey?: any; + SSECustomerKeyMD5?: string; + SSEKMSKeyId?: string; + ServerSideEncryption?: string; + StorageClass?: string; + WebsiteRedirectLocation?: string; + } + export interface GetObjectRequest { Bucket: string; IfMatch?: string; diff --git a/aws-serverless-express/aws-serverless-express-tests.ts b/aws-serverless-express/aws-serverless-express-tests.ts new file mode 100644 index 00000000000000..6a0d7694d9123c --- /dev/null +++ b/aws-serverless-express/aws-serverless-express-tests.ts @@ -0,0 +1,29 @@ +/// +/// + +import * as awsServerlessExpress from 'aws-serverless-express'; +import * as express from 'express'; + +const app = express(); +const server = awsServerlessExpress.createServer(app, () => {}); + +const mockEvent = { + key: 'value' +}; + +const mockContext = { + callbackWaitsForEmptyEventLoop: true, + functionName: 'testFunction', + functionVersion: '1', + invokedFunctionArn: 'arn', + memoryLimitInMB: 128, + awsRequestId: 'id', + logGroupName: 'group', + logStreamName: 'stream', + getRemainingTimeInMillis: () => 2000, + done: () => false, + fail: (error: any) => false, + succeed: (message: string) => false +}; + +awsServerlessExpress.proxy(server, mockEvent, mockContext); diff --git a/aws-serverless-express/aws-serverless-express.d.ts b/aws-serverless-express/aws-serverless-express.d.ts new file mode 100644 index 00000000000000..50aa0e1a0bd267 --- /dev/null +++ b/aws-serverless-express/aws-serverless-express.d.ts @@ -0,0 +1,24 @@ +// Type definitions for aws-serverless-express +// Project: https://github.com/awslabs/aws-serverless-express +// Definitions by: Ben Speakman +// Definitions: https://github.com/DefinitelyTyped/DefinitelyTyped + +/// +/// + +declare module 'aws-serverless-express' { + + import * as http from 'http'; + import * as lambda from 'aws-lambda'; + + export function createServer( + requestListener: (request: http.IncomingMessage, response: http.ServerResponse) => http.Server, + serverListenCallback?: () => any + ): http.Server; + + export function proxy( + server: http.Server, + event: any, + context: lambda.Context + ): void; +} diff --git a/axios/axios-tests.ts b/axios/axios-tests.ts index 50e2388624a6c0..f3d5930a2f80b7 100644 --- a/axios/axios-tests.ts +++ b/axios/axios-tests.ts @@ -69,6 +69,10 @@ axios.post("http://example.com/", { ] }); +var config: Axios.AxiosXHRConfigBase = {headers: {}}; +config.headers['X-Custom-Header'] = 'baz'; +axios.post("http://example.com/", config); + var getRepoIssue = axios.get("https://api.github.com/repos/mzabriskie/axios/issues/1"); var axiosInstance = axios.create({ diff --git a/axios/axios.d.ts b/axios/axios.d.ts index 9c4705d0936c22..a2c5bfbd458d35 100644 --- a/axios/axios.d.ts +++ b/axios/axios.d.ts @@ -39,7 +39,7 @@ declare namespace Axios { /** * custom headers to be sent */ - headers?: Object; + headers?: {[key: string]: any}; /** * URL parameters to be sent with the request diff --git a/bases/bases-tests.ts b/bases/bases-tests.ts new file mode 100644 index 00000000000000..5414b1876498cf --- /dev/null +++ b/bases/bases-tests.ts @@ -0,0 +1,10 @@ +/// +import * as bases from 'bases'; + +let bs16String: string = bases.toBase(200, 16); // => 'c8' +let bs62String: string = bases.toBase(99999, 62); // => 'q0T' +let customBaseString: string = bases.toAlphabet(300, 'aAbBcC'); // => 'Abba' + +let frombs16Int: number = bases.fromBase('c8', 16); // => 200 +let frombs62Int: number = bases.fromBase('q0T', 62); // => 99999 +let customBaseInt: number = bases.fromAlphabet('Abba', 'aAbBcC'); // => 300 diff --git a/bases/bases.d.ts b/bases/bases.d.ts new file mode 100644 index 00000000000000..2e62cf685aca82 --- /dev/null +++ b/bases/bases.d.ts @@ -0,0 +1,22 @@ +// Type definitions for bases 0.2.1 +// Project: https://github.com/aseemk/bases.js +// Definitions by: Hari Krishna +// Definitions: https://github.com/DefinitelyTyped/DefinitelyTyped + +declare module "bases" { + export function toAlphabet(num: number, alphabet: string): string; + + export function fromAlphabet(str: string, alphabet: string): number; + + export function toBase(num: number, base: number): string; + + export function fromBase(str: string, base:number): number; + + export let KNOWN_ALPHABETS: any; + + export let NUMERALS: string; + + export let LETTERS_LOWERCASE: string; + + export let LETTERS_UPPERCASE: string; +} diff --git a/billplz/billplz-tests.ts b/billplz/billplz-tests.ts new file mode 100644 index 00000000000000..4f0e4633a2eb1c --- /dev/null +++ b/billplz/billplz-tests.ts @@ -0,0 +1,46 @@ +/// + +import * as Billplz from 'billplz'; + +const billplz = new Billplz({ + key: 'your-api-key', + endpoint: 'http://localhost/', + sandbox: true +}); + +// test create collection +billplz.create_collection({ + title: 'your-title' +}); + +// test create open collection +billplz.create_collectionOpen({ + title: 'your-title', + description: 'your-description', + amount: 100 +}); + +// test create bill +billplz.create_bill({ + collection_id: 'your-collection-id', + description: 'your-description', + email: 'your-email', + mobile: 12345, + name: 'your-name', + amount: 100, + callback_url: 'https://example.com/webhook/', + redirect_url: 'https://example.com/done', + due_at: '0000-00-00' +}); + +// test get bill +billplz.get_bill('your-bill-id'); + +// test delete bill +billplz.delete_bill('your-bill-id'); + +// test change collection status +billplz.change_collection_status('your-collection-id', 'status-here'); + +// test registration check +billplz.registration_check('your-bank-account-number'); diff --git a/billplz/billplz.d.ts b/billplz/billplz.d.ts new file mode 100644 index 00000000000000..53355f280b705b --- /dev/null +++ b/billplz/billplz.d.ts @@ -0,0 +1,80 @@ +// Type definitions for billplz 1.0.2 +// Project: https://github.com/suhz/node-billplz +// Definitions by: Akim +// Definitions: https://github.com/DefinitelyTyped/DefinitelyTyped + +declare module Billplz { + // api options type + interface BillplzOptions { + key: string; + endpoint?: string; + sandbox?: boolean; + } + + // collection type + interface CollectionArguments { + title: string; + } + + // open collection type + interface OpenCollectionArguments { + title: string; + description: string; + amount: number; + fixed_amount?: boolean; + fixed_quantity?: boolean; + payment_button?: string; + reference_1_label?: string + reference_2_label?: string; + email_link?: string; + tax?: number; + } + + // bill type + interface BillArguments { + collection_id: string; + email: string; + mobile: number; + name: string; + amount: number; + callback_url: string; + description: string; + due_at?: string; + redirect_url?: string; + deliver?: boolean; + reference_1_label?: string; + reference_1?: string; + reference_2_label?: string; + reference_2?: string; + } +} + +declare class Billplz { + // constructor + constructor(options: string | Billplz.BillplzOptions); + + // create_collection + create_collection(title: Billplz.CollectionArguments, callback?: (res: any, err: any) => void): void; + + // create collectionOpen + create_collectionOpen(args: Billplz.OpenCollectionArguments, callback?: (res: any, err: any) => void): void; + + // create bill + create_bill(args: Billplz.BillArguments, callback?: (res: any, err: any) => void): void; + + // get bill + get_bill(billId: string, callback?: (res: any, err: any) => void): void; + + // delete bill + delete_bill(billId: string, callback?: (res: any, err: any) => void): void; + + // change_collection status + change_collection_status(collectionId: string, status: string, callback?: (res: any, err: any) => void): void; + + // registration check + registration_check(bankAccountNumber: string, callback?: (res: any, err: any) => void): void; +} + +declare module "billplz" { + export = Billplz; +} diff --git a/bluebird/bluebird-tests.ts b/bluebird/bluebird-tests.ts index d7995438c1c111..318e6f8a4c55c6 100644 --- a/bluebird/bluebird-tests.ts +++ b/bluebird/bluebird-tests.ts @@ -338,6 +338,29 @@ fooOrBarProm = fooProm.caught(Promise.CancellationError, (reason: any) => { // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +{ + class CustomError extends Error { + public customField: number; + } + fooProm = fooProm.catch(CustomError, reason => { + let a: number = reason.customField + }) +} + +{ + class CustomErrorWithConstructor extends Error { + constructor(public arg1: boolean, public arg2: number) { + super(); + }; + } + fooProm = fooProm.catch(CustomErrorWithConstructor, reason => { + let a: boolean = reason.arg1; + let b: number = reason.arg2; + }) +} + +// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + barProm = fooProm.error((reason: any) => { return bar; }); diff --git a/bluebird/bluebird.d.ts b/bluebird/bluebird.d.ts index 3dc66b78f0b868..ca8acb2446065f 100644 --- a/bluebird/bluebird.d.ts +++ b/bluebird/bluebird.d.ts @@ -71,14 +71,19 @@ class Bluebird implements Bluebird.Thenable, Bluebird.Inspection { */ catch(predicate: (error: any) => boolean, onReject: (error: any) => R | Bluebird.Thenable | void | Bluebird.Thenable): Bluebird; caught(predicate: (error: any) => boolean, onReject: (error: any) => R | Bluebird.Thenable | void | Bluebird.Thenable): Bluebird; + catch(predicate: (error: any) => boolean, onReject: (error: any) => U | Bluebird.Thenable): Bluebird; caught(predicate: (error: any) => boolean, onReject: (error: any) => U | Bluebird.Thenable): Bluebird; - catch(ErrorClass: Function, onReject: (error: any) => R | Bluebird.Thenable | void | Bluebird.Thenable): Bluebird; - caught(ErrorClass: Function, onReject: (error: any) => R | Bluebird.Thenable | void | Bluebird.Thenable): Bluebird; - catch(ErrorClass: Function, onReject: (error: any) => U | Bluebird.Thenable): Bluebird; - caught(ErrorClass: Function, onReject: (error: any) => U | Bluebird.Thenable): Bluebird; + + catch(ErrorClass: new (...args: any[]) => E, onReject: (error: E) => R | Bluebird.Thenable | void | Bluebird.Thenable): Bluebird; + caught(ErrorClass: new (...args: any[]) => E, onReject: (error: E) => R | Bluebird.Thenable | void | Bluebird.Thenable): Bluebird; + + catch(ErrorClass: new (...args: any[]) => E, onReject: (error: E) => U | Bluebird.Thenable): Bluebird; + caught(ErrorClass: new (...args: any[]) => E, onReject: (error: E) => U | Bluebird.Thenable): Bluebird; + catch(predicate: Object, onReject: (error: any) => R | Bluebird.Thenable | void | Bluebird.Thenable): Bluebird; caught(predicate: Object, onReject: (error: any) => R | Bluebird.Thenable | void | Bluebird.Thenable): Bluebird; + catch(predicate: Object, onReject: (error: any) => U | Bluebird.Thenable): Bluebird; caught(predicate: Object, onReject: (error: any) => U | Bluebird.Thenable): Bluebird; diff --git a/bonjour/bonjour-tests.ts b/bonjour/bonjour-tests.ts new file mode 100644 index 00000000000000..b97794b0718302 --- /dev/null +++ b/bonjour/bonjour-tests.ts @@ -0,0 +1,21 @@ +/// +import * as bonjour from 'bonjour'; + +var bonjourOptions: bonjour.BonjourOptions; +var bonjourInstance: bonjour.Bonjour; + +var serviceOptions: bonjour.ServiceOptions; +var service: bonjour.Service; + +var browserOptions: bonjour.BrowserOptions; +var browser: bonjour.Browser; + +bonjourOptions = { interface: '192.168.1.1', port: 5353 }; +bonjourInstance = new bonjour.Bonjour(bonjourOptions); + +serviceOptions = { name: 'My Web Server', type: 'http', port: 3000 }; +service = bonjourInstance.publish(serviceOptions); + +browserOptions = { protocol: 'tcp', type: 'http' }; +browser = bonjour.find(browserOptions); + diff --git a/bonjour/bonjour.d.ts b/bonjour/bonjour.d.ts new file mode 100644 index 00000000000000..0ffd9f1171be95 --- /dev/null +++ b/bonjour/bonjour.d.ts @@ -0,0 +1,71 @@ +// Type definitions for bonjour v3.5.0 +// Project: https://github.com/watson/bonjour +// Definitions by: Quentin Lampin +// Definitions: https://github.com/DefinitelyTyped/DefinitelyTyped + +declare module "bonjour" { + export interface BonjourOptions { + multicast?: boolean; + interface?: string; + port?: number; + ip?: string; + ttl?: number; + loopback?: boolean; + reuseAddr?: boolean; + } + + export interface BrowserOptions { + type?: string; + subtypes?: string[]; + protocol?: string; + txt?: Object; + } + + export interface ServiceOptions { + name: string; + host?: string; + port: number; + type: string; + subtypes?: string[]; + protocol?: 'udp'|'tcp'; + txt?: Object; + } + + export interface Service { + name: string; + type: string; + subtypes: string[]; + protocol: string; + host: string; + port: number; + fqdn: string; + rawTxt: Object; + txt: Object; + published: boolean; + + stop: (cb: ()=>any) => void; + start: () => void; + } + + export class Bonjour { + + constructor(opts: BonjourOptions); + publish(options: ServiceOptions):Service; + unpublishAll(cb: ()=>any): void; + find(options:BrowserOptions, onUp: ()=>any): Browser; + findOne(options:any, cb: (service: Service)=>any): Browser; + destroy():void; + } + + export class Browser { + services: Service[]; + + start():void; + update():void; + stop():void; + } + + export function find(options: BrowserOptions, onUp?: ()=>any): Browser; + export function findOne(options: BrowserOptions): Browser; + +} diff --git a/bootbox/bootbox.d.ts b/bootbox/bootbox.d.ts index c94b60625f1597..7ef20b38e7ad9d 100644 --- a/bootbox/bootbox.d.ts +++ b/bootbox/bootbox.d.ts @@ -40,6 +40,7 @@ interface BootboxConfirmOptions extends BootboxDialogOptions { interface BootboxPromptOptions extends BootboxBaseOptions { title: string; value?: string; + inputType?: string; callback: (result: string) => any; buttons?: BootboxConfirmPromptButtonMap; } diff --git a/bootstrap-select/bootstrap-select-tests.ts b/bootstrap-select/bootstrap-select-tests.ts new file mode 100644 index 00000000000000..9758b1c9ed1bfc --- /dev/null +++ b/bootstrap-select/bootstrap-select-tests.ts @@ -0,0 +1,43 @@ +// Bootstrap Select Test +// ================================================================================ +/// +/// + +$(".selectpicker").selectpicker({ + actionsBox: true, + container: "body", + countSelectedText: "counts > #", + deselectAllText: "test", + dropdownAlignRight: true, + dropupAuto: true, + header: "test", + hideDisabled: true, + iconBase: "fa", + liveSearch: true, + liveSearchNormalize: true, + liveSearchPlaceholder: "test", + liveSearchStyle: "contains", + maxOptions: 10, + maxOptionsText: "test", + mobile: true, + multipleSeparator: ", ", + noneSelectedText: "test", + selectAllText: "test", + selectedTextFormat: "values", + selectOnTab: true, + showContent: true, + showIcon: true, + showSubtext: true, + showTick: true, + size: "auto", + style: "test", + tickIcon: "test", + title: "test", + width: "auto" +}) + +$(".selectpicker").selectpicker("val", "foo") +$(".selectpicker").selectpicker("val", ["foo", "bar"]) +$(".selectpicker").selectpicker("selectAll") +$(".selectpicker").selectpicker("setStyle", "btn-large", "add") + diff --git a/bootstrap-select/bootstrap-select.d.ts b/bootstrap-select/bootstrap-select.d.ts new file mode 100644 index 00000000000000..9f1436a624c35b --- /dev/null +++ b/bootstrap-select/bootstrap-select.d.ts @@ -0,0 +1,44 @@ +// Type definitions for bootstrap-select v1.11.2 +// Project: https://silviomoreto.github.io/bootstrap-select/ +// Definitions by: Karol Janyst +// Definitions: https://github.com/DefinitelyTyped/DefinitelyTyped + +/// + +interface BootstrapSelectOptions { + actionsBox?: boolean + container?: string | boolean + countSelectedText?: string | Function + deselectAllText?: string + dropdownAlignRight?: string | boolean + dropupAuto?: boolean + header?: string + hideDisabled?: boolean + iconBase?: string + liveSearch?: boolean + liveSearchNormalize?: boolean + liveSearchPlaceholder?: string + liveSearchStyle?: string + maxOptions?: number | boolean + maxOptionsText?: string | Array | Function + mobile?: boolean + multipleSeparator?: string + noneSelectedText?: string + selectAllText?: string + selectedTextFormat?: string + selectOnTab?: boolean + showContent?: boolean + showIcon?: boolean + showSubtext?: boolean + showTick?: boolean + size?: string | number | boolean + style?: string + tickIcon?: string + title?: string + width?: string | boolean +} + +interface JQuery { + selectpicker(opts?: BootstrapSelectOptions): void + selectpicker(method: string, ...args: Array>): void +} diff --git a/braintree-web/braintree-web-tests.ts b/braintree-web/braintree-web-tests.ts index 9d48e2fd258e82..20fd0219f1d33c 100644 --- a/braintree-web/braintree-web-tests.ts +++ b/braintree-web/braintree-web-tests.ts @@ -53,8 +53,15 @@ braintree.client.create({ selector: '#cvv', type: 'password' }, - expirationDate: { - selector: '#expiration-date' + expirationMonth: { + selector: '#expiration-month', + select: { + options: ["01 - Jan", "02 - Feb", "03 - Mar", "04 - Apr", "05 - May", "06 - Jun", "07 - Jul", "08 - Aug", "09 - Sep", "10 - Oct", "11 - Nov", "12 - Dec"] + } + }, + expirationYear: { + selector: '#expiration-year', + select: true } } }, function (hostedFieldsErr?: BraintreeError, hostedFieldsInstance?: any) { diff --git a/braintree-web/braintree-web.d.ts b/braintree-web/braintree-web.d.ts index 4f684c62999814..e58cf7455b3478 100644 --- a/braintree-web/braintree-web.d.ts +++ b/braintree-web/braintree-web.d.ts @@ -1,4 +1,4 @@ -// Type definitions for Braintree-web v3.3.0 +// Type definitions for Braintree-web v3.5.0 // Project: https://github.com/braintree/braintree-web // Definitions by: Guy Shahine // Definitions: https://github.com/DefinitelyTyped/DefinitelyTyped @@ -541,13 +541,16 @@ declare namespace BraintreeWeb { * @property {string} selector A CSS selector to find the container where the hosted field will be inserted. * @property {string} [placeholder] Will be used as the `placeholder` attribute of the input. If `placeholder` is not natively supported by the browser, it will be polyfilled. * @property {string} [type] Will be used as the `type` attribute of the input. To mask `cvv` input, for instance, `type: "password"` can be used. - * @property {boolean} [formatInput=true] - Enable or disable automatic formatting on this field. Note: Input formatting does not work properly on Android and iOS, so input formatting is automatically disabled on those browsers. + * @property {boolean} [formatInput=true] - Enable or disable automatic formatting on this field. + * @property {object|boolean} [select] If truthy, this field becomes a `') .appendTo( @@ -539,7 +542,7 @@ $(document).ready(function () { .cache('search') .sort() .unique() - .each(function (d) { + .each(function (d: any) { select.append($('')); }); }); @@ -623,7 +626,7 @@ $(document).ready(function () { .cache('search') .sort() .unique() - .each(function (d) { + .each(function (d: any) { select.append($('')); }); @@ -632,7 +635,7 @@ $(document).ready(function () { dt .column(4) .data() - .reduce(function (a, b) { + .reduce(function (a: any, b: any) { return a + b; }) ); @@ -688,7 +691,7 @@ $(document).ready(function () { .draw(); }); - dt.columns('.select-filter').eq(0).each(function (colIdx) { + dt.columns('.select-filter').eq(0).each(function (colIdx: any) { // Create the select list and search operation var select = $(' + + + Label before} + labelPosition="before" + primary={true} + style={styles.button} + icon={} + /> + + } + /> + + +); + +const FlatButtonExampleIcon = () => ( +
+ } + style={style} + /> + } + style={style} + /> + } + style={style} + /> +
+); + + +// "http://www.material-ui.com/#/components/raised-button" +const RaisedButtonExampleSimple = () => ( +
+ + + + +
+); + +const RaisedButtonExampleComplex = () => ( +
+ + + + Label before} + labelPosition="before" + primary={true} + icon={} + style={styles.button} + /> + } + /> +
+); + +const RaisedButtonExampleIcon = () => ( +
+ } + style={style} + /> + } + style={style} + /> + } + style={style} + /> +
+); + + +// "http://www.material-ui.com/#/components/floating-action-button" +const FloatingActionButtonExampleSimple = () => ( +
+ + + + + + + + + + + + + + + + + + + + + + + +
+); + + +// "http://www.material-ui.com/#/components/icon-button" +const IconButtonExampleSimple = () => ( +
+ + +
+); + +const IconButtonExampleComplex = () => ( +
+ + + + + + + + + + home + +
+); + +const IconButtonExampleSize = () => ( +
+ + + + + + + + + + + + + + + +
+); + +const IconButtonExampleTooltip = () => ( +
+ + + + + + +
+); + +const IconButtonExampleTouch = () => ( +
+ + + + + + + + + + + + + + + + + + +
+); + + +// "http://www.material-ui.com/#/components/card" +const CardExampleWithAvatar = () => ( + + + } + > + + + + + Lorem ipsum dolor sit amet, consectetur adipiscing elit. + Donec mattis pretium massa. Aliquam erat volutpat. Nulla facilisi. + Donec vulputate interdum sollicitudin. Nunc lacinia auctor quam sed pellentesque. + Aliquam dui mauris, mattis quis lacus id, pellentesque lobortis odio. + + + + + + +); + +const CardExampleWithoutAvatar = () => ( + + + + Lorem ipsum dolor sit amet, consectetur adipiscing elit. + Donec mattis pretium massa. Aliquam erat volutpat. Nulla facilisi. + Donec vulputate interdum sollicitudin. Nunc lacinia auctor quam sed pellentesque. + Aliquam dui mauris, mattis quis lacus id, pellentesque lobortis odio. + + + + + + +); + +class CardExampleControlled extends React.Component<{}, {expanded: boolean}> { + + constructor(props) { + super(props); + this.state = { + expanded: false, + }; + } + + handleExpandChange = (expanded) => { + this.setState({expanded: expanded}); + }; + + handleToggle = (event, toggle) => { + this.setState({expanded: toggle}); + }; + + handleExpand = () => { + this.setState({expanded: true}); + }; + + handleReduce = () => { + this.setState({expanded: false}); + }; + + render() { + return ( + + + + + + } + > + + + + + Lorem ipsum dolor sit amet, consectetur adipiscing elit. + Donec mattis pretium massa. Aliquam erat volutpat. Nulla facilisi. + Donec vulputate interdum sollicitudin. Nunc lacinia auctor quam sed pellentesque. + Aliquam dui mauris, mattis quis lacus id, pellentesque lobortis odio. + + + + + + + ); + } +} + +// "http://www.material-ui.com/#/components/chip" +const ChipExampleSimple = () => ( +
+ Basic Chip + Blue Background + Blue Label Color + UI Avatar + Styled +
+); + +class ChipExampleComplex extends React.Component<{}, {}>{ + handleRequestDelete = () => { + alert('You clicked the delete button.'); + } + + handleTouchTap = () => { + alert('You clicked the Chip.'); + } + + render() { + return ( +
+ Click Me +
+ ); + } +} + + +// "http://www.material-ui.com/#/components/date-picker" +const DatePickerExampleSimple = () => ( +
+ + + +
+); + +const DatePickerExampleInline = () => ( +
+ + +
+); + +const optionsStyle = { + maxWidth: 255, + marginRight: 'auto', +}; + +interface DatePickerExampleToggleState { + minDate?: Date; + maxDate?: Date; + autoOk?: boolean; + disableYearSelection?: boolean; +} + +class DatePickerExampleToggle extends React.Component<{}, DatePickerExampleToggleState> { + constructor(props) { + super(props); + + const minDate = new Date(); + const maxDate = new Date(); + minDate.setFullYear(minDate.getFullYear() - 1); + minDate.setHours(0, 0, 0, 0); + maxDate.setFullYear(maxDate.getFullYear() + 1); + maxDate.setHours(0, 0, 0, 0); + + this.state = { + minDate: minDate, + maxDate: maxDate, + autoOk: false, + disableYearSelection: false, + }; + } + + handleChangeMinDate = (event, date) => { + this.setState({ + minDate: date, + }); + }; + + handleChangeMaxDate = (event, date) => { + this.setState({ + maxDate: date, + }); + }; + + handleToggle = (event, toggled) => { + this.setState({ + [event.target.name]: toggled, + }); + }; + + render() { + return ( +
+ +
+ + + + +
+
+ ); + } +} + +class DatePickerExampleControlled extends React.Component<{}, {controlledDate?: Date}> { + + constructor(props) { + super(props); + + this.state = { + controlledDate: null, + }; + } + + handleChange = (event, date) => { + this.setState({ + controlledDate: date, + }); + }; + + render() { + return ( + + ); + } +} + +function disableWeekends(date) { + return date.getDay() === 0 || date.getDay() === 6; +} +function disableRandomDates() { + return Math.random() > 0.7; +} +const DatePickerExampleDisableDates = () => ( +
+ + +
+); + +let DateTimeFormat = new Intl.DateTimeFormat('fr'); +const DatePickerExampleInternational = () => ( +
+ + + +
+); + + + +// "http://material-ui.com/#/components/dialog" +class DialogExampleSimple extends React.Component<{}, {open?: boolean}> { + state = { + open: false, + }; + + handleOpen = () => { + this.setState({open: true}); + }; + + handleClose = () => { + this.setState({open: false}); + }; + + render() { + const actions = [ + , + , + ]; + + return ( +
+ + + The actions in this window were passed in as an array of React objects. + +
+ ); + } +} + +class DialogExampleModal extends React.Component<{}, {open?: boolean}> { + state = { + open: false, + }; + + handleOpen = () => { + this.setState({open: true}); + }; + + handleClose = () => { + this.setState({open: false}); + }; + + render() { + const actions = [ + , + , + ]; + + return ( +
+ + + Only actions can close this dialog. + +
+ ); + } +} + +class DialogExampleCustomWidth extends React.Component<{}, {open?: boolean}> { + state = { + open: false, + }; + + handleOpen = () => { + this.setState({open: true}); + }; + + handleClose = () => { + this.setState({open: false}); + }; + + render() { + const actions = [ + , + , + ]; + + return ( +
+ + + This dialog spans the entire width of the screen. + +
+ ); + } +} + +class DialogExampleDialogDatePicker extends React.Component<{}, {open?: boolean}> { + state = { + open: false, + }; + + handleOpen = () => { + this.setState({open: true}); + }; + + handleClose = () => { + this.setState({open: false}); + }; + + render() { + const actions = [ + , + ]; + + return ( +
+ + + Open a Date Picker dialog from within a dialog. + + +
+ ); + } +} + +class DialogExampleScrollable extends React.Component<{}, {open?: boolean}> { + state = { + open: false, + }; + + handleOpen = () => { + this.setState({open: true}); + }; + + handleClose = () => { + this.setState({open: false}); + }; + + render() { + const actions = [ + , + , + ]; + + const radios = []; + for (let i = 0; i < 30; i++) { + radios.push( + + ); + } + + return ( +
+ + + + {radios} + + +
+ ); + } +} + +class DialogExampleAlert extends React.Component<{}, {open?: boolean}> { + state = { + open: false, + }; + + handleOpen = () => { + this.setState({open: true}); + }; + + handleClose = () => { + this.setState({open: false}); + }; + + render() { + const actions = [ + , + , + ]; + + return ( +
+ + + Discard draft? + +
+ ); + } +} + + +// "http://www.material-ui.com/#/components/divider" +const DividerExampleForm = () => ( + + + + + + + + + + +); + +const DividerExampleList = () => ( + + + + + + + + + + + +); + +const DividerExampleMenu = () => ( + + + + + + +); + + +// "http://www.material-ui.com/#/components/drawer" +class DrawerSimpleExample extends React.Component<{}, {open?: boolean}> { + + constructor(props) { + super(props); + this.state = {open: false}; + } + + handleToggle = () => this.setState({open: !this.state.open}); + + render() { + return ( +
+ + + Menu Item + Menu Item 2 + +
+ ); + } +} + +class DrawerUndockedExample extends React.Component<{}, {open?: boolean}> { + + constructor(props) { + super(props); + this.state = {open: false}; + } + + handleToggle = () => this.setState({open: !this.state.open}); + + handleClose = () => this.setState({open: false}); + + render() { + return ( +
+ + this.setState({open})} + > + Menu Item + Menu Item 2 + +
+ ); + } +} + +class DrawerOpenRightExample extends React.Component<{}, {open?: boolean}> { + + constructor(props) { + super(props); + this.state = {open: false}; + } + + handleToggle = () => this.setState({open: !this.state.open}); + + render() { + return ( +
+ + + + +
+ ); + } +} + + +// "http://www.material-ui.com/#/components/grid-list" +const tilesData: {img: string, title: string, author: string, featured?: boolean}[] = [ + { + img: 'images/grid-list/00-52-29-429_640.jpg', + title: 'Breakfast', + author: 'jill111', + featured: true, + }, + { + img: 'images/grid-list/burger-827309_640.jpg', + title: 'Tasty burger', + author: 'pashminu', + }, + { + img: 'images/grid-list/camera-813814_640.jpg', + title: 'Camera', + author: 'Danson67', + }, + { + img: 'images/grid-list/morning-819362_640.jpg', + title: 'Morning', + author: 'fancycrave1', + }, + { + img: 'images/grid-list/hats-829509_640.jpg', + title: 'Hats', + author: 'Hans', + }, + { + img: 'images/grid-list/honey-823614_640.jpg', + title: 'Honey', + author: 'fancycravel', + }, + { + img: 'images/grid-list/vegetables-790022_640.jpg', + title: 'Vegetables', + author: 'jill111', + }, + { + img: 'images/grid-list/water-plant-821293_640.jpg', + title: 'Water plant', + author: 'BkrmadtyaKarki', + }, +]; + +const GridListExampleSimple = () => ( +
+ + December + {tilesData.map((tile) => ( + by {tile.author}} + actionIcon={} + > + + + ))} + +
+); + +const GridListExampleComplex = () => ( +
+ + {tilesData.map((tile) => ( + } + actionPosition="left" + titlePosition="top" + titleBackground="linear-gradient(to bottom, rgba(0,0,0,0.7) 0%,rgba(0,0,0,0.3) 70%,rgba(0,0,0,0) 100%)" + cols={tile.featured ? 2 : 1} + rows={tile.featured ? 2 : 1} + > + + + ))} + +
+); + + +// "http://www.material-ui.com/#/components/font-icon" +const FontIconExampleSimple = () => ( +
+ + + + + +
+); + +const FontIconExampleIcons = () => ( +
+ home + flight_takeoff + cloud_download + videogame_asset +
+); + + +// "http://www.material-ui.com/#/components/svg-icon" +const HomeIcon = (props) => ( + + + +); + +const SvgIconExampleSimple = () => ( +
+ + + +
+); + +const SvgIconExampleIcons = () => ( +
+ + + + +
+); + + +// "http://material-ui.com/#/components/lists" +const ListExampleSimple = () => ( + + + } /> + } /> + } /> + } /> + } /> + + + + } /> + } /> + } /> + } /> + + +); + +const ListExampleChat = () => ( + + + Recent chats + } + rightIcon={} + /> + } + rightIcon={} + /> + } + rightIcon={} + /> + } + rightIcon={} + /> + } + rightIcon={} + /> + + + + Previous chats + } + /> + } + /> + + +); + +const ListExampleContacts = () => ( + + + } + rightAvatar={} + /> + } + /> + } + /> + } + /> + + + + + A + + } + rightAvatar={} + /> + } + /> + } + /> + } + /> + + +); + +const ListExampleFolder = () => ( + + + Folders + } />} + rightIcon={} + primaryText="Photos" + secondaryText="Jan 9, 2014" + /> + } />} + rightIcon={} + primaryText="Recipes" + secondaryText="Jan 17, 2014" + /> + } />} + rightIcon={} + primaryText="Work" + secondaryText="Jan 28, 2014" + /> + + + + Files + } backgroundColor={blue500} />} + rightIcon={} + primaryText="Vacation itinerary" + secondaryText="Jan 20, 2014" + /> + } backgroundColor={yellow600} />} + rightIcon={} + primaryText="Kitchen remodel" + secondaryText="Jan 10, 2014" + /> + + +); + +const ListExampleNested = () => ( + + + Nested List Items + } /> + } /> + } + initiallyOpen={true} + primaryTogglesNestedList={true} + nestedItems={[ + } + />, + } + disabled={true} + nestedItems={[ + } />, + ]} + />, + ]} + /> + + +); + +const ListExampleSettings = () => ( +
+ + + General + + + + + + Hangout Notifications + } + primaryText="Notifications" + secondaryText="Allow notifications" + /> + } + primaryText="Sounds" + secondaryText="Hangouts message" + /> + } + primaryText="Video sounds" + secondaryText="Hangouts video call" + /> + + + + + + + + + Priority Interruptions + } /> + } /> + } /> + + + + Hangout Notifications + } /> + } /> + } /> + + +
+); + +const ListExamplePhone = () => ( + + + } + rightIcon={} + primaryText="(650) 555 - 1234" + secondaryText="Mobile" + /> + } + primaryText="(323) 555 - 6789" + secondaryText="Work" + /> + + + + } + primaryText="aliconnors@example.com" + secondaryText="Personal" + /> + + + +); + +const iconButtonElement = ( + + + +); + +const rightIconMenu = ( + + Reply + Forward + Delete + +); + +const ListExampleMessages = () => ( +
+ + + Today + } + primaryText="Brunch this weekend?" + secondaryText={ +

+ Brendan Lim -- + I'll be in your neighborhood doing errands this weekend. Do you want to grab brunch? +

+ } + secondaryTextLines={2} + /> + + } + primaryText={ +

Summer BBQ  4

+ } + secondaryText={ +

+ to me, Scott, Jennifer -- + Wish I could come, but I'm out of town this weekend. +

+ } + secondaryTextLines={2} + /> + + } + primaryText="Oui oui" + secondaryText={ +

+ Grace Ng -- + Do you have Paris recommendations? Have you ever been? +

+ } + secondaryTextLines={2} + /> + + } + primaryText="Birdthday gift" + secondaryText={ +

+ Kerem Suer -- + Do you have any ideas what we can get Heidi for her birthday? How about a pony? +

+ } + secondaryTextLines={2} + /> + + } + primaryText="Recipe to try" + secondaryText={ +

+ Raquel Parrado -- + We should eat this: grated squash. Corn and tomatillo tacos. +

+ } + secondaryTextLines={2} + /> +
+
+ + + Today + } + rightIconButton={rightIconMenu} + primaryText="Brendan Lim" + secondaryText={ +

+ Brunch this weekend?
+ I'll be in your neighborhood doing errands this weekend. Do you want to grab brunch? +

+ } + secondaryTextLines={2} + /> + + } + rightIconButton={rightIconMenu} + primaryText="me, Scott, Jennifer" + secondaryText={ +

+ Summer BBQ
+ Wish I could come, but I'm out of town this weekend. +

+ } + secondaryTextLines={2} + /> + + } + rightIconButton={rightIconMenu} + primaryText="Grace Ng" + secondaryText={ +

+ Oui oui
+ Do you have any Paris recs? Have you ever been? +

+ } + secondaryTextLines={2} + /> + + } + rightIconButton={rightIconMenu} + primaryText="Kerem Suer" + secondaryText={ +

+ Birthday gift
+ Do you have any ideas what we can get Heidi for her birthday? How about a pony? +

+ } + secondaryTextLines={2} + /> + + } + rightIconButton={rightIconMenu} + primaryText="Raquel Parrado" + secondaryText={ +

+ Recipe to try
+ We should eat this: grated squash. Corn and tomatillo tacos. +

+ } + secondaryTextLines={2} + /> +
+
+
+); + +function wrapState(ComposedComponent: React.ComponentClass<__MaterialUI.List.SelectableProps>) { + return class SelectableList extends Component<{defaultValue: number}, {selectedIndex: number}> { + static propTypes = { + children: PropTypes.node.isRequired, + defaultValue: PropTypes.number.isRequired, + }; + + componentWillMount() { + this.setState({ + selectedIndex: this.props.defaultValue, + }); + } + + handleRequestChange = (event, index) => { + this.setState({ + selectedIndex: index, + }); + }; + + render() { + return ( + + {this.props.children} + + ); + } + }; +} + +let SelectableList = wrapState(MakeSelectable(List)); + +const ListExampleSelectable = () => ( + + + Selectable Contacts + } + nestedItems={[ + } + />, + ]} + /> + } + /> + } + /> + } + /> + + +); + + +// "http://www.material-ui.com/#/components/menu" +const MenuExampleSimple = () => ( +
+ + + + + + + + + + + + + + + + +
+); + +const MenuExampleDisable = () => ( +
+ + + + + + + + + + + + + + + + + + + + +
+); + +const MenuExampleIcons = () => ( +
+ + + } /> + } /> + } /> + + } /> + } /> + + } /> + + + + + + } /> + settings} /> + settings + } + /> + ¶} /> + §} /> + + +
+); + +const MenuExampleSecondary = () => ( +
+ + + + + + + + + + } /> + } /> + } /> + } /> + } /> + + + + + + + + + + + + + + + + + + +
+); + +const MenuExampleNested = () => ( +
+ + + + + + } + menuItems={[ + } + menuItems={[ + , + , + , + , + ]} + />, + , + , + , + ]} + /> + + + + + + + +
+); + + +// "http://www.material-ui.com/#/components/icon-menu" +const IconMenuExampleSimple = () => ( +
+ } + anchorOrigin={{horizontal: 'left', vertical: 'top'}} + targetOrigin={{horizontal: 'left', vertical: 'top'}} + > + + + + + + + } + anchorOrigin={{horizontal: 'left', vertical: 'bottom'}} + targetOrigin={{horizontal: 'left', vertical: 'bottom'}} + > + + + + + + + } + anchorOrigin={{horizontal: 'right', vertical: 'bottom'}} + targetOrigin={{horizontal: 'right', vertical: 'bottom'}} + > + + + + + + + } + anchorOrigin={{horizontal: 'right', vertical: 'top'}} + targetOrigin={{horizontal: 'right', vertical: 'top'}} + > + + + + + + +
+); + +interface IconMenuExampleControlledState { + valueSingle?: string; + valueMultiple?: string[]; + openMenu?: boolean; +} + +class IconMenuExampleControlled extends React.Component<{}, IconMenuExampleControlledState> { + constructor(props) { + super(props); + + this.state = { + valueSingle: '3', + valueMultiple: ['3', '5'], + }; + } + + handleChangeSingle = (event, value) => { + this.setState({ + valueSingle: value, + }); + }; + + handleChangeMultiple = (event, value) => { + this.setState({ + valueMultiple: value, + }); + }; + + handleOpenMenu = () => { + this.setState({ + openMenu: true, + }); + } + + handleOnRequestChange = (value) => { + this.setState({ + openMenu: value, + }); + } + + render() { + return ( +
+ } + onChange={this.handleChangeSingle} + value={this.state.valueSingle} + > + + + + + + + } + onChange={this.handleChangeMultiple} + value={this.state.valueMultiple} + multiple={true} + > + + + + + + + + } + open={this.state.openMenu} + onRequestChange={this.handleOnRequestChange} + > + + + + + + +
+ ); + } +} + +const IconMenuExampleScrollable = () => ( + } + anchorOrigin={{horizontal: 'left', vertical: 'top'}} + targetOrigin={{horizontal: 'left', vertical: 'top'}} + maxHeight={272} + > + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +); + +const IconMenuExampleNested = () => ( +
+ } + anchorOrigin={{horizontal: 'left', vertical: 'top'}} + targetOrigin={{horizontal: 'left', vertical: 'top'}} + > + } + menuItems={[ + , + , + , + , + ]} + /> + + } + menuItems={[ + , + , + , + , + ]} + /> + + } /> + + + + +
+); + + +// "http://www.material-ui.com/#/components/dropdown-menu" +class DropDownMenuSimpleExample extends React.Component<{}, {value?: number}> { + + constructor(props) { + super(props); + this.state = {value: 1}; + } + + handleChange = (event, index, value) => this.setState({value}); + + render() { + return ( +
+ + + + + + + +
+ + + + + + + +
+ ); + } +} + +class DropDownMenuOpenImmediateExample extends React.Component<{}, {value?: number}> { + + constructor(props) { + super(props); + this.state = {value: 2}; + } + + handleChange = (event, index, value) => this.setState({value}); + + render() { + return ( + + + + + + + + ); + } +} + +const items: React.ReactElement<__MaterialUI.Menus.MenuItemProps>[] = []; +for (let i = 0; i < 100; i++ ) { + items.push(); +} + +class DropDownMenuLongMenuExample extends React.Component<{}, {value?: number}> { + + constructor(props) { + super(props); + this.state = {value: 10}; + } + + handleChange = (event, index, value) => this.setState({value}); + + render() { + return ( + + {items} + + ); + } +} + +class DropDownMenuLabeledExample extends React.Component<{}, {value?: number}> { + + constructor(props) { + super(props); + this.state = {value: 2}; + } + + handleChange = (event, index, value) => this.setState({value}); + + render() { + return ( + + + + + + + ); + } +} + + +// "http://material-ui.com/#/components/paper" +const PaperExampleSimple = () => ( +
+ + + + + +
+); + +const PaperExampleRounded = () => ( +
+ + + + + +
+); + +const PaperExampleCircle = () => ( +
+ + + + + +
+); + + +// "http://www.material-ui.com/#/components/popover" +class PopoverExampleSimple extends React.Component<{}, {open?: boolean, anchorEl?: React.ReactInstance}> { + + constructor(props) { + super(props); + + this.state = { + open: false, + }; + } + + handleTouchTap = (event) => { + // This prevents ghost click. + event.preventDefault(); + + this.setState({ + open: true, + anchorEl: event.currentTarget, + }); + }; + + handleRequestClose = () => { + this.setState({ + open: false, + }); + }; + + render() { + return ( +
+ + + + + + + + + +
+ ); + } +} + +class PopoverExampleAnimation extends React.Component<{}, {open?: boolean, anchorEl?: React.ReactInstance}> { + + constructor(props) { + super(props); + + this.state = { + open: false, + }; + } + + handleTouchTap = (event) => { + // This prevents ghost click. + event.preventDefault(); + this.setState({ + open: true, + anchorEl: event.currentTarget, + }); + }; + + handleRequestClose = () => { + this.setState({ + open: false, + }); + }; + + render() { + return ( +
+ + + + + + + + + +
+ ); + } +} + +interface PopoverExampleConfigurableState { + open?: boolean; + anchorOrigin?: __MaterialUI.propTypes.origin; + targetOrigin?: __MaterialUI.propTypes.origin; + anchorEl?: React.ReactInstance; +} + +class PopoverExampleConfigurable extends React.Component<{}, PopoverExampleConfigurableState> { + + constructor(props) { + super(props); + + this.state = { + open: false, + anchorOrigin: { + horizontal: 'left', + vertical: 'bottom', + }, + targetOrigin: { + horizontal: 'left', + vertical: 'top', + }, + }; + } + + handleTouchTap = (event) => { + // This prevents ghost click. + event.preventDefault(); + this.setState({ + open: true, + anchorEl: event.currentTarget, + }); + }; + + handleRequestClose = () => { + this.setState({ + open: false, + }); + }; + + setAnchor = (positionElement, position) => { + const {anchorOrigin} = this.state; + anchorOrigin[positionElement] = position; + + this.setState({ + anchorOrigin: anchorOrigin, + }); + }; + + setTarget = (positionElement, position) => { + const {targetOrigin} = this.state; + targetOrigin[positionElement] = position; + + this.setState({ + targetOrigin: targetOrigin, + }); + }; + + render() { + return ( +
+ +

Current Settings

+
+          anchorOrigin: {JSON.stringify(this.state.anchorOrigin)}
+          
+ targetOrigin: {JSON.stringify(this.state.targetOrigin)} +
+

Position Options

+

Use the settings below to toggle the positioning of the popovers above

+

Anchor Origin

+
+
+ Vertical + + + +
+
+ Horizontal + + + +
+
+

Target Origin

+
+
+ Vertical + + + +
+
+ Horizontal + + + +
+
+ + + + + + + + +
+ ); + } +} + + +// "http://www.material-ui.com/#/components/circular-progress" +const CircularProgressExampleSimple = () => ( +
+ + + +
+); + +class CircularProgressExampleDeterminate extends React.Component<{}, {completed?: number}> { + private timer: number; + + constructor(props) { + super(props); + + this.state = { + completed: 0, + }; + } + + componentDidMount() { + this.timer = setTimeout(() => this.progress(5), 1000); + } + + componentWillUnmount() { + clearTimeout(this.timer); + } + + progress(completed) { + if (completed > 100) { + this.setState({completed: 100}); + } else { + this.setState({completed}); + const diff = Math.random() * 10; + this.timer = setTimeout(() => this.progress(completed + diff), 1000); + } + } + + render() { + return ( +
+ + + +
+ ); + } +} + + +// "http://www.material-ui.com/#/components/linear-progress" +const LinearProgressExampleSimple = () => ( + +); + +class LinearProgressExampleDeterminate extends React.Component<{}, {completed?: number}> { + private timer: number; + + constructor(props) { + super(props); + + this.state = { + completed: 0, + }; + } + + componentDidMount() { + this.timer = setTimeout(() => this.progress(5), 1000); + } + + componentWillUnmount() { + clearTimeout(this.timer); + } + + progress(completed) { + if (completed > 100) { + this.setState({completed: 100}); + } else { + this.setState({completed}); + const diff = Math.random() * 10; + this.timer = setTimeout(() => this.progress(completed + diff), 1000); + } + } + + render() { + return ( + + ); + } +} + + +// "http://www.material-ui.com/#/components/refresh-indicator" +const RefreshIndicatorExampleSimple = () => ( +
+ + + + +
+); + +const RefreshIndicatorExampleLoading = () => ( +
+ + +
+); + + +// "http://www.material-ui.com/#/components/select-field" +class SelectFieldExampleSimple extends React.Component<{}, {value?: number}> { + + constructor(props) { + super(props); + this.state = {value: 1}; + } + + handleChange = (event, index, value) => this.setState({value}); + + render() { + return ( +
+ + + + + + + +
+ + + + +
+ + + + + + + +
+ + + + + + + +
+ ); + } +} + +class SelectFieldLongMenuExample extends React.Component<{}, {value?: number}> { + + constructor(props) { + super(props); + this.state = {value: 10}; + } + + handleChange = (event, index, value) => this.setState({value}); + + render() { + return ( + + {items} + + ); + } +} + +class SelectFieldExampleCustomLabel extends React.Component<{}, {value?: number}> { + + constructor(props) { + super(props); + this.state = {value: 1}; + } + + handleChange = (event, index, value) => this.setState({value}); + + render() { + return ( + + + + + + + ); + } +} + +const itemsPeriod = [ + , + , + , + , + , +]; + +export default class SelectFieldExampleFloatingLabel extends React.Component<{}, {value?: number}> { + + constructor(props) { + super(props); + this.state = {value: null}; + } + + handleChange = (event, index, value) => this.setState({value}); + + render() { + return ( +
+ + {itemsPeriod} + +
+ + {itemsPeriod} + +
+ ); + } +} + +class SelectFieldExampleError extends React.Component<{}, {value?: number}> { + + constructor(props) { + super(props); + this.state = {value: null}; + } + + handleChange = (event, index, value) => this.setState({value}); + + render() { + const {value} = this.state; + + const night = value === 2 || value === 3; + + return ( +
+ + {itemsPeriod} + +
+ + {itemsPeriod} + +
+ ); + } +} + + +// "http://www.material-ui.com/#/components/slider" +const SliderExampleSimple = () => ( +
+ + + +
+); + +const SliderExampleDisabled = () => ( +
+ + + +
+); + +const SliderExampleStep = () => ( + +); + +class SliderExampleControlled extends React.Component<{}, {firstSlider?: number, secondSlider?: number}> { + + state = { + firstSlider: 0.5, + secondSlider: 50, + } + + handleFirstSlider(event, value) { + this.setState({firstSlider: value}); + } + + handleSecondSlider(event, value) { + this.setState({secondSlider: value}); + } + + render() { + return ( +
+ +

+ {'The value of this slider is: '} + {this.state.firstSlider} + {' from a range of 0 to 1 inclusive'} +

+ +

+ {'The value of this slider is: '} + {this.state.secondSlider} + {' from a range of 0 to 100 inclusive'} +

+
+ ); + } +} + + +// "http://www.material-ui.com/#/components/checkbox" +const CheckboxExampleSimple = () => ( +
+ + + } + uncheckedIcon={} + label="Custom icon" + style={styles.checkbox} + /> + + + +
+); + + +// "http://www.material-ui.com/#/components/radio-button" +const RadioButtonExampleSimple = () => ( +
+ + + + } + uncheckedIcon={} + style={styles.radioButton} + /> + + + + + + + + +
+); + + +// "http://www.material-ui.com/#/components/toggle" +const ToggleExampleSimple = () => ( +
+ + + + +
+); + + +// "http://material-ui.com/#/components/snackbar" +class SnackbarExampleSimple extends React.Component<{}, {open?: boolean}> { + + constructor(props) { + super(props); + this.state = { + open: false, + }; + } + + handleTouchTap = () => { + this.setState({ + open: true, + }); + }; + + handleRequestClose = () => { + this.setState({ + open: false, + }); + }; + + render() { + return ( +
+ + +
+ ); + } +} + +class SnackbarExampleAction extends React.Component<{}, {open?: boolean, autoHideDuration?: number, message?: string}> { + + constructor(props) { + super(props); + this.state = { + autoHideDuration: 4000, + message: 'Event added to your calendar', + open: false, + }; + } + + handleTouchTap = () => { + this.setState({ + open: true, + }); + }; + + handleActionTouchTap = () => { + this.setState({ + open: false, + }); + alert('Event removed from your calendar.'); + }; + + handleChangeDuration = (event) => { + const value = event.target.value; + this.setState({ + autoHideDuration: value.length > 0 ? parseInt(value) : 0, + }); + }; + + handleRequestClose = () => { + this.setState({ + open: false, + }); + }; + + render() { + return ( +
+ +
+ + +
+ ); + } +} + +class SnackbarExampleTwice extends React.Component<{}, {open?: boolean, message?: string}> { + + private timer: number; + + constructor(props) { + super(props); + this.state = { + message: 'Event 1 added to your calendar', + open: false, + }; + this.timer = undefined; + } + + componentWillUnMount() { + clearTimeout(this.timer); + } + + handleTouchTap = () => { + this.setState({ + open: true, + }); + + this.timer = setTimeout(() => { + this.setState({ + message: `Event ${Math.round(Math.random() * 100)} added to your calendar`, + }); + }, 1500); + }; + + handleRequestClose = () => { + this.setState({ + open: false, + }); + }; + + render() { + return ( +
+ + +
+ ); + } +} + + +// "http://www.material-ui.com/#/components/stepper" +class HorizontalLinearStepper extends React.Component<{}, {stepIndex?: number, finished?: boolean}> { + + state = { + finished: false, + stepIndex: 0, + }; + + handleNext = () => { + const {stepIndex} = this.state; + this.setState({ + stepIndex: stepIndex + 1, + finished: stepIndex >= 2, + }); + }; + + handlePrev = () => { + const {stepIndex} = this.state; + if (stepIndex > 0) { + this.setState({stepIndex: stepIndex - 1}); + } + }; + + getStepContent(stepIndex) { + switch (stepIndex) { + case 0: + return 'Select campaign settings...'; + case 1: + return 'What is an ad group anyways?'; + case 2: + return 'This is the bit I really care about!'; + default: + return 'You\'re a long way from home sonny jim!'; + } + } + + render() { + const {finished, stepIndex} = this.state; + const contentStyle = {margin: '0 16px'}; + + return ( +
+ + + Select campaign settings + + + Create an ad group + + + Create an ad + + +
+ {finished ? ( +

+ { + event.preventDefault(); + this.setState({stepIndex: 0, finished: false}); + }} + > + Click here + to reset the example. +

+ ) : ( +
+

{this.getStepContent(stepIndex)}

+
+ + +
+
+ )} +
+
+ ); + } +} + +class VerticalLinearStepper extends React.Component<{}, {stepIndex?: number, finished?: boolean}> { + + state = { + finished: false, + stepIndex: 0, + }; + + handleNext = () => { + const {stepIndex} = this.state; + this.setState({ + stepIndex: stepIndex + 1, + finished: stepIndex >= 2, + }); + }; + + handlePrev = () => { + const {stepIndex} = this.state; + if (stepIndex > 0) { + this.setState({stepIndex: stepIndex - 1}); + } + }; + + renderStepActions(step) { + const {stepIndex} = this.state; + + return ( +
+ + {step > 0 && ( + + )} +
+ ); + } + + render() { + const {finished, stepIndex} = this.state; + + return ( +
+ + + Select campaign settings + +

+ For each ad campaign that you create, you can control how much + you're willing to spend on clicks and conversions, which networks + and geographical locations you want your ads to show on, and more. +

+ {this.renderStepActions(0)} +
+
+ + Create an ad group + +

An ad group contains one or more ads which target a shared set of keywords.

+ {this.renderStepActions(1)} +
+
+ + Create an ad + +

+ Try out different ad text to see what brings in the most customers, + and learn how to enhance your ads using features like ad extensions. + If you run into any problems with your ads, find out how to tell if + they're running and how to resolve approval issues. +

+ {this.renderStepActions(2)} +
+
+
+ {finished && ( +

+ { + event.preventDefault(); + this.setState({stepIndex: 0, finished: false}); + }} + > + Click here + to reset the example. +

+ )} +
+ ); + } +} + +class HorizontalNonLinearStepper extends React.Component<{}, {stepIndex?: number}> { + + state = { + stepIndex: 0, + }; + + handleNext = () => { + const {stepIndex} = this.state; + if (stepIndex < 2) { + this.setState({stepIndex: stepIndex + 1}); + } + }; + + handlePrev = () => { + const {stepIndex} = this.state; + if (stepIndex > 0) { + this.setState({stepIndex: stepIndex - 1}); + } + }; + + getStepContent(stepIndex) { + switch (stepIndex) { + case 0: + return 'Select campaign settings...'; + case 1: + return 'What is an ad group anyways?'; + case 2: + return 'This is the bit I really care about!'; + default: + return 'You\'re a long way from home sonny jim!'; + } + } + + render() { + const {stepIndex} = this.state; + const contentStyle = {margin: '0 16px'}; + + return ( +
+ + + this.setState({stepIndex: 0})}> + Select campaign settings + + + + this.setState({stepIndex: 1})}> + Create an ad group + + + + this.setState({stepIndex: 2})}> + Create an ad + + + +
+

{this.getStepContent(stepIndex)}

+
+ + +
+
+
+ ); + } +} + +class VerticalNonLinear extends React.Component<{}, {stepIndex?: number}> { + + state = { + stepIndex: 0, + }; + + handleNext = () => { + const {stepIndex} = this.state; + if (stepIndex < 2) { + this.setState({stepIndex: stepIndex + 1}); + } + }; + + handlePrev = () => { + const {stepIndex} = this.state; + if (stepIndex > 0) { + this.setState({stepIndex: stepIndex - 1}); + } + }; + + renderStepActions(step) { + return ( +
+ + {step > 0 && ( + + )} +
+ ); + } + + render() { + const {stepIndex} = this.state; + + return ( +
+ + + this.setState({stepIndex: 0})}> + Select campaign settings + + +

+ For each ad campaign that you create, you can control how much + you're willing to spend on clicks and conversions, which networks + and geographical locations you want your ads to show on, and more. +

+ {this.renderStepActions(0)} +
+
+ + this.setState({stepIndex: 1})}> + Create an ad group + + +

An ad group contains one or more ads which target a shared set of keywords.

+ {this.renderStepActions(1)} +
+
+ + this.setState({stepIndex: 2})}> + Create an ad + + +

+ Try out different ad text to see what brings in the most customers, + and learn how to enhance your ads using features like ad extensions. + If you run into any problems with your ads, find out how to tell if + they're running and how to resolve approval issues. +

+ {this.renderStepActions(2)} +
+
+
+
+ ); + } +} + +const getStyles = () => { + return { + root: { + width: '100%', + maxWidth: 700, + margin: 'auto', + }, + content: { + margin: '0 16px', + }, + actions: { + marginTop: 12, + }, + backButton: { + marginRight: 12, + }, + }; +}; + +class GranularControlStepper extends React.Component<{}, {stepIndex?: number, visited?: number[]}> { + + state = { + stepIndex: null, + visited: [], + }; + + componentWillMount() { + const {stepIndex, visited} = this.state; + this.setState({visited: visited.concat(stepIndex)}); + } + + componentWillUpdate(nextProps, nextState) { + const {stepIndex, visited} = nextState; + if (visited.indexOf(stepIndex) === -1) { + this.setState({visited: visited.concat(stepIndex)}); + } + } + + handleNext = () => { + const {stepIndex} = this.state; + if (stepIndex < 2) { + this.setState({stepIndex: stepIndex + 1}); + } + }; + + handlePrev = () => { + const {stepIndex} = this.state; + if (stepIndex > 0) { + this.setState({stepIndex: stepIndex - 1}); + } + }; + + getStepContent(stepIndex) { + switch (stepIndex) { + case 0: + return 'Select campaign settings...'; + case 1: + return 'What is an ad group anyways?'; + case 2: + return 'This is the bit I really care about!'; + default: + return 'Click a step to get started.'; + } + } + + render() { + const {stepIndex, visited} = this.state; + const styles = getStyles(); + + return ( +
+

+ { + event.preventDefault(); + this.setState({stepIndex: null, visited: []}); + }} + > + Click here + to reset the example. +

+ + + this.setState({stepIndex: 0})}> + Select campaign settings + + + + this.setState({stepIndex: 1})}> + Create an ad group + + + + this.setState({stepIndex: 2})}> + Create an ad + + + +
+

{this.getStepContent(stepIndex)}

+ {stepIndex !== null && ( +
+ + +
+ )} +
+
+ ); + } +} + +class CustomIcon extends React.Component<{}, {stepIndex?: number}> { + + state = { + stepIndex: 0, + }; + + handleNext = () => { + const {stepIndex} = this.state; + if (stepIndex < 2) { + this.setState({stepIndex: stepIndex + 1}); + } + }; + + handlePrev = () => { + const {stepIndex} = this.state; + if (stepIndex > 0) { + this.setState({stepIndex: stepIndex - 1}); + } + }; + + getStepContent(stepIndex) { + switch (stepIndex) { + case 0: + return 'Select campaign settings...'; + case 1: + return 'What is an ad group anyways?'; + case 2: + return 'This is the bit I really care about!'; + default: + return 'You\'re a long way from home sonny jim!'; + } + } + + render() { + return ( +
+ + + + Select campaign settings + + + + } + style={{color: red500}} + > + Create an ad group + + + + + Create an ad + + + +
+ ); + } +} + + +// "http://www.material-ui.com/#/components/subheader" +// Included in ListExampleChat and ListExampleFolder + +// "http://www.material-ui.com/#/components/table" +const TableExampleSimple = () => ( + + + + ID + Name + Status + + + + + 1 + John Smith + Employed + + + 2 + Randal White + Unemployed + + + 3 + Stephanie Sanders + Employed + + + 4 + Steve Brown + Employed + + +
+); + +const tableData: {name: string, status: string, selected?: boolean}[] = [ + { + name: 'John Smith', + status: 'Employed', + selected: true, + }, + { + name: 'Randal White', + status: 'Unemployed', + }, + { + name: 'Stephanie Sanders', + status: 'Employed', + selected: true, + }, + { + name: 'Steve Brown', + status: 'Employed', + }, + { + name: 'Joyce Whitten', + status: 'Employed', + }, + { + name: 'Samuel Roberts', + status: 'Employed', + }, + { + name: 'Adam Moore', + status: 'Employed', + }, +]; + +interface TableExampleComplexState { + fixedHeader?: boolean, + fixedFooter?: boolean, + stripedRows?: boolean, + showRowHover?: boolean, + selectable?: boolean, + multiSelectable?: boolean, + enableSelectAll?: boolean, + deselectOnClickaway?: boolean, + showCheckboxes?: boolean, + height?: string, +} + +class TableExampleComplex extends React.Component<{}, TableExampleComplexState> { + + constructor(props) { + super(props); + + this.state = { + fixedHeader: true, + fixedFooter: true, + stripedRows: false, + showRowHover: false, + selectable: true, + multiSelectable: false, + enableSelectAll: false, + deselectOnClickaway: true, + showCheckboxes: true, + height: '300px', + }; + } + + handleToggle = (event, toggled) => { + this.setState({ + [event.target.name]: toggled, + }); + }; + + handleChange = (event) => { + this.setState({height: event.target.value}); + }; + + render() { + return ( +
+ + + + + Super Header + + + + ID + Name + Status + + + + {tableData.map( (row, index) => ( + + {index} + {row.name} + {row.status} + + ))} + + + + ID + Name + Status + + + + Super Footer + + + +
+ +
+

Table Properties

+ + + + + + +

TableBody Properties

+ + + +

Multiple Properties

+ +
+
+ ); + } +} + +// "http://www.material-ui.com/#/components/tabs" +function handleActive(tab) { + alert(`A tab with this value property ${tab.props.value} was activated.`); +} + +const TabsExampleSimple = () => ( + + +
+

Tab One

+

+ This is an example tab. +

+

+ You can put any sort of HTML or react component in here. It even keeps the component state! +

+ +
+
+ +
+

Tab Two

+

+ This is another example tab. +

+
+
+ +
+

Tab Three

+

+ This is a third example tab. +

+
+
+
+); + +class TabsExampleControlled extends React.Component<{}, {value?: string}> { + + constructor(props) { + super(props); + this.state = { + value: 'a', + }; + } + + handleChange = (value) => { + this.setState({ + value: value, + }); + }; + + render() { + return ( + + +
+

Controllable Tab A

+

+ Tabs are also controllable if you want to programmatically pass them their values. + This allows for more functionality in Tabs such as not + having any Tab selected or assigning them different values. +

+
+
+ +
+

Controllable Tab B

+

+ This is another example of a controllable tab. Remember, if you + use controllable Tabs, you need to give all of your tabs values or else + you wont be able to select them. +

+
+
+
+ ); + } +} + +const TabsExampleIcon = () => ( + + } /> + } /> + favorite} /> + +); + +const TabsExampleIconText = () => ( + + phone} + label="RECENTS" + /> + favorite} + label="FAVORITES" + /> + } + label="NEARBY" + /> + +); + + +// "http://www.material-ui.com/#/components/text-field" +const TextFieldExampleSimple = () => ( +
+
+
+
+
+
+
+
+
+
+ +
+); + +const TextFieldExampleError = () => ( +
+
+
+
+
+
+); + +const TextFieldExampleCustomize = () => ( +
+
+
+
+
+ +
+); + +const TextFieldExampleDisabled = () => ( +
+
+
+
+ +
+); + +class TextFieldExampleControlled extends React.Component<{}, {value?: string}> { + + constructor(props) { + super(props); + + this.state = { + value: 'Property Value', + }; + } + + handleChange = (event) => { + this.setState({ + value: event.target.value, + }); + }; + + render() { + return ( +
+ +
+ ); + } +} + +// "http://www.material-ui.com/#/components/time-picker" +const TimePickerExampleSimple = () => ( +
+ + + +
+); + +class TimePickerExampleComplex extends React.Component<{}, {value24?: Date, value12?: Date}> { + + constructor(props) { + super(props); + this.state = {value24: null, value12: null}; + } + + handleChangeTimePicker24 = (event, date) => { + this.setState({value24: date}); + }; + + handleChangeTimePicker12 = (event, date) => { + this.setState({value12: date}); + }; + + render() { + return ( +
+ + +
+ ); + } +} + +const TimePickerInternational = () => ( +
+ +
+); + + +// "http://www.material-ui.com/#/components/toolbar" +class ToolbarExamplesSimple extends React.Component<{}, {value?: number}> { + + constructor(props) { + super(props); + this.state = { + value: 3, + }; + } + + handleChange = (event, index, value) => this.setState({value}); + + render() { + return ( + + + + + + + + + + + + + + + + + + + + + } + > + + + + + + ); + } +} + +const componentWithWidth = withWidth()(ToolbarExamplesSimple); + + +interface MaterialUiTestsState { +} + +class MaterialUiTests extends React.Component<{}, MaterialUiTestsState> { + + render () { + return ( + + + + + ); + } +} + +// "http://www.material-ui.com/#/get-started/usage" +ReactDOM.render( + , + document.getElementById('app') +); diff --git a/material-ui/legacy/material-ui-0.15.1-tests.tsx.tscparams b/material-ui/legacy/material-ui-0.15.1-tests.tsx.tscparams new file mode 100644 index 00000000000000..855355b85f42ba --- /dev/null +++ b/material-ui/legacy/material-ui-0.15.1-tests.tsx.tscparams @@ -0,0 +1 @@ +--experimentalDecorators \ No newline at end of file diff --git a/material-ui/legacy/material-ui-0.15.1.d.ts b/material-ui/legacy/material-ui-0.15.1.d.ts new file mode 100644 index 00000000000000..b5ec61b14b492c --- /dev/null +++ b/material-ui/legacy/material-ui-0.15.1.d.ts @@ -0,0 +1,8630 @@ +// Type definitions for material-ui v0.15.1 +// Project: https://github.com/callemall/material-ui +// Definitions by: Nathan Brown , Oliver Herrmann +// Definitions: https://github.com/DefinitelyTyped/DefinitelyTyped + +/// + +declare module "material-ui" { + export import AppBar = __MaterialUI.AppBar; + export import AutoComplete = __MaterialUI.AutoComplete; + export import Avatar = __MaterialUI.Avatar; + export import Badge = __MaterialUI.Badge; + export import Card = __MaterialUI.Card.Card; + export import CardActions = __MaterialUI.Card.CardActions; + export import CardHeader = __MaterialUI.Card.CardHeader; + export import CardMedia = __MaterialUI.Card.CardMedia; + export import CardText = __MaterialUI.Card.CardText; + export import CardTitle = __MaterialUI.Card.CardTitle; + export import Checkbox = __MaterialUI.Switches.Checkbox; + export import Chip = __MaterialUI.Chip; + export import CircularProgress = __MaterialUI.CircularProgress; + export import DatePicker = __MaterialUI.DatePicker.DatePicker; + export import Dialog = __MaterialUI.Dialog; + export import Divider = __MaterialUI.Divider; + export import Drawer = __MaterialUI.Drawer; + export import DropDownMenu = __MaterialUI.Menus.DropDownMenu; + export import FlatButton = __MaterialUI.FlatButton; + export import FloatingActionButton = __MaterialUI.FloatingActionButton; + export import FontIcon = __MaterialUI.FontIcon; + export import GridList = __MaterialUI.GridList.GridList; + export import GridTile = __MaterialUI.GridList.GridTile; + export import IconButton = __MaterialUI.IconButton; + export import IconMenu = __MaterialUI.Menus.IconMenu; + export import LinearProgress = __MaterialUI.LinearProgress; + export import List = __MaterialUI.List.List; + export import ListItem = __MaterialUI.List.ListItem; + export import MakeSelectable = __MaterialUI.List.MakeSelectable; + export import Menu = __MaterialUI.Menus.Menu; + export import MenuItem = __MaterialUI.Menus.MenuItem; + export import Paper = __MaterialUI.Paper; + export import Popover = __MaterialUI.Popover.Popover; + export import RadioButton = __MaterialUI.Switches.RadioButton; + export import RadioButtonGroup = __MaterialUI.Switches.RadioButtonGroup; + export import RaisedButton = __MaterialUI.RaisedButton; + export import RefreshIndicator = __MaterialUI.RefreshIndicator; + export import SelectField = __MaterialUI.SelectField; + export import Slider = __MaterialUI.Slider; + export import Subheader = __MaterialUI.Subheader; + export import SvgIcon = __MaterialUI.SvgIcon; + export import Step = __MaterialUI.Stepper.Step; + export import StepButton = __MaterialUI.Stepper.StepButton; + export import StepContent = __MaterialUI.Stepper.StepContent; + export import StepLabel = __MaterialUI.Stepper.StepLabel; + export import Stepper = __MaterialUI.Stepper; + export import Snackbar = __MaterialUI.Snackbar; + export import Tab = __MaterialUI.Tabs.Tab; + export import Tabs = __MaterialUI.Tabs.Tabs; + export import Table = __MaterialUI.Table.Table; + export import TableBody = __MaterialUI.Table.TableBody; + export import TableFooter = __MaterialUI.Table.TableFooter; + export import TableHeader = __MaterialUI.Table.TableHeader; + export import TableHeaderColumn = __MaterialUI.Table.TableHeaderColumn; + export import TableRow = __MaterialUI.Table.TableRow; + export import TableRowColumn = __MaterialUI.Table.TableRowColumn; + export import TextField = __MaterialUI.TextField; + export import TimePicker = __MaterialUI.TimePicker; + export import Toggle = __MaterialUI.Switches.Toggle; + export import Toolbar = __MaterialUI.Toolbar.Toolbar; + export import ToolbarGroup = __MaterialUI.Toolbar.ToolbarGroup; + export import ToolbarSeparator = __MaterialUI.Toolbar.ToolbarSeparator; + export import ToolbarTitle = __MaterialUI.Toolbar.ToolbarTitle; + + // export type definitions + export type TouchTapEvent = __MaterialUI.TouchTapEvent; + export type TouchTapEventHandler = __MaterialUI.TouchTapEventHandler; +} + +declare namespace __MaterialUI { + export import React = __React; + + // ReactLink is from "react/addons" + interface ReactLink { + value: T; + requestChange(newValue: T): void; + } + + // What's common between React.TouchEvent and React.MouseEvent + interface TouchTapEvent extends React.SyntheticEvent { + altKey: boolean; + ctrlKey: boolean; + getModifierState(key: string): boolean; + metaKey: boolean; + shiftKey: boolean; + } + + // What's common between React.TouchEventHandler and React.MouseEventHandler + interface TouchTapEventHandler extends React.EventHandler { } + + interface ThemeWrapperProps extends React.Props { + theme: Styles.MuiTheme; + } + export class ThemeWrapper extends React.Component { + } + + export namespace Styles { + interface Spacing { + iconSize?: number; + + desktopGutter?: number; + desktopGutterMore?: number; + desktopGutterLess?: number; + desktopGutterMini?: number; + desktopKeylineIncrement?: number; + desktopDropDownMenuItemHeight?: number; + desktopDropDownMenuFontSize?: number; + desktopLeftNavMenuItemHeight?: number; + desktopSubheaderHeight?: number; + desktopToolbarHeight?: number; + } + export var Spacing: Spacing; + + interface ThemePalette { + primary1Color?: string; + primary2Color?: string; + primary3Color?: string; + accent1Color?: string; + accent2Color?: string; + accent3Color?: string; + textColor?: string; + alternateTextColor?: string; + canvasColor?: string; + borderColor?: string; + disabledColor?: string; + pickerHeaderColor?: string; + clockCircleColor?: string; + shadowColor?: string; + } + export var ThemePalette: ThemePalette; + interface MuiTheme { + spacing?: Spacing; + fontFamily?: string; + palette?: ThemePalette; + isRtl?: boolean; + userAgent?: string; + zIndex?: zIndex; + baseTheme?: RawTheme; + rawTheme?: RawTheme; + appBar?: { + color?: string; + textColor?: string; + height?: number; + titleFontWeight?: number; + padding?: number; + }; + avatar?: { + color?: string; + backgroundColor?: string; + borderColor?: string; + }; + badge?: { + color?: string; + textColor?: string; + primaryColor?: string; + primaryTextColor?: string; + secondaryColor?: string; + secondaryTextColor?: string; + fontWeight?: number; + }; + button?: { + height?: number; + minWidth?: number; + iconButtonSize?: number; + }; + card?: { + titleColor?: string; + subtitleColor?: string; + fontWeight?: number; + }; + cardMedia?: { + color?: string; + overlayContentBackground?: string; + titleColor?: string; + subtitleColor?: string; + }; + cardText?: { + textColor?: string; + }; + checkbox?: { + boxColor?: string; + checkedColor?: string; + requiredColor?: string; + disabledColor?: string; + labelColor?: string; + labelDisabledColor?: string; + }; + chip?: { + backgroundColor?: string; + deleteIconColor?: string; + textColor?: string; + fontSize?: number; + fontWeight?: number; + shadow?: string; + }; + datePicker?: { + color?: string; + textColor?: string; + calendarTextColor?: string; + selectColor?: string; + selectTextColor?: string; + calendarYearBackgroundColor?: string; + }; + dialog?: { + titleFontSize?: number; + bodyFontSize?: number; + bodyColor?: string; + }; + dropDownMenu?: { + accentColor?: string; + }; + enhancedButton?: { + tapHighlightColor?: string; + }; + flatButton?: { + color?: string; + buttonFilterColor?: string; + disabledTextColor?: string; + textColor?: string; + primaryTextColor?: string; + secondaryTextColor?: string; + fontSize?: number; + fontWeight?: number; + }; + floatingActionButton?: { + buttonSize?: number; + miniSize?: number; + color?: string; + iconColor?: string; + secondaryColor?: string; + secondaryIconColor?: string; + disabledTextColor?: string; + disabledColor?: string; + }; + gridTile?: { + textColor?: string; + }; + icon?: { + color?: string; + backgroundColor?: string; + }; + inkBar?: { + backgroundColor?: string; + }; + drawer?: { + width?: number; + color?: string; + }; + listItem?: { + nestedLevelDepth?: number; + secondaryTextColor?: string; + leftIconColor?: string; + rightIconColor?: string; + }; + menu?: { + backgroundColor?: string; + containerBackgroundColor?: string; + }; + menuItem?: { + dataHeight?: number; + height?: number; + hoverColor?: string; + padding?: number; + selectedTextColor?: string; + rightIconDesktopFill?: string; + }; + menuSubheader?: { + padding?: number; + borderColor?: string; + textColor?: string; + }; + overlay?: { + backgroundColor?: string; + }; + paper?: { + color?: string; + backgroundColor?: string; + zDepthShadows?: string[]; + }; + radioButton?: { + borderColor?: string; + backgroundColor?: string; + checkedColor?: string; + requiredColor?: string; + disabledColor?: string; + size?: number; + labelColor?: string; + labelDisabledColor?: string; + }; + raisedButton?: { + color?: string; + textColor?: string; + primaryColor?: string; + primaryTextColor?: string; + secondaryColor?: string; + secondaryTextColor?: string; + disabledColor?: string; + disabledTextColor?: string; + fontSize?: number; + fontWeight?: number; + }; + refreshIndicator?: { + strokeColor?: string; + loadingStrokeColor?: string; + }; + ripple?: { + color?: string; + }; + slider?: { + trackSize?: number; + trackColor?: string; + trackColorSelected?: string; + handleSize?: number; + handleSizeDisabled?: number; + handleSizeActive?: number; + handleColorZero?: string; + handleFillColor?: string; + selectionColor?: string; + rippleColor?: string; + }; + snackbar?: { + textColor?: string; + backgroundColor?: string; + actionColor?: string; + }; + subheader?: { + color?: string; + fontWeight?: number; + }; + stepper?: { + backgroundColor?: string; + hoverBackgroundColor?: string; + iconColor?: string; + hoveredIconColor?: string; + inactiveIconColor?: string; + textColor?: string; + disabledTextColor?: string; + connectorLineColor?: string; + }; + svgIcon?: { + color?: string, + }; + table?: { + backgroundColor?: string; + }; + tableFooter?: { + borderColor?: string; + textColor?: string; + }; + tableHeader?: { + borderColor?: string; + }; + tableHeaderColumn?: { + textColor?: string; + height?: number; + spacing?: number; + }; + tableRow?: { + hoverColor?: string; + stripeColor?: string; + selectedColor?: string; + textColor?: string; + borderColor?: string; + height?: number; + }; + tableRowColumn?: { + height?: number; + spacing?: number; + }; + tabs?: { + backgroundColor?: string; + textColor?: string; + selectedTextColor?: string; + }; + textField?: { + textColor?: string; + hintColor?: string; + floatingLabelColor?: string; + disabledTextColor?: string; + errorColor?: string; + focusColor?: string; + backgroundColor?: string; + borderColor?: string; + }; + timePicker?: { + color?: string; + textColor?: string; + accentColor?: string; + clockColor?: string; + clockCircleColor?: string; + headerColor?: string; + selectColor?: string; + selectTextColor?: string; + }; + toggle?: { + thumbOnColor?: string; + thumbOffColor?: string; + thumbDisabledColor?: string; + thumbRequiredColor?: string; + trackOnColor?: string; + trackOffColor?: string; + trackDisabledColor?: string; + labelColor?: string; + labelDisabledColor?: string; + trackRequiredColor?: string; + }; + toolbar?: { + color?: string; + hoverColor?: string; + backgroundColor?: string; + height?: number; + titleFontSize?: number; + iconColor?: string; + separatorColor?: string; + menuHoverColor?: string; + }; + tooltip?: { + color?: string; + rippleBackgroundColor?: string; + }; + } + + interface zIndex { + menu: number; + appBar: number; + drawerOverlay: number; + drawer: number; + dialogOverlay: number; + dialog: number; + layer: number; + popover: number; + snackbar: number; + tooltip: number; + } + export var zIndex: zIndex; + + interface RawTheme { + spacing?: Spacing; + fontFamily?: string; + palette?: ThemePalette; + } + var lightBaseTheme: RawTheme; + var darkBaseTheme: RawTheme; + + export function muiThemeable, P, S>(): (component: TComponent) => TComponent; + + //** @deprecated use MuiThemeProvider instead **/ + export function themeDecorator(muiTheme: Styles.MuiTheme): (Component: TFunction) => TFunction; + + interface MuiThemeProviderProps extends React.Props { + muiTheme?: Styles.MuiTheme; + } + export class MuiThemeProvider extends React.Component{ + } + + export function getMuiTheme(...muiTheme: MuiTheme[]): MuiTheme; + + interface ThemeManager { + //** @deprecated ThemeManager is deprecated. please import getMuiTheme directly from "material-ui/styles/getMuiTheme" **/ + getMuiTheme(baseTheme: RawTheme, muiTheme?: MuiTheme): MuiTheme; + + //** @deprecated modifyRawThemeSpacing is deprecated. please use getMuiTheme to modify your theme directly. http://www.material-ui.com/#/customization/themes **/ + modifyRawThemeSpacing(muiTheme: MuiTheme, newSpacing: Spacing): MuiTheme; + + //** @deprecated modifyRawThemePalette is deprecated. please use getMuiTheme to modify your theme directly. http://www.material-ui.com/#/customization/themes **/ + modifyRawThemePalette(muiTheme: MuiTheme, newPaletteKeys: ThemePalette): MuiTheme; + + //** @deprecated modifyRawThemeFontFamily is deprecated. please use getMuiTheme to modify your theme directly. http://www.material-ui.com/#/customization/themes **/ + modifyRawThemeFontFamily(muiTheme: MuiTheme, newFontFamily: string): MuiTheme; + } + export var ThemeManager: ThemeManager; + + interface Transitions { + easeOut(duration?: string, property?: string | string[], delay?: string, easeFunction?: string): string; + create(duration?: string, property?: string, delay?: string, easeFunction?: string): string; + easeOutFunction: string; + easeInOutFunction: string; + } + export var Transitions: Transitions; + + interface Typography { + textFullBlack: string; + textDarkBlack: string; + textLightBlack: string; + textMinBlack: string; + textFullWhite: string; + textDarkWhite: string; + textLightWhite: string; + + // font weight + fontWeightLight: number; + fontWeightNormal: number; + fontWeightMedium: number; + + fontStyleButtonFontSize: number; + } + export var Typography: Typography; + + //** @deprecated use darkBaseTheme instead **/ + export var DarkRawTheme: RawTheme; + + //** @deprecated use lightBaseTheme instead **/ + export var LightRawTheme: RawTheme; + } + + interface AppBarProps extends React.Props { + className?: string; + iconClassNameLeft?: string; + iconClassNameRight?: string; + iconElementLeft?: React.ReactElement; + iconElementRight?: React.ReactElement; + iconStyleRight?: React.CSSProperties; + iconStyleLeft?: React.CSSProperties; + onLeftIconButtonTouchTap?: TouchTapEventHandler; + onRightIconButtonTouchTap?: TouchTapEventHandler; + onTitleTouchTap?: TouchTapEventHandler; + showMenuIconButton?: boolean; + style?: React.CSSProperties; + title?: React.ReactNode; + titleStyle?: React.CSSProperties; + zDepth?: number; + } + export class AppBar extends React.Component{ + } + + interface AppCanvasProps extends React.Props { + } + export class AppCanvas extends React.Component { + } + + namespace propTypes { + type horizontal = 'left' | 'middle' | 'right'; + type vertical = 'top' | 'center' | 'bottom'; + type direction = 'left' | 'right' | 'up' | 'down'; + + interface origin { + horizontal: horizontal; + vertical: vertical; + } + + type corners = 'bottom-left' | 'bottom-right' | 'top-left' | 'top-right'; + type cornersAndCenter = 'bottom-center' | 'bottom-left' | 'bottom-right' | 'top-center' | 'top-left' | 'top-right'; + } + + type AutoCompleteDataItem = { text: string, value: React.ReactNode } | string; + type AutoCompleteDataSource = { text: string, value: React.ReactNode }[] | string[]; + interface AutoCompleteProps extends React.Props { + anchorOrigin?: propTypes.origin; + animated?: boolean; + dataSource: AutoCompleteDataSource; + disableFocusRipple?: boolean; + errorStyle?: React.CSSProperties; + errorText?: string; + filter?: (searchText: string, key: string, item: AutoCompleteDataItem) => boolean; + floatingLabelText?: React.ReactNode; + fullWidth?: boolean; + hintText?: string; + listStyle?: React.CSSProperties; + maxSearchResults?: number; + menuCloseDelay?: number; + menuProps?: any; + menuStyle?: React.CSSProperties; + onBlur?: React.FocusEventHandler; + onFocus?: React.FocusEventHandler; + onKeyDown?: React.KeyboardEventHandler; + onNewRequest?: (chosenRequest: string, index: number) => void; + onUpdateInput?: (searchText: string, dataSource: AutoCompleteDataSource) => void; + open?: boolean; + openOnFocus?: boolean; + searchText?: string; + style?: React.CSSProperties; + targetOrigin?: propTypes.origin; + /** @deprecated Instead, use openOnFocus */ + triggerUpdateOnFocus?: boolean; + } + export class AutoComplete extends React.Component { + static noFilter: () => boolean; + static defaultFilter: (searchText: string, key: string) => boolean; + static caseSensitiveFilter: (searchText: string, key: string) => boolean; + static caseInsensitiveFilter: (searchText: string, key: string) => boolean; + static levenshteinDistanceFilter(distanceLessThan: number): (searchText: string, key: string) => boolean; + static fuzzyFilter: (searchText: string, key: string) => boolean; + static Item: Menus.MenuItem; + static Divider: Divider; + } + + interface AvatarProps extends React.Props { + backgroundColor?: string; + className?: string; + color?: string; + icon?: React.ReactElement; + size?: number; + src?: string; + style?: React.CSSProperties; + } + export class Avatar extends React.Component { + } + + interface BadgeProps extends React.Props { + badgeContent: React.ReactNode; + badgeStyle?: React.CSSProperties; + className?: string; + primary?: boolean; + secondary?: boolean; + style?: React.CSSProperties; + } + export class Badge extends React.Component { + } + + interface BeforeAfterWrapperProps extends React.Props { + afterElementType?: string; + afterStyle?: React.CSSProperties; + beforeElementType?: string; + beforeStyle?: React.CSSProperties; + elementType?: string; + style?: React.CSSProperties; + } + export class BeforeAfterWrapper extends React.Component { + } + + // non generally overridden elements of EnhancedButton + interface SharedEnhancedButtonProps extends React.Props { + centerRipple?: boolean; + disableFocusRipple?: boolean; + disableKeyboardFocus?: boolean; + disableTouchRipple?: boolean; + focusRippleColor?: string; + focusRippleOpacity?: number; + keyboardFocused?: boolean; + linkButton?: boolean; + onBlur?: React.FocusEventHandler; + onFocus?: React.FocusEventHandler; + onKeyboardFocus?: (e: React.FocusEvent, isKeyboardFocused: boolean) => void; + onKeyDown?: React.KeyboardEventHandler; + onKeyUp?: React.KeyboardEventHandler; + onTouchTap?: TouchTapEventHandler; + onClick?: React.MouseEventHandler; + style?: React.CSSProperties; + tabIndex?: number; + touchRippleColor?: string; + touchRippleOpacity?: number; + type?: string; + containerElement?: React.ReactNode | string; + } + + interface EnhancedButtonProps extends React.HTMLAttributes, SharedEnhancedButtonProps { + // container element,