diff --git a/docs/CHANGELOG.md b/docs/CHANGELOG.md index c6fae149f8..2548dca176 100644 --- a/docs/CHANGELOG.md +++ b/docs/CHANGELOG.md @@ -1,3 +1,129 @@ + +# [1.0.0-beta.5 Blackhole Sun](https://github.com/Teradata/covalent/tree/v1.0.0-beta.5) (2017-06-09) + +## Breaking Change + +#### td-chips + +Now that chips have async support and we've abstracted the internal filtering mechanism, the developer needs to provide their own filter. + +This will also allow the developer to create custom filters both locally and server-side. + +e.g. + +```html + + +``` + + +```typescript + +strings: string[] = [ + 'stepper', + 'expansion-panel', + 'markdown', + 'highlight', + 'loading', + 'media', + 'chips', + 'http', + 'json-formatter', + 'pipes', + 'need more?', +]; + +filteredStrings: string[]; + +stringsModel: string[] = this.strings.slice(0, 6); + +ngOnInit(): void { + this.filterStrings(''); +} + +filterStrings(value: string): void { + if (value) { + this.filteredStrings = this.strings.filter((item: any) => { + return item.toLowerCase().indexOf(value.toLowerCase()) > -1; + }).filter((filteredItem: any) => { + return this.stringsModel ? this.stringsModel.indexOf(filteredItem) < 0 : true; + }); + } +} +``` + +#### td-expansion-panel + +With the introduction of `td-expansion-panel-group`, the `td-expansion-panel` expanded margin animation will not be applied unless the `td-expansion-panel` is grouped inside of a `td-expansion-panel-group`. + +e.g. + +```html + + + + + + + + + +``` + +## Bug Fixes + +* **chips:** keep focused state as long as you keep clicking inside the chips context ([22d4342c4072560e3903820c4009f8129ec0d184](https://github.com/Teradata/covalent/commit/22d4342c4072560e3903820c4009f8129ec0d184)) +* **data-table:** not throw `(rowClick)` event when clicking on checkbox ([ec1cbd8c962d0e5610b075b6f3655afa589ba121](https://github.com/Teradata/covalent/commit/ec1cbd8c962d0e5610b075b6f3655afa589ba121)), closes [#611](https://github.com/Teradata/covalent/issues/611) +* **expansion-panel:** only render label and sublabel when its needed ([e62d3bd68553be7cee188c0b761c68d11247f902](https://github.com/Teradata/covalent/commit/e62d3bd68553be7cee188c0b761c68d11247f902)) +* **layout:** use `ScrollDispatcherModule` and leverage `cdkScrollable` in layouts so material components readjust when scrolling ([629d06f161c00f99218708570d6085acbf58ee4f](https://github.com/Teradata/covalent/commit/629d06f161c00f99218708570d6085acbf58ee4f)), closes [#620](https://github.com/Teradata/covalent/issues/620) +* **media:** make media service not use window directly ([90e16f5d7be080aee1601a2d86e72c47536c3e40](https://github.com/Teradata/covalent/commit/90e16f5d7be080aee1601a2d86e72c47536c3e40)) +* **stepper:** horizontal scroll was not appearing when needed in certain cases ([9542139ba7b8e84435b1cda47f875b927787a64a](https://github.com/Teradata/covalent/commit/9542139ba7b8e84435b1cda47f875b927787a64a)), closes [#282](https://github.com/Teradata/covalent/issues/282) +* **stepper:** add `cdkScrollable` so material component can hook into it ([9542139ba7b8e84435b1cda47f875b927787a64a](https://github.com/Teradata/covalent/commit/9542139ba7b8e84435b1cda47f875b927787a64a)) +* **styles:** fix sm/md/lg card images in title-group ([dda5d9cc3c5fe5728b9b9b27f8a6afa95f969861](https://github.com/Teradata/covalent/commit/dda5d9cc3c5fe5728b9b9b27f8a6afa95f969861)) +* **theme:** remove duplicate functions that are already part of material ([98eaf28287db5ebe0597804818a99a11fe82b00a](https://github.com/Teradata/covalent/commit/98eaf28287db5ebe0597804818a99a11fe82b00a)), closes [#632](https://github.com/Teradata/covalent/issues/632) + +## Features + +* **chips:** new `[chipRemoval]` input to block chips from being removed ([51ba94db1b7adef51a67407fc9db8504678a9af8](https://github.com/Teradata/covalent/commit/51ba94db1b7adef51a67407fc9db8504678a9af8)) +* **chips:** add `[color]` input to change the color of focused chips, input and underline ([5c2635c6548741442100b98724adcf607c6fb770](https://github.com/Teradata/covalent/commit/5c2635c6548741442100b98724adcf607c6fb770)), closes [#605](https://github.com/Teradata/covalent/issues/605) +* **chips:** new `[stacked]` input to make chips stack vertically. ([9a18a6314853f35991868cd0260884fa4cc5b3a4](https://github.com/Teradata/covalent/commit/9a18a6314853f35991868cd0260884fa4cc5b3a4)) +* **chips:** ability to use object lists and set templates for both autocomplete and chips ([22d4342c4072560e3903820c4009f8129ec0d184](https://github.com/Teradata/covalent/commit/22d4342c4072560e3903820c4009f8129ec0d184)) +* **chips:** abstract the autocomplete filtering and add debounce input (local vs server) ([22d4342c4072560e3903820c4009f8129ec0d184](https://github.com/Teradata/covalent/commit/22d4342c4072560e3903820c4009f8129ec0d184)), closes [#252](https://github.com/Teradata/covalent/issues/252), [#359](https://github.com/Teradata/covalent/issues/252), [#359](https://github.com/Teradata/covalent/issues/601) +* **chips:** add `td-chip-avatar` when using template `td-chip` to mimic a contact chip ([fe9daccb5fd436a3ca527d4e694cc2e02e26f79d](https://github.com/Teradata/covalent/commit/fe9daccb5fd436a3ca527d4e694cc2e02e26f79d)) +* **dependencies:** upgrade to `@angular/material@1.0.0-beta.6` ([629d06f161c00f99218708570d6085acbf58ee4f](https://github.com/Teradata/covalent/commit/629d06f161c00f99218708570d6085acbf58ee4f)) +* **dialog:** improve `prompt-dialog` a11y by selection text in input when focused ([e9427aaee1520a83326cd242850b525915b7c5fe](https://github.com/Teradata/covalent/commit/e9427aaee1520a83326cd242850b525915b7c5fe)), closes [#616](https://github.com/Teradata/covalent/issues/616) +* **expansion-panel:** introducing `td-expansion-panel-group` to only give margin to expansion panels when grouped ([9ae0ba532bbabde6eca8d1b4315667333e83ae35](https://github.com/Teradata/covalent/commit/9ae0ba532bbabde6eca8d1b4315667333e83ae35)) +* **expansion-panel:** add `[disableRipple]` input to disable ripple effect on demand ([33810ce86915c6d1e948e426a6056500d88e6827](https://github.com/Teradata/covalent/commit/33810ce86915c6d1e948e426a6056500d88e6827)) +* **layout:** add `[mode]`, `[opened]` and `[sidenavWidth]` to `td-layout` ([e2172fafdd7ea03f7db1df8d21abea4238e14d65](https://github.com/Teradata/covalent/commit/e2172fafdd7ea03f7db1df8d21abea4238e14d65)) +* **layout:** add `[color]` input to `td-layout-footer` ([e912ef4bed205d7da4743d83c45bce3edf150084](https://github.com/Teradata/covalent/commit/e912ef4bed205d7da4743d83c45bce3edf150084)), closes [#489](https://github.com/Teradata/covalent/issues/489) +* **message:** add animation when opening/closing ([5a858c7a94bd3247487684a7473a2657105dbe2a](https://github.com/Teradata/covalent/commit/5a858c7a94bd3247487684a7473a2657105dbe2a)) +* **stepper:** add `[disableRipple]` input to disable ripple effect on demand ([33810ce86915c6d1e948e426a6056500d88e6827](https://github.com/Teradata/covalent/commit/33810ce86915c6d1e948e426a6056500d88e6827)) + +## Performance +* **all:** make sure all services are singleton when provided ([4544c1a5bcabb1fa3e60b6fe6c2f6e1a5215ab5c](https://github.com/Teradata/covalent/commit/4544c1a5bcabb1fa3e60b6fe6c2f6e1a5215ab5c)) +* **chips:** support `OnPush` change detection ([22d4342c4072560e3903820c4009f8129ec0d184](https://github.com/Teradata/covalent/commit/22d4342c4072560e3903820c4009f8129ec0d184)) +* **expansion-panel:** improved animation performance when toggling in group ([9ae0ba532bbabde6eca8d1b4315667333e83ae35](https://github.com/Teradata/covalent/commit/9ae0ba532bbabde6eca8d1b4315667333e83ae35)) + + +## Internal +* **animations:** make toggle directive use new animations API ([90e16f5d7be080aee1601a2d86e72c47536c3e40](https://github.com/Teradata/covalent/commit/90e16f5d7be080aee1601a2d86e72c47536c3e40)) +* **animations:** make fade directive use new animations API ([90e16f5d7be080aee1601a2d86e72c47536c3e40](https://github.com/Teradata/covalent/commit/90e16f5d7be080aee1601a2d86e72c47536c3e40)) +* **dependencies:** upgrade to @angular@4.2.0 ([90e16f5d7be080aee1601a2d86e72c47536c3e40](https://github.com/Teradata/covalent/commit/90e16f5d7be080aee1601a2d86e72c47536c3e40)) +* **dependencies:** upgrade to @angular/cli@1.1.0 ([90e16f5d7be080aee1601a2d86e72c47536c3e40](https://github.com/Teradata/covalent/commit/90e16f5d7be080aee1601a2d86e72c47536c3e40)) +* **docs:** new landing page and theme ([615a4ee02976f4d0ffa0f0394c562cbdcdce5a25](https://github.com/Teradata/covalent/commit/615a4ee02976f4d0ffa0f0394c562cbdcdce5a25)) +* **docs:** fix rtl/lrt demo in docs ([7874b5b7a371aeffe9d9d239e910ab31c3a79399](https://github.com/Teradata/covalent/commit/7874b5b7a371aeffe9d9d239e910ab31c3a79399)) +* **docs:** add selective preload strategy for lazy loading ([3b4da1cd72b64d20b6f0deb8c7668d785cbd272a](https://github.com/Teradata/covalent/commit/3b4da1cd72b64d20b6f0deb8c7668d785cbd272a)) +* **docs:** improved demos/examples +* **docs:** make docs render properly in IE11 ([a118fb9e9f5b83c830f7be9bc7ea19586e1067f6](https://github.com/Teradata/covalent/commit/a118fb9e9f5b83c830f7be9bc7ea19586e1067f6)) +* **chips:** add more unit tests +* **validators:** remove max/min validators since angular already has them ([8e9ab29d170f91bc61a54cb07581e0631a576410](https://github.com/Teradata/covalent/commit/8e9ab29d170f91bc61a54cb07581e0631a576410)) +* **stepper:** change internal label class to `mat-inactive` ([bb9331b3dffb93c4e96281c8d9469fa8f12e52e3](https://github.com/Teradata/covalent/commit/bb9331b3dffb93c4e96281c8d9469fa8f12e52e3)) + + # [1.0.0-beta.4 Johnny B Goode](https://github.com/Teradata/covalent/tree/v1.0.0-beta.4) (2017-05-16) @@ -18,7 +144,7 @@ import: [ This was announced as deprecated in `beta.3` to make developer import only what they need to reduce bundle size. -* **dependencies:** removal of flex-layout dependency ([a15d4936fb1ded2e2c1b8907c6b9a72892c946b7](https://github.com/Teradata/covalent/commit/a15d4936fb1ded2e2c1b8907c6b9a72892c946b7)), closes [#542](https://github.com/Teradata/covalent/issues/542) +* **dependencies:** removal of flex-layout dependency ([a15d4936fb1ded2e2c1b8907c6b9a72892c946b7](https://github.com/Teradata/covalent/commit/a15d4936fb1ded2e2c1b8907c6b9a72892c946b7)), closes [#542](https://github.com/Teradata/covalent/issues/542) Since `CovalentCoreModule` has been removed, there is really no use for @angular/flex-layout inernally. we will leave it to the developer to include it on demand. @@ -33,18 +159,18 @@ These selectors were deprecated a few releases back so it should be ok to remove ## Bug Fixes * **chips:** added missing rxjs/add/operator/debounceTime import ([755f84664e65dfa52b131406a8979c8f3502f1c2](https://github.com/Teradata/covalent/commit/755f84664e65dfa52b131406a8979c8f3502f1c2)) * **data-table:** fix when data is undefined and multiple selection ([783228f15154ec04911abf92da0bb199c67190de](https://github.com/Teradata/covalent/commit/783228f15154ec04911abf92da0bb199c67190de)) -* **data-table:** fix pseudo checkbox css ([d4d90a2cd20a30f6774a5198526381228a64363a](https://github.com/Teradata/covalent/commit/d4d90a2cd20a30f6774a5198526381228a64363a)), closes [#525](https://github.com/Teradata/covalent/issues/525) +* **data-table:** fix pseudo checkbox css ([d4d90a2cd20a30f6774a5198526381228a64363a](https://github.com/Teradata/covalent/commit/d4d90a2cd20a30f6774a5198526381228a64363a)), closes [#525](https://github.com/Teradata/covalent/issues/525) * **dev:** fix tsconfig typeRoots file path ([bec8a3a0d4c99123abe04426071ce3d5d81d9cf0](https://github.com/Teradata/covalent/commit/bec8a3a0d4c99123abe04426071ce3d5d81d9cf0)) -* **dynamic-forms:** fix AoT issue with min/max validators ([5bd684fdbd82d8b57bc6bb444cbe3f4e90b33f75](https://github.com/Teradata/covalent/commit/5bd684fdbd82d8b57bc6bb444cbe3f4e90b33f75)), closes [#508](https://github.com/Teradata/covalent/issues/508) -* **flex:** flex=“value” for grow/initial/auto/none/noshink/nogrow ([141550fc5429f8808224786bd7fc7e1119a84601](https://github.com/Teradata/covalent/commit/141550fc5429f8808224786bd7fc7e1119a84601)), closes [#586](https://github.com/Teradata/covalent/issues/586) +* **dynamic-forms:** fix AoT issue with min/max validators ([5bd684fdbd82d8b57bc6bb444cbe3f4e90b33f75](https://github.com/Teradata/covalent/commit/5bd684fdbd82d8b57bc6bb444cbe3f4e90b33f75)), closes [#508](https://github.com/Teradata/covalent/issues/508) +* **flex:** flex=“value” for grow/initial/auto/none/noshink/nogrow ([141550fc5429f8808224786bd7fc7e1119a84601](https://github.com/Teradata/covalent/commit/141550fc5429f8808224786bd7fc7e1119a84601)), closes [#586](https://github.com/Teradata/covalent/issues/586) * **loading:** remove OnPush change detection from `td-loading` since its a container component ([baea6b384f0c01f54a54b649aecf2b08ae276333](https://github.com/Teradata/covalent/commit/baea6b384f0c01f54a54b649aecf2b08ae276333)) -* **pipes:** convert bytes using powers of 2 in `TdBytesPipe` ([c77d517e8ae3beb94e6d4fa68503da7ebafaae9b](https://github.com/Teradata/covalent/commit/c77d517e8ae3beb94e6d4fa68503da7ebafaae9b)), closes [#527](https://github.com/Teradata/covalent/issues/527) +* **pipes:** convert bytes using powers of 2 in `TdBytesPipe` ([c77d517e8ae3beb94e6d4fa68503da7ebafaae9b](https://github.com/Teradata/covalent/commit/c77d517e8ae3beb94e6d4fa68503da7ebafaae9b)), closes [#527](https://github.com/Teradata/covalent/issues/527) ## Features * **chips:** ability to disable chip addition (input). ([1c75d35b3a399b2236ec49000e2c85af57552723](https://github.com/Teradata/covalent/commit/1c75d35b3a399b2236ec49000e2c85af57552723)), closes [#500](https://github.com/Teradata/covalent/issues/500) * **data-table:** ability to exclude columns when filtering data ([11c3d15a12b789d561fdb19bc1bad62d7a2f5eb3](https://github.com/Teradata/covalent/commit/11c3d15a12b789d561fdb19bc1bad62d7a2f5eb3)), closes [#513](https://github.com/Teradata/covalent/issues/513) -* **data-table:** ability to hide data table columns ([0ccb19190a6376adcd2345a1a62c642a38b2f11b](https://github.com/Teradata/covalent/commit/0ccb19190a6376adcd2345a1a62c642a38b2f11b)), closes [#511](https://github.com/Teradata/covalent/issues/511) -* **data-table:** indeterminate state in 'selectAll' checkbox ([bd0f7bcd64845801b96fb57a3de42e914da947f6](https://github.com/Teradata/covalent/commit/bd0f7bcd64845801b96fb57a3de42e914da947f6)), closes [#571](https://github.com/Teradata/covalent/issues/571) +* **data-table:** ability to hide data table columns ([0ccb19190a6376adcd2345a1a62c642a38b2f11b](https://github.com/Teradata/covalent/commit/0ccb19190a6376adcd2345a1a62c642a38b2f11b)), closes [#511](https://github.com/Teradata/covalent/issues/511) +* **data-table:** indeterminate state in 'selectAll' checkbox ([bd0f7bcd64845801b96fb57a3de42e914da947f6](https://github.com/Teradata/covalent/commit/bd0f7bcd64845801b96fb57a3de42e914da947f6)), closes [#571](https://github.com/Teradata/covalent/issues/571) * **data-table:** `(rowClick)` event for datatable rows enabled by new `[clickable]` input ([4f84c6ce493996fd749b55d2012f9eb6f4a9e367](https://github.com/Teradata/covalent/commit/4f84c6ce493996fd749b55d2012f9eb6f4a9e367)), closes [#468](https://github.com/Teradata/covalent/issues/468) * **data-table:** select event will be trigger only when clicking on checkbox ([4f84c6ce493996fd749b55d2012f9eb6f4a9e367](https://github.com/Teradata/covalent/commit/4f84c6ce493996fd749b55d2012f9eb6f4a9e367)), closes [#592](https://github.com/Teradata/covalent/issues/592) * **data-table:** shift-click for multiple row selection/deselection ([4f84c6ce493996fd749b55d2012f9eb6f4a9e367](https://github.com/Teradata/covalent/commit/4f84c6ce493996fd749b55d2012f9eb6f4a9e367)) @@ -53,12 +179,12 @@ These selectors were deprecated a few releases back so it should be ok to remove * **dependencies:** upgrade to `material@beta.5` ([b802efbc59e912b8c49fcc8540c77ff98eb829f3](https://github.com/Teradata/covalent/commit/b802efbc59e912b8c49fcc8540c77ff98eb829f3)) * **file:** add new `[formData]` property to TdFileService#upload options ([77c89acd4ba83b43754ce422fd74e6351e2a6297](https://github.com/Teradata/covalent/commit/77c89acd4ba83b43754ce422fd74e6351e2a6297)), closes [#546](https://github.com/Teradata/covalent/issues/546) * **file-upload:** add `cancel` event when cancel button is pressed ([9e3be77fb885928fb54e01adb8d023c3e26d7800](https://github.com/Teradata/covalent/commit/9e3be77fb885928fb54e01adb8d023c3e26d7800)), closes [#499](https://github.com/Teradata/covalent/issues/499) -* **highlight:** added `(contentReady)` event binding. ([b3e800cb5342722a50a97292bc81ea8282d3659e](https://github.com/Teradata/covalent/commit/b3e800cb5342722a50a97292bc81ea8282d3659e)), closes [#553](https://github.com/Teradata/covalent/issues/553) +* **highlight:** added `(contentReady)` event binding. ([b3e800cb5342722a50a97292bc81ea8282d3659e](https://github.com/Teradata/covalent/commit/b3e800cb5342722a50a97292bc81ea8282d3659e)), closes [#553](https://github.com/Teradata/covalent/issues/553) * **layout:** if [navigationRoute] is not set, then the icon/logo/title will not be navigatable. ([dda9b4b5fa6f2b44ce558665c49f1f06b0390237](https://github.com/Teradata/covalent/commit/dda9b4b5fa6f2b44ce558665c49f1f06b0390237)) -* **loading:** support for async and boolean with [until] input ([d57bf6757eb3426bd7404edb4b0d1d51c46f6478](https://github.com/Teradata/covalent/commit/d57bf6757eb3426bd7404edb4b0d1d51c46f6478)), closes [#528](https://github.com/Teradata/covalent/issues/528) +* **loading:** support for async and boolean with [until] input ([d57bf6757eb3426bd7404edb4b0d1d51c46f6478](https://github.com/Teradata/covalent/commit/d57bf6757eb3426bd7404edb4b0d1d51c46f6478)), closes [#528](https://github.com/Teradata/covalent/issues/528) * **markdown:** added `(contentReady)` event binding. ([cdf6cad19b3972259e78809aaff5aca6ba408bb1](https://github.com/Teradata/covalent/commit/cdf6cad19b3972259e78809aaff5aca6ba408bb1)), closes [#536](https://github.com/Teradata/covalent/issues/536) -* **message:** introducing `message` module for easy display of inline messages or info boxes ([8a517fb516ea2344a6471d22ec6b23b8fca8fc60](https://github.com/Teradata/covalent/commit/8a517fb516ea2344a6471d22ec6b23b8fca8fc60)), closes [#316](https://github.com/Teradata/covalent/issues/316) -* **paging:** ability to jump to page `n` with page links in `TdPagingBarComponent` ([459dcb3186a72d4e3f5d51108b7723698a13fffa](https://github.com/Teradata/covalent/commit/459dcb3186a72d4e3f5d51108b7723698a13fffa)), closes [#496](https://github.com/Teradata/covalent/issues/496) +* **message:** introducing `message` module for easy display of inline messages or info boxes ([8a517fb516ea2344a6471d22ec6b23b8fca8fc60](https://github.com/Teradata/covalent/commit/8a517fb516ea2344a6471d22ec6b23b8fca8fc60)), closes [#316](https://github.com/Teradata/covalent/issues/316) +* **paging:** ability to jump to page `n` with page links in `TdPagingBarComponent` ([459dcb3186a72d4e3f5d51108b7723698a13fffa](https://github.com/Teradata/covalent/commit/459dcb3186a72d4e3f5d51108b7723698a13fffa)), closes [#496](https://github.com/Teradata/covalent/issues/496) ## Internal * **chips:** added initial unit tests for `TdChipsComponent` ([755f84664e65dfa52b131406a8979c8f3502f1c2](https://github.com/Teradata/covalent/commit/755f84664e65dfa52b131406a8979c8f3502f1c2)) @@ -155,7 +281,7 @@ These selectors were deprecated a few releases back so it should be ok to remove * **docs:** update docs to updated Material style prefixes ([9142f083e55b77c3f8e89dfde318d23842388f20](https://github.com/Teradata/covalent/commit/9142f083e55b77c3f8e89dfde318d23842388f20)), closes [#410](https://github.com/Teradata/covalent/issues/410) * **docs:** clarify instructions to include the `platform.css` ([5d6bfe5110c29df6986cb4dd15135f0aa784c0f4](https://github.com/Teradata/covalent/commit/5d6bfe5110c29df6986cb4dd15135f0aa784c0f4)) * **docs:** add covalent-electron and covalent-data to README and docs ([878bacecde77f0e824669ed70ff62b89b7daff19](https://github.com/Teradata/covalent/commit/878bacecde77f0e824669ed70ff62b89b7daff19)) -* **theming:** use internal theme functions instead of materials. ([cc74bc154bd076eeaf965686127d9c5cf3c63969](https://github.com/Teradata/covalent/commit/cc74bc154bd076eeaf965686127d9c5cf3c63969))closes [#446](https://github.com/Teradata/covalent/issues/446), [#450](https://github.com/Teradata/covalent/issues/450), [#232](https://github.com/Teradata/covalent/issues/232), [#423](https://github.com/Teradata/covalent/issues/423) +* **theming:** use internal theme functions instead of materials. ([cc74bc154bd076eeaf965686127d9c5cf3c63969](https://github.com/Teradata/covalent/commit/cc74bc154bd076eeaf965686127d9c5cf3c63969))closes [#446](https://github.com/Teradata/covalent/issues/446), [#450](https://github.com/Teradata/covalent/issues/450), [#232](https://github.com/Teradata/covalent/issues/232), [#423](https://github.com/Teradata/covalent/issues/423) # [1.0.0-beta.2-1](https://github.com/Teradata/covalent/tree/v1.0.0-beta.2) (2017-02-27) @@ -173,7 +299,7 @@ These selectors were deprecated a few releases back so it should be ok to remove ## Breaking Change * **material:** [breaking changes](https://github.com/angular/material2/blob/master/CHANGELOG.md#breaking-changes-from-beta1) from `@material`. -* **file-upload:** add way to set its labels for easier i18n usage ([c91d3cdd61358a1af2ad459cd67f56d62070c3c7](https://github.com/Teradata/covalent/commit/c91d3cdd61358a1af2ad459cd67f56d62070c3c7)), closes [#286](https://github.com/Teradata/covalent/issues/286) +* **file-upload:** add way to set its labels for easier i18n usage ([c91d3cdd61358a1af2ad459cd67f56d62070c3c7](https://github.com/Teradata/covalent/commit/c91d3cdd61358a1af2ad459cd67f56d62070c3c7)), closes [#286](https://github.com/Teradata/covalent/issues/286) Usage: @@ -214,7 +340,7 @@ These selectors were deprecated a few releases back so it should be ok to remove ``` npm install --save https://github.com/Teradata/covalent-nightly.git ``` -* **covalent-data:** new `0.7.0` [@covalent/data](https://github.com/Teradata/covalent-data) release. +* **covalent-data:** new `0.7.0` [@covalent/data](https://github.com/Teradata/covalent-data) release. * **data-table:** add a way to configure a specific column as `sortable`. ([3e24fcfd505395da2f18db2fe2dd96f5cc6e8b87](https://github.com/Teradata/covalent/commit/3e24fcfd505395da2f18db2fe2dd96f5cc6e8b87)), closes [#347](https://github.com/Teradata/covalent/issues/347) * **data-table:** leverage the `md-pseudo-checkbox` to render the selectable rows more efficiently. ([717d309d0a31f21c0dc9870ea3f3f3b40f248a07](https://github.com/Teradata/covalent/commit/717d309d0a31f21c0dc9870ea3f3f3b40f248a07)) * **dependencies:** add documentation on how to use `ngx-translate` and `LOCALE_ID`. ([776331bb5bc4098a4264a36e1275b3c83727e61a](https://github.com/Teradata/covalent/commit/776331bb5bc4098a4264a36e1275b3c83727e61a)) @@ -409,7 +535,7 @@ Usage: * **layout:** `td-layout-nav-list` and `td-layout-nav` can be used as standalone without a `td-layout` parent (which will hide/show the menu button depending on that). ([026520cc346721d72c815b0d09fbd469fd3f2ad5](https://github.com/Teradata/covalent/commit/026520cc346721d72c815b0d09fbd469fd3f2ad5)) * **layout:** Removed fixed breakpoint for mobile in `td-layout-nav-list` and `td-layout-manage-list`. ([026520cc346721d72c815b0d09fbd469fd3f2ad5](https://github.com/Teradata/covalent/commit/026520cc346721d72c815b0d09fbd469fd3f2ad5)), closes [#265] (https://github.com/Teradata/covalent/issues/265) -* **layout:** `td-layout-nav-list` and `td-layout-manage-list` new inputs `[opened]`, `[mode]` and `[sidenavWidth]` to allow more flexibility. ([026520cc346721d72c815b0d09fbd469fd3f2ad5](https://github.com/Teradata/covalent/commit/026520cc346721d72c815b0d09fbd469fd3f2ad5)), closes [#180] (https://github.com/Teradata/covalent/issues/180) +* **layout:** `td-layout-nav-list` and `td-layout-manage-list` new inputs `[opened]`, `[mode]` and `[sidenavWidth]` to allow more flexibility. ([026520cc346721d72c815b0d09fbd469fd3f2ad5](https://github.com/Teradata/covalent/commit/026520cc346721d72c815b0d09fbd469fd3f2ad5)), closes [#180] (https://github.com/Teradata/covalent/issues/180) Usage: ```html @@ -520,13 +646,13 @@ ngAfterViewInit(): void { - CovalentDynamicFormsModule (`@covalent/dynamic-forms`) - CovalentHighlightModule (`@covalent/highlight`) - CovalentMarkdownModule (`@covalent/markdown`) - + - `markdown` is a separate module and its theme needs to be imported separatly `@import ~@covalent/markdown/markdown-theme'` and included `@include covalent-markdown-theme($theme);` - `highlight` is a separate module and its theme needs to be imported separatly `@import ~@covalent/highlight/highlight-theme'` and included `@include covalent-highlight-theme();` - `all-theme` and `platform.css` changed directories. - Before: + Before: ```scss `~@covalent/core/styles/platform.css` @@ -602,7 +728,7 @@ ngAfterViewInit(): void { ``` After (once at any toplevel component): - + ```typescript import { DomSanitizer } from '@angular/platform-browser'; import { MdIconRegistry } from '@angular/material'; @@ -634,7 +760,7 @@ ngAfterViewInit(): void { ## Features * **docs:** Added `GETTING_STARTED.md`. ([48dcbc21f10d1a8233cb3835bc4fe20644a00a6d](https://github.com/Teradata/covalent/commit/48dcbc21f10d1a8233cb3835bc4fe20644a00a6d)), closes [#178](https://github.com/Teradata/covalent/issues/178) * **dialogs:** Better a11y ([f6bc8292538bfe0468ee698f23f9911ff3a5ddaf](https://github.com/Teradata/covalent/commit/f6bc8292538bfe0468ee698f23f9911ff3a5ddaf)), closes [#170](https://github.com/Teradata/covalent/issues/170) -* **dialogs:** Exposed open/closeAll methods from MdDialog. ([f6bc8292538bfe0468ee698f23f9911ff3a5ddaf](https://github.com/Teradata/covalent/commit/f6bc8292538bfe0468ee698f23f9911ff3a5ddaf)), closes [#171](https://github.com/Teradata/covalent/issues/171) +* **dialogs:** Exposed open/closeAll methods from MdDialog. ([f6bc8292538bfe0468ee698f23f9911ff3a5ddaf](https://github.com/Teradata/covalent/commit/f6bc8292538bfe0468ee698f23f9911ff3a5ddaf)), closes [#171](https://github.com/Teradata/covalent/issues/171) * **http:** Adding an extra parameter for a `transform` callback in the RESTService methods. ([d73badbe62e7ed5a81be9b3279325b5b46ffc266](https://github.com/Teradata/covalent/commit/d73badbe62e7ed5a81be9b3279325b5b46ffc266)), closes [#179](https://github.com/Teradata/covalent/issues/179) * **http:** Added onRequestError interceptor hook. ([d73badbe62e7ed5a81be9b3279325b5b46ffc266](https://github.com/Teradata/covalent/commit/d73badbe62e7ed5a81be9b3279325b5b46ffc266)) * **http:** Request URL path interceptors. ([7db377e62254f6add6995065f09f4b5528bd0c16](https://github.com/Teradata/covalent/commit/7db377e62254f6add6995065f09f4b5528bd0c16)), closes [#194](https://github.com/Teradata/covalent/issues/194) @@ -658,7 +784,7 @@ ngAfterViewInit(): void { ``` * **dynamic-forms:** Introducing `dynamic-forms` module. ([3eb363873f11b5929655ec4c5ffa822a91fbc5e0](https://github.com/Teradata/covalent/commit/3eb363873f11b5929655ec4c5ffa822a91fbc5e0)), closes [#8](https://github.com/Teradata/covalent/issues/8) - + - Supported TdDynamicType - TdDynamicType.Text (renders md-input-container input type="text") @@ -676,7 +802,7 @@ ngAfterViewInit(): void { - TdDynamicElement.Select (renders md-select) * **notifications:** Introducing `notifications` module. ([746fe3caec62a77bc69b50a2fc0bfcf9b0a9a695](https://github.com/Teradata/covalent/commit/746fe3caec62a77bc69b50a2fc0bfcf9b0a9a695)), closes [#148](https://github.com/Teradata/covalent/issues/148) - + Usage: ```html @@ -895,14 +1021,14 @@ Usage: ... add label content (if not used, falls back to [label] input) ... add content that will be shown when the step is "active" - + ``` ## Internal -* **code-health:** added additional code-health for http forkJoin. ([9ea75f3accf0170a670c446b17f98c447d7a6454](https://github.com/Teradata/covalent/commit/9ea75f3accf0170a670c446b17f98c447d7a6454)), closes [#109](https://github.com/Teradata/covalent/issues/109) -* **dependencies:** Relaxed dependency limitations. ([f67bd1e150559ac1fe7faa22a730a70de5366635](https://github.com/Teradata/covalent/commit/f67bd1e150559ac1fe7faa22a730a70de5366635)), closes [#136](https://github.com/Teradata/covalent/issues/136) -* **http:** Remove covalent/core as dependency from http module and added angular/core and angular/http. ([f67bd1e150559ac1fe7faa22a730a70de5366635](https://github.com/Teradata/covalent/commit/f67bd1e150559ac1fe7faa22a730a70de5366635)), closes [#134](https://github.com/Teradata/covalent/issues/134) +* **code-health:** added additional code-health for http forkJoin. ([9ea75f3accf0170a670c446b17f98c447d7a6454](https://github.com/Teradata/covalent/commit/9ea75f3accf0170a670c446b17f98c447d7a6454)), closes [#109](https://github.com/Teradata/covalent/issues/109) +* **dependencies:** Relaxed dependency limitations. ([f67bd1e150559ac1fe7faa22a730a70de5366635](https://github.com/Teradata/covalent/commit/f67bd1e150559ac1fe7faa22a730a70de5366635)), closes [#136](https://github.com/Teradata/covalent/issues/136) +* **http:** Remove covalent/core as dependency from http module and added angular/core and angular/http. ([f67bd1e150559ac1fe7faa22a730a70de5366635](https://github.com/Teradata/covalent/commit/f67bd1e150559ac1fe7faa22a730a70de5366635)), closes [#134](https://github.com/Teradata/covalent/issues/134) * **dependencies:** Upgrade to `@angular@2.2.1` ([b806afabeda784b285342e3673fcaa20e722d954](https://github.com/Teradata/covalent/commit/b806afabeda784b285342e3673fcaa20e722d954)) * **dependencies:** Upgrade to `@angular-cli@beta.19-3` ([b806afabeda784b285342e3673fcaa20e722d954](https://github.com/Teradata/covalent/commit/b806afabeda784b285342e3673fcaa20e722d954)) @@ -1034,7 +1160,7 @@ After: * **docs:** Added resource docs with axure and sketch downloads for Covalent usage. ([13110bf701e3fdbfd487003b7c88f66b63c4642e](https://github.com/Teradata/covalent/commit/13110bf701e3fdbfd487003b7c88f66b63c4642e)), closes [#55](https://github.com/Teradata/covalent/issues/55) * **docs:** Updated docs with ngModule usage. closes [#65](https://github.com/Teradata/covalent/issues/65) * **release:** Inline html/css in compiled js files. ([23007cd7598a599539cc2e14d4f02735ff84a7a2](https://github.com/Teradata/covalent/commit/23007cd7598a599539cc2e14d4f02735ff84a7a2)), closes [#27](https://github.com/Teradata/covalent/issues/27) -* **release:** Bundle module code into a single `[module].umd.js` to match angular/angular2-material's. ([23007cd7598a599539cc2e14d4f02735ff84a7a2](https://github.com/Teradata/covalent/commit/23007cd7598a599539cc2e14d4f02735ff84a7a2)), closes [#56](https://github.com/Teradata/covalent/issues/56) +* **release:** Bundle module code into a single `[module].umd.js` to match angular/angular2-material's. ([23007cd7598a599539cc2e14d4f02735ff84a7a2](https://github.com/Teradata/covalent/commit/23007cd7598a599539cc2e14d4f02735ff84a7a2)), closes [#56](https://github.com/Teradata/covalent/issues/56) * **covalent-data:** Introducing `Covalent Data` mock server API endpoints for better prototyping. Visit our [repo](https://github.com/Teradata/covalent-data) for more information. * **docs:** Added covalent-data docs for usage with `Covalent Quickstart`. ([c77d42c22d2c9e745431c12b9b19e803e44871c1](https://github.com/Teradata/covalent/commit/c77d42c22d2c9e745431c12b9b19e803e44871c1)) @@ -1063,7 +1189,7 @@ After: * **all:** Updated packaging to match angular/angular2-material's packaging creating a `[module].umd.js` file per module. - Example SystemJS config with UMD bundles: + Example SystemJS config with UMD bundles: ```ts '@covalent/core': { @@ -1072,7 +1198,7 @@ After: } ``` -* **all:** Covalent modules must be included with `forRoot()` when bootstrapping. See the [ngModules guide](https://angular.io/docs/ts/latest/cookbook/ngmodule-faq.html#!#q-for-root) for +* **all:** Covalent modules must be included with `forRoot()` when bootstrapping. See the [ngModules guide](https://angular.io/docs/ts/latest/cookbook/ngmodule-faq.html#!#q-for-root) for more information. ```ts @@ -1152,7 +1278,7 @@ more information.
... -
+ ``` @@ -1195,7 +1321,7 @@ more information. * **loading:** There is a need to add `TD_LOADING_ENTRY_COMPONENTS` in the `precompile` array of your main component, so the `TdLoadingComponent` can be resolved by the `ComponentFactoryResolver`. - e.g. + e.g. ```typescript import { TD_LOADING_ENTRY_COMPONENTS } from '@covalent/core'; diff --git a/package.json b/package.json index 13ea605d49..f5c1bc7361 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "covalent", - "version": "1.0.0-beta.4", + "version": "1.0.0-beta.5", "private": true, "description": "Teradata UI Platform built on Angular Material", "keywords": [ @@ -15,7 +15,7 @@ "postinstall": "webdriver-manager update", "reinstall": "rm -rf node_modules tmp deploy dist && npm i", "webdriver-update": "bash ./node_modules/.bin/webdriver-manager update", - "test": "ng test --code-coverage --single-run", + "test": "ng test --code-coverage --single-run --sourcemap=false", "coverage-win": "start chrome ./coverage/index.html", "coverage-mac": "open -a \"Google Chrome\" coverage/index.html", "coveralls": "cat ./coverage/lcov.info | node ./node_modules/coveralls/bin/coveralls.js", @@ -55,33 +55,33 @@ "Steven Ov " ], "dependencies": { - "@angular/animations": "^4.1.0", - "@angular/common": "^4.1.0", - "@angular/compiler": "^4.1.0", - "@angular/core": "^4.1.0", - "@angular/forms": "^4.1.0", - "@angular/http": "^4.1.0", - "@angular/material": "2.0.0-beta.5", - "@angular/platform-browser": "^4.1.0", - "@angular/platform-browser-dynamic": "^4.1.0", - "@angular/platform-server": "^4.1.0", - "@angular/router": "^4.1.0", - "@ngx-translate/core": "6.0.0", - "@ngx-translate/http-loader": "0.0.3", - "@swimlane/ngx-charts": "5.0.0", + "@angular/animations": "^4.2.0", + "@angular/common": "^4.2.0", + "@angular/compiler": "^4.2.0", + "@angular/core": "^4.2.0", + "@angular/forms": "^4.2.0", + "@angular/http": "^4.2.0", + "@angular/material": "2.0.0-beta.6", + "@angular/platform-browser": "^4.2.0", + "@angular/platform-browser-dynamic": "^4.2.0", + "@angular/platform-server": "^4.2.0", + "@angular/router": "^4.2.0", + "@ngx-translate/core": "7.0.0", + "@ngx-translate/http-loader": "0.1.0", + "@swimlane/ngx-charts": "5.3.1", "core-js": "^2.4.1", "d3": "^4.4.0", "hammerjs": "^2.0.8", "highlight.js": "9.11.0", "rxjs": "^5.2.0", "showdown": "1.6.4", - "web-animations-js": "2.2.2", - "zone.js": "^0.8.6" + "web-animations-js": "2.2.5", + "zone.js": "^0.8.12" }, "devDependencies": { - "@angular/cli": "1.0.3", - "@angular/compiler-cli": "^4.1.0", - "@angular/language-service": "^4.1.0", + "@angular/cli": "1.1.1", + "@angular/compiler-cli": "^4.2.0", + "@angular/language-service": "^4.2.0", "@types/hammerjs": "^2.0.30", "@types/jasmine": "2.5.38", "@types/node": "~6.0.60", @@ -117,6 +117,6 @@ "semver": "5.2.0", "ts-node": "~2.0.0", "tslint": "^5.2.0", - "typescript": "^2.3.1" + "typescript": "^2.3.2" } } diff --git a/src/app/app.component.html b/src/app/app.component.html index 7107236c76..6657080123 100644 --- a/src/app/app.component.html +++ b/src/app/app.component.html @@ -1,7 +1,25 @@ - - - - {{item.icon}}{{item.title}} + + + + + home + Home + + + {{item.icon}} + {{item.title}} + diff --git a/src/app/app.component.ts b/src/app/app.component.ts index dc92ef04b6..b50b568355 100644 --- a/src/app/app.component.ts +++ b/src/app/app.component.ts @@ -1,43 +1,48 @@ -import { Component } from '@angular/core'; +import { Component, AfterViewInit, ChangeDetectorRef } from '@angular/core'; import { DomSanitizer } from '@angular/platform-browser'; -import { MdIconRegistry } from '@angular/material'; - +import { MdIconRegistry, Dir } from '@angular/material'; +import { TdMediaService } from '@covalent/core'; import { TranslateService } from '@ngx-translate/core'; import { getSelectedLanguage } from './utilities/translate'; +import { getDirection } from './utilities/direction'; @Component({ selector: 'docs-covalent', templateUrl: './app.component.html', styleUrls: ['./app.component.scss'], }) -export class DocsAppComponent { +export class DocsAppComponent implements AfterViewInit { routes: Object[] = [{ - icon: 'home', - route: '.', - title: 'Home', - }, { icon: 'library_books', route: 'docs', title: 'Documentation', }, { - icon: 'color_lens', - route: 'style-guide', - title: 'Style Guide', + icon: 'picture_in_picture', + route: 'components', + title: 'Components & Addons', }, { icon: 'view_quilt', route: 'layouts', title: 'Layouts', }, { - icon: 'picture_in_picture', - route: 'components', - title: 'Components & Addons', + icon: 'color_lens', + route: 'style-guide', + title: 'Style Guide', + }, { + icon: 'view_carousel', + route: 'templates', + title: 'Templates', }, ]; + dir: string; + constructor(private _iconRegistry: MdIconRegistry, private _domSanitizer: DomSanitizer, + private _changeDetectorRef: ChangeDetectorRef, + public media: TdMediaService, translateService: TranslateService) { // Set fallback language translateService.setDefaultLang('en'); @@ -54,6 +59,16 @@ export class DocsAppComponent { this._domSanitizer.bypassSecurityTrustResourceUrl('app/assets/icons/github.svg')); this._iconRegistry.addSvgIconInNamespace('assets', 'covalent', this._domSanitizer.bypassSecurityTrustResourceUrl('app/assets/icons/covalent.svg')); + this._iconRegistry.addSvgIconInNamespace('assets', 'covalent-stroke', + this._domSanitizer.bypassSecurityTrustResourceUrl('app/assets/icons/covalent-stroke.svg')); + this._iconRegistry.addSvgIconInNamespace('assets', 'covalent-outline', + this._domSanitizer.bypassSecurityTrustResourceUrl('app/assets/icons/covalent-outline.svg')); + this._iconRegistry.addSvgIconInNamespace('assets', 'angular', + this._domSanitizer.bypassSecurityTrustResourceUrl('app/assets/icons/angular.svg')); + this._iconRegistry.addSvgIconInNamespace('assets', 'angular-outline', + this._domSanitizer.bypassSecurityTrustResourceUrl('app/assets/icons/angular-outline.svg')); + this._iconRegistry.addSvgIconInNamespace('assets', 'material-outline', + this._domSanitizer.bypassSecurityTrustResourceUrl('app/assets/icons/material-outline.svg')); this._iconRegistry.addSvgIconInNamespace('assets', 'teradata-ux', this._domSanitizer.bypassSecurityTrustResourceUrl('app/assets/icons/teradata-ux.svg')); this._iconRegistry.addSvgIconInNamespace('assets', 'appcenter', @@ -62,5 +77,14 @@ export class DocsAppComponent { this._domSanitizer.bypassSecurityTrustResourceUrl('app/assets/icons/listener.svg')); this._iconRegistry.addSvgIconInNamespace('assets', 'querygrid', this._domSanitizer.bypassSecurityTrustResourceUrl('app/assets/icons/querygrid.svg')); + + // set direction + this.dir = getDirection(); } + + ngAfterViewInit(): void { + this.media.broadcast(); + this._changeDetectorRef.detectChanges(); + } + } diff --git a/src/app/app.module.ts b/src/app/app.module.ts index cb73a34a10..60e36f836a 100644 --- a/src/app/app.module.ts +++ b/src/app/app.module.ts @@ -8,23 +8,29 @@ import { TranslateModule, TranslateService, TranslateLoader } from '@ngx-transla import { DocsAppComponent } from './app.component'; import { HomeComponent } from './components/home/home.component'; +import { TemplatesComponent } from './components/templates/templates.component'; import { appRoutes, appRoutingProviders } from './app.routes'; -import { MdButtonModule, MdListModule, MdIconModule, MdCardModule, MdCoreModule, MdMenuModule } from '@angular/material'; +import { MdButtonModule, MdListModule, MdIconModule, MdCardModule, MdCoreModule, MdMenuModule, MdTabsModule, + MdToolbarModule, MdGridListModule, MdTooltipModule } from '@angular/material'; -import { CovalentLayoutModule, CovalentExpansionPanelModule, CovalentNotificationsModule, CovalentMenuModule } from '../platform/core'; +import { CovalentLayoutModule, CovalentExpansionPanelModule, CovalentNotificationsModule, CovalentMenuModule, + CovalentMediaModule } from '../platform/core'; import { CovalentHighlightModule } from '../platform/highlight'; import { CovalentHttpModule } from '../platform/http'; import { CovalentMarkdownModule } from '../platform/markdown'; import { CovalentDynamicFormsModule } from '../platform/dynamic-forms'; -import { GitHubService } from './services'; +import { ToolbarModule } from './components/toolbar/toolbar.module'; + +import { GitHubService, InternalDocsService, SelectivePreloadingStrategyService } from './services'; import { getSelectedLanguage, createTranslateLoader } from './utilities/translate'; @NgModule({ declarations: [ DocsAppComponent, HomeComponent, + TemplatesComponent, ], // directives, components, and pipes owned by this NgModule imports: [ BrowserAnimationsModule, @@ -40,15 +46,21 @@ import { getSelectedLanguage, createTranslateLoader } from './utilities/translat MdIconModule, MdCardModule, MdMenuModule, + MdTabsModule, + MdToolbarModule, + MdGridListModule, + MdTooltipModule, /** Covalent Modules */ CovalentLayoutModule, CovalentExpansionPanelModule, CovalentNotificationsModule, CovalentMenuModule, + CovalentMediaModule, CovalentHttpModule.forRoot(), CovalentHighlightModule, CovalentMarkdownModule, CovalentDynamicFormsModule, + ToolbarModule, TranslateModule.forRoot({ loader: { provide: TranslateLoader, @@ -60,10 +72,12 @@ import { getSelectedLanguage, createTranslateLoader } from './utilities/translat ], // modules needed to run this module providers: [ appRoutingProviders, - GitHubService, { + GitHubService, + InternalDocsService, { // Configure LOCALE_ID depending on the language set in browser provide: LOCALE_ID, useFactory: getSelectedLanguage, deps: [TranslateService], }, + SelectivePreloadingStrategyService, ], // additional providers needed for this module entryComponents: [ ], bootstrap: [ DocsAppComponent ], diff --git a/src/app/app.routes.ts b/src/app/app.routes.ts index 2568e6fe0d..cb07cf7092 100644 --- a/src/app/app.routes.ts +++ b/src/app/app.routes.ts @@ -1,18 +1,29 @@ import { Routes, RouterModule } from '@angular/router'; import { HomeComponent } from './components/home/home.component'; +import { TemplatesComponent } from './components/templates/templates.component'; +import { SelectivePreloadingStrategyService } from './services'; const routes: Routes = [{ component: HomeComponent, path: '', }, { - path: '', loadChildren: './components/docs/docs.module#DocsModule', + component: TemplatesComponent, + path: 'templates', }, { - path: '', loadChildren: './components/style-guide/style-guide.module#StyleGuideModule', + // preload: true loads the module immediately + path: '', data: { preload: false, }, loadChildren: './components/docs/docs.module#DocsModule', }, { - path: '', loadChildren: './components/layouts/layouts.module#LayoutsModule', + // preload: true loads the module immediately + path: '', data: { preload: false, }, loadChildren: './components/style-guide/style-guide.module#StyleGuideModule', }, { - path: '', loadChildren: './components/components/components.module#ComponentsModule', + // preload: true loads the module immediately + path: '', data: { preload: false, }, loadChildren: './components/layouts/layouts.module#LayoutsModule', + }, { + // preload: true loads the module immediately + path: '', data: { preload: true, }, loadChildren: './components/components/components.module#ComponentsModule', + }, { + path: '**', redirectTo: '/', }, ]; @@ -20,4 +31,7 @@ export const appRoutingProviders: any[] = [ ]; -export const appRoutes: any = RouterModule.forRoot(routes, { useHash: true }); +export const appRoutes: any = RouterModule.forRoot(routes, { + useHash: true, + preloadingStrategy: SelectivePreloadingStrategyService, +}); diff --git a/src/app/assets/ico/favicon.ico b/src/app/assets/ico/favicon.ico index f3699612c3..fe7278dc3f 100644 Binary files a/src/app/assets/ico/favicon.ico and b/src/app/assets/ico/favicon.ico differ diff --git a/src/app/assets/icons/angular-outline.svg b/src/app/assets/icons/angular-outline.svg new file mode 100644 index 0000000000..8d31df2cb6 --- /dev/null +++ b/src/app/assets/icons/angular-outline.svg @@ -0,0 +1,13 @@ + + + + angular + Created with Sketch. + + + + + + + + \ No newline at end of file diff --git a/src/app/assets/icons/angular.svg b/src/app/assets/icons/angular.svg new file mode 100644 index 0000000000..96301efe1b --- /dev/null +++ b/src/app/assets/icons/angular.svg @@ -0,0 +1,16 @@ + + + + + + + + + + diff --git a/src/app/assets/icons/covalent-outline.svg b/src/app/assets/icons/covalent-outline.svg new file mode 100644 index 0000000000..74353cdb8a --- /dev/null +++ b/src/app/assets/icons/covalent-outline.svg @@ -0,0 +1,12 @@ + + + Covalent + Copyright 2016-2017 Teradata. + + + + + + + + \ No newline at end of file diff --git a/src/app/assets/icons/covalent-stroke.svg b/src/app/assets/icons/covalent-stroke.svg new file mode 100644 index 0000000000..bb277bc02a --- /dev/null +++ b/src/app/assets/icons/covalent-stroke.svg @@ -0,0 +1,14 @@ + + + covalent-stroke + Created with Sketch. + + + + + + + + + + \ No newline at end of file diff --git a/src/app/assets/icons/covalent.svg b/src/app/assets/icons/covalent.svg index b37a47325d..ee3f0e9e32 100644 --- a/src/app/assets/icons/covalent.svg +++ b/src/app/assets/icons/covalent.svg @@ -1,10 +1,9 @@ - - covalent - Created with Sketch. + Covalent + Copyright 2016-2017 Teradata. - + diff --git a/src/app/assets/icons/material-outline.svg b/src/app/assets/icons/material-outline.svg new file mode 100644 index 0000000000..4fe075d923 --- /dev/null +++ b/src/app/assets/icons/material-outline.svg @@ -0,0 +1,18 @@ + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/src/app/assets/icons/material.svg b/src/app/assets/icons/material.svg new file mode 100644 index 0000000000..a73fac1863 --- /dev/null +++ b/src/app/assets/icons/material.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/app/components/components/chips/chips.component.html b/src/app/components/components/chips/chips.component.html index 3265649bcf..4aac7c41b4 100644 --- a/src/app/components/components/chips/chips.component.html +++ b/src/app/components/components/chips/chips.component.html @@ -1,17 +1,19 @@ - Chips & Autocomplete + Chips & Autocomplete with strings Autocomplete with chips and no custom inputs Demo
-
Type and select a preset option:
+
Type and select a preset option or press enter:
@@ -23,10 +25,12 @@ ]]> @@ -37,8 +41,9 @@ export class ChipsDemoComponent { readOnly: boolean = false; chipAddition: boolean = true; + chipRemoval: boolean = true; - items: string[] = [ + strings: string[] = [ 'stepper', 'expansion-panel', 'markdown', @@ -52,8 +57,25 @@ 'need more?', ]; - itemsRequireMatch: string[] = this.items.slice(0, 6); + filteredStrings: string[]; + stringsModel: string[] = this.strings.slice(0, 6); + + ngOnInit(): void { + this.filterStrings(''); + } + + filterStrings(value: string): void { + this.filteredStrings = this.strings.filter((item: any) => { + if (value) { + return item.toLowerCase().indexOf(value.toLowerCase()) > -1; + } else { + return false; + } + }).filter((filteredItem: any) => { + return this.stringsModel ? this.stringsModel.indexOf(filteredItem) < 0 : true; + }); + } } ]]> @@ -73,18 +95,203 @@ Chip addition + +
+ + Chip removal + +
- Autocomplete with custom inputs - Autocomplete demo allowing custom inputs + Chips & Autocomplete with objects + Autocomplete with chips and templates and accent color + + + + Demo +
+
Type and select a preset option or press enter:
+ + + location_city {{chip.city}}, (Pop: {{chip.population}}) + + +
+ location_city {{option.city}} +
+
+
+
+
+ + Code + +

HTML:

+ + + + location_city { {chip.city} }, (Pop: { {chip.population} }) + + +
+ location_city { {option.city} } +
+
+ + ]]> +
+

Typescript:

+ + { + if (value) { + return obj.city.toLowerCase().indexOf(value.toLowerCase()) > -1; + } else { + return false; + } + }).filter((filteredObj: any) => { + return this.objectsModel ? this.objectsModel.indexOf(filteredObj) < 0 : true; + }); + } + } + ]]> + +
+
+
+
+ + Chips & async Autocomplete with template chip avatar + Load autocomplete items asynchronous when typing in the input + + + + Demo +
+
Type and see how it will load items async:
+ + +
{{chip.substring(0, 1).toUpperCase()}}
{{chip}} +
+ +
+
+
+ + Code + +

HTML:

+ + + +
{ {chip.substring(0, 1).toUpperCase()} }
{ {chip} } +
+ + + ]]> +
+

Typescript:

+ + { + this.filteredAsync = this.strings.filter((item: any) => { + return item.toLowerCase().indexOf(value.toLowerCase()) > -1; + }).filter((filteredItem: any) => { + return this.asyncModel ? this.asyncModel.indexOf(filteredItem) < 0 : true; + }); + this.filteringAsync = false; + }, 2000); + } + } + } + ]]> + +
+
+
+
+ + Stacked chips and Autocomplete with custom inputs + Autocomplete demo allowing custom inputs and stacked chips Demo
Type and select option or enter custom text and press enter:
- + +
@@ -93,7 +300,12 @@

HTML:

+ + ]]>

Typescript:

@@ -101,7 +313,7 @@ { + if (value) { + return item.toLowerCase().indexOf(value.toLowerCase()) > -1; + } else { + return false; + } + }); + } + } ]]> @@ -124,14 +350,14 @@
Custom chips - Demo allowing custom inputs for tags + Demo allowing custom inputs for tags and warn color Demo
Type any test and press enter:
- +
@@ -140,7 +366,7 @@

HTML:

+ ]]>

Typescript:

@@ -155,72 +381,5 @@
- - TdChipsComponent - How to use this component - - -

]]>

-

Use ]]> element to generate a list of strings as chips.

-

Add the [items] attribute to enable the autocomplete with a search list, and [requireMatch] to validate the input against the provided search list.

-

When used with forms, you can track change-states [dirty/pristine] and [touched/untouched].

-

Since [(ngModel)] would be an array, you need to implement a custom validator for [valid/invalid] when its empty.

-

Properties:

-

The ]]> component has {{chipsAttrs.length}} properties:

- - - -

{{attr.name}}: {{attr.type}}

-

{{attr.description}}

-
- -
-
-

Example:

-

HTML:

- - - - ]]> - -

Typescript:

- - - -

Setup:

-

Import the [CovalentChipsModule] in your NgModule:

- - - -
-
+ + diff --git a/src/app/components/components/chips/chips.component.ts b/src/app/components/components/chips/chips.component.ts index c6952a6dcb..fe9da73ea2 100644 --- a/src/app/components/components/chips/chips.component.ts +++ b/src/app/components/components/chips/chips.component.ts @@ -1,4 +1,4 @@ -import { Component, HostBinding } from '@angular/core'; +import { Component, HostBinding, OnInit } from '@angular/core'; import { slideInDownAnimation } from '../../../app.animations'; @@ -8,48 +8,18 @@ import { slideInDownAnimation } from '../../../app.animations'; templateUrl: './chips.component.html', animations: [slideInDownAnimation], }) -export class ChipsDemoComponent { +export class ChipsDemoComponent implements OnInit { @HostBinding('@routeAnimation') routeAnimation: boolean = true; @HostBinding('class.td-route-animation') classAnimation: boolean = true; - chipsAttrs: Object[] = [{ - description: `Enables Autocompletion with the provided list of strings.`, - name: 'items?', - type: 'string[]', - }, { - description: `Disables the chip input and removal.`, - name: 'readOnly?', - type: 'boolean', - }, { - description: `Validates input against the provided search list before adding it to the model. - If it doesnt exist, it cancels the event.`, - name: 'requireMatch?', - type: 'boolean', - }, { - description: `Placeholder for the autocomplete input.`, - name: 'placeholder?', - type: 'string', - }, { - description: `Method to be executed when string is added as chip through the autocomplete. - Sends chip value as event.`, - name: 'add?', - type: 'function', - }, { - description: `Method to be executed when string is removed as chip with the "remove" button. - Sends chip value as event.`, - name: 'remove?', - type: 'function', - }, { - description: `Disables the ability to add chips. If it doesn't exist chipAddition defaults to true.`, - name: 'chipAddition?', - type: 'boolean', - }]; - readOnly: boolean = false; chipAddition: boolean = true; + chipRemoval: boolean = true; + + filteringAsync: boolean = false; - items: string[] = [ + strings: string[] = [ 'stepper', 'expansion-panel', 'markdown', @@ -63,6 +33,82 @@ export class ChipsDemoComponent { 'need more?', ]; - itemsRequireMatch: string[] = this.items.slice(0, 6); + filteredStrings: string[]; + + stringsModel: string[] = this.strings.slice(0, 6); + + objects: any[] = [ + {id: 1, city: 'San Diego', population: '4M'}, + {id: 2, city: 'San Franscisco', population: '6M'}, + {id: 3, city: 'Los Angeles', population: '5M'}, + {id: 4, city: 'Austin', population: '3M'}, + {id: 5, city: 'New York City', population: '10M'}, + ]; + + filteredObjects: string[]; + + objectsModel: string[] = this.objects.slice(0, 2); + + filteredAsync: string[]; + + asyncModel: string[] = this.strings.slice(0, 2); + + filteredStackedStrings: string[]; + + stackedStringsModel: string[] = this.strings.slice(0, 2); + + ngOnInit(): void { + this.filterStrings(''); + this.filterObjects(''); + } + + filterStrings(value: string): void { + this.filteredStrings = this.strings.filter((item: any) => { + if (value) { + return item.toLowerCase().indexOf(value.toLowerCase()) > -1; + } else { + return false; + } + }).filter((filteredItem: any) => { + return this.stringsModel ? this.stringsModel.indexOf(filteredItem) < 0 : true; + }); + } + + filterObjects(value: string): void { + this.filteredObjects = this.objects.filter((obj: any) => { + if (value) { + return obj.city.toLowerCase().indexOf(value.toLowerCase()) > -1; + } else { + return false; + } + }).filter((filteredObj: any) => { + return this.objectsModel ? this.objectsModel.indexOf(filteredObj) < 0 : true; + }); + } + + filterAsync(value: string): void { + this.filteredAsync = undefined; + if (value) { + this.filteringAsync = true; + // Timeout isn't actually needed here, only added for demo to simulate async behavior + setTimeout(() => { + this.filteredAsync = this.strings.filter((item: any) => { + return item.toLowerCase().indexOf(value.toLowerCase()) > -1; + }).filter((filteredItem: any) => { + return this.asyncModel ? this.asyncModel.indexOf(filteredItem) < 0 : true; + }); + this.filteringAsync = false; + }, 2000); + } + } + filterStackedStrings(value: string): void { + this.filteredStackedStrings = this.strings.filter((item: any) => { + if (value) { + return item.toLowerCase().indexOf(value.toLowerCase()) > -1; + } else { + return false; + } + }); + } } diff --git a/src/app/components/components/components.component.html b/src/app/components/components/components.component.html index cf6464ec84..9a82dfca25 100644 --- a/src/app/components/components/components.component.html +++ b/src/app/components/components/components.component.html @@ -1,5 +1,4 @@ Angular Material - {{item.icon}}

{{item.title}}

@@ -56,20 +55,11 @@

{{item.title}}

-
- Covalent Components & Addons - - - - - +
+ Components & Addons +
-
+
\ No newline at end of file diff --git a/src/app/components/components/components.component.ts b/src/app/components/components/components.component.ts index 0a90cc0f94..fecd248123 100644 --- a/src/app/components/components/components.component.ts +++ b/src/app/components/components/components.component.ts @@ -1,5 +1,5 @@ -import { Component, HostBinding, AfterViewInit, ElementRef, Inject, Renderer2 } from '@angular/core'; -import { DOCUMENT } from '@angular/platform-browser'; +import { Component, HostBinding, ChangeDetectorRef, AfterViewInit } from '@angular/core'; + import { TdMediaService } from '@covalent/core'; import { fadeAnimation } from '../../app.animations'; @@ -136,16 +136,12 @@ export class ComponentsComponent implements AfterViewInit { title: 'NGX-Translate', }]; - constructor(public media: TdMediaService, - private _renderer: Renderer2, - @Inject(DOCUMENT) private _document: any) {} + constructor(private _changeDetectorRef: ChangeDetectorRef, + public media: TdMediaService) {} ngAfterViewInit(): void { // broadcast to all listener observables when loading the page this.media.broadcast(); - } - - changeDir(dir: string): void { - this._renderer.setAttribute(this._document.querySelector('html'), 'dir', dir); + this._changeDetectorRef.detectChanges(); } } diff --git a/src/app/components/components/components.module.ts b/src/app/components/components/components.module.ts index b4fd411a94..470c785334 100644 --- a/src/app/components/components/components.module.ts +++ b/src/app/components/components/components.module.ts @@ -34,7 +34,8 @@ import { NgxChartsModule } from '@swimlane/ngx-charts'; import { TranslateModule } from '@ngx-translate/core'; import { MdButtonModule, MdListModule, MdIconModule, MdCardModule, MdMenuModule, MdInputModule, MdButtonToggleModule, MdSlideToggleModule, - MdSelectModule, MdToolbarModule, MdTabsModule, MdTooltipModule, MdCoreModule, MdAutocompleteModule } from '@angular/material'; + MdSelectModule, MdToolbarModule, MdTabsModule, MdTooltipModule, MdCoreModule, MdAutocompleteModule, + MdProgressBarModule } from '@angular/material'; import { CovalentCommonModule, CovalentLayoutModule, CovalentMediaModule, CovalentExpansionPanelModule, CovalentFileModule, CovalentStepsModule, CovalentLoadingModule, CovalentDialogsModule, CovalentSearchModule, CovalentPagingModule, @@ -46,6 +47,8 @@ import { CovalentDynamicFormsModule } from '../../../platform/dynamic-forms'; import { DocumentationToolsModule } from '../../documentation-tools'; +import { ToolbarModule } from '../../components/toolbar/toolbar.module'; + @NgModule({ declarations: [ ComponentsComponent, @@ -92,6 +95,8 @@ import { DocumentationToolsModule } from '../../documentation-tools'; MdToolbarModule, MdTabsModule, MdTooltipModule, + MdProgressBarModule, + MdAutocompleteModule, /** Covalent Modules */ CovalentCommonModule, CovalentLayoutModule, @@ -116,6 +121,7 @@ import { DocumentationToolsModule } from '../../documentation-tools'; NgxChartsModule, TranslateModule, componentsRoutes, + ToolbarModule, ], }) export class ComponentsModule {} diff --git a/src/app/components/components/data-table/data-table.component.html b/src/app/components/components/data-table/data-table.component.html index 1ae1d7d3c9..663cea3d2a 100644 --- a/src/app/components/components/data-table/data-table.component.html +++ b/src/app/components/components/data-table/data-table.component.html @@ -72,7 +72,7 @@

with custom headings, columns, and inline editing

columns: ITdDataTableColumn[] = [ { name: 'sku', label: 'SKU #', tooltip: 'Stock Keeping Unit' }, { name: 'item', label: 'Item name' }, - { name: 'price', label 'Price (US$)', numeric: true, format: v => v.toFixed(2) }, + { name: 'price', label: 'Price (US$)', numeric: true, format: v => v.toFixed(2) }, ]; constructor(private _dialogService: TdDialogService) {} @@ -267,6 +267,7 @@

No results to display.

[multiple]="multiple" [sortable]="true" [sortBy]="sortBy" + [(ngModel)]="selectedRows" [sortOrder]="sortOrder" (sortChange)="sort($event)"> @@ -305,6 +306,7 @@

No results to display.

currentPage: number = 1; pageSize: number = 5; sortBy: string = 'sku'; + selectedRows: any[] = []; sortOrder: TdDataTableSortingOrder = TdDataTableSortingOrder.Descending; constructor(private _dataTableService: TdDataTableService) {} diff --git a/src/app/components/components/directives/directives.component.html b/src/app/components/components/directives/directives.component.html index bf25f1a54b..ec3d52f7a8 100644 --- a/src/app/components/components/directives/directives.component.html +++ b/src/app/components/components/directives/directives.component.html @@ -6,6 +6,22 @@

A directive is essentially like a component functionally without a template. There are structural and attribute directives.

Structural directives can change the DOM layout by adding and removing DOM elements. NgFor and NgIf are two familiar examples.

An Attribute directive can change the appearance or behavior of an element. The built-in NgStyle directive, for example, can change several element styles at the same time.

+ +

Setup:

+

Import the [CovalentCommonModule] in your NgModule:

+ + + @@ -102,32 +118,3 @@ - - - Min/Max Validators - - -

We've added min/max validations since @angular doesnt support them at the moment.

-

Supported:

-
    -
  • TdMinValidator for selector: [min][formControlName],[min][formControl],[min][ngModel]
  • -
  • TdMaxValidator for selector: [max][formControlName],[max][formControl],[max][ngModel]
  • -
-

Example enter lower than 5 or higher than 10:

-
- - - -
-

Errors:

- {{el?.errors | json}} -

HTML:

- - - - - ]]> - -
-
diff --git a/src/app/components/components/expansion-panel/expansion-panel.component.html b/src/app/components/components/expansion-panel/expansion-panel.component.html index 993a400654..d7af2f304e 100644 --- a/src/app/components/components/expansion-panel/expansion-panel.component.html +++ b/src/app/components/components/expansion-panel/expansion-panel.component.html @@ -1,17 +1,146 @@ - Expansion Panels - Expand & collapse containers + Expansion panels + Use single or multiple expansion panels - -

Expand/Collapse Event for Expansion 1: {{expandCollapseExpansion1Msg}}

-
-
- + + + Demo + +
+

md-padding class

+
Demo 1
+
Demo 2
+
Demo 3
+
Demo 4
+
+
+ +
+

md-padding class

+
Demo 5
+
Demo 6
+
Demo 7
+
Demo 8
+
+
+
+ + Code + +

HTML:

+ + +
+

md-padding class

+
Demo 1
+
Demo 2
+
Demo 3
+
Demo 4
+
+
+ +
+

md-padding class

+
Demo 5
+
Demo 6
+
Demo 7
+
Demo 8
+
+
+ ]]> + +

Typescript:

+ + + + + + + + +
+ + Disabled + +
+
+ + + + Grouped Expansion panels + Add margin animation between grouped expansion panels + + + + Demo + + +
+

md-padding class

+
+
+ +
+

md-padding class

+
+
+ +
+

md-padding class

+
+
+
+
+ + Code + +

HTML:

+ + + +
+

md-padding class

+
+
+ +
+

md-padding class

+
+
+ +
+

md-padding class

+
+
+ + ]]> +
+
+
+
+
+ + + Expansion panel with summary and templates + Expand to view form, collapse to view summary + + + + Demo + + + star + Google + + + 1600 Amphitheatre Pkwy, Mountain View, CA 94043, USA + @@ -38,201 +167,155 @@

Headquarters

- -
-

md-padding class

-
Demo 1
-
Demo 2
-
Demo 3
-
Demo 4
-
-
- - - star - Custom Label (template) - - - list - Custom Sublabel (template) - -
-

md-padding class

-
Phase 1
-
Phase 2
-
Phase 3
-
-
-
-
-

The entire panel header can be replaced as well:

-
-
- - - - Custom td-expansion-panel-header - - - -
-
- Owner - chevron_right - John Jameson -
-
- API Key - chevron_right - 1141e8e8-8d24-4956-93c2 -
-
- Last Updated - chevron_right - Wed, July 6, 2016 11:13 AM -
-
-
- -

Metadata

- - account_box -

John Jameson

-

Owner

-
- - - description -

An item description

-

Description

-
- - - vpn_key -

1141e8e8-8d24-4956-93c2

-

API Key

-
- -

Dates

- - access_time -

Wed, July 6, 2016 11:13 AM

-

Last Updated

-
- - - today -

Wed, July 4, 2016 09:11 AM

-

Created

-
-
-
-
-
- - - - - - + + + Code + +

HTML:

+ + + + star + Google + + + 1600 Amphitheatre Pkwy, Mountain View, CA 94043, USA + + + + + pin_drop +

Google

+

Headquarters

+

+ 1600 Amphitheatre Pkwy
Mountain View, CA 94043, USA +

+
+
+
+
+ + + + + + +
+ +
+ + +
+ + ]]> +
+
+
+ + - TdExpansionPanelComponent - How to use this component + Expansion panel with header template + replace the entire header as needed and disable ripple - -

]]>

-

Use ]]> element to add expand/collapse feature to your html blocks

-

Place your html in ]]> element.

-

Behavior:

- -
-

Collapsed panel

-

A collapsed panel displays summary information. Upon selecting the collapsed panel, it expands to display the full expansion panel.

-
- - -

Expanded panel

-

Upon selection, a collapsed panel expands, allowing users to add or edit information. Helper text may be added to the panel to assist the user.

-
- -

Usage:

-

The ]]> component can be used two ways:

- - -

Editing

-

Expansion panels are best used for lightweight editing of an element, such as selecting a value for a setting.

-
- - -

Creation flows

-

Expansion panels may be displayed in a sequence to form creation flows.

-
-
-

Properties:

-

The ]]> component has {{expansionAttrs.length}} properties:

- - - -

{{attr.name}}: {{attr.type}}

-

{{attr.description}}

-
- -
-
-

Example:

-

HTML:

- - + + + Demo + - ... add header content (overrides label and sublabel) - - - ... add label content (if not used, falls back to [label] input) - - - ... add sublabel content (if not used, falls back to [sublabel] input) + + Custom td-expansion-panel-header + - ... add summary that will be shown when expansion-panel is "collapsed". +
+
+ Owner + chevron_right + John Jameson +
+
+ API Key + chevron_right + 1141e8e8-8d24-4956-93c2 +
+
- ... add content that will be shown when the step is "expanded" + +

Metadata

+ + account_box +

John Jameson

+

Owner

+
+ + + description +

An item description

+

Description

+
+ + + vpn_key +

1141e8e8-8d24-4956-93c2

+

API Key

+
+
- ]]> -
-

Typescript:

- - - -

Setup:

-

Import the [CovalentExpansionPanelModule] in your NgModule:

- - - - - + + + Code + +

HTML:

+ + + + + Custom td-expansion-panel-header + + + +
+
+ Owner + chevron_right + John Jameson +
+
+ API Key + chevron_right + 1141e8e8-8d24-4956-93c2 +
+
+
+ +

Metadata

+ + account_box +

John Jameson

+

Owner

+
+ + + description +

An item description

+

Description

+
+ + + vpn_key +

1141e8e8-8d24-4956-93c2

+

API Key

+
+
+ + ]]> +
+
+
+ + + diff --git a/src/app/components/components/expansion-panel/expansion-panel.component.ts b/src/app/components/components/expansion-panel/expansion-panel.component.ts index 5719af48fe..3086977400 100644 --- a/src/app/components/components/expansion-panel/expansion-panel.component.ts +++ b/src/app/components/components/expansion-panel/expansion-panel.component.ts @@ -13,67 +13,6 @@ export class ExpansionPanelDemoComponent { @HostBinding('@routeAnimation') routeAnimation: boolean = true; @HostBinding('class.td-route-animation') classAnimation: boolean = true; - expansionAttrs: Object[] = [{ - description: 'Sets label of [TdExpansionPanelComponent] header. Defaults to "Click to expand"', - name: 'label?', - type: 'string', - }, { - description: 'Sets sublabel of [TdExpansionPanelComponent] header.', - name: 'sublabel?', - type: 'string', - }, { - description: 'Toggles [TdExpansionPanelComponent] between expand/collapse.', - name: 'expand?', - type: 'boolean', - }, { - description: `Hides icon and disables header, blocks click event and sets [TdExpansionPanelComponent] - to collapse if "true".`, - name: 'disabled?', - type: 'boolean', - }, { - description: 'Event emitted when [TdExpansionPanelComponent] is expanded.', - name: 'expanded?', - type: 'function()', - }, { - description: 'Event emitted when [TdExpansionPanelComponent] is collapsed.', - name: 'collapsed?', - type: 'function()', - }, { - description: `Toggle active state of [TdExpansionPanelComponent]. Retuns "true" if successful, else "false". - Can be accessed by referencing element in local variable.`, - name: 'toggle', - type: 'function()', - }, { - description: `Opens [TdExpansionPanelComponent]. Retuns "true" if successful, else "false". - Can be accessed by referencing element in local variable.`, - name: 'open', - type: 'function()', - }, { - description: `Closes [TdExpansionPanelComponent]. Retuns "true" if successful, else "false". - Can be accessed by referencing element in local variable.`, - name: 'close', - type: 'function()', - }]; - - expandCollapseExpansion1Msg: string = 'No expanded/collapsed detected yet'; - expansion1: boolean = false; disabled: boolean = false; - toggleExpansion1(): void { - if (!this.disabled) { - this.expansion1 = !this.expansion1; - } - } - - toggleDisabled(): void { - this.disabled = !this.disabled; - } - - expandExpansion1Event(): void { - this.expandCollapseExpansion1Msg = 'Expand event emitted.'; - } - - collapseExpansion1Event(): void { - this.expandCollapseExpansion1Msg = 'Collapse event emitted.'; - } } diff --git a/src/app/components/components/loading/loading.component.ts b/src/app/components/components/loading/loading.component.ts index 1663647ebf..c796e8aaf3 100644 --- a/src/app/components/components/loading/loading.component.ts +++ b/src/app/components/components/loading/loading.component.ts @@ -113,7 +113,6 @@ export class LoadingDemoComponent implements OnInit { } ngOnInit(): void { - this.toggleDefaultFullscreenDemo(); this.startDirectives(); } @@ -144,7 +143,7 @@ export class LoadingDemoComponent implements OnInit { this.replaceTemplateSyntaxDisabled = true; this._loadingService.register('replaceTemplateSyntax'); let value: number = 0; - let interval: number = setInterval(() => { + let interval: any = setInterval(() => { this._loadingService.setValue('replaceTemplateSyntax', value); value = value + 10; if (value > 100) { diff --git a/src/app/components/components/overview/overview.component.html b/src/app/components/components/overview/overview.component.html index b72ac5ad64..86bd7b0267 100644 --- a/src/app/components/components/overview/overview.component.html +++ b/src/app/components/components/overview/overview.component.html @@ -5,7 +5,7 @@
-
+
{{item.icon}} @@ -28,7 +28,7 @@
-
+
{{item.icon}} @@ -50,7 +50,7 @@
-
+ -
+
{{item.icon}} diff --git a/src/app/components/components/overview/overview.component.ts b/src/app/components/components/overview/overview.component.ts index 03548e424d..ff796eec12 100644 --- a/src/app/components/components/overview/overview.component.ts +++ b/src/app/components/components/overview/overview.component.ts @@ -14,116 +14,116 @@ export class ComponentsOverviewComponent { @HostBinding('class.td-route-animation') classAnimation: boolean = true; items: Object[] = [{ - color: 'deep-purple-700', + color: 'deep-purple-A700', icon: 'view_list', route: 'steps', title: 'Stepper', }, { - color: 'blue-700', + color: 'blue-A700', icon: 'open_with', route: 'expansion-panel', title: 'Expansion Panel', }, { - color: 'light-blue-700', + color: 'pink-A700', icon: 'space_bar', route: 'file-input', title: 'File Input', }, { - color: 'cyan-700', + color: 'cyan-A700', icon: 'attach_file', route: 'file-upload', title: 'File Upload', }, { - color: 'grey-700', + color: 'deep-orange-A700', icon: 'label', route: 'chips', title: 'Chips', }, { - color: 'light-green-700', + color: 'lime-A700', icon: 'hourglass_empty', route: 'loading', title: 'Loading', }, { - color: 'amber-700', + color: 'amber-A700', icon: 'open_in_browser', route: 'dialogs', title: 'Simple Dialogs', }, { - color: 'green-700', + color: 'green-A700', icon: 'grid_on', route: 'data-table', title: 'Data Table', }, { - color: 'teal-700', + color: 'teal-A700', icon: 'format_indent_increase', route: 'json-formatter', title: 'JSON Formatter', }, { - color: 'blue-grey-700', + color: 'indigo-A700', icon: 'swap_horiz', route: 'paging', title: 'Paging', }, { - color: 'purple-700', + color: 'purple-A700', icon: 'notifications', route: 'notifications', title: 'Notifications', }, { - color: 'light-blue-A400', + color: 'light-blue-A700', icon: 'info_outline', route: 'message', title: 'Messages', }, { - color: 'lime-700', + color: 'indigo-A700', icon: 'search', route: 'search', title: 'Search', }, { - color: 'red-700', + color: 'red-A700', icon: 'devices', route: 'media', title: 'Media Queries', }, { - color: 'light-blue-700', + color: 'light-blue-A700', icon: 'wb_iridescent', route: 'directives', title: 'Directives', }, { - color: 'deep-orange-700', + color: 'deep-orange-A700', icon: 'filter_list', route: 'pipes', title: 'Pipes', }, ]; optional: Object[] = [{ - color: 'pink-700', + color: 'pink-A700', icon: 'code', route: 'syntax-highlighting', title: 'Highlighting', }, { - color: 'orange-700', + color: 'orange-A700', icon: 'chrome_reader_mode', route: 'markdown', title: 'Markdown', }, { - color: 'green-700', + color: 'green-A700', icon: 'format_align_center', route: 'dynamic-forms', title: 'Dynamic Forms', }, { - color: 'indigo-700', + color: 'indigo-A700', icon: 'http', route: 'http', title: 'HTTP Service', }, ]; external: Object[] = [{ - color: 'purple-600', + color: 'purple-A700', icon: 'insert_chart', route: 'ngx-charts', title: 'NGX-Charts', }, { - color: 'blue-600', + color: 'blue-A700', icon: 'language', route: 'ngx-translate', title: 'NGX-Translate', diff --git a/src/app/components/components/pipes/pipes.component.html b/src/app/components/components/pipes/pipes.component.html index 484ffe05f1..01cf4550ab 100644 --- a/src/app/components/components/pipes/pipes.component.html +++ b/src/app/components/components/pipes/pipes.component.html @@ -7,6 +7,21 @@
A pipe takes in data as input and transforms it to a desired output.
+

Setup:

+

Import the [CovalentCommonModule] in your NgModule:

+ + + @@ -177,4 +192,15 @@

Original value: { { log.text_value } }

]]> -
\ No newline at end of file + + + + Angular Pipes + + + + launch + Angular comes with a stock of pipes such as DatePipe, UpperCasePipe, LowerCasePipe, CurrencyPipe, and PercentPipe + + + \ No newline at end of file diff --git a/src/app/components/components/steps/steps.component.html b/src/app/components/components/steps/steps.component.html index fdf1ea6571..5dfb34fc82 100644 --- a/src/app/components/components/steps/steps.component.html +++ b/src/app/components/components/steps/steps.component.html @@ -21,7 +21,7 @@

{{horizontal ? 'Horizontal Mode' : 'Vertical Mode'}}

Basic Usage (template) Include any content you like for an active stepper - + This step is required! @@ -50,7 +50,7 @@

{{horizontal ? 'Horizontal Mode' : 'Vertical Mode'}}

Basic Usage (template) Include any content you like for an active stepper
- + This step is required! @@ -195,7 +195,7 @@

Example:

HTML:

+ ... add label content (if not used, falls back to [label] input) diff --git a/src/app/components/components/steps/steps.component.ts b/src/app/components/components/steps/steps.component.ts index 6f5f806893..f1b9328b8b 100644 --- a/src/app/components/components/steps/steps.component.ts +++ b/src/app/components/components/steps/steps.component.ts @@ -46,6 +46,10 @@ export class StepsDemoComponent implements OnInit, OnDestroy { description: 'Sets state of [TdStepComponent] depending on value. Defaults to [StepState.None | "none"]', name: 'state?', type: 'StepState or ["none" | "required" | "complete"]', + }, { + description: ' Whether the ripple effect for this component is disabled', + name: 'disableRipple?', + type: 'boolean', }, { description: 'Event emitted when [TdStepComponent] is activated.', name: 'activated?', diff --git a/src/app/components/docs/docs.component.html b/src/app/components/docs/docs.component.html index a554b53906..96f22fb1a2 100644 --- a/src/app/components/docs/docs.component.html +++ b/src/app/components/docs/docs.component.html @@ -19,9 +19,11 @@

{{item.title}}

-
- Documentation - +
+ Documentation + +
+
+
- \ No newline at end of file diff --git a/src/app/components/docs/docs.component.ts b/src/app/components/docs/docs.component.ts index b38c915cde..f9f2b20af8 100644 --- a/src/app/components/docs/docs.component.ts +++ b/src/app/components/docs/docs.component.ts @@ -1,4 +1,4 @@ -import { Component, HostBinding, AfterViewInit } from '@angular/core'; +import { Component, HostBinding, AfterViewInit, ChangeDetectorRef } from '@angular/core'; import { TdMediaService } from '@covalent/core'; import { fadeAnimation } from '../../app.animations'; @@ -66,11 +66,13 @@ export class DocsComponent implements AfterViewInit { title: 'Testing', }]; - constructor(public media: TdMediaService) {} + constructor(private _changeDetectorRef: ChangeDetectorRef, + public media: TdMediaService) {} ngAfterViewInit(): void { // broadcast to all listener observables when loading the page this.media.broadcast(); + this._changeDetectorRef.detectChanges(); } } diff --git a/src/app/components/docs/docs.module.ts b/src/app/components/docs/docs.module.ts index c00b4cc93d..fd31147211 100644 --- a/src/app/components/docs/docs.module.ts +++ b/src/app/components/docs/docs.module.ts @@ -17,11 +17,14 @@ import { MockDataComponent } from './mock-data/mock-data.component'; import { DocumentationToolsModule } from '../../documentation-tools'; -import { MdButtonModule, MdListModule, MdIconModule, MdCardModule, MdToolbarModule, MdCoreModule } from '@angular/material'; +import { MdButtonModule, MdListModule, MdIconModule, MdCardModule, MdToolbarModule, MdCoreModule, + MdMenuModule } from '@angular/material'; import { CovalentLayoutModule, CovalentMediaModule } from '../../../platform/core'; import { CovalentHighlightModule } from '../../../platform/highlight'; +import { ToolbarModule } from '../../components/toolbar/toolbar.module'; + @NgModule({ declarations: [ DocsComponent, @@ -46,12 +49,14 @@ import { CovalentHighlightModule } from '../../../platform/highlight'; MdIconModule, MdCardModule, MdToolbarModule, + MdMenuModule, /** Covalent Modules */ CovalentLayoutModule, CovalentMediaModule, CovalentHighlightModule, DocumentationToolsModule, docsRoutes, + ToolbarModule, ], }) export class DocsModule {} diff --git a/src/app/components/home/home.component.html b/src/app/components/home/home.component.html index 85c6e1c107..2c75775dc0 100644 --- a/src/app/components/home/home.component.html +++ b/src/app/components/home/home.component.html @@ -1,255 +1,314 @@ -
- - - - -
Updates
- - - - {{item.icon}} -

{{item.description}}

-

{{item.title}}

-
- -
- - change_history -

Angular v4.1 and material@beta.5 support

-

Dependencies updated

+ +
+
+ + +
+
+ - - - - -
-

FAQs

- -
- Covalent is a UI Platform that combines proven design language with a comprehensive web framework, built on Angular & Angular-Material (Design). - Covalent gives you a quickstart to build a modern web application UI and ensure consistency across your enterprise products. - Some of Covalent's most important features include: -
    -
  • Angular-Material
  • -
  • Angular Command-line interface (CLI) for builds, deploys, testing & more.
  • -
  • Drastically simplified interface layouts (for dashboards, lists, etc).
  • -
  • Custom web components (stepper, file upload, expansion panels & more).
  • -
  • 750+ Material Design icons.
  • -
  • Style Guide with brand standards, color palettes & tips.
  • -
  • Design Patterns for consistent, reusable web components such as cards, forms, etc.
  • -
  • Testing Tools for both unit tests and end-to-end tests.
  • -
  • Quickstart app to get started right away!
  • -
-
-
- -
- We follow Atomic Design principles and apply them to Angular-Material web components. In Atomic Design, several atoms (such as buttons and inputs) form molecules (such as a search box). - Our covalent bonds are the molecules that we're building on top of Angular-Material. Also, covalent bonds are liquid and conform to their container, just like our responsive layouts! -
-
- -
- By using Covalent as a unified UI Platform there are a ton of benefits. Here are some highlights: -
    -
  • Angular-Material doesn't have a full app quickstart. Covalent does.
  • -
  • Covalent provides the Angular-Material (AngularJS) flexbox layout that was removed in Angular-Material (angular).
  • -
  • Covalent provides several custom components such as steppers & expansion panels.
  • -
  • Custom layouts & components in Covalent are developed specifically for enterprise solutions.
  • -
  • Covalent provides a selection of UI layouts out of the box.
  • -
  • Our team is continuously adding tools like Syntax Highlighting & Markdown.
  • -
  • Our team will always maintain native compatibility with Angular & Material
  • -
  • Our team will always follow the principles of the official Material Design spec.
  • -
-
-
- -
- By adopting Material Design along with Angular, we get a style guide spec that is perfectly matched with an incredbly powerful and modern web framework, all for free. - Along with that, there are lots of other great benefits such as: -
    -
  • A design spec that is married to code implementation.
  • -
  • Official implementations from the the designer/developer (Google).
  • -
  • Free code implementation and updates from a continuously evolving design spec.
  • -
  • Compatability with many devices & breakpoints, from watch and mobile all the way up to fullscreen desktop.
  • -
  • Usage familiarity for users, designers & developers.
  • -
  • Focus on out-of the box accessibility.
  • -
  • Open sourced design & code.
  • -
  • Modularity that gives a natural bridge to agile development principles.
  • -
  • Inspiration, community & resources from around the world.
  • -
-
-
- -
- With any new framework, people's intial reaction is that they'll lose their company brand or identity. - Consider when 960 grids came out, or Bootstrap from Twitter. Many said "all sites will look the same!". - They weren't completely wrong, for a time, when adoption of these new frameworks began. However, with time, usage, and innovation, your special brand identity and uniqueness will always shine through! - Also consider: -
    -
  • Material Design is being embraced across the web, and is not specific to Google anymore
  • -
  • Material Design can be thought of as a native Web SDK, similar to developing a MacOS or iOS app.
  • -
  • Onboarding users is a simpler process if design patterns are familiar.
  • -
  • Think of your favorite iOS, Android or Windows app that adheres to the OS's design. Aren’t the features more important? What woud you really consider “brand”?
  • -
-
-
- -
-

The short answer: we had to pick something & we believe Angular has won the adoption war.

- The longer answer: - Before passing judgement if you have Angular 1.x experience, remember that Angular is a complete rewrite from the ground up. - Angular moved from an opinionated framework to a sophistated platform. - Angular utilizes ES2015 (previously ES6) and the power of Typescript, which results in a much more native JavaScript platform with coding paradigms & power previously reserved for backend languages. - This means many more back end engineers can jump into the front end and ramp up quickly to productivity. - Also there are many other benefits, such as: -
    -
  • New & exciting software to learn & advocate
  • -
  • More easily attract new hires
  • -
  • An incredibly powerful standardized CLI that is provided to us
  • -
  • More powerful IDEs for development
  • -
  • Integrated testing tools
  • -
  • Native mobile & desktop app support
  • -
-
-
- -
- We give you everything you need to quickly get started on your UI, but you have the domain knowledge and are the expert in your product. - You'll need to build all the custom views, controllers & services for your product, and hook them up to your RESTful APIs. - Don't worry though, we have detailed docs & tips, and there's a wealth of help on the internet (it's why we chose such a popular platform). -
-
- -
- We'd LOVE any type of contribution and collaboration! There's all kinds of ways you can join in: -
    -
  • Submit a bug (cool)
  • -
  • Open a pull request to fix a bug (cooler)
  • -
  • Suggest a new feature (which we'll prioritize by demand)
  • -
  • Open a pull request with new feature (make sure it follows the guidelines)
  • -
  • Give us feedback on any aspect of this site or the platform
  • -
  • Join the Teradata UX team!
  • -
+
+
+
+
+
+
+
+

Built with favorite on Angular

+

Teradata is one of the largest enterprise consumers of Angular. Currently the entire product suite is being built or revamped on Angular v4.

+

As Angular unites Teradata developers across the organization, they are able to contribute back to the open-source community with the powerful new tools being developed internally.

- - -
- - -
- To build an atomic, standardized, reusable UI component platform based on Material Design, for Teradata to use for all user interfaces, while collaborating in an open source model. +
+
+
+ +
+
+
+
+
+
+
+
+ + + + {{item.icon}} +

{{item.title}}

+

{{item.description}}

+
+ +
+
+
+ + - - -
- Teradata's UX team is extremely lean & agile (notice agile is lower case). We have a simple list of milestones and issues prioritized by demand across products. - Some big ticket items are underway such as TD Charts, an extensive & standardized component built on Google Charts (continuing w/ the Google web stack). - We're also building Dynamic Forms which will allow products to build complex forms with a simple key:value pair JSON structure. - Remember, we're agile so our roadmap is iterative & bite sized for frequent, rapid releases. +
- - - launch -

Releases

-

Our latest version you can use today!

-
- - - launch -

Milestones

-

Rough time estimates

-
- - - launch -

Feature Requests & Bugs

-

Priotized by demand

-
-
- - -
- Covalent is a UI Platform that combines proven design language with a comprehensive web framework, built on Angular & Angular-Material (Design). - Electron is a framework for creating native desktop applications with web technologies like JavaScript, HTML, and CSS. - Covalent Electron is the Electron Platform to build desktop apps using Covalent and Electron - View Repo -
-
- -
- Covalent Data is a Mock API server for rapid prototyping and API standards - Built on Golang - Allows for quick prototyping for your Covalent Applications with an easy to mock http backend server - View Repo +
+
+
+
+
+
+
+
+
+

Following the Material Design spec

+

Covalent follows the Material Design specification as closely as possible through the construction of all components.

+

Adopting Material Design as our own spec allows our UI/UX staff to adopt and share powerful open-source resources, while Covalent end users enjoy the immediate familiarity and affordance of this global deign spec.

- +
+
+
+ +
- - -
- Copyright © 2016 - 2017 Teradata. All rights reserved +
+
+
+
+
+

FAQs

+ + +
+ Covalent is a UI Platform that combines proven design language with a comprehensive web framework, built on Angular & Angular-Material (Design). + Covalent gives you a quickstart to build a modern web application UI and ensure consistency across your enterprise products. + Some of Covalent's most important features include: +
    +
  • Angular-Material
  • +
  • Angular Command-line interface (CLI) for builds, deploys, testing & more.
  • +
  • Drastically simplified interface layouts (for dashboards, lists, etc).
  • +
  • Custom web components (stepper, file upload, expansion panels & more).
  • +
  • 750+ Material Design icons.
  • +
  • Style Guide with brand standards, color palettes & tips.
  • +
  • Design Patterns for consistent, reusable web components such as cards, forms, etc.
  • +
  • Testing Tools for both unit tests and end-to-end tests.
  • +
  • Quickstart app to get started right away!
  • +
+
+
+ +
+ We follow Atomic Design principles and apply them to Angular-Material web components. In Atomic Design, several atoms (such as buttons and inputs) form molecules (such as a search box). + Our covalent bonds are the molecules that we're building on top of Angular-Material. Also, covalent bonds are liquid and conform to their container, just like our responsive layouts! +
+
+ +
+ By using Covalent as a unified UI Platform there are a ton of benefits. Here are some highlights: +
    +
  • Angular-Material doesn't have a full app quickstart. Covalent does.
  • +
  • Covalent provides the Angular-Material (AngularJS) flexbox layout that was removed in Angular-Material (angular).
  • +
  • Covalent provides several custom components such as steppers & expansion panels.
  • +
  • Custom layouts & components in Covalent are developed specifically for enterprise solutions.
  • +
  • Covalent provides a selection of UI layouts out of the box.
  • +
  • Our team is continuously adding tools like Syntax Highlighting & Markdown.
  • +
  • Our team will always maintain native compatibility with Angular & Material
  • +
  • Our team will always follow the principles of the official Material Design spec.
  • +
+
+
+ +
+ By adopting Material Design along with Angular, we get a style guide spec that is perfectly matched with an incredbly powerful and modern web framework, all for free. + Along with that, there are lots of other great benefits such as: +
    +
  • A design spec that is married to code implementation.
  • +
  • Official implementations from the the designer/developer (Google).
  • +
  • Free code implementation and updates from a continuously evolving design spec.
  • +
  • Compatability with many devices & breakpoints, from watch and mobile all the way up to fullscreen desktop.
  • +
  • Usage familiarity for users, designers & developers.
  • +
  • Focus on out-of the box accessibility.
  • +
  • Open sourced design & code.
  • +
  • Modularity that gives a natural bridge to agile development principles.
  • +
  • Inspiration, community & resources from around the world.
  • +
+
+
+ +
+ With any new framework, people's intial reaction is that they'll lose their company brand or identity. + Consider when 960 grids came out, or Bootstrap from Twitter. Many said "all sites will look the same!". + They weren't completely wrong, for a time, when adoption of these new frameworks began. However, with time, usage, and innovation, your special brand identity and uniqueness will always shine through! + Also consider: +
    +
  • Material Design is being embraced across the web, and is not specific to Google anymore
  • +
  • Material Design can be thought of as a native Web SDK, similar to developing a MacOS or iOS app.
  • +
  • Onboarding users is a simpler process if design patterns are familiar.
  • +
  • Think of your favorite iOS, Android or Windows app that adheres to the OS's design. Aren’t the features more important? What woud you really consider “brand”?
  • +
+
+
+ +
+

The short answer: we had to pick something & we believe Angular has won the adoption war.

+ The longer answer: + Before passing judgement if you have Angular 1.x experience, remember that Angular v2+ is a complete rewrite from the ground up. + Angular moved from an opinionated framework to a sophistated platform. + Angular utilizes ES2015 (previously ES6) and the power of Typescript, which results in a much more native JavaScript platform with coding paradigms & power previously reserved for backend languages. + This means many more back end engineers can jump into the front end and ramp up quickly to productivity. + Also there are many other benefits, such as: +
    +
  • New & exciting software to learn & advocate
  • +
  • More easily attract new hires
  • +
  • An incredibly powerful standardized CLI that is provided to us
  • +
  • More powerful IDEs for development
  • +
  • Integrated testing tools
  • +
  • Native mobile & desktop app support
  • +
+
+
+ +
+ We give you everything you need to quickly get started on your UI, but you have the domain knowledge and are the expert in your product. + You'll need to build all the custom views, controllers & services for your product, and hook them up to your RESTful APIs. + Don't worry though, we have detailed docs & tips, and there's a wealth of help on the internet (it's why we chose such a popular platform). +
+
+ +
+ We'd LOVE any type of contribution and collaboration! There's all kinds of ways you can join in: +
    +
  • Submit a bug (cool)
  • +
  • Open a pull request to fix a bug (cooler)
  • +
  • Suggest a new feature (which we'll prioritize by demand)
  • +
  • Open a pull request with new feature (make sure it follows the guidelines)
  • +
  • Give us feedback on any aspect of this site or the platform
  • +
  • Join the Teradata UX team!
  • +
+
+
+ +
+ + +
+ To build an atomic, standardized, reusable UI component platform based on Material Design, for Teradata to use for all user interfaces, while collaborating in an open source model. +
+
+
+
+ Teradata's UX team is extremely lean & agile (notice agile is lower case). We have a simple list of milestones and issues prioritized by demand across products. + Some big ticket items are underway such as TD Charts, an extensive & standardized component built on Google Charts (continuing w/ the Google web stack). + We're also building Dynamic Forms which will allow products to build complex forms with a simple key:value pair JSON structure. + Remember, we're agile so our roadmap is iterative & bite sized for frequent, rapid releases. +
+
+ + + launch +

Releases

+

Our latest version you can use today!

+
+ + + launch +

Milestones

+

Rough time estimates

+
+ + + launch +

Feature Requests & Bugs

+

Priotized by demand

+
+
+
+ +
+ Covalent is a UI Platform that combines proven design language with a comprehensive web framework, built on Angular & Angular-Material (Design). + Electron is a framework for creating native desktop applications with web technologies like JavaScript, HTML, and CSS. + Covalent Electron is the Electron Platform to build desktop apps using Covalent and Electron + View Repo +
+
+ +
+ Covalent Data is a Mock API server for rapid prototyping and API standards + Built on Golang + Allows for quick prototyping for your Covalent Applications with an easy to mock http backend server + View Repo +
+
+
+
+
+
+
+ +
+
Copyright © 2016 - 2017 Teradata. All rights reserved
- +
diff --git a/src/app/components/home/home.component.scss b/src/app/components/home/home.component.scss index 5b11e4278c..35ad04d7f1 100644 --- a/src/app/components/home/home.component.scss +++ b/src/app/components/home/home.component.scss @@ -9,9 +9,26 @@ width: 60px; margin-left: 16px; } +.mat-icon-svg-xxl { + width: 90%; + height: auto; +} .md-icon-ux { width: 165px; } -[td-after-card] { - margin: 64px 8px 8px 8px; +@media (max-width: 799px) { + .mat-icon-md { + font-size: 50px; + } + .mat-icon-xl { + font-size: 120px; + } +} +@media (min-width: 800px) { + .mat-icon-md { + font-size: 70px; + } + .mat-icon-xl { + font-size: 160px; + } } \ No newline at end of file diff --git a/src/app/components/home/home.component.ts b/src/app/components/home/home.component.ts index c65630815a..9bf61853be 100644 --- a/src/app/components/home/home.component.ts +++ b/src/app/components/home/home.component.ts @@ -1,5 +1,5 @@ -import { Component, HostBinding, OnInit } from '@angular/core'; - +import { Component, HostBinding, AfterViewInit } from '@angular/core'; +import { TdMediaService } from '@covalent/core'; import { GitHubService } from '../../services'; import { fadeAnimation } from '../../app.animations'; @@ -11,102 +11,73 @@ import { fadeAnimation } from '../../app.animations'; animations: [fadeAnimation], }) -export class HomeComponent implements OnInit { +export class HomeComponent implements AfterViewInit { @HostBinding('@routeAnimation') routeAnimation: boolean = true; @HostBinding('class.td-route-animation') classAnimation: boolean = true; starCount: number = 0; - items: Object[] = [{ - color: 'purple-700', + sections: Object[] = [{ + color: 'deep-purple-A400', description: 'Your guide to start using the UI platform in your app!', icon: 'library_books', route: 'docs', title: 'Documentation', }, { - color: 'blue-700', - description: 'Teradata brand logo usage, color palettes and more', - icon: 'color_lens', - route: 'style-guide', - title: 'Style Guide', + color: 'teal-A700', + description: 'Covalent Components, Directives, Pipes & Services', + icon: 'picture_in_picture', + route: 'components', + title: 'Components', }, { - color: 'teal-700', + color: 'cyan-A700', description: 'Several different material design layout options for your apps', icon: 'view_quilt', route: 'layouts', title: 'Layouts', }, { - color: 'green-700', - description: 'Covalent Components, Directives, Pipes & Services', - icon: 'picture_in_picture', - route: 'components', - title: 'Components & Addons', + color: 'indigo-A400', + description: 'Teradata brand logo usage, color palettes and more', + icon: 'color_lens', + route: 'style-guide', + title: 'Style Guide', + }, { + color: 'green-A700', + description: 'Gallery of example applications and usages', + icon: 'view_carousel', + route: 'templates', + title: 'Templates', }, ]; - updates: Object[] = [{ - description: 'Keyboard support for selection', - icon: 'grid_on', - route: 'components/data-table', - title: 'Data Table feature', - }, { - description: 'Row click events', - icon: 'grid_on', - route: 'components/data-table', - title: 'Data Table feature', - }, { - description: 'Hide columns & exclude from filtering', - icon: 'grid_on', - route: 'components/data-table', - title: 'Data Table feature', - }, { - description: 'Async & boolean loading', - icon: 'hourglass_empty', - route: 'components/loading', - title: 'Loading features', + repos: Object[] = [{ + color: 'amber-A400', + description: 'A pre-built Angular 4 app using Covalent ready to go!', + icon: 'flash_on', + link: 'https://github.com/Teradata/covalent-quickstart', + title: 'Covalent Quickstart', }, { - description: 'Component for alerts/info/warning/error/success', - icon: 'info_outline', - route: 'components/message', - title: 'New Messages component', + color: 'orange-A400', + description: 'A native desktop hybrid starter app built on Electron.', + icon: 'laptop_mac', + link: 'https://github.com/Teradata/covalent-electron', + title: 'Covalent Electron', }, { - description: 'Numbered page links to jump ahead', - icon: 'swap_horiz', - route: 'components/paging', - title: 'Pagination feature', - }, { - description: 'Disable adding of chips', - icon: 'label', - route: 'components/chips', - title: 'Chips feature', - }, { - description: 'New formData property', - icon: 'attach_file', - route: 'components/file-upload', - title: 'File service feature', - }, { - description: 'New contentReady event binding', - icon: 'chrome_reader_mode', - route: 'components/markdown', - title: 'Markdown feature', - }, { - description: 'New contentReady event binding', - icon: 'code', - route: 'components/highlight', - title: 'Highlight feature', - }, { - description: 'Make navigationRoute optional', - icon: 'view_quilt', - route: 'components/layouts', - title: 'Layouts feature', + color: 'deep-orange-A400', + description: 'Mock API server for rapid prototyping and API standards.', + icon: 'aspect_ratio', + link: 'https://github.com/Teradata/covalent-data', + title: 'Covalent Data', }, ]; - constructor(private _gitHubService: GitHubService) { + constructor(private _gitHubService: GitHubService, + public media: TdMediaService) { } - ngOnInit(): void { + ngAfterViewInit(): void { + this.media.broadcast(); this._gitHubService.queryStartCount().subscribe((starsCount: number) => { this.starCount = starsCount; }); diff --git a/src/app/components/layouts/card-over/card-over.component.html b/src/app/components/layouts/card-over/card-over.component.html index 87f14599a2..59f50e6ba9 100644 --- a/src/app/components/layouts/card-over/card-over.component.html +++ b/src/app/components/layouts/card-over/card-over.component.html @@ -1,4 +1,5 @@ + Card Over Layout A card overlaying a toolbar (this page is using card over) diff --git a/src/app/components/layouts/layouts.module.ts b/src/app/components/layouts/layouts.module.ts index af4b83f962..29cb47ce20 100644 --- a/src/app/components/layouts/layouts.module.ts +++ b/src/app/components/layouts/layouts.module.ts @@ -17,6 +17,8 @@ import { CovalentHighlightModule } from '../../../platform/highlight'; import { DocumentationToolsModule } from '../../documentation-tools'; +import { ToolbarModule } from '../../components/toolbar/toolbar.module'; + @NgModule({ declarations: [ LayoutsComponent, @@ -44,6 +46,7 @@ import { DocumentationToolsModule } from '../../documentation-tools'; CovalentHighlightModule, DocumentationToolsModule, layoutsRoutes, + ToolbarModule, ], }) export class LayoutsModule {} diff --git a/src/app/components/layouts/manage-list/manage-list.component.html b/src/app/components/layouts/manage-list/manage-list.component.html index 14b8787b9d..f4d246648d 100644 --- a/src/app/components/layouts/manage-list/manage-list.component.html +++ b/src/app/components/layouts/manage-list/manage-list.component.html @@ -1,5 +1,6 @@ - + diff --git a/src/app/components/layouts/manage-list/manage-list.component.ts b/src/app/components/layouts/manage-list/manage-list.component.ts index 912ecc7957..66470202c8 100644 --- a/src/app/components/layouts/manage-list/manage-list.component.ts +++ b/src/app/components/layouts/manage-list/manage-list.component.ts @@ -1,4 +1,4 @@ -import { Component, HostBinding, AfterViewInit, ChangeDetectionStrategy } from '@angular/core'; +import { Component, HostBinding, AfterViewInit, ChangeDetectionStrategy, ChangeDetectorRef } from '@angular/core'; import { TdMediaService } from '@covalent/core'; import { fadeAnimation } from '../../../app.animations'; @@ -15,11 +15,15 @@ export class ManageListComponent implements AfterViewInit { @HostBinding('@routeAnimation') routeAnimation: boolean = true; @HostBinding('class.td-route-animation') classAnimation: boolean = true; - constructor(public media: TdMediaService) {} + constructor(private _changeDetectorRef: ChangeDetectorRef, + public media: TdMediaService) {} ngAfterViewInit(): void { // broadcast to all listener observables when loading the page - this.media.broadcast(); + Promise.resolve(undefined).then(() => { + this.media.broadcast(); + this._changeDetectorRef.markForCheck(); + }); } } diff --git a/src/app/components/layouts/nav-list/nav-list.component.html b/src/app/components/layouts/nav-list/nav-list.component.html index 5bb057dcc3..a17ecee8ab 100644 --- a/src/app/components/layouts/nav-list/nav-list.component.html +++ b/src/app/components/layouts/nav-list/nav-list.component.html @@ -18,9 +18,9 @@

Item Name

item description

-
- Page Title - +
+ Nav List +
Nav List Layout diff --git a/src/app/components/layouts/nav-list/nav-list.component.ts b/src/app/components/layouts/nav-list/nav-list.component.ts index e53ea52e63..31e685a7f2 100644 --- a/src/app/components/layouts/nav-list/nav-list.component.ts +++ b/src/app/components/layouts/nav-list/nav-list.component.ts @@ -1,4 +1,4 @@ -import { Component, HostBinding, AfterViewInit, ChangeDetectionStrategy } from '@angular/core'; +import { Component, HostBinding, AfterViewInit, ChangeDetectionStrategy, ChangeDetectorRef } from '@angular/core'; import { TdMediaService } from '@covalent/core'; import { fadeAnimation } from '../../../app.animations'; @@ -15,11 +15,15 @@ export class NavListComponent implements AfterViewInit { @HostBinding('@routeAnimation') routeAnimation: boolean = true; @HostBinding('class.td-route-animation') classAnimation: boolean = true; - constructor(public media: TdMediaService) {} + constructor(private _changeDetectorRef: ChangeDetectorRef, + public media: TdMediaService) {} ngAfterViewInit(): void { // broadcast to all listener observables when loading the page - this.media.broadcast(); + Promise.resolve(undefined).then(() => { + this.media.broadcast(); + this._changeDetectorRef.markForCheck(); + }); } } diff --git a/src/app/components/layouts/nav-view/nav-view.component.html b/src/app/components/layouts/nav-view/nav-view.component.html index 5bf2418deb..cdee9ddbb4 100644 --- a/src/app/components/layouts/nav-view/nav-view.component.html +++ b/src/app/components/layouts/nav-view/nav-view.component.html @@ -1,4 +1,5 @@ +
Nav View diff --git a/src/app/components/layouts/overview/overview.component.html b/src/app/components/layouts/overview/overview.component.html index 9262571359..6397c947d3 100644 --- a/src/app/components/layouts/overview/overview.component.html +++ b/src/app/components/layouts/overview/overview.component.html @@ -1,4 +1,5 @@ +

For your entire app or for different sections of your app, select one of these Material Design layout options:

@@ -25,145 +26,147 @@

{{item.title}}

Flexbox Layout ("grid")

- -
-

We've ported the CSS3 Flexbox layout system from Angular-Material v1, so those docs shoud be your starting point.

-

In a nutshell, the Flexbox layout gives you:

-
    -
  • Horizontal row layout for child elements
  • -
  • Vertical column layout for child elements
  • -
  • Alignment & ordering for child elements
  • -
  • Any "flex" elastic width for child elements
  • -
  • Conditionally responsive versions for xs,sm,md,lg,xl breakpoints
  • -
-
-
- -
-

Horizontal row container:

-
-
child
-
child
-
child
+ + +
+

We've ported the CSS3 Flexbox layout system from Angular-Material v1, so those docs shoud be your starting point.

+

In a nutshell, the Flexbox layout gives you:

+
    +
  • Horizontal row layout for child elements
  • +
  • Vertical column layout for child elements
  • +
  • Alignment & ordering for child elements
  • +
  • Any "flex" elastic width for child elements
  • +
  • Conditionally responsive versions for xs,sm,md,lg,xl breakpoints
  • +
- - - -
child
-
child
-
child
-
- ]]> - - -

Vertical column container:

-
-
child
-
child
-
child
+ + +
+

Horizontal row container:

+
+
child
+
child
+
child
+
+ + + +
child
+
child
+
child
+
+ ]]> + + +

Vertical column container:

+
+
child
+
child
+
child
+
+ + + +
child
+
child
+
child
+
+ ]]> +
- - - -
child
-
child
-
child
-
- ]]> - -
- - -
-

Layout margin

-
-
child
-
child
-
child
+ + +
+

Layout margin

+
+
child
+
child
+
child
+
+ + + +
child
+
child
+
child
+
+ ]]> + + +

Layout padding

+
+
child
+
child
+
child
+
+ + + +
child
+
child
+
child
+
+ ]]> +
- - - -
child
-
child
-
child
-
- ]]> - - -

Layout padding

-
-
child
-
child
-
child
+ + +
+

40/flex/30 (notice how flex fills remaining space):

+
+
child
+
child
+
child
+
+ + + +
child
+
child
+
child
+
+ ]]> + + +

Responsive widths (will change as you resize browser):

+
+
child
+
child
+
child
+
+ + + +
child
+
child
+
child
+
+ ]]> + + +

Typical responsive layout (just collapse on xs which is mobile)

+
+
child
+
child
+
+ + + +
child
+
child
+
+ ]]> +
- - - -
child
-
child
-
child
-
- ]]> - -
- - -
-

40/flex/30 (notice how flex fills remaining space):

-
-
child
-
child
-
child
-
- - - -
child
-
child
-
child
-
- ]]> - - -

Responsive widths (will change as you resize browser):

-
-
child
-
child
-
child
-
- - - -
child
-
child
-
child
-
- ]]> - - -

Typical responsive layout (just collapse on xs which is mobile)

-
-
child
-
child
-
- - - -
child
-
child
-
- ]]> - -
- + +
diff --git a/src/app/components/style-guide/cards/cards.component.html b/src/app/components/style-guide/cards/cards.component.html index 68d2ced694..746d9a9ec6 100644 --- a/src/app/components/style-guide/cards/cards.component.html +++ b/src/app/components/style-guide/cards/cards.component.html @@ -300,8 +300,8 @@

Item { {i} }

- Card with header & images - A card with header, avatar & image + Card with various components + A card with header, images, action icons & progress bar
@@ -311,11 +311,23 @@

Item { {i} }

Header title Header subtitle - +

Content title

Here is some more content

+ + +
+ + + + +
+
+ + +
@@ -326,16 +338,115 @@

Content title

Header title Header subtitle - +

Content title

Here is some more content

+ + +
+ + + + +
+
+ + +
]]> + + Card with image variations + md-card-sm-image, md-card-md-image, md-card-lg-image & md-card-title-group + + +
+
+ + + Card with image first + 100% width image + + Notice if the image is first it has proper rounded corners. + + +
+
+ + + Card with small image + 80px x 80px image + + + +
+
+ + + Card with medium image + 112px x 112px image + + + +
+
+ + + Card with large image + 152px x 152px image + + + +
+
+ + + + + Card with image first + 100% width image + + Notice if the image is first it has proper rounded corners. + + +
+
+ + + Card with small image + 80px x 80px image + + + +
+
+ + + Card with medium image + 112px x 112px image + + + +
+
+ + + Card with large image + 152px x 152px image + + + +
+ ]]> + +
+
Resources @@ -345,6 +456,11 @@

Content title

Card Specs + + launch + Angular Material Card Docs + + launch Google Now Cards diff --git a/src/app/components/style-guide/style-guide.component.html b/src/app/components/style-guide/style-guide.component.html index 6eefac4055..048ad80ce9 100644 --- a/src/app/components/style-guide/style-guide.component.html +++ b/src/app/components/style-guide/style-guide.component.html @@ -34,8 +34,10 @@

{{item.title}}

- Teradata Style Guide - + Style Guide + +
+
+
- diff --git a/src/app/components/style-guide/style-guide.component.ts b/src/app/components/style-guide/style-guide.component.ts index 1330fc6d2e..eb11169230 100644 --- a/src/app/components/style-guide/style-guide.component.ts +++ b/src/app/components/style-guide/style-guide.component.ts @@ -1,4 +1,4 @@ -import { Component, HostBinding, AfterViewInit } from '@angular/core'; +import { Component, HostBinding, AfterViewInit, ChangeDetectorRef } from '@angular/core'; import { TdMediaService } from '@covalent/core'; import { fadeAnimation } from '../../app.animations'; @@ -72,10 +72,12 @@ export class StyleGuideComponent implements AfterViewInit { title: 'Navigation Drawer', }]; - constructor(public media: TdMediaService) {} + constructor(private _changeDetectorRef: ChangeDetectorRef, + public media: TdMediaService) {} ngAfterViewInit(): void { // broadcast to all listener observables when loading the page this.media.broadcast(); + this._changeDetectorRef.detectChanges(); } } diff --git a/src/app/components/style-guide/style-guide.module.ts b/src/app/components/style-guide/style-guide.module.ts index 4507708f9f..cebfb6b541 100644 --- a/src/app/components/style-guide/style-guide.module.ts +++ b/src/app/components/style-guide/style-guide.module.ts @@ -18,12 +18,15 @@ import { ResourcesComponent } from './resources/resources.component'; import { NavigationDrawerComponent } from './navigation-drawer/navigation-drawer.component'; import { MdButtonModule, MdListModule, MdIconModule, MdCardModule, MdToolbarModule, MdCoreModule, MdSnackBarModule, - MdInputModule, MdMenuModule, MdSelectModule, MdGridListModule, MdTabsModule, MdSidenavModule } from '@angular/material'; + MdInputModule, MdMenuModule, MdSelectModule, MdGridListModule, MdTabsModule, MdSidenavModule, + MdTooltipModule, MdProgressBarModule } from '@angular/material'; import { CovalentLayoutModule, CovalentMediaModule, CovalentSearchModule, CovalentPagingModule, CovalentExpansionPanelModule, CovalentDialogsModule } from '../../../platform/core'; import { CovalentHighlightModule } from '../../../platform/highlight'; +import { ToolbarModule } from '../../components/toolbar/toolbar.module'; + @NgModule({ declarations: [ StyleGuideComponent, @@ -57,6 +60,8 @@ import { CovalentHighlightModule } from '../../../platform/highlight'; MdTabsModule, MdSidenavModule, MdSnackBarModule, + MdTooltipModule, + MdProgressBarModule, /** Covalent Modules */ CovalentLayoutModule, CovalentMediaModule, @@ -66,6 +71,7 @@ import { CovalentHighlightModule } from '../../../platform/highlight'; CovalentHighlightModule, CovalentDialogsModule, styleGuideRoutes, + ToolbarModule, ], }) export class StyleGuideModule {} diff --git a/src/app/components/templates/templates.component.html b/src/app/components/templates/templates.component.html new file mode 100644 index 0000000000..f5c4fa8d49 --- /dev/null +++ b/src/app/components/templates/templates.component.html @@ -0,0 +1,29 @@ + + +
+
+
+

Covalent Templates

+

Example starter templates for your application

+
+
+
+
+ +
+ diff --git a/src/app/components/templates/templates.component.scss b/src/app/components/templates/templates.component.scss new file mode 100644 index 0000000000..7c397a7636 --- /dev/null +++ b/src/app/components/templates/templates.component.scss @@ -0,0 +1,10 @@ +:host /deep/ { + md-grid-tile img { + width: 100%; + height: auto; + } + .mat-grid-tile .mat-figure { + align-items: flex-start; + justify-content: flex-start; + } +} \ No newline at end of file diff --git a/src/app/components/templates/templates.component.ts b/src/app/components/templates/templates.component.ts new file mode 100644 index 0000000000..b19130125e --- /dev/null +++ b/src/app/components/templates/templates.component.ts @@ -0,0 +1,32 @@ +import { Component, HostBinding, AfterViewInit, ChangeDetectorRef } from '@angular/core'; +import { TdMediaService } from '@covalent/core'; +import { fadeAnimation } from '../../app.animations'; + +import { Observable } from 'rxjs/Observable'; + +import { InternalDocsService, ITemplate } from '../../services'; + +@Component({ + selector: 'app-templates', + styleUrls: ['./templates.component.scss'], + templateUrl: './templates.component.html', + animations: [fadeAnimation], +}) +export class TemplatesComponent implements AfterViewInit { + + @HostBinding('@routeAnimation') routeAnimation: boolean = true; + @HostBinding('class.td-route-animation') classAnimation: boolean = true; + + templatesObs: Observable; + + constructor(public media: TdMediaService, + private _changeDetectorRef: ChangeDetectorRef, + private _internalDocsService: InternalDocsService) { + this.templatesObs = this._internalDocsService.queryTemplates(); + } + + ngAfterViewInit(): void { + this.media.broadcast(); + this._changeDetectorRef.detectChanges(); + } +} diff --git a/src/app/components/toolbar/toolbar.component.html b/src/app/components/toolbar/toolbar.component.html new file mode 100644 index 0000000000..3dcdf4b407 --- /dev/null +++ b/src/app/components/toolbar/toolbar.component.html @@ -0,0 +1,51 @@ + + \ No newline at end of file diff --git a/src/app/components/toolbar/toolbar.component.scss b/src/app/components/toolbar/toolbar.component.scss new file mode 100644 index 0000000000..7bfcb81600 --- /dev/null +++ b/src/app/components/toolbar/toolbar.component.scss @@ -0,0 +1,8 @@ +/* + * Copyright (C) 2016-2017 by Teradata Corporation. All rights reserved. + * TERADATA CORPORATION CONFIDENTIAL AND TRADE SECRET + */ + +:host { + display: block; +} diff --git a/src/app/components/toolbar/toolbar.component.ts b/src/app/components/toolbar/toolbar.component.ts new file mode 100644 index 0000000000..3f2310941e --- /dev/null +++ b/src/app/components/toolbar/toolbar.component.ts @@ -0,0 +1,90 @@ +/* + * Copyright (C) 2016-2017 by Teradata Corporation. All rights reserved. + * TERADATA CORPORATION CONFIDENTIAL AND TRADE SECRET + */ + +import { Component, ElementRef, Inject, Renderer2, Output, EventEmitter } from '@angular/core'; +import { DOCUMENT } from '@angular/platform-browser'; + +import { Dir } from '@angular/material'; + +import { getDirection, setDirection } from '../../utilities/direction'; + +@Component({ + selector: 'td-toolbar', + templateUrl: '././toolbar.component.html', + styleUrls: ['././toolbar.component.scss'], +}) +export class ToolbarComponent { + updates: Object[] = [{ + description: 'Agnostic filtering with (inputChange) and [debounce] (local vs server side)', + icon: 'label', + route: '/components/chips', + title: 'Chips feature', + }, { + description: 'object list and template support and new [td-chip-avatar] attribute', + icon: 'label', + route: '/components/chips', + title: 'Chips feature', + }, { + description: 'new [chipRemoval] input', + icon: 'label', + route: '/components/chips', + title: 'Chips feature', + }, { + description: 'new [color] input', + icon: 'label', + route: '/components/chips', + title: 'Chips feature', + }, { + description: 'new [stacked] input', + icon: 'label', + route: '/components/chips', + title: 'Chips feature', + }, { + description: 'new td-expansion-panel-group component', + icon: 'open_with', + route: '/components/expansion-panel', + title: 'Expansion panel feature', + }, { + description: 'new [disableRipple] input', + icon: 'open_with', + route: '/components/expansion-panel', + title: 'Expansion panel feature', + }, { + description: 'new [mode], [opened], [sidenavWidth] inputs for td-layout', + icon: 'view_quilt', + route: '/layouts', + title: 'Layouts feature', + }, { + description: 'new [color] input for td-layout-footer', + icon: 'view_quilt', + route: '/layouts', + title: 'Layouts feature', + }, { + description: 'animation when opening/closing', + icon: 'info_outline', + route: '/components/message', + title: 'Message feature', + }, { + description: 'new [disableRipple] input', + icon: 'view_list', + route: '/components/steps', + title: 'Stepper feature', + }, + ]; + + dir: 'ltr' | 'rtl' = getDirection(); + + constructor(private _renderer: Renderer2, + private _dir: Dir, + @Inject(DOCUMENT) private _document: any) { + this._dir.dir = this.dir; + } + + changeDir(dir: 'ltr' | 'rtl'): void { + this._renderer.setAttribute(this._document.querySelector('html'), 'dir', dir); + this._dir.dir = dir; + setDirection(dir); + } +} diff --git a/src/app/components/toolbar/toolbar.module.ts b/src/app/components/toolbar/toolbar.module.ts new file mode 100644 index 0000000000..9fbcd2cd7b --- /dev/null +++ b/src/app/components/toolbar/toolbar.module.ts @@ -0,0 +1,31 @@ +import { NgModule, ModuleWithProviders } from '@angular/core'; +import { CommonModule } from '@angular/common'; +import { RouterModule } from '@angular/router'; + +import { ToolbarComponent } from './toolbar.component'; + +import { MdButtonModule, MdListModule, MdIconModule, MdMenuModule } from '@angular/material'; + +import { CovalentMenuModule, CovalentNotificationsModule } from '../../../platform/core'; + +@NgModule({ + imports: [ + CommonModule, + MdButtonModule, + MdListModule, + MdIconModule, + MdMenuModule, + CovalentMenuModule, + CovalentNotificationsModule, + RouterModule, + ], + declarations: [ + ToolbarComponent, + ], + exports: [ + ToolbarComponent, + ], +}) +export class ToolbarModule { + +} diff --git a/src/app/services/index.ts b/src/app/services/index.ts index 2c23c67f7d..caae7dea53 100644 --- a/src/app/services/index.ts +++ b/src/app/services/index.ts @@ -1 +1,3 @@ export { GitHubService } from './github.service'; +export { InternalDocsService, ITemplate } from './internal-docs.service'; +export { SelectivePreloadingStrategyService } from './selective-preloading-strategy.service'; diff --git a/src/app/services/internal-docs.service.ts b/src/app/services/internal-docs.service.ts new file mode 100644 index 0000000000..3fe4c1c0a5 --- /dev/null +++ b/src/app/services/internal-docs.service.ts @@ -0,0 +1,44 @@ +import { Injectable } from '@angular/core'; +import { Response } from '@angular/http'; +import { Observable } from 'rxjs/Observable'; +import { Subscriber } from 'rxjs/Subscriber'; + +import { HttpInterceptorService } from '@covalent/http'; + +export interface ITemplate { + name: string; + description: string; + plnkr: string; + img: string; + color: string; + icon: string; +} + +const INTERNAL_DOCS_URL: string = 'https://covalent-docs.firebaseio.com/'; + +@Injectable() +export class InternalDocsService { + + constructor(private _http: HttpInterceptorService) { + + } + + queryTemplates(): Observable { + return new Observable((subscriber: Subscriber) => { + this._http.get(INTERNAL_DOCS_URL + '/templates.json').subscribe((response: Response) => { + let data: ITemplate[]; + try { + data = response.json(); + } catch (e) { + data = []; + subscriber.error(); + } + subscriber.next(data); + subscriber.complete(); + }, (error: any) => { + subscriber.error(); + }); + }); + } + +} diff --git a/src/app/services/selective-preloading-strategy.service.ts b/src/app/services/selective-preloading-strategy.service.ts new file mode 100755 index 0000000000..1a968b188b --- /dev/null +++ b/src/app/services/selective-preloading-strategy.service.ts @@ -0,0 +1,19 @@ +import { Injectable } from '@angular/core'; +import { PreloadingStrategy, Route } from '@angular/router'; +import { Observable } from 'rxjs/Observable'; +import 'rxjs/add/observable/of'; + +@Injectable() +export class SelectivePreloadingStrategyService implements PreloadingStrategy { + + preload(route: Route, load: () => Observable): Observable { + + // Configured on lazyload module route + if (route.data && route.data.preload) { + return load(); + } else { + /* tslint:disable-next-line */ + return Observable.of(null); + } + } +} diff --git a/src/app/utilities/direction.ts b/src/app/utilities/direction.ts new file mode 100644 index 0000000000..706e7ee6f9 --- /dev/null +++ b/src/app/utilities/direction.ts @@ -0,0 +1,20 @@ +export const DIRECTION_STORAGE_KEY: string = 'app-direction'; + +/** + * Utility method to get selected direction from sessionStorage + */ +export function getDirection(): 'ltr' | 'rtl' { + let storedDirection: 'ltr' | 'rtl' = sessionStorage.getItem(DIRECTION_STORAGE_KEY); + // Check if the direction was stored + if (storedDirection) { + return storedDirection; + } + return 'ltr'; +} + +/** + * Utility method to set selected direction to sessionStorage + */ +export function setDirection(direction: 'ltr' | 'rtl'): void { + sessionStorage.setItem(DIRECTION_STORAGE_KEY, direction); +} diff --git a/src/favicon.ico b/src/favicon.ico index f3699612c3..fe7278dc3f 100644 Binary files a/src/favicon.ico and b/src/favicon.ico differ diff --git a/src/index.html b/src/index.html index f5e9c60746..7af51097e4 100644 --- a/src/index.html +++ b/src/index.html @@ -10,7 +10,7 @@ -
+

Covalent Loading...

diff --git a/src/platform/core/chips/README.md b/src/platform/core/chips/README.md index 4e7410a4aa..12206cde86 100644 --- a/src/platform/core/chips/README.md +++ b/src/platform/core/chips/README.md @@ -1,8 +1,10 @@ # td-chips -`td-chips` element generates a list of strings as chips. +`td-chips` element generates a list of strings or objects as chips. -Add the [items] attribute to enable the autocomplete with a search list, and [requireMatch] to validated the input against the provided search list. +Add the [items] attribute to enable the autocomplete with a list, and [requireMatch] to not allow custom values. + +Leverage the templates to create your own chip or contact chip. ## API Summary @@ -10,12 +12,17 @@ Properties: | Name | Type | Description | | --- | --- | --- | -| `items?` | `string[]` | Enables Autocompletion with the provided list of search strings. -| `readOnly` | `boolean` | Disables the chip input and removal. -| `requireMatch?` | `boolean` | Validates input against the provided search list before adding it to the model. If it doesnt exist, it cancels the event. +| `color?` | `'primary' | 'accent' | 'warn'` | color for the input and focus state of the chips. Defaults to 'primary' +| `items?` | `any[]` | Renders the `md-autocomplete` with the provided list to display as options. +| `requireMatch?` | `boolean` | Blocks custom inputs and only allows selections from the autocomplete list. +| `stacked?` | `boolean` | Set stacked or horizontal chips depending on value. Defaults to false. | `placeholder?` | `string` | Placeholder for the autocomplete input. -| `add?` | `function` | Method to be executed when string is added as chip through the autocomplete. Sends chip value as event. -| `remove?` | `function` | Method to be executed when string is removed as chip with the "remove" button. Sends chip value as event. +| `chipAddition` | `boolean` | Disables the ability to add chips. When setting readOnly as true, this will be overriden. Defaults to true. +| `chipRemoval` | `boolean` | Disables the ability to remove chips. When setting readOnly as true, this will be overriden. Defaults to true. +| `debounce` | `string` | Debounce timeout between keypresses. Defaults to 200. +| `add?` | `function` | Method to be executed when a chip is added. Sends chip value as event. +| `remove?` | `function` | Method to be executed when a chip is removed. Sends chip value as event. +| `inputChange?` | `function` | Method to be executed when the value in the autocomplete input changes. Sends string value as event. ## Setup @@ -37,7 +44,25 @@ export class MyModule {} Example for HTML usage: - ```html - +```html + + +
A
{{chip}} +
+ + {{option}} + + // anything below it
- ``` \ No newline at end of file +``` diff --git a/src/platform/core/chips/_chips-theme.scss b/src/platform/core/chips/_chips-theme.scss index 2ad63ddd1a..1acb47b627 100644 --- a/src/platform/core/chips/_chips-theme.scss +++ b/src/platform/core/chips/_chips-theme.scss @@ -14,20 +14,49 @@ background: mat-color($background, status-bar); color: mat-color($foreground, text); &:focus:not(.td-chip-disabled) { - background: mat-color($primary); - &, md-icon { - color: mat-color($primary, default-contrast); - md-icon:hover { - color: mat-color($foreground, icon); + md-icon:hover { + color: mat-color($foreground, icon); + } + &.mat-primary { + background: mat-color($primary); + &, md-icon { + color: mat-color($primary, default-contrast); + } + } + &.mat-accent { + background: mat-color($accent); + &, md-icon { + color: mat-color($accent, default-contrast); + } + } + &.mat-warn { + background: mat-color($warn); + &, md-icon { + color: mat-color($warn, default-contrast); } } } - md-icon { + md-icon.td-chip-removal { color: mat-color($foreground, hint-text); &:hover { color: mat-color($foreground, icon); } } } + &.mat-primary { + .mat-input-underline .mat-input-ripple { + background-color: mat-color($primary); + } + } + &.mat-accent { + .mat-input-underline .mat-input-ripple { + background-color: mat-color($accent); + } + } + &.mat-warn { + .mat-input-underline .mat-input-ripple { + background-color: mat-color($warn); + } + } } } \ No newline at end of file diff --git a/src/platform/core/chips/chips.component.html b/src/platform/core/chips/chips.component.html index b8df30f41e..0491a87736 100644 --- a/src/platform/core/chips/chips.component.html +++ b/src/platform/core/chips/chips.component.html @@ -1,38 +1,55 @@ -
- - - - {{chip}} - +
+ + +
+
+ {{chip}} + + +
+ cancel - +
+
+
+ + + + + + + {{item}} + + + - - - - - - {{item}} - - - -
- -
+
+
+ +
+ \ No newline at end of file diff --git a/src/platform/core/chips/chips.component.scss b/src/platform/core/chips/chips.component.scss index d746e6458d..23242095ae 100644 --- a/src/platform/core/chips/chips.component.scss +++ b/src/platform/core/chips/chips.component.scss @@ -3,73 +3,96 @@ :host { display: block; padding: 0px 5px 0px 5px; + min-height: 48px; + .td-chips-wrapper { + display: flex; + flex-direction: row; + flex-wrap: wrap; + align-items: flex-start; + min-height: 42px; + &.td-chips-stacked { + flex-direction: column; + align-items: stretch; + } + } /deep/ { .mat-input-wrapper { margin-bottom: 2px; } + /* TODO see if we can make styles more abstract to future proof for contact chips */ .mat-basic-chip { display: inline-block; cursor: default; border-radius: 16px; - line-height: 32px; @include rtl(margin, 8px 8px 0 0, 8px 0 0 8px); - padding: 0 12px; + .td-chip { + min-height: 32px; + font-size: 14px; + @include rtl(padding, 0 0 0 12px, 0 12px 0 0); + [td-chip-avatar] { + display: flex; + order: -20; + justify-content: center; + align-items: center; + height: 32px; + width: 32px; + flex-shrink: 0; + @include rtl(margin, 0 8px 0 -12px, 0 -12px 0 8px); + border-radius: 50%; + } + } box-sizing: border-box; max-width: 100%; position: relative; - md-icon { - position: relative; - top: 5px; - @include rtl(left, 5px, auto); - @include rtl(right, auto, 5px); - height: 18px; - width: 18px; - font-size: 19px; + &.td-chip-after-pad { + @include rtl(padding, 0 12px 0 0, 0 0 0 12px); + } + md-icon.td-chip-removal { + margin: 0 4px; + font-size: 21px; &:hover { cursor: pointer; } } } } -} - -.mat-input-underline { - position: relative; - height: 1px; - width: 100%; - - &.mat-disabled { - border-top: 0; - background-position: 0; - background-size: 4px 1px; - background-repeat: repeat-x; - } - - .mat-input-ripple { - position: absolute; - height: 2px; - z-index: 1; - top: -1px; + .mat-input-underline { + position: relative; + height: 1px; width: 100%; - transform-origin: top; - opacity: 0; - transform: scaleY(0); - &.mat-warn { - opacity: 1; - transform: scaleY(1); + margin-top: 4px; + border-top-width: 1px; + border-top-style: solid; + + &.mat-disabled { + border-top: 0; + background-position: 0; + background-size: 4px 1px; + background-repeat: repeat-x; } - &.mat-focused { - opacity: 1; - transform: scaleY(1); + + .mat-input-ripple { + position: absolute; + height: 2px; + z-index: 1; + top: -1px; + width: 100%; + transform-origin: 50%; + transform: scaleX(0.5); + visibility: hidden; + transition: background-color .3s cubic-bezier(.55,0,.55,.2); + &.mat-focused { + visibility: visible; + transform: scaleX(1); + transition: transform 150ms linear, + background-color .3s cubic-bezier(.55,0,.55,.2); + } } } } :host { /deep/ md-input-container { - input::-webkit-calendar-picker-indicator { // removes input arrow for datalist in chrome - display: none; - } .mat-input-underline { display: none; } diff --git a/src/platform/core/chips/chips.component.spec.ts b/src/platform/core/chips/chips.component.spec.ts index a00e6d6f8c..ca6be6759d 100644 --- a/src/platform/core/chips/chips.component.spec.ts +++ b/src/platform/core/chips/chips.component.spec.ts @@ -3,15 +3,27 @@ import { async, ComponentFixture, } from '@angular/core/testing'; -import { BrowserAnimationsModule } from '@angular/platform-browser/animations'; +import { NoopAnimationsModule } from '@angular/platform-browser/animations'; import { Component, DebugElement } from '@angular/core'; import { FormControl, FormsModule, ReactiveFormsModule, } from '@angular/forms'; -import { OverlayContainer, MdInputDirective, DOWN_ARROW, UP_ARROW, ENTER, SPACE, TAB } from '@angular/material'; +import { OverlayContainer, MdInputDirective, MdChip, DELETE, BACKSPACE, ENTER, LEFT_ARROW, RIGHT_ARROW } from '@angular/material'; import { By } from '@angular/platform-browser'; import { CovalentChipsModule, TdChipsComponent } from './chips.module'; +function createFakeKeyboardEvent(keyCode: number): any { + return { + keyCode: keyCode, + preventDefault: function(): void { + /* noop */ + }, + stopPropagation: function(): void { + /* noop */ + }, + }; +} + describe('Component: Chips', () => { let overlayContainerElement: HTMLElement; @@ -21,10 +33,15 @@ describe('Component: Chips', () => { CovalentChipsModule, FormsModule, ReactiveFormsModule, - BrowserAnimationsModule, + NoopAnimationsModule, ], declarations: [ + TdChipsTestComponent, + TdChipsA11yTestComponent, TdChipsBasicTestComponent, + TdChipsObjectsRequireMatchTestComponent, + TdChipsStackedTestComponent, + TdChipRemovalTestComponent, ], providers: [ {provide: OverlayContainer, useFactory: () => { @@ -44,6 +61,274 @@ describe('Component: Chips', () => { TestBed.compileComponents(); })); + describe('should test general features: ', () => { + let fixture: ComponentFixture; + let input: DebugElement; + let chips: DebugElement; + + beforeEach(() => { + fixture = TestBed.createComponent(TdChipsTestComponent); + fixture.detectChanges(); + + chips = fixture.debugElement.query(By.directive(TdChipsComponent)); + input = chips.query(By.css('input')); + }); + + it('should have primary color', (done: DoneFn) => { + fixture.detectChanges(); + fixture.whenStable().then(() => { + expect((chips.nativeElement).classList.contains('mat-primary')).toBeTruthy(); + done(); + }); + }); + + it('should set to accent color', (done: DoneFn) => { + fixture.componentInstance.color = 'accent'; + fixture.detectChanges(); + fixture.whenStable().then(() => { + expect((chips.nativeElement).classList.contains('mat-accent')).toBeTruthy(); + done(); + }); + }); + + it('should set to warn color and then to accent', (done: DoneFn) => { + fixture.componentInstance.color = 'warn'; + fixture.detectChanges(); + fixture.whenStable().then(() => { + expect((chips.nativeElement).classList.contains('mat-warn')).toBeTruthy(); + fixture.componentInstance.color = 'accent'; + fixture.detectChanges(); + fixture.whenStable().then(() => { + expect((chips.nativeElement).classList.contains('mat-accent')).toBeTruthy(); + done(); + }); + }); + }); + + }); + + describe('a11y keyboard in chips and input: ', () => { + let fixture: ComponentFixture; + let input: DebugElement; + let chips: DebugElement; + + beforeEach(() => { + fixture = TestBed.createComponent(TdChipsA11yTestComponent); + fixture.detectChanges(); + + chips = fixture.debugElement.query(By.directive(TdChipsComponent)); + input = chips.query(By.css('input')); + }); + + it('should focus input', (done: DoneFn) => { + fixture.componentInstance.chipAddition = true; + fixture.detectChanges(); + fixture.whenStable().then(() => { + chips.nativeElement.focus(); + chips.triggerEventHandler('focus', new Event('focus')); + fixture.detectChanges(); + fixture.whenStable().then(() => { + expect((chips.componentInstance)._inputChild.focused).toBeTruthy(); + done(); + }); + }); + }); + + it('should focus first chip', (done: DoneFn) => { + fixture.componentInstance.chipAddition = false; + fixture.detectChanges(); + fixture.whenStable().then(() => { + chips.nativeElement.focus(); + fixture.detectChanges(); + fixture.whenStable().then(() => { + chips.triggerEventHandler('focus', new Event('focus')); + fixture.detectChanges(); + fixture.whenStable().then(() => { + expect(fixture.debugElement.queryAll(By.directive(MdChip))[0].nativeElement) + .toBe(document.activeElement); + done(); + }); + }); + }); + }); + + it('should focus around the chips going left', (done: DoneFn) => { + fixture.componentInstance.chipAddition = false; + fixture.detectChanges(); + fixture.whenStable().then(() => { + chips.nativeElement.focus(); + fixture.detectChanges(); + fixture.whenStable().then(() => { + chips.triggerEventHandler('focus', new Event('focus')); + fixture.detectChanges(); + fixture.whenStable().then(() => { + expect(fixture.debugElement.queryAll(By.directive(MdChip))[0].nativeElement) + .toBe(document.activeElement); + fixture.debugElement.queryAll(By.directive(MdChip))[0] + .triggerEventHandler('keydown', createFakeKeyboardEvent(LEFT_ARROW)); + fixture.detectChanges(); + fixture.whenStable().then(() => { + expect(fixture.debugElement.queryAll(By.directive(MdChip))[2].nativeElement) + .toBe(document.activeElement); + fixture.debugElement.queryAll(By.directive(MdChip))[2] + .triggerEventHandler('keydown', createFakeKeyboardEvent(LEFT_ARROW)); + fixture.detectChanges(); + fixture.whenStable().then(() => { + expect(fixture.debugElement.queryAll(By.directive(MdChip))[1].nativeElement) + .toBe(document.activeElement); + fixture.debugElement.queryAll(By.directive(MdChip))[1] + .triggerEventHandler('keydown', createFakeKeyboardEvent(LEFT_ARROW)); + fixture.detectChanges(); + fixture.whenStable().then(() => { + expect(fixture.debugElement.queryAll(By.directive(MdChip))[0].nativeElement) + .toBe(document.activeElement); + done(); + }); + }); + }); + }); + }); + }); + }); + + it('should focus around the chips going right', (done: DoneFn) => { + fixture.componentInstance.chipAddition = false; + fixture.detectChanges(); + fixture.whenStable().then(() => { + chips.nativeElement.focus(); + fixture.detectChanges(); + fixture.whenStable().then(() => { + chips.triggerEventHandler('focus', new Event('focus')); + fixture.detectChanges(); + fixture.whenStable().then(() => { + expect(fixture.debugElement.queryAll(By.directive(MdChip))[0].nativeElement) + .toBe(document.activeElement); + fixture.debugElement.queryAll(By.directive(MdChip))[0] + .triggerEventHandler('keydown', createFakeKeyboardEvent(RIGHT_ARROW)); + fixture.detectChanges(); + fixture.whenStable().then(() => { + expect(fixture.debugElement.queryAll(By.directive(MdChip))[1].nativeElement) + .toBe(document.activeElement); + fixture.debugElement.queryAll(By.directive(MdChip))[1] + .triggerEventHandler('keydown', createFakeKeyboardEvent(RIGHT_ARROW)); + fixture.detectChanges(); + fixture.whenStable().then(() => { + expect(fixture.debugElement.queryAll(By.directive(MdChip))[2].nativeElement) + .toBe(document.activeElement); + fixture.debugElement.queryAll(By.directive(MdChip))[2] + .triggerEventHandler('keydown', createFakeKeyboardEvent(RIGHT_ARROW)); + fixture.detectChanges(); + fixture.whenStable().then(() => { + expect(fixture.debugElement.queryAll(By.directive(MdChip))[0].nativeElement) + .toBe(document.activeElement); + done(); + }); + }); + }); + }); + }); + }); + }); + + }); + + describe('panel usage and add/removal: ', () => { + let fixture: ComponentFixture; + let input: DebugElement; + let chips: DebugElement; + + beforeEach(() => { + fixture = TestBed.createComponent(TdChipsBasicTestComponent); + fixture.detectChanges(); + + chips = fixture.debugElement.query(By.directive(TdChipsComponent)); + input = chips.query(By.css('input')); + }); + + it('should set a value in the input and enter it as chip', (done: DoneFn) => { + chips.triggerEventHandler('focus', new Event('focus')); + fixture.detectChanges(); + fixture.whenStable().then(() => { + (chips.componentInstance)._inputChild.value = 'test'; + fixture.detectChanges(); + fixture.whenStable().then(() => { + input.triggerEventHandler('keyup.enter', createFakeKeyboardEvent(ENTER)); + fixture.detectChanges(); + fixture.whenStable().then(() => { + // set tiemout + setTimeout(() => { + expect(chips.componentInstance.value.length).toBe(1); + expect(fixture.debugElement.queryAll(By.directive(MdChip)).length).toBe(1); + expect(fixture.debugElement.queryAll(By.directive(MdChip))[0].nativeElement.textContent).toContain('test'); + done(); + }, 200); + }); + }); + }); + }); + + it('should open the panel, click on an option and add it as chip', (done: DoneFn) => { + fixture.componentInstance.filter(''); + chips.triggerEventHandler('focus', new Event('focus')); + fixture.detectChanges(); + fixture.whenStable().then(() => { + const option: HTMLElement = overlayContainerElement.querySelector('md-option'); + option.click(); + fixture.detectChanges(); + fixture.whenStable().then(() => { + expect(chips.componentInstance.value.length).toBe(1); + expect(fixture.debugElement.queryAll(By.directive(MdChip)).length).toBe(1); + done(); + }); + }); + }); + + it('should open the panel, click on an option to add it as chip and remove it with backspace', (done: DoneFn) => { + fixture.componentInstance.filter(''); + chips.triggerEventHandler('focus', new Event('focus')); + fixture.detectChanges(); + fixture.whenStable().then(() => { + const option: HTMLElement = overlayContainerElement.querySelector('md-option'); + option.click(); + fixture.detectChanges(); + fixture.whenStable().then(() => { + expect(chips.componentInstance.value.length).toBe(1); + expect(fixture.debugElement.queryAll(By.directive(MdChip)).length).toBe(1); + fixture.debugElement.queryAll(By.directive(MdChip))[0].triggerEventHandler('keydown', createFakeKeyboardEvent(BACKSPACE)); + fixture.detectChanges(); + fixture.whenStable().then(() => { + expect(chips.componentInstance.value.length).toBe(0); + expect(fixture.debugElement.queryAll(By.directive(MdChip)).length).toBe(0); + done(); + }); + }); + }); + }); + + it('should open the panel, click on an option to add it as chip and remove it by clicking on the remove button', (done: DoneFn) => { + fixture.componentInstance.filter(''); + chips.triggerEventHandler('focus', new Event('focus')); + fixture.detectChanges(); + fixture.whenStable().then(() => { + const option: HTMLElement = overlayContainerElement.querySelector('md-option'); + option.click(); + fixture.detectChanges(); + fixture.whenStable().then(() => { + expect(chips.componentInstance.value.length).toBe(1); + expect(fixture.debugElement.queryAll(By.directive(MdChip)).length).toBe(1); + fixture.debugElement.queryAll(By.css('.td-chip-removal'))[0].triggerEventHandler('click', new Event('click')); + fixture.detectChanges(); + fixture.whenStable().then(() => { + expect(chips.componentInstance.value.length).toBe(0); + expect(fixture.debugElement.queryAll(By.directive(MdChip)).length).toBe(0); + done(); + }); + }); + }); + }); + + }); + describe('panel usage and filtering: ', () => { let fixture: ComponentFixture; let input: DebugElement; @@ -53,7 +338,6 @@ describe('Component: Chips', () => { fixture = TestBed.createComponent(TdChipsBasicTestComponent); fixture.detectChanges(); - input = fixture.debugElement.query(By.css('input')); chips = fixture.debugElement.query(By.directive(TdChipsComponent)); }); @@ -65,20 +349,18 @@ describe('Component: Chips', () => { expect(overlayContainerElement.textContent).not.toContain('chips'); expect(overlayContainerElement.textContent).not.toContain('pasta'); expect(overlayContainerElement.textContent).not.toContain('sushi'); - input.triggerEventHandler('focus', new Event('focus')); + fixture.componentInstance.filter(''); + chips.triggerEventHandler('focus', new Event('focus')); fixture.detectChanges(); fixture.whenStable().then(() => { - fixture.detectChanges(); - fixture.whenStable().then(() => { - expect(overlayContainerElement.textContent).toContain('steak'); - expect(overlayContainerElement.textContent).toContain('pizza'); - expect(overlayContainerElement.textContent).toContain('tacos'); - expect(overlayContainerElement.textContent).toContain('sandwich'); - expect(overlayContainerElement.textContent).toContain('chips'); - expect(overlayContainerElement.textContent).toContain('pasta'); - expect(overlayContainerElement.textContent).toContain('sushi'); - done(); - }); + expect(overlayContainerElement.textContent).toContain('steak'); + expect(overlayContainerElement.textContent).toContain('pizza'); + expect(overlayContainerElement.textContent).toContain('tacos'); + expect(overlayContainerElement.textContent).toContain('sandwich'); + expect(overlayContainerElement.textContent).toContain('chips'); + expect(overlayContainerElement.textContent).toContain('pasta'); + expect(overlayContainerElement.textContent).toContain('sushi'); + done(); }); }); @@ -90,86 +372,301 @@ describe('Component: Chips', () => { expect(overlayContainerElement.textContent).not.toContain('chips'); expect(overlayContainerElement.textContent).not.toContain('pasta'); expect(overlayContainerElement.textContent).not.toContain('sushi'); - input.triggerEventHandler('focus', new Event('focus')); + fixture.componentInstance.filter(''); + chips.triggerEventHandler('focus', new Event('focus')); fixture.detectChanges(); fixture.whenStable().then(() => { + expect(overlayContainerElement.textContent).toContain('steak'); + expect(overlayContainerElement.textContent).toContain('pizza'); + expect(overlayContainerElement.textContent).toContain('tacos'); + expect(overlayContainerElement.textContent).toContain('sandwich'); + expect(overlayContainerElement.textContent).toContain('chips'); + expect(overlayContainerElement.textContent).toContain('pasta'); + expect(overlayContainerElement.textContent).toContain('sushi'); + (chips.componentInstance).inputControl.setValue('a'); fixture.detectChanges(); fixture.whenStable().then(() => { - expect(overlayContainerElement.textContent).toContain('steak'); - expect(overlayContainerElement.textContent).toContain('pizza'); - expect(overlayContainerElement.textContent).toContain('tacos'); - expect(overlayContainerElement.textContent).toContain('sandwich'); - expect(overlayContainerElement.textContent).toContain('chips'); - expect(overlayContainerElement.textContent).toContain('pasta'); - expect(overlayContainerElement.textContent).toContain('sushi'); - (chips.componentInstance).inputControl.setValue('a'); + // mimic debounce + setTimeout(() => { + fixture.detectChanges(); + fixture.whenStable().then(() => { + expect(overlayContainerElement.textContent).toContain('steak'); + expect(overlayContainerElement.textContent).toContain('pizza'); + expect(overlayContainerElement.textContent).toContain('tacos'); + expect(overlayContainerElement.textContent).toContain('sandwich'); + expect(overlayContainerElement.textContent).not.toContain('chips'); + expect(overlayContainerElement.textContent).toContain('pasta'); + expect(overlayContainerElement.textContent).not.toContain('sushi'); + done(); + }); + }, 200); + }); + }); + }); + }); + + describe('panel usage and requireMatch usage: ', () => { + let fixture: ComponentFixture; + let input: DebugElement; + let chips: DebugElement; + + beforeEach(() => { + fixture = TestBed.createComponent(TdChipsObjectsRequireMatchTestComponent); + fixture.detectChanges(); + + chips = fixture.debugElement.query(By.directive(TdChipsComponent)); + }); + + it('should open the panel, click on an option to add it as chip', (done: DoneFn) => { + fixture.componentInstance.objects = [{ + name: 'San Diego', + }, { + name: 'Los Angeles', + }]; + chips.triggerEventHandler('focus', new Event('focus')); + fixture.detectChanges(); + fixture.whenStable().then(() => { + fixture.detectChanges(); + fixture.whenStable().then(() => { + const option: HTMLElement = overlayContainerElement.querySelector('md-option'); + option.click(); fixture.detectChanges(); fixture.whenStable().then(() => { - setTimeout(() => { + expect(chips.componentInstance.value.length).toBe(1); + expect(fixture.debugElement.queryAll(By.directive(MdChip)).length).toBe(1); + done(); + }); + }); + }); + }); + + }); + + describe('stacked usage: ', () => { + let fixture: ComponentFixture; + let input: DebugElement; + let chips: DebugElement; + + beforeEach(() => { + fixture = TestBed.createComponent(TdChipsStackedTestComponent); + fixture.detectChanges(); + + chips = fixture.debugElement.query(By.directive(TdChipsComponent)); + }); + + it('should rendered chips stacked', (done: DoneFn) => { + fixture.detectChanges(); + fixture.whenStable().then(() => { + expect((chips.query(By.css('.td-chips-wrapper')).nativeElement).classList.contains('td-chips-stacked')) + .toBeFalsy(); + fixture.componentInstance.stacked = true; + fixture.detectChanges(); + fixture.whenStable().then(() => { + expect((chips.query(By.css('.td-chips-wrapper')).nativeElement).classList.contains('td-chips-stacked')) + .toBeTruthy(); + done(); + }); + }); + }); + + }); + + describe('chip removal usage, requires readOnly to be false: ', () => { + let fixture: ComponentFixture; + let input: DebugElement; + let chips: DebugElement; + + beforeEach(() => { + fixture = TestBed.createComponent(TdChipRemovalTestComponent); + fixture.detectChanges(); + + chips = fixture.debugElement.query(By.directive(TdChipsComponent)); + input = chips.query(By.css('input')); + }); + + it('should not focus input', (done: DoneFn) => { + fixture.componentInstance.chipRemoval = true; + fixture.componentInstance.chipAddition = false; + fixture.detectChanges(); + fixture.whenStable().then(() => { + chips.nativeElement.focus(); + chips.triggerEventHandler('focus', new Event('focus')); + fixture.detectChanges(); + fixture.whenStable().then(() => { + expect((chips.componentInstance)._inputChild.focused).toBeFalsy(); + done(); + }); + }); + }); + + it('should not show cancel button', (done: DoneFn) => { + fixture.componentInstance.chipRemoval = false; + fixture.componentInstance.chipAddition = false; + fixture.detectChanges(); + fixture.whenStable().then(() => { + chips.nativeElement.focus(); + chips.triggerEventHandler('focus', new Event('focus')); + fixture.detectChanges(); + fixture.whenStable().then(() => { + expect(fixture.debugElement.queryAll(By.css('.td-chip-removal')).length).toBe(0); + done(); + }); + }); + }); + + it('should focus input, then focus first chip and remove first chip by clicking on the remove button', (done: DoneFn) => { + fixture.componentInstance.chipRemoval = true; + fixture.detectChanges(); + fixture.whenStable().then(() => { + chips.nativeElement.focus(); + chips.triggerEventHandler('focus', new Event('focus')); + fixture.detectChanges(); + fixture.whenStable().then(() => { + expect((chips.componentInstance)._inputChild.focused).toBeTruthy(); + fixture.detectChanges(); + fixture.whenStable().then(() => { + expect(chips.componentInstance.value.length).toBe(3); + expect(fixture.debugElement.queryAll(By.directive(MdChip)).length).toBe(3); + fixture.debugElement.queryAll(By.css('.td-chip-removal'))[0] + .triggerEventHandler('click', new Event('click')); + fixture.detectChanges(); + fixture.whenStable().then(() => { + expect(chips.componentInstance.value.length).toBe(2); + expect(fixture.debugElement.queryAll(By.directive(MdChip)).length).toBe(2); + done(); + }); + }); + }); + }); + }); + + it('should focus first chip and remove chip with backspace and delete', (done: DoneFn) => { + fixture.componentInstance.chipRemoval = true; + fixture.componentInstance.chipAddition = false; + fixture.detectChanges(); + fixture.whenStable().then(() => { + chips.nativeElement.focus(); + fixture.detectChanges(); + fixture.whenStable().then(() => { + chips.triggerEventHandler('focus', new Event('focus')); + fixture.detectChanges(); + fixture.whenStable().then(() => { + expect(fixture.debugElement.queryAll(By.directive(MdChip))[0].nativeElement) + .toBe(document.activeElement); + fixture.detectChanges(); + fixture.whenStable().then(() => { + fixture.debugElement.queryAll(By.directive(MdChip))[0] + .triggerEventHandler('keydown', createFakeKeyboardEvent(BACKSPACE)); fixture.detectChanges(); fixture.whenStable().then(() => { - expect(overlayContainerElement.textContent).toContain('steak'); - expect(overlayContainerElement.textContent).toContain('pizza'); - expect(overlayContainerElement.textContent).toContain('tacos'); - expect(overlayContainerElement.textContent).toContain('sandwich'); - expect(overlayContainerElement.textContent).not.toContain('chips'); - expect(overlayContainerElement.textContent).toContain('pasta'); - expect(overlayContainerElement.textContent).not.toContain('sushi'); - done(); + expect(chips.componentInstance.value.length).toBe(2); + expect(fixture.debugElement.queryAll(By.directive(MdChip)).length).toBe(2); + fixture.detectChanges(); + fixture.whenStable().then(() => { + expect(chips.componentInstance.value.length).toBe(2); + fixture.debugElement.queryAll(By.directive(MdChip))[0] + .triggerEventHandler('keydown', createFakeKeyboardEvent(DELETE)); + fixture.detectChanges(); + fixture.whenStable().then(() => { + expect(chips.componentInstance.value.length).toBe(1); + expect(fixture.debugElement.queryAll(By.directive(MdChip)).length).toBe(1); + done(); + }); + }); }); - }, 100); + }); + }); + }); + }); + }); + + it('should focus around the chips going left', (done: DoneFn) => { + fixture.componentInstance.chipRemoval = true; + fixture.componentInstance.chipAddition = false; + fixture.detectChanges(); + fixture.whenStable().then(() => { + chips.nativeElement.focus(); + fixture.detectChanges(); + fixture.whenStable().then(() => { + chips.triggerEventHandler('focus', new Event('focus')); + fixture.detectChanges(); + fixture.whenStable().then(() => { + expect(fixture.debugElement.queryAll(By.directive(MdChip))[0].nativeElement) + .toBe(document.activeElement); + fixture.debugElement.queryAll(By.directive(MdChip))[0] + .triggerEventHandler('keydown', createFakeKeyboardEvent(LEFT_ARROW)); + fixture.detectChanges(); + fixture.whenStable().then(() => { + expect(fixture.debugElement.queryAll(By.directive(MdChip))[2].nativeElement) + .toBe(document.activeElement); + fixture.debugElement.queryAll(By.directive(MdChip))[2] + .triggerEventHandler('keydown', createFakeKeyboardEvent(LEFT_ARROW)); + fixture.detectChanges(); + fixture.whenStable().then(() => { + expect(fixture.debugElement.queryAll(By.directive(MdChip))[1].nativeElement) + .toBe(document.activeElement); + fixture.debugElement.queryAll(By.directive(MdChip))[1] + .triggerEventHandler('keydown', createFakeKeyboardEvent(LEFT_ARROW)); + fixture.detectChanges(); + fixture.whenStable().then(() => { + expect(fixture.debugElement.queryAll(By.directive(MdChip))[0].nativeElement) + .toBe(document.activeElement); + done(); + }); + }); + }); }); }); }); }); - it('should open the panel, filter selectedItems and filter the list', (done: DoneFn) => { - expect(overlayContainerElement.textContent).not.toContain('steak'); - expect(overlayContainerElement.textContent).not.toContain('pizza'); - expect(overlayContainerElement.textContent).not.toContain('tacos'); - expect(overlayContainerElement.textContent).not.toContain('sandwich'); - expect(overlayContainerElement.textContent).not.toContain('chips'); - expect(overlayContainerElement.textContent).not.toContain('pasta'); - expect(overlayContainerElement.textContent).not.toContain('sushi'); - fixture.componentInstance.selectedItems.push('steak'); - fixture.componentInstance.selectedItems.push('sandwich'); - input.triggerEventHandler('focus', new Event('focus')); + it('should focus around the chips going right', (done: DoneFn) => { + fixture.componentInstance.chipRemoval = true; + fixture.componentInstance.chipAddition = false; fixture.detectChanges(); fixture.whenStable().then(() => { + chips.nativeElement.focus(); fixture.detectChanges(); fixture.whenStable().then(() => { - expect(overlayContainerElement.textContent).not.toContain('steak'); - expect(overlayContainerElement.textContent).toContain('pizza'); - expect(overlayContainerElement.textContent).toContain('tacos'); - expect(overlayContainerElement.textContent).not.toContain('sandwich'); - expect(overlayContainerElement.textContent).toContain('chips'); - expect(overlayContainerElement.textContent).toContain('pasta'); - expect(overlayContainerElement.textContent).toContain('sushi'); - (chips.componentInstance).inputControl.setValue('a'); + chips.triggerEventHandler('focus', new Event('focus')); fixture.detectChanges(); fixture.whenStable().then(() => { - setTimeout(() => { + expect(fixture.debugElement.queryAll(By.directive(MdChip))[0].nativeElement) + .toBe(document.activeElement); + fixture.debugElement.queryAll(By.directive(MdChip))[0] + .triggerEventHandler('keydown', createFakeKeyboardEvent(RIGHT_ARROW)); + fixture.detectChanges(); + fixture.whenStable().then(() => { + expect(fixture.debugElement.queryAll(By.directive(MdChip))[1].nativeElement) + .toBe(document.activeElement); + fixture.debugElement.queryAll(By.directive(MdChip))[1] + .triggerEventHandler('keydown', createFakeKeyboardEvent(RIGHT_ARROW)); fixture.detectChanges(); fixture.whenStable().then(() => { - expect(overlayContainerElement.textContent).not.toContain('steak'); - expect(overlayContainerElement.textContent).toContain('pizza'); - expect(overlayContainerElement.textContent).toContain('tacos'); - expect(overlayContainerElement.textContent).not.toContain('sandwich'); - expect(overlayContainerElement.textContent).not.toContain('chips'); - expect(overlayContainerElement.textContent).toContain('pasta'); - expect(overlayContainerElement.textContent).not.toContain('sushi'); - done(); + expect(fixture.debugElement.queryAll(By.directive(MdChip))[2].nativeElement) + .toBe(document.activeElement); + fixture.debugElement.queryAll(By.directive(MdChip))[2] + .triggerEventHandler('keydown', createFakeKeyboardEvent(RIGHT_ARROW)); + fixture.detectChanges(); + fixture.whenStable().then(() => { + expect(fixture.debugElement.queryAll(By.directive(MdChip))[0].nativeElement) + .toBe(document.activeElement); + done(); + }); }); - }, 100); + }); }); }); }); }); + }); // TODO - // requireMatch usage + // more requireMatch usage + + // more a11y unit tests // readOnly usage @@ -185,11 +682,46 @@ describe('Component: Chips', () => { @Component({ template: ` - + + `, +}) +class TdChipsTestComponent { + color: string; + items: string[] = [ + 'steak', + 'pizza', + 'tacos', + ]; + selectedItems: string[] = this.items.slice(0, 2); +} + +@Component({ + template: ` + + `, +}) +class TdChipsA11yTestComponent { + chipAddition: boolean = true; + items: string[] = [ + 'steak', + 'pizza', + 'tacos', + 'sandwich', + 'chips', + 'pasta', + 'sushi', + ]; + selectedItems: string[] = this.items.slice(0, 3); +} + +@Component({ + template: ` + `, }) class TdChipsBasicTestComponent { placeholder: string; + filteredItems: string[]; selectedItems: string[] = []; items: string[] = [ 'steak', @@ -200,4 +732,67 @@ class TdChipsBasicTestComponent { 'pasta', 'sushi', ]; + filter(value: string): void { + this.filteredItems = this.items.filter((item: any) => { + return item.toLowerCase().indexOf(value.toLowerCase()) > -1; + }).filter((filteredItem: any) => { + return this.selectedItems ? this.selectedItems.indexOf(filteredItem) < 0 : true; + }); + } +} + +@Component({ + template: ` + + + {{chip.name}} + + + {{option.name}} + + `, +}) +class TdChipsObjectsRequireMatchTestComponent { + selectedObjects: any[] = []; + objects: any[]; +} + +@Component({ + template: ` + + `, +}) +class TdChipsStackedTestComponent { + stacked: boolean = false; + items: string[] = [ + 'steak', + 'pizza', + 'tacos', + 'sandwich', + 'chips', + 'pasta', + 'sushi', + ]; + selectedItems: string[] = this.items.slice(0, 3); +} + +@Component({ + template: ` + + `, +}) +class TdChipRemovalTestComponent { + chipRemoval: boolean = true; + chipAddition: boolean = true; + items: string[] = [ + 'steak', + 'pizza', + 'tacos', + 'sandwich', + 'chips', + 'pasta', + 'sushi', + ]; + selectedItems: string[] = this.items.slice(0, 3); } diff --git a/src/platform/core/chips/chips.component.ts b/src/platform/core/chips/chips.component.ts index 419da5af4a..b705e9a3a1 100644 --- a/src/platform/core/chips/chips.component.ts +++ b/src/platform/core/chips/chips.component.ts @@ -1,51 +1,92 @@ -import { Component, Input, Output, forwardRef, DoCheck, ViewChild, ViewChildren, QueryList, OnInit, HostListener } from '@angular/core'; +import { Component, Input, Output, forwardRef, DoCheck, ViewChild, ViewChildren, QueryList, OnInit, HostListener, + ElementRef, Optional, Inject, Directive, TemplateRef, ViewContainerRef, ContentChild, ChangeDetectionStrategy, + ChangeDetectorRef, AfterViewInit, OnDestroy, HostBinding, Renderer2 } from '@angular/core'; +import { DOCUMENT } from '@angular/platform-browser'; import { EventEmitter } from '@angular/core'; import { NG_VALUE_ACCESSOR, ControlValueAccessor, FormControl } from '@angular/forms'; -import { MdChip, MdInputDirective, ESCAPE, LEFT_ARROW, RIGHT_ARROW, DELETE, BACKSPACE } from '@angular/material'; + +import { MdChip, MdInputDirective, TemplatePortalDirective, MdOption, MdAutocompleteTrigger, UP_ARROW, DOWN_ARROW, + ESCAPE, LEFT_ARROW, RIGHT_ARROW, DELETE, BACKSPACE, ENTER, SPACE, TAB, HOME } from '@angular/material'; + import { Observable } from 'rxjs/Observable'; -import { Subject } from 'rxjs/Subject'; +import { Subscription } from 'rxjs/Subscription'; import 'rxjs/add/observable/timer'; +import 'rxjs/add/operator/toPromise'; import 'rxjs/add/operator/debounceTime'; const noop: any = () => { // empty method }; -export const TD_CHIPS_CONTROL_VALUE_ACCESSOR: any = { - provide: NG_VALUE_ACCESSOR, - useExisting: forwardRef(() => TdChipsComponent), - multi: true, -}; +@Directive({ + selector: '[td-chip]ng-template', +}) +export class TdChipDirective extends TemplatePortalDirective { + constructor(templateRef: TemplateRef, viewContainerRef: ViewContainerRef) { + super(templateRef, viewContainerRef); + } +} + +@Directive({ + selector: '[td-autocomplete-option]ng-template', +}) +export class TdAutocompleteOptionDirective extends TemplatePortalDirective { + constructor(templateRef: TemplateRef, viewContainerRef: ViewContainerRef) { + super(templateRef, viewContainerRef); + } +} @Component({ - providers: [ TD_CHIPS_CONTROL_VALUE_ACCESSOR ], + providers: [{ + provide: NG_VALUE_ACCESSOR, + useExisting: forwardRef(() => TdChipsComponent), + multi: true, + }], selector: 'td-chips', styleUrls: ['./chips.component.scss' ], templateUrl: './chips.component.html', + changeDetection: ChangeDetectionStrategy.OnPush, }) -export class TdChipsComponent implements ControlValueAccessor, DoCheck, OnInit { +export class TdChipsComponent implements ControlValueAccessor, DoCheck, OnInit, AfterViewInit, OnDestroy { + + private _outsideClickSubs: Subscription; + + private _isMousedown: boolean = false; /** * Implemented as part of ControlValueAccessor. */ - private _value: any = []; + private _value: any[] = []; + private _items: any[]; private _length: number = 0; + private _stacked: boolean = false; private _requireMatch: boolean = false; private _readOnly: boolean = false; + private _color: 'primary' | 'accent' | 'warn' = 'primary'; private _chipAddition: boolean = true; + private _chipRemoval: boolean = true; + private _focused: boolean = false; + private _tabIndex: number = 0; + + _internalClick: boolean = false; + @ViewChild('input') _nativeInput: ElementRef; @ViewChild(MdInputDirective) _inputChild: MdInputDirective; + @ViewChild(MdAutocompleteTrigger) _autocompleteTrigger: MdAutocompleteTrigger; @ViewChildren(MdChip) _chipsChildren: QueryList; - /** - * Boolean value that specifies if the input is valid against the provieded list. - */ - matches: boolean = true; + @ContentChild(TdChipDirective) _chipTemplate: TdChipDirective; + @ContentChild(TdAutocompleteOptionDirective) _autocompleteOptionTemplate: TdAutocompleteOptionDirective; + + @ViewChildren(MdOption) _options: QueryList; + /** * Flag that is true when autocomplete is focused. */ - focused: boolean = false; + get focused(): boolean { + return this._focused; + } /** * FormControl for the mdInput element. @@ -53,25 +94,35 @@ export class TdChipsComponent implements ControlValueAccessor, DoCheck, OnInit { inputControl: FormControl = new FormControl(); /** - * Subject to control what items to render in the autocomplete - */ - subject: Subject = new Subject(); - - /** - * Observable of items to render in the autocomplete + * items?: any[] + * Renders the `md-autocomplete` with the provided list to display as options. */ - filteredItems: Observable = this.subject.asObservable(); + @Input('items') + set items(items: any[]) { + this._items = items; + this._setFirstOptionActive(); + this._changeDetectorRef.markForCheck(); + } + get items(): any[] { + return this._items; + } /** - * items?: string[] - * Enables Autocompletion with the provided list of strings. + * stacked?: boolean + * Set stacked or horizontal chips depending on value. + * Defaults to false. */ - @Input('items') items: string[] = []; + @Input('stacked') + set stacked(stacked: any) { + this._stacked = stacked !== '' ? (stacked === 'true' || stacked === true) : true; + } + get stacked(): any { + return this._stacked; + } /** * requireMatch?: boolean - * Validates input against the provided list before adding it to the model. - * If it doesnt exist, it cancels the event. + * Blocks custom inputs and only allows selections from the autocomplete list. */ @Input('requireMatch') set requireMatch(requireMatch: any) { @@ -96,8 +147,8 @@ export class TdChipsComponent implements ControlValueAccessor, DoCheck, OnInit { /** * chipAddition?: boolean - * Disables the ability to add chips. If it doesn't exist chip addition defaults to true. - * When setting readOnly as true, this will be overriden. + * Disables the ability to add chips. When setting readOnly as true, this will be overriden. + * Defaults to true. */ @Input('chipAddition') set chipAddition(chipAddition: boolean) { @@ -116,25 +167,76 @@ export class TdChipsComponent implements ControlValueAccessor, DoCheck, OnInit { return this.chipAddition && !this.readOnly; } + /** + * chipRemoval?: boolean + * Disables the ability to remove chips. If it doesn't exist chip remmoval defaults to true. + * When setting readOnly as true, this will be overriden to false. + */ + @Input('chipRemoval') + set chipRemoval(chipRemoval: boolean) { + this._chipRemoval = chipRemoval; + } + get chipRemoval(): boolean { + return this._chipRemoval; + } + + /** + * Checks if not in readOnly state and if chipRemoval is set to 'true' + * States if a chip can be removed + */ + get canRemoveChip(): boolean { + return this.chipRemoval && !this.readOnly; + } + /** * placeholder?: string * Placeholder for the autocomplete input. */ @Input('placeholder') placeholder: string; + /** + * debounce?: number + * Debounce timeout between keypresses. Defaults to 200. + */ + @Input('debounce') debounce: number = 200; + + /** + * color?: 'primary' | 'accent' | 'warn' + * Sets the color for the input and focus/selected state of the chips. + * Defaults to 'primary' + */ + @Input('color') + set color(color: 'primary' | 'accent' | 'warn') { + if (color) { + this._renderer.removeClass(this._elementRef.nativeElement, 'mat-' + this._color); + this._color = color; + this._renderer.addClass(this._elementRef.nativeElement, 'mat-' + this._color); + } + } + get color(): 'primary' | 'accent' | 'warn' { + return this._color; + } + /** * add?: function - * Method to be executed when string is added as chip through the autocomplete. + * Method to be executed when a chip is added. * Sends chip value as event. */ - @Output('add') add: EventEmitter = new EventEmitter(); + @Output('add') onAdd: EventEmitter = new EventEmitter(); /** * remove?: function - * Method to be executed when string is removed as chip with the "remove" button. + * Method to be executed when a chip is removed. * Sends chip value as event. */ - @Output('remove') remove: EventEmitter = new EventEmitter(); + @Output('remove') onRemove: EventEmitter = new EventEmitter(); + + /** + * inputChange?: function + * Method to be executed when the value in the autocomplete input changes. + * Sends string value as event. + */ + @Output('inputChange') onInputChange: EventEmitter = new EventEmitter(); /** * Implemented as part of ControlValueAccessor. @@ -143,24 +245,103 @@ export class TdChipsComponent implements ControlValueAccessor, DoCheck, OnInit { if (v !== this._value) { this._value = v; this._length = this._value ? this._value.length : 0; - if (this._value) { - this._filter(this.inputControl.value); - } + this._changeDetectorRef.markForCheck(); } } get value(): any { return this._value; } + /** + * Hostbinding to set the a11y of the TdChipsComponent depending on its state + */ + @HostBinding('attr.tabindex') + get tabIndex(): number { + return this.readOnly ? -1 : this._tabIndex; + } + + constructor(private _elementRef: ElementRef, + private _renderer: Renderer2, + private _changeDetectorRef: ChangeDetectorRef, + @Optional() @Inject(DOCUMENT) private _document: any) { + this._renderer.addClass(this._elementRef.nativeElement, 'mat-' + this._color); + } + + /** + * Listens to host focus event to act on it + */ + @HostListener('focus', ['$event']) + focusListener(event: FocusEvent): void { + // should only focus if its not via mousedown to prevent clashing with autocomplete + if (!this._isMousedown) { + this.focus(); + } + event.preventDefault(); + } + + /** + * Listens to host mousedown event to act on it + */ + @HostListener('mousedown', ['$event']) + mousedownListener(event: FocusEvent): void { + // sets a flag to know if there was a mousedown and then it returns it back to false + this._isMousedown = true; + Observable.timer().toPromise().then(() => { + this._isMousedown = false; + }); + } + + /** + * If clicking on :host or `td-chips-wrapper`, then we stop the click propagation so the autocomplete + * doesnt close automatically. + */ + @HostListener('click', ['$event']) + clickListener(event: Event): void { + const clickTarget: HTMLElement = event.target; + if (clickTarget === this._elementRef.nativeElement || + clickTarget.className.indexOf('td-chips-wrapper') > -1) { + this.focus(); + event.preventDefault(); + event.stopPropagation(); + } + } + + /** + * Listens to host keydown event to act on it depending on the keypress + */ + @HostListener('keydown', ['$event']) + keydownListener(event: KeyboardEvent): void { + switch (event.keyCode) { + case TAB: + // if tabing out, then unfocus the component + Observable.timer().toPromise().then(() => { + this.removeFocusedState(); + }); + break; + case ESCAPE: + if (this._inputChild.focused) { + this._nativeInput.nativeElement.blur(); + this.removeFocusedState(); + this._closeAutocomplete(); + } else { + this.focus(); + } + break; + default: + // default + } + } + ngOnInit(): void { this.inputControl.valueChanges - .debounceTime(100) + .debounceTime(this.debounce) .subscribe((value: string) => { - this.matches = true; - this._filter(value); + this.onInputChange.emit(value ? value : ''); }); - // filter the autocomplete options after everything is rendered - Observable.timer().subscribe(() => { - this._filter(this.inputControl.value); - }); + this._changeDetectorRef.markForCheck(); + } + + ngAfterViewInit(): void { + this._watchOutsideClick(); + this._changeDetectorRef.markForCheck(); } ngDoCheck(): void { @@ -171,35 +352,74 @@ export class TdChipsComponent implements ControlValueAccessor, DoCheck, OnInit { } } - /** - * Returns a list of filtered items. - */ - filter(val: string): string[] { - return this.items.filter((item: string) => { - return val ? item.indexOf(val) > -1 : true; - }); + ngOnDestroy(): void { + if (this._outsideClickSubs) { + this._outsideClickSubs.unsubscribe(); + this._outsideClickSubs = undefined; + } } /** * Method that is executed when trying to create a new chip from the autocomplete. + * It check if [requireMatch] is enabled, and tries to add the first active option + * else if just adds the value thats on the input * returns 'true' if successful, 'false' if it fails. */ - addChip(value: string): boolean { - if (value.trim() === '' || this._value.indexOf(value) > -1) { - this.matches = false; - return false; - } - if (this.items && this.requireMatch) { - if (this.items.indexOf(value) < 0) { - this.matches = false; + _handleAddChip(): boolean { + let value: any; + if (this.requireMatch) { + let selectedOptions: MdOption[] = this._options.toArray().filter((option: MdOption) => { + return option.active; + }); + if (selectedOptions.length > 0) { + value = selectedOptions[0].value; + selectedOptions[0].setInactiveStyles(); + } + if (!value) { return false; } + } else { + // if there is a selection, then use that + // else use the input value as chip + if (this._autocompleteTrigger.activeOption) { + value = this._autocompleteTrigger.activeOption.value; + this._autocompleteTrigger.activeOption.setInactiveStyles(); + } else { + value = this._inputChild.value; + if (value.trim() === '') { + return false; + } + } } + return this.addChip(value); + } + + /** + * Method thats exectuted when trying to add a value as chip + * returns 'true' if successful, 'false' if it fails. + */ + addChip(value: any): boolean { + /** + * add a debounce ms delay when reopening the autocomplete to give it time + * to rerender the next list and at the correct spot + */ + this._closeAutocomplete(); + Observable.timer(this.debounce).toPromise().then(() => { + this.setFocusedState(); + this._setFirstOptionActive(); + this._openAutocomplete(); + }); + + this.inputControl.setValue(''); + // check if value is already part of the model + if (this._value.indexOf(value) > -1) { + return false; + } + this._value.push(value); - this.add.emit(value); + this.onAdd.emit(value); this.onChange(this._value); - this.inputControl.setValue(''); - this.matches = true; + this._changeDetectorRef.markForCheck(); return true; } @@ -207,36 +427,66 @@ export class TdChipsComponent implements ControlValueAccessor, DoCheck, OnInit { * Method that is executed when trying to remove a chip. * returns 'true' if successful, 'false' if it fails. */ - removeChip(value: string): boolean { - let index: number = this._value.indexOf(value); - if (index < 0) { + removeChip(index: number): boolean { + let removedValues: any[] = this._value.splice(index, 1); + if (removedValues.length === 0) { return false; } - this._value.splice(index, 1); - this.remove.emit(value); + + /** + * Checks if deleting last single chip, to focus input afterwards + * Else check if its not the last chip of the list to focus the next one. + */ + if (index === (this._totalChips - 1) && index === 0) { + this._inputChild.focus(); + } else if (index < (this._totalChips - 1)) { + this._focusChip(index + 1); + } else if (index > 0) { + this._focusChip(index - 1); + } + + this.onRemove.emit(removedValues[0]); this.onChange(this._value); this.inputControl.setValue(''); + this._changeDetectorRef.markForCheck(); return true; } - handleFocus(): boolean { - this.focused = true; + _handleFocus(): boolean { + this.setFocusedState(); + this._setFirstOptionActive(); return true; } - handleBlur(): boolean { - this.focused = false; - this.matches = true; - this.onTouched(); - return true; + /** + * Sets focus state of the component + */ + setFocusedState(): void { + if (!this.readOnly) { + this._focused = true; + this._tabIndex = -1; + this._changeDetectorRef.markForCheck(); + } + } + + /** + * Removes focus state of the component + */ + removeFocusedState(): void { + this._focused = false; + this._tabIndex = 0; + this._changeDetectorRef.markForCheck(); } /** - * Programmatically focus the input. Since its the component entry point + * Programmatically focus the input or first chip. Since its the component entry point + * depending if a user can add or remove chips */ focus(): void { if (this.canAddChip) { this._inputChild.focus(); + } else if (!this.readOnly) { + this._focusFirstChip(); } } @@ -245,19 +495,37 @@ export class TdChipsComponent implements ControlValueAccessor, DoCheck, OnInit { */ _inputKeydown(event: KeyboardEvent): void { switch (event.keyCode) { + case UP_ARROW: + /** + * Since the first item is highlighted on [requireMatch], we need to inactivate it + * when pressing the up key + */ + if (this.requireMatch) { + let length: number = this._options.length; + if (length > 0 && this._options.toArray()[0].active) { + this._options.toArray()[0].setInactiveStyles(); + // prevent default window scrolling + event.preventDefault(); + } + } + break; case LEFT_ARROW: case DELETE: case BACKSPACE: + this._closeAutocomplete(); /** Check to see if input is empty when pressing left arrow to move to the last chip */ if (!this._inputChild.value) { this._focusLastChip(); + // prevent default window scrolling event.preventDefault(); } break; case RIGHT_ARROW: + this._closeAutocomplete(); /** Check to see if input is empty when pressing right arrow to move to the first chip */ if (!this._inputChild.value) { this._focusFirstChip(); + // prevent default window scrolling event.preventDefault(); } break; @@ -273,48 +541,81 @@ export class TdChipsComponent implements ControlValueAccessor, DoCheck, OnInit { switch (event.keyCode) { case DELETE: case BACKSPACE: - /** Check to see if not in [readOnly] state to delete a chip */ - if (!this.readOnly) { - /** - * Checks if deleting last single chip, to focus input afterwards - * Else check if its not the last chip of the list to focus the next one. - */ - if (index === (this._totalChips - 1) && index === 0) { - this.focus(); - } else if (index < (this._totalChips - 1)) { - this._focusChip(index + 1); - } - this.removeChip(this.value[index]); + /** Check to see if we can delete a chip */ + if (this.canRemoveChip) { + this.removeChip(index); } break; + case UP_ARROW: case LEFT_ARROW: /** - * Check to see if left arrow was pressed while focusing the first chip to focus input next + * Check to see if left/down arrow was pressed while focusing the first chip to focus input next * Also check if input should be focused */ - if (index === 0 && this.canAddChip) { - this.focus(); - event.stopPropagation(); + if (index === 0) { + // only try to target input if pressing left + if (this.canAddChip && event.keyCode === LEFT_ARROW) { + this._inputChild.focus(); + } else { + this._focusLastChip(); + } + } else if (index > 0) { + this._focusChip(index - 1); } + // prevent default window scrolling + event.preventDefault(); break; + case DOWN_ARROW: case RIGHT_ARROW: /** - * Check to see if right arrow was pressed while focusing the last chip to focus input next + * Check to see if right/up arrow was pressed while focusing the last chip to focus input next * Also check if input should be focused */ - if (index === (this._totalChips - 1) && this.canAddChip) { - this.focus(); - event.stopPropagation(); + if (index === (this._totalChips - 1)) { + // only try to target input if pressing right + if (this.canAddChip && event.keyCode === RIGHT_ARROW) { + this._inputChild.focus(); + } else { + this._focusFirstChip(); + } + } else if (index < (this._totalChips - 1)) { + this._focusChip(index + 1); } - break; - case ESCAPE: - this.focus(); + // prevent default window scrolling + event.preventDefault(); break; default: // default } } + /** + * Method to remove from display the value added from the autocomplete since it goes directly as chip. + */ + _removeInputDisplay(): string { + return ''; + } + + /** + * Method to open the autocomplete manually if its not already opened + */ + _openAutocomplete(): void { + if (!this._autocompleteTrigger.panelOpen) { + this._autocompleteTrigger.openPanel(); + this._changeDetectorRef.markForCheck(); + } + } + + /** + * Method to close the autocomplete manually if its not already closed + */ + _closeAutocomplete(): void { + if (this._autocompleteTrigger.panelOpen) { + this._autocompleteTrigger.closePanel(); + this._changeDetectorRef.markForCheck(); + } + } + /** * Implemented as part of ControlValueAccessor. */ @@ -333,22 +634,10 @@ export class TdChipsComponent implements ControlValueAccessor, DoCheck, OnInit { onChange = (_: any) => noop; onTouched = () => noop; - /** - * - * Method to filter the options for the autocomplete - */ - private _filter(value: string): void { - let items: string[] = this.filter(value); - items = items.filter((filteredItem: string) => { - return this._value && filteredItem ? this._value.indexOf(filteredItem) < 0 : true; - }); - this.subject.next(items); - } - /** * Get total of chips */ - private get _totalChips(): number { + get _totalChips(): number { let chips: MdChip[] = this._chipsChildren.toArray(); return chips.length; } @@ -383,5 +672,53 @@ export class TdChipsComponent implements ControlValueAccessor, DoCheck, OnInit { } else { this.inputControl.disable(); } + this._changeDetectorRef.markForCheck(); + } + + /** + * Sets first option as active to let the user know which one will be added when pressing enter + * Only if [requireMatch] has been set + */ + private _setFirstOptionActive(): void { + if (this.requireMatch) { + // need to use a timer here to wait until the autocomplete has been opened (end of queue) + Observable.timer().toPromise().then(() => { + if (this.focused && this._options && this._options.length > 0) { + // clean up of previously active options + this._options.toArray().forEach((option: MdOption) => { + option.setInactiveStyles(); + }); + // set the first one as active + this._options.toArray()[0].setActiveStyles(); + this._changeDetectorRef.markForCheck(); + } + }); + } + } + + /** + * Watches clicks outside of the component to remove the focus + * The autocomplete panel is considered inside the component so we + * need to use a flag to find out when its clicked. + */ + private _watchOutsideClick(): void { + if (this._document) { + this._outsideClickSubs = Observable.fromEvent(this._document, 'click').filter((event: MouseEvent) => { + const clickTarget: HTMLElement = event.target; + setTimeout(() => { + this._internalClick = false; + }); + return this.focused && + (clickTarget !== this._elementRef.nativeElement) && + !this._elementRef.nativeElement.contains(clickTarget) && !this._internalClick; + }).subscribe(() => { + if (this.focused) { + this.removeFocusedState(); + this.onTouched(); + this._changeDetectorRef.markForCheck(); + } + }); + } + return undefined; } } diff --git a/src/platform/core/chips/chips.module.ts b/src/platform/core/chips/chips.module.ts index 90bbb29763..c22cf37545 100644 --- a/src/platform/core/chips/chips.module.ts +++ b/src/platform/core/chips/chips.module.ts @@ -5,8 +5,8 @@ import { CommonModule } from '@angular/common'; import { MdInputModule, MdIconModule, MdAutocompleteModule, MdChipsModule } from '@angular/material'; -import { TdChipsComponent } from './chips.component'; -export { TdChipsComponent } from './chips.component'; +import { TdChipsComponent, TdChipDirective, TdAutocompleteOptionDirective } from './chips.component'; +export { TdChipsComponent, TdChipDirective, TdAutocompleteOptionDirective } from './chips.component'; @NgModule({ imports: [ @@ -19,9 +19,13 @@ export { TdChipsComponent } from './chips.component'; ], declarations: [ TdChipsComponent, + TdChipDirective, + TdAutocompleteOptionDirective, ], exports: [ TdChipsComponent, + TdChipDirective, + TdAutocompleteOptionDirective, ], }) export class CovalentChipsModule { diff --git a/src/platform/core/common/animations/fade/fade.directive.ts b/src/platform/core/common/animations/fade/fade.directive.ts index fa235bb7bc..bbdbd881c4 100644 --- a/src/platform/core/common/animations/fade/fade.directive.ts +++ b/src/platform/core/common/animations/fade/fade.directive.ts @@ -1,9 +1,5 @@ -import { - Directive, ElementRef, Input, Output, EventEmitter, HostBinding, Renderer2, OnInit, ChangeDetectorRef, AnimationPlayer, -} from '@angular/core'; -import { ɵAnimation as Animation, AnimationDriver, - ɵAnimationStyleNormalizer as AnimationStyleNormalizer, ɵDomAnimationEngine as DomAnimationEngine } from '@angular/animations/browser'; -import { animate } from '@angular/animations'; +import { Directive, ElementRef, Input, Output, EventEmitter, HostBinding, Renderer2, ChangeDetectorRef } from '@angular/core'; +import { animate, AnimationBuilder, AnimationPlayer, AUTO_STYLE, style, animation } from '@angular/animations'; @Directive({ selector: '[tdFade]', @@ -11,10 +7,9 @@ import { animate } from '@angular/animations'; export class TdFadeDirective { private _state: boolean; - private _defaultOpacity: string; private _defaultDisplay: string; - private _engine: DomAnimationEngine; - private _animationPlayer: AnimationPlayer; + private _animationFadeInPlayer: AnimationPlayer; + private _animationFadeOutPlayer: AnimationPlayer; /** * duration?: number @@ -30,13 +25,17 @@ export class TdFadeDirective { @Input('tdFade') set state(state: boolean) { this._state = state; - if (this._animationPlayer) { - this._animationPlayer.destroy(); - this._animationPlayer = undefined; - } if (state) { + if (this._animationFadeOutPlayer) { + this._animationFadeOutPlayer.destroy(); + this._animationFadeOutPlayer = undefined; + } this.hide(); } else { + if (this._animationFadeInPlayer) { + this._animationFadeInPlayer.destroy(); + this._animationFadeInPlayer = undefined; + } this.show(); } } @@ -45,13 +44,13 @@ export class TdFadeDirective { * fadeIn?: function * Method to be executed when fadeIn animation ends. */ - @Output('fadeIn') fadeIn: EventEmitter = new EventEmitter(); + @Output('fadeIn') onFadeIn: EventEmitter = new EventEmitter(); /** * fadeOut?: function * Method to be executed when fadeOut animation ends. */ - @Output('fadeOut') fadeOut: EventEmitter = new EventEmitter(); + @Output('fadeOut') onFadeOut: EventEmitter = new EventEmitter(); /** * Binds native 'aria-expanded' attribute. @@ -72,28 +71,25 @@ export class TdFadeDirective { constructor(private _renderer: Renderer2, private _element: ElementRef, private _changeDetectorRef: ChangeDetectorRef, - animationDriver: AnimationDriver, - animationStyleNormalizer: AnimationStyleNormalizer) { - this._engine = new DomAnimationEngine(animationDriver, animationStyleNormalizer); + private _animationBuilder: AnimationBuilder) { + this._defaultDisplay = this._element.nativeElement.style.display; } /** * Hides element: starts animation and adds "display:'none'" style at the end. */ hide(): void { - this._defaultDisplay = this._element.nativeElement.style.display; - this._defaultOpacity = !this._element.nativeElement.style.opacity ? 1 : this._element.nativeElement.style.opacity; - this._animationPlayer = this._engine.animateTimeline( - this._element.nativeElement, - new Animation([animate(this.duration + 'ms ease-out')], - ).buildTimelines([{opacity: this._defaultOpacity}], [{opacity: 0}])); - this._changeDetectorRef.markForCheck(); - this._animationPlayer.play(); - this._animationPlayer.onDone(() => { - this._animationPlayer.destroy(); - this._renderer.setStyle(this._element.nativeElement, 'display', 'none'); - this._changeDetectorRef.markForCheck(); + this._animationFadeInPlayer = this._animationBuilder.build(animation([ + style({ + opacity: AUTO_STYLE, + display: AUTO_STYLE, + }), + animate(this.duration + 'ms ease-out', style({opacity: '0'})), + ])).create(this._element.nativeElement); + this._animationFadeInPlayer.onDone(() => { + this._onFadeInDone(); }); + this._animationFadeInPlayer.play(); } /** @@ -102,14 +98,35 @@ export class TdFadeDirective { show(): void { this._renderer.setStyle(this._element.nativeElement, 'display', this._defaultDisplay); this._changeDetectorRef.markForCheck(); - this._animationPlayer = this._engine.animateTimeline( - this._element.nativeElement, - new Animation([animate(this.duration + 'ms ease-in')], - ).buildTimelines([{opacity: 0}], [{opacity: this._defaultOpacity}])); - this._animationPlayer.play(); - this._animationPlayer.onDone(() => { - this._animationPlayer.destroy(); - this._changeDetectorRef.markForCheck(); + this._animationFadeOutPlayer = this._animationBuilder.build(animation([ + style({ + opacity: '0', + display: 'none', + }), + animate(this.duration + 'ms ease-in', style({opacity: AUTO_STYLE})), + ])).create(this._element.nativeElement); + this._animationFadeOutPlayer.onDone(() => { + this._onFadeOutDone(); }); + this._animationFadeOutPlayer.play(); + } + + private _onFadeInDone(): void { + if (this._animationFadeInPlayer) { + this._animationFadeInPlayer.destroy(); + this._animationFadeInPlayer = undefined; + this._renderer.setStyle(this._element.nativeElement, 'display', 'none'); + this._changeDetectorRef.markForCheck(); + this.onFadeIn.emit(); + } + } + + private _onFadeOutDone(): void { + if (this._animationFadeOutPlayer) { + this._animationFadeOutPlayer.destroy(); + this._animationFadeOutPlayer = undefined; + this._changeDetectorRef.markForCheck(); + this.onFadeOut.emit(); + } } } diff --git a/src/platform/core/common/animations/toggle/toggle.directive.ts b/src/platform/core/common/animations/toggle/toggle.directive.ts index ce1d3b45c3..5aae207752 100644 --- a/src/platform/core/common/animations/toggle/toggle.directive.ts +++ b/src/platform/core/common/animations/toggle/toggle.directive.ts @@ -1,7 +1,5 @@ -import { Directive, ElementRef, Input, HostBinding, Renderer2, AnimationPlayer, OnInit, ChangeDetectorRef } from '@angular/core'; -import { ɵAnimation as Animation, AnimationDriver, - ɵAnimationStyleNormalizer as AnimationStyleNormalizer, ɵDomAnimationEngine as DomAnimationEngine } from '@angular/animations/browser'; -import { animate } from '@angular/animations'; +import { Directive, ElementRef, Input, HostBinding, Renderer2, ChangeDetectorRef } from '@angular/core'; +import { animate, AnimationBuilder, AnimationPlayer, AUTO_STYLE, style, animation } from '@angular/animations'; @Directive({ selector: '[tdToggle]', @@ -11,8 +9,8 @@ export class TdToggleDirective { private _state: boolean; private _defaultOverflow: string; private _defaultDisplay: string; - private _engine: DomAnimationEngine; - private _animationPlayer: AnimationPlayer; + private _animationShowPlayer: AnimationPlayer; + private _animationHidePlayer: AnimationPlayer; /** * duration?: number @@ -28,13 +26,17 @@ export class TdToggleDirective { @Input('tdToggle') set state(state: boolean) { this._state = state; - if (this._animationPlayer) { - this._animationPlayer.destroy(); - this._animationPlayer = undefined; - } if (state) { + if (this._animationShowPlayer) { + this._animationShowPlayer.destroy(); + this._animationShowPlayer = undefined; + } this.hide(); } else { + if (this._animationHidePlayer) { + this._animationHidePlayer.destroy(); + this._animationHidePlayer = undefined; + } this.show(); } } @@ -58,9 +60,9 @@ export class TdToggleDirective { constructor(private _renderer: Renderer2, private _element: ElementRef, private _changeDetectorRef: ChangeDetectorRef, - animationDriver: AnimationDriver, - animationStyleNormalizer: AnimationStyleNormalizer) { - this._engine = new DomAnimationEngine(animationDriver, animationStyleNormalizer); + private _animationBuilder: AnimationBuilder) { + this._defaultDisplay = this._element.nativeElement.style.display; + this._defaultOverflow = this._element.nativeElement.style.overflow; } /** @@ -68,21 +70,19 @@ export class TdToggleDirective { * starts animation and adds "display:'none'" style at the end. */ hide(): void { - this._defaultDisplay = this._element.nativeElement.style.display; - this._defaultOverflow = this._element.nativeElement.style.overflow; - this._animationPlayer = this._engine.animateTimeline( - this._element.nativeElement, - new Animation([animate(this.duration + 'ms ease-out')], - ).buildTimelines([{height: this._element.nativeElement.scrollHeight + 'px'}], [{height: 0}])); + this._animationHidePlayer = this._animationBuilder.build(animation([ + style({ + height: AUTO_STYLE, + display: AUTO_STYLE, + }), + animate(this.duration + 'ms ease-in', style({height: '0'})), + ])).create(this._element.nativeElement); this._renderer.setStyle(this._element.nativeElement, 'overflow', 'hidden'); this._changeDetectorRef.markForCheck(); - this._animationPlayer.play(); - this._animationPlayer.onDone(() => { - this._animationPlayer.destroy(); - this._renderer.setStyle(this._element.nativeElement, 'overflow', this._defaultOverflow); - this._renderer.setStyle(this._element.nativeElement, 'display', 'none'); - this._changeDetectorRef.markForCheck(); + this._animationHidePlayer.onDone(() => { + this._onHideDone(); }); + this._animationHidePlayer.play(); } /** @@ -92,16 +92,36 @@ export class TdToggleDirective { show(): void { this._renderer.setStyle(this._element.nativeElement, 'display', this._defaultDisplay); this._changeDetectorRef.markForCheck(); - this._animationPlayer = this._engine.animateTimeline( - this._element.nativeElement, - new Animation([animate(this.duration + 'ms ease-in')], - ).buildTimelines([{height: 0}], [{height: this._element.nativeElement.scrollHeight + 'px'}])); + this._animationShowPlayer = this._animationBuilder.build(animation([ + style({ + height: '0', + display: 'none', + }), + animate(this.duration + 'ms ease-out', style({height: AUTO_STYLE})), + ])).create(this._element.nativeElement); this._renderer.setStyle(this._element.nativeElement, 'overflow', 'hidden'); - this._animationPlayer.play(); - this._animationPlayer.onDone(() => { - this._animationPlayer.destroy(); + this._animationShowPlayer.onDone(() => { + this._onShowDone(); + }); + this._animationShowPlayer.play(); + } + + private _onHideDone(): void { + if (this._animationHidePlayer) { + this._animationHidePlayer.destroy(); + this._animationHidePlayer = undefined; this._renderer.setStyle(this._element.nativeElement, 'overflow', this._defaultOverflow); + this._renderer.setStyle(this._element.nativeElement, 'display', 'none'); this._changeDetectorRef.markForCheck(); - }); + } + } + + private _onShowDone(): void { + if (this._animationShowPlayer) { + this._animationShowPlayer.destroy(); + this._animationShowPlayer = undefined; + this._renderer.setStyle(this._element.nativeElement, 'overflow', this._defaultOverflow); + this._changeDetectorRef.markForCheck(); + } } } diff --git a/src/platform/core/common/common.module.ts b/src/platform/core/common/common.module.ts index fafe581edf..2936622908 100644 --- a/src/platform/core/common/common.module.ts +++ b/src/platform/core/common/common.module.ts @@ -34,15 +34,9 @@ const TD_FORMS: Type[] = [ export { TdAutoTrimDirective }; // Validators -import { TdMinValidator } from './forms/validators/min/min.validator'; -import { TdMaxValidator } from './forms/validators/max/max.validator'; - const TD_VALIDATORS: Type[] = [ - TdMinValidator, - TdMaxValidator, ]; -export { TdMinValidator, TdMaxValidator }; export { CovalentValidators } from './forms/validators/validators'; /** diff --git a/src/platform/core/common/forms/validators/max/max.validator.ts b/src/platform/core/common/forms/validators/max/max.validator.ts deleted file mode 100644 index 76bdbbdb1a..0000000000 --- a/src/platform/core/common/forms/validators/max/max.validator.ts +++ /dev/null @@ -1,28 +0,0 @@ -import { Directive, Input, forwardRef } from '@angular/core'; -import { NG_VALIDATORS, Validator, Validators, AbstractControl, ValidatorFn } from '@angular/forms'; - -import { CovalentValidators } from '../validators'; - -export const MAX_VALIDATOR: any = { - provide: NG_VALIDATORS, - useExisting: forwardRef(() => TdMaxValidator), - multi: true, -}; - -@Directive({ - selector: '[max][formControlName],[max][formControl],[max][ngModel]', - providers: [ MAX_VALIDATOR ], -}) -export class TdMaxValidator implements Validator { - - private _validator: ValidatorFn; - - @Input('max') - set max(max: number) { - this._validator = CovalentValidators.max(max); - } - - validate(c: AbstractControl): {[key: string]: any} { - return this._validator(c); - } -} diff --git a/src/platform/core/common/forms/validators/min/min.validator.ts b/src/platform/core/common/forms/validators/min/min.validator.ts deleted file mode 100644 index 6fdd69fce0..0000000000 --- a/src/platform/core/common/forms/validators/min/min.validator.ts +++ /dev/null @@ -1,28 +0,0 @@ -import { Directive, Input, forwardRef } from '@angular/core'; -import { NG_VALIDATORS, Validator, Validators, AbstractControl, ValidatorFn } from '@angular/forms'; - -import { CovalentValidators } from '../validators'; - -export const MIN_VALIDATOR: any = { - provide: NG_VALIDATORS, - useExisting: forwardRef(() => TdMinValidator), - multi: true, -}; - -@Directive({ - selector: '[min][formControlName],[min][formControl],[min][ngModel]', - providers: [ MIN_VALIDATOR ], -}) -export class TdMinValidator implements Validator { - - private _validator: ValidatorFn; - - @Input('min') - set min(min: number) { - this._validator = CovalentValidators.min(min); - } - - validate(c: AbstractControl): {[key: string]: any} { - return this._validator(c); - } -} diff --git a/src/platform/core/common/styles/_card.scss b/src/platform/core/common/styles/_card.scss index 9154b25103..7f10bdd802 100644 --- a/src/platform/core/common/styles/_card.scss +++ b/src/platform/core/common/styles/_card.scss @@ -1,6 +1,6 @@ @import 'variables'; -body { +html { .mat-card { padding: 0; margin: 8px; @@ -15,8 +15,14 @@ body { margin: 16px 0 0 15px; border-radius: 50%; } - [md-card-image] { + .mat-card-image { width: 100%; + } + .mat-card-image, + .mat-card-lg-image, + .mat-card-md-image, + .mat-card-sm-image, + .mat-card-title-group { margin: 0; } md-card-title { @@ -32,10 +38,70 @@ body { padding: $padding; } &, & .mat-card { - & .mat-card-actions:last-child { + & .mat-card-actions { padding: $padding / 2; margin: 0; } } + .mat-card-actions:last-child { + margin-bottom: 0px; + padding-bottom: 8px; + } + } + &:not([dir='rtl']) { + .mat-card-title-group { + .mat-card-image, + .mat-card-lg-image, + .mat-card-md-image, + .mat-card-sm-image { + &:last-child { + border-top-right-radius: $md-card-radius; + border-bottom-right-radius: $md-card-radius; + } + } + } + .mat-card { + .mat-card-image { + &:first-child { + border-top-left-radius: $md-card-radius; + border-top-right-radius: $md-card-radius; + } + } + .mat-card-lg-image, + .mat-card-md-image, + .mat-card-sm-image { + &:first-child { + border-top-left-radius: $md-card-radius; + } + } + } + } + &[dir='rtl'] { + .mat-card-title-group { + .mat-card-image, + .mat-card-lg-image, + .mat-card-md-image, + .mat-card-sm-image { + &:last-child { + border-top-left-radius: $md-card-radius; + border-bottom-left-radius: $md-card-radius; + } + } + } + .mat-card { + .mat-card-image { + &:first-child { + border-top-left-radius: $md-card-radius; + border-top-right-radius: $md-card-radius; + } + } + .mat-card-lg-image, + .mat-card-md-image, + .mat-card-sm-image { + &:first-child { + border-top-right-radius: $md-card-radius; + } + } + } } } diff --git a/src/platform/core/common/styles/_palette.scss b/src/platform/core/common/styles/_palette.scss index 0dab0b72c0..44fb8767af 100644 --- a/src/platform/core/common/styles/_palette.scss +++ b/src/platform/core/common/styles/_palette.scss @@ -635,66 +635,3 @@ $mat-blue-grey: ( A700: $white-87-opacity, ) ); - - -// Background palette for light themes. -$mat-light-theme-background: ( - status-bar: map_get($mat-grey, 300), - app-bar: map_get($mat-grey, 100), - background: map_get($mat-grey, 50), - hover: rgba(black, 0.04), // TODO(kara): check style with Material Design UX - card: white, - dialog: white, - disabled-button: $black-12-opacity, - raised-button: white, - focused-button: $black-6-opacity, - selected-button: map_get($mat-grey, 300), - selected-disabled-button: map_get($mat-grey, 400), - disabled-button-toggle: map_get($mat-grey, 200), -); - -// Background palette for dark themes. -$mat-dark-theme-background: ( - status-bar: black, - app-bar: map_get($mat-grey, 900), - background: #303030, - hover: rgba(white, 0.04), // TODO(kara): check style with Material Design UX - card: map_get($mat-grey, 800), - dialog: map_get($mat-grey, 800), - disabled-button: $white-12-opacity, - raised-button: map-get($mat-grey, 800), - focused-button: $white-6-opacity, - selected-button: map_get($mat-grey, 900), - selected-disabled-button: map_get($mat-grey, 800), - disabled-button-toggle: map_get($mat-grey, 1000), -); - -// Foreground palette for light themes. -$mat-light-theme-foreground: ( - base: black, - divider: $black-12-opacity, - dividers: $black-12-opacity, - disabled: rgba(black, 0.38), - disabled-button: rgba(black, 0.38), - disabled-text: rgba(black, 0.38), - hint-text: rgba(black, 0.38), - secondary-text: rgba(black, 0.54), - icon: rgba(black, 0.54), - icons: rgba(black, 0.54), - text: rgba(black, 0.87) -); - -// Foreground palette for dark themes. -$mat-dark-theme-foreground: ( - base: white, - divider: $white-12-opacity, - dividers: $white-12-opacity, - disabled: rgba(white, 0.3), - disabled-button: rgba(white, 0.3), - disabled-text: rgba(white, 0.3), - hint-text: rgba(white, 0.3), - secondary-text: rgba(white, 0.7), - icon: white, - icons: white, - text: white -); \ No newline at end of file diff --git a/src/platform/core/common/styles/_theme-functions.scss b/src/platform/core/common/styles/_theme-functions.scss index 19046d13d0..3bd6a8208a 100644 --- a/src/platform/core/common/styles/_theme-functions.scss +++ b/src/platform/core/common/styles/_theme-functions.scss @@ -1,44 +1,8 @@ -@import 'palette'; - @function rem($multiplier) { $font-size: 10px; @return $multiplier * $font-size; } -// For a given hue in a palette, return the contrast color from the map of contrast palettes. -// @param $color-map -// @param $hue -@function mat-contrast($palette, $hue) { - @return map-get(map-get($palette, contrast), $hue); -} - - -// Creates a map of hues to colors for a theme. This is used to define a theme palette in terms -// of the Material Design hues. -// @param $color-map -// @param $primary -// @param $lighter -@function mat-palette($base-palette, $default: 500, $lighter: 100, $darker: 700) { - $result: map_merge($base-palette, ( - default: map-get($base-palette, $default), - lighter: map-get($base-palette, $lighter), - darker: map-get($base-palette, $darker), - default-contrast: mat-contrast($base-palette, $default), - lighter-contrast: mat-contrast($base-palette, $lighter), - darker-contrast: mat-contrast($base-palette, $darker) - )); - - // For each hue in the palette, add a "-contrast" color to the map. - @each $hue, $color in $base-palette { - $result: map_merge($result, ( - '#{$hue}-contrast': mat-contrast($base-palette, $hue) - )); - } - - @return $result; -} - - // Gets a color from a theme palette (the output of mat-palette). // The hue can be one of the standard values (500, A400, etc.), one of the three preconfigured // hues (default, lighter, darker), or any of the aforementioned prefixed with "-contrast". @@ -47,7 +11,7 @@ // @param $hue The hue from the palette to use. If this is a value between 0 and 1, it will // be treated as opacity. // @param $opacity The alpha channel value for the color. -@function mat-color($palette, $hue: default, $opacity: 1) { +@function mat-color($palette, $hue: default, $opacity: null) { // If hueKey is a number between zero and one, then it actually contains an // opacity value, so recall this function with the default hue and that given opacity. @if type-of($hue) == number and $hue >= 0 and $hue <= 1 { @@ -55,33 +19,7 @@ } $color: map-get($palette, $hue); - $opacity: if(opacity($color) < 1, opacity($color), $opacity); + $opacity: if($opacity == null, opacity($color), $opacity); @return rgba($color, $opacity); } - - -// Creates a container object for a light theme to be given to individual component theme mixins. -@function mat-light-theme($primary, $accent, $warn: mat-palette($mat-red)) { - @return ( - primary: $primary, - accent: $accent, - warn: $warn, - is-dark: false, - foreground: $mat-light-theme-foreground, - background: $mat-light-theme-background, - ); -} - - -// Creates a container object for a dark theme to be given to individual component theme mixins. -@function mat-dark-theme($primary, $accent, $warn: mat-palette($mat-red)) { - @return ( - primary: $primary, - accent: $accent, - warn: $warn, - is-dark: true, - foreground: $mat-dark-theme-foreground, - background: $mat-dark-theme-background, - ); -} \ No newline at end of file diff --git a/src/platform/core/common/styles/_variables.scss b/src/platform/core/common/styles/_variables.scss index 6bc0580026..fef76e571c 100644 --- a/src/platform/core/common/styles/_variables.scss +++ b/src/platform/core/common/styles/_variables.scss @@ -39,6 +39,7 @@ $app-bar-height: 64px; // card header variables $md-card-header-size: 40px; +$md-card-radius: 2px; // Icons $icon-size: rem(2.4); diff --git a/src/platform/core/data-table/data-table.component.html b/src/platform/core/data-table/data-table.component.html index fca74c66fd..d59c0a8337 100644 --- a/src/platform/core/data-table/data-table.component.html +++ b/src/platform/core/data-table/data-table.component.html @@ -30,7 +30,7 @@ [tabIndex]="isSelectable ? 0 : -1" [class.mat-selected]="(isClickable || isSelectable) && isRowSelected(row)" *ngFor="let row of data; let rowIndex = index" - (click)="handleRowClick(row, $event, rowIndex)" + (click)="handleRowClick(row, $event)" (keyup)="isSelectable && _rowKeyup($event, row, rowIndex)" (keydown.space)="blockEvent($event)" (keydown.shift.space)="blockEvent($event)" @@ -41,6 +41,7 @@ [state]="isRowSelected(row) ? 'checked' : 'unchecked'" (mousedown)="disableTextSelection()" (mouseup)="enableTextSelection()" + stopRowClick (click)="select(row, $event, rowIndex)"> diff --git a/src/platform/core/data-table/data-table.component.spec.ts b/src/platform/core/data-table/data-table.component.spec.ts index 2adbf1782e..e6cf4fb235 100644 --- a/src/platform/core/data-table/data-table.component.spec.ts +++ b/src/platform/core/data-table/data-table.component.spec.ts @@ -15,20 +15,21 @@ import { TdDataTableService } from './services/data-table.service'; import { CovalentDataTableModule } from './data-table.module'; import { NgModule, DebugElement } from '@angular/core'; import { MdCheckbox } from '@angular/material'; -import { BrowserAnimationsModule } from '@angular/platform-browser/animations'; +import { NoopAnimationsModule } from '@angular/platform-browser/animations'; describe('Component: DataTable', () => { beforeEach(async(() => { TestBed.configureTestingModule({ imports: [ - BrowserAnimationsModule, + NoopAnimationsModule, CovalentDataTableModule, ], declarations: [ TdDataTableBasicTestComponent, TdDataTableSelectableTestComponent, TdDataTableRowClickTestComponent, + TdDataTableSelectableRowClickTestComponent, ], providers: [ TdDataTableService, @@ -330,6 +331,38 @@ describe('Component: DataTable', () => { }); }); }))); + + it('should click on a row and see the rowClick event only when clicking on row', + async(inject([], () => { + let fixture: ComponentFixture = TestBed.createComponent(TdDataTableSelectableRowClickTestComponent); + let component: TdDataTableSelectableRowClickTestComponent = fixture.debugElement.componentInstance; + + component.clickable = true; + component.selectable = true; + + let clickEventSpy: jasmine.Spy = spyOn(component, 'clickEvent'); + let selectEventSpy: jasmine.Spy = spyOn(component, 'selectEvent'); + + fixture.detectChanges(); + fixture.whenStable().then(() => { + fixture.debugElement.queryAll(By.directive(TdDataTableRowComponent))[1].nativeElement.click(); + fixture.detectChanges(); + fixture.whenStable().then(() => { + expect(clickEventSpy.calls.count()).toBe(1); + expect(selectEventSpy.calls.count()).toBe(0); + + fixture.detectChanges(); + fixture.whenStable().then(() => { + fixture.debugElement.queryAll(By.directive(MdPseudoCheckbox))[0].nativeElement.click(); + fixture.detectChanges(); + fixture.whenStable().then(() => { + expect(clickEventSpy.calls.count()).toBe(1); + expect(selectEventSpy.calls.count()).toBe(1); + }); + }); + }); + }); + }))); }); }); @@ -392,3 +425,34 @@ class TdDataTableRowClickTestComponent { /* noop */ } } + +@Component({ + template: ` + + `, +}) +class TdDataTableSelectableRowClickTestComponent { + data: any[] = [ + { sku: '1452-2', item: 'Pork Chops', price: 32.11 }, + { sku: '1421-0', item: 'Prime Rib', price: 41.15 }, + ]; + columns: ITdDataTableColumn[] = [ + { name: 'sku', label: 'SKU #' }, + { name: 'item', label: 'Item name' }, + { name: 'price', label: 'Price (US$)', numeric: true }, + ]; + selectable: boolean = false; + clickable: boolean = false; + clickEvent(): void { + /* noop */ + } + selectEvent(): void { + /* noop */ + } +} diff --git a/src/platform/core/data-table/data-table.component.ts b/src/platform/core/data-table/data-table.component.ts index 4598af0d2b..7744985538 100644 --- a/src/platform/core/data-table/data-table.component.ts +++ b/src/platform/core/data-table/data-table.component.ts @@ -435,9 +435,14 @@ export class TdDataTableComponent implements ControlValueAccessor, AfterContentI * emits the onRowClickEvent when a row is clicked * if clickable is true and selectable is false then select the row */ - handleRowClick(row: any, event: Event, currentSelected: number): void { + handleRowClick(row: any, event: Event): void { if (this.isClickable) { - this.onRowClick.emit({row: row}); + // ignoring linting rules here because attribute it actually null or not there + // can't check for undefined + /* tslint:disable-next-line */ + if (event.srcElement.getAttribute('stopRowClick') === null) { + this.onRowClick.emit({row: row}); + } } } diff --git a/src/platform/core/data-table/data-table.module.ts b/src/platform/core/data-table/data-table.module.ts index 6897c24a14..2e5f678029 100644 --- a/src/platform/core/data-table/data-table.module.ts +++ b/src/platform/core/data-table/data-table.module.ts @@ -8,9 +8,10 @@ import { TdDataTableColumnComponent } from './data-table-column/data-table-colum import { TdDataTableCellComponent } from './data-table-cell/data-table-cell.component'; import { TdDataTableRowComponent } from './data-table-row/data-table-row.component'; import { TdDataTableTableComponent } from './data-table-table/data-table-table.component'; -import { TdDataTableService } from './services/data-table.service'; import { TdDataTableTemplateDirective } from './directives/data-table-template.directive'; +import { TdDataTableService, DATA_TABLE_PROVIDER } from './services/data-table.service'; + const TD_DATA_TABLE: Type[] = [ TdDataTableComponent, TdDataTableTemplateDirective, @@ -45,7 +46,7 @@ export { TdDataTableTableComponent } from './data-table-table/data-table-table.c TD_DATA_TABLE, ], providers: [ - TdDataTableService, + DATA_TABLE_PROVIDER, ], }) export class CovalentDataTableModule { diff --git a/src/platform/core/data-table/services/data-table.service.ts b/src/platform/core/data-table/services/data-table.service.ts index 906b2155c3..d965d96bd4 100644 --- a/src/platform/core/data-table/services/data-table.service.ts +++ b/src/platform/core/data-table/services/data-table.service.ts @@ -1,4 +1,4 @@ -import { Injectable } from '@angular/core'; +import { Injectable, Provider, SkipSelf, Optional } from '@angular/core'; import { TdDataTableSortingOrder, ITdDataTableColumn } from '../data-table.component'; @@ -75,3 +75,15 @@ export class TdDataTableService { return data; } } + +export function DATA_TABLE_PROVIDER_FACTORY( + parent: TdDataTableService): TdDataTableService { + return parent || new TdDataTableService(); +} + +export const DATA_TABLE_PROVIDER: Provider = { + // If there is already a service available, use that. Otherwise, provide a new one. + provide: TdDataTableService, + deps: [[new Optional(), new SkipSelf(), TdDataTableService]], + useFactory: DATA_TABLE_PROVIDER_FACTORY, +}; diff --git a/src/platform/core/dialogs/dialogs.module.ts b/src/platform/core/dialogs/dialogs.module.ts index c42b48d416..ab5a43f29b 100644 --- a/src/platform/core/dialogs/dialogs.module.ts +++ b/src/platform/core/dialogs/dialogs.module.ts @@ -10,7 +10,7 @@ import { TdDialogComponent, TdDialogTitleDirective, import { TdAlertDialogComponent } from './alert-dialog/alert-dialog.component'; import { TdConfirmDialogComponent } from './confirm-dialog/confirm-dialog.component'; import { TdPromptDialogComponent } from './prompt-dialog/prompt-dialog.component'; -import { TdDialogService } from './services/dialog.service'; +import { TdDialogService, DIALOG_PROVIDER } from './services/dialog.service'; const TD_DIALOGS: Type[] = [ TdAlertDialogComponent, @@ -47,7 +47,7 @@ export { TdDialogService, TdDialogComponent, TdDialogTitleDirective, TD_DIALOGS, ], providers: [ - TdDialogService, + DIALOG_PROVIDER, ], entryComponents: [ TD_DIALOGS_ENTRY_COMPONENTS, diff --git a/src/platform/core/dialogs/prompt-dialog/prompt-dialog.component.html b/src/platform/core/dialogs/prompt-dialog/prompt-dialog.component.html index 49e9c882c0..e82899552d 100644 --- a/src/platform/core/dialogs/prompt-dialog/prompt-dialog.component.html +++ b/src/platform/core/dialogs/prompt-dialog/prompt-dialog.component.html @@ -7,6 +7,8 @@
) {} + ngAfterViewInit(): void { + // focus input once everything is rendered and good to go + Promise.resolve().then(() => { + (this._input.nativeElement).focus(); + }); + } + + /** + * Method executed when input is focused + * Selects all text + */ + handleInputFocus(): void { + (this._input.nativeElement).select(); + } + cancel(): void { this._dialogRef.close(undefined); } diff --git a/src/platform/core/dialogs/services/dialog.service.ts b/src/platform/core/dialogs/services/dialog.service.ts index a6a36851cf..ccb22fdb63 100644 --- a/src/platform/core/dialogs/services/dialog.service.ts +++ b/src/platform/core/dialogs/services/dialog.service.ts @@ -1,4 +1,4 @@ -import { Injectable, ViewContainerRef } from '@angular/core'; +import { Injectable, ViewContainerRef, Provider, SkipSelf, Optional } from '@angular/core'; import { MdDialog, MdDialogRef, MdDialogConfig, ComponentType } from '@angular/material'; import { TdAlertDialogComponent } from '../alert-dialog/alert-dialog.component'; @@ -142,3 +142,15 @@ export class TdDialogService { } } + +export function DIALOG_PROVIDER_FACTORY( + parent: TdDialogService, dialog: MdDialog): TdDialogService { + return parent || new TdDialogService(dialog); +} + +export const DIALOG_PROVIDER: Provider = { + // If there is already service available, use that. Otherwise, provide a new one. + provide: TdDialogService, + deps: [[new Optional(), new SkipSelf(), TdDialogService], MdDialog], + useFactory: DIALOG_PROVIDER_FACTORY, +}; diff --git a/src/platform/core/expansion-panel/README.md b/src/platform/core/expansion-panel/README.md new file mode 100644 index 0000000000..de50729009 --- /dev/null +++ b/src/platform/core/expansion-panel/README.md @@ -0,0 +1,80 @@ +# td-expansion-panel + +`td-expansion-panel` element adds expand/collapse features to your html blocks + +It also contains an optional summary to display anything in collapsed state. + +## API Summary + +Properties: + +| Name | Type | Description | +| --- | --- | --- | +| `label?` | `string` | Sets label of component header. +| `sublabel?` | `string` | Sets sublabel of component header. +| `expand?` | `boolean` | Toggles component between expand/collapse state. +| `disableRipple?` | `boolean` | Whether the ripple effect for this component is disabled. +| `expanded?` | `function` | Event emitted when component is expanded. +| `collapsed?` | `function` | Event emitted when component is collapsed. +| `toggle?` | `function` | Toggle state of component. Returns "true" if successful, else "false". +| `open?` | `function` | Opens component and sets state to expanded. Retuns "true" if successful, else "false". +| `close?` | `function` | Closes component and sets state to collapsed. Retuns "true" if successful, else "false". + +## Setup + +Import the [CovalentExpansionPanelModule] in your NgModule: + +```typescript +import { CovalentExpansionPanelModule } from '@covalent/core'; +@NgModule({ + imports: [ + CovalentExpansionPanelModule, + ... + ], + ... +}) +export class MyModule {} +``` + +## Usage + +Example for HTML usage: + +```html + + + ... add header content (overrides label and sublabel) + + + ... add label content (if not used, falls back to [label] input) + + + ... add sublabel content (if not used, falls back to [sublabel] input) + + + ... add summary that will be shown when expansion-panel is "collapsed". + + ... add content that + +``` + +# td-expansion-panel-group + +`td-expansion-panel-group` is used to group expansion panel components. + +It adds margin between them when expanded following the material spec. + +## Usage + +Example for HTML usage: + +```html + + + ..content + + + ..content + + +``` diff --git a/src/platform/core/expansion-panel/_expansion-panel-theme.scss b/src/platform/core/expansion-panel/_expansion-panel-theme.scss index 3ef2787967..057baa4c9f 100644 --- a/src/platform/core/expansion-panel/_expansion-panel-theme.scss +++ b/src/platform/core/expansion-panel/_expansion-panel-theme.scss @@ -7,23 +7,29 @@ $warn: map-get($theme, warn); $foreground: map-get($theme, foreground); $background: map-get($theme, background); - // panel - td-expansion-panel { - @include mat-elevation(1); - background-color: mat-color($background, card); - &:not(:last-of-type) { - & .td-expanded { - margin-bottom: $margin; + + .td-expansion-panel-group { + .td-expansion-panel { + transition: 120ms ease-in; + &:not(:last-of-type) { + &.td-expanded { + margin-bottom: $margin; + } } - } - &:not(:first-of-type) { - & .td-expanded { - margin-top: $margin; + &:not(:first-of-type) { + &.td-expanded { + margin-top: $margin; + } } } + } + + .td-expansion-panel { + @include mat-elevation(1); + background-color: mat-color($background, card); .td-expansion-panel-header { - &:focus, - &:hover { + &:focus:not(.mat-disabled), + &:hover:not(.mat-disabled) { background: mat-color($background, 'hover'); } .td-expansion-panel-header-content { diff --git a/src/platform/core/expansion-panel/expansion-panel-group.component.html b/src/platform/core/expansion-panel/expansion-panel-group.component.html new file mode 100644 index 0000000000..95a0b70bdc --- /dev/null +++ b/src/platform/core/expansion-panel/expansion-panel-group.component.html @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/platform/core/expansion-panel/expansion-panel-group.component.scss b/src/platform/core/expansion-panel/expansion-panel-group.component.scss new file mode 100644 index 0000000000..e69de29bb2 diff --git a/src/platform/core/expansion-panel/expansion-panel-group.component.ts b/src/platform/core/expansion-panel/expansion-panel-group.component.ts new file mode 100644 index 0000000000..fbef2d651d --- /dev/null +++ b/src/platform/core/expansion-panel/expansion-panel-group.component.ts @@ -0,0 +1,15 @@ +import { Component, Renderer2, ElementRef } from '@angular/core'; + +@Component({ + selector: 'td-expansion-panel-group', + styleUrls: ['./expansion-panel-group.component.scss' ], + templateUrl: './expansion-panel-group.component.html', +}) +export class TdExpansionPanelGroupComponent { + + constructor(private _renderer: Renderer2, + private _elementRef: ElementRef) { + this._renderer.addClass(this._elementRef.nativeElement, 'td-expansion-panel-group'); + } + +} diff --git a/src/platform/core/expansion-panel/expansion-panel.component.html b/src/platform/core/expansion-panel/expansion-panel.component.html index 4939e8b2fa..6d48433d0b 100644 --- a/src/platform/core/expansion-panel/expansion-panel.component.html +++ b/src/platform/core/expansion-panel/expansion-panel.component.html @@ -1,38 +1,35 @@ -
-
+ +
- -
-
- - {{label}} -
-
- - {{sublabel}} -
- - keyboard_arrow_down - keyboard_arrow_up + *ngIf="!expansionPanelHeader" + layout="row" + layout-align="start center" + flex> +
+ + {{label}}
+
+ + {{sublabel}} +
+ + keyboard_arrow_down + keyboard_arrow_up
-
- -
-
- -
-
\ No newline at end of file +
+
+ +
+
+ +
diff --git a/src/platform/core/expansion-panel/expansion-panel.component.scss b/src/platform/core/expansion-panel/expansion-panel.component.scss index 010de28b91..717659b151 100644 --- a/src/platform/core/expansion-panel/expansion-panel.component.scss +++ b/src/platform/core/expansion-panel/expansion-panel.component.scss @@ -1,22 +1,15 @@ :host { display: block; - .td-expansion-panel { - transition: 400ms all ease; - .td-expansion-panel-header { - position: relative; - outline: none; - &:focus, - &:hover { - cursor: pointer; - } - &.mat-disabled { - background: none; - cursor: auto; - } - .td-expansion-panel-header-content { - height: 48px; - padding: 0 16px; - } + .td-expansion-panel-header { + position: relative; + outline: none; + &:focus:not(.mat-disabled), + &:hover:not(.mat-disabled) { + cursor: pointer; + } + .td-expansion-panel-header-content { + height: 48px; + padding: 0 16px; } } } diff --git a/src/platform/core/expansion-panel/expansion-panel.component.spec.ts b/src/platform/core/expansion-panel/expansion-panel.component.spec.ts index 980f1b45d6..0dff991a77 100644 --- a/src/platform/core/expansion-panel/expansion-panel.component.spec.ts +++ b/src/platform/core/expansion-panel/expansion-panel.component.spec.ts @@ -5,7 +5,7 @@ import { ComponentFixture, } from '@angular/core/testing'; import { Component } from '@angular/core'; -import { BrowserAnimationsModule } from '@angular/platform-browser/animations'; +import { NoopAnimationsModule } from '@angular/platform-browser/animations'; import { CovalentExpansionPanelModule, TdExpansionPanelComponent } from './expansion-panel.module'; import { By } from '@angular/platform-browser'; @@ -18,7 +18,7 @@ describe('Component: ExpansionPanel', () => { TdExpansionPanelSummaryTestComponent, ], imports: [ - BrowserAnimationsModule, + NoopAnimationsModule, CovalentExpansionPanelModule, ], }); diff --git a/src/platform/core/expansion-panel/expansion-panel.component.ts b/src/platform/core/expansion-panel/expansion-panel.component.ts index a28b7ab951..ef91ea6c18 100644 --- a/src/platform/core/expansion-panel/expansion-panel.component.ts +++ b/src/platform/core/expansion-panel/expansion-panel.component.ts @@ -1,4 +1,5 @@ -import { Component, Directive, Input, Output, TemplateRef, ViewContainerRef, ContentChild } from '@angular/core'; +import { Component, Directive, Input, Output, TemplateRef, ViewContainerRef, ContentChild, + ElementRef, Renderer2 } from '@angular/core'; import { EventEmitter } from '@angular/core'; import { TemplatePortalDirective } from '@angular/material'; @@ -47,6 +48,7 @@ export class TdExpansionPanelSummaryComponent {} }) export class TdExpansionPanelComponent { + private _disableRipple: boolean = false; private _expand: boolean = false; private _disabled: boolean = false; @@ -67,13 +69,25 @@ export class TdExpansionPanelComponent { */ @Input() sublabel: string; + /** + * disableRipple?: string + * Whether the ripple effect for this component is disabled. + */ + @Input('disableRipple') + set disableRipple(disableRipple: boolean) { + this._disableRipple = disableRipple !== '' ? (disableRipple === 'true' || disableRipple === true) : true; + } + get disableRipple(): boolean { + return this._disableRipple; + } + /** * expand?: boolean * Toggles [TdExpansionPanelComponent] between expand/collapse. */ @Input('expand') set expand(expand: boolean) { - this._setExpand(expand); + this._setExpand(expand === 'true' || expand === true); } get expand(): boolean { return this._expand; @@ -107,6 +121,11 @@ export class TdExpansionPanelComponent { */ @Output() collapsed: EventEmitter = new EventEmitter(); + constructor(private _renderer: Renderer2, + private _elementRef: ElementRef) { + this._renderer.addClass(this._elementRef.nativeElement, 'td-expansion-panel'); + } + /** * Method executed when [TdExpansionPanelComponent] is clicked. */ @@ -149,8 +168,10 @@ export class TdExpansionPanelComponent { if (this._expand !== newExpand) { this._expand = newExpand; if (newExpand) { + this._renderer.addClass(this._elementRef.nativeElement, 'td-expanded'); this._onExpanded(); } else { + this._renderer.removeClass(this._elementRef.nativeElement, 'td-expanded'); this._onCollapsed(); } return true; diff --git a/src/platform/core/expansion-panel/expansion-panel.module.ts b/src/platform/core/expansion-panel/expansion-panel.module.ts index 508675cffe..a3713c3445 100644 --- a/src/platform/core/expansion-panel/expansion-panel.module.ts +++ b/src/platform/core/expansion-panel/expansion-panel.module.ts @@ -6,8 +6,10 @@ import { MdRippleModule, MdIconModule, PortalModule } from '@angular/material'; import { TdExpansionPanelComponent, TdExpansionPanelHeaderDirective, TdExpansionPanelLabelDirective, TdExpansionPanelSublabelDirective, TdExpansionPanelSummaryComponent } from './expansion-panel.component'; +import { TdExpansionPanelGroupComponent } from './expansion-panel-group.component'; const TD_EXPANSION_PANEL: Type[] = [ + TdExpansionPanelGroupComponent, TdExpansionPanelComponent, TdExpansionPanelHeaderDirective, TdExpansionPanelLabelDirective, @@ -16,6 +18,7 @@ const TD_EXPANSION_PANEL: Type[] = [ ]; export { TdExpansionPanelComponent } from './expansion-panel.component'; +export { TdExpansionPanelGroupComponent } from './expansion-panel-group.component'; @NgModule({ imports: [ diff --git a/src/platform/core/json-formatter/json-formatter.component.spec.ts b/src/platform/core/json-formatter/json-formatter.component.spec.ts index 33ec2f5444..d855b624dd 100644 --- a/src/platform/core/json-formatter/json-formatter.component.spec.ts +++ b/src/platform/core/json-formatter/json-formatter.component.spec.ts @@ -5,7 +5,7 @@ import { ComponentFixture, } from '@angular/core/testing'; import { Component } from '@angular/core'; -import { BrowserAnimationsModule } from '@angular/platform-browser/animations'; +import { NoopAnimationsModule } from '@angular/platform-browser/animations'; import { CovalentJsonFormatterModule, TdJsonFormatterComponent } from './json-formatter.module'; import { By } from '@angular/platform-browser'; @@ -17,7 +17,7 @@ describe('Component: JsonFormatter', () => { TdJsonFormatterBasicTestComponent, ], imports: [ - BrowserAnimationsModule, + NoopAnimationsModule, CovalentJsonFormatterModule, ], }); diff --git a/src/platform/core/layout/README.md b/src/platform/core/layout/README.md index da68042cbe..1f47399cdb 100644 --- a/src/platform/core/layout/README.md +++ b/src/platform/core/layout/README.md @@ -3,6 +3,30 @@ `` is a blank main sidenav component that gets hooked as parent of all the other layouts. (triggered by their menu buttons) +## API Summary + +| Name | Type | Description | +| --- | --- | --- | +| mode | 'over', 'side' or 'push' | The mode or styling of the sidenav. Defaults to 'over'. +| opened | boolean | Whether or not the sidenav is opened. Use this binding to open/close the sidenav. Defaults to 'false'. +| sidenavWidth | string | Sets the 'width' of the sidenav in either 'px' or '%' ('%' is not well supported yet as stated in the layout docs). Defaults to '320px'. + + +## Usage + +`[td-sidenav-content]` is used to include content in the main sidenav. + +Example for Main Layout: + +```html + +
+ .. more sidenav content +
+ .. main content +
+``` + ## Installation This component can be installed as npm package. diff --git a/src/platform/core/layout/_layout-theme.scss b/src/platform/core/layout/_layout-theme.scss index 36801afc9f..d70de3f6a2 100644 --- a/src/platform/core/layout/_layout-theme.scss +++ b/src/platform/core/layout/_layout-theme.scss @@ -2,6 +2,9 @@ @import '../common/styles/theme-functions'; @mixin td-layout-theme($theme) { + $primary: map-get($theme, primary); + $accent: map-get($theme, accent); + $warn: map-get($theme, warn); $background: map-get($theme, background); $foreground: map-get($theme, foreground); @@ -20,9 +23,30 @@ z-index: 1; } } + .mat-sidenav-side.td-layout-sidenav { + @include mat-elevation(2); + } .td-layout-footer { background: mat-color($background, app-bar); color: mat-color($foreground, text); @include mat-elevation(2); + &.mat-primary { + background: mat-color($primary); + &, md-icon { + color: mat-color($primary, default-contrast); + } + } + &.mat-accent { + background: mat-color($accent); + &, md-icon { + color: mat-color($accent, default-contrast); + } + } + &.mat-warn { + background: mat-color($warn); + &, md-icon { + color: mat-color($warn, default-contrast); + } + } } } \ No newline at end of file diff --git a/src/platform/core/layout/layout-card-over/README.md b/src/platform/core/layout/layout-card-over/README.md index 2618fd841b..3dbd2546e6 100644 --- a/src/platform/core/layout/layout-card-over/README.md +++ b/src/platform/core/layout/layout-card-over/README.md @@ -22,14 +22,14 @@ Example for Card Over Layout / Nav Layout combo: ```html - - + + .. main content
.. content after card
- + // color is optional ... main footer content
diff --git a/src/platform/core/layout/layout-footer/layout-footer.component.html b/src/platform/core/layout/layout-footer/layout-footer.component.html index ca5f777d98..6dbc743063 100644 --- a/src/platform/core/layout/layout-footer/layout-footer.component.html +++ b/src/platform/core/layout/layout-footer/layout-footer.component.html @@ -1,3 +1 @@ - + diff --git a/src/platform/core/layout/layout-footer/layout-footer.component.scss b/src/platform/core/layout/layout-footer/layout-footer.component.scss index 9a14b0c4d8..3864095759 100644 --- a/src/platform/core/layout/layout-footer/layout-footer.component.scss +++ b/src/platform/core/layout/layout-footer/layout-footer.component.scss @@ -1,6 +1,4 @@ :host { display: block; -} -.td-layout-footer { padding: 10px 16px; } diff --git a/src/platform/core/layout/layout-footer/layout-footer.component.ts b/src/platform/core/layout/layout-footer/layout-footer.component.ts index a74c928fdc..347716a2b9 100644 --- a/src/platform/core/layout/layout-footer/layout-footer.component.ts +++ b/src/platform/core/layout/layout-footer/layout-footer.component.ts @@ -1,4 +1,4 @@ -import { Component } from '@angular/core'; +import { Component, Input, Renderer2, ElementRef } from '@angular/core'; @Component({ /* tslint:disable-next-line */ @@ -8,4 +8,28 @@ import { Component } from '@angular/core'; }) export class TdLayoutFooterComponent { + private _color: 'primary' | 'accent' | 'warn'; + + /** + * color?: string + * + * Optional color option: primary | accent | warn. + */ + @Input('color') + set color(color: 'primary' | 'accent' | 'warn') { + if (color) { + this._renderer.removeClass(this._elementRef.nativeElement, 'mat-' + this._color); + this._color = color; + this._renderer.addClass(this._elementRef.nativeElement, 'mat-' + this._color); + } + } + get color(): 'primary' | 'accent' | 'warn' { + return this._color; + } + + constructor(private _renderer: Renderer2, + private _elementRef: ElementRef) { + this._renderer.addClass(this._elementRef.nativeElement, 'td-layout-footer'); + } + } diff --git a/src/platform/core/layout/layout-manage-list/README.md b/src/platform/core/layout/layout-manage-list/README.md index ad051f4b56..f506bcccc8 100644 --- a/src/platform/core/layout/layout-manage-list/README.md +++ b/src/platform/core/layout/layout-manage-list/README.md @@ -23,7 +23,7 @@ Example for Manage List Layout / Nav Layout combo: ```html - +
.. main toolbar content
@@ -42,7 +42,7 @@ Example for Manage List Layout / Nav Layout combo: ... sub footer content - + // color is optional ... main footer content
diff --git a/src/platform/core/layout/layout-manage-list/layout-manage-list.component.html b/src/platform/core/layout/layout-manage-list/layout-manage-list.component.html index 1e6d65c54f..8214ccf4f7 100644 --- a/src/platform/core/layout/layout-manage-list/layout-manage-list.component.html +++ b/src/platform/core/layout/layout-manage-list/layout-manage-list.component.html @@ -9,7 +9,7 @@ layout-fill class="md-whiteframe-z1"> -
+
@@ -20,7 +20,7 @@ -
+
diff --git a/src/platform/core/layout/layout-manage-list/layout-manage-list.component.ts b/src/platform/core/layout/layout-manage-list/layout-manage-list.component.ts index eb6acf79c8..6fd020b984 100644 --- a/src/platform/core/layout/layout-manage-list/layout-manage-list.component.ts +++ b/src/platform/core/layout/layout-manage-list/layout-manage-list.component.ts @@ -56,7 +56,7 @@ export class TdLayoutManageListComponent { * Proxy toggle method to access sidenav from outside (from td-layout template). */ public toggle(): Promise { - return this._sideNav.toggle(); + return this._sideNav.toggle(!this._sideNav.opened); } /** diff --git a/src/platform/core/layout/layout-nav-list/README.md b/src/platform/core/layout/layout-nav-list/README.md index 57a528c711..6465597cb0 100644 --- a/src/platform/core/layout/layout-nav-list/README.md +++ b/src/platform/core/layout/layout-nav-list/README.md @@ -32,7 +32,7 @@ Example for Nav List Layout: ```html - +
... left toolbar content
@@ -46,7 +46,7 @@ Example for Nav List Layout: ... sub footer content - + // color is optional ... main footer content
diff --git a/src/platform/core/layout/layout-nav-list/layout-nav-list.component.html b/src/platform/core/layout/layout-nav-list/layout-nav-list.component.html index 18e52bd6ce..70db922e92 100644 --- a/src/platform/core/layout/layout-nav-list/layout-nav-list.component.html +++ b/src/platform/core/layout/layout-nav-list/layout-nav-list.component.html @@ -25,7 +25,7 @@ -
+
@@ -36,7 +36,7 @@ -
+
diff --git a/src/platform/core/layout/layout-nav-list/layout-nav-list.component.ts b/src/platform/core/layout/layout-nav-list/layout-nav-list.component.ts index 9f973c9f43..9b5dfaaf6f 100644 --- a/src/platform/core/layout/layout-nav-list/layout-nav-list.component.ts +++ b/src/platform/core/layout/layout-nav-list/layout-nav-list.component.ts @@ -117,7 +117,7 @@ export class TdLayoutNavListComponent { * Proxy toggle method to access sidenav from outside (from td-layout template). */ public toggle(): Promise { - return this._sideNav.toggle(); + return this._sideNav.toggle(!this._sideNav.opened); } /** @@ -138,7 +138,7 @@ export class TdLayoutNavListComponent { * If main sidenav is available, it will open the sidenav of the parent [TdLayoutComponent]. */ openMainSidenav(): void { - this._layout.open(); + this._layout.toggle(); } } diff --git a/src/platform/core/layout/layout-nav/README.md b/src/platform/core/layout/layout-nav/README.md index 5657f34b4e..45f65d4fb4 100644 --- a/src/platform/core/layout/layout-nav/README.md +++ b/src/platform/core/layout/layout-nav/README.md @@ -23,12 +23,12 @@ Example for Nav Layout: ```html - +
.. main toolbar content
... main content - + // color is optional ... main footer content
diff --git a/src/platform/core/layout/layout-nav/layout-nav.component.html b/src/platform/core/layout/layout-nav/layout-nav.component.html index 31dd9316e4..9e3a695ae5 100644 --- a/src/platform/core/layout/layout-nav/layout-nav.component.html +++ b/src/platform/core/layout/layout-nav/layout-nav.component.html @@ -14,7 +14,7 @@ -
+
diff --git a/src/platform/core/layout/layout-nav/layout-nav.component.ts b/src/platform/core/layout/layout-nav/layout-nav.component.ts index 5039c2d07a..502fa14c88 100644 --- a/src/platform/core/layout/layout-nav/layout-nav.component.ts +++ b/src/platform/core/layout/layout-nav/layout-nav.component.ts @@ -73,6 +73,6 @@ export class TdLayoutNavComponent { * If main sidenav is available, it will open the sidenav of the parent [TdLayoutComponent]. */ openMainSidenav(): void { - this._layout.open(); + this._layout.toggle(); } } diff --git a/src/platform/core/layout/layout.component.html b/src/platform/core/layout/layout.component.html index 34013ac955..a2b7160e5d 100644 --- a/src/platform/core/layout/layout.component.html +++ b/src/platform/core/layout/layout.component.html @@ -1,5 +1,10 @@ - + diff --git a/src/platform/core/layout/layout.component.ts b/src/platform/core/layout/layout.component.ts index bbbc7c906d..8f2e30d514 100644 --- a/src/platform/core/layout/layout.component.ts +++ b/src/platform/core/layout/layout.component.ts @@ -11,11 +11,52 @@ export class TdLayoutComponent { @ViewChild(MdSidenav) sidenav: MdSidenav; + /** + * mode?: 'side', 'push' or 'over' + * + * The mode or styling of the sidenav. + * Defaults to "over". + * See "MdSidenav" documentation for more info. + * + * https://github.com/angular/material2/tree/master/src/lib/sidenav + */ + @Input('mode') mode: 'side' | 'push' | 'over' = 'over'; + + /** + * opened?: boolean + * + * Whether or not the sidenav is opened. Use this binding to open/close the sidenav. + * Defaults to "false". + * + * See "MdSidenav" documentation for more info. + * + * https://github.com/angular/material2/tree/master/src/lib/sidenav + */ + @Input('opened') opened: boolean = false; + + /** + * sidenavWidth?: string + * + * Sets the "width" of the sidenav in either "px" or "%" ("%" is not well supported yet as stated in the layout docs) + * Defaults to "320px". + * + * https://github.com/angular/material2/tree/master/src/lib/sidenav + */ + @Input('sidenavWidth') sidenavWidth: string = '320px'; + + /** + * Checks if `ESC` should close the sidenav + * Should only close it for `push` and `over` modes + */ + get disableClose(): boolean { + return this.mode === 'side'; + } + /** * Proxy toggle method to access sidenav from outside (from td-layout template). */ public toggle(): Promise { - return this.sidenav.toggle(); + return this.sidenav.toggle(!this.sidenav.opened); } /** diff --git a/src/platform/core/layout/layout.module.ts b/src/platform/core/layout/layout.module.ts index d6e30421f6..8366afa0d3 100644 --- a/src/platform/core/layout/layout.module.ts +++ b/src/platform/core/layout/layout.module.ts @@ -2,7 +2,7 @@ import { Type } from '@angular/core'; import { NgModule, ModuleWithProviders } from '@angular/core'; import { CommonModule } from '@angular/common'; -import { MdSidenavModule, MdToolbarModule, MdButtonModule, MdIconModule, MdCardModule, MdListModule } from '@angular/material'; +import { MdSidenavModule, MdToolbarModule, MdButtonModule, MdIconModule, MdCardModule, MdListModule, ScrollDispatchModule } from '@angular/material'; import { TdLayoutComponent } from './layout.component'; import { TdLayoutNavComponent } from './layout-nav/layout-nav.component'; @@ -32,6 +32,7 @@ export { TdLayoutComponent, TdLayoutNavComponent, TdLayoutNavListComponent, @NgModule({ imports: [ CommonModule, + ScrollDispatchModule, MdSidenavModule, MdToolbarModule, MdButtonModule, diff --git a/src/platform/core/loading/directives/loading.directive.spec.ts b/src/platform/core/loading/directives/loading.directive.spec.ts index 507501e8ab..687439131a 100644 --- a/src/platform/core/loading/directives/loading.directive.spec.ts +++ b/src/platform/core/loading/directives/loading.directive.spec.ts @@ -7,7 +7,7 @@ import { import { Component } from '@angular/core'; import { Observable } from 'rxjs/Observable'; import { Subject } from 'rxjs/Subject'; -import { BrowserAnimationsModule } from '@angular/platform-browser/animations'; +import { NoopAnimationsModule } from '@angular/platform-browser/animations'; import { By } from '@angular/platform-browser'; import { CovalentLoadingModule, LoadingMode, LoadingType, LoadingStrategy, TdLoadingService } from '../loading.module'; @@ -24,7 +24,7 @@ describe('Directive: Loading', () => { TdLoadingBooleanTemplateUntilTestComponent, ], imports: [ - BrowserAnimationsModule, + NoopAnimationsModule, CovalentLoadingModule, ], }); @@ -40,7 +40,6 @@ describe('Directive: Loading', () => { loadingService.register('name'); fixture.detectChanges(); fixture.whenStable().then(() => { - fixture.detectChanges(); expect(fixture.debugElement.query(By.css('td-loading'))).toBeTruthy(); expect(fixture.debugElement.query(By.css('md-progress-spinner'))).toBeTruthy(); expect(fixture.debugElement.query(By.css('.mat-primary'))).toBeTruthy(); @@ -50,13 +49,9 @@ describe('Directive: Loading', () => { loadingService.resolve('name'); fixture.detectChanges(); fixture.whenStable().then(() => { - fixture.detectChanges(); - fixture.whenStable().then(() => { - fixture.detectChanges(); - expect(fixture.debugElement.query(By.css('.content'))).toBeTruthy(); - expect(fixture.debugElement.query(By.css('td-loading'))).toBeFalsy(); - done(); - }); + expect(fixture.debugElement.query(By.css('.content'))).toBeTruthy(); + expect(fixture.debugElement.query(By.css('td-loading'))).toBeFalsy(); + done(); }); }); })(); @@ -75,7 +70,6 @@ describe('Directive: Loading', () => { loadingService.register('name'); fixture.detectChanges(); fixture.whenStable().then(() => { - fixture.detectChanges(); expect(fixture.debugElement.query(By.css('td-loading'))).toBeTruthy(); expect(fixture.debugElement.query(By.css('md-progress-bar'))).toBeTruthy(); expect(fixture.debugElement.query(By.css('.mat-accent'))).toBeTruthy(); @@ -85,13 +79,9 @@ describe('Directive: Loading', () => { loadingService.resolve('name'); fixture.detectChanges(); fixture.whenStable().then(() => { - fixture.detectChanges(); - fixture.whenStable().then(() => { - fixture.detectChanges(); - expect(fixture.debugElement.query(By.css('.content'))).toBeTruthy(); - expect(fixture.debugElement.query(By.css('td-loading'))).toBeFalsy(); - done(); - }); + expect(fixture.debugElement.query(By.css('.content'))).toBeTruthy(); + expect(fixture.debugElement.query(By.css('td-loading'))).toBeFalsy(); + done(); }); }); })(); @@ -109,60 +99,34 @@ describe('Directive: Loading', () => { expect(fixture.debugElement.query(By.css('.content'))).toBeTruthy(); expect(fixture.debugElement.query(By.css('td-loading'))).toBeTruthy(); expect((fixture.debugElement.query(By.css('.td-loading')).nativeElement) - .style.opacity).toBe(''); + .style.opacity).toBe('0'); expect((fixture.debugElement.query(By.css('.td-loading')).nativeElement) - .style.display).toBe(''); + .style.display).toBe('none'); + loadingService.register('name'); fixture.detectChanges(); fixture.whenStable().then(() => { + expect(fixture.debugElement.query(By.css('td-loading'))).toBeTruthy(); + expect(fixture.debugElement.query(By.css('md-progress-spinner'))).toBeTruthy(); + expect(fixture.debugElement.query(By.css('.mat-warn'))).toBeTruthy(); + expect(fixture.debugElement.query(By.css('.td-overlay'))).toBeTruthy(); + expect(fixture.debugElement.query(By.css('.td-fullscreen'))).toBeFalsy(); + expect(fixture.debugElement.query(By.css('.content'))).toBeTruthy(); fixture.detectChanges(); fixture.whenStable().then(() => { - fixture.detectChanges(); expect((fixture.debugElement.query(By.css('.td-loading')).nativeElement) - .style.opacity).toBe('0'); + .style.opacity).toBe(''); expect((fixture.debugElement.query(By.css('.td-loading')).nativeElement) - .style.display).toBe('none'); - loadingService.register('name'); + .style.display).toBe(''); + loadingService.resolve('name'); fixture.detectChanges(); fixture.whenStable().then(() => { - fixture.detectChanges(); - expect(fixture.debugElement.query(By.css('td-loading'))).toBeTruthy(); - expect(fixture.debugElement.query(By.css('md-progress-spinner'))).toBeTruthy(); - expect(fixture.debugElement.query(By.css('.mat-warn'))).toBeTruthy(); - expect(fixture.debugElement.query(By.css('.td-overlay'))).toBeTruthy(); - expect(fixture.debugElement.query(By.css('.td-fullscreen'))).toBeFalsy(); + expect((fixture.debugElement.query(By.css('.td-loading')).nativeElement) + .style.opacity).toBe('0'); + expect((fixture.debugElement.query(By.css('.td-loading')).nativeElement) + .style.display).toBe('none'); expect(fixture.debugElement.query(By.css('.content'))).toBeTruthy(); - fixture.whenStable().then(() => { - fixture.detectChanges(); - setTimeout(() => { - fixture.whenStable().then(() => { - fixture.detectChanges(); - expect((fixture.debugElement.query(By.css('.td-loading')).nativeElement) - .style.opacity).toBe(''); - expect((fixture.debugElement.query(By.css('.td-loading')).nativeElement) - .style.display).toBe(''); - loadingService.resolve('name'); - fixture.detectChanges(); - fixture.whenStable().then(() => { - fixture.detectChanges(); - setTimeout(() => { - fixture.whenStable().then(() => { - fixture.detectChanges(); - fixture.whenStable().then(() => { - fixture.detectChanges(); - expect((fixture.debugElement.query(By.css('.td-loading')).nativeElement) - .style.opacity).toBe('0'); - expect((fixture.debugElement.query(By.css('.td-loading')).nativeElement) - .style.display).toBe('none'); - expect(fixture.debugElement.query(By.css('.content'))).toBeTruthy(); - expect(fixture.debugElement.query(By.css('td-loading'))).toBeTruthy(); - done(); - }); - }); - }, 200); - }); - }); - }, 200); - }); + expect(fixture.debugElement.query(By.css('td-loading'))).toBeTruthy(); + done(); }); }); }); @@ -182,71 +146,50 @@ describe('Directive: Loading', () => { expect(fixture.debugElement.query(By.css('.content'))).toBeTruthy(); expect(fixture.debugElement.query(By.css('td-loading'))).toBeTruthy(); expect((fixture.debugElement.query(By.css('.td-loading')).nativeElement) - .style.opacity).toBe(''); + .style.opacity).toBe('0'); expect((fixture.debugElement.query(By.css('.td-loading')).nativeElement) - .style.display).toBe(''); + .style.display).toBe('none'); + loadingService.register('name'); fixture.detectChanges(); fixture.whenStable().then(() => { + expect(fixture.debugElement.query(By.css('td-loading'))).toBeTruthy(); + expect(fixture.debugElement.query(By.css('md-progress-bar'))).toBeTruthy(); + expect(fixture.debugElement.query(By.css('.mat-primary'))).toBeTruthy(); + expect(fixture.debugElement.query(By.css('.td-overlay'))).toBeTruthy(); + expect(fixture.debugElement.query(By.css('.td-fullscreen'))).toBeFalsy(); + expect(fixture.debugElement.query(By.css('.content'))).toBeTruthy(); fixture.detectChanges(); fixture.whenStable().then(() => { - fixture.detectChanges(); expect((fixture.debugElement.query(By.css('.td-loading')).nativeElement) - .style.opacity).toBe('0'); + .style.opacity).toBe(''); expect((fixture.debugElement.query(By.css('.td-loading')).nativeElement) - .style.display).toBe('none'); - loadingService.register('name'); + .style.display).toBe(''); + + loadingService.setValue('name', 20); fixture.detectChanges(); - fixture.whenStable().then(() => { - fixture.detectChanges(); - expect(fixture.debugElement.query(By.css('td-loading'))).toBeTruthy(); - expect(fixture.debugElement.query(By.css('md-progress-bar'))).toBeTruthy(); - expect(fixture.debugElement.query(By.css('.mat-primary'))).toBeTruthy(); - expect(fixture.debugElement.query(By.css('.td-overlay'))).toBeTruthy(); - expect(fixture.debugElement.query(By.css('.td-fullscreen'))).toBeFalsy(); - expect(fixture.debugElement.query(By.css('.content'))).toBeTruthy(); - fixture.whenStable().then(() => { - fixture.detectChanges(); - setTimeout(() => { - fixture.whenStable().then(() => { - fixture.detectChanges(); - expect((fixture.debugElement.query(By.css('.td-loading')).nativeElement) - .style.opacity).toBe(''); - expect((fixture.debugElement.query(By.css('.td-loading')).nativeElement) - .style.display).toBe(''); - loadingService.setValue('name', 20); - fixture.detectChanges(); - expect(fixture.debugElement.query(By.css('md-progress-bar')).componentInstance._primaryTransform()) - .toEqual({transform: 'scaleX(0.2)'}); + expect(fixture.debugElement.query(By.css('md-progress-bar')).componentInstance._primaryTransform()) + .toEqual({transform: 'scaleX(0.2)'}); + + loadingService.setValue('name', 50); + fixture.detectChanges(); + expect(fixture.debugElement.query(By.css('md-progress-bar')).componentInstance._primaryTransform()) + .toEqual({transform: 'scaleX(0.5)'}); - loadingService.setValue('name', 50); - fixture.detectChanges(); - expect(fixture.debugElement.query(By.css('md-progress-bar')).componentInstance._primaryTransform()) - .toEqual({transform: 'scaleX(0.5)'}); + loadingService.setValue('name', 100); + fixture.detectChanges(); + expect(fixture.debugElement.query(By.css('md-progress-bar')).componentInstance._primaryTransform()) + .toEqual({transform: 'scaleX(1)'}); - loadingService.setValue('name', 100); - fixture.detectChanges(); - expect(fixture.debugElement.query(By.css('md-progress-bar')).componentInstance._primaryTransform()) - .toEqual({transform: 'scaleX(1)'}); - loadingService.resolve('name'); - fixture.detectChanges(); - fixture.whenStable().then(() => { - fixture.detectChanges(); - setTimeout(() => { - fixture.whenStable().then(() => { - fixture.detectChanges(); - expect((fixture.debugElement.query(By.css('.td-loading')).nativeElement) - .style.opacity).toBe('0'); - expect((fixture.debugElement.query(By.css('.td-loading')).nativeElement) - .style.display).toBe('none'); - expect(fixture.debugElement.query(By.css('.content'))).toBeTruthy(); - expect(fixture.debugElement.query(By.css('td-loading'))).toBeTruthy(); - done(); - }); - }, 200); - }); - }); - }, 200); - }); + loadingService.resolve('name'); + fixture.detectChanges(); + fixture.whenStable().then(() => { + expect((fixture.debugElement.query(By.css('.td-loading')).nativeElement) + .style.opacity).toBe('0'); + expect((fixture.debugElement.query(By.css('.td-loading')).nativeElement) + .style.display).toBe('none'); + expect(fixture.debugElement.query(By.css('.content'))).toBeTruthy(); + expect(fixture.debugElement.query(By.css('td-loading'))).toBeTruthy(); + done(); }); }); }); @@ -293,17 +236,10 @@ describe('Directive: Loading', () => { component.sendResult('success'); fixture.detectChanges(); fixture.whenStable().then(() => { - fixture.detectChanges(); - setTimeout(() => { - fixture.detectChanges(); - fixture.whenStable().then(() => { - expect(fixture.debugElement.query(By.css('.content'))).toBeTruthy(); - expect(fixture.debugElement.query(By.css('td-loading'))).toBeFalsy(); - expect((fixture.debugElement.query(By.css('.content')).nativeElement).textContent).toContain('success'); - fixture.detectChanges(); - done(); - }); - }, 200); + expect(fixture.debugElement.query(By.css('.content'))).toBeTruthy(); + expect(fixture.debugElement.query(By.css('td-loading'))).toBeFalsy(); + expect((fixture.debugElement.query(By.css('.content')).nativeElement).textContent).toContain('success'); + done(); }); }); })(); @@ -327,17 +263,10 @@ describe('Directive: Loading', () => { component.sendError('error'); fixture.detectChanges(); fixture.whenStable().then(() => { - fixture.detectChanges(); - setTimeout(() => { - fixture.detectChanges(); - fixture.whenStable().then(() => { - expect(fixture.debugElement.query(By.css('.content'))).toBeTruthy(); - expect(fixture.debugElement.query(By.css('td-loading'))).toBeFalsy(); - expect((fixture.debugElement.query(By.css('.content')).nativeElement).textContent.trim()).toBeFalsy(); - fixture.detectChanges(); - done(); - }); - }, 200); + expect(fixture.debugElement.query(By.css('.content'))).toBeTruthy(); + expect(fixture.debugElement.query(By.css('td-loading'))).toBeFalsy(); + expect((fixture.debugElement.query(By.css('.content')).nativeElement).textContent.trim()).toBeFalsy(); + done(); }); }); })(); @@ -361,16 +290,9 @@ describe('Directive: Loading', () => { component.loading = false; fixture.detectChanges(); fixture.whenStable().then(() => { - fixture.detectChanges(); - setTimeout(() => { - fixture.detectChanges(); - fixture.whenStable().then(() => { - expect(fixture.debugElement.query(By.css('.content'))).toBeTruthy(); - expect(fixture.debugElement.query(By.css('td-loading'))).toBeFalsy(); - fixture.detectChanges(); - done(); - }); - }, 200); + expect(fixture.debugElement.query(By.css('.content'))).toBeTruthy(); + expect(fixture.debugElement.query(By.css('td-loading'))).toBeFalsy(); + done(); }); }); })(); diff --git a/src/platform/core/loading/loading.component.ts b/src/platform/core/loading/loading.component.ts index 1cd05f8820..9e71c03976 100644 --- a/src/platform/core/loading/loading.component.ts +++ b/src/platform/core/loading/loading.component.ts @@ -154,25 +154,19 @@ export class TdLoadingComponent { this.value = 0; // Check for changes for `OnPush` change detection this._changeDetectorRef.markForCheck(); - setTimeout(() => { - this._animationOut.next(undefined); - }); + this._animationOut.next(undefined); } /** * Starts in animation and returns an observable for completition event. */ startInAnimation(): Observable { - setTimeout(() => { - this.animation = true; - // Check for changes for `OnPush` change detection - this._changeDetectorRef.markForCheck(); - }); /* need to switch back to the selected mode, so we have saved it in another variable * and then recover it. (issue with protractor) */ this._mode = this._defaultMode; // Check for changes for `OnPush` change detection + this.animation = true; this._changeDetectorRef.markForCheck(); return this._animationIn.asObservable(); } diff --git a/src/platform/core/loading/loading.module.ts b/src/platform/core/loading/loading.module.ts index 9224233f33..5149631a4b 100644 --- a/src/platform/core/loading/loading.module.ts +++ b/src/platform/core/loading/loading.module.ts @@ -4,8 +4,8 @@ import { NgModule, ModuleWithProviders } from '@angular/core'; import { CommonModule } from '@angular/common'; import { MdProgressBarModule, MdProgressSpinnerModule, OverlayModule, PortalModule } from '@angular/material'; -import { TdLoadingService } from './services/loading.service'; -import { TdLoadingFactory } from './services/loading.factory'; +import { TdLoadingService, LOADING_PROVIDER } from './services/loading.service'; +import { TdLoadingFactory, LOADING_FACTORY_PROVIDER } from './services/loading.factory'; import { TdLoadingDirective } from './directives/loading.directive'; import { TdLoadingComponent } from './loading.component'; @@ -36,8 +36,8 @@ export { TdLoadingService, ITdLoadingConfig } from './services/loading.service'; TD_LOADING, ], providers: [ - TdLoadingFactory, - TdLoadingService, + LOADING_FACTORY_PROVIDER, + LOADING_PROVIDER, ], entryComponents: [ TD_LOADING_ENTRY_COMPONENTS, diff --git a/src/platform/core/loading/services/loading.factory.ts b/src/platform/core/loading/services/loading.factory.ts index e867ebfde1..ebe86e17aa 100644 --- a/src/platform/core/loading/services/loading.factory.ts +++ b/src/platform/core/loading/services/loading.factory.ts @@ -1,4 +1,4 @@ -import { Injectable, ComponentFactoryResolver, ChangeDetectorRef } from '@angular/core'; +import { Injectable, ComponentFactoryResolver, ChangeDetectorRef, Provider, SkipSelf, Optional } from '@angular/core'; import { Injector, ComponentRef, ViewContainerRef, TemplateRef } from '@angular/core'; import { TemplatePortal, Overlay, OverlayState, OverlayRef, OverlayOrigin, ComponentPortal } from '@angular/material'; import { Subject } from 'rxjs/Subject'; @@ -191,3 +191,15 @@ export class TdLoadingFactory { } } } + +export function LOADING_FACTORY_PROVIDER_FACTORY( + parent: TdLoadingFactory, componentFactoryResolver: ComponentFactoryResolver, overlay: Overlay, injector: Injector): TdLoadingFactory { + return parent || new TdLoadingFactory(componentFactoryResolver, overlay, injector); +} + +export const LOADING_FACTORY_PROVIDER: Provider = { + // If there is already a service available, use that. Otherwise, provide a new one. + provide: TdLoadingFactory, + deps: [[new Optional(), new SkipSelf(), TdLoadingFactory], ComponentFactoryResolver, Overlay, Injector], + useFactory: LOADING_FACTORY_PROVIDER_FACTORY, +}; diff --git a/src/platform/core/loading/services/loading.service.spec.ts b/src/platform/core/loading/services/loading.service.spec.ts index c69bcfbc0a..d374b5dd8e 100644 --- a/src/platform/core/loading/services/loading.service.spec.ts +++ b/src/platform/core/loading/services/loading.service.spec.ts @@ -43,25 +43,19 @@ describe('Service: Loading', () => { expect(fixture.debugElement.query(By.css('.content'))).toBeTruthy(); loadingService.register(); fixture.detectChanges(); - setTimeout(() => { + fixture.whenStable().then(() => { + expect(overlayContainerElement.querySelector('td-loading')).toBeTruthy(); + expect(overlayContainerElement.querySelector('md-progress-spinner')).toBeTruthy(); + expect(overlayContainerElement.querySelector('.mat-primary')).toBeTruthy(); + expect(overlayContainerElement.querySelector('.td-overlay')).toBeTruthy(); + expect(overlayContainerElement.querySelector('.td-fullscreen')).toBeTruthy(); + loadingService.resolve(); + fixture.detectChanges(); fixture.whenStable().then(() => { - fixture.detectChanges(); - expect(overlayContainerElement.querySelector('td-loading')).toBeTruthy(); - expect(overlayContainerElement.querySelector('md-progress-spinner')).toBeTruthy(); - expect(overlayContainerElement.querySelector('.mat-primary')).toBeTruthy(); - expect(overlayContainerElement.querySelector('.td-overlay')).toBeTruthy(); - expect(overlayContainerElement.querySelector('.td-fullscreen')).toBeTruthy(); - loadingService.resolve(); - fixture.detectChanges(); - setTimeout(() => { - fixture.detectChanges(); - fixture.whenStable().then(() => { - expect(overlayContainerElement.querySelector('td-loading')).toBeFalsy(); - done(); - }); - }, 200); + expect(overlayContainerElement.querySelector('td-loading')).toBeFalsy(); + done(); }); - }, 200); + }); })(); }); @@ -77,25 +71,19 @@ describe('Service: Loading', () => { expect(fixture.debugElement.query(By.css('.content'))).toBeTruthy(); loadingService.register('name'); fixture.detectChanges(); - setTimeout(() => { + fixture.whenStable().then(() => { + expect(overlayContainerElement.querySelector('td-loading')).toBeTruthy(); + expect(overlayContainerElement.querySelector('md-progress-bar')).toBeTruthy(); + expect(overlayContainerElement.querySelector('.mat-accent')).toBeTruthy(); + expect(overlayContainerElement.querySelector('.td-overlay')).toBeTruthy(); + expect(overlayContainerElement.querySelector('.td-fullscreen')).toBeTruthy(); + loadingService.resolve('name'); + fixture.detectChanges(); fixture.whenStable().then(() => { - fixture.detectChanges(); - expect(overlayContainerElement.querySelector('td-loading')).toBeTruthy(); - expect(overlayContainerElement.querySelector('md-progress-bar')).toBeTruthy(); - expect(overlayContainerElement.querySelector('.mat-accent')).toBeTruthy(); - expect(overlayContainerElement.querySelector('.td-overlay')).toBeTruthy(); - expect(overlayContainerElement.querySelector('.td-fullscreen')).toBeTruthy(); - loadingService.resolve('name'); - fixture.detectChanges(); - setTimeout(() => { - fixture.detectChanges(); - fixture.whenStable().then(() => { - expect(overlayContainerElement.querySelector('td-loading')).toBeFalsy(); - done(); - }); - }, 200); + expect(overlayContainerElement.querySelector('td-loading')).toBeFalsy(); + done(); }); - }, 200); + }); })(); }); @@ -111,25 +99,19 @@ describe('Service: Loading', () => { expect(fixture.debugElement.query(By.css('.content'))).toBeTruthy(); loadingService.register('name'); fixture.detectChanges(); - setTimeout(() => { + fixture.whenStable().then(() => { + expect(overlayContainerElement.querySelector('td-loading')).toBeTruthy(); + expect(overlayContainerElement.querySelector('md-progress-bar')).toBeTruthy(); + expect(overlayContainerElement.querySelector('.mat-accent')).toBeTruthy(); + expect(overlayContainerElement.querySelector('.td-overlay')).toBeTruthy(); + expect(overlayContainerElement.querySelector('.td-fullscreen')).toBeTruthy(); + loadingService.resolve('name'); + fixture.detectChanges(); fixture.whenStable().then(() => { - fixture.detectChanges(); - expect(overlayContainerElement.querySelector('td-loading')).toBeTruthy(); - expect(overlayContainerElement.querySelector('md-progress-bar')).toBeTruthy(); - expect(overlayContainerElement.querySelector('.mat-accent')).toBeTruthy(); - expect(overlayContainerElement.querySelector('.td-overlay')).toBeTruthy(); - expect(overlayContainerElement.querySelector('.td-fullscreen')).toBeTruthy(); - loadingService.resolve('name'); - fixture.detectChanges(); - setTimeout(() => { - fixture.detectChanges(); - fixture.whenStable().then(() => { - expect(overlayContainerElement.querySelector('td-loading')).toBeFalsy(); - done(); - }); - }, 200); + expect(overlayContainerElement.querySelector('td-loading')).toBeFalsy(); + done(); }); - }, 200); + }); })(); }); @@ -188,25 +170,19 @@ describe('Service: Loading', () => { loadingService.register(); loadingService.register(); fixture.detectChanges(); - setTimeout(() => { + fixture.whenStable().then(() => { + expect(overlayContainerElement.querySelector('td-loading')).toBeTruthy(); + expect(overlayContainerElement.querySelector('md-progress-spinner')).toBeTruthy(); + expect(overlayContainerElement.querySelector('.mat-primary')).toBeTruthy(); + expect(overlayContainerElement.querySelector('.td-overlay')).toBeTruthy(); + expect(overlayContainerElement.querySelector('.td-fullscreen')).toBeTruthy(); + loadingService.resolveAll(); + fixture.detectChanges(); fixture.whenStable().then(() => { - fixture.detectChanges(); - expect(overlayContainerElement.querySelector('td-loading')).toBeTruthy(); - expect(overlayContainerElement.querySelector('md-progress-spinner')).toBeTruthy(); - expect(overlayContainerElement.querySelector('.mat-primary')).toBeTruthy(); - expect(overlayContainerElement.querySelector('.td-overlay')).toBeTruthy(); - expect(overlayContainerElement.querySelector('.td-fullscreen')).toBeTruthy(); - loadingService.resolveAll(); - fixture.detectChanges(); - setTimeout(() => { - fixture.detectChanges(); - fixture.whenStable().then(() => { - expect(overlayContainerElement.querySelector('td-loading')).toBeFalsy(); - done(); - }); - }, 200); + expect(overlayContainerElement.querySelector('td-loading')).toBeFalsy(); + done(); }); - }, 200); + }); })(); }); }); diff --git a/src/platform/core/loading/services/loading.service.ts b/src/platform/core/loading/services/loading.service.ts index ac71493683..7be6495abf 100644 --- a/src/platform/core/loading/services/loading.service.ts +++ b/src/platform/core/loading/services/loading.service.ts @@ -1,4 +1,4 @@ -import { Injectable } from '@angular/core'; +import { Injectable, Provider, SkipSelf, Optional } from '@angular/core'; import { ViewContainerRef, TemplateRef } from '@angular/core'; import { Subject } from 'rxjs/Subject'; import { Observable } from 'rxjs/Observable'; @@ -230,3 +230,15 @@ export class TdLoadingService { delete this._timeouts[name]; } } + +export function LOADING_PROVIDER_FACTORY( + parent: TdLoadingService, loadingFactory: TdLoadingFactory): TdLoadingService { + return parent || new TdLoadingService(loadingFactory); +} + +export const LOADING_PROVIDER: Provider = { + // If there is already a service available, use that. Otherwise, provide a new one. + provide: TdLoadingService, + deps: [[new Optional(), new SkipSelf(), TdLoadingService], TdLoadingFactory], + useFactory: LOADING_PROVIDER_FACTORY, +}; diff --git a/src/platform/core/media/directives/media-toggle.directive.ts b/src/platform/core/media/directives/media-toggle.directive.ts index 2de0cf4fbf..cc5739b047 100644 --- a/src/platform/core/media/directives/media-toggle.directive.ts +++ b/src/platform/core/media/directives/media-toggle.directive.ts @@ -81,8 +81,11 @@ export class TdMediaToggleDirective implements OnInit, OnDestroy { private _changeAttributes(): void { for (let attr in this._attributes) { - this._renderer.setAttribute(this._elementRef.nativeElement, attr, - this._matches ? this._attributes[attr] : undefined); + if (this._matches) { + this._renderer.setAttribute(this._elementRef.nativeElement, attr, this._attributes[attr]); + } else { + this._renderer.removeAttribute(this._elementRef.nativeElement, attr); + } } } @@ -98,8 +101,11 @@ export class TdMediaToggleDirective implements OnInit, OnDestroy { private _changeStyles(): void { for (let style in this._styles) { - this._renderer.setStyle(this._elementRef.nativeElement, style, - this._matches ? this._styles[style] : undefined); + if (this._matches) { + this._renderer.setStyle(this._elementRef.nativeElement, style, this._styles[style]); + } else { + this._renderer.removeStyle(this._elementRef.nativeElement, style); + } } } diff --git a/src/platform/core/media/media.module.ts b/src/platform/core/media/media.module.ts index 5147ee25bd..7db5f3302c 100644 --- a/src/platform/core/media/media.module.ts +++ b/src/platform/core/media/media.module.ts @@ -3,7 +3,7 @@ import { NgModule, ModuleWithProviders } from '@angular/core'; import { CommonModule } from '@angular/common'; -import { TdMediaService } from './services/media.service'; +import { TdMediaService, MEDIA_PROVIDER } from './services/media.service'; import { TdMediaToggleDirective } from './directives/media-toggle.directive'; const TD_MEDIA: Type[] = [ @@ -23,7 +23,7 @@ export { TdMediaService, TdMediaToggleDirective }; TD_MEDIA, ], providers: [ - TdMediaService, + MEDIA_PROVIDER, ], }) export class CovalentMediaModule { diff --git a/src/platform/core/media/services/media.service.ts b/src/platform/core/media/services/media.service.ts index 5e574464f1..5300f4c974 100644 --- a/src/platform/core/media/services/media.service.ts +++ b/src/platform/core/media/services/media.service.ts @@ -1,10 +1,13 @@ -import { Injectable, NgZone } from '@angular/core'; +import { Injectable, NgZone, SkipSelf, Optional, Provider } from '@angular/core'; import { Subject } from 'rxjs/Subject'; import { Observable } from 'rxjs/Observable'; +import { Subscription } from 'rxjs/Subscription'; @Injectable() export class TdMediaService { + private _resizing: boolean = false; + private _globalSubscription: Subscription; private _queryMap: Map = new Map(); private _querySources: {[key: string]: Subject} = {}; private _queryObservables: {[key: string]: Observable} = {}; @@ -23,24 +26,32 @@ export class TdMediaService { this._queryMap.set('portrait', 'portrait'); this._queryMap.set('print', 'print'); - let running: boolean = false; - window.onresize = () => { - // way to prevent the resize event from triggering the match media if there is already one event running already. - if (!running) { - running = true; - if (window.requestAnimationFrame) { - window.requestAnimationFrame(() => { - this._onResize(); - running = false; - }); - } else { + this._resizing = false; + // we make sure that the resize checking happend outside of angular since it happens often + this._globalSubscription = this._ngZone.runOutsideAngular(() => { + return Observable.fromEvent(window, 'resize').subscribe(() => { + // way to prevent the resize event from triggering the match media if there is already one event running already. + if (!this._resizing) { + this._resizing = true; setTimeout(() => { this._onResize(); - running = false; - }, 66); + this._resizing = false; + }, 100); } - } - }; + }); + }); + } + + /** + * Deregisters a query so its stops being notified or used. + */ + deregisterQuery(query: string): void { + if (this._queryMap.get(query.toLowerCase())) { + query = this._queryMap.get(query.toLowerCase()); + } + this._querySources[query].unsubscribe(); + delete this._querySources[query]; + delete this._queryObservables[query]; } /** @@ -51,7 +62,7 @@ export class TdMediaService { query = this._queryMap.get(query.toLowerCase()); } return this._ngZone.run(() => { - return window.matchMedia(query).matches; + return matchMedia(query).matches; }); } @@ -87,6 +98,18 @@ export class TdMediaService { } private _matchMediaTrigger(query: string): void { - this._querySources[query].next(window.matchMedia(query).matches); + this._querySources[query].next(matchMedia(query).matches); } } + +export function MEDIA_PROVIDER_FACTORY( + parent: TdMediaService, ngZone: NgZone): TdMediaService { + return parent || new TdMediaService(ngZone); +} + +export const MEDIA_PROVIDER: Provider = { + // If there is already a service available, use that. Otherwise, provide a new one. + provide: TdMediaService, + deps: [[new Optional(), new SkipSelf(), TdMediaService], NgZone], + useFactory: MEDIA_PROVIDER_FACTORY, +}; diff --git a/src/platform/core/message/message.component.spec.ts b/src/platform/core/message/message.component.spec.ts index c1784c3823..18f984c5e4 100644 --- a/src/platform/core/message/message.component.spec.ts +++ b/src/platform/core/message/message.component.spec.ts @@ -10,14 +10,14 @@ import { By } from '@angular/platform-browser'; import { TdMessageComponent } from './message.component'; import { CovalentMessageModule } from './message.module'; import { NgModule, DebugElement } from '@angular/core'; -import { BrowserAnimationsModule } from '@angular/platform-browser/animations'; +import { NoopAnimationsModule } from '@angular/platform-browser/animations'; describe('Component: Message', () => { beforeEach(async(() => { TestBed.configureTestingModule({ imports: [ - BrowserAnimationsModule, + NoopAnimationsModule, CovalentMessageModule, ], declarations: [ @@ -81,7 +81,6 @@ describe('Component: Message', () => { fixture.detectChanges(); fixture.whenStable().then(() => { fixture.detectChanges(); - expect(fixture.debugElement.query(By.css('.td-message-label'))).toBeTruthy(); expect(fixture.debugElement.query(By.css('.td-message-sublabel'))).toBeFalsy(); done(); @@ -95,8 +94,6 @@ describe('Component: Message', () => { component.color = 'primary'; fixture.detectChanges(); fixture.whenStable().then(() => { - fixture.detectChanges(); - expect(fixture.debugElement.query(By.css('.td-message-wrapper')).query(By.css('button'))).toBeTruthy(); done(); }); @@ -111,19 +108,16 @@ describe('Component: Message', () => { component.color = 'primary'; fixture.detectChanges(); fixture.whenStable().then(() => { - fixture.detectChanges(); expect(fixture.debugElement.query(By.css('.td-message-wrapper'))).toBeTruthy(); message.close(); fixture.detectChanges(); fixture.whenStable().then(() => { - fixture.detectChanges(); expect(fixture.debugElement.query(By.css('.td-message-wrapper'))).toBeFalsy(); message.open(); fixture.detectChanges(); fixture.whenStable().then(() => { - fixture.detectChanges(); expect(fixture.debugElement.query(By.css('.td-message-wrapper'))).toBeTruthy(); done(); }); @@ -131,6 +125,32 @@ describe('Component: Message', () => { }); }); + it('should not render the component, open it and then close it', (done: DoneFn) => { + let fixture: ComponentFixture = TestBed.createComponent(TdMessageOpenedTestComponent); + let component: TdMessageOpenedTestComponent = fixture.debugElement.componentInstance; + let message: TdMessageComponent = fixture.debugElement.query(By.directive(TdMessageComponent)).componentInstance; + + component.label = 'Label'; + component.color = 'primary'; + fixture.detectChanges(); + fixture.whenStable().then(() => { + expect(fixture.debugElement.query(By.css('.td-message-wrapper'))).toBeFalsy(); + + message.open(); + fixture.detectChanges(); + fixture.whenStable().then(() => { + expect(fixture.debugElement.query(By.css('.td-message-wrapper'))).toBeTruthy(); + + message.close(); + fixture.detectChanges(); + fixture.whenStable().then(() => { + expect(fixture.debugElement.query(By.css('.td-message-wrapper'))).toBeFalsy(); + done(); + }); + }); + }); + }); + it('should render the component, toggle it and then toggle it again', (done: DoneFn) => { let fixture: ComponentFixture = TestBed.createComponent(TdMessageBasicTestComponent); let component: TdMessageBasicTestComponent = fixture.debugElement.componentInstance; @@ -140,19 +160,16 @@ describe('Component: Message', () => { component.color = 'primary'; fixture.detectChanges(); fixture.whenStable().then(() => { - fixture.detectChanges(); expect(fixture.debugElement.query(By.css('.td-message-wrapper'))).toBeTruthy(); message.toggle(); fixture.detectChanges(); fixture.whenStable().then(() => { - fixture.detectChanges(); expect(fixture.debugElement.query(By.css('.td-message-wrapper'))).toBeFalsy(); message.toggle(); fixture.detectChanges(); fixture.whenStable().then(() => { - fixture.detectChanges(); expect(fixture.debugElement.query(By.css('.td-message-wrapper'))).toBeTruthy(); done(); }); @@ -160,6 +177,25 @@ describe('Component: Message', () => { }); }); + it('should render the component, then [opened] to false', (done: DoneFn) => { + let fixture: ComponentFixture = TestBed.createComponent(TdMessageOpenedTestComponent); + let component: TdMessageOpenedTestComponent = fixture.debugElement.componentInstance; + + component.opened = true; + component.label = 'Label'; + component.color = 'primary'; + fixture.detectChanges(); + fixture.whenStable().then(() => { + expect(fixture.debugElement.query(By.css('.td-message-wrapper'))).toBeTruthy(); + component.opened = false; + fixture.detectChanges(); + fixture.whenStable().then(() => { + expect(fixture.debugElement.query(By.css('.td-message-wrapper'))).toBeFalsy(); + done(); + }); + }); + }); + it('should not render the component, set [opened] to true and then [opened] to false', (done: DoneFn) => { let fixture: ComponentFixture = TestBed.createComponent(TdMessageOpenedTestComponent); let component: TdMessageOpenedTestComponent = fixture.debugElement.componentInstance; @@ -168,19 +204,16 @@ describe('Component: Message', () => { component.color = 'primary'; fixture.detectChanges(); fixture.whenStable().then(() => { - fixture.detectChanges(); expect(fixture.debugElement.query(By.css('.td-message-wrapper'))).toBeFalsy(); component.opened = true; fixture.detectChanges(); fixture.whenStable().then(() => { - fixture.detectChanges(); expect(fixture.debugElement.query(By.css('.td-message-wrapper'))).toBeTruthy(); component.opened = false; fixture.detectChanges(); fixture.whenStable().then(() => { - fixture.detectChanges(); expect(fixture.debugElement.query(By.css('.td-message-wrapper'))).toBeFalsy(); done(); }); diff --git a/src/platform/core/message/message.component.ts b/src/platform/core/message/message.component.ts index 854ad923f5..772fb64770 100644 --- a/src/platform/core/message/message.component.ts +++ b/src/platform/core/message/message.component.ts @@ -1,5 +1,8 @@ import { Component, Directive, Input, Renderer2, ElementRef, AfterViewInit, ViewContainerRef, TemplateRef, ViewChild, - HostBinding, ChangeDetectorRef } from '@angular/core'; + HostBinding, HostListener, ChangeDetectorRef } from '@angular/core'; + +import { TdCollapseAnimation } from '../common/animations/collapse/collapse.animation'; +import { TdFadeInOutAnimation } from '../common/animations/fade/fadeInOut.animation'; @Directive({ selector: '[tdMessageContainer]', @@ -12,19 +15,44 @@ export class TdMessageContainerDirective { selector: 'td-message', templateUrl: './message.component.html', styleUrls: ['./message.component.scss'], + animations: [ + TdCollapseAnimation(100), + TdFadeInOutAnimation(100), + ], }) export class TdMessageComponent implements AfterViewInit { private _color: string; private _opened: boolean = true; + private _hidden: boolean = false; + private _animating: boolean = false; private _initialized: boolean = false; @ViewChild(TdMessageContainerDirective) _childElement: TdMessageContainerDirective; @ViewChild(TemplateRef) _template: TemplateRef; + /** + * Binding host to tdFadeInOut animation + */ + @HostBinding('@tdFadeInOut') + get fadeAnimation(): boolean { + return this._opened; + } + + /** + * Binding host to tdCollapse animation + */ + @HostBinding('@tdCollapse') + get collapsedAnimation(): boolean { + return !this._opened; + } + + /** + * Binding host to display style when hidden + */ @HostBinding('style.display') get hidden(): string { - return !this._opened ? 'none' : undefined; + return this._hidden ? 'none' : undefined; } /** @@ -102,37 +130,51 @@ export class TdMessageComponent implements AfterViewInit { } /** - * Initializes the component and attaches the content if [opened] was true. + * Detach element when close animation is finished to set animating state to false + * hidden state to true and detach element from DOM + */ + @HostListener('@tdCollapse.done') + animationDoneListener(): void { + if (!this._opened) { + this._hidden = true; + this._detach(); + } + this._animating = false; + this._changeDetectorRef.markForCheck(); + } + + /** + * Initializes the component and attaches the content. */ ngAfterViewInit(): void { Promise.resolve(undefined).then(() => { if (this._opened) { - this._childElement.viewContainer.createEmbeddedView(this._template); - this._changeDetectorRef.markForCheck(); + this._attach(); } this._initialized = true; }); } /** - * Renders the message on screen. + * Renders the message on screen + * Validates if there is an animation currently and if its already opened */ open(): void { - if (!this._opened) { + if (!this._opened && !this._animating) { this._opened = true; - this._childElement.viewContainer.createEmbeddedView(this._template); - this._changeDetectorRef.markForCheck(); + this._attach(); + this._startAnimationState(); } } /** * Removes the message content from screen. + * Validates if there is an animation currently and if its already closed */ close(): void { - if (this._opened) { + if (this._opened && !this._animating) { this._opened = false; - this._childElement.viewContainer.clear(); - this._changeDetectorRef.markForCheck(); + this._startAnimationState(); } } @@ -146,4 +188,29 @@ export class TdMessageComponent implements AfterViewInit { this.open(); } } + + /** + * Method to set the state before starting an animation + */ + private _startAnimationState(): void { + this._animating = true; + this._hidden = false; + this._changeDetectorRef.markForCheck(); + } + + /** + * Method to attach template to DOM + */ + private _attach(): void { + this._childElement.viewContainer.createEmbeddedView(this._template); + this._changeDetectorRef.markForCheck(); + } + + /** + * Method to detach template from DOM + */ + private _detach(): void { + this._childElement.viewContainer.clear(); + this._changeDetectorRef.markForCheck(); + } } diff --git a/src/platform/core/package.json b/src/platform/core/package.json index 94faa4c1c5..99cac29e3f 100644 --- a/src/platform/core/package.json +++ b/src/platform/core/package.json @@ -1,6 +1,6 @@ { "name": "@covalent/core", - "version": "1.0.0-beta.4", + "version": "1.0.0-beta.5", "description": "Teradata UI Platform built on Angular Material", "main": "./core.umd.js", "module": "./index.js", @@ -38,11 +38,11 @@ "Steven Ov " ], "peerDependencies": { - "@angular/common": "^4.1.0", - "@angular/core": "^4.1.0", - "@angular/forms": "^4.1.0", - "@angular/http": "^4.1.0", - "@angular/router": "^4.1.0", - "@angular/material": "2.0.0-beta.5" + "@angular/common": "^4.2.0", + "@angular/core": "^4.2.0", + "@angular/forms": "^4.2.0", + "@angular/http": "^4.2.0", + "@angular/router": "^4.2.0", + "@angular/material": "2.0.0-beta.6" } } diff --git a/src/platform/core/paging/paging-bar.component.spec.ts b/src/platform/core/paging/paging-bar.component.spec.ts index 1309bf3e16..554fb7813b 100644 --- a/src/platform/core/paging/paging-bar.component.spec.ts +++ b/src/platform/core/paging/paging-bar.component.spec.ts @@ -10,14 +10,14 @@ import { By } from '@angular/platform-browser'; import { TdPagingBarComponent } from './paging-bar.component'; import { CovalentPagingModule } from './paging.module'; import { NgModule, DebugElement } from '@angular/core'; -import { BrowserAnimationsModule } from '@angular/platform-browser/animations'; +import { NoopAnimationsModule } from '@angular/platform-browser/animations'; describe('Component: PagingBar', () => { beforeEach(async(() => { TestBed.configureTestingModule({ imports: [ - BrowserAnimationsModule, + NoopAnimationsModule, CovalentPagingModule, ], declarations: [ diff --git a/src/platform/core/search/search-box/search-box.component.ts b/src/platform/core/search/search-box/search-box.component.ts index d1971e467a..aa96c12e9b 100644 --- a/src/platform/core/search/search-box/search-box.component.ts +++ b/src/platform/core/search/search-box/search-box.component.ts @@ -1,5 +1,5 @@ import { Component, ViewChild, Input, Output, EventEmitter } from '@angular/core'; -import { trigger, state, style, transition, animate } from '@angular/animations'; +import { trigger, state, style, transition, animate, AUTO_STYLE } from '@angular/animations'; import { TdSearchInputComponent } from '../search-input/search-input.component'; @@ -11,13 +11,11 @@ import { TdSearchInputComponent } from '../search-input/search-input.component'; trigger('inputState', [ state('0', style({ width: '0%', - 'margin-left': '0px', - 'margin-right': '0px', + margin: '0px', })), state('1', style({ width: '100%', - 'margin-left': '*', - 'margin-right': '*', + margin: AUTO_STYLE, })), transition('0 => 1', animate('200ms ease-in')), transition('1 => 0', animate('200ms ease-out')), diff --git a/src/platform/core/steps/_steps-theme.scss b/src/platform/core/steps/_steps-theme.scss index ac94c3c10b..6f4213286b 100644 --- a/src/platform/core/steps/_steps-theme.scss +++ b/src/platform/core/steps/_steps-theme.scss @@ -25,15 +25,15 @@ } // header .td-step-header { - &:focus, - &:hover { + &:focus:not(.mat-disabled), + &:hover:not(.mat-disabled) { background: mat-color($background, 'hover'); } .td-step-label-wrapper { .md-caption { color: mat-color($foreground, secondary-text); } - &.mat-disabled { + &.mat-inactive { &, & * { color: mat-color($foreground, disabled); } diff --git a/src/platform/core/steps/step-body/step-body.component.html b/src/platform/core/steps/step-body/step-body.component.html index e7c7b97f71..77e7306998 100644 --- a/src/platform/core/steps/step-body/step-body.component.html +++ b/src/platform/core/steps/step-body/step-body.component.html @@ -1,9 +1,9 @@
-
+
-
+
diff --git a/src/platform/core/steps/step-body/step-body.component.scss b/src/platform/core/steps/step-body/step-body.component.scss index e69de29bb2..8a8f7dcb3a 100644 --- a/src/platform/core/steps/step-body/step-body.component.scss +++ b/src/platform/core/steps/step-body/step-body.component.scss @@ -0,0 +1,6 @@ +.td-step-body { + overflow-x: hidden; + .td-step-content { + overflow-x: auto; + } +} \ No newline at end of file diff --git a/src/platform/core/steps/step-header/step-header.component.html b/src/platform/core/steps/step-header/step-header.component.html index 862019924a..2117c23096 100644 --- a/src/platform/core/steps/step-header/step-header.component.html +++ b/src/platform/core/steps/step-header/step-header.component.html @@ -1,7 +1,7 @@
warning
diff --git a/src/platform/core/steps/step-header/step-header.component.scss b/src/platform/core/steps/step-header/step-header.component.scss index 8f2414752c..cf8c6f155e 100644 --- a/src/platform/core/steps/step-header/step-header.component.scss +++ b/src/platform/core/steps/step-header/step-header.component.scss @@ -3,14 +3,9 @@ $step-circle: 24px; .td-step-header { position: relative; outline: none; - &:focus, - &:hover { + &:hover:not(.mat-disabled) { cursor: pointer; } - &.mat-disabled { - background: none; - cursor: auto; - } .td-step-header-content { height: 72px; } diff --git a/src/platform/core/steps/step-header/step-header.component.ts b/src/platform/core/steps/step-header/step-header.component.ts index 2de6a4e3aa..2f934ebee1 100644 --- a/src/platform/core/steps/step-header/step-header.component.ts +++ b/src/platform/core/steps/step-header/step-header.component.ts @@ -14,6 +14,12 @@ export class TdStepHeaderComponent { */ @Input('number') number: number; + /** + * disableRipple?: string + * Whether the ripple effect on header is disabled. + */ + @Input('disableRipple') disableRipple: boolean; + /** * active?: boolean * Sets for active/inactive states on header. diff --git a/src/platform/core/steps/step.component.ts b/src/platform/core/steps/step.component.ts index 44549c8940..13929a5ba0 100644 --- a/src/platform/core/steps/step.component.ts +++ b/src/platform/core/steps/step.component.ts @@ -42,6 +42,7 @@ export class TdStepSummaryDirective extends TemplatePortalDirective { }) export class TdStepComponent implements OnInit { + private _disableRipple: boolean = false; private _active: boolean = false; private _state: StepState = StepState.None; private _disabled: boolean = false; @@ -69,13 +70,25 @@ export class TdStepComponent implements OnInit { */ @Input('sublabel') sublabel: string; + /** + * disableRipple?: string + * Whether the ripple effect for this component is disabled. + */ + @Input('disableRipple') + set disableRipple(disableRipple: boolean) { + this._disableRipple = disableRipple !== '' ? (disableRipple === 'true' || disableRipple === true) : true; + } + get disableRipple(): boolean { + return this._disableRipple; + } + /** * active?: boolean * Toggles [TdStepComponent] between active/deactive. */ @Input('active') set active(active: boolean) { - this._setActive(active); + this._setActive(active === 'true' || active === true); } get active(): boolean { return this._active; diff --git a/src/platform/core/steps/steps.component.html b/src/platform/core/steps/steps.component.html index 1ba2e40f14..26f72228a1 100644 --- a/src/platform/core/steps/steps.component.html +++ b/src/platform/core/steps/steps.component.html @@ -3,7 +3,8 @@ @@ -19,7 +20,8 @@ (keydown.enter)="step.toggle()" [number]="index + 1" [active]="step.active" - [disabled]="step.disabled" + [disabled]="step.disabled" + [disableRipple]="step.disableRipple" [state]="step.state" (click)="step.toggle()" *ngIf="isVertical()"> diff --git a/src/platform/core/steps/steps.component.spec.ts b/src/platform/core/steps/steps.component.spec.ts index 466c7baf9c..572a94459c 100644 --- a/src/platform/core/steps/steps.component.spec.ts +++ b/src/platform/core/steps/steps.component.spec.ts @@ -5,7 +5,7 @@ import { ComponentFixture, } from '@angular/core/testing'; import { Component, DebugElement } from '@angular/core'; -import { BrowserAnimationsModule } from '@angular/platform-browser/animations'; +import { NoopAnimationsModule } from '@angular/platform-browser/animations'; import { By } from '@angular/platform-browser'; import { CovalentStepsModule, StepState, StepMode } from './steps.module'; @@ -19,7 +19,7 @@ describe('Component: Steps', () => { TdStepsDynamicTestComponent, ], imports: [ - BrowserAnimationsModule, + NoopAnimationsModule, CovalentStepsModule, ], }); diff --git a/src/platform/core/steps/steps.module.ts b/src/platform/core/steps/steps.module.ts index b08d118908..ab03a8b95d 100644 --- a/src/platform/core/steps/steps.module.ts +++ b/src/platform/core/steps/steps.module.ts @@ -2,7 +2,7 @@ import { Type } from '@angular/core'; import { NgModule, ModuleWithProviders } from '@angular/core'; import { CommonModule } from '@angular/common'; -import { MdIconModule, MdRippleModule, PortalModule } from '@angular/material'; +import { MdIconModule, MdRippleModule, PortalModule, ScrollDispatchModule } from '@angular/material'; import { CovalentCommonModule } from '../common/common.module'; @@ -32,6 +32,7 @@ export { TdStepsComponent, IStepChangeEvent, StepMode } from './steps.component' MdIconModule, MdRippleModule, PortalModule, + ScrollDispatchModule, CovalentCommonModule, ], declarations: [ diff --git a/src/platform/dynamic-forms/dynamic-elements/dynamic-input/dynamic-input.component.html b/src/platform/dynamic-forms/dynamic-elements/dynamic-input/dynamic-input.component.html index c385ffbf77..f5d8ab3290 100644 --- a/src/platform/dynamic-forms/dynamic-elements/dynamic-input/dynamic-input.component.html +++ b/src/platform/dynamic-forms/dynamic-elements/dynamic-input/dynamic-input.component.html @@ -6,13 +6,13 @@ [placeholder]="label" [type]="type" [required]="required" - [min]="min" - [max]="max" + [attr.min]="min" + [attr.max]="max" flex> - Max: {{control.get('max')?.maxValue}} - Min: {{control.get('min')?.minValue}} + Max: {{max}} + Min: {{min}} diff --git a/src/platform/dynamic-forms/dynamic-forms.module.ts b/src/platform/dynamic-forms/dynamic-forms.module.ts index cf0187b8f4..a87a29be4d 100644 --- a/src/platform/dynamic-forms/dynamic-forms.module.ts +++ b/src/platform/dynamic-forms/dynamic-forms.module.ts @@ -8,7 +8,7 @@ import { CovalentCommonModule } from '../core'; import { TdDynamicFormsComponent } from './dynamic-forms.component'; import { TdDynamicElementComponent, TdDynamicElementDirective } from './dynamic-element.component'; -import { TdDynamicFormsService } from './services/dynamic-forms.service'; +import { TdDynamicFormsService, DYNAMIC_FORMS_PROVIDER } from './services/dynamic-forms.service'; import { TdDynamicInputComponent } from './dynamic-elements/dynamic-input/dynamic-input.component'; import { TdDynamicTextareaComponent } from './dynamic-elements/dynamic-textarea/dynamic-textarea.component'; @@ -56,7 +56,7 @@ const TD_DYNAMIC_FORMS_ENTRY_COMPONENTS: Type[] = [ TD_DYNAMIC_FORMS_ENTRY_COMPONENTS, ], providers: [ - TdDynamicFormsService, + DYNAMIC_FORMS_PROVIDER, ], entryComponents: [ TD_DYNAMIC_FORMS_ENTRY_COMPONENTS ], }) diff --git a/src/platform/dynamic-forms/package.json b/src/platform/dynamic-forms/package.json index abeea4c9dd..ff2a415143 100644 --- a/src/platform/dynamic-forms/package.json +++ b/src/platform/dynamic-forms/package.json @@ -1,6 +1,6 @@ { "name": "@covalent/dynamic-forms", - "version": "1.0.0-beta.4", + "version": "1.0.0-beta.5", "description": "Teradata UI Platform Dynamic Forms Module", "main": "./dynamic-forms.umd.js", "module": "./index.js", @@ -37,6 +37,6 @@ "Steven Ov " ], "dependencies": { - "@covalent/core": "1.0.0-beta.4" + "@covalent/core": "1.0.0-beta.5" } } diff --git a/src/platform/dynamic-forms/services/dynamic-forms.service.ts b/src/platform/dynamic-forms/services/dynamic-forms.service.ts index fe8310d88e..916c2b8729 100644 --- a/src/platform/dynamic-forms/services/dynamic-forms.service.ts +++ b/src/platform/dynamic-forms/services/dynamic-forms.service.ts @@ -1,8 +1,6 @@ -import { Injectable } from '@angular/core'; +import { Injectable, Provider, SkipSelf, Optional } from '@angular/core'; import { Validators, ValidatorFn, FormControl } from '@angular/forms'; -import { CovalentValidators } from '../../core'; - import { TdDynamicInputComponent } from '../dynamic-elements/dynamic-input/dynamic-input.component'; import { TdDynamicTextareaComponent } from '../dynamic-elements/dynamic-textarea/dynamic-textarea.component'; import { TdDynamicSlideToggleComponent } from '../dynamic-elements/dynamic-slide-toggle/dynamic-slide-toggle.component'; @@ -123,11 +121,23 @@ export class TdDynamicFormsService { validator = Validators.required; } if (config.max || config.max === 0) { - validator = Validators.compose([validator, CovalentValidators.max(config.max)]); + validator = Validators.compose([validator, Validators.max(parseFloat(config.max))]); } if (config.min || config.min === 0) { - validator = Validators.compose([validator, CovalentValidators.min(config.min)]); + validator = Validators.compose([validator, Validators.min(parseFloat(config.min))]); } return validator; } } + +export function DYNAMIC_FORMS_PROVIDER_FACTORY( + parent: TdDynamicFormsService): TdDynamicFormsService { + return parent || new TdDynamicFormsService(); +} + +export const DYNAMIC_FORMS_PROVIDER: Provider = { + // If there is already a service available, use that. Otherwise, provide a new one. + provide: TdDynamicFormsService, + deps: [[new Optional(), new SkipSelf(), TdDynamicFormsService]], + useFactory: DYNAMIC_FORMS_PROVIDER_FACTORY, +}; diff --git a/src/platform/highlight/package.json b/src/platform/highlight/package.json index 2bedeb5a8b..7d950a6cdf 100644 --- a/src/platform/highlight/package.json +++ b/src/platform/highlight/package.json @@ -1,6 +1,6 @@ { "name": "@covalent/highlight", - "version": "1.0.0-beta.4", + "version": "1.0.0-beta.5", "description": "Teradata UI Platform Highlight Module", "main": "./highlight.umd.js", "module": "./index.js", @@ -40,7 +40,7 @@ "highlight.js": "9.11.0" }, "peerDependencies": { - "@angular/common": "^4.1.0", - "@angular/core": "^4.1.0" + "@angular/common": "^4.2.0", + "@angular/core": "^4.2.0" } } diff --git a/src/platform/http/http.module.ts b/src/platform/http/http.module.ts index fd553058a5..3b14c07004 100644 --- a/src/platform/http/http.module.ts +++ b/src/platform/http/http.module.ts @@ -1,4 +1,4 @@ -import { NgModule, ModuleWithProviders, Injector, InjectionToken } from '@angular/core'; +import { NgModule, ModuleWithProviders, Injector, InjectionToken, Provider } from '@angular/core'; import { HttpModule, Http } from '@angular/http'; import { HttpInterceptorService, IHttpInterceptorConfig } from './interceptors/http-interceptor.service'; @@ -12,6 +12,12 @@ export function httpFactory(http: Http, injector: Injector, config: HttpConfig): return new HttpInterceptorService(http, injector, new URLRegExpInterceptorMatcher(), config.interceptors); } +export const HTTP_INTERCEPTOR_PROVIDER: Provider = { + provide: HttpInterceptorService, + useFactory: httpFactory, + deps: [Http, Injector, HTTP_CONFIG], +}; + @NgModule({ imports: [ HttpModule, @@ -24,11 +30,8 @@ export class CovalentHttpModule { providers: [{ provide: HTTP_CONFIG, useValue: config, - }, { - provide: HttpInterceptorService, - useFactory: httpFactory, - deps: [Http, Injector, HTTP_CONFIG], }, + HTTP_INTERCEPTOR_PROVIDER, ], }; } diff --git a/src/platform/http/package.json b/src/platform/http/package.json index 60646e5ffc..410515612d 100644 --- a/src/platform/http/package.json +++ b/src/platform/http/package.json @@ -1,6 +1,6 @@ { "name": "@covalent/http", - "version": "1.0.0-beta.4", + "version": "1.0.0-beta.5", "description": "Teradata UI Platform Http Helper Module", "main": "./http.umd.js", "module": "./index.js", @@ -38,7 +38,7 @@ "Steven Ov " ], "peerDependencies": { - "@angular/core": "^4.1.0", - "@angular/http": "^4.1.0" + "@angular/core": "^4.2.0", + "@angular/http": "^4.2.0" } } diff --git a/src/platform/markdown/package.json b/src/platform/markdown/package.json index f07f310672..4876ddb7d0 100644 --- a/src/platform/markdown/package.json +++ b/src/platform/markdown/package.json @@ -1,6 +1,6 @@ { "name": "@covalent/markdown", - "version": "1.0.0-beta.4", + "version": "1.0.0-beta.5", "description": "Teradata UI Platform Markdown Module", "main": "./markdown.umd.js", "module": "./index.js", @@ -38,7 +38,7 @@ "showdown": "1.6.4" }, "peerDependencies": { - "@angular/common": "^4.1.0", - "@angular/core": "^4.1.0" + "@angular/common": "^4.2.0", + "@angular/core": "^4.2.0" } } diff --git a/src/polyfills.ts b/src/polyfills.ts index 602e30a8c4..d7515f9198 100644 --- a/src/polyfills.ts +++ b/src/polyfills.ts @@ -12,6 +12,7 @@ import 'core-js/es6/date'; import 'core-js/es6/array'; import 'core-js/es6/regexp'; import 'core-js/es6/map'; +import 'core-js/es6/weak-map'; import 'core-js/es6/set'; import 'core-js/es6/reflect'; diff --git a/src/styles.scss b/src/styles.scss index fe4daf3902..0efa25962f 100644 --- a/src/styles.scss +++ b/src/styles.scss @@ -14,5 +14,4 @@ html[dir="rtl"] & { direction: rtl; } - } \ No newline at end of file diff --git a/src/theme.scss b/src/theme.scss index a04235302b..dc2e20d613 100644 --- a/src/theme.scss +++ b/src/theme.scss @@ -8,11 +8,44 @@ // have to load a single css file for Angular Material in your app. @include mat-core(); +// Custom orange contrast +$mat-orange-custom: ( 50: #FFF3E0, + 100: #FFE0B2, + 200: #FFCC80, + 300: #FFB74D, + 400: #FFA726, + 500: #FF9800, + 600: #FB8C00, + 700: #F57C00, + 800: #EF6C00, + 900: #E65100, + A100: #FFD180, + A200: #FFAB40, + A400: #FF9100, + A700: #FF6D00, + contrast: ( + 50: $black-87-opacity, + 100: $black-87-opacity, + 200: $black-87-opacity, + 300: $black-87-opacity, + 400: $black-87-opacity, + 500: white, + 600: white, + 700: white, + 800: $white-87-opacity, + 900: $white-87-opacity, + A100: $black-87-opacity, + A200: $black-87-opacity, + A400: $black-87-opacity, + A700: $white-87-opacity, + ) + ); + // Define the palettes for your theme using the Material Design palettes available in palette.scss // (imported above). For each palette, you can optionally specify a default, lighter, and darker // hue. -$primary: mat-palette($mat-orange, 800); -$accent: mat-palette($mat-light-blue, 600, A100, A400); +$primary: mat-palette($mat-blue-grey, 900); +$accent: mat-palette($mat-orange-custom, A700, A100, A400); // The warn palette is optional (defaults to red). $warn: mat-palette($mat-red, 600); @@ -28,6 +61,36 @@ $theme: mat-light-theme($primary, $accent, $warn); @include covalent-markdown-theme($theme); @include covalent-highlight-theme(); // OR @import '~highlight.js/styles/vs.css'; +// Alt theme +.theme-alt { + $primary-alt: mat-palette($mat-orange, 800); + $accent-alt: mat-palette($mat-light-blue, 700); + $warn-alt: mat-palette($mat-red, 600); + $theme-alt: mat-light-theme($primary-alt, $accent-alt, $warn-alt); + @include angular-material-theme($theme-alt); + @include covalent-theme($theme-alt); +} + +// Dark theme +.theme-dark { + $primary-dark: mat-palette($mat-blue-grey, 900); + $accent-dark: mat-palette($mat-deep-orange, A400); + $warn-dark: mat-palette($mat-red, 600); + $theme-dark: mat-dark-theme($primary-dark, $accent-dark, $warn-dark); + @include angular-material-theme($theme-dark); + @include covalent-theme($theme-dark); +} + +// Subpage themes +.theme-docs { + $primary-docs: mat-palette($mat-deep-purple, 700); + $accent-docs: mat-palette($mat-cyan, A400); + $warn-docs: mat-palette($mat-red, 600); + $theme-docs: mat-light-theme($primary-docs, $accent-docs, $warn-docs); + @include angular-material-theme($theme-docs); + @include covalent-theme($theme-docs); +} + // Custom theme examples .blue-orange { $primary2: mat-palette($mat-blue, 700); @@ -86,3 +149,23 @@ md-nav-list { .legend-title-text { color: mat-color($foreground, secondary-text); } + +// Expansion panels +.theme-dark td-expansion-panel { + background-color: mat-color($mat-blue-grey, 800); +} + +// Active top nav +nav { + a { + line-height: 4; + display: block; + &:not(.active) { + color: rgba(255, 255, 255, 0.56); + } + &.active { + color: mat-color($accent); + border-bottom: 1px solid mat-color($accent); + } + } +} \ No newline at end of file diff --git a/yarn.lock b/yarn.lock index 724e714daa..a9614f8622 100644 --- a/yarn.lock +++ b/yarn.lock @@ -2,16 +2,18 @@ # yarn lockfile v1 -"@angular/animations@^4.1.0": - version "4.1.2" - resolved "https://registry.yarnpkg.com/@angular/animations/-/animations-4.1.2.tgz#3371596e736b7d240e200477d0dd8c5929352124" +"@angular/animations@^4.2.0": + version "4.2.0" + resolved "https://registry.yarnpkg.com/@angular/animations/-/animations-4.2.0.tgz#e964fc56c9621f28679f24d5e69026e2d1571425" + dependencies: + tslib "^1.7.1" -"@angular/cli@1.0.3": - version "1.0.3" - resolved "https://registry.yarnpkg.com/@angular/cli/-/cli-1.0.3.tgz#73a4b43f2ea8e720f52f1041e5e833cae1fb291f" +"@angular/cli@1.1.1": + version "1.1.1" + resolved "https://registry.yarnpkg.com/@angular/cli/-/cli-1.1.1.tgz#ee5cf7637ad859c08e8a5e7a7f2161d0e74ce7a5" dependencies: - "@ngtools/json-schema" "1.0.9" - "@ngtools/webpack" "1.3.1" + "@ngtools/json-schema" "1.1.0" + "@ngtools/webpack" "1.4.1" autoprefixer "^6.5.3" chalk "^1.1.3" common-tags "^1.3.1" @@ -34,11 +36,10 @@ isbinaryfile "^3.0.0" istanbul-instrumenter-loader "^2.0.0" json-loader "^0.5.4" - karma-sourcemap-loader "^0.3.7" - karma-webpack "^2.0.0" less "^2.7.2" less-loader "^4.0.2" lodash "^4.11.1" + memory-fs "^0.4.1" minimatch "^3.0.3" node-modules-path "^1.0.0" nopt "^4.0.1" @@ -55,89 +56,111 @@ script-loader "^0.7.0" semver "^5.1.0" silent-error "^1.0.0" - source-map-loader "^0.1.5" + source-map-loader "^0.2.0" style-loader "^0.13.1" stylus "^0.54.5" stylus-loader "^3.0.1" temp "0.8.3" - typescript ">=2.0.0 <2.3.0" + typescript ">=2.0.0 <2.4.0" url-loader "^0.5.7" walk-sync "^0.3.1" - webpack "~2.2.0" - webpack-dev-server "~2.4.2" + webpack "~2.4.0" + webpack-dev-middleware "^1.10.2" + webpack-dev-server "~2.4.5" webpack-merge "^2.4.0" zone.js "^0.8.4" optionalDependencies: node-sass "^4.3.0" -"@angular/common@^4.1.0": - version "4.1.2" - resolved "https://registry.yarnpkg.com/@angular/common/-/common-4.1.2.tgz#8f6d0496c204210bfe255feb437a72253f06984d" +"@angular/common@^4.2.0": + version "4.2.0" + resolved "https://registry.yarnpkg.com/@angular/common/-/common-4.2.0.tgz#5df34718bcefc49918bfcb2683f6c19720b66a61" + dependencies: + tslib "^1.7.1" -"@angular/compiler-cli@^4.1.0": - version "4.1.2" - resolved "https://registry.yarnpkg.com/@angular/compiler-cli/-/compiler-cli-4.1.2.tgz#b65ba8980330c048702aed242a956daf0251f02a" +"@angular/compiler-cli@^4.2.0": + version "4.2.0" + resolved "https://registry.yarnpkg.com/@angular/compiler-cli/-/compiler-cli-4.2.0.tgz#bd6f6b71f003df48a8f86184a8c16533afdf23ec" dependencies: - "@angular/tsc-wrapped" "4.1.2" + "@angular/tsc-wrapped" "4.2.0" minimist "^1.2.0" reflect-metadata "^0.1.2" -"@angular/compiler@^4.1.0": - version "4.1.2" - resolved "https://registry.yarnpkg.com/@angular/compiler/-/compiler-4.1.2.tgz#09542381162fd8dd962d84559498ce69a05071ea" +"@angular/compiler@^4.2.0": + version "4.2.0" + resolved "https://registry.yarnpkg.com/@angular/compiler/-/compiler-4.2.0.tgz#a21df81995b210f822ffd70b57247d474876fbed" + dependencies: + tslib "^1.7.1" -"@angular/core@^4.1.0": - version "4.1.2" - resolved "https://registry.yarnpkg.com/@angular/core/-/core-4.1.2.tgz#37b5c040b9dd37003499aea04319d699e3870596" +"@angular/core@^4.2.0": + version "4.2.0" + resolved "https://registry.yarnpkg.com/@angular/core/-/core-4.2.0.tgz#8bf57d01379c2a9e29476ad569dec9e20d5b17dc" + dependencies: + tslib "^1.7.1" -"@angular/forms@^4.1.0": - version "4.1.2" - resolved "https://registry.yarnpkg.com/@angular/forms/-/forms-4.1.2.tgz#82983e9ec5d0833e7ae14beb8e47dd357c88f490" +"@angular/forms@^4.2.0": + version "4.2.0" + resolved "https://registry.yarnpkg.com/@angular/forms/-/forms-4.2.0.tgz#cb3ae69172e254452fa77578605ebc1bb72138c9" + dependencies: + tslib "^1.7.1" -"@angular/http@^4.1.0": - version "4.1.2" - resolved "https://registry.yarnpkg.com/@angular/http/-/http-4.1.2.tgz#fc378c3330c0410e1fb8aac2546329a6887776e4" +"@angular/http@^4.2.0": + version "4.2.0" + resolved "https://registry.yarnpkg.com/@angular/http/-/http-4.2.0.tgz#484af53639e04a68834c5167a1955d2d0cde8e1c" + dependencies: + tslib "^1.7.1" -"@angular/language-service@^4.1.0": - version "4.1.2" - resolved "https://registry.yarnpkg.com/@angular/language-service/-/language-service-4.1.2.tgz#438019426beb12178c3432b7eda55ad35fa8d1aa" +"@angular/language-service@^4.2.0": + version "4.2.0" + resolved "https://registry.yarnpkg.com/@angular/language-service/-/language-service-4.2.0.tgz#4bec4b43af3ed866b994fdac5dc2ca96654fa361" + dependencies: + tslib "^1.7.1" -"@angular/material@2.0.0-beta.5": - version "2.0.0-beta.5" - resolved "https://registry.yarnpkg.com/@angular/material/-/material-2.0.0-beta.5.tgz#712141ebfa77e3ace3ec8e32b5953b355e773965" +"@angular/material@2.0.0-beta.6": + version "2.0.0-beta.6" + resolved "https://registry.yarnpkg.com/@angular/material/-/material-2.0.0-beta.6.tgz#83bfdf00f540a8c7db900a1e7b8ed2cff49df821" + dependencies: + tslib "^1.7.1" -"@angular/platform-browser-dynamic@^4.1.0": - version "4.1.2" - resolved "https://registry.yarnpkg.com/@angular/platform-browser-dynamic/-/platform-browser-dynamic-4.1.2.tgz#d241c61792c794bec627ab64b31a66bea22abb9f" +"@angular/platform-browser-dynamic@^4.2.0": + version "4.2.0" + resolved "https://registry.yarnpkg.com/@angular/platform-browser-dynamic/-/platform-browser-dynamic-4.2.0.tgz#b84c05616bd824e15b52b2b85c47b58b25d0158a" + dependencies: + tslib "^1.7.1" -"@angular/platform-browser@^4.1.0": - version "4.1.2" - resolved "https://registry.yarnpkg.com/@angular/platform-browser/-/platform-browser-4.1.2.tgz#16e50a8f75b4d675c9e2903e499e0fe4c6a125ac" +"@angular/platform-browser@^4.2.0": + version "4.2.0" + resolved "https://registry.yarnpkg.com/@angular/platform-browser/-/platform-browser-4.2.0.tgz#dfd782e7ebacba1bbe2ae0556d5d7fb012f2a6cd" + dependencies: + tslib "^1.7.1" -"@angular/platform-server@^4.1.0": - version "4.1.2" - resolved "https://registry.yarnpkg.com/@angular/platform-server/-/platform-server-4.1.2.tgz#3ef2206a59fd2d138d267aad101a50d3d806e39c" +"@angular/platform-server@^4.2.0": + version "4.2.0" + resolved "https://registry.yarnpkg.com/@angular/platform-server/-/platform-server-4.2.0.tgz#90add7fcd9c4f568a31058c9d93a9aca09eb4c58" dependencies: parse5 "^3.0.1" + tslib "^1.7.1" xhr2 "^0.1.4" -"@angular/router@^4.1.0": - version "4.1.2" - resolved "https://registry.yarnpkg.com/@angular/router/-/router-4.1.2.tgz#31b1b126fec2e1c32f4557ef8eb605536adccb27" +"@angular/router@^4.2.0": + version "4.2.0" + resolved "https://registry.yarnpkg.com/@angular/router/-/router-4.2.0.tgz#7cda9a23621ee41b466eced8bb4cbb62237ba6b9" + dependencies: + tslib "^1.7.1" -"@angular/tsc-wrapped@4.1.2": - version "4.1.2" - resolved "https://registry.yarnpkg.com/@angular/tsc-wrapped/-/tsc-wrapped-4.1.2.tgz#26cb145a67b9b80f5dda7874c4f0b1f1e173927d" +"@angular/tsc-wrapped@4.2.0": + version "4.2.0" + resolved "https://registry.yarnpkg.com/@angular/tsc-wrapped/-/tsc-wrapped-4.2.0.tgz#e62ce9953c27ba96e4c6daf117f10e31169ccea2" dependencies: tsickle "^0.21.0" -"@ngtools/json-schema@1.0.9": - version "1.0.9" - resolved "https://registry.yarnpkg.com/@ngtools/json-schema/-/json-schema-1.0.9.tgz#19e46db409c66b4c43841eab514ff9640871affc" +"@ngtools/json-schema@1.1.0": + version "1.1.0" + resolved "https://registry.yarnpkg.com/@ngtools/json-schema/-/json-schema-1.1.0.tgz#c3a0c544d62392acc2813a42c8a0dc6f58f86922" -"@ngtools/webpack@1.3.1": - version "1.3.1" - resolved "https://registry.yarnpkg.com/@ngtools/webpack/-/webpack-1.3.1.tgz#12149b6b9cb3bf858f4b2ae9650456e17674d2eb" +"@ngtools/webpack@1.4.1": + version "1.4.1" + resolved "https://registry.yarnpkg.com/@ngtools/webpack/-/webpack-1.4.1.tgz#6d498f21cd1afc027b8b746d8524a7f4e91e1dab" dependencies: enhanced-resolve "^3.1.0" loader-utils "^1.0.2" @@ -165,8 +188,8 @@ resolved "https://registry.yarnpkg.com/@types/jasmine/-/jasmine-2.5.38.tgz#a4379124c4921d4e21de54ec74669c9e9b356717" "@types/node@^6.0.46", "@types/node@~6.0.60": - version "6.0.73" - resolved "https://registry.yarnpkg.com/@types/node/-/node-6.0.73.tgz#85dc4bb6f125377c75ddd2519a1eeb63f0a4ed70" + version "6.0.78" + resolved "https://registry.yarnpkg.com/@types/node/-/node-6.0.78.tgz#5d4a3f579c1524e01ee21bf474e6fba09198f470" "@types/q@^0.0.32": version "0.0.32" @@ -197,9 +220,13 @@ acorn@^3.2.0: version "3.3.0" resolved "https://registry.yarnpkg.com/acorn/-/acorn-3.3.0.tgz#45e37fb39e8da3f25baee3ff5369e2bb5f22017a" -acorn@^4.0.3, acorn@^4.0.4: - version "4.0.11" - resolved "https://registry.yarnpkg.com/acorn/-/acorn-4.0.11.tgz#edcda3bd937e7556410d42ed5860f67399c794c0" +acorn@^4.0.3: + version "4.0.13" + resolved "https://registry.yarnpkg.com/acorn/-/acorn-4.0.13.tgz#105495ae5361d697bd195c825192e1ad7f253787" + +acorn@^5.0.0: + version "5.0.3" + resolved "https://registry.yarnpkg.com/acorn/-/acorn-5.0.3.tgz#c460df08491463f028ccb82eab3730bf01087b3d" adm-zip@0.4.4: version "0.4.4" @@ -214,8 +241,8 @@ after@0.8.2: resolved "https://registry.yarnpkg.com/after/-/after-0.8.2.tgz#fedb394f9f0e02aa9768e702bda23b505fae7e1f" agent-base@2: - version "2.0.1" - resolved "https://registry.yarnpkg.com/agent-base/-/agent-base-2.0.1.tgz#bd8f9e86a8eb221fffa07bd14befd55df142815e" + version "2.1.1" + resolved "https://registry.yarnpkg.com/agent-base/-/agent-base-2.1.1.tgz#d6de10d5af6132d5bd692427d46fc538539094c7" dependencies: extend "~3.0.0" semver "~5.0.1" @@ -224,13 +251,20 @@ ajv-keywords@^1.1.1: version "1.5.1" resolved "https://registry.yarnpkg.com/ajv-keywords/-/ajv-keywords-1.5.1.tgz#314dd0a4b3368fad3dfcdc54ede6171b886daf3c" -ajv@^4.11.2, ajv@^4.7.0, ajv@^4.9.1: +ajv@^4.7.0, ajv@^4.9.1: version "4.11.8" resolved "https://registry.yarnpkg.com/ajv/-/ajv-4.11.8.tgz#82ffb02b29e662ae53bdc20af15947706739c536" dependencies: co "^4.6.0" json-stable-stringify "^1.0.1" +ajv@^5.0.0: + version "5.1.5" + resolved "https://registry.yarnpkg.com/ajv/-/ajv-5.1.5.tgz#8734931b601f00d4feef7c65738d77d1b65d1f68" + dependencies: + co "^4.6.0" + json-stable-stringify "^1.0.1" + align-text@^0.1.1, align-text@^0.1.3: version "0.1.4" resolved "https://registry.yarnpkg.com/align-text/-/align-text-0.1.4.tgz#0cd90a561093f35d0a99256c22b7069433fad117" @@ -253,9 +287,9 @@ ansi-cyan@^0.1.1: dependencies: ansi-wrap "0.1.0" -ansi-escapes@^1.1.0: - version "1.4.0" - resolved "https://registry.yarnpkg.com/ansi-escapes/-/ansi-escapes-1.4.0.tgz#d3a8a83b319aa67793662b13e761c7911422306e" +ansi-escapes@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/ansi-escapes/-/ansi-escapes-2.0.0.tgz#5bae52be424878dd9783e8910e3fc2922e83c81b" ansi-html@0.0.7: version "0.0.7" @@ -301,8 +335,8 @@ append-transform@^0.4.0: default-require-extensions "^1.0.0" aproba@^1.0.3: - version "1.1.1" - resolved "https://registry.yarnpkg.com/aproba/-/aproba-1.1.1.tgz#95d3600f07710aa0e9298c726ad5ecf2eacbabab" + version "1.1.2" + resolved "https://registry.yarnpkg.com/aproba/-/aproba-1.1.2.tgz#45c6629094de4e96f693ef7eab74ae079c240fc1" archy@^1.0.0: version "1.0.0" @@ -418,7 +452,7 @@ async-foreach@^0.1.3: version "0.1.3" resolved "https://registry.yarnpkg.com/async-foreach/-/async-foreach-0.1.3.tgz#36121f845c0578172de419a97dbeb1d16ec34542" -async@^0.9.0, async@~0.9.0: +async@^0.9.0: version "0.9.2" resolved "https://registry.yarnpkg.com/async/-/async-0.9.2.tgz#aea74d5e61c1f899613bf64bda66d4c78f2fd17d" @@ -427,8 +461,8 @@ async@^1.4.0, async@^1.5.2: resolved "https://registry.yarnpkg.com/async/-/async-1.5.2.tgz#ec6a61ae56480c0c3cb241c95618e20892f9672a" async@^2.1.2, async@^2.1.4, async@^2.1.5: - version "2.4.0" - resolved "https://registry.yarnpkg.com/async/-/async-2.4.0.tgz#4990200f18ea5b837c2cc4f8c031a6985c385611" + version "2.4.1" + resolved "https://registry.yarnpkg.com/async/-/async-2.4.1.tgz#62a56b279c98a11d0987096a01cc3eeb8eb7bbd7" dependencies: lodash "^4.14.0" @@ -468,12 +502,12 @@ babel-code-frame@^6.11.0, babel-code-frame@^6.22.0: js-tokens "^3.0.0" babel-generator@^6.18.0: - version "6.24.1" - resolved "https://registry.yarnpkg.com/babel-generator/-/babel-generator-6.24.1.tgz#e715f486c58ded25649d888944d52aa07c5d9497" + version "6.25.0" + resolved "https://registry.yarnpkg.com/babel-generator/-/babel-generator-6.25.0.tgz#33a1af70d5f2890aeb465a4a7793c1df6a9ea9fc" dependencies: babel-messages "^6.23.0" babel-runtime "^6.22.0" - babel-types "^6.24.1" + babel-types "^6.25.0" detect-indent "^4.0.0" jsesc "^1.3.0" lodash "^4.2.0" @@ -494,41 +528,41 @@ babel-runtime@^6.18.0, babel-runtime@^6.22.0: regenerator-runtime "^0.10.0" babel-template@^6.16.0: - version "6.24.1" - resolved "https://registry.yarnpkg.com/babel-template/-/babel-template-6.24.1.tgz#04ae514f1f93b3a2537f2a0f60a5a45fb8308333" + version "6.25.0" + resolved "https://registry.yarnpkg.com/babel-template/-/babel-template-6.25.0.tgz#665241166b7c2aa4c619d71e192969552b10c071" dependencies: babel-runtime "^6.22.0" - babel-traverse "^6.24.1" - babel-types "^6.24.1" - babylon "^6.11.0" + babel-traverse "^6.25.0" + babel-types "^6.25.0" + babylon "^6.17.2" lodash "^4.2.0" -babel-traverse@^6.18.0, babel-traverse@^6.24.1: - version "6.24.1" - resolved "https://registry.yarnpkg.com/babel-traverse/-/babel-traverse-6.24.1.tgz#ab36673fd356f9a0948659e7b338d5feadb31695" +babel-traverse@^6.18.0, babel-traverse@^6.25.0: + version "6.25.0" + resolved "https://registry.yarnpkg.com/babel-traverse/-/babel-traverse-6.25.0.tgz#2257497e2fcd19b89edc13c4c91381f9512496f1" dependencies: babel-code-frame "^6.22.0" babel-messages "^6.23.0" babel-runtime "^6.22.0" - babel-types "^6.24.1" - babylon "^6.15.0" + babel-types "^6.25.0" + babylon "^6.17.2" debug "^2.2.0" globals "^9.0.0" invariant "^2.2.0" lodash "^4.2.0" -babel-types@^6.18.0, babel-types@^6.24.1: - version "6.24.1" - resolved "https://registry.yarnpkg.com/babel-types/-/babel-types-6.24.1.tgz#a136879dc15b3606bda0d90c1fc74304c2ff0975" +babel-types@^6.18.0, babel-types@^6.25.0: + version "6.25.0" + resolved "https://registry.yarnpkg.com/babel-types/-/babel-types-6.25.0.tgz#70afb248d5660e5d18f811d91c8303b54134a18e" dependencies: babel-runtime "^6.22.0" esutils "^2.0.2" lodash "^4.2.0" to-fast-properties "^1.0.1" -babylon@^6.11.0, babylon@^6.13.0, babylon@^6.15.0: - version "6.17.1" - resolved "https://registry.yarnpkg.com/babylon/-/babylon-6.17.1.tgz#17f14fddf361b695981fe679385e4f1c01ebd86f" +babylon@^6.13.0, babylon@^6.17.2: + version "6.17.2" + resolved "https://registry.yarnpkg.com/babylon/-/babylon-6.17.2.tgz#201d25ef5f892c41bae49488b08db0dd476e9f5c" backo2@1.0.2: version "1.0.2" @@ -550,9 +584,9 @@ base64id@1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/base64id/-/base64id-1.0.0.tgz#47688cb99bb6804f0e06d3e763b1c32e57d8e6b6" -batch@0.5.3: - version "0.5.3" - resolved "https://registry.yarnpkg.com/batch/-/batch-0.5.3.tgz#3f3414f380321743bfc1042f9a83ff1d5824d464" +batch@0.6.1: + version "0.6.1" + resolved "https://registry.yarnpkg.com/batch/-/batch-0.6.1.tgz#dc34314f4e679318093fc760272525f94bf25c16" bcrypt-pbkdf@^1.0.0: version "1.0.1" @@ -603,19 +637,19 @@ bn.js@^4.0.0, bn.js@^4.1.0, bn.js@^4.1.1, bn.js@^4.4.0: resolved "https://registry.yarnpkg.com/bn.js/-/bn.js-4.11.6.tgz#53344adb14617a13f6e8dd2ce28905d1c0ba3215" body-parser@^1.12.4: - version "1.17.1" - resolved "https://registry.yarnpkg.com/body-parser/-/body-parser-1.17.1.tgz#75b3bc98ddd6e7e0d8ffe750dfaca5c66993fa47" + version "1.17.2" + resolved "https://registry.yarnpkg.com/body-parser/-/body-parser-1.17.2.tgz#f8892abc8f9e627d42aedafbca66bf5ab99104ee" dependencies: bytes "2.4.0" content-type "~1.0.2" - debug "2.6.1" + debug "2.6.7" depd "~1.1.0" http-errors "~1.6.1" iconv-lite "0.4.15" on-finished "~2.3.0" qs "6.4.0" raw-body "~2.2.0" - type-is "~1.6.14" + type-is "~1.6.15" boolbase@~1.0.0: version "1.0.0" @@ -716,10 +750,6 @@ browserslist@^1.3.6, browserslist@^1.5.2, browserslist@^1.7.6: caniuse-db "^1.0.30000639" electron-to-chromium "^1.2.7" -buffer-shims@~1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/buffer-shims/-/buffer-shims-1.0.0.tgz#9978ce317388c649ad8793028c3477ef044a8b51" - buffer-xor@^1.0.2: version "1.0.3" resolved "https://registry.yarnpkg.com/buffer-xor/-/buffer-xor-1.0.3.tgz#26e61ed1422fb70dd42e6e36729ed51d855fe8d9" @@ -795,8 +825,8 @@ caniuse-api@^1.5.2: lodash.uniq "^4.5.0" caniuse-db@^1.0.30000529, caniuse-db@^1.0.30000634, caniuse-db@^1.0.30000639: - version "1.0.30000668" - resolved "https://registry.yarnpkg.com/caniuse-db/-/caniuse-db-1.0.30000668.tgz#0999d376c8335a699cc98f10520afcc86fe1c0f1" + version "1.0.30000680" + resolved "https://registry.yarnpkg.com/caniuse-db/-/caniuse-db-1.0.30000680.tgz#d76ebeaaeb82e3d9952bfdc5c231c4f83cd48144" caseless@~0.11.0: version "0.11.0" @@ -850,9 +880,9 @@ clap@^1.0.9: dependencies: chalk "^1.1.3" -clean-css@4.0.x: - version "4.0.13" - resolved "https://registry.yarnpkg.com/clean-css/-/clean-css-4.0.13.tgz#feb2a176062d72a6c3e624d9213cac6a0c485e80" +clean-css@4.1.x: + version "4.1.3" + resolved "https://registry.yarnpkg.com/clean-css/-/clean-css-4.1.3.tgz#07cfe8980edb20d455ddc23aadcf1e04c6e509ce" dependencies: source-map "0.5.x" @@ -913,8 +943,8 @@ co@^4.6.0: resolved "https://registry.yarnpkg.com/co/-/co-4.6.0.tgz#6ea6bdf3d853ae54ccb8e47bfa0bf3f9031fb184" coa@~1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/coa/-/coa-1.0.1.tgz#7f959346cfc8719e3f7233cd6852854a7c67d8a3" + version "1.0.2" + resolved "https://registry.yarnpkg.com/coa/-/coa-1.0.2.tgz#2ba9fec3b4aa43d7a49d7e6c3561e92061b6bcec" dependencies: q "^1.1.2" @@ -981,7 +1011,7 @@ combined-stream@^1.0.5, combined-stream@~1.0.5: dependencies: delayed-stream "~1.0.0" -commander@2, commander@2.9.x, commander@^2.9.0: +commander@2, commander@2.9.x, commander@^2.9.0, commander@~2.9.0: version "2.9.0" resolved "https://registry.yarnpkg.com/commander/-/commander-2.9.0.tgz#9c99094176e12240cb22d6c5146098400fe0f7d4" dependencies: @@ -1043,11 +1073,11 @@ connect-history-api-fallback@^1.3.0: resolved "https://registry.yarnpkg.com/connect-history-api-fallback/-/connect-history-api-fallback-1.3.0.tgz#e51d17f8f0ef0db90a64fdb47de3051556e9f169" connect@^3.3.5: - version "3.6.1" - resolved "https://registry.yarnpkg.com/connect/-/connect-3.6.1.tgz#b7760693a74f0454face1d9378edb3f885b43227" + version "3.6.2" + resolved "https://registry.yarnpkg.com/connect/-/connect-3.6.2.tgz#694e8d20681bfe490282c8ab886be98f09f42fe7" dependencies: - debug "2.6.3" - finalhandler "1.0.1" + debug "2.6.7" + finalhandler "1.0.3" parseurl "~1.3.1" utils-merge "1.0.0" @@ -1175,12 +1205,13 @@ css-color-names@0.0.4: resolved "https://registry.yarnpkg.com/css-color-names/-/css-color-names-0.0.4.tgz#808adc2e79cf84738069b646cb20ec27beb629e0" css-loader@^0.28.1: - version "0.28.1" - resolved "https://registry.yarnpkg.com/css-loader/-/css-loader-0.28.1.tgz#220325599f8f00452d9ceb4c3ca6c8a66798642d" + version "0.28.4" + resolved "https://registry.yarnpkg.com/css-loader/-/css-loader-0.28.4.tgz#6cf3579192ce355e8b38d5f42dd7a1f2ec898d0f" dependencies: babel-code-frame "^6.11.0" css-selector-tokenizer "^0.7.0" cssnano ">=2.6.1 <4" + icss-utils "^2.1.0" loader-utils "^1.0.2" lodash.camelcase "^4.3.0" object-assign "^4.0.1" @@ -1205,14 +1236,6 @@ css-select@^1.1.0: domutils "1.5.1" nth-check "~1.0.1" -css-selector-tokenizer@^0.6.0: - version "0.6.0" - resolved "https://registry.yarnpkg.com/css-selector-tokenizer/-/css-selector-tokenizer-0.6.0.tgz#6445f582c7930d241dcc5007a43d6fcb8f073152" - dependencies: - cssesc "^0.1.0" - fastparse "^1.1.1" - regexpu-core "^1.0.0" - css-selector-tokenizer@^0.7.0: version "0.7.0" resolved "https://registry.yarnpkg.com/css-selector-tokenizer/-/css-selector-tokenizer-0.7.0.tgz#e6988474ae8c953477bf5e7efecfceccd9cf4c86" @@ -1289,13 +1312,13 @@ custom-event@~1.0.0: version "1.0.1" resolved "https://registry.yarnpkg.com/custom-event/-/custom-event-1.0.1.tgz#5d02a46850adf1b4a317946a3928fccb5bfd0425" -d3-array@1, d3-array@1.2.0: +d3-array@1, d3-array@1.2.0, d3-array@^1.2.0: version "1.2.0" resolved "https://registry.yarnpkg.com/d3-array/-/d3-array-1.2.0.tgz#147d269720e174c4057a7f42be8b0f3f2ba53108" -d3-axis@1.0.6: - version "1.0.6" - resolved "https://registry.yarnpkg.com/d3-axis/-/d3-axis-1.0.6.tgz#dccbc21a73e5786de820bf1a22b237f522b878be" +d3-axis@1.0.7: + version "1.0.7" + resolved "https://registry.yarnpkg.com/d3-axis/-/d3-axis-1.0.7.tgz#048433d307061f62d1d248e2930c01d7b6738cd8" d3-brush@1.0.4: version "1.0.4" @@ -1326,9 +1349,9 @@ d3-dispatch@1, d3-dispatch@1.0.3: version "1.0.3" resolved "https://registry.yarnpkg.com/d3-dispatch/-/d3-dispatch-1.0.3.tgz#46e1491eaa9b58c358fce5be4e8bed626e7871f8" -d3-drag@1, d3-drag@1.0.4: - version "1.0.4" - resolved "https://registry.yarnpkg.com/d3-drag/-/d3-drag-1.0.4.tgz#a9c1609f11dd5530ae275ebd64377ec54efb9d8f" +d3-drag@1, d3-drag@1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/d3-drag/-/d3-drag-1.1.0.tgz#4a49b4d77a42e9e3d5a0ef3b492b14aaa2e5a733" dependencies: d3-dispatch "1" d3-selection "1" @@ -1358,9 +1381,9 @@ d3-format@1, d3-format@1.2.0: version "1.2.0" resolved "https://registry.yarnpkg.com/d3-format/-/d3-format-1.2.0.tgz#6b480baa886885d4651dc248a8f4ac9da16db07a" -d3-geo@1.6.3: - version "1.6.3" - resolved "https://registry.yarnpkg.com/d3-geo/-/d3-geo-1.6.3.tgz#21683a43a061eaba21a7f254b51d5937eb640756" +d3-geo@1.6.4: + version "1.6.4" + resolved "https://registry.yarnpkg.com/d3-geo/-/d3-geo-1.6.4.tgz#f20e1e461cb1845f5a8be55ab6f876542a7e3199" dependencies: d3-array "1" @@ -1368,9 +1391,9 @@ d3-hierarchy@1.1.4: version "1.1.4" resolved "https://registry.yarnpkg.com/d3-hierarchy/-/d3-hierarchy-1.1.4.tgz#96c3942f3f21cf997a11b4edf00dde2a77b4c6d0" -d3-interpolate@1, d3-interpolate@1.1.4: - version "1.1.4" - resolved "https://registry.yarnpkg.com/d3-interpolate/-/d3-interpolate-1.1.4.tgz#a43ec5b3bee350d8516efdf819a4c08c053db302" +d3-interpolate@1, d3-interpolate@1.1.5: + version "1.1.5" + resolved "https://registry.yarnpkg.com/d3-interpolate/-/d3-interpolate-1.1.5.tgz#69e099ff39214716e563c9aec3ea9d1ea4b8a79f" dependencies: d3-color "1" @@ -1386,13 +1409,13 @@ d3-quadtree@1, d3-quadtree@1.0.3: version "1.0.3" resolved "https://registry.yarnpkg.com/d3-quadtree/-/d3-quadtree-1.0.3.tgz#ac7987e3e23fe805a990f28e1b50d38fcb822438" -d3-queue@3.0.5: - version "3.0.5" - resolved "https://registry.yarnpkg.com/d3-queue/-/d3-queue-3.0.5.tgz#0ceffe1f131c459b13b9f69f1056b41dfc33c00d" +d3-queue@3.0.7: + version "3.0.7" + resolved "https://registry.yarnpkg.com/d3-queue/-/d3-queue-3.0.7.tgz#c93a2e54b417c0959129d7d73f6cf7d4292e7618" -d3-random@1.0.3: - version "1.0.3" - resolved "https://registry.yarnpkg.com/d3-random/-/d3-random-1.0.3.tgz#6526c844aa5e7c457e29ddacd6f2734f845b42c1" +d3-random@1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/d3-random/-/d3-random-1.1.0.tgz#6642e506c6fa3a648595d2b2469788a8d12529d3" d3-request@1.0.5: version "1.0.5" @@ -1403,11 +1426,11 @@ d3-request@1.0.5: d3-dsv "1" xmlhttprequest "1" -d3-scale@1.0.5: - version "1.0.5" - resolved "https://registry.yarnpkg.com/d3-scale/-/d3-scale-1.0.5.tgz#418506f0fb18eb052b385e196398acc2a4134858" +d3-scale@1.0.6: + version "1.0.6" + resolved "https://registry.yarnpkg.com/d3-scale/-/d3-scale-1.0.6.tgz#bce19da80d3a0cf422c9543ae3322086220b34ed" dependencies: - d3-array "1" + d3-array "^1.2.0" d3-collection "1" d3-color "1" d3-format "1" @@ -1415,13 +1438,13 @@ d3-scale@1.0.5: d3-time "1" d3-time-format "2" -d3-selection@1, d3-selection@1.0.5: - version "1.0.5" - resolved "https://registry.yarnpkg.com/d3-selection/-/d3-selection-1.0.5.tgz#948c73b41a44e28d1742ae2ff207c2aebca2734b" +d3-selection@1, d3-selection@1.1.0, d3-selection@^1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/d3-selection/-/d3-selection-1.1.0.tgz#1998684896488f839ca0372123da34f1d318809c" -d3-shape@1.0.6: - version "1.0.6" - resolved "https://registry.yarnpkg.com/d3-shape/-/d3-shape-1.0.6.tgz#b09e305cf0c7c6b9a98c90e6b42f62dac4bcfd5b" +d3-shape@1.1.1: + version "1.1.1" + resolved "https://registry.yarnpkg.com/d3-shape/-/d3-shape-1.1.1.tgz#50a1037e48a79f5b8fd9d58cde52799aeb1f7723" dependencies: d3-path "1" @@ -1439,24 +1462,24 @@ d3-timer@1, d3-timer@1.0.5: version "1.0.5" resolved "https://registry.yarnpkg.com/d3-timer/-/d3-timer-1.0.5.tgz#b266d476c71b0d269e7ac5f352b410a3b6fe6ef0" -d3-transition@1, d3-transition@1.0.4: - version "1.0.4" - resolved "https://registry.yarnpkg.com/d3-transition/-/d3-transition-1.0.4.tgz#e1a9ebae3869a9d9c2874ab00841fa8313ae5de5" +d3-transition@1, d3-transition@1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/d3-transition/-/d3-transition-1.1.0.tgz#cfc85c74e5239324290546623572990560c3966f" dependencies: d3-color "1" d3-dispatch "1" d3-ease "1" d3-interpolate "1" - d3-selection "1" + d3-selection "^1.1.0" d3-timer "1" d3-voronoi@1.1.2: version "1.1.2" resolved "https://registry.yarnpkg.com/d3-voronoi/-/d3-voronoi-1.1.2.tgz#1687667e8f13a2d158c80c1480c5a29cb0d8973c" -d3-zoom@1.1.4: - version "1.1.4" - resolved "https://registry.yarnpkg.com/d3-zoom/-/d3-zoom-1.1.4.tgz#903fd2c988b5cace43f00dcf7aae09470c9cc12d" +d3-zoom@1.2.0: + version "1.2.0" + resolved "https://registry.yarnpkg.com/d3-zoom/-/d3-zoom-1.2.0.tgz#b3231f4f9386241475defe1c557bfd3fde1065fb" dependencies: d3-dispatch "1" d3-drag "1" @@ -1465,39 +1488,39 @@ d3-zoom@1.1.4: d3-transition "1" d3@^4.4.0: - version "4.8.0" - resolved "https://registry.yarnpkg.com/d3/-/d3-4.8.0.tgz#1ad8d18997869c90b6ad6114e9b92425cee78460" + version "4.9.1" + resolved "https://registry.yarnpkg.com/d3/-/d3-4.9.1.tgz#f860be9252261a3c14eea64b1d2590d14f4db838" dependencies: d3-array "1.2.0" - d3-axis "1.0.6" + d3-axis "1.0.7" d3-brush "1.0.4" d3-chord "1.0.4" d3-collection "1.0.3" d3-color "1.0.3" d3-dispatch "1.0.3" - d3-drag "1.0.4" + d3-drag "1.1.0" d3-dsv "1.0.5" d3-ease "1.0.3" d3-force "1.0.6" d3-format "1.2.0" - d3-geo "1.6.3" + d3-geo "1.6.4" d3-hierarchy "1.1.4" - d3-interpolate "1.1.4" + d3-interpolate "1.1.5" d3-path "1.0.5" d3-polygon "1.0.3" d3-quadtree "1.0.3" - d3-queue "3.0.5" - d3-random "1.0.3" + d3-queue "3.0.7" + d3-random "1.1.0" d3-request "1.0.5" - d3-scale "1.0.5" - d3-selection "1.0.5" - d3-shape "1.0.6" + d3-scale "1.0.6" + d3-selection "1.1.0" + d3-shape "1.1.1" d3-time "1.0.6" d3-time-format "2.0.5" d3-timer "1.0.5" - d3-transition "1.0.4" + d3-transition "1.1.0" d3-voronoi "1.1.2" - d3-zoom "1.1.4" + d3-zoom "1.2.0" dashdash@^1.12.0: version "1.14.1" @@ -1516,11 +1539,11 @@ dateformat@^1.0.11: get-stdin "^4.0.1" meow "^3.3.0" -debug@*, debug@2, debug@^2.1.3, debug@^2.2.0, debug@^2.6.3: - version "2.6.6" - resolved "https://registry.yarnpkg.com/debug/-/debug-2.6.6.tgz#a9fa6fbe9ca43cf1e79f73b75c0189cbb7d6db5a" +debug@*, debug@2, debug@2.6.8, debug@^2.1.3, debug@^2.2.0, debug@^2.6.3, debug@^2.6.8: + version "2.6.8" + resolved "https://registry.yarnpkg.com/debug/-/debug-2.6.8.tgz#e731531ca2ede27d188222427da17821d68ff4fc" dependencies: - ms "0.7.3" + ms "2.0.0" debug@0.7.4: version "0.7.4" @@ -1538,17 +1561,11 @@ debug@2.3.3: dependencies: ms "0.7.2" -debug@2.6.1: - version "2.6.1" - resolved "https://registry.yarnpkg.com/debug/-/debug-2.6.1.tgz#79855090ba2c4e3115cc7d8769491d58f0491351" - dependencies: - ms "0.7.2" - -debug@2.6.3: - version "2.6.3" - resolved "https://registry.yarnpkg.com/debug/-/debug-2.6.3.tgz#0f7eb8c30965ec08c72accfa0130c8b79984141d" +debug@2.6.7: + version "2.6.7" + resolved "https://registry.yarnpkg.com/debug/-/debug-2.6.7.tgz#92bad1f6d05bbb6bba22cca88bcd0ec894c2861e" dependencies: - ms "0.7.2" + ms "2.0.0" decamelize@^1.0.0, decamelize@^1.1.1, decamelize@^1.1.2: version "1.2.0" @@ -1629,6 +1646,10 @@ detect-indent@^4.0.0: dependencies: repeating "^2.0.0" +detect-node@^2.0.3: + version "2.0.3" + resolved "https://registry.yarnpkg.com/detect-node/-/detect-node-2.0.3.tgz#a2033c09cc8e158d37748fbde7507832bd6ce127" + di@^0.0.1: version "0.0.1" resolved "https://registry.yarnpkg.com/di/-/di-0.0.1.tgz#806649326ceaa7caa3306d75d985ea2748ba913c" @@ -1732,8 +1753,8 @@ ee-first@1.1.1: resolved "https://registry.yarnpkg.com/ee-first/-/ee-first-1.1.1.tgz#590c61156b0ae2f4f0255732a158b266bc56b21d" electron-to-chromium@^1.2.7: - version "1.3.10" - resolved "https://registry.yarnpkg.com/electron-to-chromium/-/electron-to-chromium-1.3.10.tgz#63d62b785471f0d8dda85199d64579de8a449f08" + version "1.3.13" + resolved "https://registry.yarnpkg.com/electron-to-chromium/-/electron-to-chromium-1.3.13.tgz#1b3a5eace6e087bb5e257a100b0cbfe81b2891fc" elliptic@^6.0.0: version "6.4.0" @@ -1946,8 +1967,8 @@ exports-loader@^0.6.3: source-map "0.5.x" express@^4.13.3: - version "4.15.2" - resolved "https://registry.yarnpkg.com/express/-/express-4.15.2.tgz#af107fc148504457f2dca9a6f2571d7129b97b35" + version "4.15.3" + resolved "https://registry.yarnpkg.com/express/-/express-4.15.3.tgz#bab65d0f03aa80c358408972fc700f916944b662" dependencies: accepts "~1.3.3" array-flatten "1.1.1" @@ -1955,28 +1976,28 @@ express@^4.13.3: content-type "~1.0.2" cookie "0.3.1" cookie-signature "1.0.6" - debug "2.6.1" + debug "2.6.7" depd "~1.1.0" encodeurl "~1.0.1" escape-html "~1.0.3" etag "~1.8.0" - finalhandler "~1.0.0" + finalhandler "~1.0.3" fresh "0.5.0" merge-descriptors "1.0.1" methods "~1.1.2" on-finished "~2.3.0" parseurl "~1.3.1" path-to-regexp "0.1.7" - proxy-addr "~1.1.3" + proxy-addr "~1.1.4" qs "6.4.0" range-parser "~1.2.0" - send "0.15.1" - serve-static "1.12.1" + send "0.15.3" + serve-static "1.12.3" setprototypeof "1.0.3" statuses "~1.3.1" - type-is "~1.6.14" + type-is "~1.6.15" utils-merge "1.0.0" - vary "~1.1.0" + vary "~1.1.1" extend-shallow@^1.1.2: version "1.1.4" @@ -1994,10 +2015,12 @@ extend@3, extend@^3.0.0, extend@~3.0.0: version "3.0.1" resolved "https://registry.yarnpkg.com/extend/-/extend-3.0.1.tgz#a755ea7bc1adfcc5a31ce7e762dbaadc5e636444" -external-editor@^2.0.1: - version "2.0.1" - resolved "https://registry.yarnpkg.com/external-editor/-/external-editor-2.0.1.tgz#4c597c6c88fa6410e41dbbaa7b1be2336aa31095" +external-editor@^2.0.4: + version "2.0.4" + resolved "https://registry.yarnpkg.com/external-editor/-/external-editor-2.0.4.tgz#1ed9199da9cbfe2ef2f7a31b2fde8b0d12368972" dependencies: + iconv-lite "^0.4.17" + jschardet "^1.4.2" tmp "^0.0.31" extglob@^0.3.1: @@ -2007,13 +2030,13 @@ extglob@^0.3.1: is-extglob "^1.0.0" extract-text-webpack-plugin@^2.1.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/extract-text-webpack-plugin/-/extract-text-webpack-plugin-2.1.0.tgz#69315b885f876dbf96d3819f6a9f1cca7aebf159" + version "2.1.2" + resolved "https://registry.yarnpkg.com/extract-text-webpack-plugin/-/extract-text-webpack-plugin-2.1.2.tgz#756ef4efa8155c3681833fbc34da53b941746d6c" dependencies: - ajv "^4.11.2" async "^2.1.2" loader-utils "^1.0.2" - webpack-sources "^0.1.0" + schema-utils "^0.3.0" + webpack-sources "^1.0.1" extract-zip@~1.5.0: version "1.5.0" @@ -2090,11 +2113,11 @@ fill-range@^2.1.0: repeat-element "^1.1.2" repeat-string "^1.5.2" -finalhandler@1.0.1, finalhandler@~1.0.0: - version "1.0.1" - resolved "https://registry.yarnpkg.com/finalhandler/-/finalhandler-1.0.1.tgz#bcd15d1689c0e5ed729b6f7f541a6df984117db8" +finalhandler@1.0.3, finalhandler@~1.0.3: + version "1.0.3" + resolved "https://registry.yarnpkg.com/finalhandler/-/finalhandler-1.0.3.tgz#ef47e77950e999780e86022a560e3217e0d0cc89" dependencies: - debug "2.6.3" + debug "2.6.7" encodeurl "~1.0.1" escape-html "~1.0.3" on-finished "~2.3.0" @@ -2122,12 +2145,6 @@ findup-sync@^0.4.2: micromatch "^2.3.7" resolve-dir "^0.1.0" -findup-sync@~0.3.0: - version "0.3.0" - resolved "https://registry.yarnpkg.com/findup-sync/-/findup-sync-0.3.0.tgz#37930aa5d816b777c03445e1966cc6790a4c0b16" - dependencies: - glob "~5.0.0" - fined@^1.0.1: version "1.0.2" resolved "https://registry.yarnpkg.com/fined/-/fined-1.0.2.tgz#5b28424b760d7598960b7ef8480dff8ad3660e97" @@ -2381,7 +2398,7 @@ glob@^4.3.1: minimatch "^2.0.1" once "^1.3.0" -glob@^5.0.3, glob@~5.0.0: +glob@^5.0.3: version "5.0.15" resolved "https://registry.yarnpkg.com/glob/-/glob-5.0.15.tgz#1bc936b9e02f4a603fcc222ecf7633d30b8b93b1" dependencies: @@ -2402,13 +2419,13 @@ glob@^6.0.4: path-is-absolute "^1.0.0" glob@^7.0.0, glob@^7.0.3, glob@^7.0.5, glob@^7.0.6, glob@^7.1.1, glob@~7.1.1: - version "7.1.1" - resolved "https://registry.yarnpkg.com/glob/-/glob-7.1.1.tgz#805211df04faaf1c63a3600306cdf5ade50b2ec8" + version "7.1.2" + resolved "https://registry.yarnpkg.com/glob/-/glob-7.1.2.tgz#c19c9df9a028702d678612384a6552404c636d15" dependencies: fs.realpath "^1.0.0" inflight "^1.0.4" inherits "2" - minimatch "^3.0.2" + minimatch "^3.0.4" once "^1.3.0" path-is-absolute "^1.0.0" @@ -2437,8 +2454,8 @@ global-prefix@^0.1.4: which "^1.2.12" globals@^9.0.0: - version "9.17.0" - resolved "https://registry.yarnpkg.com/globals/-/globals-9.17.0.tgz#0c0ca696d9b9bb694d2e5470bd37777caad50286" + version "9.18.0" + resolved "https://registry.yarnpkg.com/globals/-/globals-9.18.0.tgz#aa3896b3e69b487f17e31ed2143d69a8e30c2d8a" globby@^5.0.0: version "5.0.0" @@ -2602,7 +2619,7 @@ hammerjs@^2.0.8: version "2.0.8" resolved "https://registry.yarnpkg.com/hammerjs/-/hammerjs-2.0.8.tgz#04ef77862cff2bb79d30f7692095930222bf60f1" -handle-thing@^1.2.4: +handle-thing@^1.2.5: version "1.2.5" resolved "https://registry.yarnpkg.com/handle-thing/-/handle-thing-1.2.5.tgz#fd7aad726bf1a5fd16dfc29b2f7a6601d27139c4" @@ -2615,8 +2632,8 @@ handlebars@^1.3.0: uglify-js "~2.3" handlebars@^4.0.3: - version "4.0.8" - resolved "https://registry.yarnpkg.com/handlebars/-/handlebars-4.0.8.tgz#22b875cd3f0e6cbea30314f144e82bc7a72ff420" + version "4.0.10" + resolved "https://registry.yarnpkg.com/handlebars/-/handlebars-4.0.10.tgz#3d30c718b09a3d96f23ea4cc1f403c4d3ba9ff4f" dependencies: async "^1.4.0" optimist "^0.6.1" @@ -2756,17 +2773,17 @@ html-entities@^1.2.0: resolved "https://registry.yarnpkg.com/html-entities/-/html-entities-1.2.1.tgz#0df29351f0721163515dfb9e5543e5f6eed5162f" html-minifier@^3.2.3: - version "3.4.4" - resolved "https://registry.yarnpkg.com/html-minifier/-/html-minifier-3.4.4.tgz#616fe3e3ef16da02b393d9a6099eeff468a35df0" + version "3.5.2" + resolved "https://registry.yarnpkg.com/html-minifier/-/html-minifier-3.5.2.tgz#d73bc3ff448942408818ce609bf3fb0ea7ef4eb7" dependencies: camel-case "3.0.x" - clean-css "4.0.x" + clean-css "4.1.x" commander "2.9.x" he "1.1.x" ncname "1.0.x" param-case "2.1.x" relateurl "0.2.x" - uglify-js "~2.8.22" + uglify-js "3.0.x" html-webpack-plugin@^2.19.0: version "2.28.0" @@ -2788,18 +2805,10 @@ htmlparser2@~3.3.0: domutils "1.1" readable-stream "1.0" -http-deceiver@^1.2.4: +http-deceiver@^1.2.7: version "1.2.7" resolved "https://registry.yarnpkg.com/http-deceiver/-/http-deceiver-1.2.7.tgz#fa7168944ab9a519d337cb0bec7284dc3e723d87" -http-errors@~1.5.0: - version "1.5.1" - resolved "https://registry.yarnpkg.com/http-errors/-/http-errors-1.5.1.tgz#788c0d2c1de2c81b9e6e8c01843b6b97eb920750" - dependencies: - inherits "2.0.3" - setprototypeof "1.0.2" - statuses ">= 1.3.1 < 2" - http-errors@~1.6.1: version "1.6.1" resolved "https://registry.yarnpkg.com/http-errors/-/http-errors-1.6.1.tgz#5f8b8ed98aca545656bf572997387f904a722257" @@ -2845,7 +2854,7 @@ https-proxy-agent@^1.0.0: debug "2" extend "3" -iconv-lite@0.4: +iconv-lite@0.4, iconv-lite@^0.4.17: version "0.4.17" resolved "https://registry.yarnpkg.com/iconv-lite/-/iconv-lite-0.4.17.tgz#4fdaa3b38acbc2c031b045d0edcdfe1ecab18c8d" @@ -2853,17 +2862,23 @@ iconv-lite@0.4.15: version "0.4.15" resolved "https://registry.yarnpkg.com/iconv-lite/-/iconv-lite-0.4.15.tgz#fe265a218ac6a57cfe854927e9d04c19825eddeb" -icss-replace-symbols@^1.0.2: - version "1.0.2" - resolved "https://registry.yarnpkg.com/icss-replace-symbols/-/icss-replace-symbols-1.0.2.tgz#cb0b6054eb3af6edc9ab1d62d01933e2d4c8bfa5" +icss-replace-symbols@^1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/icss-replace-symbols/-/icss-replace-symbols-1.1.0.tgz#06ea6f83679a7749e386cfe1fe812ae5db223ded" + +icss-utils@^2.1.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/icss-utils/-/icss-utils-2.1.0.tgz#83f0a0ec378bf3246178b6c2ad9136f135b1c962" + dependencies: + postcss "^6.0.1" ieee754@^1.1.4: version "1.1.8" resolved "https://registry.yarnpkg.com/ieee754/-/ieee754-1.1.8.tgz#be33d40ac10ef1926701f6f08a2d86fbfd1ad3e4" image-size@~0.5.0: - version "0.5.3" - resolved "https://registry.yarnpkg.com/image-size/-/image-size-0.5.3.tgz#5cbe9fafc8436386ceb7e9e3a9d90c5b71b70ad9" + version "0.5.4" + resolved "https://registry.yarnpkg.com/image-size/-/image-size-0.5.4.tgz#94e07beec0659386f1aefb84b2222e88405485cd" img-stats@^0.5.2: version "0.5.2" @@ -2917,19 +2932,20 @@ ini@^1.3.4, ini@~1.3.0: resolved "https://registry.yarnpkg.com/ini/-/ini-1.3.4.tgz#0537cb79daf59b59a1a517dff706c86ec039162e" inquirer@^3.0.0: - version "3.0.6" - resolved "https://registry.yarnpkg.com/inquirer/-/inquirer-3.0.6.tgz#e04aaa9d05b7a3cb9b0f407d04375f0447190347" + version "3.1.0" + resolved "https://registry.yarnpkg.com/inquirer/-/inquirer-3.1.0.tgz#e05400d48b94937c2d3caa7038663ba9189aab01" dependencies: - ansi-escapes "^1.1.0" + ansi-escapes "^2.0.0" chalk "^1.0.0" cli-cursor "^2.1.0" cli-width "^2.0.0" - external-editor "^2.0.1" + external-editor "^2.0.4" figures "^2.0.0" lodash "^4.3.0" mute-stream "0.0.7" run-async "^2.2.0" - rx "^4.1.0" + rx-lite "^4.0.8" + rx-lite-aggregates "^4.0.8" string-width "^2.0.0" strip-ansi "^3.0.0" through "^2.3.6" @@ -2988,8 +3004,8 @@ is-directory@^0.3.1: resolved "https://registry.yarnpkg.com/is-directory/-/is-directory-0.3.1.tgz#61339b6f2475fc772fd9c9d83f5c8575dc154ae1" is-dotfile@^1.0.0: - version "1.0.2" - resolved "https://registry.yarnpkg.com/is-dotfile/-/is-dotfile-1.0.2.tgz#2c132383f39199f8edc268ca01b9b007d205cc4d" + version "1.0.3" + resolved "https://registry.yarnpkg.com/is-dotfile/-/is-dotfile-1.0.3.tgz#a6a2f32ffd2dfb04f5ca25ecd0f6b83cf798a1e1" is-equal-shallow@^0.1.3: version "0.1.3" @@ -3077,10 +3093,10 @@ is-plain-obj@^1.0.0: resolved "https://registry.yarnpkg.com/is-plain-obj/-/is-plain-obj-1.1.0.tgz#71a50c8429dfca773c92a390a4a03b39fcd51d3e" is-plain-object@^2.0.1: - version "2.0.1" - resolved "https://registry.yarnpkg.com/is-plain-object/-/is-plain-object-2.0.1.tgz#4d7ca539bc9db9b737b8acb612f2318ef92f294f" + version "2.0.3" + resolved "https://registry.yarnpkg.com/is-plain-object/-/is-plain-object-2.0.3.tgz#c15bf3e4b66b62d72efaf2925848663ecbc619b6" dependencies: - isobject "^1.0.0" + isobject "^3.0.0" is-posix-bracket@^0.1.0: version "0.1.1" @@ -3152,32 +3168,32 @@ isexe@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/isexe/-/isexe-2.0.0.tgz#e8fbf374dc556ff8947a10dcb0572d633f2cfa10" -isobject@^1.0.0: - version "1.0.2" - resolved "https://registry.yarnpkg.com/isobject/-/isobject-1.0.2.tgz#f0f9b8ce92dd540fa0740882e3835a2e022ec78a" - isobject@^2.0.0: version "2.1.0" resolved "https://registry.yarnpkg.com/isobject/-/isobject-2.1.0.tgz#f065561096a3f1da2ef46272f815c840d87e0c89" dependencies: isarray "1.0.0" +isobject@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/isobject/-/isobject-3.0.0.tgz#39565217f3661789e8a0a0c080d5f7e6bc46e1a0" + isstream@~0.1.2: version "0.1.2" resolved "https://registry.yarnpkg.com/isstream/-/isstream-0.1.2.tgz#47e63f7af55afa6f92e1500e690eb8b8529c099a" istanbul-api@^1.1.1: - version "1.1.8" - resolved "https://registry.yarnpkg.com/istanbul-api/-/istanbul-api-1.1.8.tgz#a844e55c6f9aeee292e7f42942196f60b23dc93e" + version "1.1.9" + resolved "https://registry.yarnpkg.com/istanbul-api/-/istanbul-api-1.1.9.tgz#2827920d380d4286d857d57a2968a841db8a7ec8" dependencies: async "^2.1.4" fileset "^2.0.2" - istanbul-lib-coverage "^1.1.0" - istanbul-lib-hook "^1.0.6" - istanbul-lib-instrument "^1.7.1" - istanbul-lib-report "^1.1.0" - istanbul-lib-source-maps "^1.2.0" - istanbul-reports "^1.1.0" + istanbul-lib-coverage "^1.1.1" + istanbul-lib-hook "^1.0.7" + istanbul-lib-instrument "^1.7.2" + istanbul-lib-report "^1.1.1" + istanbul-lib-source-maps "^1.2.1" + istanbul-reports "^1.1.1" js-yaml "^3.7.0" mkdirp "^0.5.1" once "^1.4.0" @@ -3191,50 +3207,50 @@ istanbul-instrumenter-loader@^2.0.0: loader-utils "^0.2.16" object-assign "^4.1.0" -istanbul-lib-coverage@^1.1.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/istanbul-lib-coverage/-/istanbul-lib-coverage-1.1.0.tgz#caca19decaef3525b5d6331d701f3f3b7ad48528" +istanbul-lib-coverage@^1.1.1: + version "1.1.1" + resolved "https://registry.yarnpkg.com/istanbul-lib-coverage/-/istanbul-lib-coverage-1.1.1.tgz#73bfb998885299415c93d38a3e9adf784a77a9da" -istanbul-lib-hook@^1.0.6: - version "1.0.6" - resolved "https://registry.yarnpkg.com/istanbul-lib-hook/-/istanbul-lib-hook-1.0.6.tgz#c0866d1e81cf2d5319249510131fc16dee49231f" +istanbul-lib-hook@^1.0.7: + version "1.0.7" + resolved "https://registry.yarnpkg.com/istanbul-lib-hook/-/istanbul-lib-hook-1.0.7.tgz#dd6607f03076578fe7d6f2a630cf143b49bacddc" dependencies: append-transform "^0.4.0" -istanbul-lib-instrument@^1.1.3, istanbul-lib-instrument@^1.7.1: - version "1.7.1" - resolved "https://registry.yarnpkg.com/istanbul-lib-instrument/-/istanbul-lib-instrument-1.7.1.tgz#169e31bc62c778851a99439dd99c3cc12184d360" +istanbul-lib-instrument@^1.1.3, istanbul-lib-instrument@^1.7.2: + version "1.7.2" + resolved "https://registry.yarnpkg.com/istanbul-lib-instrument/-/istanbul-lib-instrument-1.7.2.tgz#6014b03d3470fb77638d5802508c255c06312e56" dependencies: babel-generator "^6.18.0" babel-template "^6.16.0" babel-traverse "^6.18.0" babel-types "^6.18.0" babylon "^6.13.0" - istanbul-lib-coverage "^1.1.0" + istanbul-lib-coverage "^1.1.1" semver "^5.3.0" -istanbul-lib-report@^1.1.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/istanbul-lib-report/-/istanbul-lib-report-1.1.0.tgz#444c4ecca9afa93cf584f56b10f195bf768c0770" +istanbul-lib-report@^1.1.1: + version "1.1.1" + resolved "https://registry.yarnpkg.com/istanbul-lib-report/-/istanbul-lib-report-1.1.1.tgz#f0e55f56655ffa34222080b7a0cd4760e1405fc9" dependencies: - istanbul-lib-coverage "^1.1.0" + istanbul-lib-coverage "^1.1.1" mkdirp "^0.5.1" path-parse "^1.0.5" supports-color "^3.1.2" -istanbul-lib-source-maps@^1.2.0: - version "1.2.0" - resolved "https://registry.yarnpkg.com/istanbul-lib-source-maps/-/istanbul-lib-source-maps-1.2.0.tgz#8c7706d497e26feeb6af3e0c28fd5b0669598d0e" +istanbul-lib-source-maps@^1.2.1: + version "1.2.1" + resolved "https://registry.yarnpkg.com/istanbul-lib-source-maps/-/istanbul-lib-source-maps-1.2.1.tgz#a6fe1acba8ce08eebc638e572e294d267008aa0c" dependencies: debug "^2.6.3" - istanbul-lib-coverage "^1.1.0" + istanbul-lib-coverage "^1.1.1" mkdirp "^0.5.1" rimraf "^2.6.1" source-map "^0.5.3" -istanbul-reports@^1.1.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/istanbul-reports/-/istanbul-reports-1.1.0.tgz#1ef3b795889219cfb5fad16365f6ce108d5f8c66" +istanbul-reports@^1.1.1: + version "1.1.1" + resolved "https://registry.yarnpkg.com/istanbul-reports/-/istanbul-reports-1.1.1.tgz#042be5c89e175bc3f86523caab29c014e77fee4e" dependencies: handlebars "^4.0.3" @@ -3243,8 +3259,8 @@ jasmine-core@~2.5.2: resolved "https://registry.yarnpkg.com/jasmine-core/-/jasmine-core-2.5.2.tgz#6f61bd79061e27f43e6f9355e44b3c6cab6ff297" jasmine-core@~2.6.0: - version "2.6.1" - resolved "https://registry.yarnpkg.com/jasmine-core/-/jasmine-core-2.6.1.tgz#66a61cddb699958e3613edef346c996f6311fc3b" + version "2.6.3" + resolved "https://registry.yarnpkg.com/jasmine-core/-/jasmine-core-2.6.3.tgz#45072950e4a42b1e322fe55c001100a465d77815" jasmine@^2.5.3: version "2.6.0" @@ -3254,16 +3270,10 @@ jasmine@^2.5.3: glob "^7.0.6" jasmine-core "~2.6.0" -jasminewd2@^2.0.0: +jasminewd2@^2.1.0: version "2.1.0" resolved "https://registry.yarnpkg.com/jasminewd2/-/jasminewd2-2.1.0.tgz#da595275d1ae631de736ac0a7c7d85c9f73ef652" -jodid25519@^1.0.0: - version "1.0.2" - resolved "https://registry.yarnpkg.com/jodid25519/-/jodid25519-1.0.2.tgz#06d4912255093419477d425633606e0e90782967" - dependencies: - jsbn "~0.1.0" - js-base64@^2.1.5, js-base64@^2.1.8, js-base64@^2.1.9: version "2.1.9" resolved "https://registry.yarnpkg.com/js-base64/-/js-base64-2.1.9.tgz#f0e80ae039a4bd654b5f281fc93f04a914a7fcce" @@ -3297,6 +3307,10 @@ jsbn@~0.1.0: version "0.1.1" resolved "https://registry.yarnpkg.com/jsbn/-/jsbn-0.1.1.tgz#a5e654c2e5a2deb5f201d96cefbca80c0ef2f513" +jschardet@^1.4.2: + version "1.4.2" + resolved "https://registry.yarnpkg.com/jschardet/-/jschardet-1.4.2.tgz#2aa107f142af4121d145659d44f50830961e699a" + jsesc@^1.3.0: version "1.3.0" resolved "https://registry.yarnpkg.com/jsesc/-/jsesc-1.3.0.tgz#46c3fec8c1892b12b0833db9bc7622176dbab34b" @@ -3327,7 +3341,7 @@ json3@3.3.2, json3@^3.3.2: version "3.3.2" resolved "https://registry.yarnpkg.com/json3/-/json3-3.3.2.tgz#3c0434743df93e2f5c42aee7b19bcb483575f4e1" -json5@^0.5.0: +json5@^0.5.0, json5@^0.5.1: version "0.5.1" resolved "https://registry.yarnpkg.com/json5/-/json5-0.5.1.tgz#1eade7acc012034ad84e2396767ead9fa5495821" @@ -3394,22 +3408,6 @@ karma-phantomjs-launcher@1.0.1: lodash "^4.0.1" phantomjs-prebuilt "^2.1.7" -karma-sourcemap-loader@^0.3.7: - version "0.3.7" - resolved "https://registry.yarnpkg.com/karma-sourcemap-loader/-/karma-sourcemap-loader-0.3.7.tgz#91322c77f8f13d46fed062b042e1009d4c4505d8" - dependencies: - graceful-fs "^4.1.2" - -karma-webpack@^2.0.0: - version "2.0.3" - resolved "https://registry.yarnpkg.com/karma-webpack/-/karma-webpack-2.0.3.tgz#39cebf5ca2580139b27f9ae69b78816b9c82fae6" - dependencies: - async "~0.9.0" - loader-utils "^0.2.5" - lodash "^3.8.0" - source-map "^0.1.41" - webpack-dev-middleware "^1.0.11" - karma@~1.4.1: version "1.4.1" resolved "https://registry.yarnpkg.com/karma/-/karma-1.4.1.tgz#41981a71d54237606b0a3ea8c58c90773f41650e" @@ -3457,8 +3455,8 @@ kind-of@^2.0.1: is-buffer "^1.0.2" kind-of@^3.0.2: - version "3.2.0" - resolved "https://registry.yarnpkg.com/kind-of/-/kind-of-3.2.0.tgz#b58abe4d5c044ad33726a8c1525b48cf891bff07" + version "3.2.2" + resolved "https://registry.yarnpkg.com/kind-of/-/kind-of-3.2.2.tgz#31ea21a734bab9bbb0f32466d893aea51e4a3c64" dependencies: is-buffer "^1.1.5" @@ -3493,8 +3491,8 @@ lcov-parse@0.0.10: resolved "https://registry.yarnpkg.com/lcov-parse/-/lcov-parse-0.0.10.tgz#1b0b8ff9ac9c7889250582b70b71315d9da6d9a3" less-loader@^4.0.2: - version "4.0.3" - resolved "https://registry.yarnpkg.com/less-loader/-/less-loader-4.0.3.tgz#d1e6462ca2f090c11248455e14b8dda4616d0521" + version "4.0.4" + resolved "https://registry.yarnpkg.com/less-loader/-/less-loader-4.0.4.tgz#b4a8c43843e65c67d2ea2eb1465b5c4233d5006a" dependencies: clone "^2.1.1" loader-utils "^1.1.0" @@ -3541,7 +3539,7 @@ loader-runner@^2.3.0: version "2.3.0" resolved "https://registry.yarnpkg.com/loader-runner/-/loader-runner-2.3.0.tgz#f482aea82d543e07921700d5a46ef26fdac6b8a2" -loader-utils@^0.2.16, loader-utils@^0.2.5, loader-utils@~0.2.2: +loader-utils@^0.2.16, loader-utils@~0.2.2: version "0.2.17" resolved "https://registry.yarnpkg.com/loader-utils/-/loader-utils-0.2.17.tgz#f86e6374d43205a6e6c60e9196f17c0299bfb348" dependencies: @@ -3750,8 +3748,8 @@ lru-cache@2, lru-cache@2.2.x: resolved "https://registry.yarnpkg.com/lru-cache/-/lru-cache-2.2.4.tgz#6c658619becf14031d0d0b594b16042ce4dc063d" lru-cache@^4.0.1: - version "4.0.2" - resolved "https://registry.yarnpkg.com/lru-cache/-/lru-cache-4.0.2.tgz#1d17679c069cda5d040991a09dbc2c0db377e55e" + version "4.1.0" + resolved "https://registry.yarnpkg.com/lru-cache/-/lru-cache-4.1.0.tgz#59be49a683b8d986a939f1ca60fdb6989f4b2046" dependencies: pseudomap "^1.0.1" yallist "^2.0.0" @@ -3773,8 +3771,8 @@ magic-string@^0.19.0: vlq "^0.2.1" make-error@^1.1.1: - version "1.2.3" - resolved "https://registry.yarnpkg.com/make-error/-/make-error-1.2.3.tgz#6c4402df732e0977ac6faf754a5074b3d2b1d19d" + version "1.3.0" + resolved "https://registry.yarnpkg.com/make-error/-/make-error-1.3.0.tgz#52ad3a339ccf10ce62b4040b708fe707244b8b96" map-cache@^0.2.0: version "0.2.2" @@ -3798,7 +3796,7 @@ media-typer@0.3.0: version "0.3.0" resolved "https://registry.yarnpkg.com/media-typer/-/media-typer-0.3.0.tgz#8710d7af0aa626f8fffa1ce00168545263255748" -memory-fs@^0.4.0, memory-fs@~0.4.1: +memory-fs@^0.4.0, memory-fs@^0.4.1, memory-fs@~0.4.1: version "0.4.1" resolved "https://registry.yarnpkg.com/memory-fs/-/memory-fs-0.4.1.tgz#3a9a20b8462523e447cfbc7e8bb80ed667bfc552" dependencies: @@ -3893,7 +3891,7 @@ minimalistic-crypto-utils@^1.0.0, minimalistic-crypto-utils@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/minimalistic-crypto-utils/-/minimalistic-crypto-utils-1.0.1.tgz#f6c00c1c0b082246e5c4d99dfb8c7c083b2b582a" -"minimatch@2 || 3", minimatch@^3.0.0, minimatch@^3.0.2, minimatch@^3.0.3, minimatch@~3.0.2: +"minimatch@2 || 3", minimatch@^3.0.0, minimatch@^3.0.2, minimatch@^3.0.3, minimatch@^3.0.4, minimatch@~3.0.2: version "3.0.4" resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-3.0.4.tgz#5166e286457f03306064be5497e8dbb0c3d32083" dependencies: @@ -3951,9 +3949,9 @@ ms@0.7.2: version "0.7.2" resolved "https://registry.yarnpkg.com/ms/-/ms-0.7.2.tgz#ae25cf2512b3885a1d95d7f037868d8431124765" -ms@0.7.3: - version "0.7.3" - resolved "https://registry.yarnpkg.com/ms/-/ms-0.7.3.tgz#708155a5e44e33f5fd0fc53e81d0d40a91be1fff" +ms@2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/ms/-/ms-2.0.0.tgz#5608aeadfc00be6c2901df5f9861788de0d597c8" multipipe@^0.1.2: version "0.1.2" @@ -3990,8 +3988,8 @@ no-case@^2.2.0: lower-case "^1.1.1" node-gyp@^3.3.1: - version "3.6.1" - resolved "https://registry.yarnpkg.com/node-gyp/-/node-gyp-3.6.1.tgz#19561067ff185464aded478212681f47fd578cbc" + version "3.6.2" + resolved "https://registry.yarnpkg.com/node-gyp/-/node-gyp-3.6.2.tgz#9bfbe54562286284838e750eac05295853fa1c60" dependencies: fstream "^1.0.0" glob "^7.0.3" @@ -4040,8 +4038,8 @@ node-modules-path@^1.0.0: resolved "https://registry.yarnpkg.com/node-modules-path/-/node-modules-path-1.0.1.tgz#40096b08ce7ad0ea14680863af449c7c75a5d1c8" node-pre-gyp@^0.6.29: - version "0.6.34" - resolved "https://registry.yarnpkg.com/node-pre-gyp/-/node-pre-gyp-0.6.34.tgz#94ad1c798a11d7fc67381b50d47f8cc18d9799f7" + version "0.6.36" + resolved "https://registry.yarnpkg.com/node-pre-gyp/-/node-pre-gyp-0.6.36.tgz#db604112cb74e0d477554e9b505b17abddfab786" dependencies: mkdirp "^0.5.1" nopt "^4.0.1" @@ -4073,8 +4071,8 @@ node-sass@3.8.0: sass-graph "^2.1.1" node-sass@^4.2.0, node-sass@^4.3.0: - version "4.5.2" - resolved "https://registry.yarnpkg.com/node-sass/-/node-sass-4.5.2.tgz#4012fa2bd129b1d6365117e88d9da0500d99da64" + version "4.5.3" + resolved "https://registry.yarnpkg.com/node-sass/-/node-sass-4.5.3.tgz#d09c9d1179641239d1b97ffc6231fdcec53e1568" dependencies: async-foreach "^0.1.3" chalk "^1.1.1" @@ -4190,7 +4188,7 @@ object.omit@^2.0.0: for-own "^0.1.4" is-extendable "^0.1.1" -obuf@^1.0.0, obuf@^1.1.0: +obuf@^1.0.0, obuf@^1.1.1: version "1.1.1" resolved "https://registry.yarnpkg.com/obuf/-/obuf-1.1.1.tgz#104124b6c602c6796881a042541d36db43a5264e" @@ -4645,31 +4643,31 @@ postcss-minify-selectors@^2.0.4: postcss-selector-parser "^2.0.0" postcss-modules-extract-imports@^1.0.0: - version "1.0.1" - resolved "https://registry.yarnpkg.com/postcss-modules-extract-imports/-/postcss-modules-extract-imports-1.0.1.tgz#8fb3fef9a6dd0420d3f6d4353cf1ff73f2b2a341" + version "1.2.0" + resolved "https://registry.yarnpkg.com/postcss-modules-extract-imports/-/postcss-modules-extract-imports-1.2.0.tgz#66140ecece38ef06bf0d3e355d69bf59d141ea85" dependencies: - postcss "^5.0.4" + postcss "^6.0.1" postcss-modules-local-by-default@^1.0.1: - version "1.1.1" - resolved "https://registry.yarnpkg.com/postcss-modules-local-by-default/-/postcss-modules-local-by-default-1.1.1.tgz#29a10673fa37d19251265ca2ba3150d9040eb4ce" + version "1.2.0" + resolved "https://registry.yarnpkg.com/postcss-modules-local-by-default/-/postcss-modules-local-by-default-1.2.0.tgz#f7d80c398c5a393fa7964466bd19500a7d61c069" dependencies: - css-selector-tokenizer "^0.6.0" - postcss "^5.0.4" + css-selector-tokenizer "^0.7.0" + postcss "^6.0.1" postcss-modules-scope@^1.0.0: - version "1.0.2" - resolved "https://registry.yarnpkg.com/postcss-modules-scope/-/postcss-modules-scope-1.0.2.tgz#ff977395e5e06202d7362290b88b1e8cd049de29" + version "1.1.0" + resolved "https://registry.yarnpkg.com/postcss-modules-scope/-/postcss-modules-scope-1.1.0.tgz#d6ea64994c79f97b62a72b426fbe6056a194bb90" dependencies: - css-selector-tokenizer "^0.6.0" - postcss "^5.0.4" + css-selector-tokenizer "^0.7.0" + postcss "^6.0.1" postcss-modules-values@^1.1.0: - version "1.2.2" - resolved "https://registry.yarnpkg.com/postcss-modules-values/-/postcss-modules-values-1.2.2.tgz#f0e7d476fe1ed88c5e4c7f97533a3e772ad94ca1" + version "1.3.0" + resolved "https://registry.yarnpkg.com/postcss-modules-values/-/postcss-modules-values-1.3.0.tgz#ecffa9d7e192518389f42ad0e83f72aec456ea20" dependencies: - icss-replace-symbols "^1.0.2" - postcss "^5.0.14" + icss-replace-symbols "^1.1.0" + postcss "^6.0.1" postcss-normalize-charset@^1.1.0: version "1.1.1" @@ -4772,6 +4770,14 @@ postcss@^5.0.0, postcss@^5.0.10, postcss@^5.0.11, postcss@^5.0.12, postcss@^5.0. source-map "^0.5.6" supports-color "^3.2.3" +postcss@^6.0.1: + version "6.0.1" + resolved "https://registry.yarnpkg.com/postcss/-/postcss-6.0.1.tgz#000dbd1f8eef217aa368b9a212c5fc40b2a8f3f2" + dependencies: + chalk "^1.1.3" + source-map "^0.5.6" + supports-color "^3.2.3" + prepend-http@^1.0.0: version "1.0.4" resolved "https://registry.yarnpkg.com/prepend-http/-/prepend-http-1.0.4.tgz#d4f4562b0ce3696e41ac52d0e002e57a635dc6dc" @@ -4810,8 +4816,8 @@ promise@^7.1.1: asap "~2.0.3" protractor@~5.1.0: - version "5.1.1" - resolved "https://registry.yarnpkg.com/protractor/-/protractor-5.1.1.tgz#10c4e336571b28875b8acc3ae3e4e1e40ef7e986" + version "5.1.2" + resolved "https://registry.yarnpkg.com/protractor/-/protractor-5.1.2.tgz#9b221741709a4c62d5cd53c6aadd54a71137e95f" dependencies: "@types/node" "^6.0.46" "@types/q" "^0.0.32" @@ -4820,16 +4826,16 @@ protractor@~5.1.0: chalk "^1.1.3" glob "^7.0.3" jasmine "^2.5.3" - jasminewd2 "^2.0.0" + jasminewd2 "^2.1.0" optimist "~0.6.0" q "1.4.1" saucelabs "~1.3.0" selenium-webdriver "3.0.1" source-map-support "~0.4.0" webdriver-js-extender "^1.0.0" - webdriver-manager "^12.0.1" + webdriver-manager "^12.0.6" -proxy-addr@~1.1.3: +proxy-addr@~1.1.4: version "1.1.4" resolved "https://registry.yarnpkg.com/proxy-addr/-/proxy-addr-1.1.4.tgz#27e545f6960a44a627d9b44467e35c1b6b4ce2f3" dependencies: @@ -4909,8 +4915,10 @@ randomatic@^1.1.3: kind-of "^3.0.2" randombytes@^2.0.0, randombytes@^2.0.1: - version "2.0.3" - resolved "https://registry.yarnpkg.com/randombytes/-/randombytes-2.0.3.tgz#674c99760901c3c4112771a31e521dc349cc09ec" + version "2.0.5" + resolved "https://registry.yarnpkg.com/randombytes/-/randombytes-2.0.5.tgz#dc009a246b8d09a177b4b7a0ae77bc570f4b1b79" + dependencies: + safe-buffer "^5.1.0" range-parser@^1.0.3, range-parser@^1.2.0, range-parser@~1.2.0: version "1.2.0" @@ -4961,15 +4969,15 @@ readable-stream@1.0, "readable-stream@>=1.0.33-1 <1.1.0-0", readable-stream@~1.0 isarray "0.0.1" string_decoder "~0.10.x" -readable-stream@^2.0.0, readable-stream@^2.0.1, readable-stream@^2.0.2, readable-stream@^2.0.4, readable-stream@^2.0.5, readable-stream@^2.0.6, readable-stream@^2.1.4, readable-stream@^2.1.5, readable-stream@^2.2.6: - version "2.2.9" - resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-2.2.9.tgz#cf78ec6f4a6d1eb43d26488cac97f042e74b7fc8" +readable-stream@^2.0.0, readable-stream@^2.0.1, readable-stream@^2.0.2, readable-stream@^2.0.4, readable-stream@^2.0.5, readable-stream@^2.0.6, readable-stream@^2.1.4, readable-stream@^2.1.5, readable-stream@^2.2.6, readable-stream@^2.2.9: + version "2.2.11" + resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-2.2.11.tgz#0796b31f8d7688007ff0b93a8088d34aa17c0f72" dependencies: - buffer-shims "~1.0.0" core-util-is "~1.0.0" inherits "~2.0.1" isarray "~1.0.0" process-nextick-args "~1.0.6" + safe-buffer "~5.0.1" string_decoder "~1.0.0" util-deprecate "~1.0.1" @@ -5071,8 +5079,8 @@ relateurl@0.2.x: resolved "https://registry.yarnpkg.com/relateurl/-/relateurl-0.2.7.tgz#54dbf377e51440aca90a4cd274600d3ff2d888a9" remove-trailing-separator@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/remove-trailing-separator/-/remove-trailing-separator-1.0.1.tgz#615ebb96af559552d4bf4057c8436d486ab63cc4" + version "1.0.2" + resolved "https://registry.yarnpkg.com/remove-trailing-separator/-/remove-trailing-separator-1.0.2.tgz#69b062d978727ad14dc6b56ba4ab772fd8d70511" renderkid@^2.0.1: version "2.0.1" @@ -5276,9 +5284,15 @@ rw@1: version "1.3.3" resolved "https://registry.yarnpkg.com/rw/-/rw-1.3.3.tgz#3f862dfa91ab766b14885ef4d01124bfda074fb4" -rx@^4.1.0: - version "4.1.0" - resolved "https://registry.yarnpkg.com/rx/-/rx-4.1.0.tgz#a5f13ff79ef3b740fe30aa803fb09f98805d4782" +rx-lite-aggregates@^4.0.8: + version "4.0.8" + resolved "https://registry.yarnpkg.com/rx-lite-aggregates/-/rx-lite-aggregates-4.0.8.tgz#753b87a89a11c95467c4ac1626c4efc4e05c67be" + dependencies: + rx-lite "*" + +rx-lite@*, rx-lite@^4.0.8: + version "4.0.8" + resolved "https://registry.yarnpkg.com/rx-lite/-/rx-lite-4.0.8.tgz#0b1e11af8bc44836f04a6407e92da42467b79444" rxjs@^5.0.1, rxjs@^5.2.0: version "5.4.0" @@ -5286,18 +5300,22 @@ rxjs@^5.0.1, rxjs@^5.2.0: dependencies: symbol-observable "^1.0.1" -safe-buffer@^5.0.1: +safe-buffer@^5.0.1, safe-buffer@^5.1.0: + version "5.1.0" + resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.1.0.tgz#fe4c8460397f9eaaaa58e73be46273408a45e223" + +safe-buffer@~5.0.1: version "5.0.1" resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.0.1.tgz#d263ca54696cd8a306b5ca6551e92de57918fbe7" sass-graph@^2.1.1: - version "2.2.3" - resolved "https://registry.yarnpkg.com/sass-graph/-/sass-graph-2.2.3.tgz#2ba9f170f6cafed5b51665abe13cf319c9269c31" + version "2.2.4" + resolved "https://registry.yarnpkg.com/sass-graph/-/sass-graph-2.2.4.tgz#13fbd63cd1caf0908b9fd93476ad43a51d1e0b49" dependencies: glob "^7.0.0" lodash "^4.0.0" scss-tokenizer "^0.2.3" - yargs "^6.6.0" + yargs "^7.0.0" sass-loader@^6.0.3: version "6.0.5" @@ -5327,6 +5345,12 @@ sax@>=0.6.0, sax@~1.2.1: version "1.2.2" resolved "https://registry.yarnpkg.com/sax/-/sax-1.2.2.tgz#fd8631a23bc7826bef5d871bdb87378c95647828" +schema-utils@^0.3.0: + version "0.3.0" + resolved "https://registry.yarnpkg.com/schema-utils/-/schema-utils-0.3.0.tgz#f5877222ce3e931edae039f17eb3716e7137f8cf" + dependencies: + ajv "^5.0.0" + script-loader@^0.7.0: version "0.7.0" resolved "https://registry.yarnpkg.com/script-loader/-/script-loader-0.7.0.tgz#685dc7e7069e0dee7a92674f0ebc5b0f55baa5ec" @@ -5385,11 +5409,11 @@ semver@~5.0.1: version "5.0.3" resolved "https://registry.yarnpkg.com/semver/-/semver-5.0.3.tgz#77466de589cd5d3c95f138aa78bc569a3cb5d27a" -send@0.15.1: - version "0.15.1" - resolved "https://registry.yarnpkg.com/send/-/send-0.15.1.tgz#8a02354c26e6f5cca700065f5f0cdeba90ec7b5f" +send@0.15.3: + version "0.15.3" + resolved "https://registry.yarnpkg.com/send/-/send-0.15.3.tgz#5013f9f99023df50d1bd9892c19e3defd1d53309" dependencies: - debug "2.6.1" + debug "2.6.7" depd "~1.1.0" destroy "~1.0.4" encodeurl "~1.0.1" @@ -5398,7 +5422,7 @@ send@0.15.1: fresh "0.5.0" http-errors "~1.6.1" mime "1.3.4" - ms "0.7.2" + ms "2.0.0" on-finished "~2.3.0" range-parser "~1.2.0" statuses "~1.3.1" @@ -5408,25 +5432,25 @@ sequencify@~0.0.7: resolved "https://registry.yarnpkg.com/sequencify/-/sequencify-0.0.7.tgz#90cff19d02e07027fd767f5ead3e7b95d1e7380c" serve-index@^1.7.2: - version "1.8.0" - resolved "https://registry.yarnpkg.com/serve-index/-/serve-index-1.8.0.tgz#7c5d96c13fb131101f93c1c5774f8516a1e78d3b" + version "1.9.0" + resolved "https://registry.yarnpkg.com/serve-index/-/serve-index-1.9.0.tgz#d2b280fc560d616ee81b48bf0fa82abed2485ce7" dependencies: accepts "~1.3.3" - batch "0.5.3" - debug "~2.2.0" + batch "0.6.1" + debug "2.6.8" escape-html "~1.0.3" - http-errors "~1.5.0" - mime-types "~2.1.11" + http-errors "~1.6.1" + mime-types "~2.1.15" parseurl "~1.3.1" -serve-static@1.12.1: - version "1.12.1" - resolved "https://registry.yarnpkg.com/serve-static/-/serve-static-1.12.1.tgz#7443a965e3ced647aceb5639fa06bf4d1bbe0039" +serve-static@1.12.3: + version "1.12.3" + resolved "https://registry.yarnpkg.com/serve-static/-/serve-static-1.12.3.tgz#9f4ba19e2f3030c547f8af99107838ec38d5b1e2" dependencies: encodeurl "~1.0.1" escape-html "~1.0.3" parseurl "~1.3.1" - send "0.15.1" + send "0.15.3" set-blocking@^2.0.0, set-blocking@~2.0.0: version "2.0.0" @@ -5440,10 +5464,6 @@ setimmediate@^1.0.4: version "1.0.5" resolved "https://registry.yarnpkg.com/setimmediate/-/setimmediate-1.0.5.tgz#290cbb232e306942d7d7ea9b83732ab7856f8285" -setprototypeof@1.0.2: - version "1.0.2" - resolved "https://registry.yarnpkg.com/setprototypeof/-/setprototypeof-1.0.2.tgz#81a552141ec104b88e89ce383103ad5c66564d08" - setprototypeof@1.0.3: version "1.0.3" resolved "https://registry.yarnpkg.com/setprototypeof/-/setprototypeof-1.0.3.tgz#66567e37043eeb4f04d91bd658c0cbefb55b8e04" @@ -5557,13 +5577,21 @@ sort-keys@^1.0.0: dependencies: is-plain-obj "^1.0.0" -source-list-map@^0.1.7, source-list-map@~0.1.7: +source-list-map@^0.1.7: version "0.1.8" resolved "https://registry.yarnpkg.com/source-list-map/-/source-list-map-0.1.8.tgz#c550b2ab5427f6b3f21f5afead88c4f5587b2106" -source-map-loader@^0.1.5: - version "0.1.6" - resolved "https://registry.yarnpkg.com/source-map-loader/-/source-map-loader-0.1.6.tgz#c09903da6d73b9e53b7ed8ee5245597051e98e91" +source-list-map@^1.1.1: + version "1.1.2" + resolved "https://registry.yarnpkg.com/source-list-map/-/source-list-map-1.1.2.tgz#9889019d1024cce55cdc069498337ef6186a11a1" + +source-list-map@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/source-list-map/-/source-list-map-2.0.0.tgz#aaa47403f7b245a92fbc97ea08f250d6087ed085" + +source-map-loader@^0.2.0: + version "0.2.1" + resolved "https://registry.yarnpkg.com/source-map-loader/-/source-map-loader-0.2.1.tgz#48126be9230bd47fad05e46a8c3c2e3d2dabe507" dependencies: async "^0.9.0" loader-utils "~0.2.2" @@ -5575,7 +5603,7 @@ source-map-support@^0.4.0, source-map-support@^0.4.2, source-map-support@~0.4.0: dependencies: source-map "^0.5.6" -source-map@0.1.x, source-map@^0.1.41, source-map@~0.1.33, source-map@~0.1.7: +source-map@0.1.x, source-map@~0.1.33, source-map@~0.1.7: version "0.1.43" resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.1.43.tgz#c24bc146ca517c1471f5dacbe2571b2b7f9e3346" dependencies: @@ -5609,37 +5637,40 @@ spdx-license-ids@^1.0.2: version "1.2.2" resolved "https://registry.yarnpkg.com/spdx-license-ids/-/spdx-license-ids-1.2.2.tgz#c9df7a3424594ade6bd11900d596696dc06bac57" -spdy-transport@^2.0.15: - version "2.0.18" - resolved "https://registry.yarnpkg.com/spdy-transport/-/spdy-transport-2.0.18.tgz#43fc9c56be2cccc12bb3e2754aa971154e836ea6" +spdy-transport@^2.0.18: + version "2.0.20" + resolved "https://registry.yarnpkg.com/spdy-transport/-/spdy-transport-2.0.20.tgz#735e72054c486b2354fe89e702256004a39ace4d" dependencies: - debug "^2.2.0" + debug "^2.6.8" + detect-node "^2.0.3" hpack.js "^2.1.6" - obuf "^1.1.0" - readable-stream "^2.0.1" - wbuf "^1.4.0" + obuf "^1.1.1" + readable-stream "^2.2.9" + safe-buffer "^5.0.1" + wbuf "^1.7.2" spdy@^3.4.1: - version "3.4.4" - resolved "https://registry.yarnpkg.com/spdy/-/spdy-3.4.4.tgz#e0406407ca90ff01b553eb013505442649f5a819" + version "3.4.7" + resolved "https://registry.yarnpkg.com/spdy/-/spdy-3.4.7.tgz#42ff41ece5cc0f99a3a6c28aabb73f5c3b03acbc" dependencies: - debug "^2.2.0" - handle-thing "^1.2.4" - http-deceiver "^1.2.4" + debug "^2.6.8" + handle-thing "^1.2.5" + http-deceiver "^1.2.7" + safe-buffer "^5.0.1" select-hose "^2.0.0" - spdy-transport "^2.0.15" + spdy-transport "^2.0.18" sprintf-js@^1.0.3: - version "1.1.0" - resolved "https://registry.yarnpkg.com/sprintf-js/-/sprintf-js-1.1.0.tgz#cffcaf702daf65ea39bb4e0fa2b299cec1a1be46" + version "1.1.1" + resolved "https://registry.yarnpkg.com/sprintf-js/-/sprintf-js-1.1.1.tgz#36be78320afe5801f6cea3ee78b6e5aab940ea0c" sprintf-js@~1.0.2: version "1.0.3" resolved "https://registry.yarnpkg.com/sprintf-js/-/sprintf-js-1.0.3.tgz#04e6926f662895354f3dd015203633b857297e2c" sshpk@^1.7.0: - version "1.13.0" - resolved "https://registry.yarnpkg.com/sshpk/-/sshpk-1.13.0.tgz#ff2a3e4fd04497555fed97b39a0fd82fafb3a33c" + version "1.13.1" + resolved "https://registry.yarnpkg.com/sshpk/-/sshpk-1.13.1.tgz#512df6da6287144316dc4c18fe1cf1d940739be3" dependencies: asn1 "~0.2.3" assert-plus "^1.0.0" @@ -5648,7 +5679,6 @@ sshpk@^1.7.0: optionalDependencies: bcrypt-pbkdf "^1.0.0" ecc-jsbn "~0.1.1" - jodid25519 "^1.0.0" jsbn "~0.1.0" tweetnacl "~0.14.0" @@ -5711,10 +5741,10 @@ string_decoder@^0.10.25, string_decoder@~0.10.x: resolved "https://registry.yarnpkg.com/string_decoder/-/string_decoder-0.10.31.tgz#62e203bc41766c6c28c9fc84301dab1c5310fa94" string_decoder@~1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/string_decoder/-/string_decoder-1.0.0.tgz#f06f41157b664d86069f84bdbdc9b0d8ab281667" + version "1.0.2" + resolved "https://registry.yarnpkg.com/string_decoder/-/string_decoder-1.0.2.tgz#b29e1f4e1125fa97a10382b8a533737b7491e179" dependencies: - buffer-shims "~1.0.0" + safe-buffer "~5.0.1" stringstream@~0.0.4: version "0.0.5" @@ -5891,8 +5921,8 @@ tildify@^1.0.0: os-homedir "^1.0.0" time-stamp@^1.0.0: - version "1.0.1" - resolved "https://registry.yarnpkg.com/time-stamp/-/time-stamp-1.0.1.tgz#9f4bd23559c9365966f3302dbba2b07c6b99b151" + version "1.1.0" + resolved "https://registry.yarnpkg.com/time-stamp/-/time-stamp-1.1.0.tgz#764a5a11af50561921b133f3b44e618687e0f5c3" timers-browserify@^2.0.2: version "2.0.2" @@ -5993,28 +6023,28 @@ tsickle@^0.21.0: source-map "^0.5.6" source-map-support "^0.4.2" -tslib@^1.6.0: - version "1.7.0" - resolved "https://registry.yarnpkg.com/tslib/-/tslib-1.7.0.tgz#6e8366695f72961252b35167b0dd4fbeeafba491" +tslib@^1.7.1: + version "1.7.1" + resolved "https://registry.yarnpkg.com/tslib/-/tslib-1.7.1.tgz#bc8004164691923a79fe8378bbeb3da2017538ec" tslint@^5.2.0: - version "5.2.0" - resolved "https://registry.yarnpkg.com/tslint/-/tslint-5.2.0.tgz#16a2addf20cb748385f544e9a0edab086bc34114" + version "5.4.3" + resolved "https://registry.yarnpkg.com/tslint/-/tslint-5.4.3.tgz#761c8402b80e347b7733a04390a757b253580467" dependencies: babel-code-frame "^6.22.0" colors "^1.1.2" + commander "^2.9.0" diff "^3.2.0" - findup-sync "~0.3.0" glob "^7.1.1" - optimist "~0.6.0" + minimatch "^3.0.4" resolve "^1.3.2" semver "^5.3.0" - tslib "^1.6.0" - tsutils "^1.8.0" + tslib "^1.7.1" + tsutils "^2.3.0" -tsutils@^1.8.0: - version "1.8.0" - resolved "https://registry.yarnpkg.com/tsutils/-/tsutils-1.8.0.tgz#bf8118ed8e80cd5c9fc7d75728c7963d44ed2f52" +tsutils@^2.3.0: + version "2.3.0" + resolved "https://registry.yarnpkg.com/tsutils/-/tsutils-2.3.0.tgz#96e661d7c2363f31adc8992ac67bbe7b7fc175e5" tty-browserify@0.0.0: version "0.0.0" @@ -6034,7 +6064,7 @@ tweetnacl@^0.14.3, tweetnacl@~0.14.0: version "0.14.5" resolved "https://registry.yarnpkg.com/tweetnacl/-/tweetnacl-0.14.5.tgz#5ae68177f192d4456269d108afa93ff8743f4f64" -type-is@~1.6.14: +type-is@~1.6.15: version "1.6.15" resolved "https://registry.yarnpkg.com/type-is/-/type-is-1.6.15.tgz#cab10fb4909e441c82842eafe1ad646c81804410" dependencies: @@ -6045,17 +6075,20 @@ typedarray@~0.0.5: version "0.0.6" resolved "https://registry.yarnpkg.com/typedarray/-/typedarray-0.0.6.tgz#867ac74e3864187b1d3d47d996a78ec5c8830777" -"typescript@>=2.0.0 <2.3.0": - version "2.2.2" - resolved "https://registry.yarnpkg.com/typescript/-/typescript-2.2.2.tgz#606022508479b55ffa368b58fee963a03dfd7b0c" +"typescript@>=2.0.0 <2.4.0", typescript@^2.3.2: + version "2.3.4" + resolved "https://registry.yarnpkg.com/typescript/-/typescript-2.3.4.tgz#3d38321828231e434f287514959c37a82b629f42" -typescript@^2.3.1: - version "2.3.2" - resolved "https://registry.yarnpkg.com/typescript/-/typescript-2.3.2.tgz#f0f045e196f69a72f06b25fd3bd39d01c3ce9984" +uglify-js@3.0.x: + version "3.0.15" + resolved "https://registry.yarnpkg.com/uglify-js/-/uglify-js-3.0.15.tgz#aacb323a846b234602270dead8a32441a8806f42" + dependencies: + commander "~2.9.0" + source-map "~0.5.1" -uglify-js@^2.6, uglify-js@^2.7.5, uglify-js@~2.8.22: - version "2.8.24" - resolved "https://registry.yarnpkg.com/uglify-js/-/uglify-js-2.8.24.tgz#48eb5175cf32e22ec11a47e638d7c8b4e0faf2dd" +uglify-js@^2.6, uglify-js@^2.8.5: + version "2.8.28" + resolved "https://registry.yarnpkg.com/uglify-js/-/uglify-js-2.8.28.tgz#e335032df9bb20dcb918f164589d5af47f38834a" dependencies: source-map "~0.5.1" yargs "~3.10.0" @@ -6205,7 +6238,7 @@ validate-npm-package-license@^3.0.1: spdx-correct "~1.0.0" spdx-expression-parse "~1.0.0" -vary@~1.1.0: +vary@~1.1.0, vary@~1.1.1: version "1.1.1" resolved "https://registry.yarnpkg.com/vary/-/vary-1.1.1.tgz#67535ebb694c1d52257457984665323f587e8d37" @@ -6298,13 +6331,13 @@ void-elements@^2.0.0: resolved "https://registry.yarnpkg.com/void-elements/-/void-elements-2.0.1.tgz#c066afb582bb1cb4128d60ea92392e94d5e9dbec" walk-sync@^0.3.1: - version "0.3.1" - resolved "https://registry.yarnpkg.com/walk-sync/-/walk-sync-0.3.1.tgz#558a16aeac8c0db59c028b73c66f397684ece465" + version "0.3.2" + resolved "https://registry.yarnpkg.com/walk-sync/-/walk-sync-0.3.2.tgz#4827280afc42d0e035367c4a4e31eeac0d136f75" dependencies: ensure-posix-path "^1.0.0" matcher-collection "^1.0.0" -watchpack@^1.2.0: +watchpack@^1.3.1: version "1.3.1" resolved "https://registry.yarnpkg.com/watchpack/-/watchpack-1.3.1.tgz#7d8693907b28ce6013e7f3610aa2a1acf07dad87" dependencies: @@ -6312,15 +6345,15 @@ watchpack@^1.2.0: chokidar "^1.4.3" graceful-fs "^4.1.2" -wbuf@^1.1.0, wbuf@^1.4.0: +wbuf@^1.1.0, wbuf@^1.7.2: version "1.7.2" resolved "https://registry.yarnpkg.com/wbuf/-/wbuf-1.7.2.tgz#d697b99f1f59512df2751be42769c1580b5801fe" dependencies: minimalistic-assert "^1.0.0" -web-animations-js@2.2.2: - version "2.2.2" - resolved "https://registry.yarnpkg.com/web-animations-js/-/web-animations-js-2.2.2.tgz#7c3aa5382c5eade70cd206880d56a37869630638" +web-animations-js@2.2.5: + version "2.2.5" + resolved "https://registry.yarnpkg.com/web-animations-js/-/web-animations-js-2.2.5.tgz#26ca1b34c1347332a0813f8b2bfe69664efa80aa" webdriver-js-extender@^1.0.0: version "1.0.0" @@ -6329,7 +6362,7 @@ webdriver-js-extender@^1.0.0: "@types/selenium-webdriver" "^2.53.35" selenium-webdriver "^2.53.2" -webdriver-manager@^12.0.1: +webdriver-manager@^12.0.6: version "12.0.6" resolved "https://registry.yarnpkg.com/webdriver-manager/-/webdriver-manager-12.0.6.tgz#3df1a481977010b4cbf8c9d85c7a577828c0e70b" dependencies: @@ -6345,7 +6378,7 @@ webdriver-manager@^12.0.1: semver "^5.3.0" xml2js "^0.4.17" -webpack-dev-middleware@^1.0.11, webpack-dev-middleware@^1.10.2: +webpack-dev-middleware@^1.10.2: version "1.10.2" resolved "https://registry.yarnpkg.com/webpack-dev-middleware/-/webpack-dev-middleware-1.10.2.tgz#2e252ce1dfb020dbda1ccb37df26f30ab014dbd1" dependencies: @@ -6354,7 +6387,7 @@ webpack-dev-middleware@^1.0.11, webpack-dev-middleware@^1.10.2: path-is-absolute "^1.0.0" range-parser "^1.0.3" -webpack-dev-server@~2.4.2: +webpack-dev-server@~2.4.5: version "2.4.5" resolved "https://registry.yarnpkg.com/webpack-dev-server/-/webpack-dev-server-2.4.5.tgz#31384ce81136be1080b4b4cde0eb9b90e54ee6cf" dependencies: @@ -6382,18 +6415,25 @@ webpack-merge@^2.4.0: dependencies: lodash "^4.17.4" -webpack-sources@^0.1.0, webpack-sources@^0.1.4: - version "0.1.5" - resolved "https://registry.yarnpkg.com/webpack-sources/-/webpack-sources-0.1.5.tgz#aa1f3abf0f0d74db7111c40e500b84f966640750" +webpack-sources@^0.2.3: + version "0.2.3" + resolved "https://registry.yarnpkg.com/webpack-sources/-/webpack-sources-0.2.3.tgz#17c62bfaf13c707f9d02c479e0dcdde8380697fb" dependencies: - source-list-map "~0.1.7" + source-list-map "^1.1.1" source-map "~0.5.3" -webpack@~2.2.0: - version "2.2.1" - resolved "https://registry.yarnpkg.com/webpack/-/webpack-2.2.1.tgz#7bb1d72ae2087dd1a4af526afec15eed17dda475" +webpack-sources@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/webpack-sources/-/webpack-sources-1.0.1.tgz#c7356436a4d13123be2e2426a05d1dad9cbe65cf" dependencies: - acorn "^4.0.4" + source-list-map "^2.0.0" + source-map "~0.5.3" + +webpack@~2.4.0: + version "2.4.1" + resolved "https://registry.yarnpkg.com/webpack/-/webpack-2.4.1.tgz#15a91dbe34966d8a4b99c7d656efd92a2e5a6f6a" + dependencies: + acorn "^5.0.0" acorn-dynamic-import "^2.0.0" ajv "^4.7.0" ajv-keywords "^1.1.1" @@ -6401,6 +6441,7 @@ webpack@~2.2.0: enhanced-resolve "^3.0.0" interpret "^1.0.0" json-loader "^0.5.4" + json5 "^0.5.1" loader-runner "^2.3.0" loader-utils "^0.2.16" memory-fs "~0.4.1" @@ -6409,9 +6450,9 @@ webpack@~2.2.0: source-map "^0.5.3" supports-color "^3.1.0" tapable "~0.2.5" - uglify-js "^2.7.5" - watchpack "^1.2.0" - webpack-sources "^0.1.4" + uglify-js "^2.8.5" + watchpack "^1.3.1" + webpack-sources "^0.2.3" yargs "^6.0.0" websocket-driver@>=0.5.1: @@ -6551,6 +6592,12 @@ yargs-parser@^4.2.0: dependencies: camelcase "^3.0.0" +yargs-parser@^5.0.0: + version "5.0.0" + resolved "https://registry.yarnpkg.com/yargs-parser/-/yargs-parser-5.0.0.tgz#275ecf0d7ffe05c77e64e7c86e4cd94bf0e1228a" + dependencies: + camelcase "^3.0.0" + yargs@^6.0.0, yargs@^6.6.0: version "6.6.0" resolved "https://registry.yarnpkg.com/yargs/-/yargs-6.6.0.tgz#782ec21ef403345f830a808ca3d513af56065208" @@ -6569,6 +6616,24 @@ yargs@^6.0.0, yargs@^6.6.0: y18n "^3.2.1" yargs-parser "^4.2.0" +yargs@^7.0.0: + version "7.1.0" + resolved "https://registry.yarnpkg.com/yargs/-/yargs-7.1.0.tgz#6ba318eb16961727f5d284f8ea003e8d6154d0c8" + dependencies: + camelcase "^3.0.0" + cliui "^3.2.0" + decamelize "^1.1.1" + get-caller-file "^1.0.1" + os-locale "^1.4.0" + read-pkg-up "^1.0.1" + require-directory "^2.1.1" + require-main-filename "^1.0.1" + set-blocking "^2.0.0" + string-width "^1.0.2" + which-module "^1.0.0" + y18n "^3.2.1" + yargs-parser "^5.0.0" + yargs@~3.10.0: version "3.10.0" resolved "https://registry.yarnpkg.com/yargs/-/yargs-3.10.0.tgz#f7ee7bd857dd7c1d2d38c0e74efbd681d1431fd1" @@ -6594,6 +6659,6 @@ yn@^1.2.0: dependencies: object-assign "^4.1.1" -zone.js@^0.8.4, zone.js@^0.8.6: - version "0.8.10" - resolved "https://registry.yarnpkg.com/zone.js/-/zone.js-0.8.10.tgz#6d1b696492c029cdbe808e59e87bbd9491b98aa8" +zone.js@^0.8.4, zone.js@^0.8.9: + version "0.8.12" + resolved "https://registry.yarnpkg.com/zone.js/-/zone.js-0.8.12.tgz#86ff5053c98aec291a0bf4bbac501d694a05cfbb"