diff --git a/app.ts b/app.ts index ac1fb20..1187b04 100644 --- a/app.ts +++ b/app.ts @@ -1,16 +1,45 @@ -import { AuthFlow, AuthStateEmitter } from './flow'; -import { log } from './logger'; +import {AuthFlow, AuthStateEmitter} from './flow'; +import {log} from './logger'; const SIGN_IN = 'Sign-In'; const SIGN_OUT = 'Sign-Out'; +interface SnackBarOptions { + message: string; + timeout?: number; + actionHandler?: (event: any) => void; + actionText?: string; +} + +interface UserInfo { + name: string; + given_name: string; + family_name: string; + picture: string; +} + export class App { private authFlow: AuthFlow = new AuthFlow(); - private handleSignIn = document.querySelector('#handle-sign-in')!; + private userInfo: UserInfo|null = null; - constructor() { - this.handleSignIn.textContent = SIGN_IN; + private handleSignIn = + document.querySelector('#handle-sign-in') as HTMLElement; + private fetchUserInfo = + document.querySelector('#handle-user-info') as HTMLElement; + + private userCard = document.querySelector('#user-info') as HTMLElement; + + private userProfileImage = + document.querySelector('#user-profile-image') as HTMLImageElement; + + private userName = document.querySelector('#user-name') as HTMLElement; + + private snackbarContainer: any = + document.querySelector('#appauth-snackbar') as HTMLElement; + + constructor() { + this.initializeUi(); this.handleSignIn.addEventListener('click', (event) => { if (this.handleSignIn.textContent === SIGN_IN) { this.signIn(); @@ -20,25 +49,71 @@ export class App { event.preventDefault(); }); - this.authFlow.authStateEmitter.on(AuthStateEmitter.ON_AUTHORIZATION_RESPONSE, () => { - this.handleSignIn.textContent = SIGN_OUT; + this.fetchUserInfo.addEventListener('click', () => { + this.authFlow.performWithFreshTokens().then(accessToken => { + let request = + new Request('https://www.googleapis.com/oauth2/v3/userinfo', { + headers: new Headers({'Authorization': `Bearer ${accessToken}`}), + method: 'GET', + cache: 'no-cache' + }); + + fetch(request) + .then(result => result.json()) + .then(user => { + log('User Info ', user); + this.userInfo = user; + this.updateUi(); + }) + .catch(error => { + log('Something bad happened ', error); + }); + }); }); + + this.authFlow.authStateEmitter.on( + AuthStateEmitter.ON_TOKEN_RESPONSE, () => { + this.updateUi(); + }); } signIn(username?: string): Promise { if (!this.authFlow.loggedIn()) { - return this.authFlow.fetchServiceConfiguration() - .then(() => this.authFlow.makeAuthorizationRequest(username)); + return this.authFlow.fetchServiceConfiguration().then( + () => this.authFlow.makeAuthorizationRequest(username)); } else { return Promise.resolve(); } } - signOut() { - this.authFlow.signOut(); + private initializeUi() { this.handleSignIn.textContent = SIGN_IN; + this.fetchUserInfo.style.display = 'none'; + this.userCard.style.display = 'none'; + } + + // update ui post logging in. + private updateUi() { + this.handleSignIn.textContent = SIGN_OUT; + this.fetchUserInfo.style.display = ''; + if (this.userInfo) { + this.userProfileImage.src = `${this.userInfo.picture}?sz=96`; + this.userName.textContent = this.userInfo.name; + this.showSnackBar( + {message: `Welcome ${this.userInfo.name}`, timeout: 4000}); + this.userCard.style.display = ''; + } + } + + private showSnackBar(data: SnackBarOptions) { + this.snackbarContainer.MaterialSnackbar.showSnackbar(data); } + signOut() { + this.authFlow.signOut(); + this.userInfo = null; + this.initializeUi(); + } } log('Init complete'); diff --git a/flow.ts b/flow.ts index a6640d6..46a9140 100644 --- a/flow.ts +++ b/flow.ts @@ -1,19 +1,19 @@ -import { AuthorizationRequest } from '@openid/appauth/built/authorization_request'; -import { AuthorizationNotifier, AuthorizationRequestHandler, AuthorizationRequestResponse, BUILT_IN_PARAMETERS } from '@openid/appauth/built/authorization_request_handler'; -import { AuthorizationResponse } from '@openid/appauth/built/authorization_response'; -import { AuthorizationServiceConfiguration } from '@openid/appauth/built/authorization_service_configuration'; -import { NodeBasedHandler } from '@openid/appauth/built/node_support/node_request_handler'; -import { NodeRequestor } from '@openid/appauth/built/node_support/node_requestor'; -import { GRANT_TYPE_AUTHORIZATION_CODE, GRANT_TYPE_REFRESH_TOKEN, TokenRequest } from '@openid/appauth/built/token_request'; -import { BaseTokenRequestHandler, TokenRequestHandler } from '@openid/appauth/built/token_request_handler'; -import { TokenError, TokenResponse } from '@openid/appauth/built/token_response'; +import {AuthorizationRequest} from '@openid/appauth/built/authorization_request'; +import {AuthorizationNotifier, AuthorizationRequestHandler, AuthorizationRequestResponse, BUILT_IN_PARAMETERS} from '@openid/appauth/built/authorization_request_handler'; +import {AuthorizationResponse} from '@openid/appauth/built/authorization_response'; +import {AuthorizationServiceConfiguration} from '@openid/appauth/built/authorization_service_configuration'; +import {NodeBasedHandler} from '@openid/appauth/built/node_support/node_request_handler'; +import {NodeRequestor} from '@openid/appauth/built/node_support/node_requestor'; +import {GRANT_TYPE_AUTHORIZATION_CODE, GRANT_TYPE_REFRESH_TOKEN, TokenRequest} from '@openid/appauth/built/token_request'; +import {BaseTokenRequestHandler, TokenRequestHandler} from '@openid/appauth/built/token_request_handler'; +import {TokenError, TokenResponse} from '@openid/appauth/built/token_response'; import EventEmitter = require('events'); -import { log } from './logger'; -import { StringMap } from "@openid/appauth/built/types"; +import {log} from './logger'; +import {StringMap} from '@openid/appauth/built/types'; export class AuthStateEmitter extends EventEmitter { - static ON_AUTHORIZATION_RESPONSE = 'on_authorization_response'; + static ON_TOKEN_RESPONSE = 'on_token_response'; } /* the Node.js based HTTP client. */ @@ -24,7 +24,7 @@ const openIdConnectUrl = 'https://accounts.google.com'; /* example client configuration */ const clientId = - '511828570984-dhnshqcpegee66hgnp754dupe8sbas18.apps.googleusercontent.com'; + '511828570984-dhnshqcpegee66hgnp754dupe8sbas18.apps.googleusercontent.com'; const redirectUri = 'http://localhost:8000'; const scope = 'openid'; // TODO(rahulrav@): Figure out a way to get rid of this @@ -37,10 +37,10 @@ export class AuthFlow { readonly authStateEmitter: AuthStateEmitter; // state - private configuration: AuthorizationServiceConfiguration | null; + private configuration: AuthorizationServiceConfiguration|null; - private refreshToken: string | null; - private accessTokenResponse: TokenResponse | null; + private refreshToken: string|null; + private accessTokenResponse: TokenResponse|null; constructor() { this.notifier = new AuthorizationNotifier(); @@ -54,21 +54,23 @@ export class AuthFlow { this.notifier.setAuthorizationListener((request, response, error) => { log('Authorization request complete ', request, response, error); if (response) { - this.authStateEmitter.emit(AuthStateEmitter.ON_AUTHORIZATION_RESPONSE); this.makeRefreshTokenRequest(response.code) - .then(result => this.performWithFreshTokens() - .then(() => log('All done.'))); + .then(result => this.performWithFreshTokens()) + .then(() => { + this.authStateEmitter.emit(AuthStateEmitter.ON_TOKEN_RESPONSE); + log('All Done.'); + }) } }); } fetchServiceConfiguration(): Promise { return AuthorizationServiceConfiguration - .fetchFromIssuer(openIdConnectUrl, requestor) - .then(response => { - log('Fetched service configuration', response); - this.configuration = response; - }); + .fetchFromIssuer(openIdConnectUrl, requestor) + .then(response => { + log('Fetched service configuration', response); + this.configuration = response; + }); } makeAuthorizationRequest(username?: string) { @@ -77,20 +79,20 @@ export class AuthFlow { return; } - const extras: StringMap = { 'prompt': 'consent', 'access_type': 'offline' }; + const extras: StringMap = {'prompt': 'consent', 'access_type': 'offline'}; if (username) { extras['login_hint'] = username; } // create a request const request = new AuthorizationRequest( - clientId, redirectUri, scope, AuthorizationRequest.RESPONSE_TYPE_CODE, - undefined /* state */, extras); + clientId, redirectUri, scope, AuthorizationRequest.RESPONSE_TYPE_CODE, + undefined /* state */, extras); log('Making authorization request ', this.configuration, request); this.authorizationHandler.performAuthorizationRequest( - this.configuration, request); + this.configuration, request); } private makeRefreshTokenRequest(code: string): Promise { @@ -100,17 +102,17 @@ export class AuthFlow { } // use the code to make the token request. let request = new TokenRequest( - clientId, redirectUri, GRANT_TYPE_AUTHORIZATION_CODE, code, undefined, - { 'client_secret': clientSecret }); + clientId, redirectUri, GRANT_TYPE_AUTHORIZATION_CODE, code, undefined, + {'client_secret': clientSecret}); return this.tokenHandler.performTokenRequest(this.configuration, request) - .then(response => { - log(`Refresh Token is ${response.refreshToken}`); - this.refreshToken = response.refreshToken; - this.accessTokenResponse = response; - return response; - }) - .then(() => { }); + .then(response => { + log(`Refresh Token is ${response.refreshToken}`); + this.refreshToken = response.refreshToken; + this.accessTokenResponse = response; + return response; + }) + .then(() => {}); } loggedIn(): boolean { @@ -136,12 +138,12 @@ export class AuthFlow { return Promise.resolve(this.accessTokenResponse.accessToken); } let request = new TokenRequest( - clientId, redirectUri, GRANT_TYPE_REFRESH_TOKEN, undefined, - this.refreshToken, { 'client_secret': clientSecret }); + clientId, redirectUri, GRANT_TYPE_REFRESH_TOKEN, undefined, + this.refreshToken, {'client_secret': clientSecret}); return this.tokenHandler.performTokenRequest(this.configuration, request) - .then(response => { - this.accessTokenResponse = response; - return response.accessToken; - }); + .then(response => { + this.accessTokenResponse = response; + return response.accessToken; + }); } } diff --git a/index.html b/index.html index 0ac2540..dbdbea9 100644 --- a/index.html +++ b/index.html @@ -1,39 +1,49 @@ - + - AppAuth in Electron Shell - + AppAuth-JS with Electron + +
-
+
-

AppAuthJS

-

This example shows how one can integrate AppAuthJS and Electron.

+
+

AppAuth-JS

+
+
+ +
-
- -
-
- For more information look source of the application at the following link. -
-
- +
+ This example shows how one can integrate AppAuthJS and Electron. For more information look source of the application at the + following https://github.com/openid/AppAuth-JS.
+
+ + +
+
+
+
+ +
+
+
+ +
+
+
- - - + diff --git a/index.ts b/index.ts index 627e51c..59b15a8 100644 --- a/index.ts +++ b/index.ts @@ -1,14 +1,14 @@ -import { app, BrowserWindow } from 'electron'; +import {app, BrowserWindow} from 'electron'; import url = require('url'); import path = require('path'); -import { log } from './logger'; +import {log} from './logger'; // retain a reference to the window, otherwise it gets gc-ed -let w: Electron.BrowserWindow | null = null; +let w: Electron.BrowserWindow|null = null; function createWindow(): Electron.BrowserWindow { log('Creating window.'); - w = new BrowserWindow({ width: 1920, height: 1080 }); + w = new BrowserWindow({width: 1920, height: 1080}); w.loadURL(url.format({ pathname: path.join(path.dirname(__dirname), 'index.html'), protocol: 'file:', @@ -35,8 +35,8 @@ app.on('window-all-closed', () => { }); app.on('activate', () => { - log('Activating'); - if (!!w) { + if (window === null) { + log('Creating a new window'); w = createWindow(); } }); diff --git a/package.json b/package.json index 3c49a6c..1ac0eb8 100644 --- a/package.json +++ b/package.json @@ -6,9 +6,12 @@ "scripts": { "compile": "tsc", "watch": "tsc --watch", - "start": "npm run-script build && node_modules/.bin/electron .", + "start": "npm run-script compile && node_modules/.bin/electron .", "dev": "npm run-script watch & node_modules/.bin/electron ." }, + "files": [ + "built/**" + ], "keywords": [ "AppAuth-JS", "Electron" @@ -22,7 +25,7 @@ "@types/opener": "^1.4.0", "@types/request": "0.0.43", "electron": "^1.6.10", - "material-components-web": "^0.12.1" + "material-design-lite": "^1.3.0" }, "devDependencies": {} -} \ No newline at end of file +} diff --git a/styles.css b/styles.css index 3e068e1..7a7f00b 100644 --- a/styles.css +++ b/styles.css @@ -1,5 +1,38 @@ -#app-auth .mdc-card__media > img { - width: 256px; - height: 256px; - margin: auto; +.app-auth-card.mdl-card { + margin: 2rem; + width: 80vw; } + +.flex-container { + display: flex; + justify-content: center; +} + +.appauth-logo { + flex-grow: 1; + background-color: #EFEFEF; + width: 40vw; + height: 40vw; +} + +.app-auth-profile { + margin-top: 2rem; +} + +#user-info { + height: auto; + min-height: auto; + padding: 1rem; +} + +#user-name { + margin-left: 1rem; + align-self: center; +} + +#user-profile-image { + align-self: center; + width: 6rem; + height: 6rem; + border-radius: 3rem; +} \ No newline at end of file diff --git a/tsconfig.json b/tsconfig.json index c2e9ea4..b84b8ac 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -1,36 +1,54 @@ { "compilerOptions": { /* Basic Options */ - "target": "es5", /* Specify ECMAScript target version: 'ES3' (default), 'ES5', 'ES2015', 'ES2016', 'ES2017', or 'ESNEXT'. */ - "module": "commonjs", /* Specify module code generation: 'commonjs', 'amd', 'system', 'umd' or 'es2015'. */ + "target": "es5", + /* Specify ECMAScript target version: 'ES3' (default), 'ES5', 'ES2015', 'ES2016', 'ES2017', or 'ESNEXT'. */ + "module": "commonjs", + /* Specify module code generation: 'commonjs', 'amd', 'system', 'umd' or 'es2015'. */ "lib": [ "dom", "es2015" - ], /* Specify library files to be included in the compilation: */ - "allowJs": false, /* Allow javascript files to be compiled. */ + ], + /* Specify library files to be included in the compilation: */ + "allowJs": false, + /* Allow javascript files to be compiled. */ // "checkJs": true, /* Report errors in .js files. */ - "jsx": "preserve", /* Specify JSX code generation: 'preserve', 'react-native', or 'react'. */ - "declaration": true, /* Generates corresponding '.d.ts' file. */ - "sourceMap": true, /* Generates corresponding '.map' file. */ + "jsx": "preserve", + /* Specify JSX code generation: 'preserve', 'react-native', or 'react'. */ + "declaration": true, + /* Generates corresponding '.d.ts' file. */ + "sourceMap": true, + /* Generates corresponding '.map' file. */ // "outFile": "./", /* Concatenate and emit output to single file. */ - "outDir": "built", /* Redirect output structure to the directory. */ - "rootDir": "./", /* Specify the root directory of input files. Use to control the output directory structure with --outDir. */ - "removeComments": false, /* Do not emit comments to output. */ + "outDir": "built", + /* Redirect output structure to the directory. */ + "rootDir": "./", + /* Specify the root directory of input files. Use to control the output directory structure with --outDir. */ + "removeComments": false, + /* Do not emit comments to output. */ // "noEmit": true, /* Do not emit outputs. */ // "importHelpers": true, /* Import emit helpers from 'tslib'. */ - "downlevelIteration": true, /* Provide full support for iterables in 'for-of', spread, and destructuring when targeting 'ES5' or 'ES3'. */ + "downlevelIteration": true, + /* Provide full support for iterables in 'for-of', spread, and destructuring when targeting 'ES5' or 'ES3'. */ // "isolatedModules": true, /* Transpile each file as a separate module (similar to 'ts.transpileModule'). */ /* Strict Type-Checking Options */ - "strict": true, /* Enable all strict type-checking options. */ - "noImplicitAny": true, /* Raise error on expressions and declarations with an implied 'any' type. */ - "strictNullChecks": true, /* Enable strict null checks. */ - "noImplicitThis": true, /* Raise error on 'this' expressions with an implied 'any' type. */ - "alwaysStrict": true, /* Parse in strict mode and emit "use strict" for each source file. */ + "strict": true, + /* Enable all strict type-checking options. */ + "noImplicitAny": true, + /* Raise error on expressions and declarations with an implied 'any' type. */ + "strictNullChecks": true, + /* Enable strict null checks. */ + "noImplicitThis": true, + /* Raise error on 'this' expressions with an implied 'any' type. */ + "alwaysStrict": true, + /* Parse in strict mode and emit "use strict" for each source file. */ /* Additional Checks */ // "noUnusedLocals": false, /* Report errors on unused locals. */ // "noUnusedParameters": true, /* Report errors on unused parameters. */ - "noImplicitReturns": true, /* Report error when not all code paths in function return a value. */ - "noFallthroughCasesInSwitch": true, /* Report errors for fallthrough cases in switch statement. */ + "noImplicitReturns": true, + /* Report error when not all code paths in function return a value. */ + "noFallthroughCasesInSwitch": true, + /* Report errors for fallthrough cases in switch statement. */ /* Module Resolution Options */ // "moduleResolution": "node", /* Specify module resolution strategy: 'node' (Node.js) or 'classic' (TypeScript pre-1.6). */ // "baseUrl": "./", /* Base directory to resolve non-absolute module names. */ @@ -45,7 +63,8 @@ // "inlineSourceMap": true, /* Emit a single file with source maps instead of having a separate file. */ // "inlineSources": true, /* Emit the source alongside the sourcemaps within a single file; requires '--inlineSourceMap' or '--sourceMap' to be set. */ /* Experimental Options */ - "experimentalDecorators": true, /* Enables experimental support for ES7 decorators. */ + "experimentalDecorators": true, + /* Enables experimental support for ES7 decorators. */ "emitDecoratorMetadata": true /* Enables experimental support for emitting type metadata for decorators. */ } } \ No newline at end of file diff --git a/yarn.lock b/yarn.lock index 0b437d6..44eeba4 100644 --- a/yarn.lock +++ b/yarn.lock @@ -2,238 +2,6 @@ # yarn lockfile v1 -"@material/animation@^0.2.3": - version "0.2.3" - resolved "https://registry.yarnpkg.com/@material/animation/-/animation-0.2.3.tgz#25f24962cd649e76459a16ab234b7846a7a7f419" - -"@material/auto-init@^0.1.2": - version "0.1.2" - resolved "https://registry.yarnpkg.com/@material/auto-init/-/auto-init-0.1.2.tgz#a6d5f88efff08c087e53f55c2cdfbb22ce6f4901" - -"@material/base@^0.2.0": - version "0.2.0" - resolved "https://registry.yarnpkg.com/@material/base/-/base-0.2.0.tgz#685e2c344aa037e42be7978e1f365ff183b9f3a1" - -"@material/button@^0.3.7": - version "0.3.7" - resolved "https://registry.yarnpkg.com/@material/button/-/button-0.3.7.tgz#3912791322f7f7129a5a2239c3098e8b10a4ceb8" - dependencies: - "@material/animation" "^0.2.3" - "@material/elevation" "^0.1.8" - "@material/ripple" "^0.6.2" - "@material/theme" "^0.1.5" - "@material/typography" "^0.2.2" - -"@material/card@^0.2.2": - version "0.2.2" - resolved "https://registry.yarnpkg.com/@material/card/-/card-0.2.2.tgz#d51034694f79efa3271702e4971a2460fa5ea87f" - dependencies: - "@material/elevation" "^0.1.8" - "@material/rtl" "^0.1.4" - "@material/theme" "^0.1.5" - "@material/typography" "^0.2.2" - -"@material/checkbox@^0.3.5": - version "0.3.5" - resolved "https://registry.yarnpkg.com/@material/checkbox/-/checkbox-0.3.5.tgz#6de81f6fe82a725b1530d5fc8939e786c6b07c44" - dependencies: - "@material/animation" "^0.2.3" - "@material/base" "^0.2.0" - "@material/ripple" "^0.6.2" - "@material/rtl" "^0.1.4" - "@material/theme" "^0.1.5" - -"@material/dialog@^0.3.0": - version "0.3.0" - resolved "https://registry.yarnpkg.com/@material/dialog/-/dialog-0.3.0.tgz#7e3421d986b031ea6494a9d58591b55e8966d5b8" - dependencies: - "@material/animation" "^0.2.3" - "@material/base" "^0.2.0" - "@material/elevation" "^0.1.8" - "@material/ripple" "^0.6.2" - "@material/rtl" "^0.1.4" - "@material/theme" "^0.1.5" - "@material/typography" "^0.1.1" - focus-trap "^2.3.0" - -"@material/drawer@^0.4.3": - version "0.4.3" - resolved "https://registry.yarnpkg.com/@material/drawer/-/drawer-0.4.3.tgz#2e342a18ab902f5f41cacb5cb7522ab25059a6c7" - dependencies: - "@material/animation" "^0.2.3" - "@material/base" "^0.2.0" - "@material/elevation" "^0.1.8" - "@material/rtl" "^0.1.4" - "@material/theme" "^0.1.5" - "@material/typography" "^0.2.2" - -"@material/elevation@^0.1.8": - version "0.1.8" - resolved "https://registry.yarnpkg.com/@material/elevation/-/elevation-0.1.8.tgz#57a1f3541a330d035633db7f5db82c462d0ccad0" - dependencies: - "@material/animation" "^0.2.3" - -"@material/fab@^0.3.9": - version "0.3.9" - resolved "https://registry.yarnpkg.com/@material/fab/-/fab-0.3.9.tgz#4817c768ed55654f5fcedc477b2b285ce8facd02" - dependencies: - "@material/animation" "^0.2.3" - "@material/elevation" "^0.1.8" - "@material/ripple" "^0.6.2" - "@material/theme" "^0.1.5" - -"@material/form-field@^0.2.6": - version "0.2.6" - resolved "https://registry.yarnpkg.com/@material/form-field/-/form-field-0.2.6.tgz#f05873776a5f9256905b0a4fff451211bffd9dc5" - dependencies: - "@material/base" "^0.2.0" - "@material/rtl" "^0.1.4" - "@material/theme" "^0.1.5" - "@material/typography" "^0.2.2" - -"@material/grid-list@^0.2.3": - version "0.2.3" - resolved "https://registry.yarnpkg.com/@material/grid-list/-/grid-list-0.2.3.tgz#d1a9beb026130582abc7fcca8a6a15d34d99ce95" - dependencies: - "@material/base" "^0.2.0" - "@material/rtl" "^0.1.4" - "@material/theme" "^0.1.5" - "@material/typography" "^0.2.2" - -"@material/icon-toggle@^0.1.12": - version "0.1.12" - resolved "https://registry.yarnpkg.com/@material/icon-toggle/-/icon-toggle-0.1.12.tgz#e7076cd0f7071fbcd2060fe3d4e774ecbba01d9c" - dependencies: - "@material/animation" "^0.2.3" - "@material/base" "^0.2.0" - "@material/ripple" "^0.6.2" - "@material/theme" "^0.1.5" - -"@material/layout-grid@^0.1.2": - version "0.1.2" - resolved "https://registry.yarnpkg.com/@material/layout-grid/-/layout-grid-0.1.2.tgz#c19d69e3a8ff9f0949528e1c7fe2ab4fda492c7b" - -"@material/linear-progress@^0.1.1": - version "0.1.1" - resolved "https://registry.yarnpkg.com/@material/linear-progress/-/linear-progress-0.1.1.tgz#29861c19ed75cab9a0d2051c5ae584cc1229d090" - dependencies: - "@material/animation" "^0.2.3" - "@material/base" "^0.2.0" - "@material/theme" "^0.1.5" - -"@material/list@^0.2.9": - version "0.2.9" - resolved "https://registry.yarnpkg.com/@material/list/-/list-0.2.9.tgz#cafcba9d8551ec546e4ed86e00dc345e66eda74c" - dependencies: - "@material/ripple" "^0.6.2" - "@material/rtl" "^0.1.4" - "@material/theme" "^0.1.5" - "@material/typography" "^0.2.2" - -"@material/menu@^0.2.7": - version "0.2.7" - resolved "https://registry.yarnpkg.com/@material/menu/-/menu-0.2.7.tgz#8e7c43b28d77160efd97eed17b6b2dd37b320aab" - dependencies: - "@material/animation" "^0.2.3" - "@material/base" "^0.2.0" - "@material/elevation" "^0.1.8" - "@material/theme" "^0.1.5" - "@material/typography" "^0.2.2" - -"@material/radio@^0.2.5": - version "0.2.5" - resolved "https://registry.yarnpkg.com/@material/radio/-/radio-0.2.5.tgz#fc9fe47f222e519ce6916c8fe19c7d62ea9dcbea" - dependencies: - "@material/animation" "^0.2.3" - "@material/base" "^0.2.0" - "@material/ripple" "^0.6.2" - "@material/theme" "^0.1.5" - -"@material/ripple@^0.6.2": - version "0.6.2" - resolved "https://registry.yarnpkg.com/@material/ripple/-/ripple-0.6.2.tgz#a8556db7c141d35f5582c5990be8690bef9dee59" - dependencies: - "@material/base" "^0.2.0" - "@material/theme" "^0.1.5" - -"@material/rtl@^0.1.4": - version "0.1.4" - resolved "https://registry.yarnpkg.com/@material/rtl/-/rtl-0.1.4.tgz#03b99a0ff4fae54d271ce7c586b5cf6dee8c60bc" - -"@material/select@^0.3.7": - version "0.3.7" - resolved "https://registry.yarnpkg.com/@material/select/-/select-0.3.7.tgz#456d1be159b5181a461c5f05d1e1d2834021ab31" - dependencies: - "@material/animation" "^0.2.3" - "@material/base" "^0.2.0" - "@material/list" "^0.2.9" - "@material/menu" "^0.2.7" - "@material/rtl" "^0.1.4" - "@material/theme" "^0.1.5" - "@material/typography" "^0.2.2" - -"@material/snackbar@^0.2.0": - version "0.2.0" - resolved "https://registry.yarnpkg.com/@material/snackbar/-/snackbar-0.2.0.tgz#c7cfea9c76d424c7b726d0233091b6ac5650468d" - dependencies: - "@material/animation" "^0.2.3" - "@material/base" "^0.2.0" - "@material/button" "^0.3.7" - "@material/rtl" "^0.1.4" - "@material/theme" "^0.1.5" - "@material/typography" "^0.2.2" - -"@material/switch@^0.1.8": - version "0.1.8" - resolved "https://registry.yarnpkg.com/@material/switch/-/switch-0.1.8.tgz#e36c01a6a59959f2ac43e361bc1bf65a2efb445c" - dependencies: - "@material/animation" "^0.2.3" - "@material/elevation" "^0.1.8" - "@material/theme" "^0.1.5" - -"@material/tabs@^0.2.0": - version "0.2.0" - resolved "https://registry.yarnpkg.com/@material/tabs/-/tabs-0.2.0.tgz#626d9a26e0f616288bbe459200d9e0d35b21d7b0" - dependencies: - "@material/animation" "^0.2.3" - "@material/base" "^0.2.0" - "@material/ripple" "^0.6.2" - "@material/rtl" "^0.1.4" - "@material/theme" "^0.1.5" - "@material/typography" "^0.2.2" - -"@material/textfield@^0.2.10": - version "0.2.10" - resolved "https://registry.yarnpkg.com/@material/textfield/-/textfield-0.2.10.tgz#4420764f220b17145beb1cc2ce090b39350f2d27" - dependencies: - "@material/animation" "^0.2.3" - "@material/base" "^0.2.0" - "@material/rtl" "^0.1.4" - "@material/theme" "^0.1.5" - "@material/typography" "^0.2.2" - -"@material/theme@^0.1.5": - version "0.1.5" - resolved "https://registry.yarnpkg.com/@material/theme/-/theme-0.1.5.tgz#5c7bd9a1974d8c1c0eacf037e0235aad9c5cb699" - -"@material/toolbar@^0.3.3": - version "0.3.3" - resolved "https://registry.yarnpkg.com/@material/toolbar/-/toolbar-0.3.3.tgz#9867e3f565edca7f6f9ddc6be7913e5917422872" - dependencies: - "@material/base" "^0.2.0" - "@material/elevation" "^0.1.8" - "@material/rtl" "^0.1.4" - "@material/theme" "^0.1.5" - "@material/typography" "^0.2.2" - -"@material/typography@^0.1.1": - version "0.1.1" - resolved "https://registry.yarnpkg.com/@material/typography/-/typography-0.1.1.tgz#fb2e3437bd3284d39e9fb91485767ade6b2bd0c1" - -"@material/typography@^0.2.2": - version "0.2.2" - resolved "https://registry.yarnpkg.com/@material/typography/-/typography-0.2.2.tgz#dc5f0763ad7d6e5ad5c86c394b360f2b4cf30bb2" - "@openid/appauth@^0.1.6": version "0.1.6" resolved "https://registry.yarnpkg.com/@openid/appauth/-/appauth-0.1.6.tgz#78e8ebf2f3a0f4b167d2ec21c3e4246592becc58" @@ -595,12 +363,6 @@ find-up@^1.0.0: path-exists "^2.0.0" pinkie-promise "^2.0.0" -focus-trap@^2.3.0: - version "2.3.0" - resolved "https://registry.yarnpkg.com/focus-trap/-/focus-trap-2.3.0.tgz#07c91964867d346315f4f5f8df88bf96455316e2" - dependencies: - tabbable "^1.0.3" - forever-agent@~0.6.1: version "0.6.1" resolved "https://registry.yarnpkg.com/forever-agent/-/forever-agent-0.6.1.tgz#fbc71f0c41adeb37f96c577ad1ed42d8fdacca91" @@ -879,37 +641,9 @@ map-obj@^1.0.0, map-obj@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/map-obj/-/map-obj-1.0.1.tgz#d933ceb9205d82bdcf4886f6742bdc2b4dea146d" -material-components-web@^0.12.1: - version "0.12.1" - resolved "https://registry.yarnpkg.com/material-components-web/-/material-components-web-0.12.1.tgz#3ef8562b53acfc23bbeae812751ba021e246cbb0" - dependencies: - "@material/animation" "^0.2.3" - "@material/auto-init" "^0.1.2" - "@material/base" "^0.2.0" - "@material/button" "^0.3.7" - "@material/card" "^0.2.2" - "@material/checkbox" "^0.3.5" - "@material/dialog" "^0.3.0" - "@material/drawer" "^0.4.3" - "@material/elevation" "^0.1.8" - "@material/fab" "^0.3.9" - "@material/form-field" "^0.2.6" - "@material/grid-list" "^0.2.3" - "@material/icon-toggle" "^0.1.12" - "@material/layout-grid" "^0.1.2" - "@material/linear-progress" "^0.1.1" - "@material/list" "^0.2.9" - "@material/menu" "^0.2.7" - "@material/radio" "^0.2.5" - "@material/ripple" "^0.6.2" - "@material/select" "^0.3.7" - "@material/snackbar" "^0.2.0" - "@material/switch" "^0.1.8" - "@material/tabs" "^0.2.0" - "@material/textfield" "^0.2.10" - "@material/theme" "^0.1.5" - "@material/toolbar" "^0.3.3" - "@material/typography" "^0.2.2" +material-design-lite@^1.3.0: + version "1.3.0" + resolved "https://registry.yarnpkg.com/material-design-lite/-/material-design-lite-1.3.0.tgz#d004ce3fee99a1eeb74a78b8a325134a5f1171d3" meow@^3.1.0: version "3.7.0" @@ -1341,10 +1075,6 @@ sumchecker@^1.2.0: debug "^2.2.0" es6-promise "^4.0.5" -tabbable@^1.0.3: - version "1.0.6" - resolved "https://registry.yarnpkg.com/tabbable/-/tabbable-1.0.6.tgz#7c26a87ea6f4a25edf5edb619745a0ae740724fc" - throttleit@0.0.2: version "0.0.2" resolved "https://registry.yarnpkg.com/throttleit/-/throttleit-0.0.2.tgz#cfedf88e60c00dd9697b61fdd2a8343a9b680eaf"